-- Copyright (C) 1981, 1984, 1985 by Xerox Corporation. All rights reserved. -- Protocol.mesa, HGM, Transport Mechanism: subroutines for mail and reg server protocols -- HGM, 15-Sep-85 4:17:57 -- 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: LONG 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: LONG 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: LONG 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: LONG 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: LONG 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: LONG 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.