31 |
# |
# |
32 |
############################################################################### |
############################################################################### |
33 |
|
|
34 |
|
############################################################################### |
35 |
|
# meterod version |
36 |
|
################################################################################ |
37 |
|
|
38 |
|
$::VERSION='1.06.02'; |
39 |
|
$::RELEASE_DATE='not yet released'; |
40 |
|
|
41 |
############################################################################### |
############################################################################### |
42 |
# Configuration |
# Configuration |
44 |
|
|
45 |
use strict; |
use strict; |
46 |
|
|
47 |
|
use Socket; |
48 |
|
|
49 |
use Meteor::Syslog; |
use Meteor::Syslog; |
50 |
|
|
51 |
use Meteor::Socket; |
use Meteor::Socket; |
65 |
our $AGE_CHECK_INTERVALL=60; |
our $AGE_CHECK_INTERVALL=60; |
66 |
|
|
67 |
our $MAX_EXIT_DELAY=120; |
our $MAX_EXIT_DELAY=120; |
68 |
|
|
69 |
|
our $UDP_MAX_MESSAGE_SIZE=8192; |
70 |
|
|
71 |
############################################################################### |
############################################################################### |
72 |
# Main |
# Main |
73 |
############################################################################### |
############################################################################### |
74 |
|
|
75 |
# |
# |
76 |
|
# Record startup time |
77 |
|
# |
78 |
|
$::STARTUP_TIME=time; |
79 |
|
$::STARTUP_TIME+=0; # avoid warning |
80 |
|
|
81 |
|
# |
82 |
# Program name |
# Program name |
83 |
# |
# |
84 |
$::PGM=$0; |
$::PGM=$0; |
106 |
{ |
{ |
107 |
$0="$::PGM daemon"; |
$0="$::PGM daemon"; |
108 |
|
|
109 |
unless($::CONF{'Debug'}) |
my $facility=$::CONF{'SyslogFacility'} || $Meteor::Syslog::DEFAULT_FACILITY; |
110 |
|
|
111 |
|
unless($::CONF{'Debug'} || $facility eq 'none') |
112 |
{ |
{ |
113 |
# close standard file descriptors |
# close standard file descriptors |
114 |
close(STDIN); |
close(STDIN); |
116 |
close(STDERR); |
close(STDERR); |
117 |
chdir("/"); |
chdir("/"); |
118 |
umask(0); |
umask(0); |
119 |
|
|
120 |
# fork and exit parent |
# fork and exit parent |
121 |
|
print STDERR "Exit: Fork\n"; |
122 |
exit if fork; |
exit if fork; |
123 |
setpgrp(0, $$) if defined $SIG{TTOU}; |
setpgrp(0, $$) if defined $SIG{TTOU}; |
124 |
$SIG{TTOU}='ignore' if defined $SIG{TTOU}; |
$SIG{TTOU}='ignore' if defined $SIG{TTOU}; |
126 |
# Avoid 'stdin reopened for output' warning with newer perls |
# Avoid 'stdin reopened for output' warning with newer perls |
127 |
open(NULL,'/dev/null'); |
open(NULL,'/dev/null'); |
128 |
<NULL> if(0); |
<NULL> if(0); |
|
|
|
129 |
open(OUT,">/var/run/$::PGM.pid"); |
open(OUT,">/var/run/$::PGM.pid"); |
130 |
print OUT "$$\n"; |
print OUT "$$\n"; |
131 |
close(OUT); |
close(OUT); |
132 |
|
|
133 |
} |
} |
134 |
else |
else |
135 |
{ |
{ |
136 |
print "$::PGM PID: $$\n"; |
&::syslog('info',"PID\t%s",$$); |
137 |
} |
} |
138 |
} |
} |
139 |
|
|
145 |
$SIG{'TERM'}=sub{$::TERM=1}; |
$SIG{'TERM'}=sub{$::TERM=1}; |
146 |
$SIG{'USR1'}=sub{$::USR1=1}; |
$SIG{'USR1'}=sub{$::USR1=1}; |
147 |
$SIG{'USR2'}=sub{$::USR2=1}; |
$SIG{'USR2'}=sub{$::USR2=1}; |
148 |
|
$SIG{'PIPE'}=sub{&::syslog('info',"Signal PIPE received and ignored\n");}; |
149 |
|
|
150 |
# |
# |
151 |
# Run server |
# Run server |
152 |
# |
# |
167 |
); |
); |
168 |
my $subscriberServerFN=$subscriberServer->fileno(); |
my $subscriberServerFN=$subscriberServer->fileno(); |
169 |
|
|
170 |
|
my $udpServer=undef; |
171 |
|
my $udpPort=$::CONF{'UDPPort'}; |
172 |
|
my $udpServerFN=undef; |
173 |
|
if($udpPort && $udpPort>0) |
174 |
|
{ |
175 |
|
$udpServer=Meteor::Socket->newUDPServer( |
176 |
|
$udpPort, |
177 |
|
$::CONF{'UDPIP'} |
178 |
|
); |
179 |
|
$udpServerFN=$udpServer->fileno(); |
180 |
|
} |
181 |
|
|
182 |
my $serverVector=''; |
my $serverVector=''; |
183 |
vec($serverVector,$controlServerFN,1)=1; |
vec($serverVector,$controlServerFN,1)=1; |
184 |
vec($serverVector,$subscriberServerFN,1)=1; |
vec($serverVector,$subscriberServerFN,1)=1; |
185 |
|
vec($serverVector,$udpServerFN,1)=1 if(defined($udpServerFN)); |
186 |
|
|
187 |
my $lastAgeCheck=time; |
my $lastAgeCheck=time; |
188 |
|
|
198 |
{ |
{ |
199 |
while(!$::TERM) |
while(!$::TERM) |
200 |
{ |
{ |
201 |
|
|
202 |
|
|
203 |
my $rVec=$serverVector; |
my $rVec=$serverVector; |
204 |
my $wVec=''; |
my $wVec=''; |
205 |
my $eVec=''; |
my $eVec=''; |
206 |
|
|
207 |
my $rout; |
my $rout; |
208 |
my $wout; |
my $wout; |
209 |
my $eout; |
my $eout; |
210 |
|
|
211 |
Meteor::Connection->addAllHandleBits(\$rVec,\$wVec,\$eVec); |
Meteor::Connection->addAllHandleBits(\$rVec,\$wVec,\$eVec); |
212 |
|
|
213 |
my $timeout=$MAIN_LOOP_TIMEOUT; |
my $timeout=$MAIN_LOOP_TIMEOUT; |
232 |
{ |
{ |
233 |
Meteor::Subscriber->newFromServer($subscriberServer); |
Meteor::Subscriber->newFromServer($subscriberServer); |
234 |
} |
} |
235 |
|
if(defined($udpServerFN) && vec($rout,$udpServerFN,1)) |
236 |
|
{ |
237 |
|
&handleUPD($udpServer); |
238 |
|
} |
239 |
|
|
240 |
Meteor::Connection->checkAllHandleBits($rout,$wout,$eout); |
Meteor::Connection->checkAllHandleBits($rout,$wout,$eout); |
241 |
} |
} |
265 |
|
|
266 |
Meteor::Channel->clearAllBuffers(); |
Meteor::Channel->clearAllBuffers(); |
267 |
} |
} |
268 |
|
|
269 |
if($::USR2) |
if($::USR2) |
270 |
{ |
{ |
271 |
$::USR2=0; |
$::USR2=0; |
274 |
|
|
275 |
Meteor::Document->clearDocuments() |
Meteor::Document->clearDocuments() |
276 |
} |
} |
277 |
|
|
278 |
my $t=time; |
my $t=time; |
279 |
if($t>$lastAgeCheck+$AGE_CHECK_INTERVALL) |
if($t>$lastAgeCheck+$AGE_CHECK_INTERVALL) |
280 |
{ |
{ |
284 |
$t=$lastAgeCheck; |
$t=$lastAgeCheck; |
285 |
|
|
286 |
Meteor::Subscriber->checkPersistentConnectionsForMaxTime(); |
Meteor::Subscriber->checkPersistentConnectionsForMaxTime(); |
287 |
|
Meteor::Connection->destroyBadRequests(); |
288 |
} |
} |
289 |
|
|
290 |
if(defined($nextPing) && $nextPing<=$t) |
if(defined($nextPing) && $nextPing<=$t) |
347 |
{ |
{ |
348 |
&::syslog('info',"$cnt client(s) unresponsive, will shutdown anyway"); |
&::syslog('info',"$cnt client(s) unresponsive, will shutdown anyway"); |
349 |
|
|
350 |
|
print STDERR "Exit: TERM Shutdown (unresponsive clients)\n"; |
351 |
exit(1); |
exit(1); |
352 |
} |
} |
353 |
|
|
354 |
&::syslog('info',"shutdown succeeded"); |
&::syslog('info',"shutdown succeeded"); |
355 |
|
|
356 |
|
print STDERR "Exit: TERM Shutdown (clean)\n"; |
357 |
exit(0); |
exit(0); |
358 |
} |
} |
359 |
|
|
360 |
&::syslog('emerg',"$::PGM loop exited"); |
&::syslog('emerg',"$::PGM loop exited"); |
361 |
|
|
362 |
|
############################################################################### |
363 |
|
# Subroutines |
364 |
|
############################################################################### |
365 |
|
sub handleUPD { |
366 |
|
$udpServer=shift; |
367 |
|
|
368 |
|
my $line; |
369 |
|
my $hispaddr=recv($udpServer->{'handle'},$line,$::UDP_MAX_MESSAGE_SIZE,0); |
370 |
|
|
371 |
|
&::syslog('debug',"udp message received: %s",$line); |
372 |
|
|
373 |
|
return unless($line=~s/^(\S+)\s//); |
374 |
|
|
375 |
|
my $cmd=$1; |
376 |
|
|
377 |
|
if($cmd eq 'ADDMESSAGE') |
378 |
|
{ |
379 |
|
return unless($line=~s/^(\S+)\s//); |
380 |
|
|
381 |
|
my $channelName=$1; |
382 |
|
my $channel=Meteor::Channel->channelWithName($channelName); |
383 |
|
my $msg=$channel->addMessage($line); |
384 |
|
my $msgID=$msg->id(); |
385 |
|
&::syslog('debug',"udp: new message added, ID %s",$msgID); |
386 |
|
} |
387 |
|
} |
388 |
|
|
389 |
1; |
1; |
|
############################################################################EOF |
|
390 |
|
############################################################################EOF |