version 1.40, 2004/02/09 10:58:03
|
version 1.46, 2004/05/25 15:32:13
|
Line 110 my $LondVersion = "unknown"; # Versi
|
Line 110 my $LondVersion = "unknown"; # Versi
|
# |
# |
my %LogFormats; |
my %LogFormats; |
|
|
$LogFormats{"CRITICAL"} = "<font color=red>CRITICAL: %s</font>"; |
$LogFormats{"CRITICAL"} = "<font color='red'>CRITICAL: %s</font>"; |
$LogFormats{"SUCCESS"} = "<font color=green>SUCCESS: %s</font>"; |
$LogFormats{"SUCCESS"} = "<font color='green'>SUCCESS: %s</font>"; |
$LogFormats{"INFO"} = "<font color=yellow>INFO: %s</font>"; |
$LogFormats{"INFO"} = "<font color='yellow'>INFO: %s</font>"; |
$LogFormats{"WARNING"} = "<font color=blue>WARNING: %s</font>"; |
$LogFormats{"WARNING"} = "<font color='blue'>WARNING: %s</font>"; |
$LogFormats{"DEFAULT"} = " %s "; |
$LogFormats{"DEFAULT"} = " %s "; |
|
|
|
|
Line 262 sub SocketTimeout {
|
Line 262 sub SocketTimeout {
|
Log("WARNING", "A socket timeout was detected"); |
Log("WARNING", "A socket timeout was detected"); |
Debug(0, " SocketTimeout called: "); |
Debug(0, " SocketTimeout called: "); |
$Socket->Dump(); |
$Socket->Dump(); |
|
if(exists($ActiveTransactions{$Socket})) { |
|
FailTransaction($ActiveTransactions{$Socket}); |
|
} |
KillSocket($Socket); # A transaction timeout also counts as |
KillSocket($Socket); # A transaction timeout also counts as |
# a connection failure: |
# a connection failure: |
$ConnectionRetriesLeft--; |
$ConnectionRetriesLeft--; |
|
if($ConnectionRetriesLeft <= 0) { |
|
Log("CRITICAL", "Host marked dead: ".GetServerHost()); |
|
} |
|
|
} |
} |
#----------------------------- Timer management ------------------------ |
#----------------------------- Timer management ------------------------ |
|
|
Line 326 sub Tick {
|
Line 333 sub Tick {
|
if($successCount == 0) { # All connections failed: |
if($successCount == 0) { # All connections failed: |
Debug(5,"Work in queue failed to make any connectiouns\n"); |
Debug(5,"Work in queue failed to make any connectiouns\n"); |
EmptyQueue(); # Fail pending transactions with con_lost. |
EmptyQueue(); # Fail pending transactions with con_lost. |
|
CloseAllLondConnections(); # Should all be closed but.... |
} |
} |
} else { |
} else { |
ShowStatus(GetServerHost()." >>> DEAD!!! <<<"); |
ShowStatus(GetServerHost()." >>> DEAD!!! <<<"); |
Debug(5,"Work in queue, but gave up on connections..flushing\n"); |
Debug(5,"Work in queue, but gave up on connections..flushing\n"); |
EmptyQueue(); # Connections can't be established. |
EmptyQueue(); # Connections can't be established. |
|
CloseAllLondConnections(); # Should all already be closed but... |
} |
} |
|
|
} |
} |
Line 521 sub CompleteTransaction {
|
Line 530 sub CompleteTransaction {
|
unlink $Transaction->getFile(); |
unlink $Transaction->getFile(); |
} |
} |
} |
} |
|
|
=pod |
=pod |
|
|
=head1 StartClientReply |
=head1 StartClientReply |
|
|
Initiates a reply to a client where the reply data is a parameter. |
Initiates a reply to a client where the reply data is a parameter. |
Line 537 sub CompleteTransaction {
|
Line 548 sub CompleteTransaction {
|
The data to send to apached client. |
The data to send to apached client. |
|
|
=cut |
=cut |
|
|
sub StartClientReply { |
sub StartClientReply { |
my $Transaction = shift; |
my $Transaction = shift; |
my $data = shift; |
my $data = shift; |
Line 554 sub StartClientReply {
|
Line 566 sub StartClientReply {
|
cb => \&ClientWritable, |
cb => \&ClientWritable, |
data => $data); |
data => $data); |
} |
} |
|
|
=pod |
=pod |
|
|
=head2 FailTransaction |
=head2 FailTransaction |
|
|
Finishes a transaction with failure because the associated lond socket |
Finishes a transaction with failure because the associated lond socket |
Line 564 sub StartClientReply {
|
Line 578 sub StartClientReply {
|
- The transaction is 'live' in which case we initiate the sending |
- The transaction is 'live' in which case we initiate the sending |
of "con_lost" to the client. |
of "con_lost" to the client. |
|
|
Deleting the transaction means killing it from the |
Deleting the transaction means killing it from the %ActiveTransactions hash. |
%ActiveTransactions hash. |
|
|
|
Parameters: |
Parameters: |
|
|
Line 573 Parameters:
|
Line 586 Parameters:
|
|
|
The LondTransaction we are failing. |
The LondTransaction we are failing. |
|
|
|
|
=cut |
=cut |
|
|
sub FailTransaction { |
sub FailTransaction { |
Line 584 sub FailTransaction {
|
Line 598 sub FailTransaction {
|
Debug(1," Replying con_lost to ".$transaction->getRequest()); |
Debug(1," Replying con_lost to ".$transaction->getRequest()); |
StartClientReply($transaction, "con_lost\n"); |
StartClientReply($transaction, "con_lost\n"); |
} |
} |
if($ConnectionRetriesLeft <= 0) { |
|
Log("CRITICAL", "Host marked dead: ".GetServerHost()); |
|
} |
|
|
|
} |
} |
|
|
Line 614 Close all connections open on lond prior
|
Line 625 Close all connections open on lond prior
|
=cut |
=cut |
sub CloseAllLondConnections { |
sub CloseAllLondConnections { |
foreach my $Socket (keys %ActiveConnections) { |
foreach my $Socket (keys %ActiveConnections) { |
KillSocket($Socket); |
if(exists($ActiveTransactions{$Socket})) { |
|
FailTransaction($ActiveTransactions{$Socket}); |
|
} |
|
KillSocket($Socket); |
} |
} |
} |
} |
=cut |
=cut |
Line 666 sub KillSocket {
|
Line 680 sub KillSocket {
|
# |
# |
if($ConnectionCount == 0) { |
if($ConnectionCount == 0) { |
EmptyQueue(); |
EmptyQueue(); |
|
CloseAllLondConnections; # Should all already be closed but... |
} |
} |
} |
} |
|
|
Line 740 transaction is in progress, the socket a
|
Line 755 transaction is in progress, the socket a
|
|
|
sub LondReadable { |
sub LondReadable { |
|
|
my $Event = shift; |
my $Event = shift; |
my $Watcher = $Event->w; |
my $Watcher = $Event->w; |
my $Socket = $Watcher->data; |
my $Socket = $Watcher->data; |
my $client = undef; |
my $client = undef; |
|
|
&Debug(6,"LondReadable called state = ".$Socket->GetState()); |
&Debug(6,"LondReadable called state = ".$Socket->GetState()); |
|
|
|
|
my $State = $Socket->GetState(); # All action depends on the state. |
my $State = $Socket->GetState(); # All action depends on the state. |
|
|
SocketDump(6, $Socket); |
SocketDump(6, $Socket); |
my $status = $Socket->Readable(); |
my $status = $Socket->Readable(); |
|
|
&Debug(2, "Socket->Readable returned: $status"); |
&Debug(2, "Socket->Readable returned: $status"); |
|
|
if($status != 0) { |
if($status != 0) { |
# bad return from socket read. Currently this means that |
# bad return from socket read. Currently this means that |
# The socket has become disconnected. We fail the transaction. |
# The socket has become disconnected. We fail the transaction. |
|
|
Log("WARNING", |
Log("WARNING", |
"Lond connection lost."); |
"Lond connection lost."); |
if(exists($ActiveTransactions{$Socket})) { |
if(exists($ActiveTransactions{$Socket})) { |
FailTransaction($ActiveTransactions{$Socket}); |
FailTransaction($ActiveTransactions{$Socket}); |
} |
} |
$Watcher->cancel(); |
$Watcher->cancel(); |
KillSocket($Socket); |
KillSocket($Socket); |
$ConnectionRetriesLeft--; # Counts as connection failure |
$ConnectionRetriesLeft--; # Counts as connection failure |
return; |
return; |
} |
} |
SocketDump(6,$Socket); |
SocketDump(6,$Socket); |
|
|
$State = $Socket->GetState(); # Update in case of transition. |
$State = $Socket->GetState(); # Update in case of transition. |
&Debug(6, "After read, state is ".$State); |
&Debug(6, "After read, state is ".$State); |
|
|
if($State eq "Initialized") { |
if($State eq "Initialized") { |
|
|
|
|
} 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 |
# need to transition to writable: |
# need to transition to writable: |
|
|
|
$Watcher->cb(\&LondWritable); |
|
$Watcher->poll("w"); |
|
|
$Watcher->cb(\&LondWritable); |
} elsif ($State eq "ChallengeReplied") { |
$Watcher->poll("w"); |
|
|
|
} elsif ($State eq "ChallengeReplied") { |
} elsif ($State eq "RequestingVersion") { |
|
# Need to ask for the version... that is writiability: |
|
|
} elsif ($State eq "RequestingVersion") { |
$Watcher->cb(\&LondWritable); |
# Need to ask for the version... that is writiability: |
$Watcher->poll("w"); |
|
|
$Watcher->cb(\&LondWritable); |
} elsif ($State eq "ReadingVersionString") { |
$Watcher->poll("w"); |
# Read the rest of the version string... |
|
} elsif ($State eq "SetHost") { |
} elsif ($State eq "ReadingVersionString") { |
# Need to request the actual domain get set... |
# Read the rest of the version string... |
|
} elsif ($State eq "SetHost") { |
$Watcher->cb(\&LondWritable); |
# Need to request the actual domain get set... |
$Watcher->poll("w"); |
|
} elsif ($State eq "HostSet") { |
$Watcher->cb(\&LondWritable); |
# Reading the 'ok' from the peer. |
$Watcher->poll("w"); |
|
} elsif ($State eq "HostSet") { |
} elsif ($State eq "RequestingKey") { |
# Reading the 'ok' from the peer. |
|
|
|
} elsif ($State eq "RequestingKey") { |
|
# The ok was received. Now we need to request the key |
# The ok was received. Now we need to request the key |
# That requires us to be writable: |
# That requires us to be writable: |
|
|
$Watcher->cb(\&LondWritable); |
$Watcher->cb(\&LondWritable); |
$Watcher->poll("w"); |
$Watcher->poll("w"); |
|
|
} elsif ($State eq "ReceivingKey") { |
} elsif ($State eq "ReceivingKey") { |
|
|
} elsif ($State eq "Idle") { |
} elsif ($State eq "Idle") { |
|
|
# 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: |
|
|
if($LondVersion eq "unknown") { |
if($LondVersion eq "unknown") { |
$LondVersion = $Socket->PeerVersion(); |
$LondVersion = $Socket->PeerVersion(); |
Log("INFO", "Connected to lond version: $LondVersion"); |
Log("INFO", "Connected to lond version: $LondVersion"); |
} |
} |
# If necessary, complete a transaction and then go into the |
# If necessary, complete a transaction and then go into the |
# idle queue. |
# idle queue. |
# Note that a trasition to idle indicates a live lond |
# Note that a trasition to idle indicates a live lond |
# on the other end so reset the connection retries. |
# on the other end so reset the connection retries. |
# |
# |
$ConnectionRetriesLeft = $ConnectionRetries; # success resets the count |
$ConnectionRetriesLeft = $ConnectionRetries; # success resets the count |
$Watcher->cancel(); |
$Watcher->cancel(); |
if(exists($ActiveTransactions{$Socket})) { |
if(exists($ActiveTransactions{$Socket})) { |
Debug(5,"Completing transaction!!"); |
Debug(5,"Completing transaction!!"); |
CompleteTransaction($Socket, |
CompleteTransaction($Socket, |
$ActiveTransactions{$Socket}); |
$ActiveTransactions{$Socket}); |
} else { |
} else { |
Log("SUCCESS", "Connection ".$ConnectionCount." to " |
Log("SUCCESS", "Connection ".$ConnectionCount." to " |
.$RemoteHost." now ready for action"); |
.$RemoteHost." now ready for action"); |
} |
} |
ServerToIdle($Socket); # Next work unit or idle. |
ServerToIdle($Socket); # Next work unit or idle. |
|
|
} elsif ($State eq "SendingRequest") { |
} elsif ($State eq "SendingRequest") { |
# We need to be writable for this and probably don't belong |
# We need to be writable for this and probably don't belong |
# here inthe first place. |
# here inthe first place. |
|
|
Deubg(6, "SendingRequest state encountered in readable"); |
Deubg(6, "SendingRequest state encountered in readable"); |
$Watcher->poll("w"); |
$Watcher->poll("w"); |
$Watcher->cb(\&LondWritable); |
$Watcher->cb(\&LondWritable); |
|
|
} elsif ($State eq "ReceivingReply") { |
} elsif ($State eq "ReceivingReply") { |
|
|
|
|
} else { |
} else { |
# Invalid state. |
# Invalid state. |
Debug(4, "Invalid state in LondReadable"); |
Debug(4, "Invalid state in LondReadable"); |
} |
} |
} |
} |
|
|
=pod |
=pod |
Line 932 sub LondWritable {
|
Line 947 sub LondWritable {
|
|
|
SocketDump(6,$Socket); |
SocketDump(6,$Socket); |
|
|
if ($State eq "Connected") { |
# If the socket is writable, we must always write. |
|
# Only by writing will we undergo state transitions. |
|
# Old logic wrote in state specific code below, however |
|
# That forces us at least through another invocation of |
|
# this function after writability is possible again. |
|
# This logic also factors out common code for handling |
|
# write failures... in all cases, write failures |
|
# Kill the socket. |
|
# This logic makes the branches of the >big< if below |
|
# so that the writing states are actually NO-OPs. |
|
|
|
if ($Socket->Writable() != 0) { |
|
# The write resulted in an error. |
|
# We'll treat this as if the socket got disconnected: |
|
Log("WARNING", "Connection to ".$RemoteHost. |
|
" has been disconnected"); |
|
if(exists($ActiveTransactions{$Socket})) { |
|
FailTransaction($ActiveTransactions{$Socket}); |
|
} |
|
$Watcher->cancel(); |
|
KillSocket($Socket); |
|
return; |
|
} |
|
|
if ($Socket->Writable() != 0) { |
|
# The write resulted in an error. |
|
# We'll treat this as if the socket got disconnected: |
|
Log("WARNING", "Connection to ".$RemoteHost. |
|
" has been disconnected"); |
|
FailTransaction($ActiveTransactions{$Socket}); |
|
$Watcher->cancel(); |
|
KillSocket($Socket); |
|
return; |
|
} |
|
|
|
# "init" is being sent... |
|
|
|
} elsif ($State eq "Initialized") { |
|
|
|
# Now that init was sent, we switch |
|
# to watching for readability: |
|
|
|
$Watcher->cb(\&LondReadable); |
if ($State eq "Connected") { |
$Watcher->poll("r"); |
|
|
|
} elsif ($State eq "ChallengeReceived") { |
# "init" is being sent... |
# We received the challenge, now we |
|
# are echoing it back. This is a no-op, |
} elsif ($State eq "Initialized") { |
# we're waiting for the state to change |
|
|
|
if($Socket->Writable() != 0) { |
|
|
|
$Watcher->cancel(); |
# Now that init was sent, we switch |
KillSocket($Socket); |
# to watching for readability: |
return; |
|
} |
$Watcher->cb(\&LondReadable); |
|
$Watcher->poll("r"); |
|
|
} elsif ($State eq "ChallengeReplied") { |
} elsif ($State eq "ChallengeReceived") { |
# The echo was sent back, so we switch |
# We received the challenge, now we |
# to watching readability. |
# are echoing it back. This is a no-op, |
|
# we're waiting for the state to change |
$Watcher->cb(\&LondReadable); |
|
$Watcher->poll("r"); |
} elsif ($State eq "ChallengeReplied") { |
} elsif ($State eq "RequestingVersion") { |
# The echo was sent back, so we switch |
# Sending the peer a version request... |
# to watching readability. |
|
|
if($Socket->Writable() != 0) { |
$Watcher->cb(\&LondReadable); |
$Watcher->cancel(); |
$Watcher->poll("r"); |
KillSocket($Socket); |
} elsif ($State eq "RequestingVersion") { |
return; |
# Sending the peer a version request... |
} |
|
} elsif ($State eq "ReadingVersionString") { |
} elsif ($State eq "ReadingVersionString") { |
# Transition to read since we have sent the |
# Transition to read since we have sent the |
# version command and now just need to read the |
# version command and now just need to read the |
# version string from the peer: |
# version string from the peer: |
|
|
$Watcher->cb(\&LondReadable); |
|
$Watcher->poll("r"); |
|
|
|
} elsif ($State eq "SetHost") { |
$Watcher->cb(\&LondReadable); |
# Setting the remote domain... |
$Watcher->poll("r"); |
|
|
if($Socket->Writable() != 0) { |
} elsif ($State eq "SetHost") { |
$Watcher->cancel(); |
# Setting the remote domain... |
KillSocket($Socket); |
|
return; |
} elsif ($State eq "HostSet") { |
} |
# Back to readable to get the ok. |
} elsif ($State eq "HostSet") { |
|
# Back to readable to get the ok. |
|
|
|
$Watcher->cb(\&LondReadable); |
$Watcher->cb(\&LondReadable); |
$Watcher->poll("r"); |
$Watcher->poll("r"); |
|
|
|
|
} elsif ($State eq "RequestingKey") { |
} elsif ($State eq "RequestingKey") { |
# At this time we're requesting the key. |
# At this time we're requesting the key. |
# again, this is essentially a no-op. |
# again, this is essentially a no-op. |
# we'll write the next chunk until the |
|
# state changes. |
} elsif ($State eq "ReceivingKey") { |
|
# Now we need to wait for the key |
if($Socket->Writable() != 0) { |
# to come back from the peer: |
# Write resulted in an error. |
|
|
|
$Watcher->cancel(); |
|
KillSocket($Socket); |
|
return; |
|
|
|
} |
$Watcher->cb(\&LondReadable); |
} elsif ($State eq "ReceivingKey") { |
$Watcher->poll("r"); |
# Now we need to wait for the key |
|
# to come back from the peer: |
|
|
|
$Watcher->cb(\&LondReadable); |
} elsif ($State eq "SendingRequest") { |
$Watcher->poll("r"); |
|
|
|
} elsif ($State eq "SendingRequest") { |
|
|
|
# At this time we are sending a request to the |
# At this time we are sending a request to the |
# peer... write the next chunk: |
# peer... write the next chunk: |
|
|
if($Socket->Writable() != 0) { |
|
|
|
if(exists($ActiveTransactions{$Socket})) { |
} elsif ($State eq "ReceivingReply") { |
Debug(3, "Lond connection lost, failing transactions"); |
# The send has completed. Wait for the |
FailTransaction($ActiveTransactions{$Socket}); |
# data to come in for a reply. |
} |
Debug(8,"Writable sent request/receiving reply"); |
$Watcher->cancel(); |
$Watcher->cb(\&LondReadable); |
KillSocket($Socket); |
$Watcher->poll("r"); |
return; |
|
|
|
} |
|
|
|
} elsif ($State eq "ReceivingReply") { |
} else { |
# The send has completed. Wait for the |
# Control only passes here on an error: |
# data to come in for a reply. |
# the socket state does not match any |
Debug(8,"Writable sent request/receiving reply"); |
# of the known states... so an error |
$Watcher->cb(\&LondReadable); |
# must be logged. |
$Watcher->poll("r"); |
|
|
|
} else { |
|
# Control only passes here on an error: |
|
# the socket state does not match any |
|
# of the known states... so an error |
|
# must be logged. |
|
|
|
&Debug(4, "Invalid socket state ".$State."\n"); |
&Debug(4, "Invalid socket state ".$State."\n"); |
} |
} |
|
|
} |
} |
=pod |
=pod |
Line 1229 sub QueueTransaction {
|
Line 1221 sub QueueTransaction {
|
Debug(5,"Starting additional lond connection"); |
Debug(5,"Starting additional lond connection"); |
if(MakeLondConnection() == 0) { |
if(MakeLondConnection() == 0) { |
EmptyQueue(); # Fail transactions, can't make connection. |
EmptyQueue(); # Fail transactions, can't make connection. |
|
CloseAllLondConnections; # Should all be closed but... |
} |
} |
} else { |
} else { |
ShowStatus(GetServerHost()." >>> DEAD !!!! <<<"); |
ShowStatus(GetServerHost()." >>> DEAD !!!! <<<"); |
EmptyQueue(); # It's worse than that ... he's dead Jim. |
EmptyQueue(); # It's worse than that ... he's dead Jim. |
|
CloseAllLondConnections; # Should all be closed but.. |
} |
} |
} |
} |
} else { # Can start the request: |
} else { # Can start the request: |
Line 1275 sub ClientRequest {
|
Line 1269 sub ClientRequest {
|
Debug(8,"Data: ".$data." this read: ".$thisread); |
Debug(8,"Data: ".$data." this read: ".$thisread); |
$data = $data.$thisread; # Append new data. |
$data = $data.$thisread; # Append new data. |
$watcher->data($data); |
$watcher->data($data); |
if($data =~ /(.*\n)/) { # Request entirely read. |
if($data =~ /\n$/) { # Request entirely read. |
if($data eq "close_connection_exit\n") { |
if($data eq "close_connection_exit\n") { |
Log("CRITICAL", |
Log("CRITICAL", |
"Request Close Connection ... exiting"); |
"Request Close Connection ... exiting"); |
Line 1422 into the status file.
|
Line 1416 into the status file.
|
We also use this to reset the retries count in order to allow the |
We also use this to reset the retries count in order to allow the |
client to retry connections with a previously dead server. |
client to retry connections with a previously dead server. |
=cut |
=cut |
|
|
sub ChildStatus { |
sub ChildStatus { |
my $event = shift; |
my $event = shift; |
my $watcher = $event->w; |
my $watcher = $event->w; |
Line 1434 sub ChildStatus {
|
Line 1429 sub ChildStatus {
|
# |
# |
# Write out information about each of the connections: |
# Write out information about each of the connections: |
# |
# |
print $fh "Active connection statuses: \n"; |
if ($DebugLevel > 2) { |
my $i = 1; |
print $fh "Active connection statuses: \n"; |
print STDERR "================================= Socket Status Dump:\n"; |
my $i = 1; |
foreach my $item (keys %ActiveConnections) { |
print STDERR "================================= Socket Status Dump:\n"; |
my $Socket = $ActiveConnections{$item}->data; |
foreach my $item (keys %ActiveConnections) { |
my $state = $Socket->GetState(); |
my $Socket = $ActiveConnections{$item}->data; |
print $fh "Connection $i State: $state\n"; |
my $state = $Socket->GetState(); |
print STDERR "---------------------- Connection $i \n"; |
print $fh "Connection $i State: $state\n"; |
$Socket->Dump(); |
print STDERR "---------------------- Connection $i \n"; |
$i++; |
$Socket->Dump(); |
|
$i++; |
|
} |
} |
} |
$ConnectionRetriesLeft = $ConnectionRetries; |
$ConnectionRetriesLeft = $ConnectionRetries; |
} |
} |