File:  [LON-CAPA] / loncom / lonnet / perl / lonnet.pm
Revision 1.1: download - view: text, annotated - select for diffs
Wed Oct 13 17:48:51 1999 UTC (24 years, 9 months ago) by albertel
Branches: MAIN
CVS tags: HEAD
Initial revision

    1: # The LearningOnline Network
    2: # TCP networking package
    3: # 6/1/99,6/2,6/10,6/11,6/12,6/14,6/26,6/28,6/29,6/30,
    4: # 7/1,7/2,7/9,7/10,7/12,7/14,7/15,7/19 Gerd Kortemeyer
    5: 
    6: package Apache::lonnet;
    7: 
    8: use strict;
    9: use Apache::File;
   10: use vars qw(%perlvar %hostname %homecache %spareid %hostdom %libserv $readit);
   11: use IO::Socket;
   12: 
   13: # --------------------------------------------------------------------- Logging
   14: 
   15: sub logthis {
   16:     my $message=shift;
   17:     my $execdir=$perlvar{'lonDaemons'};
   18:     my $now=time;
   19:     my $local=localtime($now);
   20:     my $fh=Apache::File->new(">>$execdir/logs/lonnet.log");
   21:     print $fh "$local ($$): $message\n";
   22:     return 1;
   23: }
   24: 
   25: sub logperm {
   26:     my $message=shift;
   27:     my $execdir=$perlvar{'lonDaemons'};
   28:     my $now=time;
   29:     my $local=localtime($now);
   30:     my $fh=Apache::File->new(">>$execdir/logs/lonnet.perm.log");
   31:     print $fh "$now:$message:$local\n";
   32:     return 1;
   33: }
   34: 
   35: # -------------------------------------------------- Non-critical communication
   36: sub subreply {
   37:     my ($cmd,$server)=@_;
   38:     my $peerfile="$perlvar{'lonSockDir'}/$server";
   39:     my $client=IO::Socket::UNIX->new(Peer    =>"$peerfile",
   40:                                      Type    => SOCK_STREAM,
   41:                                      Timeout => 10)
   42:        or return "con_lost";
   43:     print $client "$cmd\n";
   44:     my $answer=<$client>;
   45:     chomp($answer);
   46:     if (!$answer) { $answer="con_lost"; }
   47:     return $answer;
   48: }
   49: 
   50: sub reply {
   51:     my ($cmd,$server)=@_;
   52:     my $answer=subreply($cmd,$server);
   53:     if ($answer eq 'con_lost') { $answer=subreply($cmd,$server); }
   54:     return $answer;
   55: }
   56: 
   57: # ------------------------------------------------ Try to send delayed messages
   58: 
   59: sub senddelayed {
   60:     my $server=shift;
   61:     my $dfname;
   62:     my $path="$perlvar{'lonSockDir'}/delayed";
   63:     while ($dfname=<$path/*.$server>) {
   64:         my $wcmd;
   65:         {
   66:          my $dfh=Apache::File->new($dfname);
   67:          $wcmd=<$dfh>;
   68:         }
   69:         my ($server,$cmd)=split(/:/,$wcmd);
   70:         chomp($cmd);
   71:         my $answer=subreply($cmd,$server);
   72:         if ($answer ne 'con_lost') {
   73: 	    unlink("$dfname");
   74:             &logthis("Delayed $cmd to $server: $answer");
   75:             &logperm("S:$server:$cmd");
   76:         }        
   77:     }
   78: }
   79: 
   80: # ----------------------------------------------------------- Send USR1 to lonc
   81: 
   82: sub reconlonc {
   83:     my $peerfile=shift;
   84:     &logthis("Trying to reconnect for $peerfile");
   85:     my $loncfile="$perlvar{'lonDaemons'}/logs/lonc.pid";
   86:     if (my $fh=Apache::File->new("$loncfile")) {
   87: 	my $loncpid=<$fh>;
   88:         chomp($loncpid);
   89:         if (kill 0 => $loncpid) {
   90: 	    &logthis("lonc at pid $loncpid responding, sending USR1");
   91:             kill USR1 => $loncpid;
   92:             sleep 1;
   93:             if (-e "$peerfile") { return; }
   94:             &logthis("$peerfile still not there, give it another try");
   95:             sleep 5;
   96:             if (-e "$peerfile") { return; }
   97:             &logthis("$peerfile still not there, giving up");
   98:         } else {
   99: 	    &logthis("lonc at pid $loncpid not responding, giving up");
  100:         }
  101:     } else {
  102:         &logthis('lonc not running, giving up');
  103:     }
  104: }
  105: 
  106: # ------------------------------------------------------ Critical communication
  107: sub critical {
  108:     my ($cmd,$server)=@_;
  109:     &senddelayed($server);
  110:     my $answer=reply($cmd,$server);
  111:     if ($answer eq 'con_lost') {
  112:         my $pingreply=reply('ping',$server);
  113: 	&reconlonc("$perlvar{'lonSockDir'}/$server");
  114:         my $pongreply=reply('pong',$server);
  115:         &logthis("Ping/Pong for $server: $pingreply/$pongreply");
  116:         $answer=reply($cmd,$server);
  117:         if ($answer eq 'con_lost') {
  118:             my $now=time;
  119:             my $middlename=$cmd;
  120:             $middlename=~s/\W//g;
  121:             my $dfilename=
  122:              "$perlvar{'lonSockDir'}/delayed/$now.$middlename.$server";
  123:             {
  124:              my $dfh;
  125:              if ($dfh=Apache::File->new(">$dfilename")) {
  126:                 print $dfh "$server:$cmd\n";
  127: 	     }
  128:             }
  129:             sleep 2;
  130:             my $wcmd='';
  131:             {
  132: 	     my $dfh;
  133:              if ($dfh=Apache::File->new("$dfilename")) {
  134:                 $wcmd=<$dfh>;
  135: 	     }
  136:             }
  137:             chomp($wcmd);
  138:             if ($wcmd eq "$server:$cmd") {
  139: 		&logthis("Connection buffer $dfilename: $cmd");
  140:                 &logperm("D:$server:$cmd");
  141: 	        return 'con_delayed';
  142:             } else {
  143:                 &logthis("CRITICAL CONNECTION FAILED: $server $cmd");
  144:                 &logperm("F:$server:$cmd");
  145:                 return 'con_failed';
  146:             }
  147:         }
  148:     }
  149:     return $answer;
  150: }
  151: 
  152: 
  153: # ------------------------------ Find server with least workload from spare.tab
  154: sub spareserver {
  155:     my $tryserver;
  156:     my $spareserver='';
  157:     my $lowestserver=100;
  158:     foreach $tryserver (keys %spareid) {
  159:        my $answer=reply('load',$tryserver);
  160:        if (($answer =~ /\d/) && ($answer<$lowestserver)) {
  161: 	   $spareserver="http://$hostname{$tryserver}";
  162:            $lowestserver=$answer;
  163:        }
  164:     }    
  165:     return $spareserver;
  166: }
  167: 
  168: # --------- Try to authenticate user from domain's lib servers (first this one)
  169: sub authenticate {
  170:     my ($uname,$upass,$udom)=@_;
  171: 
  172:     if (($perlvar{'lonRole'} eq 'library') && 
  173:         ($udom eq $perlvar{'lonDefDomain'})) {
  174: 	my $subdir=$uname;
  175:         $subdir =~ s/(.)(.)(.).*/$1\/$2\/$3/;
  176:         my $passfilename="$perlvar{'lonUsersDir'}/$udom/$subdir/$uname/passwd";
  177:         if (-e $passfilename) {
  178:            my $pf = Apache::File->new($passfilename);
  179:            my $realpasswd=<$pf>;
  180:            chomp($realpasswd);
  181:            if ( $realpasswd eq $upass ) { 
  182:               return $perlvar{'lonHostID'};
  183: 	   } else {
  184: 	      return 'no_host';
  185:            }
  186:         }
  187:     }
  188: 
  189:     my $tryserver;
  190:     foreach $tryserver (keys %libserv) {
  191: 	if ($hostdom{$tryserver} eq $udom) {
  192:            my $answer=reply("auth:$udom:$uname:$upass",$tryserver);
  193:            if ($answer =~ /authorized/) {
  194:               if ($answer eq 'authorized') { return $tryserver; } 
  195: 	   }
  196:        }
  197:     }    
  198:     return 'no_host';
  199: }
  200: 
  201: # ---------------------- Find the homebase for a user from domain's lib servers
  202: sub homeserver {
  203:     my ($uname,$udom)=@_;
  204: 
  205:     my $index="$uname:$udom";
  206:     if ($homecache{$index}) { return "$homecache{$index}"; }
  207: 
  208:     my $tryserver;
  209:     foreach $tryserver (keys %libserv) {
  210: 	if ($hostdom{$tryserver} eq $udom) {
  211:            my $answer=reply("home:$udom:$uname",$tryserver);
  212:            if ($answer eq 'found') { 
  213: 	      $homecache{$index}=$tryserver;
  214:               return $tryserver; 
  215: 	   }
  216:        }
  217:     }    
  218:     return 'no_host';
  219: }
  220: 
  221: # ----------------------------- Subscribe to a resource, return URL if possible
  222: sub subscribe {
  223:     my $fname=shift;
  224:     &logthis($fname);
  225:     my $author=$fname;
  226:     $author=~s/\/home\/httpd\/html\/res\/([^\/]*)\/([^\/]*).*/$1\/$2/;
  227:     my ($udom,$uname)=split(/\//,$author);
  228:     my $home=homeserver($uname,$udom);
  229:     &logthis("$home $udom $uname");
  230:     if (($home eq 'no_host') || ($home eq $perlvar{'lonHostID'})) { 
  231:         return 'not_found'; 
  232:     }
  233:     my $answer=reply("sub:$fname",$home);
  234:     return $answer;
  235: }
  236:     
  237: 
  238: # ================================================================ Main Program
  239: 
  240: sub BEGIN {
  241: if ($readit ne 'done') {
  242: # ------------------------------------------------------------ Read access.conf
  243: {
  244:     my $config=Apache::File->new("/etc/httpd/conf/access.conf");
  245: 
  246:     while (my $configline=<$config>) {
  247:         if ($configline =~ /PerlSetVar/) {
  248: 	   my ($dummy,$varname,$varvalue)=split(/\s+/,$configline);
  249:            $perlvar{$varname}=$varvalue;
  250:         }
  251:     }
  252: }
  253: 
  254: # ------------------------------------------------------------- Read hosts file
  255: {
  256:     my $config=Apache::File->new("$perlvar{'lonTabDir'}/hosts.tab");
  257: 
  258:     while (my $configline=<$config>) {
  259:        my ($id,$domain,$role,$name,$ip)=split(/:/,$configline);
  260:        $hostname{$id}=$name;
  261:        $hostdom{$id}=$domain;
  262:        if ($role eq 'library') { $libserv{$id}=$name; }
  263:     }
  264: }
  265: 
  266: # ------------------------------------------------------ Read spare server file
  267: {
  268:     my $config=Apache::File->new("$perlvar{'lonTabDir'}/spare.tab");
  269: 
  270:     while (my $configline=<$config>) {
  271:        chomp($configline);
  272:        if (($configline) && ($configline ne $perlvar{'lonHostID'})) {
  273:           $spareid{$configline}=1;
  274:        }
  275:     }
  276: }
  277: $readit='done';
  278: &logthis('Read configuration');
  279: }
  280: }
  281: 1;
  282: 
  283: 
  284: 

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