<> <> <> <> <> <> <> <<>> DIRECTORY PrincOpsUtils USING[ BITOR, Enter, Exit, HighHalf, LowHalf, MakeLongPointer ], RPC USING[ Conversation, EncryptionKey, InterfaceName, maxPrincipalLength, maxShortStringLength, Principal, unencrypted, VersionRange ], VM USING [AddressForPageNumber, PageCount, PageNumber, PageNumberForAddress, PagesForWords]; RPCLupine: DEFINITIONS IMPORTS PrincOpsUtils, VM = BEGIN <> PacketBufferLock: MONITORLOCK; <<>> -- Definitions copied across from RPC.mesa for Lupine's benefit maxPrincipalLength: CARDINAL = RPC.maxPrincipalLength; maxShortStringLength: CARDINAL = RPC.maxShortStringLength; <> <<>> <> <> <<>> <> <<>> <> <> Encapsulation: PRIVATE TYPE[7]; -- large enough for all current networks Header: PRIVATE TYPE[10+6+4]; <> maxPupWords: PRIVATE CARDINAL = <PupSpec.press -->> 266 -- Pup data -- + 10 -- Pup header -- + 1 -- Pup checksum --; encryptionBlockSize: PRIVATE CARDINAL = 4; SecurityChecksum: PRIVATE TYPE[2]; maxDataLength: CARDINAL = <> ( ( maxPupWords - 1 -- Pup checksum -- - SIZE[Header] ) / encryptionBlockSize --round down--) * encryptionBlockSize - SIZE[SecurityChecksum]; DataLength: TYPE = [0..maxDataLength]; pktOverhead: CARDINAL = pktAlign -- wastage for aligning the buffer -- + SIZE[StubPktData[0]] + encryptionBlockSize-1 -- rounding -- + SIZE[SecurityChecksum] + 1 -- Pup checksum --; pktAlign: PRIVATE WORD = 3B; -- maximum wastage for quad-word alignment StubPkt: TYPE = POINTER TO StubPktData; RPCPkt: TYPE = LONG StubPkt; StubPktData: TYPE = MACHINE DEPENDENT RECORD[ -- must be suitably aligned convHandle: PRIVATE RPC.Conversation, encapsulation: PRIVATE Encapsulation, header: PRIVATE Header, -- Pup/OIS header -- data: SEQUENCE COMPUTED DataLength OF UNSPECIFIED]; GetStubPkt: PROC[ space: POINTER TO UNSPECIFIED] RETURNS[--pkt:-- StubPkt ] = INLINE <> < result=1,>> < result=1,>> < result=5,>> < result=5.>> { RETURN[ LOOPHOLE[PrincOpsUtils.BITOR[LOOPHOLE[space, WORD]+2, pktAlign],POINTER]-2 ] }; GetPkt: PROC[ space: LONG POINTER TO UNSPECIFIED] RETURNS[--pkt:-- RPCLupine.RPCPkt ] = INLINE {RETURN[ LOOPHOLE[space+1]]}; <> GetRPCPkt: PROC[ space: LONG POINTER TO UNSPECIFIED] RETURNS[--pkt:-- RPCPkt ] = INLINE <> < result=1,>> < result=1,>> < result=5,>> < result=5.>> <> { RETURN[ PrincOpsUtils.MakeLongPointer[ low: LOOPHOLE[PrincOpsUtils.BITOR[LOOPHOLE[PrincOpsUtils.LowHalf[space+2], WORD], pktAlign] - 2], high: PrincOpsUtils.HighHalf[space+2] ]] }; -- Binding primitives for use by stubs -- <> <> <> ExportHandle: TYPE[SIZE[CARDINAL]]; -- index to table of dispatcher procedures ExportInterface: PROC[user: RPC.Principal, password: RPC.EncryptionKey, interface: RPC.InterfaceName, dispatcher: Dispatcher, stubProtocol: RPC.VersionRange, localOnly: BOOLEAN _ FALSE] RETURNS[ interfaceInstance: ExportHandle ]; <> UnexportInterface: PROC[ interfaceInstance: ExportHandle ] RETURNS[ExportHandle]; <> ImportHandle: TYPE = REF ImportInstance; ImportInstance: TYPE; ImportInterface: PROC[interface: RPC.InterfaceName, stubProtocol: RPC.VersionRange, localOnly: BOOLEAN _ FALSE] RETURNS[ interfaceInstance: ImportHandle ]; <> UnimportInterface: PROC[ interfaceInstance: ImportHandle ] RETURNS[ ImportHandle ]; <> <> <> <> <> <> <> <> StartCall: PROC[callPkt: RPCPkt, interface: ImportHandle, localConversation: RPC.Conversation _ RPC.unencrypted]; <> Call: PROC[pkt: RPCPkt, callLength: DataLength, maxReturnLength: DataLength, signalHandler: Dispatcher _ NIL] RETURNS[ returnLength: DataLength, lastPkt: BOOLEAN]; <> <> SendPrelimPkt: PROC[pkt: RPCPkt, length: DataLength]; <> ReceiveExtraPkt: PROC[prevPkt: RPCPkt] RETURNS[ length: DataLength, lastPkt: BOOLEAN]; <> Dispatcher: TYPE = PROC[pkt: RPCPkt, callLength: DataLength, lastPkt: BOOLEAN, localConversation: RPC.Conversation ] RETURNS[ returnLength: DataLength ]; <<"pkt" is the first argument packet. This must be passed to any calls of ReceiveExtraPkt or SendPrelimPkt; the stub leaves the last return pkt data in "pkt". "pkt" has maxlength = maxDataLength. The caller of the dispatcher will catch RPC.CallFailed -->> StartSignal: PROC[signalPkt: RPCPkt]; <> <> <> RejectUnbound: ERROR; <> RejectProtocol: ERROR; <> <> MaxPacketBufferListSize: INT = 7; -- Maximum size kept in the cache MaxPacketBufferIntervalInRec: INT = 10; PacketBufferCacheListRec: TYPE = RECORD [ prev: REF PacketBufferCacheListRec, next: REF PacketBufferCacheListRec _ NIL, putIndex: CARDINAL _ 1, intervalStarts: ARRAY [1..MaxPacketBufferIntervalInRec] OF VM.PageNumber _ ALL[0] ]; PacketBufferCacheList: ARRAY [1..MaxPacketBufferListSize] OF REF PacketBufferCacheListRec ; AllocInline: PROC [nWords: CARDINAL] RETURNS [address: LONG POINTER TO WORD] = INLINE { IF PrincOpsUtils.Enter[@PacketBufferLock] THEN { nPages: VM.PageCount = MAX[1, VM.PagesForWords[nWords]]; IF nPages <= MaxPacketBufferListSize THEN { putIndex: INT _ PacketBufferCacheList[nPages].putIndex; IF putIndex > 1 THEN { putIndex_ putIndex - 1; address _ VM.AddressForPageNumber[PacketBufferCacheList[nPages].intervalStarts[putIndex]]; PacketBufferCacheList[nPages].putIndex _ putIndex; PrincOpsUtils.Exit[@PacketBufferLock]; RETURN; }; }; PrincOpsUtils.Exit[@PacketBufferLock]; }; RETURN[Alloc[nWords]]; }; DeAllocInline: PROC [address: LONG POINTER TO WORD, nWords: CARDINAL] = INLINE { nPages: VM.PageCount = MAX[1, VM.PagesForWords[nWords]]; IF PrincOpsUtils.Enter[@PacketBufferLock] AND LOOPHOLE[address, INT] # 0 THEN { IF nPages <= MaxPacketBufferListSize THEN { putIndex: INT _ PacketBufferCacheList[nPages].putIndex; IF putIndex <= MaxPacketBufferIntervalInRec THEN { PacketBufferCacheList[nPages].intervalStarts[putIndex] _ VM.PageNumberForAddress[address]; PacketBufferCacheList[nPages].putIndex _ putIndex + 1; PrincOpsUtils.Exit[@PacketBufferLock]; RETURN; }; }; PrincOpsUtils.Exit[@PacketBufferLock]; }; DeAlloc[address, nWords]; }; Alloc: PROC [nWords: CARDINAL] RETURNS [address: LONG POINTER TO WORD] ; DeAlloc: PROC [address: LONG POINTER TO WORD, nWords: CARDINAL]; END. <<>> <<>> <> <> <<>> <<>>