version 1.28, 2002/02/19 22:51:13
|
version 1.29, 2002/02/25 15:48:11
|
Line 44
|
Line 44
|
# 03/14/01,03/15,06/12,11/26,11/27,11/28 Gerd Kortemeyer |
# 03/14/01,03/15,06/12,11/26,11/27,11/28 Gerd Kortemeyer |
# 12/20 Scott Harrison |
# 12/20 Scott Harrison |
# YEAR=2002 |
# YEAR=2002 |
# 2/19/02 |
# 2/19/02,02/22/02,02/25/02 Gerd Kortemeyer |
# |
# |
# based on nonforker from Perl Cookbook |
# based on nonforker from Perl Cookbook |
# - server who multiplexes without forking |
# - server who multiplexes without forking |
Line 66 my $lastlog='';
|
Line 66 my $lastlog='';
|
# grabs exception and records it to log before exiting |
# grabs exception and records it to log before exiting |
sub catchexception { |
sub catchexception { |
my ($signal)=@_; |
my ($signal)=@_; |
$SIG{'QUIT'}='DEFAULT'; |
$SIG{QUIT}='DEFAULT'; |
$SIG{__DIE__}='DEFAULT'; |
$SIG{__DIE__}='DEFAULT'; |
|
chomp($signal); |
&logthis("<font color=red>CRITICAL: " |
&logthis("<font color=red>CRITICAL: " |
."ABNORMAL EXIT. Child $$ for server $wasserver died through " |
."ABNORMAL EXIT. Child $$ for server [$wasserver] died through " |
."\"$signal\" with this parameter->[$@]</font>"); |
."\"$signal\" with parameter [$@]</font>"); |
die($@); |
die($@); |
} |
} |
|
|
Line 80 $childmaxattempts=5;
|
Line 81 $childmaxattempts=5;
|
|
|
sub online { |
sub online { |
my $host=shift; |
my $host=shift; |
|
&status("Pinging ".$host); |
my $p=Net::Ping->new("tcp",20); |
my $p=Net::Ping->new("tcp",20); |
my $online=$p->ping("$host"); |
my $online=$p->ping("$host"); |
$p->close(); |
$p->close(); |
Line 89 sub online {
|
Line 91 sub online {
|
|
|
sub connected { |
sub connected { |
my ($local,$remote)=@_; |
my ($local,$remote)=@_; |
|
&status("Checking connection $local to $remote"); |
$local=~s/\W//g; |
$local=~s/\W//g; |
$remote=~s/\W//g; |
$remote=~s/\W//g; |
|
|
Line 116 sub connected {
|
Line 119 sub connected {
|
|
|
# -------------------------------- Set signal handlers to record abnormal exits |
# -------------------------------- Set signal handlers to record abnormal exits |
|
|
|
&status("Init exception handlers"); |
$SIG{QUIT}=\&catchexception; |
$SIG{QUIT}=\&catchexception; |
$SIG{__DIE__}=\&catchexception; |
$SIG{__DIE__}=\&catchexception; |
|
|
# ------------------------------------ Read httpd access.conf and get variables |
# ------------------------------------ Read httpd access.conf and get variables |
|
&status("Read access.conf"); |
open (CONFIG,"/etc/httpd/conf/access.conf") || die "Can't read access.conf"; |
open (CONFIG,"/etc/httpd/conf/access.conf") || die "Can't read access.conf"; |
|
|
while ($configline=<CONFIG>) { |
while ($configline=<CONFIG>) { |
Line 133 while ($configline=<CONFIG>) {
|
Line 137 while ($configline=<CONFIG>) {
|
close(CONFIG); |
close(CONFIG); |
|
|
# ----------------------------- Make sure this process is running from user=www |
# ----------------------------- Make sure this process is running from user=www |
|
&status("Check user ID"); |
my $wwwid=getpwnam('www'); |
my $wwwid=getpwnam('www'); |
if ($wwwid!=$<) { |
if ($wwwid!=$<) { |
$emailto="$perlvar{'lonAdmEMail'},$perlvar{'lonSysEMail'}"; |
$emailto="$perlvar{'lonAdmEMail'},$perlvar{'lonSysEMail'}"; |
Line 224 sub checkchildren {
|
Line 229 sub checkchildren {
|
foreach (sort keys %children) { |
foreach (sort keys %children) { |
sleep 1; |
sleep 1; |
unless (kill 'USR1' => $_) { |
unless (kill 'USR1' => $_) { |
&logthis ('Child '.$_.' is dead'); |
&logthis ('<font color=red>CRITICAL: Child '.$_.' is dead</font>'); |
&logstatus($$.' is dead'); |
&logstatus($$.' is dead'); |
} |
} |
} |
} |
Line 273 sub logthis {
|
Line 278 sub logthis {
|
my $now=time; |
my $now=time; |
my $local=localtime($now); |
my $local=localtime($now); |
$lastlog=$local.': '.$message; |
$lastlog=$local.': '.$message; |
print $fh "$local ($$): $message\n"; |
print $fh "$local ($$) [$status]: $message\n"; |
} |
} |
|
|
|
|
Line 312 sub status {
|
Line 317 sub status {
|
|
|
|
|
# ---------------------------------------------------- Fork once and dissociate |
# ---------------------------------------------------- Fork once and dissociate |
|
&status("Fork and dissociate"); |
$fpid=fork; |
$fpid=fork; |
exit if $fpid; |
exit if $fpid; |
die "Couldn't fork: $!" unless defined ($fpid); |
die "Couldn't fork: $!" unless defined ($fpid); |
Line 320 die "Couldn't fork: $!" unless defined (
|
Line 325 die "Couldn't fork: $!" unless defined (
|
POSIX::setsid() or die "Can't start new session: $!"; |
POSIX::setsid() or die "Can't start new session: $!"; |
|
|
# ------------------------------------------------------- Write our PID on disk |
# ------------------------------------------------------- Write our PID on disk |
|
&status("Write PID"); |
$execdir=$perlvar{'lonDaemons'}; |
$execdir=$perlvar{'lonDaemons'}; |
open (PIDSAVE,">$execdir/logs/lonc.pid"); |
open (PIDSAVE,">$execdir/logs/lonc.pid"); |
print PIDSAVE "$$\n"; |
print PIDSAVE "$$\n"; |
Line 362 while (1) {
|
Line 367 while (1) {
|
$childatt{$thisserver}++; |
$childatt{$thisserver}++; |
&logthis( |
&logthis( |
"<font color=yellow>INFO: Trying to reconnect for $thisserver " |
"<font color=yellow>INFO: Trying to reconnect for $thisserver " |
."($childatt{$thisserver} of $childmaxattempts attempts)</font>"); |
."(".($childatt{$thisserver}?$childatt{$thisserver}:'none'). |
|
" of $childmaxattempts attempts)</font>"); |
make_new_child($thisserver); |
make_new_child($thisserver); |
} else { |
} else { |
&logthis( |
&logthis( |
Line 410 $port = "$perlvar{'lonSockDir'}/$conserv
|
Line 416 $port = "$perlvar{'lonSockDir'}/$conserv
|
|
|
unlink($port); |
unlink($port); |
|
|
# ---------------------------------------------------- Client to network server |
# -------------------------------------------------------------- Open other end |
|
|
&status("Opening TCP: $conserver"); |
|
|
|
unless ( |
|
$remotesock = IO::Socket::INET->new(PeerAddr => $hostip{$conserver}, |
|
PeerPort => $perlvar{'londPort'}, |
|
Proto => "tcp", |
|
Type => SOCK_STREAM) |
|
) { |
|
my $st=120+int(rand(240)); |
|
&logthis( |
|
"<font color=blue>WARNING: Couldn't connect $conserver ($st secs): $@</font>"); |
|
sleep($st); |
|
exit; |
|
}; |
|
# ----------------------------------------------------------------- Init dialog |
|
|
|
&status("Init dialogue: $conserver"); |
|
|
|
$SIG{ALRM}=sub { die "timeout" }; |
|
$SIG{__DIE__}='DEFAULT'; |
|
eval { |
|
alarm(60); |
|
print $remotesock "init\n"; |
|
$answer=<$remotesock>; |
|
print $remotesock "$answer"; |
|
$answer=<$remotesock>; |
|
chomp($answer); |
|
alarm(0); |
|
}; |
|
$SIG{ALRM}='DEFAULT'; |
|
$SIG{__DIE__}=\&catchexception; |
|
|
|
if ($@=~/timeout/) { |
|
&logthis("Timed out during init: $conserver"); |
|
exit; |
|
} |
|
|
|
|
|
&logthis("Init reply for $conserver: >$answer<"); |
|
if ($answer ne 'ok') { |
|
my $st=120+int(rand(240)); |
|
&logthis( |
|
"<font color=blue>WARNING: Init failed $conserver ($st secs)</font>"); |
|
sleep($st); |
|
exit; |
|
} |
|
sleep 5; |
|
&status("Ponging $conserver"); |
|
print $remotesock "pong\n"; |
|
$answer=<$remotesock>; |
|
chomp($answer); |
|
&logthis("Pong reply for $conserver: >$answer<"); |
|
# ----------------------------------------------------------- Initialize cipher |
|
|
|
&status("Initialize cipher: $conserver"); |
&openremote($conserver); |
print $remotesock "ekey\n"; |
|
my $buildkey=<$remotesock>; |
|
my $key=$conserver.$perlvar{'lonHostID'}; |
|
$key=~tr/a-z/A-Z/; |
|
$key=~tr/G-P/0-9/; |
|
$key=~tr/Q-Z/0-9/; |
|
$key=$key.$buildkey.$key.$buildkey.$key.$buildkey; |
|
$key=substr($key,0,32); |
|
my $cipherkey=pack("H32",$key); |
|
if ($cipher=new IDEA $cipherkey) { |
|
&logthis("Secure connection initialized: $conserver"); |
|
} else { |
|
my $st=120+int(rand(240)); |
|
&logthis( |
|
"<font color=blue>WARNING: ". |
|
"Could not establish secure connection, $conserver ($st secs)!</font>"); |
|
sleep($st); |
|
exit; |
|
} |
|
|
|
# ----------------------------------------- We're online, send delayed messages |
# ----------------------------------------- We're online, send delayed messages |
&status("Checking for delayed messages"); |
&status("Checking for delayed messages"); |
Line 498 if ($cipher=new IDEA $cipherkey) {
|
Line 431 if ($cipher=new IDEA $cipherkey) {
|
foreach (@allbuffered) { |
foreach (@allbuffered) { |
&status("Sending delayed $conserver $_"); |
&status("Sending delayed $conserver $_"); |
$dfname="$path/$_"; |
$dfname="$path/$_"; |
&logthis($dfname); |
&logthis('Sending '.$dfname); |
my $wcmd; |
my $wcmd; |
{ |
{ |
my $dfh=IO::File->new($dfname); |
my $dfh=IO::File->new($dfname); |
Line 625 while (1) {
|
Line 558 while (1) {
|
next unless exists $outbuffer{$client}; |
next unless exists $outbuffer{$client}; |
|
|
$rv = $client->send($outbuffer{$client}, 0); |
$rv = $client->send($outbuffer{$client}, 0); |
|
|
|
unless ($outbuffer{$client}=~/con_lost\n$/) { |
unless (defined $rv) { |
unless (defined $rv) { |
# Whine, but move on. |
# Whine, but move on. |
&logthis("I was told I could write, but I can't.\n"); |
&logthis("I was told I could write, but I can't.\n"); |
Line 650 while (1) {
|
Line 585 while (1) {
|
close($client); |
close($client); |
next; |
next; |
} |
} |
|
} else { |
|
# -------------------------------------------------------- Wow, connection lost |
|
&logthis( |
|
"<font color=red>CRITICAL: Closing connection $conserver</font>"); |
|
&status("Connection lost $conserver"); |
|
$remotesock->shutdown(2); |
|
&logthis("Attempting to open new connection"); |
|
&openremote($conserver); |
|
} |
} |
} |
|
|
} |
} |
} |
} |
|
|
Line 667 sub handle {
|
Line 612 sub handle {
|
# ============================================================= Process request |
# ============================================================= Process request |
# $request is the text of the request |
# $request is the text of the request |
# put text of reply into $outbuffer{$client} |
# put text of reply into $outbuffer{$client} |
|
# ------------------------------------------------------------ Is this the end? |
|
if ($request eq "close_connection_exit\n") { |
|
&status("Request close connection: $conserver"); |
|
&logthis( |
|
"<font color=red>CRITICAL: Request Close Connection $conserver</font>"); |
|
$remotesock->shutdown(2); |
|
$server->close(); |
|
exit; |
|
} |
# ----------------------------------------------------------------------------- |
# ----------------------------------------------------------------------------- |
if ($request =~ /^encrypt\:/) { |
if ($request =~ /^encrypt\:/) { |
my $cmd=$request; |
my $cmd=$request; |
Line 741 sub nonblock {
|
Line 695 sub nonblock {
|
or die "Can't make socket nonblocking: $!\n"; |
or die "Can't make socket nonblocking: $!\n"; |
} |
} |
|
|
|
|
|
sub openremote { |
|
# ---------------------------------------------------- Client to network server |
|
|
|
my $conserver=shift; |
|
|
|
&status("Opening TCP: $conserver"); |
|
|
|
unless ( |
|
$remotesock = IO::Socket::INET->new(PeerAddr => $hostip{$conserver}, |
|
PeerPort => $perlvar{'londPort'}, |
|
Proto => "tcp", |
|
Type => SOCK_STREAM) |
|
) { |
|
my $st=120+int(rand(240)); |
|
&logthis( |
|
"<font color=blue>WARNING: Couldn't connect $conserver ($st secs): $@</font>"); |
|
sleep($st); |
|
exit; |
|
}; |
|
# ----------------------------------------------------------------- Init dialog |
|
|
|
&status("Init dialogue: $conserver"); |
|
|
|
$SIG{ALRM}=sub { die "timeout" }; |
|
$SIG{__DIE__}='DEFAULT'; |
|
eval { |
|
alarm(60); |
|
print $remotesock "init\n"; |
|
$answer=<$remotesock>; |
|
print $remotesock "$answer"; |
|
$answer=<$remotesock>; |
|
chomp($answer); |
|
alarm(0); |
|
}; |
|
$SIG{ALRM}='DEFAULT'; |
|
$SIG{__DIE__}=\&catchexception; |
|
|
|
if ($@=~/timeout/) { |
|
&logthis("Timed out during init: $conserver"); |
|
exit; |
|
} |
|
|
|
if ($answer ne 'ok') { |
|
&logthis("Init reply for $conserver: >$answer<"); |
|
my $st=120+int(rand(240)); |
|
&logthis( |
|
"<font color=blue>WARNING: Init failed $conserver ($st secs)</font>"); |
|
sleep($st); |
|
exit; |
|
} |
|
|
|
sleep 5; |
|
&status("Ponging $conserver"); |
|
print $remotesock "pong\n"; |
|
$answer=<$remotesock>; |
|
chomp($answer); |
|
if ($answer!~/^$converver/) { |
|
&logthis("Pong reply for $conserver: >$answer<"); |
|
} |
|
# ----------------------------------------------------------- Initialize cipher |
|
|
|
&status("Initialize cipher: $conserver"); |
|
print $remotesock "ekey\n"; |
|
my $buildkey=<$remotesock>; |
|
my $key=$conserver.$perlvar{'lonHostID'}; |
|
$key=~tr/a-z/A-Z/; |
|
$key=~tr/G-P/0-9/; |
|
$key=~tr/Q-Z/0-9/; |
|
$key=$key.$buildkey.$key.$buildkey.$key.$buildkey; |
|
$key=substr($key,0,32); |
|
my $cipherkey=pack("H32",$key); |
|
if ($cipher=new IDEA $cipherkey) { |
|
&logthis("Secure connection initialized: $conserver"); |
|
} else { |
|
my $st=120+int(rand(240)); |
|
&logthis( |
|
"<font color=blue>WARNING: ". |
|
"Could not establish secure connection, $conserver ($st secs)!</font>"); |
|
sleep($st); |
|
exit; |
|
} |
|
|
|
} |
|
|
# ----------------------------------- POD (plain old documentation, CPAN style) |
# ----------------------------------- POD (plain old documentation, CPAN style) |
|
|
=head1 NAME |
=head1 NAME |