-- Transport Mechanism - subroutines for mail and reg server protocols --
-- [Juniper]<DMS>MS>Protocol.mesa
-- Mark Johnson 12-Nov-81 10:02:40 --
-- 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];
stringAddr: LONG POINTER ← string;
Stream.PutBlock[
str, [LOOPHOLE[stringAddr], 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];
tempAddr: LONG POINTER ← temp;
stringAddr: LONG POINTER ← string;
[used, why, ] ← Stream.GetBlock[
str, [LOOPHOLE[tempAddr], 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, [LOOPHOLE[stringAddr], 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.