Annotation of loncom/lonnet/perl/lonnet.pm, revision 1.1.1.1

1.1       albertel    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>