<> <> <> <> <> <<>> DIRECTORY Basics USING [FWORD, HWORD, LongNumber, Word16], IO USING [GetChar, GetFWord, GetHWord, PutChar, STREAM], Rope USING [ROPE]; CrRPC: CEDAR DEFINITIONS IMPORTS IO ~ { <> <> <<>> <> <<$SPP gets you "official" Courier. This uses SPP streams for its transport and supports bulk data transfer, but does not allow broadcast calls.>> <> <<>> <> <> HWORD: TYPE ~ Basics.HWORD; FWORD: TYPE ~ Basics.FWORD; ROPE: TYPE ~ Rope.ROPE; STREAM: TYPE ~ IO.STREAM; <> Handle: TYPE ~ REF Object; <> RefAddress: TYPE ~ REF; <> HandleClass: TYPE ~ ATOM; <> HandleKind: TYPE ~ { client, server }; <> CreateClientHandle: PROC [class: HandleClass, remote: RefAddress] RETURNS [Handle]; <> <> DestroyProc: TYPE ~ PROC [h: Handle]; DestroyClientHandle: DestroyProc ~ INLINE { h.procs.destroy[h] }; SetParametersProc: TYPE ~ PROC [h: Handle, op: ATOM, argument: REF] RETURNS [hNew: Handle, result: REF]; SetParameters: SetParametersProc ~ INLINE { [hNew, result] ¬ h.procs.setParameters[h, op, argument] }; <> <> PutArgsProc: TYPE ~ PROC [h: Handle, s: STREAM]; <> <> GetResultsProc: TYPE ~ PROC [h: Handle, s: STREAM]; <> <> GetErrorProc: TYPE ~ PROC [h: Handle, s: STREAM, errNum: CARDINAL]; <> <> CallProc: TYPE ~ PROC [ h: Handle, remotePgm: CARD32, remotePgmVersion: CARD16, remoteProc: CARD16, putArgs: PutArgsProc ¬ NIL, getResults: GetResultsProc ¬ NIL, getError: GetErrorProc ¬ NIL]; <> <> <<(1) call putArgs to stuff the arguments.>> <<(2) send the call message.>> <<(3) get the reply; if it's a normal return then call getResults, otherwise ERROR Error[...].>> <> <> Call: CallProc ~ INLINE { h.procs.call[h, remotePgm, remotePgmVersion, remoteProc, putArgs, getResults, getError] }; <> ServerProc: TYPE ~ PROC [ h: Handle, s: STREAM, pgm: CARD32, pgmVersion: CARD16, proc: CARD16, beginReturn: BeginReturnProc, beginError: BeginErrorProc, beginReject: BeginRejectProc ]; <> BeginReturnProc: TYPE ~ PROC [h: Handle]; <> BeginErrorProc: TYPE ~ PROC [h: Handle, errNum: CARDINAL]; <> BeginRejectProc: TYPE ~ PROC [h: Handle, rejectReason: CARDINAL ¬ noSuchProcedure]; <> <> noSuchProgram: CARD16 ~ 0; noSuchVersion: CARD16 ~ 1; noSuchProcedure: CARD16 ~ 2; invalidArgument: CARD16 ~ 3; unspecifiedReject: CARD16 ~ CARD16.LAST; StopServerQueryProc: TYPE ~ PROC [h: Handle] RETURNS [pleaseStop: BOOL]; <> RegisterServerProcs: PROC [ pgm: CARD32, pgmLoVersion: CARD16, pgmHiVersion: CARD16, serverProc: ServerProc, stopServerQueryProc: StopServerQueryProc ¬ NIL ]; <> StartServerInstance: PROC [ pgm: CARD32, pgmVersion: CARD16, class: HandleClass ¬ NIL, local: RefAddress ¬ NIL]; <> EnsureListener: PROC [ class: HandleClass, local: RefAddress ¬ NIL]; <> <> GetByte: PROC [s: STREAM] RETURNS [BYTE] ~ INLINE { RETURN [LOOPHOLE[IO.GetChar[s]]] }; GetChar: PROC [s: STREAM] RETURNS [CHAR] ~ INLINE { RETURN [IO.GetChar[s]] }; GetHWord: PROC [s: STREAM] RETURNS [hWord: HWORD] ~ INLINE { RETURN[IO.GetHWord[s]] }; GetCard16: PROC [s: STREAM] RETURNS [CARD16] ~ INLINE { buf: Basics.Word16; buf.hi ¬ ORD[IO.GetChar[s]]; buf.lo ¬ ORD[IO.GetChar[s]]; RETURN [buf.card] }; GetInt16: PROC [s: STREAM] RETURNS [INT16] ~ INLINE { buf: Basics.Word16; buf.hi ¬ ORD[IO.GetChar[s]]; buf.lo ¬ ORD[IO.GetChar[s]]; RETURN [buf.int] }; GetBool: PROC [s: STREAM] RETURNS [BOOL] ~ INLINE { [] ¬ IO.GetChar[s]; RETURN [ORD[IO.GetChar[s]] # 0] }; GetFWord: PROC [s: STREAM] RETURNS [fWord: FWORD] ~ INLINE { RETURN[IO.GetFWord[s]] }; GetCard32: PROC [s: STREAM] RETURNS [CARD32] ~ INLINE { buf: Basics.LongNumber; buf.hh ¬ ORD[IO.GetChar[s]]; buf.hl ¬ ORD[IO.GetChar[s]]; buf.lh ¬ ORD[IO.GetChar[s]]; buf.ll ¬ ORD[IO.GetChar[s]]; RETURN [buf.lc] }; GetInt32: PROC [s: STREAM] RETURNS [INT32] ~ INLINE { buf: Basics.LongNumber; buf.hh ¬ ORD[IO.GetChar[s]]; buf.hl ¬ ORD[IO.GetChar[s]]; buf.lh ¬ ORD[IO.GetChar[s]]; buf.ll ¬ ORD[IO.GetChar[s]]; RETURN [buf.li] }; PutByte: PROC [s: STREAM, byte: BYTE] ~ INLINE { IO.PutChar[s, LOOPHOLE[byte]] }; PutChar: PROC [s: STREAM, char: CHAR] ~ INLINE { IO.PutChar[s, char] }; PutHWord: PROC [s: STREAM, hWord: HWORD] ~ INLINE { IO.PutChar[s, VAL[hWord.hi]]; IO.PutChar[s, VAL[hWord.lo]] }; PutCard16: PROC [s: STREAM, card16: CARD16] ~ INLINE { buf: Basics.Word16; buf.card ¬ card16; IO.PutChar[s, VAL[buf.hi]]; IO.PutChar[s, VAL[buf.lo]] }; PutInt16: PROC [s: STREAM, int16: INT16] ~ INLINE { buf: Basics.Word16; buf.int ¬ int16; IO.PutChar[s, VAL[buf.hi]]; IO.PutChar[s, VAL[buf.lo]] }; PutBool: PROC [s: STREAM, bool: BOOL] ~ INLINE { IO.PutChar[s, VAL[0]]; IO.PutChar[s, IF bool THEN VAL[1] ELSE VAL[0]] }; PutFWord: PROC [s: STREAM, fWord: FWORD] ~ INLINE { IO.PutChar[s, VAL[fWord.hi.hi]]; IO.PutChar[s, VAL[fWord.hi.lo]]; IO.PutChar[s, VAL[fWord.lo.hi]]; IO.PutChar[s, VAL[fWord.lo.lo]] }; PutCard32: PROC [s: STREAM, card32: CARD32] ~ INLINE { buf: Basics.LongNumber; buf.lc ¬ card32; IO.PutChar[s, VAL[buf.hh]]; IO.PutChar[s, VAL[buf.hl]]; IO.PutChar[s, VAL[buf.lh]]; IO.PutChar[s, VAL[buf.ll]] }; PutInt32: PROC [s: STREAM, int32: INT32] ~ INLINE { buf: Basics.LongNumber; buf.li ¬ int32; IO.PutChar[s, VAL[buf.hh]]; IO.PutChar[s, VAL[buf.hl]]; IO.PutChar[s, VAL[buf.lh]]; IO.PutChar[s, VAL[buf.ll]] }; SeqHWord: TYPE ~ REF SeqHWordObject; SeqHWordObject: TYPE ~ MACHINE DEPENDENT RECORD [ body: PACKED SEQUENCE length: CARD16 OF HWORD ]; GetSeqHWord: PROC [s: STREAM] RETURNS [seqHWord: SeqHWord]; PutSeqHWord: PROC [s: STREAM, seqHWord: SeqHWord]; SkipSeqHWord: PROC [s: STREAM]; SeqCard16: TYPE ~ REF SeqCard16Object; SeqCard16Object: TYPE ~ MACHINE DEPENDENT RECORD [ body: PACKED SEQUENCE length: CARD16 OF CARD16 ]; GetSeqCard16: PROC [s: STREAM] RETURNS [seqCard16: SeqCard16]; PutSeqCard16: PROC [s: STREAM, seqCard16: SeqCard16]; SkipSeqCard16: PROC [s: STREAM]; GetRope: PROC [s: STREAM] RETURNS [rope: ROPE]; PutRope: PROC [s: STREAM, rope: ROPE]; SkipRope: PROC [s: STREAM]; MarshalledRopeHWords: PROC [rope: ROPE] RETURNS [hWords: CARDINAL]; <> <> <<>> BulkDataCheckAbortProc: TYPE ~ PROC [h: Handle] RETURNS [abort: BOOL]; BulkDataXferProc: TYPE ~ PROC [h: Handle, s: STREAM, checkAbort: BulkDataCheckAbortProc] RETURNS [abort: BOOL]; <> BulkDataSource: TYPE ~ BulkDataXferProc; BulkDataSink: TYPE ~ BulkDataXferProc; <> <<>> <> GetBulkDataXferProcProc: TYPE ~ PROC [h: Handle, s: STREAM] RETURNS [BulkDataXferProc]; GetBulkDataSource: GetBulkDataXferProcProc; <<~ INLINE { RETURN [h.procs.getBulkDataSource[h, s] };>> GetBulkDataSink: GetBulkDataXferProcProc; <<~ INLINE { RETURN [h.procs.getBulkDataSink[h, s] };>> PutBulkDataXferProcProc: TYPE ~ PROC [h: Handle, s: STREAM, proc: BulkDataXferProc]; PutBulkDataSource: PutBulkDataXferProcProc ~ INLINE { h.procs.putBulkDataSource[h, s, proc] }; PutBulkDataSink: PutBulkDataXferProcProc ~ INLINE { h.procs.putBulkDataSink[h, s, proc] }; <> <> <> BulkDataValueProc: TYPE ~ PROC [s: STREAM] RETURNS [abort: BOOL ¬ FALSE]; <> <> <> ReadBulkDataStreamProc: TYPE ~ PROC [h: Handle, s: STREAM, checkAbort: BulkDataCheckAbortProc, readValue: BulkDataValueProc] RETURNS [abort: BOOL]; ReadBulkDataStream: ReadBulkDataStreamProc ~ INLINE { RETURN [h.procs.readBulkDataStream[h, s, checkAbort, readValue]] }; <> <> <> <<>> <> <> <> <> <<...>> <> <> <<};>> WriteBulkDataSegmentProc: TYPE ~ PROC [h: Handle, s: STREAM, checkAbort: BulkDataCheckAbortProc, writeValue: BulkDataValueProc, n: CARDINAL ¬ 1] RETURNS [abort: BOOL, heAborted: BOOL]; WriteBulkDataSegment: WriteBulkDataSegmentProc ~ INLINE { [abort, heAborted] ¬ h.procs.writeBulkDataSegment[h, s, checkAbort, writeValue, n] }; <> < 0: first writes the header of a streamOfT element of type nextSegment with count n; then calls the BulkDataValueProc n times to fill in the data.>> <> <<>> <> <> <> <> <> <> <> <> <<[heAborts, abort] _ WriteBulkDataSegment[h, s, checkAbort, WriteTheShortInteger];>> <> <> <> <<};>> <> <> <<>> <> ContinuationProc: TYPE ~ PROC [s: STREAM, clientData: REF] RETURNS [STREAM]; <> <> CallContinuationProc: TYPE ~ PROC [h: Handle, proc: ContinuationProc, clientData: REF]; CallContinuation: CallContinuationProc ~ INLINE { h.procs.callContinuation[h, proc, clientData] }; <> <> <> <<>> SetContinuationProc: TYPE ~ PROC [h: Handle, proc: ContinuationProc, clientData: REF]; SetContinuation: SetContinuationProc ~ INLINE { h.procs.setContinuation[h, proc, clientData] }; <> <> <> <> Error: ERROR [h: Handle, errorReason: ErrorReason, text: ROPE]; ErrorReason: TYPE ~ { <> unknown, <> unknownClass, courierVersionMismatch, rejectedNoSuchProgram, rejectedNoSuchVersion, rejectedNoSuchProcedure, rejectedInvalidArgument, rejectedUnspecified, remoteError, cantConnectToRemote, <> argsError, resultsError, bulkDataError, protocolError, remoteClose, communicationFailure, notImplemented, unknownOperation, <> notServerHandle, notClientHandle, <
> addressInappropriateForClass, <> other }; <> Object: TYPE ~ RECORD [ class: HandleClass, kind: HandleKind, procs: REF ProcsObject, data: REF, -- private, for use by implementor clientData: REF -- public, for use by client ]; ProcsObject: TYPE ~ RECORD [ destroy: DestroyProc, setParameters: SetParametersProc, call: CallProc, getBulkDataSource: GetBulkDataXferProcProc, getBulkDataSink: GetBulkDataXferProcProc, putBulkDataSource: PutBulkDataXferProcProc, putBulkDataSink: PutBulkDataXferProcProc, readBulkDataStream: ReadBulkDataStreamProc, writeBulkDataSegment: WriteBulkDataSegmentProc, callContinuation: CallContinuationProc, setContinuation: SetContinuationProc, finalize: PROC [Handle] RETURNS[renewHandle: BOOL] -- true if want to reuse handle ]; }.