X-Git-Url: https://git.dogcows.com/gitweb?p=chaz%2Fchatty;a=blobdiff_plain;f=extra%2Fcometd%2Fmeteord;fp=extra%2Fcometd%2Fmeteord;h=2394c9443187168d8fe212ad37ba3448e7e941e2;hp=0000000000000000000000000000000000000000;hb=100d54b49cab3783276b3a470fffa5e509929daf;hpb=06da6ad7294f8293cfe3a5e77e0f676d2884cd79 diff --git a/extra/cometd/meteord b/extra/cometd/meteord new file mode 100755 index 0000000..2394c94 --- /dev/null +++ b/extra/cometd/meteord @@ -0,0 +1,382 @@ +#!/usr/bin/perl -w +############################################################################### +# Meteor +# An HTTP server for the 2.0 web +# Copyright (c) 2006 contributing authors +# +# The Meteor daemon +# +# Main program should call Meteor::Config::setCommandLineParameters(@ARGV),. +# Afterwards anybody can access $::CONF{}, where +# is any valid parameter (except 'Help') listed in the +# @DEFAULTS array below. +# +############################################################################### +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the Free +# Software Foundation; either version 2 of the License, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +# more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# For more information visit www.meteorserver.org +# +############################################################################### + +############################################################################### +# meterod version +################################################################################ + + $::VERSION='1.06'; + $::RELEASE_DATE='2008-03-02'; + +############################################################################### +# Configuration +############################################################################### + + use strict; + + use Socket; + + use Meteor::Syslog; + + use Meteor::Socket; + use Meteor::Connection; + use Meteor::Controller; + use Meteor::Subscriber; + use Meteor::Channel; + use Meteor::Document; + use Meteor::Config; + + $::CRLF="\r\n"; # Line separator to be used throughout all modules + + our $CONTROL_QUEUE_SIZE=5; + our $SUBSCRIBER_QUEUE_SIZE=20; + + our $MAIN_LOOP_TIMEOUT=60; + our $AGE_CHECK_INTERVALL=60; + + our $MAX_EXIT_DELAY=120; + + our $UDP_MAX_MESSAGE_SIZE=8192; + +############################################################################### +# Main +############################################################################### + + # + # Record startup time + # + $::STARTUP_TIME=time; + $::STARTUP_TIME+=0; # avoid warning + + # + # Program name + # + $::PGM=$0; + $::PGM=~s/^.*\///; + + # + # Handle command line options and config file + # + Meteor::Config->setCommandLineParameters(@ARGV); + + # + # Do something about warn and die + # + unless($::CONF{'Debug'}) + { + $SIG{'__WARN__'}=\&Meteor::Syslog::myWarn; + $SIG{'__DIE__'}=\&Meteor::Syslog::myDie; + } + + &::syslog('info',"$::PGM launched!"); + + # + # Daemonize + # + { + $0="$::PGM daemon"; + + my $facility=$::CONF{'SyslogFacility'} || $Meteor::Syslog::DEFAULT_FACILITY; + + unless($::CONF{'Debug'} || $facility eq 'none') + { + # close standard file descriptors + close(STDIN); + close(STDOUT); + close(STDERR); + chdir("/"); + umask(0); + # fork and exit parent + exit if fork; + setpgrp(0, $$) if defined $SIG{TTOU}; + $SIG{TTOU}='ignore' if defined $SIG{TTOU}; + + # Avoid 'stdin reopened for output' warning with newer perls + open(NULL,'/dev/null'); + if(0); + + open(OUT,">/var/run/$::PGM.pid"); + print OUT "$$\n"; + close(OUT); + } + else + { + &::syslog('info',"PID\t%s",$$); + } + } + + # + # Signal handlers + # + $::HUP=$::TERM=$::USR1=$::USR2=0; + $SIG{'HUP'}=sub{$::HUP=1}; + $SIG{'TERM'}=sub{$::TERM=1}; + $SIG{'USR1'}=sub{$::USR1=1}; + $SIG{'USR2'}=sub{$::USR2=1}; + + # + # Run server + # + my $con_counter=0; + my $con; + + my $controlServer=Meteor::Socket->newServer( + $::CONF{'ControllerPort'}, + $CONTROL_QUEUE_SIZE, + $::CONF{'ControllerIP'} + ); + my $controlServerFN=$controlServer->fileno(); + + my $subscriberServer=Meteor::Socket->newServer( + $::CONF{'SubscriberPort'}, + $SUBSCRIBER_QUEUE_SIZE, + $::CONF{'SubscriberIP'} + ); + my $subscriberServerFN=$subscriberServer->fileno(); + + my $udpServer=undef; + my $udpPort=$::CONF{'UDPPort'}; + my $udpServerFN=undef; + if($udpPort && $udpPort>0) + { + $udpServer=Meteor::Socket->newUDPServer( + $udpPort, + $::CONF{'UDPIP'} + ); + $udpServerFN=$udpServer->fileno(); + } + + my $serverVector=''; + vec($serverVector,$controlServerFN,1)=1; + vec($serverVector,$subscriberServerFN,1)=1; + vec($serverVector,$udpServerFN,1)=1 if(defined($udpServerFN)); + + my $lastAgeCheck=time; + + my $nextPing=undef; + if(exists($::CONF{'PingInterval'}) && $::CONF{'PingInterval'}>2) + { + $nextPing=$::CONF{'PingInterval'}+$lastAgeCheck; + } + + while(!$::TERM) + { + eval + { + while(!$::TERM) + { + my $rVec=$serverVector; + my $wVec=''; + my $eVec=''; + + my $rout; + my $wout; + my $eout; + + Meteor::Connection->addAllHandleBits(\$rVec,\$wVec,\$eVec); + + my $timeout=$MAIN_LOOP_TIMEOUT; + if(defined($nextPing)) + { + $timeout=$nextPing-time; + } + + my $result=0; + if($timeout>0) + { + $result=&Meteor::Socket::sselect($rout=$rVec,$wout=$wVec,$eout=$eVec,$timeout); + } + + if($result>0) + { + if(vec($rout,$controlServerFN,1)) + { + Meteor::Controller->newFromServer($controlServer); + } + if(vec($rout,$subscriberServerFN,1)) + { + Meteor::Subscriber->newFromServer($subscriberServer); + } + if(defined($udpServerFN) && vec($rout,$udpServerFN,1)) + { + &handleUPD($udpServer); + } + + Meteor::Connection->checkAllHandleBits($rout,$wout,$eout); + } + elsif($result<0) + { + &::syslog('crit',"Select failed: $!"); + sleep(30); + } + + if($::HUP) + { + $::HUP=0; + + &::syslog('info',"Received SIGHUP, re-reading config and clearing document cache!"); + + Meteor::Config->readConfig(); + Meteor::Config->updateConfig(); + + Meteor::Document->clearDocuments() + } + + if($::USR1) + { + $::USR1=0; + + &::syslog('info',"Received SIGUSR1, clearing channel buffers!"); + + Meteor::Channel->clearAllBuffers(); + } + + if($::USR2) + { + $::USR2=0; + + &::syslog('info',"Received SIGUSR2, clearing document cache!"); + + Meteor::Document->clearDocuments() + } + + my $t=time; + if($t>$lastAgeCheck+$AGE_CHECK_INTERVALL) + { + my $minTimeStap=time-$::CONF{'MaxMessageAge'}; + Meteor::Channel->trimMessageStoresByTimestamp($minTimeStap); + $lastAgeCheck=time; + $t=$lastAgeCheck; + + Meteor::Subscriber->checkPersistentConnectionsForMaxTime(); + } + + if(defined($nextPing) && $nextPing<=$t) + { + $nextPing=undef; + + Meteor::Subscriber->pingPersistentConnections(); + + if(exists($::CONF{'MaxMessageAge'}) && $::CONF{'MaxMessageAge'}>2) + { + $nextPing=$::CONF{'PingInterval'}+time; + } + } + } + }; + unless($::TERM) + { + &::syslog('alert',"$::PGM loop died (will restart in 2 seconds): $@"); + sleep(2); + } + } + + # + # Proper shutdown + # + if($::TERM) + { + &::syslog('info',"Received SIGTERM, begin shutdown!"); + + $subscriberServer->close(); + $controlServer->close(); + + unlink("/var/run/$::PGM.pid") unless($::CONF{'Debug'}); + + Meteor::Connection->closeAllConnections(); + + my $timoutAt=time+$MAX_EXIT_DELAY; + + while(Meteor::Connection->connectionCount() && time<$timoutAt) + { + my $rVec=''; + my $wVec=''; + my $eVec=''; + + my $rout; + my $wout; + my $eout; + + Meteor::Connection->addAllHandleBits(\$rVec,\$wVec,\$eVec); + + my $result=&Meteor::Socket::sselect($rout=$rVec,$wout=$wVec,$eout=$eVec,$timoutAt-time); + + if($result>0) + { + Meteor::Connection->checkAllHandleBits($rout,$wout,$eout); + } + } + + if(my $cnt=Meteor::Connection->connectionCount()) + { + &::syslog('info',"$cnt client(s) unresponsive, will shutdown anyway"); + + exit(1); + } + + &::syslog('info',"shutdown succeeded"); + + exit(0); + } + + &::syslog('emerg',"$::PGM loop exited"); + +############################################################################### +# Subroutines +############################################################################### +sub handleUPD { + $udpServer=shift; + + my $line; + my $hispaddr=recv($udpServer->{'handle'},$line,$::UDP_MAX_MESSAGE_SIZE,0); + + &::syslog('debug',"udp message received: %s",$line); + + return unless($line=~s/^(\S+)\s//); + + my $cmd=$1; + + if($cmd eq 'ADDMESSAGE') + { + return unless($line=~s/^(\S+)\s//); + + my $channelName=$1; + my $channel=Meteor::Channel->channelWithName($channelName); + my $msg=$channel->addMessage($line); + my $msgID=$msg->id(); + &::syslog('debug',"udp: new message added, ID %s",$msgID); + } +} + +1; +############################################################################EOF \ No newline at end of file