-- Transport Mechanism - subroutines for mail and reg server protocols --
-- [Juniper]<DMS>MS>Protocol.mesa
-- Andrew Birrell 23-Jan-81 17:07:47 --
DIRECTORY
BodyDefs USING[ ItemHeader, maxRNameLength, oldestTime, Password,
RName, RNameSize, Timestamp],
Inline USING[ BITSHIFT, BITXOR ],
ProtocolDefs USING[ FailureReason, Handle, MSOperation, ReceiveRName,
ReceiveString, ReturnCode, RSOperation, SendRName,
SendString ],
PupDefs USING[ PupPackageMake, SecondsToTocks ],
PupStream USING[ GetPupAddress, PupAddress, PupByteStreamCreate,
StreamClosing ],
PupTypes USING[ Byte, PupAddress, PupSocketID ],
Stream USING[ CompletionCode, GetBlock, Handle, PutBlock, SendNow,
TimeOut],
String USING[ AppendChar, AppendLongNumber, AppendNumber ];
Protocol: MONITOR
IMPORTS BodyDefs, Inline, ProtocolDefs, PupDefs, PupStream, Stream,
String
EXPORTS ProtocolDefs =
BEGIN
OPEN ProtocolDefs;
MakeKey: PUBLIC PROC[password: STRING] RETURNS[ key: BodyDefs.Password ] =
BEGIN
key ← ALL[0];
FOR i: CARDINAL IN [0..password.length)
DO j: [0..LENGTH[key]) = (i/bpw) MOD LENGTH[key];
c: WORD = LOOPHOLE[ IF password[i] IN ['A..'Z]
THEN password[i] - 'A + 'a
ELSE password[i] ];
key[j] ← Inline.BITXOR[ key[j],
Inline.BITSHIFT[c, IF (i MOD 2) = 0 THEN 9 ELSE 1]];
ENDLOOP;
END;
bpw: CARDINAL = 2;
RegServerEnquirySocket: PUBLIC PupTypes.PupSocketID ← [0, 50B];
RegServerSpareSocket: PUBLIC PupTypes.PupSocketID ← [0, 51B];
RegServerPollingSocket: PUBLIC PupTypes.PupSocketID ← [0, 52B];
spareSocket: PUBLIC PupTypes.PupSocketID ← [0, 53B];
mailServerPollingSocket: PUBLIC PupTypes.PupSocketID ← [0, 54B];
mailServerServerSocket: PUBLIC PupTypes.PupSocketID ← [0, 55B];
mailServerInputSocket: PUBLIC PupTypes.PupSocketID ← [0, 56B];
mailServerOutputSocket: PUBLIC PupTypes.PupSocketID ← [0, 57B];
running: BOOLEAN ← FALSE;
TooLateForTestingMode: SIGNAL = CODE;
SetTestingMode: PUBLIC ENTRY PROCEDURE =
BEGIN
IF running THEN SIGNAL TooLateForTestingMode[];
RegServerEnquirySocket.a ← 1;
RegServerSpareSocket.a ← 1;
RegServerPollingSocket.a ← 1;
spareSocket.a ← 1;
mailServerPollingSocket.a ← 1;
mailServerServerSocket.a ← 1;
mailServerInputSocket.a ← 1;
mailServerOutputSocket.a ← 1;
END;
Init: PUBLIC ENTRY PROCEDURE =
{ --initialize the exported variables;-- running ← TRUE };
myAddr: PupTypes.PupAddress;
IsLocal: PUBLIC PROCEDURE[addr: PupTypes.PupAddress] RETURNS[ BOOLEAN ] =
BEGIN
RETURN[ addr.net = myAddr.net AND addr.host = myAddr.host ]
END;
Failed: PUBLIC ERROR[why: FailureReason] = CODE;
CreateStream: PUBLIC PROCEDURE[addr: PupTypes.PupAddress,
secs: CARDINAL ← 120 ]
RETURNS[ ProtocolDefs.Handle ] =
BEGIN
ENABLE PupStream.StreamClosing => ERROR Failed[communicationError];
RETURN[ PupStream.PupByteStreamCreate[addr,
PupDefs.SecondsToTocks[secs] ] ]
END;
DestroyStream: PUBLIC PROCEDURE[str: ProtocolDefs.Handle] =
BEGIN
str.delete[str];
END;
SendNow: PUBLIC PROCEDURE[ str: ProtocolDefs.Handle ] =
BEGIN
ENABLE
BEGIN
PupStream.StreamClosing => ERROR Failed[communicationError];
Stream.TimeOut => ERROR Failed[noData];
END;
Stream.SendNow[str];
END;
Byte: TYPE = [0..256);
SendByte: PUBLIC PROCEDURE[ str: ProtocolDefs.Handle, byte: Byte ] =
BEGIN
word: PACKED ARRAY [0..bpw) OF Byte;
word[0] ← byte;
SendBytes[str, @word, 1];
END;
ReceiveByte: PUBLIC PROCEDURE[ str: ProtocolDefs.Handle ]
RETURNS[ byte: Byte ] =
BEGIN
word: PACKED ARRAY [0..bpw) OF Byte;
ReceiveBytes[str, @word, 1];
byte ← word[0];
END;
SendCount: PUBLIC PROCEDURE[ str: ProtocolDefs.Handle, count: CARDINAL ] =
{ SendBytes[str, @count, bpw*SIZE[CARDINAL]] };
ReceiveCount: PUBLIC PROCEDURE[ str: ProtocolDefs.Handle ]
RETURNS[ count: CARDINAL ] =
{ ReceiveBytes[str, @count, bpw*SIZE[CARDINAL]] };
SendItemHeader: PUBLIC PROCEDURE[ str: ProtocolDefs.Handle,
header: BodyDefs.ItemHeader] =
{ SendBytes[str, @header, bpw*SIZE[BodyDefs.ItemHeader]] };
ReceiveItemHeader: PUBLIC PROCEDURE[ str: ProtocolDefs.Handle ]
RETURNS[ header: BodyDefs.ItemHeader ] =
{ ReceiveBytes[str, @header, bpw*SIZE[BodyDefs.ItemHeader]] };
SendTimestamp: PUBLIC PROCEDURE[ str: ProtocolDefs.Handle,
stamp: BodyDefs.Timestamp] =
{ SendBytes[str, @stamp, bpw*SIZE[BodyDefs.Timestamp]] };
ReceiveTimestamp: PUBLIC PROCEDURE[ str: ProtocolDefs.Handle ]
RETURNS[ stamp: BodyDefs.Timestamp ] =
{ ReceiveBytes[str, @stamp, bpw*SIZE[BodyDefs.Timestamp]] };
AppendTimestamp: PUBLIC PROCEDURE[s: STRING, stamp: BodyDefs.Timestamp] =
BEGIN
String.AppendNumber[s, stamp.net, 8];
String.AppendChar[s, '#];
String.AppendNumber[s, stamp.host, 8];
String.AppendChar[s, '@];
String.AppendLongNumber[s, stamp.time, 10];
END;
SendPassword: PUBLIC PROCEDURE[ str: ProtocolDefs.Handle,
key, pw: BodyDefs.Password] =
{ SendBytes[str, @pw, bpw*SIZE[BodyDefs.Password]] };
ReceivePassword: PUBLIC PROCEDURE[ str: ProtocolDefs.Handle,
key: BodyDefs.Password ]
RETURNS[ pw: BodyDefs.Password ] =
{ ReceiveBytes[str, @pw, bpw*SIZE[BodyDefs.Password]] };
SendRC: PUBLIC PROCEDURE[ str: ProtocolDefs.Handle,
rc: ProtocolDefs.ReturnCode] =
{ SendBytes[str, @rc, bpw*SIZE[ProtocolDefs.ReturnCode]] };
ReceiveRC: PUBLIC PROCEDURE[ str: ProtocolDefs.Handle ]
RETURNS[ rc: ProtocolDefs.ReturnCode ] =
{ ReceiveBytes[str, @rc, bpw*SIZE[ProtocolDefs.ReturnCode]] };
SendMSOperation: PUBLIC PROCEDURE[ str: ProtocolDefs.Handle,
op: ProtocolDefs.MSOperation] =
{ SendBytes[str, @op, bpw*SIZE[ProtocolDefs.MSOperation]] };
ReceiveMSOperation: PUBLIC PROCEDURE[ str: ProtocolDefs.Handle ]
RETURNS[ op: ProtocolDefs.MSOperation ] =
{ ReceiveBytes[str, @op, bpw*SIZE[ProtocolDefs.MSOperation]] };
SendRSOperation: PUBLIC PROCEDURE[ str: ProtocolDefs.Handle,
op: ProtocolDefs.RSOperation] =
{ SendBytes[str, @op, bpw*SIZE[ProtocolDefs.RSOperation]] };
ReceiveRSOperation: PUBLIC PROCEDURE[ str: ProtocolDefs.Handle ]
RETURNS[ op: ProtocolDefs.RSOperation ] =
{ ReceiveBytes[str, @op, bpw*SIZE[ProtocolDefs.RSOperation]] };
SendBytes: PUBLIC PROC[str: ProtocolDefs.Handle,
buffer: POINTER, count: CARDINAL] =
BEGIN
ENABLE PupStream.StreamClosing => ERROR Failed[communicationError];
Stream.PutBlock[str,[buffer,0,count], FALSE ];
END;
ReceiveBytes: PUBLIC PROC[str: ProtocolDefs.Handle,
buffer: POINTER, count: CARDINAL] =
BEGIN
ENABLE
BEGIN
PupStream.StreamClosing => ERROR Failed[communicationError];
Stream.TimeOut => ERROR Failed[noData];
END;
why: Stream.CompletionCode;
[,why,] ← Stream.GetBlock[str, [buffer,0,count] ];
IF why # normal THEN ERROR Failed[protocolError];
END;
SendString: PUBLIC PROC[ str: ProtocolDefs.Handle,
string: STRING] =
BEGIN
ENABLE PupStream.StreamClosing => ERROR Failed[communicationError];
Stream.PutBlock[str,
[string,0,bpw*SIZE[StringBody[string.length]]],
FALSE ];
END;
ReceiveString: PUBLIC PROC[ str: ProtocolDefs.Handle,
string: STRING] =
BEGIN
ENABLE
BEGIN
PupStream.StreamClosing => ERROR Failed[communicationError];
Stream.TimeOut => ERROR Failed[noData];
END;
used: CARDINAL ← 0;
why: Stream.CompletionCode;
temp: STRING = [0];
[used,why,] ←
Stream.GetBlock[str,[temp,0,SIZE[StringBody[0]]*bpw]];
IF why # normal OR temp.length > string.maxlength
THEN ERROR Failed[protocolError];
string.length ← temp.length;
[,why,]← Stream.GetBlock[str,[string,used,
bpw*SIZE[StringBody[string.length]]]];
IF why # normal THEN ERROR Failed[protocolError];
END;
Enquire: PUBLIC PROCEDURE[str: ProtocolDefs.Handle,
op: ProtocolDefs.RSOperation,
name: BodyDefs.RName,
oldStamp: BodyDefs.Timestamp
← BodyDefs.oldestTime ]
RETURNS[ rc: ProtocolDefs.ReturnCode, stamp: BodyDefs.Timestamp ] =
BEGIN
SendRSOperation[str, op];
SendRName[str, name];
IF op IN [Expand .. CheckStamp]
THEN SendTimestamp[str, oldStamp];
SendNow[str];
rc ← ReceiveRC[str];
IF rc.code = done
AND op IN [Expand .. CheckStamp]
THEN stamp ← ReceiveTimestamp[str]
ELSE stamp ← oldStamp;
END;
ReceiveRList: PUBLIC PROCEDURE[str: ProtocolDefs.Handle,
work: PROCEDURE[BodyDefs.RName] ] =
BEGIN
length: CARDINAL ← ReceiveCount[str];
WHILE length > 0
DO name: BodyDefs.RName = [BodyDefs.maxRNameLength];
ReceiveRName[str, name];
length ← length - BodyDefs.RNameSize[name];
work[name];
ENDLOOP;
END;
PupDefs.PupPackageMake[];
PupStream.GetPupAddress[@myAddr, "ME"L];
END.