version 1.40, 2004/02/09 10:58:03
|
version 1.41, 2004/02/09 13:39:28
|
Line 740 transaction is in progress, the socket a
|
Line 740 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 932 sub LondWritable {
|
|
|
SocketDump(6,$Socket); |
SocketDump(6,$Socket); |
|
|
if ($State eq "Connected") { |
if ($State eq "Connected") { |
|
|
if ($Socket->Writable() != 0) { |
if ($Socket->Writable() != 0) { |
# The write resulted in an error. |
# The write resulted in an error. |
# We'll treat this as if the socket got disconnected: |
# We'll treat this as if the socket got disconnected: |
Log("WARNING", "Connection to ".$RemoteHost. |
Log("WARNING", "Connection to ".$RemoteHost. |
" has been disconnected"); |
" has been disconnected"); |
FailTransaction($ActiveTransactions{$Socket}); |
FailTransaction($ActiveTransactions{$Socket}); |
$Watcher->cancel(); |
$Watcher->cancel(); |
KillSocket($Socket); |
KillSocket($Socket); |
return; |
return; |
} |
} |
|
|
# "init" is being sent... |
# "init" is being sent... |
|
|
} elsif ($State eq "Initialized") { |
} elsif ($State eq "Initialized") { |
|
|
# Now that init was sent, we switch |
# Now that init was sent, we switch |
# to watching for readability: |
# to watching for readability: |
|
|
$Watcher->cb(\&LondReadable); |
$Watcher->cb(\&LondReadable); |
$Watcher->poll("r"); |
$Watcher->poll("r"); |
|
|
} elsif ($State eq "ChallengeReceived") { |
|
# We received the challenge, now we |
|
# are echoing it back. This is a no-op, |
|
# we're waiting for the state to change |
|
|
|
if($Socket->Writable() != 0) { |
} elsif ($State eq "ChallengeReceived") { |
|
# We received the challenge, now we |
$Watcher->cancel(); |
# are echoing it back. This is a no-op, |
KillSocket($Socket); |
# we're waiting for the state to change |
return; |
|
} |
|
|
|
} elsif ($State eq "ChallengeReplied") { |
if($Socket->Writable() != 0) { |
# The echo was sent back, so we switch |
|
# to watching readability. |
|
|
|
$Watcher->cb(\&LondReadable); |
|
$Watcher->poll("r"); |
|
} elsif ($State eq "RequestingVersion") { |
|
# Sending the peer a version request... |
|
|
|
if($Socket->Writable() != 0) { |
|
$Watcher->cancel(); |
|
KillSocket($Socket); |
|
return; |
|
} |
|
} elsif ($State eq "ReadingVersionString") { |
|
# Transition to read since we have sent the |
|
# version command and now just need to read the |
|
# version string from the peer: |
|
|
|
$Watcher->cb(\&LondReadable); |
|
$Watcher->poll("r"); |
|
|
|
} elsif ($State eq "SetHost") { |
|
# Setting the remote domain... |
|
|
|
if($Socket->Writable() != 0) { |
|
$Watcher->cancel(); |
|
KillSocket($Socket); |
|
return; |
|
} |
|
} elsif ($State eq "HostSet") { |
|
# Back to readable to get the ok. |
|
|
|
$Watcher->cb(\&LondReadable); |
|
$Watcher->poll("r"); |
|
|
|
|
|
} elsif ($State eq "RequestingKey") { |
$Watcher->cancel(); |
# At this time we're requesting the key. |
KillSocket($Socket); |
# again, this is essentially a no-op. |
return; |
# we'll write the next chunk until the |
} |
# state changes. |
|
|
} elsif ($State eq "ChallengeReplied") { |
if($Socket->Writable() != 0) { |
# The echo was sent back, so we switch |
# Write resulted in an error. |
# to watching readability. |
|
|
$Watcher->cancel(); |
$Watcher->cb(\&LondReadable); |
KillSocket($Socket); |
$Watcher->poll("r"); |
return; |
} elsif ($State eq "RequestingVersion") { |
|
# Sending the peer a version request... |
} |
|
} elsif ($State eq "ReceivingKey") { |
if($Socket->Writable() != 0) { |
# Now we need to wait for the key |
$Watcher->cancel(); |
# to come back from the peer: |
KillSocket($Socket); |
|
return; |
|
} |
|
} elsif ($State eq "ReadingVersionString") { |
|
# Transition to read since we have sent the |
|
# version command and now just need to read the |
|
# version string from the peer: |
|
|
|
$Watcher->cb(\&LondReadable); |
|
$Watcher->poll("r"); |
|
|
|
} elsif ($State eq "SetHost") { |
|
# Setting the remote domain... |
|
|
|
if($Socket->Writable() != 0) { |
|
$Watcher->cancel(); |
|
KillSocket($Socket); |
|
return; |
|
} |
|
} elsif ($State eq "HostSet") { |
|
# Back to readable to get the ok. |
|
|
|
$Watcher->cb(\&LondReadable); |
|
$Watcher->poll("r"); |
|
|
|
|
|
} elsif ($State eq "RequestingKey") { |
|
# At this time we're requesting the key. |
|
# again, this is essentially a no-op. |
|
# we'll write the next chunk until the |
|
# state changes. |
|
|
|
if($Socket->Writable() != 0) { |
|
# Write resulted in an error. |
|
|
|
$Watcher->cancel(); |
|
KillSocket($Socket); |
|
return; |
|
|
|
} |
|
} elsif ($State eq "ReceivingKey") { |
|
# Now we need to wait for the key |
|
# to come back from the peer: |
|
|
$Watcher->cb(\&LondReadable); |
$Watcher->cb(\&LondReadable); |
$Watcher->poll("r"); |
$Watcher->poll("r"); |
|
|
} elsif ($State eq "SendingRequest") { |
} 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($Socket->Writable() != 0) { |
|
|
if(exists($ActiveTransactions{$Socket})) { |
if(exists($ActiveTransactions{$Socket})) { |
Debug(3, "Lond connection lost, failing transactions"); |
Debug(3, "Lond connection lost, failing transactions"); |
FailTransaction($ActiveTransactions{$Socket}); |
FailTransaction($ActiveTransactions{$Socket}); |
} |
} |
$Watcher->cancel(); |
$Watcher->cancel(); |
KillSocket($Socket); |
KillSocket($Socket); |
return; |
return; |
|
|
} |
} |
|
|
} elsif ($State eq "ReceivingReply") { |
} elsif ($State eq "ReceivingReply") { |
# The send has completed. Wait for the |
# The send has completed. Wait for the |
# data to come in for a reply. |
# data to come in for a reply. |
Debug(8,"Writable sent request/receiving reply"); |
Debug(8,"Writable sent request/receiving reply"); |
$Watcher->cb(\&LondReadable); |
$Watcher->cb(\&LondReadable); |
$Watcher->poll("r"); |
$Watcher->poll("r"); |
|
|
} else { |
} else { |
# Control only passes here on an error: |
# Control only passes here on an error: |
# the socket state does not match any |
# the socket state does not match any |
# of the known states... so an error |
# of the known states... so an error |
# must be logged. |
# must be logged. |
|
|
&Debug(4, "Invalid socket state ".$State."\n"); |
&Debug(4, "Invalid socket state ".$State."\n"); |
} |
} |
|
|
} |
} |
=pod |
=pod |