[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--