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>