DIRECTORY Basics USING[ BITSHIFT, BITXOR ], ConvertUnsafe USING[ ToRope ], GVBasics USING[ GVString, maxGVStringLength, oldestTime, Password, RName, Timestamp], GVProtocol USING[ bpw, FailureReason, GVSocket, Handle, ReceiveCount, ReceiveRC, ReceiveRName, ReceiveTimestamp, ReturnCode, RSOperation, SendCount, SendRName, SendRSOperation, SendTimestamp, StringSize ], IO USING[ EndOfStream, Flush, GetChar, PutChar, PutFR, PutRope, STREAM, UnsafeBlock, UnsafeGetBlock, UnsafePutBlock ], PupDefs USING[ AnyLocalPupAddress, PupPackageMake, SecondsToTocks ], PupStream USING[ PupAddress, PupByteStreamCreate, StreamClosing, TimeOut ], PupTypes USING[ Byte, fillInSocketID, PupAddress, PupSocketID ], Rope USING[ Fetch, Length, ROPE ]; GVProtocolImpl: CEDAR MONITOR IMPORTS Basics, ConvertUnsafe, GVProtocol, IO, PupDefs, PupStream, Rope EXPORTS GVBasics, GVProtocol = BEGIN OPEN GVProtocol; MakeKey: PUBLIC PROC[password: Rope.ROPE] RETURNS[ key: GVBasics.Password ] = BEGIN key _ ALL[0]; FOR i: CARDINAL IN CARDINAL[0..password.Length[]) DO j: [0..LENGTH[key]) = (i/bpw) MOD LENGTH[key]; c: WORD = LOOPHOLE[ IF password.Fetch[i] IN ['A..'Z] THEN password.Fetch[i] - 'A + 'a ELSE password.Fetch[i] ]; key[j] _ Basics.BITXOR[ key[j], Basics.BITSHIFT[c, IF (i MOD 2) = 0 THEN 9 ELSE 1]]; ENDLOOP; END; RopeFromTimestamp: PUBLIC PROC[stamp: GVBasics.Timestamp] RETURNS[Rope.ROPE] = { RETURN[ IO.PutFR["%b#%b@%g", [integer[stamp.net]], [integer[stamp.host]], [integer[stamp.time]] ] ] }; bpw: INT = GVProtocol.bpw; sockets: ARRAY GVProtocol.GVSocket OF PupTypes.PupSocketID _ [ none: [0,0], RSEnquiry: [0, 50B], RSPoll: [0, 52B], Lily: [0, 53B], MSPoll: [0, 54B], MSForward: [0, 55B], MSSend: [0, 56B], MSRetrieve: [0, 57B] ]; SetTestingMode: PUBLIC ENTRY PROCEDURE = BEGIN FOR s: GVProtocol.GVSocket IN GVProtocol.GVSocket DO sockets[s].a _ 1 ENDLOOP; END; GetSocket: PUBLIC ENTRY PROC[gv: GVSocket] RETURNS[PupTypes.PupSocketID] = { RETURN[ sockets[gv] ] }; 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 SIGNAL[why: FailureReason, text: Rope.ROPE] = CODE; CreateStream: PUBLIC PROCEDURE[host: PupTypes.PupAddress, socket: GVProtocol.GVSocket, secs: CARDINAL _ 120 ] RETURNS[ GVProtocol.Handle ] = BEGIN ENABLE PupStream.StreamClosing => ERROR Failed[communicationError, text]; IF socket # none THEN host.socket _ sockets[socket]; RETURN[ PupStream.PupByteStreamCreate[host, PupDefs.SecondsToTocks[secs] ] ] END; SendNow: PUBLIC PROCEDURE[ str: GVProtocol.Handle ] = BEGIN ENABLE PupStream.StreamClosing => ERROR Failed[communicationError, text]; str.Flush[]; END; Byte: TYPE = [0..256); SendByte: PUBLIC PROCEDURE[ str: GVProtocol.Handle, byte: Byte ] = BEGIN ENABLE PupStream.StreamClosing => ERROR Failed[communicationError, text]; str.PutChar[LOOPHOLE[byte]]; END; ReceiveByte: PUBLIC PROCEDURE[ str: GVProtocol.Handle ] RETURNS[ byte: Byte ] = BEGIN ENABLE BEGIN PupStream.StreamClosing => ERROR Failed[communicationError, text]; PupStream.TimeOut => SIGNAL Failed[noData, "Server not sending data"]; IO.EndOfStream => ERROR Failed[protocolError, "Unexpected \"mark\""]; END; byte _ LOOPHOLE[str.GetChar[]]; END; SendBytes: PUBLIC PROC[str: GVProtocol.Handle, block: IO.UnsafeBlock] = BEGIN ENABLE PupStream.StreamClosing => ERROR Failed[communicationError, text]; str.UnsafePutBlock[block]; END; ReceiveBytes: PUBLIC UNSAFE PROC[str: GVProtocol.Handle, block: IO.UnsafeBlock] = TRUSTED BEGIN ENABLE BEGIN PupStream.StreamClosing => ERROR Failed[communicationError, text]; PupStream.TimeOut => SIGNAL Failed[noData, "Server not sending data"]; IO.EndOfStream => ERROR Failed[protocolError, "Protocol error: unexpected \"mark\""]; END; nBytes: INT = str.UnsafeGetBlock[block]; IF nBytes # block.count THEN ERROR Failed[protocolError, "Protocol error: unexpected \"mark\""]; END; SendGVString: PUBLIC PROC[ str: GVProtocol.Handle, rope: GVBasics.GVString] = BEGIN length: INT = rope.Length[]; IF length > GVBasics.maxGVStringLength THEN ERROR Failed[clientError, "Excessive rope length"]; GVProtocol.SendCount[str, length]; GVProtocol.SendCount[str, 0--ignored--]; SendRope[str, rope]; IF length MOD 2 # 0 THEN SendByte[str,0]; END; ReceiveGVString: PUBLIC PROC[ str: GVProtocol.Handle] RETURNS[GVBasics.GVString] = TRUSTED BEGIN string: STRING = [GVBasics.maxGVStringLength]; string.length _ GVProtocol.ReceiveCount[str]; [] _ GVProtocol.ReceiveCount[str]; IF string.length > string.maxlength THEN ERROR Failed[protocolError, "Protocol error: too many characters"]; ReceiveBytes[str, [LOOPHOLE[LONG[@string.text]], 0, bpw*(SIZE[StringBody[string.length]] - SIZE[StringBody[0]])]]; RETURN[ConvertUnsafe.ToRope[string]] END; SendRope: PUBLIC PROC[ str: GVProtocol.Handle, rope: Rope.ROPE] = BEGIN str.PutRope[rope ! PupStream.StreamClosing => ERROR Failed[communicationError, text]]; END; Enquire: PUBLIC PROCEDURE[str: GVProtocol.Handle, op: GVProtocol.RSOperation, name: GVBasics.RName, oldStamp: GVBasics.Timestamp _ GVBasics.oldestTime ] RETURNS[ rc: GVProtocol.ReturnCode, stamp: GVBasics.Timestamp ] = BEGIN GVProtocol.SendRSOperation[str, op]; GVProtocol.SendRName[str, name]; IF op IN [Expand .. CheckStamp] THEN GVProtocol.SendTimestamp[str, oldStamp]; SendNow[str]; rc _ GVProtocol.ReceiveRC[str]; IF rc.code = done AND op IN [Expand .. CheckStamp] THEN stamp _ GVProtocol.ReceiveTimestamp[str] ELSE stamp _ oldStamp; END; ReceiveRList: PUBLIC PROCEDURE[str: GVProtocol.Handle, work: PROCEDURE[GVBasics.RName] ] = BEGIN length: INT _ ReceiveCount[str]; WHILE length > 0 DO name: GVBasics.RName = GVProtocol.ReceiveRName[str]; length _ length - GVProtocol.StringSize[name]; work[name]; ENDLOOP; END; Init: PROC = TRUSTED BEGIN PupDefs.PupPackageMake[]; myAddr _ PupDefs.AnyLocalPupAddress[PupTypes.fillInSocketID]; END; Init[]; END. èGrapevineUser (Cedar) - subroutines for mail and reg server protocols GVProtocolImpl.mesa Andrew Birrell 23-Jan-81 17:07:47 Last Edited by: Levin, September 22, 1983 11:59 am Last Edited by: Birrell, August 25, 1983 5:06 pm Ê?˜JšœE™EJšœ™Jšœ"™"J™2J™0šÏk ˜ Jšœœœœ˜!Jšœœ ˜Jšœ œG˜UJšœ œ½˜ÍJšœœ8œ0˜vJšœœ7˜DJšœ œ<˜KJšœ œ2˜@Jšœœœ˜"—J˜šœœ˜Jšœ$œ˜GJšœ˜J˜—Jš˜J˜Jšœ ˜J˜J˜š Ïnœœœœœ˜MJš˜Jšœœ˜ Jšœœœœ˜1šœœœœ˜1š œœœœœ ˜4Jšœ˜ Jšœ˜—Jš œœœœœœœ˜T—Jšœ˜Jšœ˜—J˜š žœœœœœ˜Nšœœœ˜JšœI˜I—J˜J˜—Jšœœ˜J˜šœ œœ˜>Jšœ ˜ Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜—J˜šžœœœ œ˜(Jš˜Jšœœœœ˜NJšœ˜—J˜š ž œœœœœ˜JJšœœ˜—J˜J˜J˜š žœœ œœœ˜IJš˜Jšœœ˜;Jšœ˜J˜—Jš œœœ œœ˜BJ˜šž œœ œ?œ˜mJšœ˜Jš˜Jšœœ"˜IJšœœ˜4JšœF˜LJšœ˜J˜—šžœœ œ˜5Jš˜Jšœœ"˜IJ˜ Jšœ˜J˜—Jšœœ ˜J˜šžœœ œ(˜BJš˜Jšœœ"˜IJšœ œ˜Jšœ˜J˜—šž œœ œ˜7Jšœ˜Jš˜š˜Jš˜Jšœœ"˜BJšœœ+˜FJšœœ.˜EJšœ˜—Jšœœ˜Jšœ˜J˜—šž œœœ œ˜GJš˜Jšœœ"˜IJšœ˜Jšœ˜J˜—š ž œœœœ œ˜YJš˜š˜Jš˜Jšœœ"˜BJšœœ+˜FJšœœ>˜UJšœ˜—Jšœœ˜(Jšœ˜Jšœœ>˜HJšœ˜J˜—šž œœœ4˜MJš˜Jšœœ˜Jšœ$˜&Jšœœ.˜8Jšœ>Ïc œ˜KJšœ˜Jšœœœ˜)Jšœ˜J˜—š žœœœœ˜ZJš˜Jšœœ ˜.J˜PJšœ!˜#Jšœœ>˜HJš œœœœœ˜rJšœ˜$Jšœ˜J˜—šžœœœ%œ˜AJš˜Jšœ.œ#˜VJšœ˜J˜—šžœœ œ˜1J˜J˜J˜4Jšœ:˜AJš˜J˜$J˜ Jšœœ˜Jšœ)˜-J˜ J˜Jšœ˜Jšœœ˜ Jšœ)˜-Jšœ˜Jšœ˜J˜—šž œœ œ˜6Jšœ œ˜#Jš˜Jšœœ˜ Jšœ ˜šœ5˜7Jšœ.˜.J˜ —Jšœ˜Jšœ˜J˜—šžœœ˜Jš˜J˜J˜=Jšœ˜—J˜J˜J˜Jšœ˜J˜—…—?