version 1.18, 2003/10/28 11:55:58
|
version 1.25, 2003/11/04 11:52:06
|
Line 63 use lib ".";
|
Line 63 use lib ".";
|
use strict; # Because it's good practice. |
use strict; # Because it's good practice. |
use English; # Cause I like meaningful names. |
use English; # Cause I like meaningful names. |
use Getopt::Long; |
use Getopt::Long; |
use IO::Socket::UNIX; # To communicate with lonc. |
|
use LondConnection; |
use LondConnection; |
|
use IO::Poll qw(POLLRDNORM POLLWRNORM POLLIN POLLHUP POLLOUT); |
|
|
# File scoped variables: |
# File scoped variables: |
|
|
my %perlvar; # Perl variable defs from apache config. |
my %perlvar; # Perl variable defs from apache config. |
my %hostshash; # Host table as a host indexed hash. |
my %hostshash; # Host table as a host indexed hash. |
|
|
my $MyHost; # Host name to use as me. |
my $MyHost=""; # Host name to use as me. |
my $ForeignHostTab; # Name of foreign hosts table. |
my $ForeignHostTab=""; # Name of foreign hosts table. |
|
|
|
my $DefaultServerPort = 5663; # Default server port if standalone. |
|
my $ServerPort; # Port used to connect to lond. |
|
|
|
my $TransitionTimeout = 5; # Poll timeout in seconds. |
|
|
|
|
|
# LondConnection::SetDebug(10); |
|
|
|
|
# |
# |
# prints out utility's command usage info. |
# prints out utility's command usage info. |
Line 110 USAGE
|
Line 119 USAGE
|
|
|
|
|
} |
} |
|
|
|
# |
|
# Make a direct connection to the lond in 'host'. The port is |
|
# gotten from the global variable: ServerPort. |
|
# Returns: |
|
# The connection or undef if one could not be formed. |
|
# |
|
sub MakeLondConnection { |
|
my $host = shift; |
|
|
|
my $Connection = LondConnection->new($host, $ServerPort); |
|
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 |
|
# state machine that has to do with negotiating the startup |
|
# sequence with lond. The general strategy is to loop |
|
# until the connection state becomes idle or disconnected. |
|
# Disconnected indicates an error or rejection of the |
|
# connection at some point in the negotiation. |
|
# idle indicates a connection ready for a request. |
|
# The main loop consults the object to determine if it |
|
# wants to be writeable or readable, waits for that |
|
# condition on the socket (with timeout) and then issues |
|
# the appropriate LondConnection call. Note that |
|
# LondConnection is capable of doing everything necessary |
|
# to get to the initial idle state. |
|
# |
|
# |
|
# Parameters: |
|
# connection - A connection that has been created with |
|
# the remote lond. This connection should |
|
# be in the Connected state ready to send |
|
# the init sequence. |
|
# |
|
sub NegotiateStartup { |
|
my $connection = shift; |
|
my $returnstatus = "ok"; # Optimistic!!. |
|
|
|
my $state = $connection->GetState; |
|
if($state ne "Connected") { |
|
print "Error: Initial lond connection state: $state should be Connected\n"; |
|
return "error"; |
|
} |
|
|
|
return SequenceStateMachine($connection, $TransitionTimeout); |
|
} |
# |
# |
# Lifted from lonnet.pm - and we need to figure out a way to get it back in. |
# Perform a transaction with the remote lond. |
# Performas a transaction with lond via the lonc proxy server. |
# Paramters: |
|
# connection - the connection object that represents |
|
# a LondConnection to the remote lond. |
|
# command - The request to send to the remote system. |
|
# Returns: |
|
# The 'reaction' of the lond to this command. |
|
# However if the connection to lond is lost during the transaction |
|
# or some other error occurs, the text "error:con_lost" is returned. |
|
# |
|
sub PerformTransaction { |
|
my $connection = shift; |
|
my $command = shift; |
|
my $retval; # What we'll returnl. |
|
|
|
|
|
# Set up the connection to do the transaction then |
|
# do the I/O until idle or error. |
|
# |
|
$connection->InitiateTransaction($command); |
|
|
|
my $status = SequenceStateMachine($connection, $TransitionTimeout); |
|
if($status eq "ok") { |
|
$retval = $connection->GetReply; |
|
} else { |
|
$retval = $status; |
|
} |
|
|
|
return $retval; |
|
} |
|
# |
|
# Performs a transaction direct to a remote lond. |
# Parameter: |
# Parameter: |
# cmd - The text of the request. |
# cmd - The text of the request. |
# host - The host to which the request ultimately goes. |
# host - The host to which the request ultimately goes. |
Line 121 USAGE
|
Line 263 USAGE
|
# lond/lonc etc. |
# lond/lonc etc. |
# |
# |
sub subreply { |
sub subreply { |
my ($cmd,$server)=@_; |
my $cmd = shift; |
my $peerfile="$perlvar{'lonSockDir'}/$server"; |
my $host = shift; |
my $client=IO::Socket::UNIX->new(Peer =>"$peerfile", |
|
Type => SOCK_STREAM, |
|
Timeout => 10) |
my $connection = MakeLondConnection($host); |
or return "con_lost"; |
if ($connection eq undef) { |
print $client "$cmd\n"; |
return "Connect Failed"; |
my $answer=<$client>; |
} |
if (!$answer) { $answer="con_lost"; } |
my $reply = NegotiateStartup($connection); |
chomp($answer); |
if($reply ne "ok") { |
return $answer; |
return "connection negotiation failed"; |
|
} |
|
my $reply = PerformTransaction($connection, $cmd); |
|
return $reply; |
|
|
|
|
|
# my ($cmd,$server)=@_; |
|
# my $peerfile="$perlvar{'lonSockDir'}/$server"; |
|
# my $client=IO::Socket::UNIX->new(Peer =>"$peerfile", |
|
# Type => SOCK_STREAM, |
|
# Timeout => 10) |
|
# or return "con_lost"; |
|
# print $client "$cmd\n"; |
|
# my $answer=<$client>; |
|
# if (!$answer) { $answer="con_lost"; } |
|
# chomp($answer); |
|
# return $answer; |
} |
} |
# >>> BUGBUG <<< |
# >>> BUGBUG <<< |
# |
# |
Line 227 sub ParseArgs {
|
Line 385 sub ParseArgs {
|
return @result; |
return @result; |
} |
} |
# |
# |
# Read the loncapa configuration stuff. |
# Read the loncapa configuration stuff. If ForeignHostTab is empty, |
|
# assume we are part of a loncapa cluster and read the hosts.tab |
|
# file from the config directory. Otherwise, ForeignHossTab |
|
# is the name of an alternate configuration file to read in |
|
# standalone mode. |
# |
# |
sub ReadConfig { |
sub ReadConfig { |
my $perlvarref = LondConnection::read_conf('loncapa.conf'); |
|
%perlvar = %{$perlvarref}; |
|
my $hoststab = LondConnection::read_hosts( |
|
"$perlvar{'lonTabDir'}/hosts.tab"); |
|
%hostshash = %{$hoststab}; |
|
|
|
|
if($ForeignHostTab eq "") { |
|
my $perlvarref = LondConnection::read_conf('loncapa.conf'); |
|
%perlvar = %{$perlvarref}; |
|
my $hoststab = LondConnection::read_hosts( |
|
"$perlvar{'lonTabDir'}/hosts.tab"); |
|
%hostshash = %{$hoststab}; |
|
$MyHost = $perlvar{lonHostID}; # Set hostname from vars. |
|
$ServerPort = $perlvar{londPort}; |
|
} else { |
|
|
|
LondConnection::ReadForeignConfig($MyHost, $ForeignHostTab); |
|
my $hoststab = LondConnection::read_hosts($ForeignHostTab); # we need to know too. |
|
%hostshash = %{$hoststab}; |
|
$ServerPort = $DefaultServerPort; |
|
} |
|
|
} |
} |
# |
# |
# Determine if the target host is valid. |
# Determine if the target host is valid. |
Line 388 sub ReinitProcess {
|
Line 561 sub ReinitProcess {
|
} |
} |
#--------------------------- Entry point: -------------------------- |
#--------------------------- Entry point: -------------------------- |
|
|
ReadConfig; # Read the configuration info (incl.hosts). |
|
|
|
|
|
# Parse the parameters |
# Parse the parameters |
Line 408 if ($EUID != 0) {
|
Line 580 if ($EUID != 0) {
|
die "ENOPRIV - No privilege for requested operation" |
die "ENOPRIV - No privilege for requested operation" |
} |
} |
|
|
|
# |
|
# Read the configuration file. |
|
# |
|
|
|
ReadConfig; # Read the configuration info (incl.hosts). |
|
|
# Based on the operation requested invoke the appropriate function: |
# Based on the operation requested invoke the appropriate function: |
|
|