version 1.24, 2003/11/04 11:36:04
|
version 1.25, 2003/11/04 11:52:06
|
Line 133 sub MakeLondConnection {
|
Line 133 sub MakeLondConnection {
|
return return $Connection; |
return return $Connection; |
} |
} |
# |
# |
|
# Process the connection state machine until the connection |
|
# becomes idle. This is used both to negotiate the initial |
|
# connection, during which the LondConnection sequences a rather |
|
# complex state machine and during the transaction itself |
|
# for a simpler set of transitions. |
|
# All we really need to be concerned with is whether or not |
|
# we're readable or writable and the final state: |
|
# |
|
# Parameter: |
|
# connection - Represents the LondConnection to be sequenced. |
|
# timeout - Maximum time to wait for readable/writable sockets. |
|
# in seconds. < 0 waits forever. |
|
# Return: |
|
# 'ok' - We got to idle ok. |
|
# 'error:msg' - An error occured. msg describes the error. |
|
# |
|
sub SequenceStateMachine { |
|
my $connection = shift; |
|
my $timeout = shift; |
|
|
|
my $Socket = $connection->GetSocket; |
|
my $returnstatus = "ok"; # optimist!!! |
|
my $error = 0; # Used to force early loop termination |
|
# damned perl has no break!!. |
|
my $state = $connection->GetState; |
|
|
|
while(($connection->GetState ne "Idle") && (!$error)) { |
|
# |
|
# Figure out what the connection wants. read/write and wait for it |
|
# or for the timeout. |
|
# |
|
my $wantread = $connection->WantReadable; |
|
my $poll = new IO::Poll; |
|
$poll->mask($Socket, => $wantread ? POLLIN : POLLOUT); |
|
$poll->poll($timeout); |
|
my $done = $poll->handles(); |
|
if(scalar($done) == 0) { # no handles ready... timeout!! |
|
$returnstatus = "error:"; |
|
$returnstatus .= "Timeout in state $state\n"; |
|
$error = 1; |
|
} else { |
|
my $status; |
|
$status = $wantread ? $connection->Readable : |
|
$connection->Writable; |
|
if($status != 0) { |
|
$returnstatus = "error:"; |
|
$returnstatus .= " I/O failed in state $state\n"; |
|
$error = 1; |
|
} |
|
} |
|
$state = $connection->GetState; |
|
} |
|
return $returnstatus; |
|
} |
|
|
|
# |
# This function runs through the section of the connection |
# This function runs through the section of the connection |
# state machine that has to do with negotiating the startup |
# state machine that has to do with negotiating the startup |
# sequence with lond. The general strategy is to loop |
# sequence with lond. The general strategy is to loop |
Line 163 sub NegotiateStartup {
|
Line 219 sub NegotiateStartup {
|
print "Error: Initial lond connection state: $state should be Connected\n"; |
print "Error: Initial lond connection state: $state should be Connected\n"; |
return "error"; |
return "error"; |
} |
} |
my $Socket = $connection->GetSocket; # This is a IO:Socket::INET object. |
|
|
|
# Ready now to enter the main loop: |
return SequenceStateMachine($connection, $TransitionTimeout); |
# |
|
my $error = 0; |
|
while (($connection->GetState ne "Idle") && (!$error)) { |
|
# |
|
# Wait for the socket to get into the appropriate state: |
|
# |
|
my $wantread = $connection->WantReadable; |
|
my $poll = new IO::Poll; |
|
$poll->mask($Socket => $wantread ? POLLIN : POLLOUT); |
|
$poll->poll($TransitionTimeout); |
|
my $done = $poll->handles(); |
|
if(scalar($done) == 0) { # Timeout!!! |
|
print "Error: Timeout in state : $state negotiating connection\n"; |
|
$returnstatus = "error"; |
|
$error = 1; |
|
} else { |
|
my $status; |
|
$status = $wantread ? $connection->Readable : $connection->Writable; |
|
if ($status != 0) { |
|
print "Error: I/O failed in state : $state negotiating connection\n"; |
|
$returnstatus = "error"; |
|
$error = 1; |
|
} |
|
} |
|
} |
|
|
|
|
|
return $returnstatus; |
|
} |
} |
# |
# |
# Perform a transaction with the remote lond. |
# Perform a transaction with the remote lond. |
Line 210 sub PerformTransaction {
|
Line 237 sub PerformTransaction {
|
my $connection = shift; |
my $connection = shift; |
my $command = shift; |
my $command = shift; |
my $retval; # What we'll returnl. |
my $retval; # What we'll returnl. |
|
|
|
|
# Set up the connection to do the transaction then |
# Set up the connection to do the transaction then |
# do the I/O until idle or error. |
# do the I/O until idle or error. |
# |
# |
$connection->InitiateTransaction($command); |
$connection->InitiateTransaction($command); |
my $error = 0; |
|
my $Socket = $connection->GetSocket; |
|
my $state; |
|
|
|
while (($connection->GetState ne "Idle") && (!$error)) { |
my $status = SequenceStateMachine($connection, $TransitionTimeout); |
# |
if($status eq "ok") { |
# Wait for the socket to get into the appropriate state: |
|
# |
|
my $wantread = $connection->WantReadable; |
|
my $poll = new IO::Poll; |
|
$poll->mask($Socket => $wantread ? POLLIN : POLLOUT); |
|
$poll->poll($TransitionTimeout); |
|
my $done = $poll->handles(); |
|
if(scalar($done) == 0) { # Timeout!!! |
|
print "Error: Timeout in state : $state negotiating connection\n"; |
|
$retval = "error"; |
|
$error = 1; |
|
} else { |
|
my $status; |
|
$status = $wantread ? $connection->Readable : $connection->Writable; |
|
if ($status != 0) { |
|
print "Error: I/O failed in state : $state negotiating connection\n"; |
|
$retval = "error"; |
|
$error = 1; |
|
} |
|
} |
|
} |
|
# |
|
# Fetch the reply from the transaction |
|
# |
|
if(! $error) { |
|
$retval = $connection->GetReply; |
$retval = $connection->GetReply; |
|
} else { |
|
$retval = $status; |
} |
} |
|
|
return $retval; |
return $retval; |
Line 273 sub subreply {
|
Line 275 sub subreply {
|
if($reply ne "ok") { |
if($reply ne "ok") { |
return "connection negotiation failed"; |
return "connection negotiation failed"; |
} |
} |
print "Connection negotiated\n"; |
|
my $reply = PerformTransaction($connection, $cmd); |
my $reply = PerformTransaction($connection, $cmd); |
return $reply; |
return $reply; |
|
|