home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Fresh Fish 10
/
Fresh_Fish_10_2352.bin
/
new
/
dev
/
obero
/
oberon
/
projectoberonsrc
/
lineserver.mod
(
.txt
)
< prev
next >
Wrap
Oberon Text
|
1994-10-18
|
17KB
|
505 lines
Syntax10.Scn.Fnt
MODULE LineServer; (*NW 18.4.89 / 15.9.93*)
IMPORT SYSTEM, Core, V24, FileDir, Files, Texts, Oberon;
(*packet types: 0ttt00rs
1 = data, 2 = data ack,
3 = open, 4 = open ack,
5 = close, 6 = close ack,
7 = abort *)
CONST PakSize = 256; maxLen = 1000000;
T0 = 1500; (*timeout 5 sec*)
ENQ = 40X; SND = 41X; REC = 42X; FDIR = 45X; NPW = 48X; DEL = 49X;
MDIR = 4AX; SML = 4BX; RML = 4CX; DML = 4DX;
ACK = 10X; NAK = 25X; NPR = 26X; CX = 63X;
VAR W: Texts.Writer;
handler: Oberon.Task;
Lstat: INTEGER; (*1: busy, 0: free*)
Lmode: INTEGER; (*1: master, 0: server*)
rx, K: INTEGER; (*receiver buffer index*)
rbuf: ARRAY PakSize+4 OF CHAR; (*receiver buffer*)
myR, myS: INTEGER; (*receiver and sender sequence numbers*)
mailuno, logcnt: INTEGER;
mailTime: LONGINT;
MF: Files.File; (*last mail file accessed*)
hdch: ARRAY 2 OF CHAR;
cx400: ARRAY 14 OF CHAR;
buf: ARRAY 512 OF CHAR; (*mailbox and filedir commands*)
PROCEDURE EOL;
BEGIN Texts.WriteLn(W); Texts.Append(Oberon.Log, W.buf)
END EOL;
PROCEDURE Log(ch: CHAR);
BEGIN Texts.Write(W, ch); INC(logcnt);
IF logcnt = 80 THEN Texts.WriteLn(W); logcnt := 0 END ;
Texts.Append(Oberon.Log, W.buf)
END Log;
PROCEDURE Rec(VAR ch: CHAR);
VAR time: LONGINT; ch1: CHAR;
BEGIN time := Oberon.Time() + T0;
LOOP
IF V24.Available() > 0 THEN V24.Receive(ch1); ch := CHR(ORD(ch1) MOD 80H); EXIT END ;
IF Oberon.Time() > time THEN ch := 1X; EXIT END
END
END Rec;
PROCEDURE SendPacket(typ, len: INTEGER; VAR data: ARRAY OF CHAR);
VAR i, u, x: INTEGER; cs: LONGINT;
BEGIN V24.Send(hdch[1-Lmode]);
cs := typ + 5; i := 0;
WHILE i < len DO
cs := (cs*5 + ORD(data[i])) MOD 32767; INC(i)
END ;
data[len] := CHR(cs); data[len+1] := CHR(cs DIV 100H); INC(len, 2);
V24.Send(CHR(typ MOD 64 + 33)); x := typ DIV 64; u := 1; i := 0;
WHILE i < len DO (*encode*)
IF u = 0 THEN
x := ORD(data[i]); V24.Send(CHR(x MOD 64 + 33)); x := x DIV 64; u := 1
ELSIF u = 1 THEN
x := ORD(data[i])*4 + x; V24.Send(CHR(x MOD 64 + 33)); x := x DIV 64; u := 2
ELSIF u = 2 THEN
x := ORD(data[i])*16 + x; V24.Send(CHR(x MOD 64 + 33)); V24.Send(CHR(x DIV 64 + 33)); u := 0
END ;
INC(i)
END ;
IF u > 0 THEN V24.Send(CHR(x MOD 64 + 33)) END ;
V24.Send(0DX)
END SendPacket;
PROCEDURE ReceivePacket(VAR typ, len: INTEGER);
VAR ch: CHAR;
i, j, u, x: INTEGER; cs: LONGINT;
BEGIN len := 0; typ := 0; rbuf[1] := 0X;
REPEAT Rec(ch) UNTIL ch > 0X;
IF ch = hdch[Lmode] THEN
Rec(ch); i := 0; u := 0;
WHILE (ch > 0DX) & (i < 260) DO
IF u = 0 THEN
x := ORD(ch) - 33; Rec(ch); x := (ORD(ch) - 33) * 64 + x;
rbuf[i] := CHR(x); INC(i); x := x DIV 256; u := 2
ELSIF u = 1 THEN
x := (ORD(ch) - 33) * 4 + x; rbuf[i] := CHR(x); INC(i); u := 0
ELSIF u = 2 THEN
x := (ORD(ch) - 33) * 16 + x; rbuf[i] := CHR(x); INC(i); x := x DIV 256; u := 1
END ;
Rec(ch)
END ;
IF (ch = 0DX) & (i > 2) THEN
DEC(i, 2); j := 0; cs := 1;
WHILE j < i DO
cs := (cs*5 + ORD(rbuf[j])) MOD 32767; INC(j)
END ;
IF (CHR(cs) = rbuf[i]) & (CHR(cs DIV 256) = rbuf[i+1]) THEN
rx := 1; typ := ORD(rbuf[0]); len := i-1
END
END
END
END ReceivePacket;
PROCEDURE Send1(len: INTEGER; VAR buf: ARRAY OF CHAR; VAR res: INTEGER);
VAR retries, typ, plen: INTEGER;
BEGIN myS := 1 - myS; retries := 3;
SendPacket(myR*2+myS+14H, len, buf);
LOOP ReceivePacket(typ, plen);
IF typ <= 0 THEN (*error*) DEC(retries);
IF retries = 0 THEN res := 1; EXIT END ;
SendPacket(myR*2+myS+14H, len, buf)
ELSIF (typ DIV 10H = 2) & (typ DIV 2 MOD 2 = myS) THEN res := 0; EXIT
ELSIF typ DIV 10H = 7 THEN (*abort*) res := 2; Lstat := 0; EXIT
END
END
END Send1;
PROCEDURE Receive1(VAR len, res: INTEGER);
VAR typ: INTEGER; dmy: ARRAY 4 OF CHAR;
BEGIN
LOOP ReceivePacket(typ, len);
IF typ <= 0 THEN (*error*) res := 1; EXIT
ELSIF typ DIV 10H = 1 THEN (*data*)
IF typ MOD 2 # myR THEN
myR := 1 - myR; SendPacket(myR*2+myS+20H, 0, dmy); res := 0; EXIT
ELSE SendPacket(myR*2+myS+20H, 0, dmy)
END
ELSIF typ DIV 10H = 3 THEN (*open*) SendPacket(40H, 0, dmy)
END
END
END Receive1;
PROCEDURE SendData(F: Files.File; VAR res: INTEGER);
VAR k: INTEGER; x: CHAR;
R: Files.Rider;
buf: ARRAY PakSize+4 OF CHAR;
BEGIN Files.Set(R, F, 0);
REPEAT 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 ;
Send1(k, buf, res);
UNTIL (res # 0) OR (k < PakSize)
END SendData;
PROCEDURE SendMail(VAR R: Files.Rider; len: LONGINT; VAR res: INTEGER);
VAR k, m, typ: INTEGER; x: CHAR;
buf: ARRAY PakSize+4 OF CHAR;
BEGIN
REPEAT k := 0;
LOOP Files.Read(R, x);
IF k = len THEN EXIT END ;
buf[k] := SYSTEM.VAL(CHAR, SYSTEM.ROT(x, 3)); INC(k);
IF k = PakSize THEN EXIT END
END ;
Send1(k, buf, res); len := len - k
UNTIL (res # 0) OR (k < PakSize)
END SendMail;
PROCEDURE ReceiveData(F: Files.File; VAR L: LONGINT; VAR res: INTEGER);
VAR k, len: INTEGER;
R: Files.Rider;
BEGIN Files.Set(R, F, 0); L := 0;
LOOP Receive1(len, res);
IF res = 0 THEN
L := L + len; k := 0;
IF L > maxLen THEN Log("$"); res := 1; EXIT END ;
WHILE k < len DO
Files.Write(R, rbuf[rx]); INC(rx); INC(k)
END ;
IF k < 256 THEN EXIT END
ELSE EXIT
END
END
END ReceiveData;
PROCEDURE SendBuffer(VAR res: INTEGER);
VAR s, d: INTEGER; B0, B1: CHAR;
BEGIN B0 := buf[PakSize]; B1 := buf[PakSize+1];
Send1(PakSize, buf, res); buf[PakSize] := B0; buf[PakSize+1] := B1;
d := 0; s := PakSize;
WHILE s < K DO buf[d] := buf[s]; INC(d); INC(s) END ;
K := d
END SendBuffer;
PROCEDURE SendToSun(VAR res: INTEGER);
VAR len, uno: INTEGER;
id: Core.ShortName;
F: Files.File;
BEGIN
LOOP
IF Core.LineQueue.n = 0 THEN Send1(0, id, res); EXIT END ;
Core.GetTask(Core.LineQueue, F, id, uno); Log(".");
SendData(F, res);
IF res # 0 THEN EXIT END ;
Receive1(len, res);
IF res # 0 THEN EXIT END ;
Core.RemoveTask(Core.LineQueue)
END
END SendToSun;
PROCEDURE ReceiveFromSun(VAR res: INTEGER);
VAR len: LONGINT;
ch: CHAR;
id: Core.ShortName;
F: Files.File;
BEGIN id := "sun";
LOOP F := Files.New(""); ReceiveData(F, len, res);
IF (len = 0) OR (res # 0) THEN EXIT END ;
Files.Close(F); Log(".");
Core.InsertTask(Core.MailQueue, F, id, -1); Send1(0, id, res)
END
END ReceiveFromSun;
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* AppendDirEntry(name: FileDir.FileName; adr: LONGINT; VAR cont: BOOLEAN);
VAR i, res: INTEGER;
BEGIN i := 0;
WHILE name[i] > 0X DO buf[K] := name[i]; INC(K); INC(i) END ;
buf[K] := 0DX; INC(K);
IF K >= PakSize THEN SendBuffer(res);
IF res # 0 THEN cont := FALSE END
END
END AppendDirEntry;
PROCEDURE PickS(VAR s: ARRAY OF CHAR);
VAR i: INTEGER; ch: CHAR;
BEGIN i := 0;
REPEAT ch := rbuf[rx]; INC(rx); s[i] := ch; INC(i) UNTIL ch = 0X
END PickS;
PROCEDURE PickW(VAR w: ARRAY OF SYSTEM.BYTE; n: INTEGER);
VAR i: INTEGER;
BEGIN i := 0;
REPEAT w[i] := rbuf[rx]; INC(rx); INC(i) UNTIL i = n
END PickW;
(* ---------------