home *** CD-ROM | disk | FTP | other *** search
Oberon Text | 1994-10-18 | 11.8 KB | 354 lines |
- Syntax10.Scn.Fnt
- MODULE NetServer; (*NW 15.2.90 / 15.9.93*)
- IMPORT SYSTEM, SCC, Core, FileDir, Files, Texts, Oberon;
- CONST PakSize = 512;
- T0 = 300; T1 = 1000; (*timeouts*)
- maxFileLen = 100000H;
- ACK = 10H; NAK = 25H; NPR = 26H; (*acknowledgements*)
- NRQ = 34H; NRS = 35H; (*name request, response*)
- SND = 41H; REC = 42H; (*send / receive request*)
- FDIR = 45H; DEL = 49H; (*directory and delete file requests*)
- PRT = 43H; (*receive to print request*)
- TRQ = 46H; TIM = 47H; (*time requests*)
- MSG = 44H; NPW = 48H; (*new password request*)
- TOT = 7FH; (*timeout*)
- MDIR = 4AH; SML = 4BH; RML = 4CH; DML = 4DH;
- VAR W: Texts.Writer;
- handler: Oberon.Task;
- head0, head1: SCC.Header;
- seqno: SHORTINT;
- K, mailuno: INTEGER;
- protected: BOOLEAN;
- MF: Files.File; (*last mail file accessed*)
- buf: ARRAY 1024 OF CHAR; (*used by FDIR*)
- dmy: ARRAY 4 OF CHAR;
- PROCEDURE EOL;
- BEGIN Texts.WriteLn(W); Texts.Append(Oberon.Log, W.buf)
- END EOL;
- PROCEDURE SetPartner(VAR name: ARRAY OF CHAR);
- BEGIN head0.dadr := head1.sadr; head0.destLink := head1.srcLink
- END SetPartner;
- PROCEDURE Send(t: SHORTINT; L: INTEGER; VAR data: ARRAY OF CHAR);
- BEGIN head0.typ := t; head0.len := L; SCC.SendPacket(head0, data)
- END Send;
- PROCEDURE ReceiveHead(timeout: LONGINT);
- VAR time: LONGINT;
- BEGIN time := Oberon.Time() + timeout;
- LOOP SCC.ReceiveHead(head1);
- IF head1.valid THEN
- IF head1.sadr = head0.dadr THEN EXIT
- ELSE SCC.Skip(head1.len)
- END
- ELSIF Oberon.Time() >= time THEN head1.typ := TOT; EXIT
- END
- END
- END ReceiveHead;
- PROCEDURE AppendS(VAR s, d: ARRAY OF CHAR; VAR k: INTEGER);
- VAR i: INTEGER; ch: CHAR;
- BEGIN i := 0;
- REPEAT ch := s[i]; d[k] := ch; INC(i); INC(k) UNTIL ch = 0X
- END AppendS;
- PROCEDURE AppendW(s: LONGINT; VAR d: ARRAY OF CHAR; n: INTEGER; VAR k: INTEGER);
- VAR i: INTEGER;
- BEGIN i := 0;
- REPEAT d[k] := CHR(s); s := s DIV 100H; INC(i); INC(k) UNTIL i = n
- END AppendW;
- PROCEDURE AppendN(x: LONGINT; VAR d: ARRAY OF CHAR; VAR k: INTEGER);
- VAR i: INTEGER; u: ARRAY 8 OF CHAR;
- BEGIN i := 0;
- REPEAT u[i] := CHR(x MOD 10 + 30H); INC(i); x := x DIV 10 UNTIL x = 0;
- REPEAT DEC(i); d[k] := u[i]; INC(k) UNTIL i = 0
- END AppendN;
- PROCEDURE AppendDate(t, d: INTEGER; VAR buf: ARRAY OF CHAR; VAR k: INTEGER);
- PROCEDURE Pair(ch: CHAR; x: LONGINT);
- BEGIN buf[k] := ch; INC(k);
- buf[k] := CHR(x DIV 10 + 30H); INC(k); buf[k] := CHR(x MOD 10 + 30H); INC(k)
- END Pair;
- BEGIN
- Pair(" ", d MOD 20H); Pair(".", d DIV 20H MOD 10H); Pair(".", d DIV 200H MOD 80H);
- Pair(" ", t DIV 800H MOD 20H); Pair(":", t DIV 20H MOD 40H); Pair(":", t MOD 20H * 2)
- END AppendDate;
- PROCEDURE SendBuffer(len: INTEGER; VAR done: BOOLEAN);
- VAR kd, ks: INTEGER;
- BEGIN
- REPEAT Send(seqno, len, buf); ReceiveHead(T1)
- UNTIL head1.typ # seqno + 10H;
- seqno := (seqno+1) MOD 8; kd := 0; ks := PakSize;
- WHILE ks < K DO buf[kd] := buf[ks]; INC(kd); INC(ks) END ;
- K := kd; done := head1.typ = seqno + 10H
- END SendBuffer;
- PROCEDURE AppendDirEntry(name: FileDir.FileName; adr: LONGINT; VAR done: BOOLEAN);
- VAR i: INTEGER; ch: CHAR;
- BEGIN i := 0; ch := name[0];
- WHILE ch > 0X DO buf[K] := ch; INC(i); INC(K); ch := name[i] END ;
- buf[K] := 0DX; INC(K);
- IF K >= PakSize THEN SendBuffer(PakSize, done) END
- END AppendDirEntry;
- PROCEDURE PickS(VAR s: ARRAY OF CHAR);
- VAR i, n: INTEGER; ch: CHAR;
- BEGIN i := 0; n := SHORT(LEN(s))-1; SCC.Receive(ch);
- WHILE ch > 0X DO
- IF i < n THEN s[i] := ch; INC(i) END ;
- SCC.Receive(ch)
- END ;
- s[i] := 0X
- END PickS;
- PROCEDURE PickQ(VAR w: LONGINT);
- VAR c0, c1, c2: CHAR; s: SHORTINT;
- BEGIN SCC.Receive(c0); SCC.Receive(c1); SCC.Receive(c2); SCC.Receive(s);
- w := s; w := ((w * 100H + LONG(c2)) * 100H + LONG(c1)) * 100H + LONG(c0)
- END PickQ;
- PROCEDURE PickW(VAR w: INTEGER);
- VAR c0: CHAR; s: SHORTINT;
- BEGIN SCC.Receive(c0); SCC.Receive(s); w := s; w := w * 100H + ORD(c0)
- END PickW;
- PROCEDURE SendData(F: Files.File);
- VAR k: INTEGER;
- x: CHAR;
- len: LONGINT;
- R: Files.Rider;
- BEGIN Files.Set(R, F, 0); len := 0; seqno := 0;
- LOOP k := 0;
- LOOP Files.Read(R, x);
- IF R.eof THEN EXIT END ;
- buf[k] := x; INC(k);
- IF k = PakSize THEN EXIT END
- END ;
- REPEAT Send(seqno, k, buf); ReceiveHead(T1)
- UNTIL head1.typ # seqno + 10H;
- seqno := (seqno + 1) MOD 8; len := len + k;
- IF head1.typ # seqno + 10H THEN EXIT END ;
- IF k < PakSize THEN EXIT END
- END
- END SendData;
- PROCEDURE ReceiveData(F: Files.File; VAR done: BOOLEAN);
- VAR k, retry: INTEGER;
- x: CHAR;
- len: LONGINT;
- R: Files.Rider;
- BEGIN Files.Set(R, F, 0); seqno := 0; len := 0; retry := 4;
- LOOP
- IF head1.typ = seqno THEN
- seqno := (seqno + 1) MOD 8; len := len + head1.len;
- IF len > maxFileLen THEN
- Send(NAK, 0, dmy); done := FALSE; Files.Close(F); Files.Purge(F); EXIT
- END ;
- retry := 4; Send(seqno + 10H, 0, dmy); k := 0;
- WHILE k < head1.len DO
- SCC.Receive(x); Files.Write(R, x); INC(k)
- END ;
- IF k < PakSize THEN done := TRUE; EXIT END
- ELSE DEC(retry);
- IF retry = 0 THEN done := FALSE; EXIT END ;
- Send(seqno + 10H, 0, dmy)
- END ;
- ReceiveHead(T0)
- END
- END ReceiveData;
- PROCEDURE SendMail(VAR R: Files.Rider; len: LONGINT);
- VAR k: INTEGER; x: CHAR;
- BEGIN seqno := 0;
- LOOP k := 0;
- LOOP Files.Read(R, x);
- IF k = len THEN EXIT END ;
- buf[k] := SYSTEM.ROT(x, 3); INC(k);
- IF k = PakSize THEN EXIT END
- END ;
- REPEAT Send(seqno, k, buf); ReceiveHead(T1)
- UNTIL head1.typ # seqno + 10H;
- seqno := (seqno + 1) MOD 8; len := len - k;
- IF head1.typ # seqno + 10H THEN EXIT END ;
- IF k < PakSize THEN EXIT END
- END
- END SendMail;
- PROCEDURE Serve;
- VAR i, j, k0, k1, n, uno: INTEGER;
- ch: CHAR; typ: SHORTINT;
- done: BOOLEAN;
- F: Files.File;
- R: Files.Rider;
- t, d, pw, npw, pos, len: LONGINT;
- Id: Core.ShortName;
- fname: Core.Name;
- mdir: Core.MailDir;
- mrtab: Core.MResTab;
- BEGIN SCC.ReceiveHead(head1);
- IF ~head1.valid THEN RETURN END ;
- typ := head1.typ;
- IF typ = SND THEN
- PickS(Id); PickQ(pw); PickS(fname); SetPartner(Id);
- IF Core.UserNo(Id, pw) >= 0 THEN
- F := Files.Old(fname);
- IF F # NIL THEN SendData(F)
- ELSE Send(NAK, 0, dmy)
- END
- ELSE Send(NPR, 0, dmy)
- END
- ELSIF typ = REC THEN
- PickS(Id); PickQ(pw); PickS(fname); SetPartner(Id);
- IF ~protected & (Core.UserNo(Id, pw) >= 0) THEN
- F := Files.New(fname);
- Send(ACK, 0, dmy); ReceiveHead(T0);
- IF head1.valid THEN
- ReceiveData(F, done);
- IF done THEN Files.Register(F) END
- END
- ELSE Send(NPR, 0, dmy)
- END
- ELSIF typ = PRT THEN
- PickS(Id); PickQ(pw); SetPartner(Id); uno := Core.UserNo(Id, pw);
- IF uno >= 0 THEN
- F := Files.New("");
- Send(ACK, 0, dmy); ReceiveHead(T0);
- IF head1.valid THEN
- ReceiveData(F, done);
- IF done THEN Files.Close(F); Core.InsertTask(Core.PrintQueue, F, Id, uno) END
- END
- ELSE Send(NPR, 0, dmy)
- END
- ELSIF typ = DEL THEN
- PickS(Id); PickQ(pw); PickS(fname); SetPartner(Id);
- IF ~protected & (Core.UserNo(Id, pw) >= 0) THEN
- Files.Delete(fname, i);
- IF i = 0 THEN Send(ACK, 0, dmy) ELSE Send(NAK, 0, dmy) END
- ELSE Send(NPR, 0, dmy)
- END
- ELSIF typ = FDIR THEN
- PickS(Id); PickQ(pw); PickS(fname); SetPartner(Id); uno := Core.UserNo(Id, pw);
- IF uno >= 0 THEN
- K := 0; seqno := 0; FileDir.Enumerate(fname, AppendDirEntry);
- SendBuffer(K, done)
- ELSE Send(NPR, 0, dmy)
- END
- ELSIF typ = MDIR THEN
- PickS(Id); PickQ(pw); SetPartner(Id); uno := Core.UserNo(Id, pw);
- IF uno >= 0 THEN
- IF uno # mailuno THEN
- Core.GetFileName(uno, fname); MF := Files.Old(fname); mailuno := uno
- END ;
- K := 0; seqno := 0;
- IF MF # NIL THEN
- Files.Set(R, MF, 32); Files.ReadBytes(R, mdir, SIZE(Core.MailDir));
- i := mdir[0].next; j := 30; done := TRUE;
- WHILE (i # 0) & (j > 0) & done DO
- AppendN(i, buf, K); AppendDate(mdir[i].time, mdir[i].date, buf, K);
- buf[K] := " "; INC(K); AppendS(mdir[i].originator, buf, K);
- buf[K-1] := " "; AppendN(mdir[i].len, buf, K); buf[K] := 0DX; INC(K);
- IF K >= PakSize THEN SendBuffer(PakSize, done) END ;
- i := mdir[i].next; DEC(j)
- END
- END ;
- SendBuffer(K, done)
- ELSE Send(NPR, 0, dmy)
- END
- ELSIF typ = SML THEN (*send mail*)
- PickS(Id); PickQ(pw); PickW(n); SetPartner(Id); uno := Core.UserNo(Id, pw);
- IF uno >= 0 THEN
- IF uno # mailuno THEN
- Core.GetFileName(uno, fname); MF := Files.Old(fname); mailuno := uno
- END ;
- IF (MF # NIL) & (n > 0) & (n < 31) THEN
- Files.Set(R, MF, (n+1)*32);
- Files.ReadInt(R, i); Files.ReadInt(R, j); pos := LONG(i) * 100H;
- Files.ReadLInt(R, len);
- IF len > 0 THEN Files.Set(R, MF, pos); SendMail(R, len)
- ELSE Send(NAK, 0, dmy)
- END
- ELSE Send(NAK, 0, dmy)
- END
- ELSE Send(NPR, 0, dmy)
- END
- ELSIF typ = RML THEN (*receive mail*)
- PickS(Id); PickQ(pw); SetPartner(Id); uno := Core.UserNo(Id, pw);
- IF uno >= 0 THEN
- F := Files.New("");
- Send(ACK, 0, dmy); ReceiveHead(T0);
- IF head1.valid THEN
- ReceiveData(F, done);
- IF done THEN Files.Close(F); Core.InsertTask(Core.MailQueue, F, Id, uno) END
- END
- ELSE Send(NPR, 0, dmy)
- END
- ELSIF typ = DML THEN (*delete mail*)
- PickS(Id); PickQ(pw); PickW(n); SetPartner(Id); uno := Core.UserNo(Id, pw);
- IF uno >= 0 THEN
- IF uno # mailuno THEN
- Core.GetFileName(uno, fname); MF := Files.Old(fname); mailuno := uno
- END ;
- IF (MF # NIL) & (n > 0) & (n < 31) THEN
- Files.Set(R, MF, 0);
- Files.ReadBytes(R, mrtab, 32); Files.ReadBytes(R, mdir, SIZE(Core.MailDir));
- i := 0; k1 := 30;
- LOOP k0 := mdir[i].next; DEC(k1);
- IF (k0 = 0) OR (k1 = 0) THEN Send(NAK, 0, buf); EXIT END ;
- IF k0 = n THEN
- j := mdir[n].pos;
- k0 := SHORT((mdir[n].len + 255) DIV 256) + j;
- REPEAT INCL(mrtab[j DIV 32], j MOD 32); INC(j) UNTIL j = k0;
- mdir[n].len := 0; mdir[i].next := mdir[n].next;
- Files.Set(R, MF, 0); Files.WriteBytes(R, mrtab, 32);
- Files.WriteBytes(R, mdir, SIZE(Core.MailDir)); Files.Close(MF);
- Send(ACK, 0, dmy); EXIT
- END ;
- i := k0
- END
- ELSE Send(NAK, 0, dmy)
- END
- ELSE Send(NPR, 0, dmy)
- END
- ELSIF typ = TRQ THEN
- Oberon.GetClock(t, d); SetPartner(Id); i := 0;
- AppendW(t, fname, 4, i); AppendW(d, fname, 4, i); Send(TIM, 8, fname)
- ELSIF typ = NRQ THEN i := 0;
- LOOP SCC.Receive(ch); Id[i] := ch; INC(i);
- IF ch = 0X THEN EXIT END ;
- IF i = 7 THEN Id[7] := 0X; EXIT END
- END ;
- WHILE i < head1.len DO SCC.Receive(ch); INC(i) END ;
- IF Id = Oberon.User THEN
- head1.dadr := head1.sadr; head1.typ := NRS; head1.len := 0;
- SCC.SendPacket(head1, dmy)
- END
- ELSIF typ = MSG THEN i := 0;
- WHILE i < head1.len DO SCC.Receive(ch); Texts.Write(W, ch); INC(i) END ;
- SetPartner(Id); Send(ACK, 0, dmy); EOL
- ELSIF typ = NPW THEN
- PickS(Id); PickQ(pw); uno := Core.UserNo(Id, pw);
- IF uno >= 0 THEN
- SetPartner(Id); Send(ACK, 0, dmy); ReceiveHead(T0);
- IF head1.typ = 0 THEN
- PickQ(npw); Core.SetPassword(uno, npw); Send(ACK, 0, dmy)
- ELSE Send(NAK, 0, dmy)
- END
- ELSE Send(NPR, 0, dmy)
- END
- ELSE SCC.Skip(head1.len)
- END ;
- Core.Collect
- END Serve;
- (*----------------------- Commands -------------------*)
- PROCEDURE Start*;
- BEGIN Oberon.Remove(handler); Oberon.Install(handler);
- MF := NIL; mailuno := -2;
- Texts.WriteString(W, "Net started (NW 15.9.93)"); EOL
- END Start;
- PROCEDURE State*;
- VAR RR0, RR1: SHORTINT;
- BEGIN SYSTEM.GET(0FFFD88H, RR0); SYSTEM.PUT(0FFFD88H, 1); SYSTEM.GET(0FFFD88H, RR1);
- Texts.WriteString(W, "Net state"); Texts.WriteHex(W, RR0); Texts.WriteHex(W, RR1); EOL
- END State;
- PROCEDURE Reset*;
- BEGIN SCC.Start(TRUE)
- END Reset;
- PROCEDURE Stop*;
- BEGIN Oberon.Remove(handler); Texts.WriteString(W, "Net stopped"); EOL
- END Stop;
- PROCEDURE Protect*;
- BEGIN protected := TRUE
- END Protect;
- PROCEDURE Unprotect*;
- BEGIN protected := FALSE
- END Unprotect;
- BEGIN Texts.OpenWriter(W); NEW(handler); handler.handle := Serve
- END NetServer.
-