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