<> <> <> <<>> <> DIRECTORY Endian USING [BYTE, CardFromF, CardFromH, FFromCard, FWORD, HFromCard, HWORD], IO USING [STREAM, UnsafeBlock], XNS USING [Address, Socket, unknownSocket], Rope USING [ROPE]; CrRPC: CEDAR DEFINITIONS IMPORTS Endian ~ { <> <> <<>> <> <<$SPP gets you "official" Courier. This uses SPP streams for its transport and supports bulk data transfer, but does not allow broadcast calls.>> <<$EXCHANGE gets you "expedited" Courier. This uses (unreliable) packet exchange for transport, requires that each argument or result record fit in a single packet, and has no support for bulk data transfer, but does allow broadcast calls.>> <> <<>> <> <> BYTE: TYPE ~ Endian.BYTE; FWORD: TYPE ~ Endian.FWORD; HWORD: TYPE ~ Endian.HWORD; ROPE: TYPE ~ Rope.ROPE; <> Handle: TYPE ~ REF Object; <> HandleClass: TYPE ~ ATOM; <> HandleKind: TYPE ~ { client, server }; <> CreateClientHandle: PROC [ class: HandleClass, remote: XNS.Address, timeoutMsec: INT _ 0 ] RETURNS [Handle]; <> <> DestroyClientHandle: PROC [h: Handle]; <> SetRemote: PROC [h: Handle, remote: XNS.Address] RETURNS [Handle]; <> <> SetTimeout: PROC [h: Handle, timeoutMsec: INT _ 0] RETURNS [Handle]; <> <> SetHops: PROC [h: Handle, low, high: NAT] RETURNS [Handle]; <> <> PutArgsProc: TYPE ~ PROC [h: Handle]; <> <> GetResultsProc: TYPE ~ PROC [h: Handle]; <> <> GetErrorProc: TYPE ~ PROC [h: Handle, errNum: CARDINAL]; <> <> CallProc: TYPE ~ PROC [ h: Handle, remotePgm: CARD, remotePgmVersion: CARDINAL, remoteProc: CARDINAL, putArgs: PutArgsProc _ NIL, getResults: GetResultsProc _ NIL, getError: GetErrorProc _ NIL]; <> <> <<(1) call putArgs to stuff the arguments.>> <<(2) send the call message.>> <<(4) get the reply; if it's a normal return then call getResults, otherwise ERROR Error[...].>> <> <> Call: CallProc; <> ServerProc: TYPE ~ PROC [ h: Handle, pgm: CARD, pgmVersion: CARDINAL, proc: CARDINAL, beginReturn: BeginReturnProc, beginError: BeginErrorProc, beginReject: BeginRejectProc ]; <> BeginReturnProc: TYPE ~ PROC [h: Handle]; <> BeginErrorProc: TYPE ~ PROC [h: Handle, errNum: CARDINAL]; <> <> noSuchProgram: CARDINAL ~ 0; noSuchVersion: CARDINAL ~ 1; noSuchProcedure: CARDINAL ~ 2; invalidArgument: CARDINAL ~ 3; unspecifiedReject: CARDINAL ~ 0ffffH; BeginRejectProc: TYPE ~ PROC [h: Handle, rejectReason: CARDINAL _ noSuchProcedure]; <> RegisterServerProc: PROC [ pgm: CARD, pgmVersion: CARDINAL, serverProc: ServerProc]; <> EnsureListener: PROC [ class: HandleClass, socket: XNS.Socket _ XNS.unknownSocket]; <> GetRemote: PROC [h: Handle] RETURNS [remote: XNS.Address]; <> <> GetBYTE: PROC [h: Handle] RETURNS [BYTE] ~ INLINE { RETURN [h.marshallProcs.getB[h]] }; GetCHAR: PROC [h: Handle] RETURNS [CHAR] ~ TRUSTED INLINE { RETURN [LOOPHOLE[h.marshallProcs.getB[h]]] }; GetHWORD: PROC [h: Handle] RETURNS [HWORD] ~ INLINE { RETURN [h.marshallProcs.getH[h]] }; GetBOOL: PROC [h: Handle] RETURNS [BOOL] ~ INLINE { RETURN [Endian.CardFromH[h.marshallProcs.getH[h]] # 0] }; GetCARDINAL: PROC [h: Handle] RETURNS [CARDINAL] ~ INLINE { RETURN [Endian.CardFromH[h.marshallProcs.getH[h]]] }; GetINTEGER: PROC [h: Handle] RETURNS [INTEGER] ~ TRUSTED INLINE { RETURN [LOOPHOLE[Endian.CardFromH[h.marshallProcs.getH[h]]]] }; GetFWORD: PROC [h: Handle] RETURNS [FWORD] ~ INLINE { RETURN [h.marshallProcs.getF[h]] }; GetCARD: PROC [h: Handle] RETURNS [CARD] ~ INLINE { RETURN [Endian.CardFromF[h.marshallProcs.getF[h]]] }; GetINT: PROC [h: Handle] RETURNS [INT] ~ TRUSTED INLINE { RETURN [LOOPHOLE[Endian.CardFromF[h.marshallProcs.getF[h]]]] }; UnsafeGetBlock: UNSAFE PROC [h: Handle, block: IO.UnsafeBlock] RETURNS [nBytesRead: INT] ~ TRUSTED INLINE { RETURN [h.marshallProcs.unsafeGetBlock[h, block]] }; GetHAlign: PROC [h: Handle] ~ INLINE { h.marshallProcs.getHAlign[h] }; PutBYTE: PROC [h: Handle, byte: BYTE] ~ INLINE { h.marshallProcs.putB[h, byte] }; PutCHAR: PROC [h: Handle, byte: CHAR] ~ TRUSTED INLINE { h.marshallProcs.putB[h, LOOPHOLE[byte]] }; PutHWORD: PROC [h: Handle, hWord: HWORD] ~ INLINE { h.marshallProcs.putH[h, hWord] }; PutBOOL: PROC [h: Handle, bool: BOOL] ~ INLINE { h.marshallProcs.putH[h, Endian.HFromCard[IF bool THEN 1 ELSE 0]] }; PutCARDINAL: PROC [h: Handle, cardinal: CARDINAL] ~ INLINE { h.marshallProcs.putH[h, Endian.HFromCard[cardinal]] }; PutINTEGER: PROC [h: Handle, integer: INTEGER] ~ TRUSTED INLINE { h.marshallProcs.putH[h, Endian.HFromCard[LOOPHOLE[integer]]] }; PutFWORD: PROC [h: Handle, fWord: FWORD] ~ INLINE { h.marshallProcs.putF[h, fWord] }; PutCARD: PROC [h: Handle, card: CARD] ~ INLINE { h.marshallProcs.putF[h, Endian.FFromCard[card]] }; PutINT: PROC [h: Handle, int: INT] ~ TRUSTED INLINE { h.marshallProcs.putF[h, Endian.FFromCard[LOOPHOLE[int]]] }; UnsafePutBlock: UNSAFE PROC [h: Handle, block: IO.UnsafeBlock] ~ TRUSTED INLINE { h.marshallProcs.unsafePutBlock[h, block] }; PutHAlign: PROC [h: Handle] ~ INLINE { h.marshallProcs.putHAlign[h] }; SeqHWORD: TYPE ~ REF SeqHWORDObject; SeqHWORDObject: TYPE ~ MACHINE DEPENDENT RECORD [ body: PACKED SEQUENCE length: CARDINAL OF HWORD ]; GetSeqHWORD: PROC [h: Handle] RETURNS [seqHWORD: SeqHWORD]; PutSeqHWORD: PROC [h: Handle, seqHWORD: SeqHWORD]; SkipSeqHWORD: PROC [h: Handle]; SeqCARDINAL: TYPE ~ REF SeqCARDINALObject; SeqCARDINALObject: TYPE ~ MACHINE DEPENDENT RECORD [ body: PACKED SEQUENCE length: CARDINAL OF HWORD ]; GetSeqCARDINAL: PROC [h: Handle] RETURNS [seqCARDINAL: SeqCARDINAL]; PutSeqCARDINAL: PROC [h: Handle, seqCARDINAL: SeqCARDINAL]; SkipSeqCARDINAL: PROC [h: Handle]; GetROPE: PROC [h: Handle] RETURNS [rope: ROPE]; PutROPE: PROC [h: Handle, rope: ROPE]; SkipROPE: PROC [h: Handle]; MarshalledROPEHWords: PROC [rope: ROPE] RETURNS [hWords: CARDINAL]; <> BulkDataCheckAbortProc: TYPE ~ PROC [h: Handle] RETURNS [abort: BOOL]; BulkDataXferProc: TYPE ~ PROC [h: Handle, stream: IO.STREAM, checkAbort: BulkDataCheckAbortProc] RETURNS [abort: BOOL]; <> BulkDataSource: TYPE ~ BulkDataXferProc; BulkDataSink: TYPE ~ BulkDataXferProc; <> GetBulkDataSource: PROC [h: Handle] RETURNS [BulkDataSource]; <<~ INLINE { RETURN [h.marshallProcs.getBulkDataSource[h] };>> GetBulkDataSink: PROC [h: Handle] RETURNS [BulkDataSink]; <<~ INLINE { RETURN [h.marshallProcs.getBulkDataSink[h] };>> PutBulkDataSource: PROC [h: Handle, bulkDataSource: BulkDataSource] ~ INLINE { h.marshallProcs.putBulkDataSource[h, bulkDataSource] }; PutBulkDataSink: PROC [h: Handle, bulkDataSink: BulkDataSink] ~ INLINE { h.marshallProcs.putBulkDataSink[h, bulkDataSink] }; <> Error: ERROR [h: Handle, errorReason: ErrorReason, text: ROPE]; ErrorReason: TYPE ~ { <> unknown, <> unknownClass, courierVersionMismatch, argsTooLong, resultsTooShort, notImplemented, rejectedNoSuchProgram, rejectedNoSuchVersion, rejectedNoSuchProcedure, rejectedInvalidArgument, rejectedUnspecified, remoteError, <> timeout, protocolError, remoteClose, communicationFailure, <> notServerHandle, notClientHandle, notBroadcastHandle }; <> Object: TYPE ~ RECORD [ class: HandleClass, kind: HandleKind, marshallProcs: REF MarshallProcs, procs: REF ANY, -- really (REF ClientProcs) data: REF ANY, -- private, for use by implementor clientData: REF ANY -- public, for use by client ]; MarshallProcs: TYPE ~ RECORD [ putB: PROC [Handle, BYTE], putH: PROC [Handle, HWORD], putF: PROC [Handle, FWORD], unsafePutBlock: UNSAFE PROC [Handle, IO.UnsafeBlock], putBulkDataSource: PROC [Handle, BulkDataSource], putBulkDataSink: PROC [Handle, BulkDataSink], putHAlign: PROC [Handle], getB: PROC [Handle] RETURNS [BYTE], getH: PROC [Handle] RETURNS [HWORD], getF: PROC [Handle] RETURNS [FWORD], unsafeGetBlock: UNSAFE PROC [Handle, IO.UnsafeBlock] RETURNS [INT], getBulkDataSource: PROC [Handle] RETURNS [BulkDataSource], getBulkDataSink: PROC [Handle] RETURNS [BulkDataSink], getHAlign: PROC [Handle] ]; ClientProcs: TYPE ~ RECORD [ setRemote: PROC [Handle, XNS.Address] RETURNS [Handle], setTimeout: PROC [Handle, INT] RETURNS [Handle], setHops: PROC [Handle, NAT, NAT] RETURNS [Handle], destroy: PROC [Handle], finalize: PROC [Handle] _ NIL, call: CallProc ]; ServerProcs: TYPE ~ RECORD [ getRemote: PROC [Handle] RETURNS [XNS.Address] ]; }.