DIRECTORY Basics USING [LongNumber], BufferDefs USING [Buffer, BufferAccessHandle,FreeBufferPool, MakeBufferPool, OisBuffer], CommunicationInternal USING [], DriverDefs USING [DriverXmitStatus, Glitch], PacketExchange USING [ErrorReason, maxBlockLength, RequestHandle, RequestObject], OISCP USING [GetFreeSendOisBufferFromPool, ReturnFreeOisBuffer, unknownNetID], OISCPTypes USING [bytesPerExchangeHeader, bytesPerPktHeader, ExchangeID, ExchangeClientType, WaitTime], PacketExchangeInternal USING [], PrincOps USING [ByteBltBlock], PrincOpsUtils USING [ByteBlt], Process USING [InitializeCondition, MsecToTicks], ProcessorFace USING [GetClockPulses], Router USING [FindMyHostID], NSAddress USING [broadcastHostNumber, NetworkAddress, nullNetworkAddress, SocketNumber], Socket USING [Abort, AssignNetworkAddress, ChannelAborted, ChannelHandle, Create, Delete, GetPacket, PutPacket, SetWaitTime, TimeOut]; PacketExchangeImpl: MONITOR IMPORTS DriverDefs, PrincOpsUtils, OISCP, Process, ProcessorFace, Router, Socket EXPORTS CommunicationInternal, PacketExchange, PacketExchangeInternal SHARES BufferDefs, PacketExchange = BEGIN NetworkAddress: PUBLIC TYPE = NSAddress.NetworkAddress; ExchangeHandle: TYPE = REF PacketExchangeObject; PacketExchangeObject: PUBLIC TYPE = RECORD [ cH: Socket.ChannelHandle, sendBufferAccessHandle: BufferDefs.BufferAccessHandle]; sendCompleted: CONDITION; uniqueNetworkAddress: PUBLIC NetworkAddress _ NSAddress.nullNetworkAddress; sendInProgress: CARDINAL = 1; bufferSent: CARDINAL = 2; sendAborted: CARDINAL = 3; retryCount: CARDINAL = 2; bytesPerExchangePacketHeader: CARDINAL = OISCPTypes.bytesPerPktHeader + OISCPTypes.bytesPerExchangeHeader; Timeout: PUBLIC SIGNAL = CODE; Error: PUBLIC ERROR [why: PacketExchange.ErrorReason] = CODE; IllegalUseOfRequeueProcedure: PUBLIC ERROR = CODE; GetFreeSendPacket: PUBLIC PROCEDURE [h: ExchangeHandle] RETURNS [BufferDefs.OisBuffer] = BEGIN RETURN[OISCP.GetFreeSendOisBufferFromPool[h.sendBufferAccessHandle]]; END; NotifySendCompleted: PRIVATE ENTRY PROCEDURE [b: BufferDefs.Buffer] = BEGIN b.requeueData _ bufferSent; b.requeueProcedure _ LostBuffer; BROADCAST sendCompleted; END; LostBuffer: PRIVATE PROCEDURE [b: BufferDefs.Buffer] = BEGIN DriverDefs.Glitch[IllegalUseOfRequeueProcedure]; END; SendRequestPacket: PUBLIC PROCEDURE [h: ExchangeHandle, requestB: BufferDefs.OisBuffer, replyFilter: OISCPTypes.ExchangeClientType] RETURNS [replyB: BufferDefs.OisBuffer] = BEGIN WaitSendCompleted: ENTRY PROCEDURE [waitBuffer: BufferDefs.OisBuffer] RETURNS [DriverDefs.DriverXmitStatus] = INLINE BEGIN WHILE (waitBuffer.requeueData=sendInProgress) DO WAIT sendCompleted; ENDLOOP; RETURN[LOOPHOLE[waitBuffer.status]]; END; channelAborted: BOOLEAN _ FALSE; exchangeID: OISCPTypes.ExchangeID; time: LONG CARDINAL _ ProcessorFace.GetClockPulses[]; exchangeID.a _ LOOPHOLE[time, Basics.LongNumber].highbits; exchangeID.b _ LOOPHOLE[time, Basics.LongNumber].lowbits; requestB.ois.transCntlAndPktTp.packetType _ packetExchange; requestB.ois.exchangeID _ exchangeID; THROUGH [0..retryCount) DO -- try twice replyB _ NIL; requestB.requeueProcedure _ NotifySendCompleted; requestB.requeueData _ sendInProgress; Socket.PutPacket[h.cH, requestB ! Socket.ChannelAborted => BEGIN requestB.requeueData _ sendAborted; channelAborted _ TRUE; EXIT; END]; SELECT WaitSendCompleted[requestB] FROM goodCompletion => DO -- do gets until satisfied or timed out replyB _ Socket.GetPacket[h.cH ! Socket.TimeOut => EXIT; Socket.ChannelAborted => BEGIN channelAborted _ TRUE; EXIT; END]; IF replyB.ois.transCntlAndPktTp.packetType=packetExchange AND replyB.ois.exchangeID=exchangeID AND ((replyB.ois.exchangeType=replyFilter) OR (replyFilter=unspecified)) AND (replyB.ois.source.host = requestB.ois.destination.host OR requestB.ois.destination.host = NSAddress.broadcastHostNumber) AND replyB.ois.source.socket=requestB.ois.destination.socket THEN RETURN ELSE BEGIN OISCP.ReturnFreeOisBuffer[replyB]; replyB _ NIL; END; ENDLOOP; -- goodCompletion noRouteToNetwork => RETURN WITH ERROR Error[noRouteToDestination]; ENDCASE => RETURN WITH ERROR Error[hardwareProblem]; ENDLOOP; RETURN WITH ERROR Error[IF channelAborted THEN aborted ELSE timeout]; END; -- SendRequestPacket SendRequest: PUBLIC PROCEDURE [h: ExchangeHandle, remote: NetworkAddress, requestBlk, replyBlk: PrincOps.ByteBltBlock, requestType: OISCPTypes.ExchangeClientType] RETURNS [nBytes: CARDINAL, replyType: OISCPTypes.ExchangeClientType] = BEGIN blkSizeOK: BOOLEAN; requestB, replyB: BufferDefs.OisBuffer; blkByteLen: CARDINAL _ requestBlk.stopIndexPlusOne-requestBlk.startIndex; IF blkByteLen>PacketExchange.maxBlockLength THEN RETURN WITH ERROR Error[blockTooBig]; requestB _ OISCP.GetFreeSendOisBufferFromPool[h.sendBufferAccessHandle]; requestB.ois.pktLength _ bytesPerExchangePacketHeader + blkByteLen; requestB.ois.transCntlAndPktTp.packetType _ packetExchange; requestB.ois.destination _ remote; requestB.ois.exchangeType _ requestType; [] _ PrincOpsUtils.ByteBlt[[@requestB.ois.exchangeBody, 0, blkByteLen], requestBlk]; BEGIN ENABLE UNWIND => OISCP.ReturnFreeOisBuffer[requestB]; replyB _ SendRequestPacket[h, requestB, unspecified ! Error => BEGIN IF why=timeout THEN BEGIN SIGNAL Timeout; RETRY; -- caller RESUMEs => RETRY; caller does anything else => UNWIND. END END]; END; OISCP.ReturnFreeOisBuffer[requestB]; replyType _ replyB.ois.exchangeType; nBytes _ replyB.ois.pktLength - bytesPerExchangePacketHeader; blkByteLen _ replyBlk.stopIndexPlusOne - replyBlk.startIndex; IF blkSizeOK _ ((nBytes<=blkByteLen) AND (replyBlk.startIndex<=replyBlk.stopIndexPlusOne)) THEN nBytes _ PrincOpsUtils.ByteBlt[replyBlk, [@replyB.ois.exchangeBody, 0, blkByteLen]]; OISCP.ReturnFreeOisBuffer[replyB]; IF NOT blkSizeOK THEN BEGIN nBytes _ 0; RETURN WITH ERROR Error[blockTooSmall]; END; END; -- SendRequest WaitForRequestPacket: PUBLIC PROCEDURE [h: ExchangeHandle, request: OISCPTypes.ExchangeClientType] RETURNS [requestB: BufferDefs.OisBuffer] = BEGIN channelAborted: BOOLEAN _ FALSE; THROUGH [0..retryCount) DO -- try twice requestB _ NIL; DO -- do gets until satisfied or timed out requestB _ Socket.GetPacket[h.cH ! Socket.TimeOut => EXIT; Socket.ChannelAborted => BEGIN channelAborted _ TRUE; EXIT; END]; IF requestB.ois.transCntlAndPktTp.packetType=packetExchange AND ((requestB.ois.exchangeType=request) OR (request=unspecified)) THEN RETURN ELSE BEGIN OISCP.ReturnFreeOisBuffer[requestB]; requestB _ NIL; END; ENDLOOP; -- get loop ENDLOOP; RETURN WITH ERROR Error[IF channelAborted THEN aborted ELSE timeout]; END; -- WaitForRequestPacket WaitForRequest: PUBLIC PROCEDURE [h: ExchangeHandle, requestBlk: PrincOps.ByteBltBlock, requiredRequestType: OISCPTypes.ExchangeClientType] RETURNS [rH: PacketExchange.RequestHandle _ NIL] = BEGIN blkSizeOK: BOOLEAN; nBytes, blkByteLen: CARDINAL; requestB: BufferDefs.OisBuffer; requestB _ WaitForRequestPacket[h, requiredRequestType ! Error => BEGIN IF why=timeout THEN BEGIN SIGNAL Timeout; RETRY; -- caller RESUMEs => RETRY END; END]; nBytes _ requestB.ois.pktLength - bytesPerExchangePacketHeader; blkByteLen _ requestBlk.stopIndexPlusOne - requestBlk.startIndex; IF blkSizeOK _ ((nBytes<=blkByteLen) AND (requestBlk.startIndex<=requestBlk.stopIndexPlusOne)) THEN BEGIN rH _ NEW[PacketExchange.RequestObject]; rH^ _ [ nBytes: PrincOpsUtils.ByteBlt[requestBlk, [@requestB.ois.exchangeBody, 0, nBytes]], requestType: requestB.ois.exchangeType, requestersAddress: requestB.ois.source, requestersExchangeID: requestB.ois.exchangeID]; END; OISCP.ReturnFreeOisBuffer[requestB]; IF NOT blkSizeOK THEN RETURN WITH ERROR Error[blockTooSmall]; END; -- WaitForRequest SendReplyPacket: PUBLIC PROCEDURE [h: ExchangeHandle, replyB: BufferDefs.OisBuffer] = BEGIN channelAborted: BOOLEAN _ FALSE; Socket.PutPacket[h.cH, replyB! Socket.ChannelAborted => BEGIN replyB.requeueProcedure[replyB]; channelAborted _ TRUE; CONTINUE; END]; IF channelAborted THEN RETURN WITH ERROR Error[aborted]; END; -- SendReplyPacket SendReply: PUBLIC PROCEDURE [h: ExchangeHandle, rH: PacketExchange.RequestHandle, replyBlk: PrincOps.ByteBltBlock, replyType: OISCPTypes.ExchangeClientType] = BEGIN replyB: BufferDefs.OisBuffer; blkByteLen: CARDINAL _ replyBlk.stopIndexPlusOne-replyBlk.startIndex; IF blkByteLen>PacketExchange.maxBlockLength THEN RETURN WITH ERROR Error[blockTooBig]; replyB _ OISCP.GetFreeSendOisBufferFromPool[h.sendBufferAccessHandle]; replyB.ois.pktLength _ bytesPerExchangePacketHeader + blkByteLen; replyB.ois.transCntlAndPktTp.packetType _ packetExchange; replyB.ois.destination _ rH.requestersAddress; replyB.ois.exchangeType _ replyType; replyB.ois.exchangeID _ rH.requestersExchangeID; [] _ PrincOpsUtils.ByteBlt[[@replyB.ois.exchangeBody, 0, blkByteLen], replyBlk]; SendReplyPacket[h, replyB ! Error => IF why=aborted THEN OISCP.ReturnFreeOisBuffer[replyB]]; END; -- SendReply Create: PUBLIC PROCEDURE [localSocket: NSAddress.SocketNumber, receiveRequestCount: CARDINAL, privateBuffers: BOOLEAN, waitTime: OISCPTypes.WaitTime] RETURNS [h: ExchangeHandle] = BEGIN sendRequestCount: CARDINAL = 1; me: NetworkAddress = [OISCP.unknownNetID, Router.FindMyHostID[], localSocket]; h _ NEW[PacketExchangeObject]; h.sendBufferAccessHandle _ BufferDefs.MakeBufferPool[sendRequestCount, sendRequestCount, 0, 0, FALSE]; h.cH _ Socket.Create[me, 0, receiveRequestCount, 0, privateBuffers]; Socket.SetWaitTime[h.cH, (waitTime/retryCount)+1]; END; -- CreateInternal CreateRequestor: PUBLIC PROCEDURE [waitTime: OISCPTypes.WaitTime] RETURNS [h: ExchangeHandle] = BEGIN me: NetworkAddress _ Socket.AssignNetworkAddress[]; h _ Create[me.socket, 2, TRUE, waitTime]; END; CreateReplyer: PUBLIC PROCEDURE [localSocket: NSAddress.SocketNumber, requestCount: CARDINAL, waitTime: OISCPTypes.WaitTime] RETURNS [h: ExchangeHandle] = BEGIN h _ Create[localSocket, requestCount, TRUE, waitTime]; END; Delete: PUBLIC PROCEDURE [h: ExchangeHandle] = BEGIN Socket.Abort[h.cH]; BufferDefs.FreeBufferPool[h.sendBufferAccessHandle]; Socket.Delete[h.cH]; END; -- Delete SetWaitTime: PUBLIC PROCEDURE [h: ExchangeHandle, waitTime: OISCPTypes.WaitTime] = BEGIN Socket.SetWaitTime[h.cH, (waitTime/retryCount)+1]; END; -- SetWaitTime Process.InitializeCondition[@sendCompleted, Process.MsecToTicks[2000]]; END.\795t10 12t0 61t10 6t0 105b18B225i572I568i1bI7B24b5B57b28B24b17B160b19B162b10B115i156bI17B171b17B585i13I114i1I1031i18I224i21I3b12B868i89I63i1I109i4I2i61I35i67I11i2I2i46I553i16I3b21B193i13I528i12I92i24I3b15B2t10 7t0 378i39I35i28I12i50I682i18I6i68bI15B335i20bI1Bi61bI9B420i35I474i13I6t10b6B33t0 14t10 47t0 14t10 13t0 29t10 13t0 17t10 1t0 13t10 26t0 73t10 11t0 84t10 10t0 16t10 47t0 28t10 29t0 76i5t10 15t0I1t10b15B19t0 32t10 9t0 17t10 1t0 71t10 6t0 40t10b13B1i1I31t0 14t10 36t0 33t10 1t0 2t10 10t0 17t10 1t0 17t10 6t0 1t10 11t0 2t10 14t0 24i1I1t10b6B20t0 17t10 29t0 2t10 16t0 14t10 3t0 22t10 21t0 2t10 3t0 23t10 5t0 1i4t10 6t0I2i1I1t10b11B20t0 48t10 12t0 53t10 5t0 1i4t10 30t0I7t10 1t0 19t10 1t0 41t10 3t0 LOG Time: November 10, 1980 9:57 AM By: Dalal Action: created file. Time: January 13, 1981 6:06 PM By: BLyon Action: Moved to Pilot Communication. \1i NPacketExchangeImpl.mesa Copyright c 1985 by Xerox Corporation. All rights reserved. BLyon March 2, 1981 11:43 AM Levin, August 9, 1983 9:18 am The Packet Exchange Protocol is a request/reply protocol that provides a little more reliability than raw packets transmitetd from a socket, and less reliabilty than the Sequenced Packet Protocol. Usually one end will provide some service at a well known socket or at a network address that is available through a binding process involving the Clearinghouse. The other end acquires a socket and sends a request. The request will be retransmitted a number of times with the interval between retransmissions based on the delay to the remote entity. Caller has responsibility for returning requestB , and replyB if not NIL. The pktLength, destination and exchangeType must be set by the caller. move all info into the requestB send the buffer (many times in case of timeouts) and extract info from reply buffer. inside catch phrases geneated new signal and catch RESUME all other error shot through to the client; the compiler should love this: all other error shot through to the client; The length must be set by the caller. We now own buffer replyB. we now own rH and we if no errors are encountered free it move all info into the replyB Heap.FreeNode[p: rH];-- Heap.FreeNode[p: h];-- MainLine Code Κ :˜codešœ™Kšœ Οmœ1™˜EKšžœž˜)—K˜KšœT™TKšœT™TKšœJ™JKšœM™MKšœQ™QKšœO™OKšœ@™@K˜Kšœžœžœ˜7Kšœžœžœ˜0šœžœžœžœ˜,K˜K˜7K˜—Kšœž œ˜Kšœžœ/˜KKšœžœ˜Kšœ žœ˜Kšœ žœ˜Kšœ žœ˜KšœžœD˜jK˜Kšœ žœžœžœ˜Kšœžœžœ%žœ˜=Kšœžœžœžœ˜2K˜šΟnœžœž œžœ˜XKšž˜Kšžœžœ9˜EKšžœ˜K˜—šŸœžœžœž œ˜EKšž˜K˜K˜ Kšž œ˜Kšžœ˜K˜—šŸ œžœž œ˜6Kšž˜K˜0Kšžœ˜K˜—Kšœ2™2KšœP™PKšœ™šŸœžœž œ4˜WK˜+Kšžœ!˜(Kšž˜K˜šŸœžœž œ$žœ ˜mKšžœž˜ šžœ)ž˜0Kšžœ˜Kšžœ˜—Kšžœžœ˜$Kšžœ˜K˜—Kšœžœžœ˜ K˜"Kšœžœžœ"˜5Kšœžœ#˜:Kšœžœ"˜9K˜;K˜%šžœžœΟc ˜'Kšœ žœ˜ K˜0K˜&˜:Kšž˜K˜#Kšœžœ˜Kšžœ˜Kšžœ˜—šžœžœ˜(šœžœ '˜=˜ Kšœžœ˜˜Kšž˜Kšœžœ˜Kšžœ˜Kšžœ˜——Kšžœ7˜9Kšžœ!˜$Kšžœ(žœ˜Hšžœ9ž˜>K˜>—Kšžœ:žœž˜Hšž˜Kšž˜Kšžœ˜"Kšœ žœ˜ Kšžœ˜—Kšžœ ˜—Kšœžœžœžœ˜BKšžœžœžœžœ˜4—Kšžœ˜—Kš žœžœžœžœžœ žœ ˜EKšžœ ˜K˜—šŸ œžœž œ,˜IK˜,K˜+Kšžœ žœ-˜FKšž˜Kšœ žœ˜K˜'Kšœ žœ5˜IKš žœ*žœžœžœžœ˜VKšœ žœ8˜HKšœ™K˜CK˜;K˜"K˜(K˜TK˜KšœT™TKšžœžœžœžœ˜<˜3Kšœ ž˜Kšžœ ž˜šž˜Kšœ:™:Kšžœ ˜Kšžœ A˜IKšž˜—Kšœ+™+Kšžœ˜—Kšžœ˜K˜Kšžœ˜$K˜$K˜=K˜=Kšžœ#˜%Kšžœ2˜5KšžœU˜YKšžœ˜"šžœžœ ž˜Kšž˜K˜ Kšžœžœžœ˜'Kšžœ˜—Kšžœ ˜K˜—šŸœžœž œ=žœ#˜Kšž˜Kšœžœžœ˜ šžœžœ  ˜'Kšœ žœ˜šžœ '˜+˜"Kšœžœ˜˜Kšž˜Kšœžœ˜Kšžœ˜Kšžœ˜——Kšžœ9˜;Kšžœ&žœžœž˜Nšž˜Kšž˜Kšžœ˜$Kšœ žœ˜Kšžœ˜—Kšžœ  ˜—Kšžœ˜—Kš žœžœžœžœžœ žœ ˜EKšžœ ˜K˜—šŸœžœž œ7˜WK˜3Kšžœ%žœ˜2Kšž˜Kšœ žœ˜Kšœžœ˜K˜˜6Kšœ ž˜šžœ ž˜Kšž˜Kšœ™Kšžœ ˜Kšžœ ˜"Kšžœ˜—Kšœ+™+Kšžœ˜—K˜?K˜AKšžœ"˜$šžœ7ž˜>Kšž˜Kšœžœ˜'˜K˜SK˜'K˜'K˜/—Kšžœ˜—Kšžœ˜$Kš žœžœ žœžœžœžœ˜=Kšžœ ˜K˜—Kšœ@™@šŸœžœž œ4˜UKšž˜Kšœžœžœ˜ ˜7Kšž˜K˜ Kšœžœ˜Kšžœ˜ Kšžœ˜—Kš žœžœžœžœžœ˜8Kšžœ ˜K˜—Kšœ9™9šŸ œžœž œƒ˜žKšž˜K˜Kšœ žœ1˜EKš žœ*žœžœžœžœ˜VKšœ žœ8˜FKšœ™K˜AK˜9K˜.K˜$K˜0K˜P˜Kšœ žœ žœžœ˜B—Kšœ™Kšžœ ˜K˜—šŸœžœž œ&˜>Kšœžœžœ˜7K˜Kšžœ˜Kšž˜Kšœžœ˜Kšœžœ3˜NKšœžœ˜Kšœ_žœ˜fK˜DK˜2Kšžœ ˜K˜—šŸœžœž œ!žœ˜_Kšž˜K˜3Kšœžœ ˜)Kšžœ˜K˜—šŸ œžœž œ5žœ˜]K˜Kšžœ˜Kšž˜Kšœ&žœ ˜6Kšžœ˜K˜—šŸœžœž œ˜.Kšž˜K˜K˜4K˜Kšœ™Kšžœ  ˜K˜K˜—šŸ œžœž œ5˜RKšž˜K˜2Kšžœ ˜K˜—Kšœ ™ K˜GK˜KšžœΑ˜ΔK˜Kšž˜K˜Kšœžœ"˜BKšœžœ2˜QK˜K˜—…—+ˆ<