DIRECTORY Basics USING [BITSHIFT, BITXOR, bytesPerWord], ConvertUnsafe USING [ToRope], Endian USING [HWORD], GVBasics USING [Connect, GVString, ItemHeader, maxGVStringLength, oldestTime, Password, Remark, RName, Timestamp], GVNames USING [RSOperation], GVProtocol USING [FailureReason, GVSocket, Handle, MSOperation, ReturnCode], IO USING [Close, EndOfStream, Flush, GetChar, PutChar, PutFR, PutRope, STREAM, UnsafeBlock, UnsafeGetBlock, UnsafePutBlock], IOExtras USING [GetHWord, PutHWord], Pup USING [Address, nullSocket, Socket], PupSocket USING [IsThisMe], PupStream USING [Create, StreamClosing, Timeout], PupWKS USING [gvLily, gvMSClientInput, gvMSForward, gvMSPoll, gvMSRetrieve, gvRSPoll, gvRSEnquiry], Rope USING [Fetch, Length, ROPE]; GVProtocolImpl: CEDAR MONITOR IMPORTS Basics, ConvertUnsafe, IO, IOExtras, PupSocket, PupStream, Rope EXPORTS GVBasics, GVProtocol = { Handle: TYPE = GVProtocol.Handle; MakeKey: PUBLIC PROC [password: Rope.ROPE] RETURNS [key: GVBasics.Password] = { key _ ALL[0]; FOR i: CARDINAL IN CARDINAL[0..Rope.Length[password]) DO j: [0..LENGTH[key]) = (i/bpw) MOD LENGTH[key]; c: WORD = LOOPHOLE[ IF Rope.Fetch[password, i] IN ['A..'Z] THEN Rope.Fetch[password, i] - 'A + 'a ELSE Rope.Fetch[password, i] ]; key[j] _ Basics.BITXOR[key[j], Basics.BITSHIFT[c, IF (i MOD 2) = 0 THEN 9 ELSE 1]]; ENDLOOP; }; RopeFromTimestamp: PUBLIC PROC [stamp: GVBasics.Timestamp] RETURNS [r: Rope.ROPE] = { r _ IO.PutFR["%b#%b@%g", [integer[stamp.net]], [integer[stamp.host]], [cardinal[stamp.time]]]; }; bpw: INT = Basics.bytesPerWord; SocketsArray: TYPE = ARRAY GVProtocol.GVSocket OF Pup.Socket; sockets: REF SocketsArray _ NEW[SocketsArray _ [ none: Pup.nullSocket, RSEnquiry: PupWKS.gvRSEnquiry, RSPoll: PupWKS.gvRSPoll, Lily: PupWKS.gvLily, MSPoll: PupWKS.gvMSPoll, MSForward: PupWKS.gvMSForward, MSSend: PupWKS.gvMSClientInput, MSRetrieve: PupWKS.gvMSRetrieve ]]; SetTestingMode: PUBLIC ENTRY PROC = { FOR s: GVProtocol.GVSocket IN GVProtocol.GVSocket DO sockets[s].b _ 1 ENDLOOP; }; GetSocket: PUBLIC ENTRY PROC [gv: GVProtocol.GVSocket] RETURNS [Pup.Socket] = { RETURN[sockets[gv]]; }; IsLocal: PUBLIC PROC [addr: Pup.Address] RETURNS [BOOL] = { RETURN[PupSocket.IsThisMe[addr]]; }; Failed: PUBLIC SIGNAL [why: GVProtocol.FailureReason, text: Rope.ROPE] = CODE; CreateStream: PUBLIC PROC [host: Pup.Address, socket: GVProtocol.GVSocket, secs: INT _ 120] RETURNS [Handle] = { ENABLE PupStream.StreamClosing => ERROR Failed[communicationError, text]; IF socket # none THEN host.socket _ sockets[socket]; RETURN[PupStream.Create[host, secs*1000, secs*1000]]; }; SendNow: PUBLIC PROC [str: Handle] = { ENABLE { PupStream.StreamClosing => ERROR Failed[communicationError, text]; PupStream.Timeout => SIGNAL Failed[noData, "Server not reading data"]; }; IO.Flush[str]; }; Close: PUBLIC PROC [str: Handle] = { IO.Close[str]; }; Byte: TYPE = [0..256); SendAck: PUBLIC PROC [str: Handle] = { SendByte[str, 0]; }; ReceiveAck: PUBLIC PROC [str: Handle] = { [] _ ReceiveByte[str]; }; SendBoolean: PUBLIC PROC [str: Handle, bool: BOOL] = { SendByte[str, IF bool THEN 1 ELSE 0]; }; ReceiveBoolean: PUBLIC PROC [str: Handle] RETURNS [BOOL] = { RETURN[ReceiveByte[str] # 0]; }; SendByte: PUBLIC PROC [str: Handle, byte: Byte] = { ENABLE { PupStream.StreamClosing => ERROR Failed[communicationError, text]; PupStream.Timeout => SIGNAL Failed[noData, "Server not reading data"]; }; IO.PutChar[str, LOOPHOLE[byte]]; }; ReceiveByte: PUBLIC PROC [str: Handle] RETURNS [byte: Byte] = { ENABLE { PupStream.StreamClosing => ERROR Failed[communicationError, text]; PupStream.Timeout => SIGNAL Failed[noData, "Server not sending data"]; IO.EndOfStream => ERROR Failed[protocolError, "Unexpected \"mark\""]; }; byte _ LOOPHOLE[IO.GetChar[str]]; }; SendCount: PUBLIC PROC [str: Handle, count: Endian.HWORD] = TRUSTED { ENABLE { PupStream.StreamClosing => ERROR Failed[communicationError, text]; PupStream.Timeout => SIGNAL Failed[noData, "Server not reading data"]; }; IOExtras.PutHWord[str, count]; }; ReceiveCount: PUBLIC PROC [str: Handle] RETURNS [count: Endian.HWORD] = TRUSTED { ENABLE { PupStream.StreamClosing => ERROR Failed[communicationError, text]; PupStream.Timeout => SIGNAL Failed[noData, "Server not sending data"]; IO.EndOfStream => ERROR Failed[protocolError, "Unexpected \"mark\""]; }; count _ IOExtras.GetHWord[str]; }; SendItemHeader: PUBLIC PROC [str: Handle, header: GVBasics.ItemHeader] = TRUSTED { SendBytes[str, [LOOPHOLE[LONG[@header]], 0, bpw*SIZE[GVBasics.ItemHeader]]]; }; ReceiveItemHeader: PUBLIC PROC [str: Handle] RETURNS [header: GVBasics.ItemHeader] = TRUSTED { ReceiveBytes[str, [LOOPHOLE[LONG[@header]], 0, bpw*SIZE[GVBasics.ItemHeader]]]; }; SendTimestamp: PUBLIC PROC [str: Handle, stamp: GVBasics.Timestamp] = TRUSTED { SendBytes[str, [LOOPHOLE[LONG[@stamp]], 0, bpw*SIZE[GVBasics.Timestamp]]]; }; ReceiveTimestamp: PUBLIC PROC [str: Handle] RETURNS [stamp: GVBasics.Timestamp] = TRUSTED { ReceiveBytes[str, [LOOPHOLE[LONG[@stamp]], 0, bpw*SIZE[GVBasics.Timestamp]]]; }; SendPassword: PUBLIC PROC [str: Handle, pw: GVBasics.Password] = TRUSTED { SendBytes[str, [LOOPHOLE[LONG[@pw]], 0, bpw*SIZE[GVBasics.Password]]]; }; ReceivePassword: PUBLIC PROC [str: Handle] RETURNS [pw: GVBasics.Password] = TRUSTED { ReceiveBytes[str, [LOOPHOLE[LONG[@pw]], 0, bpw*SIZE[GVBasics.Password]]]; }; SendRC: PUBLIC PROC [str: Handle, rc: GVProtocol.ReturnCode] = TRUSTED { SendBytes[str, [LOOPHOLE[LONG[@rc]], 0, bpw*SIZE[GVProtocol.ReturnCode]]]; }; ReceiveRC: PUBLIC PROC [str: Handle] RETURNS [rc: GVProtocol.ReturnCode] = TRUSTED { ReceiveBytes[str, [LOOPHOLE[LONG[@rc]], 0, bpw*SIZE[GVProtocol.ReturnCode]]]; }; SendMSOperation: PUBLIC PROC [str: Handle, op: GVProtocol.MSOperation] = TRUSTED { SendBytes[str, [LOOPHOLE[LONG[@op]], 0, bpw*SIZE[GVProtocol.MSOperation]]]; }; ReceiveMSOperation: PUBLIC PROC [str: Handle] RETURNS [op: GVProtocol.MSOperation] = TRUSTED { ReceiveBytes[str, [LOOPHOLE[LONG[@op]], 0, bpw*SIZE[GVProtocol.MSOperation]]]; }; SendRSOperation: PUBLIC PROC [str: Handle, op: GVNames.RSOperation] = TRUSTED { SendBytes[str, [LOOPHOLE[LONG[@op]], 0, bpw*SIZE[GVNames.RSOperation]]]; }; ReceiveRSOperation: PUBLIC PROC [str: Handle] RETURNS [op: GVNames.RSOperation] = TRUSTED { ReceiveBytes[str, [LOOPHOLE[LONG[@op]], 0, bpw*SIZE[GVNames.RSOperation]]]; }; SendBytes: PUBLIC PROC [str: Handle, block: IO.UnsafeBlock] = { ENABLE { PupStream.StreamClosing => ERROR Failed[communicationError, text]; PupStream.Timeout => SIGNAL Failed[noData, "Server not reading data"]; }; IO.UnsafePutBlock[str, block]; }; ReceiveBytes: PUBLIC UNSAFE PROC [str: Handle, block: IO.UnsafeBlock] = TRUSTED { ENABLE { PupStream.StreamClosing => ERROR Failed[communicationError, text]; PupStream.Timeout => SIGNAL Failed[noData, "Server not sending data"]; IO.EndOfStream => ERROR Failed[protocolError, "Protocol error: unexpected \"mark\""]; }; nBytes: INT = IO.UnsafeGetBlock[str, block]; IF nBytes # block.count THEN ERROR Failed[protocolError, "Protocol error: unexpected \"mark\""]; }; StringSize: PUBLIC PROC [string: GVBasics.GVString] RETURNS [INT] = { RETURN[2 + (Rope.Length[string] + bpw-1) / bpw]; }; SendRName: PUBLIC PROC [str: Handle, name: GVBasics.RName] = { SendGVString[str, name]; }; ReceiveRName: PUBLIC PROC [str: Handle] RETURNS [GVBasics.RName] = { RETURN[ReceiveGVString[str]]; }; SendConnect: PUBLIC PROC [str: Handle, connect: GVBasics.Connect] = { SendGVString[str, connect]; }; ReceiveConnect: PUBLIC PROC [str: Handle] RETURNS [GVBasics.Connect] = { RETURN[ReceiveGVString[str]]; }; SendRemark: PUBLIC PROC [str: Handle, remark: GVBasics.Remark] = { SendGVString[str, remark]; }; ReceiveRemark: PUBLIC PROC [str: Handle] RETURNS [GVBasics.Remark] = { RETURN[ReceiveGVString[str]]; }; SendGVString: PUBLIC PROC [str: Handle, rope: GVBasics.GVString] = { length: INT = rope.Length[]; IF length > GVBasics.maxGVStringLength THEN ERROR Failed[clientError, "Excessive rope length"]; SendCount[str, length]; SendCount[str, 0--ignored--]; SendRope[str, rope]; IF length MOD 2 # 0 THEN SendByte[str,0]; }; ReceiveFunnyString: PUBLIC PROC [str: Handle] RETURNS [GVBasics.GVString] = TRUSTED { string: STRING = [GVBasics.maxGVStringLength]; string.length _ ReceiveCount[str]; ReceiveBytes[str, [LOOPHOLE[LONG[@string.text]], 0, bpw*(SIZE[StringBody[string.length]] - SIZE[StringBody[0]])]]; RETURN[ConvertUnsafe.ToRope[string]]; }; ReceiveGVString: PUBLIC PROC [str: Handle] RETURNS [GVBasics.GVString] = TRUSTED { string: STRING = [GVBasics.maxGVStringLength]; string.length _ ReceiveCount[str]; [] _ ReceiveCount[str]; -- maxLength 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]] }; SendRope: PUBLIC PROC [str: Handle, rope: Rope.ROPE] = { ENABLE { PupStream.StreamClosing => ERROR Failed[communicationError, text]; PupStream.Timeout => SIGNAL Failed[noData, "Server not reading data"]; }; IO.PutRope[str, rope]; }; Enquire: PUBLIC PROC [str: Handle, op: GVNames.RSOperation, name: GVBasics.RName, oldStamp: GVBasics.Timestamp _ GVBasics.oldestTime] RETURNS [rc: GVProtocol.ReturnCode, stamp: GVBasics.Timestamp] = { 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; }; ReceiveRList: PUBLIC PROC [str: Handle, work: PROC [GVBasics.RName]] = { length: INT _ ReceiveCount[str]; WHILE length > 0 DO name: GVBasics.RName = ReceiveRName[str]; length _ length - StringSize[name]; work[name]; ENDLOOP; }; }. GVProtocolImpl.mesa - subroutines for mail and reg server protocols Copyright c 1985 by Xerox Corporation. All rights reserved. Hal Murray May 27, 1985 9:12:23 pm PDT Russ Atkinson (RRA) October 18, 1985 1:18:30 pm PDT Hal Murray, May 12, 1986 10:02:01 pm PDT No maxLength Κ l˜codešœC™CKšœ Οmœ1™žœ/˜|Kšœ žœ˜$Kšœžœ˜(Kšœ žœ ˜Kšœ žœ!˜1KšœžœV˜cKšœžœžœ˜!—headšœžœž˜Kšžœžœ&˜GKšžœ˜ K˜—šœžœ˜!K˜—š Οnœžœžœžœžœ˜OKšœžœ˜ š žœžœžœžœž˜8Kšœžœžœžœ˜.š œžœžœžœžœ ˜:Kšžœ"˜&Kšžœ˜—Kš œžœžœžœžœžœžœ˜SKšžœ˜—Kšœ˜K˜—š Ÿœžœžœžœ žœ˜UKšœžœX˜^Kšœ˜K˜—šœžœ˜K˜—šœžœžœžœ ˜=K˜—šœ žœžœ˜0Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜K˜—šŸœžœžœžœ˜%Kšžœžœžœžœ˜NKšœ˜K˜—š Ÿ œžœžœžœžœ˜OKšžœ˜Kšœ˜K˜—š Ÿœžœžœžœžœ˜;Kšžœ˜!Kšœ˜K˜—š œžœžœ+žœžœ˜NK˜—š Ÿ œžœžœ8žœžœ ˜pKšžœžœ"˜IKšžœžœ˜4Kšžœ/˜5Kšœ˜K˜—šŸœžœžœ˜&šžœ˜Kšœžœ"˜BKšœžœ.˜I—Kšžœ ˜Kšœ˜K˜—šŸœžœžœ˜$Kšžœ ˜Kšœ˜—K˜šœžœ ˜K˜—šŸœžœžœ˜&Kšœ˜Kšœ˜K˜—šŸ œžœžœ˜)Kšœ˜Kšœ˜K˜—šŸ œžœžœžœ˜6Kšœžœžœžœ˜%Kšœ˜K˜—š Ÿœžœžœžœžœ˜˜C—Kšœ˜K˜—š Ÿ œžœžœžœžœ˜EKšžœ*˜0Kšœ˜—K˜šŸ œžœžœ(˜>K˜˜K˜——šŸ œžœžœžœ˜DKšžœ˜šœ˜K˜K˜——šŸ œžœžœ-˜EK˜˜K˜——šŸœžœžœžœ˜HKšžœ˜šœ˜K˜K˜——šŸ œžœžœ+˜BK˜˜K˜——šŸ œžœžœžœ˜FKšžœ˜šœ˜K˜K˜——šŸ œžœžœ+˜DKšœžœ˜šžœ%ž˜+Kšžœ.˜3—Kšœ˜KšœΟc œ˜Kšœ˜Kšžœžœžœ˜)Kšœ˜K˜—š Ÿœžœžœžœžœ˜VKšœžœ ˜.Kšœ"˜"Kšœ ™ Kš œžœžœžœžœ˜rKšžœ˜%Kšœ˜K˜—š Ÿœžœžœžœžœ˜RKšœžœ ˜.Kšœ"˜"Kšœ  ˜$šžœ!ž˜(Kšžœ>˜C—Kš œžœžœžœžœ˜rKšžœ˜%Kšœ˜K˜—šŸœžœžœžœ˜8šžœ˜Kšœžœ"˜BKšœžœ.˜I—Kšžœ˜Kšœ˜K˜—šŸœžœžœq˜…Kšžœ;˜BK˜K˜Kšžœžœžœ˜BK˜ K˜Kšžœžœžœžœ˜UKšžœ˜Kšœ˜K˜—šŸ œžœžœžœ˜HKšœžœ˜ šžœ ž˜Kšœ)˜)Kšœ#˜#K˜ Kšžœ˜—Kšœ˜K˜—Kšœ˜K˜—…—&j3π