version 1.101, 2017/02/28 05:42:06
|
version 1.105, 2018/08/07 17:12:09
|
Line 74 my %perlvar = %{$perlvarref};
|
Line 74 my %perlvar = %{$perlvarref};
|
|
|
my %ChildPid; # by pid -> host. |
my %ChildPid; # by pid -> host. |
my %ChildHost; # by host. |
my %ChildHost; # by host. |
|
my %ChildKeyMode; # by pid -> keymode |
my %listening_to; # Socket->host table for who the parent |
my %listening_to; # Socket->host table for who the parent |
# is listening to. |
# is listening to. |
my %parent_dispatchers; # host-> listener watcher events. |
my %parent_dispatchers; # host-> listener watcher events. |
Line 611 sub CompleteTransaction {
|
Line 612 sub CompleteTransaction {
|
StartClientReply($Transaction, $data); |
StartClientReply($Transaction, $data); |
} else { # Delete deferred transaction file. |
} else { # Delete deferred transaction file. |
Log("SUCCESS", "A delayed transaction was completed"); |
Log("SUCCESS", "A delayed transaction was completed"); |
LogPerm("S:".$Transaction->getClient().":".$Transaction->getRequest()); |
LogPerm("S:".$Socket->PeerLoncapaHim().":".$Transaction->getRequest()); |
unlink($Transaction->getFile()); |
unlink($Transaction->getFile()); |
} |
} |
} |
} |
Line 741 Parameters:
|
Line 742 Parameters:
|
|
|
The socket to kill off. |
The socket to kill off. |
|
|
=item Restart |
=item restart |
|
|
non-zero if we are allowed to create a new connection. |
non-zero if we are allowed to create a new connection. |
|
|
Line 749 non-zero if we are allowed to create a n
|
Line 750 non-zero if we are allowed to create a n
|
|
|
sub KillSocket { |
sub KillSocket { |
my $Socket = shift; |
my $Socket = shift; |
|
my $restart = shift; |
|
|
Log("WARNING", "Shutting down a socket"); |
Log("WARNING", "Shutting down a socket"); |
$Socket->Shutdown(); |
$Socket->Shutdown(); |
Line 765 sub KillSocket {
|
Line 767 sub KillSocket {
|
if(exists($ActiveConnections{$Socket})) { |
if(exists($ActiveConnections{$Socket})) { |
$ActiveConnections{$Socket}->cancel; |
$ActiveConnections{$Socket}->cancel; |
delete($ActiveConnections{$Socket}); |
delete($ActiveConnections{$Socket}); |
$ConnectionCount--; |
# Decrement ConnectionCount unless we will immediately |
|
# re-connect (i.e., $restart is true), because this was |
|
# a connection where the SSL channel for exchange of the |
|
# shared key failed, and we may use an insecure channel. |
|
unless ($restart) { |
|
$ConnectionCount--; |
|
} |
if ($ConnectionCount < 0) { $ConnectionCount = 0; } |
if ($ConnectionCount < 0) { $ConnectionCount = 0; } |
} |
} |
# If the connection count has gone to zero and there is work in the |
# If the connection count has gone to zero and there is work in the |
# work queue, the work all gets failed with con_lost. |
# work queue, the work all gets failed with con_lost. |
# |
# |
|
|
if($ConnectionCount == 0) { |
if($ConnectionCount == 0) { |
$LondConnecting = 0; # No connections so also not connecting. |
$LondConnecting = 0; # No connections so also not connecting. |
EmptyQueue(); |
EmptyQueue(); |
CloseAllLondConnections; # Should all already be closed but... |
CloseAllLondConnections(); # Should all already be closed but... |
|
&clear_childpid($$); |
} |
} |
UpdateStatus(); |
UpdateStatus(); |
} |
} |
Line 871 sub LondReadable {
|
Line 881 sub LondReadable {
|
|
|
Log("WARNING", |
Log("WARNING", |
"Lond connection lost."); |
"Lond connection lost."); |
|
my $state_on_exit = $Socket->GetState(); |
if(exists($ActiveTransactions{$Socket})) { |
if(exists($ActiveTransactions{$Socket})) { |
FailTransaction($ActiveTransactions{$Socket}); |
FailTransaction($ActiveTransactions{$Socket}); |
} else { |
} else { |
# Socket is connecting and failed... need to mark |
# Socket is connecting and failed... need to mark |
# no longer connecting. |
# no longer connecting. |
|
|
$LondConnecting = 0; |
$LondConnecting = 0; |
} |
} |
$Watcher->cancel(); |
$Watcher->cancel(); |
KillSocket($Socket); |
if ($state_on_exit eq 'ReInitNoSSL') { |
$ConnectionRetriesLeft--; # Counts as connection failure |
# SSL certificate verification failed, and insecure connection |
|
# allowed. Send restart arg to KillSocket(), so EmptyQueue() |
|
# is not called, as we still hope to process queued request. |
|
|
|
KillSocket($Socket,1); |
|
|
|
# Re-initiate creation of Lond Connection for use with queued |
|
# request. |
|
|
|
ShowStatus("Connected to ".$RemoteHost); |
|
Log("WARNING","No SSL channel (verification failed), will try with insecure channel"); |
|
&MakeLondConnection(1); |
|
|
|
} else { |
|
KillSocket($Socket); |
|
$ConnectionRetriesLeft--; # Counts as connection failure |
|
} |
return; |
return; |
} |
} |
SocketDump(6,$Socket); |
SocketDump(6,$Socket); |
Line 892 sub LondReadable {
|
Line 918 sub LondReadable {
|
if($State eq "Initialized") { |
if($State eq "Initialized") { |
|
|
|
|
|
} elsif ($State eq "ReInitNoSSL") { |
|
|
} elsif ($State eq "ChallengeReceived") { |
} elsif ($State eq "ChallengeReceived") { |
# The challenge must be echoed back; The state machine |
# The challenge must be echoed back; The state machine |
# in the connection takes care of setting that up. Just |
# in the connection takes care of setting that up. Just |
Line 928 sub LondReadable {
|
Line 956 sub LondReadable {
|
} elsif ($State eq "ReceivingKey") { |
} elsif ($State eq "ReceivingKey") { |
|
|
} elsif ($State eq "Idle") { |
} elsif ($State eq "Idle") { |
|
|
|
if ($ConnectionCount == 1) { |
|
# Write child Pid file to keep track of ssl and insecure |
|
# connections |
|
|
|
&record_childpid($Socket); |
|
} |
|
|
# This is as good a spot as any to get the peer version |
# This is as good a spot as any to get the peer version |
# string: |
# string: |
|
|
Line 1093 sub LondWritable {
|
Line 1128 sub LondWritable {
|
|
|
$Watcher->cb(\&LondReadable); |
$Watcher->cb(\&LondReadable); |
$Watcher->poll("r"); |
$Watcher->poll("r"); |
|
|
|
} elsif ($State eq "ReInitNoSSL") { |
|
|
} elsif ($State eq "ChallengeReceived") { |
} elsif ($State eq "ChallengeReceived") { |
# We received the challenge, now we |
# We received the challenge, now we |
# are echoing it back. This is a no-op, |
# are echoing it back. This is a no-op, |
Line 1204 start off on it.
|
Line 1241 start off on it.
|
|
|
=cut |
=cut |
|
|
sub MakeLondConnection { |
sub MakeLondConnection { |
|
my ($restart) = @_; |
Debug(4,"MakeLondConnection to ".GetServerHost()." on port " |
Debug(4,"MakeLondConnection to ".GetServerHost()." on port " |
.GetServerPort()); |
.GetServerPort()); |
|
|
Line 1212 sub MakeLondConnection {
|
Line 1250 sub MakeLondConnection {
|
&GetServerPort(), |
&GetServerPort(), |
&GetHostId()); |
&GetHostId()); |
|
|
if($Connection eq undef) { |
if($Connection eq undef) { |
Log("CRITICAL","Failed to make a connection with lond."); |
Log("CRITICAL","Failed to make a connection with lond."); |
$ConnectionRetriesLeft--; |
$ConnectionRetriesLeft--; |
return 0; # Failure. |
return 0; # Failure. |
} else { |
} else { |
|
|
$LondConnecting = 1; # Connection in progress. |
$LondConnecting = 1; # Connection in progress. |
# The connection needs to have writability |
# The connection needs to have writability |
# monitored in order to send the init sequence |
# monitored in order to send the init sequence |
Line 1242 sub MakeLondConnection {
|
Line 1279 sub MakeLondConnection {
|
if ($ConnectionCount == 0) { |
if ($ConnectionCount == 0) { |
&SetupTimer; # Need to handle timeouts with connections... |
&SetupTimer; # Need to handle timeouts with connections... |
} |
} |
$ConnectionCount++; |
unless ($restart) { |
|
$ConnectionCount++; |
|
} |
$Connection->SetClientData($ConnectionCount); |
$Connection->SetClientData($ConnectionCount); |
Debug(4, "Connection count = ".$ConnectionCount); |
Debug(4, "Connection count = ".$ConnectionCount); |
if($ConnectionCount == 1) { # First Connection: |
if($ConnectionCount == 1) { # First Connection: |
Line 1652 sub SignalledToDeath {
|
Line 1691 sub SignalledToDeath {
|
."died through "."\"$signal\""); |
."died through "."\"$signal\""); |
#LogPerm("F:lonc: $$ on $RemoteHost signalled to death: " |
#LogPerm("F:lonc: $$ on $RemoteHost signalled to death: " |
# ."\"$signal\""); |
# ."\"$signal\""); |
|
&clear_childpid($$); |
exit 0; |
exit 0; |
|
|
} |
} |
Line 1972 sub server_died {
|
Line 2012 sub server_died {
|
my $host = $ChildPid{$pid}; |
my $host = $ChildPid{$pid}; |
if($host) { # It's for real... |
if($host) { # It's for real... |
&Debug(9, "Caught sigchild for $host"); |
&Debug(9, "Caught sigchild for $host"); |
|
&clear_childpid($pid); |
delete($ChildPid{$pid}); |
delete($ChildPid{$pid}); |
delete($ChildHost{$host}); |
delete($ChildHost{$host}); |
&parent_clean_up($host); |
&parent_clean_up($host); |
Line 2143 sub UpdateKids {
|
Line 2184 sub UpdateKids {
|
|
|
&KillThemAll(); |
&KillThemAll(); |
LondConnection->ResetReadConfig(); |
LondConnection->ResetReadConfig(); |
|
ShowStatus('Parent keeping the flock'); |
} |
} |
|
|
|
|
Line 2181 sub KillThemAll {
|
Line 2223 sub KillThemAll {
|
# Our children >will< die. |
# Our children >will< die. |
# but we need to catch their death and cleanup after them in case this is |
# but we need to catch their death and cleanup after them in case this is |
# a restart set of kills |
# a restart set of kills |
|
my $execdir = $perlvar{'lonDaemons'}; |
my @allpids = keys(%ChildPid); |
my @allpids = keys(%ChildPid); |
foreach my $pid (@allpids) { |
foreach my $pid (@allpids) { |
my $serving = $ChildPid{$pid}; |
my $serving = $ChildPid{$pid}; |
ShowStatus("Nicely Killing lonc for $serving pid = $pid"); |
ShowStatus("Nicely Killing lonc for $serving pid = $pid"); |
Log("CRITICAL", "Nicely Killing lonc for $serving pid = $pid"); |
Log("CRITICAL", "Nicely Killing lonc for $serving pid = $pid"); |
kill 'QUIT' => $pid; |
kill 'QUIT' => $pid; |
|
&clear_childpid($pid); |
} |
} |
ShowStatus("Finished killing child processes off."); |
ShowStatus("Finished killing child processes off."); |
} |
} |
Line 2206 sub really_kill_them_all_dammit
|
Line 2250 sub really_kill_them_all_dammit
|
Log("CRITICAL", "Nastily killing lonc for $serving pid = $pid"); |
Log("CRITICAL", "Nastily killing lonc for $serving pid = $pid"); |
kill 'KILL' => $pid; |
kill 'KILL' => $pid; |
delete($ChildPid{$pid}); |
delete($ChildPid{$pid}); |
|
delete($ChildKeyMode{$pid}); |
my $execdir = $perlvar{'lonDaemons'}; |
my $execdir = $perlvar{'lonDaemons'}; |
unlink("$execdir/logs/lonc.pid"); |
unlink("$execdir/logs/lonc.pid"); |
} |
} |
Line 2234 sub Terminate {
|
Line 2279 sub Terminate {
|
|
|
} |
} |
|
|
|
=pod |
|
|
|
=cut |
|
|
sub my_hostname { |
sub my_hostname { |
use Sys::Hostname; |
use Sys::Hostname::FQDN(); |
my $name = &hostname(); |
my $name = Sys::Hostname::FQDN::fqdn(); |
&Debug(9,"Name is $name"); |
&Debug(9,"Name is $name"); |
return $name; |
return $name; |
} |
} |
|
|
|
sub record_childpid { |
|
my ($Socket) = @_; |
|
my $docdir = $perlvar{'lonDocRoot'}; |
|
my $authmode = $Socket->GetKeyMode(); |
|
my $peer = $Socket->PeerLoncapaHim(); |
|
if (($authmode eq 'ssl') || ($authmode eq 'insecure')) { |
|
my $childpid = $$; |
|
if ($childpid) { |
|
unless (exists($ChildKeyMode{$childpid})) { |
|
$ChildKeyMode{$childpid} = $authmode; |
|
} |
|
if (-d "$docdir/lon-status/loncchld") { |
|
unless (-e "$docdir/lon-status/loncchld/$childpid") { |
|
if (open (my $pidfh,'>',"$docdir/lon-status/loncchld/$childpid")) { |
|
print $pidfh "$peer:$authmode\n"; |
|
close($pidfh); |
|
} |
|
} |
|
} |
|
} |
|
} |
|
return; |
|
} |
|
|
|
sub clear_childpid { |
|
my ($childpid) = @_; |
|
my $docdir = $perlvar{'lonDocRoot'}; |
|
if (-d "$docdir/lon-status/loncchld") { |
|
if ($childpid =~ /^\d+$/) { |
|
if (($ChildKeyMode{$childpid} eq 'insecure') || |
|
($ChildKeyMode{$childpid} eq 'ssl')) { |
|
if (-e "$docdir/lon-status/loncchld/$childpid") { |
|
unlink("$docdir/lon-status/loncchld/$childpid"); |
|
} |
|
} |
|
} |
|
} |
|
if (exists($ChildKeyMode{$childpid})) { |
|
delete($ChildKeyMode{$childpid}); |
|
} |
|
return; |
|
} |
|
|
=pod |
=pod |
|
|
=head1 Theory |
=head1 Theory |
Line 2345 connection or died. This should be foll
|
Line 2437 connection or died. This should be foll
|
|
|
"WARNING Failing transaction..." msgs for each in-flight or queued transaction. |
"WARNING Failing transaction..." msgs for each in-flight or queued transaction. |
|
|
|
=item WARNING No SSL channel (verification failed), will try with insecure channel. |
|
|
|
Called when promotion of a socket to SSL failed because SSL certificate verification failed. |
|
Domain configuration must also permit insecure channel use for key exchange. Connection |
|
negotiation will start again from the beginning, but with Authentication Mode not set to ssl. |
|
|
=item INFO Connected to lond version: <version> |
=item INFO Connected to lond version: <version> |
|
|
When connection negotiation is complete, the lond version is requested and logged here. |
When connection negotiation is complete, the lond version is requested and logged here. |