Diff for /loncom/LondConnection.pm between versions 1.1 and 1.4

version 1.1, 2003/04/18 02:39:57 version 1.4, 2003/06/11 02:04:35
Line 1 Line 1
 #  
 #   This module defines and implements a class that represents  #   This module defines and implements a class that represents
 #   a connection to a lond daemon.   #   a connection to a lond daemon.
   #
   # $Id$
   #
   # Copyright Michigan State University Board of Trustees
   #
   # This file is part of the LearningOnline Network with CAPA (LON-CAPA).
   #
   # LON-CAPA is free software; you can redistribute it and/or modify
   # it under the terms of the GNU General Public License as published by
   # the Free Software Foundation; either version 2 of the License, or
   # (at your option) any later version.
   #
   # LON-CAPA is distributed in the hope that it will be useful,
   # but WITHOUT ANY WARRANTY; without even the implied warranty of
   # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   # GNU General Public License for more details.
   #
   # You should have received a copy of the GNU General Public License
   # along with LON-CAPA; if not, write to the Free Software
   # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   #
   # /home/httpd/html/adm/gpl.txt
   #
   # http://www.lon-capa.org/
   #
 package LondConnection;  package LondConnection;
   
 use IO::Socket;  use IO::Socket;
Line 35  sub Debug { Line 59  sub Debug {
  print($message."\n");   print($message."\n");
     }      }
 }  }
 =pod   
    Dump the internal state of the object: For debugging purposes.  =pod
   
   =head2 Dump
   
   Dump the internal state of the object: For debugging purposes.
   
 =cut  =cut
   
 sub Dump {  sub Dump {
Line 49  sub Dump { Line 78  sub Dump {
 }  }
   
 =pod  =pod
   Local function to do a state transition.  If the state transition callback  
     is defined it is called with two parameters:  the self and the old state.  Local function to do a state transition.  If the state transition
   callback is defined it is called with two parameters: the self and the
   old state.
   
 =cut  =cut
   
 sub Transition {  sub Transition {
     my $self     = shift;      my $self     = shift;
     my $newstate = shift;      my $newstate = shift;
Line 63  sub Transition { Line 96  sub Transition {
     }      }
 }  }
   
   
 =pod  =pod
   Construct a new lond connection.  
   Parameters (besides the class name) include:  =head2 new
 =item hostname - host the remote lond is on.   
     This host is a host in the hosts.tab file  Construct a new lond connection.
 =item port     - port number the remote lond is listening on.  
   Parameters (besides the class name) include:
   
   =item hostname
   
   host the remote lond is on. This host is a host in the hosts.tab file
   
   =item port
   
    port number the remote lond is listening on.
   
 =cut  =cut
   
 sub new {  sub new {
     my $class    = shift; # class name.      my $class    = shift; # class name.
     my $Hostname = shift; # Name of host to connect to.      my $Hostname = shift; # Name of host to connect to.
Line 136  sub new { Line 181  sub new {
   
     return $self;      return $self;
 }  }
   
 =pod  =pod
    This member should be called when the Socket becomes readable.  
    Until the read completes,  action is state independet. Data are accepted  =head2 Readable
     into the TransactionReply until a newline character is received.  At that  
    time actionis state dependent:  This member should be called when the Socket becomes readable.  Until
 =item Connected: in this case we received challenge, the state changes  the read completes, action is state independet. Data are accepted into
     to ChallengeReceived, and we initiate a send with the challenge response.  the TransactionReply until a newline character is received.  At that
 =item ReceivingReply: In this case a reply has been received for a transaction,  time actionis state dependent:
     the state goes to Idle and we disable write and read notification.  
 =item ChallengeReeived: we just got what should be an ok\n and the  =item Connected
     connection can now handle transactions.  
   in this case we received challenge, the state changes to
   ChallengeReceived, and we initiate a send with the challenge response.
   
   =item ReceivingReply
   
   In this case a reply has been received for a transaction, the state
   goes to Idle and we disable write and read notification.
   
   =item ChallengeReeived
   
   we just got what should be an ok\n and the connection can now handle
   transactions.
   
 =cut  =cut
   
 sub Readable {  sub Readable {
     my $self    = shift;      my $self    = shift;
     my $socket  = $self->{Socket};      my $socket  = $self->{Socket};
Line 256  sub Readable { Line 315  sub Readable {
   
   
 =pod  =pod
   This member should be called when the Socket becomes writable.  
 The action is state independent. An attempt is made to drain the contents of  This member should be called when the Socket becomes writable.
 the TransactionRequest member.  Once this is drained, we mark the  object  
 as waiting for readability.  The action is state independent. An attempt is made to drain the
   contents of the TransactionRequest member.  Once this is drained, we
   mark the object as waiting for readability.
   
 Returns  0 if successful, or -1 if not.  Returns  0 if successful, or -1 if not.
     
 =cut  =cut
 sub Writable {  sub Writable {
     my $self     = shift; # Get reference to the object.      my $self     = shift; # Get reference to the object.
Line 314  sub Writable { Line 375  sub Writable {
   
 }  }
 =pod  =pod
   
   =head2 Tick
   
    Tick is called every time unit by the event framework.  It     Tick is called every time unit by the event framework.  It
    1. decrements the remaining timeout.  
    2. If the timeout is zero, calls TimedOut indicating that the   =item 1 decrements the remaining timeout.
       current operation timed out.  
   =item 2 If the timeout is zero, calls TimedOut indicating that the current operation timed out.
   
 =cut  =cut
           
Line 328  sub Tick { Line 393  sub Tick {
  $self->TimedOut();   $self->TimedOut();
     }      }
 }  }
   
 =pod  =pod
   TimedOut - called on a timeout.  If the timeout callback is defined,  
   it is called with $self as  its parameters.  
   
 =cut    =head2 TimedOut
   
   called on a timeout.  If the timeout callback is defined, it is called
   with $self as its parameters.
   
   =cut
   
 sub TimedOut  {  sub TimedOut  {
   
     my $self = shift;      my $self = shift;
Line 342  sub TimedOut  { Line 412  sub TimedOut  {
  &$callback(@args);   &$callback(@args);
     }      }
 }  }
   
 =pod  =pod
     Called to initiate a transaction.  A transaction can only be initiated  
     when the object is idle... otherwise an error is returned.  =head2 InitiateTransaction
     A transaction consists of a request to the server that will have a reply.  
     This member sets the request data in the TransactionRequest member,  Called to initiate a transaction.  A transaction can only be initiated
     makes the state SendingRequest and sets the data to allow a timout,  when the object is idle... otherwise an error is returned.  A
     and to request writability notification.    transaction consists of a request to the server that will have a
   reply.  This member sets the request data in the TransactionRequest
   member, makes the state SendingRequest and sets the data to allow a
   timout, and to request writability notification.
   
 =cut  =cut
   
 sub InitiateTransaction {  sub InitiateTransaction {
     my $self   = shift;      my $self   = shift;
     my $data   = shift;      my $data   = shift;
   
       Debug(1, "initiating transaction: ".$data);
     if($self->{State} ne "Idle") {      if($self->{State} ne "Idle") {
    Debug(0," .. but not idle here\n");
  return -1; # Error indicator.   return -1; # Error indicator.
     }      }
     # if the transaction is to be encrypted encrypt the data:      # if the transaction is to be encrypted encrypt the data:
Line 376  sub InitiateTransaction { Line 454  sub InitiateTransaction {
   
   
 =pod  =pod
     Sets a callback for state transitions.  Returns a reference to any  
     prior established callback, or undef if there was none:  =head2 SetStateTransitionCallback
   
   Sets a callback for state transitions.  Returns a reference to any
   prior established callback, or undef if there was none:
   
 =cut  =cut
   
 sub SetStateTransitionCallback {  sub SetStateTransitionCallback {
     my $self        = shift;      my $self        = shift;
     my $oldCallback = $self->{TransitionCallback};      my $oldCallback = $self->{TransitionCallback};
     $self->{TransitionCallback} = shift;      $self->{TransitionCallback} = shift;
     return $oldCallback;      return $oldCallback;
 }  }
   
 =pod  =pod
    Sets the timeout callback.  Returns a reference to any prior established   
    callback or undef if there was none.  =head2 SetTimeoutCallback
   
   Sets the timeout callback.  Returns a reference to any prior
   established callback or undef if there was none.
   
 =cut  =cut
   
 sub SetTimeoutCallback {  sub SetTimeoutCallback {
     my $self                 = shift;      my $self                 = shift;
     my $callback             = shift;      my $callback             = shift;
Line 398  sub SetTimeoutCallback { Line 487  sub SetTimeoutCallback {
 }  }
   
 =pod  =pod
    GetState - selector for the object state.  
   =head2 GetState
   
   selector for the object state.
   
 =cut  =cut
   
 sub GetState {  sub GetState {
     my $self = shift;      my $self = shift;
     return $self->{State};      return $self->{State};
 }  }
   
 =pod  =pod
    GetSocket - selector for the object socket.  
   =head2 GetSocket
   
   selector for the object socket.
   
 =cut  =cut
   
 sub GetSocket {  sub GetSocket {
     my $self  = shift;      my $self  = shift;
     return $self->{Socket};      return $self->{Socket};
 }  }
   
 =pod  =pod
    Return the state of the flag that indicates the object wants to be  
     called when readable.  =head2 WantReadable
   
   Return the state of the flag that indicates the object wants to be
   called when readable.
   
 =cut  =cut
   
 sub WantReadable {  sub WantReadable {
     my   $self = shift;      my   $self = shift;
   
     return $self->{InformReadable};      return $self->{InformReadable};
 }  }
   
 =pod  =pod
    Return the state of the flag that indicates the object wants write  
     notification.  =head2 WantWritable
   
   Return the state of the flag that indicates the object wants write
   notification.
   
 =cut  =cut
   
 sub WantWritable {  sub WantWritable {
     my $self = shift;      my $self = shift;
     return $self->{InformWritable};      return $self->{InformWritable};
 }  }
   
 =pod  =pod
   return the state of the flag that indicates the object wants to be informed  
    of timeouts.  =head2 WantTimeout
   
   return the state of the flag that indicates the object wants to be
   informed of timeouts.
   
 =cut  =cut
   
 sub WantTimeout {  sub WantTimeout {
     my $self = shift;      my $self = shift;
     return $self->{Timeoutable};      return $self->{Timeoutable};
 }  }
   
 =pod  =pod
   Returns the reply from the last transaction.  
   =head2 GetReply
   
   Returns the reply from the last transaction.
   
 =cut  =cut
   
 sub GetReply {  sub GetReply {
     my $self = shift;      my $self = shift;
     return $self->{TransactionReply};      return $self->{TransactionReply};
 }  }
   
 =pod  =pod
   Returns the encrypted version of the command string.  
   The command input string is of the form:  =head2 Encrypt
   
   Returns the encrypted version of the command string.
   
   The command input string is of the form:
   
   encrypt:command    encrypt:command
   The output string can be directly sent to lond as it's of the form:  
   The output string can be directly sent to lond as it is of the form:
   
   enc:length:<encodedrequest>    enc:length:<encodedrequest>
 '  
 =cut  =cut
   
 sub Encrypt {  sub Encrypt {
     my $self    = shift; # Reference to the object.      my $self    = shift; # Reference to the object.
     my $request = shift;        # Text to send.      my $request = shift;        # Text to send.
Line 485  sub Encrypt { Line 616  sub Encrypt {
           
           
 }  }
 =pod   
     Decrypt  =pod
     Decrypt a response from the server.  The response is in the form:  
   enc:<length>:<encrypted data>  =head2 Decrypt
   
   Decrypt a response from the server.  The response is in the form:
   
    enc:<length>:<encrypted data>
   
 =cut  =cut
   
 sub Decrypt {  sub Decrypt {
     my $self      = shift; # Recover reference to object      my $self      = shift; # Recover reference to object
     my $encrypted = shift; # This is the encrypted data.      my $encrypted = shift; # This is the encrypted data.
Line 521  sub Decrypt { Line 658  sub Decrypt {
 }  }
   
 =pod  =pod
 =head GetHostIterator  
   =head2 GetHostIterator
   
 Returns a hash iterator to the host information.  Each get from   Returns a hash iterator to the host information.  Each get from 
 this iterator returns a reference to an array that contains   this iterator returns a reference to an array that contains 
 information read from the hosts configuration file.  Array elements  information read from the hosts configuration file.  Array elements
 are used as follows:  are used as follows:
   
 [0]   - LonCapa host name.   [0]   - LonCapa host name.
 [1]   - LonCapa domain name.   [1]   - LonCapa domain name.
 [2]   - Loncapa role (e.g. library or access).   [2]   - Loncapa role (e.g. library or access).
 [3]   - DNS name server hostname.   [3]   - DNS name server hostname.
 [4]   - IP address (result of e.g. nslooup [3]).   [4]   - IP address (result of e.g. nslooup [3]).
 [5]   - Maximum connection count.   [5]   - Maximum connection count.
 [6]   - Idle timeout for reducing connection count.   [6]   - Idle timeout for reducing connection count.
 [7]   - Minimum connection count.   [7]   - Minimum connection count.
   
   
 =cut  =cut
   
 sub GetHostIterator {  sub GetHostIterator {
   
     return HashIterator->new(\%hostshash);          return HashIterator->new(\%hostshash);    
Line 547  sub GetHostIterator { Line 685  sub GetHostIterator {
 1;  1;
   
 =pod  =pod
   
 =head1 Theory  =head1 Theory
    The lond object is a state machine.  It lives through the following states:  
   
 =item Connected: a TCP connection has been formed, but the passkey has not yet  The lond object is a state machine.  It lives through the following states:
     been negotiated.  
 =item Initialized: "init" sent.  =item Connected:
 =item ChallengeReceived: lond sent its challenge to us.  
 =item ChallengeReplied:  We replied to lond's challenge waiting for lond's ok.  a TCP connection has been formed, but the passkey has not yet been
 =item RequestingKey:    We are requesting an encryption key.  negotiated.
 =item ReceivingKey:     We are receiving an encryption key.  
 =item Idle:  Connection was negotiated but no requests are active.  =item Initialized:
 =item SendingRequest: A request is being sent to the peer.  
 =item ReceivingReply: Waiting for an entire reply from the peer.  "init" sent.
 =item Disconnected:   For whatever reason, the connection was dropped.  
   =item ChallengeReceived:
   When we need to be writing data, we have a writable  
 event. When we need to be reading data, a readable event established.  lond sent its challenge to us.
 Events dispatch through the class functions Readable and Writable, and the  
 watcher contains a reference to the associated object to allow object context  =item ChallengeReplied:
 to be reached.  
   We replied to lond's challenge waiting for lond's ok.
   
   =item RequestingKey:
   
   We are requesting an encryption key.
   
   =item ReceivingKey:
   
   We are receiving an encryption key.
   
   =item Idle:
   
   Connection was negotiated but no requests are active.
   
   =item SendingRequest:
   
   A request is being sent to the peer.
   
   =item ReceivingReply:
   
   Waiting for an entire reply from the peer.
   
   =item Disconnected:
   
   For whatever reason, the connection was dropped.
   
   When we need to be writing data, we have a writable event. When we
   need to be reading data, a readable event established.  Events
   dispatch through the class functions Readable and Writable, and the
   watcher contains a reference to the associated object to allow object
   context to be reached.
   
 =head2 Member data.  =head2 Member data.
 Host   - Host socket is connected to.  
 Port   - The port the remote lond is listening on.  
 Socket - Socket open on the connection.  
 State  - The current state.  
 TransactionRequest - The request being transmitted.  
 TransactionReply   - The reply being received from the transaction.  
 InformReadable     - True if we want to be called when socket is readable.  
 InformWritable     - True if we want to be informed if the socket is writable.  
 Timeoutable        - True if the current operation is allowed to timeout.  
 TimeoutValue       - Number of seconds in the timeout.  
 TimeoutRemaining   - Number of seconds left in the timeout.  
 CipherKey          - The key that was negotiated with the peer.  
 Cipher             - The cipher obtained via the key.  
   
   =item Host
   
   Host socket is connected to.
   
   =item Port
   
   The port the remote lond is listening on.
   
   =item Socket
   
   Socket open on the connection.
   
   =item State
   
   The current state.
   
   =item TransactionRequest
   
   The request being transmitted.
   
   =item TransactionReply
   
   The reply being received from the transaction.
   
   =item InformReadable
   
   True if we want to be called when socket is readable.
   
   =item InformWritable
   
   True if we want to be informed if the socket is writable.
   
   =item Timeoutable
   
   True if the current operation is allowed to timeout.
   
   =item TimeoutValue
   
   Number of seconds in the timeout.
   
   =item TimeoutRemaining
   
   Number of seconds left in the timeout.
   
   =item CipherKey
   
   The key that was negotiated with the peer.
   
   =item Cipher
   
   The cipher obtained via the key.
   
   
 =head2 The following are callback like members:  =head2 The following are callback like members:
 =item Tick: Called in response to a timer tick. Used to managed timeouts etc.  
 =item Readable: Called when the socket becomes readable.  =item Tick:
 =item Writable: Called when the socket becomes writable.  
 =item TimedOut: Called when a timed operation timed out.  Called in response to a timer tick. Used to managed timeouts etc.
   
   =item Readable:
   
   Called when the socket becomes readable.
   
   =item Writable:
   
   Called when the socket becomes writable.
   
   =item TimedOut:
   
   Called when a timed operation timed out.
   
   
 =head2 The following are operational member functions.  =head2 The following are operational member functions.
 =item InitiateTransaction: Called to initiate a new transaction  
 =item SetStateTransitionCallback: Called to establish a function that is called  =item InitiateTransaction:
     whenever the object goes through a state transition.  This is used by  
     The client to manage the work flow for the object.  Called to initiate a new transaction
 =item SetTimeoutCallback -Set a function to be called when a transaction times  
     out.  The function will be called with the object as its sole parameter.  =item SetStateTransitionCallback:
 =item Encrypt - Encrypts a block of text according to the cipher negotiated  
        with the peer (assumes the text is a command).  Called to establish a function that is called whenever the object goes
 =item Decrypt - Decrypts a block of text according to the cipher negotiated  through a state transition.  This is used by The client to manage the
        with the peer (assumes the block was a reply.  work flow for the object.
   
   =item SetTimeoutCallback:
   
   Set a function to be called when a transaction times out.  The
   function will be called with the object as its sole parameter.
   
   =item Encrypt:
   
   Encrypts a block of text according to the cipher negotiated with the
   peer (assumes the text is a command).
   
   =item Decrypt:
   
   Decrypts a block of text according to the cipher negotiated with the
   peer (assumes the block was a reply.
   
 =head2 The following are selector member functions:  =head2 The following are selector member functions:
   
 =item GetState: Returns the current state  =item GetState:
 =item GetSocket: Gets the socekt open on the connection to lond.  
 =item WantReadable: true if the current state requires a readable event.  Returns the current state
 =item WantWritable: true if the current state requires a writable event.  
 =item WantTimeout: true if the current state requires timeout support.  =item GetSocket:
 =item GetHostIterator: Returns an iterator into the host file hash.  
   Gets the socekt open on the connection to lond.
   
   =item WantReadable:
   
   true if the current state requires a readable event.
   
   =item WantWritable:
   
   true if the current state requires a writable event.
   
   =item WantTimeout:
   
   true if the current state requires timeout support.
   
   =item GetHostIterator:
   
   Returns an iterator into the host file hash.
   
 =cut  =cut

Removed from v.1.1  
changed lines
  Added in v.1.4


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>