[LON-CAPA-cvs] cvs: newloncapa / loncnew
foxr
lon-capa-cvs@mail.lon-capa.org
Tue, 01 Apr 2003 23:22:02 -0000
This is a MIME encoded message
--foxr1049239322
Content-Type: text/plain
foxr Tue Apr 1 18:22:02 2003 EDT
Modified files:
/newloncapa loncnew
Log:
Get single client unencrypted traffic working
--foxr1049239322
Content-Type: text/plain
Content-Disposition: attachment; filename="foxr-20030401182202.txt"
Index: newloncapa/loncnew
diff -u newloncapa/loncnew:1.3 newloncapa/loncnew:1.4
--- newloncapa/loncnew:1.3 Sat Mar 22 19:04:51 2003
+++ newloncapa/loncnew Tue Apr 1 18:22:01 2003
@@ -6,7 +6,7 @@
# - Setup basic event loop. (done)
# - Add timer dispatch. (done)
# - Add ability to accept lonc UNIX domain sockets. (done)
-# - Add ability to create/negotiate lond connections.
+# - Add ability to create/negotiate lond connections (done).
# - Add general logic for dispatching requests and timeouts.
# - Add support for the lonc/lond requests.
# - Add logging/status monitoring.
@@ -28,20 +28,49 @@
use Stack;
use LondConnection;
+print "Loncnew starting\n";
+
#
# The stack below is a cache of a idle connections.
#
my $IdleConnections = Stack->new();
my %ActiveConnections;
+my %ActiveTransactions;
+
my $WorkQueue = Queue->new(); # Queue of pending transactions.
+my $ClientQueue = Queue->new(); # Queue of clients causing xactinos.
my $ConnectionCount = 0;
my $MaxConnectionCount = 5; # Will get from config later.
+my $ClientConnection = 0; # Uniquifier for client events.
$DebugLevel = 10;
+$IdleTimeout= 3600; # Wait an hour before pruning connections.
-
+#
+=pod
+=head 2 GetPeerName
+ Returns the name of the host that a socket object is connected
+ to.
+=cut
+
+sub GetPeername {
+ my $connection = shift;
+ my $AdrFamily = shift;
+ my $peer = $connection->peername();
+ my $peerport;
+ my $peerip;
+ if($AdrFamily == AF_INET) {
+ ($peerport, $peerip) = sockaddr_in($peer);
+ my $peername = gethostbyaddr($iaddr, $AdrFamily);
+ return $peername;
+ } elsif ($AdrFamily == AF_UNIX) {
+ my $peerfile;
+ ($peerfile) = sockaddr_un($peer);
+ return $peerfile;
+ }
+}
#----------------------------- Timer management ------------------------
=pod
=head2 Debug
@@ -94,11 +123,123 @@
&Debug(1, "Server to idle");
- # In this iteration, just put it on the idle queue.
+ # If there's work to do, start the transaction:
- $IdleConnections->push($Socket);
+ $reqdata = $WorkQueue->dequeue();
+ Debug(9, "Queue gave request data: ".$reqdata);
+ unless($reqdata eq undef) {
+ my $unixSocket = $ClientQueue->dequeue();
+ &Debug(3, "Starting new work request");
+ &Debug(9, "Request: ".$reqdata);
+
+ &StartRequest($Socket, $unixSocket, $reqdata);
+ } else {
+
+ # There's no work waiting, so push the server to idle list.
+ &Debug(3, "No new work requests, server connection going idle");
+ delete($ActiveTransactions{$Socket});
+ $IdleConnections->push($Socket);
+ }
}
=pod
+=head2 ClientWritable
+ Event callback for when a client socket is writable.
+ This callback is established when a transaction reponse is
+ avaiable from lond. The response is forwarded to the unix socket
+ as it becomes writable in this sub.
+Parameters:
+
+=item Event - The event that has been triggered. Event->w->data is
+ the data and Event->w->fd is the socket to write.
+
+=cut
+sub ClientWritable {
+ my $Event = shift;
+ my $Watcher = $Event->w;
+ my $Data = $Watcher->data;
+ my $Socket = $Watcher->fd;
+
+ # Try to send the data:
+
+ &Debug(1, "ClientWritable writing".$Data);
+ &Debug(9, "Socket is: ".$Socket);
+
+ my $result = $Socket->send($Data, 0);
+
+ # $result undefined: the write failed.
+ # otherwise $result is the number of bytes written.
+ # Remove that preceding string from the data.
+ # If the resulting data is empty, destroy the watcher
+ # and set up a read event handler to accept the next
+ # request.
+
+ &Debug(9,"Send result is ".$result." Defined: ".defined($result));
+ if(defined($result)) {
+ &Debug(9, "send result was defined");
+ if($result == length($Data)) { # Entire string sent.
+ &Debug(9, "ClientWritable data all written");
+ $Watcher->cancel();
+ #
+ # Set up to read next request from socket:
+
+ Event->io(cb => \&ClientRequest,
+ poll => 'r',
+ desc => "Connection to lonc client",
+ data => "",
+ fd => $Socket);
+
+ } else { # Partial string sent.
+ $Watcher->data(substr($Data, $result));
+ }
+
+ } else { # Error of some sort...
+
+ # Some errnos are possible:
+ my $errno = $!;
+ if($errno == POSIX::EWOULDBLOCK ||
+ $errno == POSIX::EAGAIN ||
+ $errno == POSIX::EINTR) {
+ # No action taken?
+ } else { # Unanticipated errno.
+ &Debug(5,"ClientWritable error or peer shutdown");
+ $Watcher->cancel; # Stop the watcher.
+ $Socket->shutdown(2); # Kill connection
+ $Socket->close(); # Close the socket.
+ }
+
+ }
+}
+
+=pod
+=head2 CompleteTransaction
+ Called when the reply data has been received for a lond
+transaction. The reply data must now be sent to the
+ultimate client on the other end of the Unix socket. This is
+done by setting up a writable event for the socket with the
+data the reply data.
+Parameters:
+=item Socket - Socket on which the lond transaction occured. This
+ is a LondConnection. The data received is in the
+ TransactionReply member.
+=item Client - Unix domain socket open on the ultimate client.
+
+=cut
+sub CompleteTransaction {
+ &Debug(4,"Complete transaction");
+ my $Socket = shift;
+ my $Client = shift;
+
+ my $data = $Socket->GetReply(); # Data to send.
+
+ &Debug(8," Reply was: ".$data);
+ Event->io(fd => $Client,
+ poll => "w",
+ cb => \&ClientWritable,
+ data => $data);
+}
+
+
+=pod
=head2 LondReadable
This function is called whenever a lond connection
is readable. The action is state dependent:
@@ -141,13 +282,10 @@
sub LondReadable {
my $Event = shift;
my $Watcher = $Event->w;
- my @data = $Watcher->data;
- my $Socket = $data[0];
+ my $Socket = $Watcher->data;
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);
@@ -155,6 +293,7 @@
if($Socket->Readable() != 0) {
# bad return from socket read.
}
+ $Socket->Dump();
$State = $Socket->GetState(); # Update in case of transition.
&Debug(5, "After read, state is ".$State);
@@ -185,8 +324,10 @@
} elsif ($State eq "Idle") {
# If necessary, complete a transaction and then go into the
# idle queue.
- if($client) {
- CompleteTransaction($Socket, $client);
+ if(exists($ActiveTransactions{$Socket})) {
+ Debug(8,"Completing transaction!!");
+ CompleteTransaction($Socket,
+ $ActiveTransactions{$Socket});
}
$Watcher->cancel();
ServerToIdle($Socket); # Next work unit or idle.
@@ -261,14 +402,16 @@
my $Event = shift;
my $Watcher = $Event->w;
my @data = $Watcher->data;
+ Debug(4,"LondWritable State = ".$State." data has ".@data." elts.\n");
+
my $Socket = $data[0]; # I know there's at least a socket.
# Figure out what to do depending on the state of the socket:
+
my $State = $Socket->GetState();
- &Debug(4,"LondWritable State = ".$State."\n");
$Socket->Dump();
if ($State eq "Connected") {
@@ -331,7 +474,7 @@
} elsif ($State eq "ReceivingReply") {
# The send has completed. Wait for the
# data to come in for a reply.
-
+ Debug(8,"Writable sent request/receiving reply");
$Watcher->poll("r");
$Watcher->cb(\&LondReadable);
@@ -405,14 +548,20 @@
my $Client = shift;
my $Request = shift;
- Debug(4, "StartRequest");
+ Debug(4, "StartRequest: ".$Request);
+
+ my $Socket = $Lond->GetSocket();
+ $ActiveTransactions{$Lond} = $Client; # Socket to relay to client.
+
$Lond->InitiateTransaction($Request);
- $event = Event::io->new(fd => $Lond->GetSocket(),
- poll => "w",
- callback=> &LondWritable,
- data => ($Lond, $Client));
+ $event = Event->io(fd => $Lond->GetSocket(),
+ poll => "w",
+ cb => \&LondWritable,
+ data => $Lond,
+ desc => "lond transaction connection");
$ActiveConnections{$Lond} = $event;
+ Debug(8," Start Request made watcher data with ".$event->data."\n");
}
=pod
@@ -433,13 +582,19 @@
my $requestSocket = shift;
my $requestData = shift;
+ Debug(4,"QueueTransaction: ".$requestData);
+
my $LondSocket = $IdleConnections->pop();
if(!defined $LondSocket) { # Need to queue request.
- $WorkQueue->enqueue(($requestSocket, $requestData));
+ Debug(4,"Must queue...");
+ $ClientQueue->enqueue($requestSocket);
+ $WorkQueue->enqueue($requestData);
if($ConnectionCount < $MaxConneciontCount) {
+ Debug(4,"Starting additional lond connection");
MakeLondConnection();
}
} else { # Can start the request:
+ Debug(4,"Can start...");
StartRequest($LondSocket, $requestSocket, $requestData);
}
}
@@ -458,20 +613,24 @@
my $watcher = $event->w;
my $socket = $watcher->fd;
my $data = $watcher->data;
-
my $thisread;
+ Debug(9, " Watcher named: ".$watcher->desc);
+
my $rv = $socket->recv($thisread, POSIX::BUFSIZ, 0);
+ Debug(8, "rcv: data length = ".length($thisread)
+ ." read =".$thisread);
unless (defined $rv && length($thisread)) {
# Likely eof on socket.
Debug(2,"Socket closed");
close($socket);
$watcher->cancel();
}
+ Debug(8,"Data: ".$data." this read: ".$thisread);
$data = $data.$thisread; # Append new data.
- $watcher->data = $data;
- if($data =~ s/(.*\n)//) { # Request entirely read.
- Debug(2, "Complete transaction received".$data);
+ $watcher->data($data);
+ if($data =~ /(.*\n)/) { # Request entirely read.
+ Debug(2, "Complete transaction received: ".$data);
QueueTransaction($socket, $data);
$watcher->cancel(); # Done looking for input data.
}
@@ -493,14 +652,19 @@
my $watcher = $event->w;
my $socket = $watcher->fd; # Get the event' socket.
my $connection = $socket->accept(); # Accept the client connection.
+ Debug(3,"Connection request accepted from "
+ .GetPeername($connection, AF_UNIX));
- Debug(3,"Connection request accepted from ".$connection->peername());
+ my $description = sprintf("Connection to lonc client %d",
+ $ClientConnection);
+ Debug(4, "Creating event named: ".$description);
Event->io(cb => \&ClientRequest,
poll => 'r',
- desc => 'Connection to lonc client '.$connection->peername(),
+ desc => $description,
data => "",
fd => $connection);
+ $ClientConnection++;
}
=pod GetLoncSocketPath
Returns the name of the UNIX socket on which to listen for client
@@ -552,16 +716,19 @@
# the timer then dive into the main event loop.
#
-
+print "Loncnew\n";
SetupTimer();
+
SetupLoncListener();
$Event::Debuglevel = $DebugLevel;
+Debug(9, "Making lond connection");
# Setup the initial server connection:
&MakeLondConnection();
+Debug(9,"Entering event loop");
my $ret = Event::loop(); # Start the main event loop.
@@ -588,6 +755,10 @@
=item ActiveConnections - A hash of lond connections that have transactions
in process that are available to be timed out.
+
+=item ActiveTransactions - A hash indexed by lond connections that
+ contain the client reply socket for each connection that has an active
+ transaction on it.
=item IdleConnections - A hash of lond connections that have no work
to do. These connections can be closed if they are idle for a long
--foxr1049239322--