-- 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.