Annotation of loncom/lonnet/perl/lonnet.pm, revision 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>