[LON-CAPA-cvs] cvs: newloncapa / loncnew
foxr
lon-capa-cvs@mail.lon-capa.org
Sun, 23 Mar 2003 00:04:52 -0000
This is a MIME encoded message
--foxr1048377892
Content-Type: text/plain
foxr Sat Mar 22 19:04:52 2003 EDT
Modified files:
/newloncapa loncnew
Log:
Get state machine if for new connections to work all the way through
key negiotiation.
--foxr1048377892
Content-Type: text/plain
Content-Disposition: attachment; filename="foxr-20030322190452.txt"
Index: newloncapa/loncnew
diff -u newloncapa/loncnew:1.2 newloncapa/loncnew:1.3
--- newloncapa/loncnew:1.2 Wed Feb 26 22:02:27 2003
+++ newloncapa/loncnew Sat Mar 22 19:04:51 2003
@@ -16,6 +16,7 @@
# - Add management/status request interface.
use lib "/home/httpd/lib/perl/";
+use lib "/home/foxr/newloncapa/types";
use Event qw(:DEFAULT );
use POSIX;
use IO::Socket;
@@ -25,6 +26,7 @@
use Crypt::IDEA;
use Queue;
use Stack;
+use LondConnection;
#
# The stack below is a cache of a idle connections.
@@ -37,7 +39,7 @@
my $ConnectionCount = 0;
my $MaxConnectionCount = 5; # Will get from config later.
-$DebugLevel = 4;
+$DebugLevel = 10;
#----------------------------- Timer management ------------------------
@@ -71,14 +73,143 @@
=cut
-sub SetupTimer() {
+sub SetupTimer {
Debug(4, "SetupTimer");
Event->timer(interval => 1, debug => 1, cb => \&Tick );
}
+=pod
+=head2 ServerToIdle
+ This function is called when a connection to the server is
+ready for more work.
+ If there is work in the Work queue the top element is dequeued
+and the connection will start to work on it. If the work queue is
+empty, the connection is pushed on the idle connection stack where
+it will either get another work unit, or alternatively, if it sits there
+long enough, it will be shut down and released.
+
+
+=cut
+sub ServerToIdle {
+ my $Socket = shift; # Get the socket.
+
+ &Debug(1, "Server to idle");
+
+ # In this iteration, just put it on the idle queue.
+
+ $IdleConnections->push($Socket);
+}
+=pod
+=head2 LondReadable
+This function is called whenever a lond connection
+is readable. The action is state dependent:
+
+=head3 State = Initialized
+ We''re waiting for the challenge, this is a no-op until the
+state changes.
+=head3 State=Challenged
+ The challenge has arrived we need to transition to Writable.
+The connection must echo the challenge back.
+=head3 State=ChallengeReplied
+ The challenge has been replied to. The we are receiveing the
+'ok' from the partner.
+=head3 State=RequestingKey
+ The ok has been received and we need to send the request for
+an encryption key. Transition to writable for that.
+=head3 State=ReceivingKey
+ The the key has been requested, now we are reading the new key.
+=head3 State=Idle
+ The encryption key has been negotiated or we have finished
+reading data from the a transaction. If the callback data has
+a client as well as the socket iformation, then we are
+doing a transaction and the data received is relayed to the client
+before the socket is put on the idle list.
+=head3 State=SendingRequest
+ I do not think this state can be received here, but if it is,
+the appropriate thing to do is to transition to writable, and send
+the request.
+=head3 State=ReceivingReply
+ We finished sending the request to the server and now transition
+to readable to receive the reply.
+
+The parameter to this function are:
+The event. Implicit in this is the watcher and its data. The data
+contains at least the lond connection object and, if a
+transaction is in progress, the socket attached to the local client.
+
+
+=cut
+sub LondReadable {
+ my $Event = shift;
+ my $Watcher = $Event->w;
+ my @data = $Watcher->data;
+ my $Socket = $data[0];
+ my $client = undef;
+
+ if ($data == 2) {
+ $client = $data [1]; # There may be a client UNIX socket.
+ }
+ my $State = $Socket->GetState(); # All action depends on the state.
+
+ &Debug(4,"LondReadable called state = ".$State);
+ $Socket->Dump();
+ if($Socket->Readable() != 0) {
+ # bad return from socket read.
+ }
+
+ $State = $Socket->GetState(); # Update in case of transition.
+ &Debug(5, "After read, state is ".$State);
+
+ if($State eq "Initialized") {
+
+
+ } elsif ($State eq "ChallengeReceived") {
+ # The challenge must be echoed back; The state machine
+ # in the connection takes care of setting that up. Just
+ # need to transition to writable:
+
+ $Watcher->poll("w");
+ $Watcher->cb(\&LondWritable);
+
+ } elsif ($State eq "ChallengeReplied") {
+
+
+ } elsif ($State eq "RequestingKey") {
+ # The ok was received. Now we need to request the key
+ # That requires us to be writable:
+
+ $Watcher->poll("w");
+ $Watcher->cb(\&LondWritable);
+
+ } elsif ($State eq "ReceivingKey") {
+
+ } elsif ($State eq "Idle") {
+ # If necessary, complete a transaction and then go into the
+ # idle queue.
+ if($client) {
+ CompleteTransaction($Socket, $client);
+ }
+ $Watcher->cancel();
+ ServerToIdle($Socket); # Next work unit or idle.
+ } elsif ($State eq "SendingRequest") {
+ # We need to be writable for this and probably don't belong
+ # here inthe first place.
+
+ Deubg(5, "SendingRequest state encountered in readable");
+ $Watcher->poll("w");
+ $Watcher->cb(\&LondWritable);
+
+ } elsif ($State eq "ReceivingReply") {
+
+
+ } else {
+ # Invalid state.
+ Debug(4, "Invalid state in LondReadable");
+ }
+}
=pod
=head2 LondWritable
-This function is called whenver a lond connection
+This function is called whenever a lond connection
becomes writable while there is a writeable monitoring
event. The action taken is very state dependent:
=head3 State = Connected
@@ -136,6 +267,10 @@
my $State = $Socket->GetState();
+
+ &Debug(4,"LondWritable State = ".$State."\n");
+ $Socket->Dump();
+
if ($State eq "Connected") {
# "init" is being sent...
@@ -148,15 +283,58 @@
# Now that init was sent, we switch
# to watching for readability:
- $Watcher->poll = "r";
- $Watcher->callback = LondReadable;
+ $Watcher->poll("r");
+ $Watcher->cb(\&LondReadable);
} 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) {
+ # Write of the next chunk resulted in an error.
+ }
+
} elsif ($State eq "ChallengeReplied") {
+ # The echo was sent back, so we switch
+ # to watching readability.
+
+ $Watcher->poll("r");
+ $Watcher->cb(\&LondReadable);
+
} 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.
+ }
+
} elsif ($State eq "ReceivingKey") {
+ # Now we need to wait for the key
+ # to come back from the peer:
+
+ $Watcher->poll("r");
+ $Watcher->cb(\&LondReadable);
+
} elsif ($State eq "SendingRequest") {
+ # At this time we are sending a request to the
+ # peer... write the next chunk:
+
+ if($Socket->Writable() != 0) {
+ # Write resulted in an error.
+
+ }
+
} elsif ($State eq "ReceivingReply") {
+ # The send has completed. Wait for the
+ # data to come in for a reply.
+
+ $Watcher->poll("r");
+ $Watcher->cb(\&LondReadable);
+
} else {
# Control only passes here on an error:
# the socket state does not match any
@@ -177,22 +355,34 @@
it will dequeue an entry and start off on it.
=cut
sub MakeLondConnection {
- Debug(4,"MakeLondConnection");
+ Debug(4,"MakeLondConnection to ".GetServerHost()." on port "
+ .GetServerPort());
- my $Connection = LondConnection::new(GetServerHost(),
- GetServerPort());
+ my $Connection = LondConnection->new(&GetServerHost(),
+ &GetServerPort());
+ if($Connection == undef) { # Needs to be more robust later.
+ die "Failed to make a connection!!".$!."\n";
+
+ }
# The connection needs to have writability
# monitored in order to send the init sequence
# that starts the whole authentication/key
# exchange underway.
#
+ my $Socket = $Connection->GetSocket();
+ if($Socket == undef) {
+ die "did not get a socket from the connection";
+ } else {
+ &Debug(4,"MakeLondConnection got socket: ".$Socket);
+ }
- $event = Event::io->new(fd => $Connection->Getocket(),
- poll => "w",
- callback => &LondWritable,
- data => ($Lond, undef));
- %ActiveConnections{$Lond} = $event;
+ $event = Event->io(fd => $Socket,
+ poll => 'w',
+ cb => \&LondWritable,
+ data => ($Connection, undef),
+ desc => 'Connection to lond server');
+ $ActiveConnections{$Lond} = $event;
@@ -222,7 +412,7 @@
poll => "w",
callback=> &LondWritable,
data => ($Lond, $Client));
- %ActiveConnections{$Lond} = $event;
+ $ActiveConnections{$Lond} = $event;
}
=pod
@@ -245,7 +435,7 @@
my $LondSocket = $IdleConnections->pop();
if(!defined $LondSocket) { # Need to queue request.
- $WorkQueue->enqueue(($requestSocket $requestData));
+ $WorkQueue->enqueue(($requestSocket, $requestData));
if($ConnectionCount < $MaxConneciontCount) {
MakeLondConnection();
}
@@ -318,7 +508,7 @@
=cut
sub GetLoncSocketPath {
- return "/home/foxr/test/londtest";
+ return "/home/foxr/londtest";
}
=pod GetServerHost
@@ -367,6 +557,10 @@
SetupLoncListener();
$Event::Debuglevel = $DebugLevel;
+
+# Setup the initial server connection:
+
+&MakeLondConnection();
my $ret = Event::loop(); # Start the main event loop.
--foxr1048377892--