Page Numbers:  Yes  X: 527  Y: 10.5"  First Page: 21Margins:  Top: 1" Bottom: .8"Heading:x0qck40(635)\f1gLupine User's GuideVersion 1.0y756x0qk40(1270)\bgAppendix A:  Public RPC Interfacesx0e36k511\f5bgThe following are the public interfaces to Lupine's RPC runtime, RPC.mesa and MesaRPC.mesa.  Small details are likely to have changed since this document was last edited, so remember that Lupine.df always refers to the latest version.d3422x6e6jk40\g-- RPC.mesa-- Andrew Birrell	 3-Dec-81 10:14:28-- BZM			29-Oct-81 11:46:31DIRECTORYRope		USING [ROPE],MesaRPC		USING [AuthenticateFailure, CallFailure, Conversation,		       ConversationID, ConversationLevel, EncryptionKey,		       EndConversation, ExportFailure, GetLevel, ImportFailure,		       GetConversationID, GenerateConversation, matchAllVersions,		       maxPrincipalLength, maxShortStringLength, SecurityLevel,		       ShortSTRING, unencrypted, VersionRange];RPC: DEFINITIONS  IMPORTS MesaRPC =  BEGIN-- Short string/rope/atom types. Used only by Lupine clients.  maxShortStringLength: CARDINAL = MesaRPC.maxShortStringLength;  -- maximum length of ShortSTRING/ShortROPE/ShortATOM values --  ShortSTRING: TYPE = MesaRPC.ShortSTRING;  ShortROPE: TYPE = Rope.ROPE;  ShortATOM: TYPE = ATOM;-- Types for Import and Export calls.  InterfaceName: TYPE = RECORD [	type: ShortROPE _ NIL,      -- e.g., "AlpineAccess.Alpine"	instance: ShortROPE _ NIL,  -- e.g., "MontBlanc.Alpine"	version: VersionRange _ matchAllVersions ];  defaultInterfaceName: InterfaceName = [];  VersionRange: TYPE = MesaRPC.VersionRange;  matchAllVersions: VersionRange = MesaRPC.matchAllVersions;-- Parameter storage zones.  Used only by Lupine clients.  Zones: TYPE = RECORD [	gc:   ZONE _ NIL,	heap: UNCOUNTED ZONE _ NIL,	mds:  MDSZone _ NIL ];  standardZones: Zones = [];  -- Encryption and Authentication facilities.  maxPrincipalLength: CARDINAL = MesaRPC.maxPrincipalLength;    -- Limit on length of ropes used for Principal names --  Principal: TYPE = ShortROPE;  EncryptionKey: TYPE = MesaRPC.EncryptionKey;  MakeKey: PROCEDURE [text: Rope.ROPE] RETURNS[EncryptionKey];  Conversation:	TYPE = MesaRPC.Conversation;    SecurityLevel: TYPE = MesaRPC.SecurityLevel;    ConversationLevel: TYPE = MesaRPC.ConversationLevel;  unencrypted: Conversation = MesaRPC.unencrypted;  GenerateConversation: PROC RETURNS[Conversation] = INLINE    { RETURN[ MesaRPC.GenerateConversation[] ] };  StartConversation: PROCEDURE[caller: Principal, key: EncryptionKey,			       callee: Principal,			       level: ConversationLevel ]                       RETURNS[conversation: Conversation];  EndConversation: PROCEDURE [conversation: Conversation] = INLINE    { MesaRPC.EndConversation[conversation] };   GetCaller: PROCEDURE [conversation: Conversation]               RETURNS [caller: Principal];   GetLevel: PROCEDURE [conversation: Conversation]               RETURNS [level: SecurityLevel] = INLINE    { RETURN[ MesaRPC.GetLevel[conversation] ] };  ConversationID: TYPE = MesaRPC.ConversationID;  GetConversationID: PROC[conversation: Conversation]	     RETURNS[id: ConversationID] = INLINE    { RETURN[ MesaRPC.GetConversationID[conversation] ] };-- Public signals:  AuthenticateFailure: TYPE = MesaRPC.AuthenticateFailure;  ExportFailure:       TYPE = MesaRPC.ExportFailure;  ImportFailure:       TYPE = MesaRPC.ImportFailure;  CallFailure:         TYPE = MesaRPC.CallFailure;  AuthenticateFailed: ERROR[why: AuthenticateFailure];    -- Raised by StartConversation --  ExportFailed: ERROR[why: ExportFailure];    -- Raised by ExportInterface --  ImportFailed: ERROR[why: ImportFailure];    -- Raised by ImportInterface --  CallFailed: SIGNAL[why: CallFailure];    -- Raised by any remote call; only why=timeout is resumable --END.d3008e12k40(1376)\f8-- MesaRPC.mesa-- Andrew Birrell	 3-Dec-81 10:12:00-- BZM			29-Oct-81 11:45:47DIRECTORYBodyDefs	USING[ maxRNameLength, Password ];MesaRPC: DEFINITIONS =  BEGIN-- Short string types. Used only by Lupine clients.  maxShortStringLength: CARDINAL = 64;  -- Maximum length of ShortSTRING values. --  ShortSTRING: TYPE = STRING;-- Types for Import/Export calls --  InterfaceName: TYPE = RECORD [	type:     LONG ShortSTRING _ NIL, -- e.g. "AlpineAccess.Alpine" --	instance: LONG ShortSTRING _ NIL, -- e.g. "MontBlanc.Alpine" --	version:  VersionRange _ matchAllVersions];  defaultInterfaceName: InterfaceName = [];  VersionRange: TYPE = MACHINE DEPENDENT RECORD[first, last: CARDINAL];    -- client-defined, closed interval --  matchAllVersions: VersionRange = [1,0];    -- importer: use any version;  exporter: no versioning implied ---- Parameter storage zones.  Used only by Lupine clients, not the runtime.  Zones: TYPE = RECORD [	heap: UNCOUNTED ZONE _ NIL,	mds:  MDSZone _ NIL ];  standardZones: Zones = [];  -- Encryption and Authentication facilities --  maxPrincipalLength: CARDINAL = MIN[maxShortStringLength,				     BodyDefs.maxRNameLength];    -- Limit on length of strings used for Principal --  Principal:	TYPE = LONG ShortSTRING;  -- Name of authentication principal --  EncryptionKey: TYPE = BodyDefs.Password;    -- DES key --  MakeKey: PROC[text: LONG STRING] RETURNS[EncryptionKey];  Conversation:	TYPE = LONG POINTER TO ConversationObject;  ConversationObject: PRIVATE TYPE;  SecurityLevel: TYPE = MACHINE DEPENDENT {        none(0),	-- unauthenticated, insecure; used for "unencrypted"        authOnly(1),	-- authenticated, but unencrypted calls        ECB(2),		-- authenticated, encrypt with ECB mode of DES        CBC(3),		-- authenticated, encrypt with CBC mode of DES        CBCCheck(4)	-- authenticated, encrypt with CBC mode of DES + checksum        };    ConversationLevel: TYPE = SecurityLevel[authOnly..CBCCheck];  unencrypted:	Conversation = NIL;    -- Dummy conversation; may be passed to RPC runtime.    --   GetConversationID[unencrypted] = ERROR;    --   GetCaller[unencrypted] = NIL;    --   GetLevel[unencrypted] = none; --  GenerateConversation: PROC RETURNS[Conversation];    -- Returns a handle for a previously unused Conversation.  This    -- conversation is only for local use, it must not be passed to    -- the RPC runtime.    --   GetConversationID[GenerateConversation[]] = unique ID;    --   GetCaller[GenerateConversation[]] = NIL;    --   GetLevel[GenerateConversation[]] = "none"; --  StartConversation: PROC[caller: Principal, key: EncryptionKey,			  callee: Principal,			  level: ConversationLevel]		  RETURNS[conversation: Conversation];    -- Obtains authenticator for conversation, registers it with runtime,    -- and allocates ConversationID --  EndConversation: PROC[conversation: Conversation];    -- Terminates use of this conversation --   GetCaller:	PROC[conversation: Conversation]	     RETURNS[caller: Principal];    -- Returns the caller name for a current call.  The result    -- string has lifetime at least equal to the duration of the    -- call.  Result is NIL if conversation's security level is "none" (including    -- conversation = "unencrypted"). --  GetLevel:	PROC[conversation: Conversation]	     RETURNS[level: SecurityLevel];  ConversationID: TYPE[3];    -- UID allocated by initiator host --  GetConversationID: PROC[conversation: Conversation]	     RETURNS[id: ConversationID];    -- Returns permanently unique ID of this conversation ---- Public signals --  AuthenticateFailure: TYPE = {  	communications,	-- couldn't contact authentication server(s) --	badCaller,	-- invalid caller name --	badKey,		-- incorrect caller password --	badCallee	-- invalid callee name --	};  ExportFailure: TYPE = {	communications, -- couldn't access binding database --	badType,	-- unacceptable interface type name --	badInstance,	-- unacceptable interface instance name --	badVersion,	-- statically silly version range --	tooMany,	-- too many exports for local tables --	badCredentials	-- not allowed to change the database --	};  ImportFailure: TYPE = {	communications, -- couldn't access binding database --	badType,	-- unacceptable interface type name --	badInstance,	-- unacceptable interface instance name --	badVersion,	-- statically silly version range --	wrongVersion,	-- exported version not in req'd range --	unbound,	-- this instance not exported --	stubProtocol	-- exporter protocol incompatible with importer --	};  CallFailure:	TYPE = {	timeout,	-- no acknowledgement within reasonable time --	unbound,	-- server no longer exports the interface --	busy,		-- server says it's too busy --	runtimeProtocol,-- user/server runtimes don't understand each other --	stubProtocol	-- user/server stubs don't understand each other --	};  AuthenticateFailed: ERROR[why: AuthenticateFailure];    -- Raised by StartConversation --  ExportFailed: ERROR[why: ExportFailure];    -- Raised by ExportInterface --  ImportFailed: ERROR[why: ImportFailure];    -- Raised by ImportInterface --  CallFailed:   SIGNAL[why: CallFailure];    -- Raised by any remote call; only why=timeout is resumable --END.d3008e12k792\f8Appendix B:  Example Remote Interface and Stubsx0e36k792(1270)\f5bgThere follows a very simple interface, Target.mesa, and its stub modules as an example.  Once again, small details may have changed, but this is unimportant since RPC programmers need not be concerned with stub implementations.  These modules are un-retouched output from the Lupine translator.d3422x6e6jk40\g39i11I-- Lupine: example interface-- Target.mesa-- Andrew Birrell  July 8, 1982 9:22 amDIRECTORYRope	USING[ ROPE ];Target: DEFINITIONS =BEGINBasic: PROC;Simple: PROC[first: INT, second: REF INT] RETURNS[a: Rope.ROPE, b: ATOM];Reason: TYPE = { x, y, z };Exception: ERROR[why: Reason];Consultation: SIGNAL;END.d3008e12(1376)\f8-- Stub file TargetRpcControl.mesa was translated on  8-Jul-82  9:59:49    -- PDT by Lupine of  7-Jul-82 17:14:26 PDT.-- Source interface Target came from file Target.bcd, which was created    -- on  8-Jul-82  9:59:46 PDT with version stamp 52#64#37310473537 from    -- source of  8-Jul-82  9:33:34 PDT.-- The RPC stub modules for Target are:    -- TargetRpcControl.mesa;    -- TargetRpcClientImpl.mesa;    -- TargetRpcBinderImpl.mesa;    -- TargetRpcServerImpl.mesa.-- The parameters for this translation are:    -- Target language = Cedar;    -- Default parameter passing = VALUE;    -- Deallocate server heap arguments = TRUE;    -- Inline RpcServerImpl dispatcher stubs = TRUE;    -- Maximum number of dynamic heap NEWs = 50, MDS NEWs = 50;    -- Acceptable parameter protocols = VersionRange[1,1].DIRECTORY  Rope,  Target,  RPC USING [defaultInterfaceName, EncryptionKey, InterfaceName, Principal,      standardZones, VersionRange, Zones];TargetRpcControl: DEFINITIONS  SHARES  Target  = BEGIN OPEN Target, RpcPublic: RPC;-- Public RPC types and constants.  InterfaceName: TYPE = RpcPublic.InterfaceName;  VersionRange: TYPE = RpcPublic.VersionRange;  Principal: TYPE = RpcPublic.Principal;  EncryptionKey: TYPE = RpcPublic.EncryptionKey;  Zones: TYPE = RpcPublic.Zones;    defaultInterfaceName: InterfaceName = RpcPublic.defaultInterfaceName;  standardZones: Zones = RpcPublic.standardZones;-- Standard remote binding routines.  ImportInterface: SAFE PROCEDURE [        interfaceName: InterfaceName _ defaultInterfaceName,        parameterStorage: Zones _ standardZones ];  UnimportInterface: SAFE PROCEDURE;  ExportInterface: SAFE PROCEDURE [        interfaceName: InterfaceName _ defaultInterfaceName,        user: Principal,        password: EncryptionKey,        parameterStorage: Zones _ standardZones ];  UnexportInterface: SAFE PROCEDURE;-- Dynamic instantiation and binding.  ImportNewInterface: SAFE PROCEDURE [        interfaceName: InterfaceName _ defaultInterfaceName,        parameterStorage: Zones _ standardZones ]    RETURNS [interfaceRecord: InterfaceRecord];  InterfaceRecord: TYPE = REF InterfaceRecordObject;  InterfaceRecordObject: TYPE = RECORD [      Basic: PROCEDURE,      Simple: PROCEDURE [first: INT, second: REF INT] RETURNS [a: Rope.ROPE,	  b: ATOM],      Exception: ERROR [why: Reason],      Consultation: SIGNAL,      lupineDetails: PRIVATE REF LupineDetailsObject_NIL];  LupineDetailsObject: PRIVATE TYPE;-- Definitions for the stubs.  LupineProtocolVersion: PUBLIC VersionRange = [first: 1, last: 1];  InterMdsCallsOnly: PUBLIC BOOLEAN = FALSE;  ProcedureIndex: PRIVATE TYPE = MACHINE DEPENDENT {      LupineUnusedIndex (0), LupineLastIndex (3),      Basic (4), Simple (5)};  SignalIndex: PRIVATE TYPE = MACHINE DEPENDENT {      LupineUnusedIndex (0), LupineLastIndex (3),      Exception (4), Consultation (5)};    END.  -- TargetRpcControl.d3008e12k792\f8-- Stub file TargetRpcClientImpl.mesa was translated on  8-Jul-82     -- 9:59:50 PDT by Lupine of  7-Jul-82 17:14:26 PDT.-- Source interface Target came from file Target.bcd, which was created    -- on  8-Jul-82  9:59:46 PDT with version stamp 52#64#37310473537 from    -- source of  8-Jul-82  9:33:34 PDT.-- The RPC stub modules for Target are:    -- TargetRpcControl.mesa;    -- TargetRpcClientImpl.mesa;    -- TargetRpcBinderImpl.mesa;    -- TargetRpcServerImpl.mesa.-- The parameters for this translation are:    -- Target language = Cedar;    -- Default parameter passing = VALUE;    -- Deallocate server heap arguments = TRUE;    -- Inline RpcServerImpl dispatcher stubs = TRUE;    -- Maximum number of dynamic heap NEWs = 50, MDS NEWs = 50;    -- Acceptable parameter protocols = VersionRange[1,1].DIRECTORY  Rope,  Target,  TargetRpcControl USING [InterMdsCallsOnly, LupineProtocolVersion,      ProcedureIndex, SignalIndex],  RPC USING [InterfaceName, standardZones, Zones],  RPCLupine --USING SOME OF [Call, DataLength, Dispatcher, GetStubPkt,      -- ImportHandle, ImportInterface, maxDataLength, maxPrincipalLength,      -- maxShortStringLength, pktOverhead, ReceiveExtraPkt, SendPrelimPkt,      -- StartCall, StartSignal, StubPkt, UnimportInterface]--,  LupineRuntime --USING SOME OF [BindingError, CheckPktLength, CopyFromPkt,      -- CopyFromMultiplePkts, CopyToPkt, CopyToMultiplePkts, DispatchingError,      -- FinishThisPkt, ListHeader, MarshalingError, MarshalingExprError,      -- NilHeader, ProtocolError, RopeHeader, RpcPktDoubleWord, RuntimeError,      -- SequenceHeader, SHORT, StartNextPkt, StringHeader, StubPktDoubleWord,      -- TranslationError, UnmarshalingError, UnmarshalingExprError, WordsForChars]--,  Atom --USING SOME OF [GetPName, MakeAtom]--,  ConvertUnsafe USING [AppendRope],  Heap USING [systemMDSZone],  RopeInline --USING SOME OF [InlineFlatten, NewText]--,  SafeStorage USING [GetSystemZone],  UnsafeStorage USING [GetSystemUZone];TargetRpcClientImpl: MONITOR  IMPORTS RpcPrivate: RPCLupine, Lupine: LupineRuntime, Atom, ConvertUnsafe,      Heap, RopeInline, SafeStorage, UnsafeStorage  EXPORTS Target, TargetRpcControl  SHARES  Target, TargetRpcControl, Rope  = BEGIN OPEN Target, RpcControl: TargetRpcControl, RpcPublic: RPC;-- Standard remote binding routines.  bound: BOOLEAN _ FALSE;  myInterface: RpcPrivate.ImportHandle _ NULL;  paramZones: RpcPublic.Zones _ RpcPublic.standardZones;  ImportInterface: PUBLIC ENTRY SAFE PROCEDURE [        interfaceName: RpcPublic.InterfaceName,        parameterStorage: RpcPublic.Zones ] =    TRUSTED BEGIN ENABLE UNWIND => NULL;    IsNull: PROCEDURE [string: LONG STRING] RETURNS [BOOLEAN] =      INLINE {RETURN[ string=NIL OR string.length=0 ]};    IF bound THEN Lupine.BindingError;    BEGIN    type: STRING = [RpcPrivate.maxShortStringLength];    instance: STRING = [RpcPrivate.maxShortStringLength];    ConvertUnsafe.AppendRope[to: type, from: interfaceName.type];    ConvertUnsafe.AppendRope[to: instance, from: interfaceName.instance];    myInterface _ RpcPrivate.ImportInterface [      interface: [        type: IF ~IsNull[type]          THEN type ELSE "Target~52#64#37310473537"L,        instance: instance,        version: interfaceName.version ],      localOnly: RpcControl.InterMdsCallsOnly,      stubProtocol: RpcControl.LupineProtocolVersion ];    END;    paramZones _ [      gc: IF parameterStorage.gc # NIL        THEN parameterStorage.gc ELSE SafeStorage.GetSystemZone[],      heap: IF parameterStorage.heap # NIL        THEN parameterStorage.heap ELSE UnsafeStorage.GetSystemUZone[],      mds: IF parameterStorage.mds # NIL        THEN parameterStorage.mds ELSE Heap.systemMDSZone ];    bound _ TRUE;    END;  UnimportInterface: PUBLIC ENTRY SAFE PROCEDURE =    TRUSTED BEGIN ENABLE UNWIND => NULL;    IF ~bound THEN Lupine.BindingError;    myInterface _ RpcPrivate.UnimportInterface[myInterface];    paramZones _ RpcPublic.standardZones;    bound _ FALSE;    END;-- Remote public procedure stubs.  Basic: PUBLIC PROCEDURE =    BEGIN    ArgumentOverlay: TYPE = MACHINE DEPENDENT RECORD [	transferIndex (0): RpcControl.ProcedureIndex _ Basic];    pktBuffer: ARRAY [1..RpcPrivate.pktOverhead+1] OF WORD;    pkt: RpcPrivate.StubPkt = RpcPrivate.GetStubPkt[space: @pktBuffer];    argPkt: POINTER TO ArgumentOverlay = @pkt.data[0];    pktLength: RpcPrivate.DataLength _ 1;    lastPkt: BOOLEAN;    RpcPrivate.StartCall[callPkt: pkt, interface: myInterface];    argPkt.transferIndex _ Basic;    [returnLength: , lastPkt: lastPkt] _      RpcPrivate.Call[ pkt: pkt, callLength: pktLength,	  maxReturnLength: 0, signalHandler: ClientDispatcher];    Lupine.CheckPktLength[pkt: pkt, pktLength: 0];    RETURN[];    END;  -- Basic.  Simple: PUBLIC PROCEDURE [first: INT, second: REF INT] RETURNS [a:      Rope.ROPE, b: ATOM] =    BEGIN    ArgumentOverlay: TYPE = MACHINE DEPENDENT RECORD [	transferIndex (0): RpcControl.ProcedureIndex _ Simple, first (1):	INT];    pktBuffer: ARRAY [1..RpcPrivate.pktOverhead+254] OF WORD;    pkt: RpcPrivate.StubPkt = RpcPrivate.GetStubPkt[space: @pktBuffer];    argPkt: POINTER TO ArgumentOverlay = @pkt.data[0];    pktLength: RpcPrivate.DataLength _ 3;    lastPkt: BOOLEAN;    RpcPrivate.StartCall[callPkt: pkt, interface: myInterface];    argPkt^ _ [first: first];    BEGIN  -- Marshal second: REF INT to pkt.data[pktLength].      pkt.data[pktLength] _ second=NIL;  pktLength _ pktLength+1;      IF second # NIL THEN	BEGIN	Lupine.StubPktDoubleWord[pkt, pktLength]^ _ second^;	pktLength _ pktLength + 2;	END;      END;  -- Marshal second.    [returnLength: , lastPkt: lastPkt] _      RpcPrivate.Call[ pkt: pkt, callLength: pktLength,	  maxReturnLength: 254, signalHandler: ClientDispatcher];    pktLength _ 0;    BEGIN  -- Unmarshal a: Rope.ROPE from pkt.data[pktLength].      ropeIsNIL: Lupine.NilHeader;      IF pktLength+2 > RpcPrivate.maxDataLength	THEN pktLength _ Lupine.FinishThisPkt[pkt: pkt, pktLength:	    pktLength];      ropeIsNIL _ pkt.data[pktLength];  pktLength _ pktLength+1;      IF ropeIsNIL	THEN a _ NIL	ELSE BEGIN	  ropeLength: Lupine.RopeHeader;	  textRope: Rope.Text;	  ropeLength _ pkt.data[pktLength];  pktLength _ pktLength+1;	  IF ropeLength > LAST[NAT]	    THEN Lupine.UnmarshalingError;	  a _ textRope _ RopeInline.NewText[size: ropeLength];	  pktLength _ Lupine.CopyFromPkt[pkt: pkt, pktLength: pktLength,	      dataAdr: BASE[DESCRIPTOR[textRope.text]], dataLength: Lupine.WordsForChars[ropeLength],	      alwaysOnePkt: FALSE];	  END;  -- IF ropeIsNIL.      END;  -- Unmarshal a.    BEGIN  -- Unmarshal b: ATOM from pkt.data[pktLength].      pNameOfAtom: Rope.ROPE;      ropeIsNIL: Lupine.NilHeader;      IF pktLength+2 > RpcPrivate.maxDataLength	THEN pktLength _ Lupine.FinishThisPkt[pkt: pkt, pktLength:	    pktLength];      ropeIsNIL _ pkt.data[pktLength];  pktLength _ pktLength+1;      IF ropeIsNIL	THEN pNameOfAtom _ NIL	ELSE BEGIN	  ropeLength: Lupine.RopeHeader;	  textRope: Rope.Text;	  ropeLength _ pkt.data[pktLength];  pktLength _ pktLength+1;	  IF ropeLength > LAST[NAT]	    THEN Lupine.UnmarshalingError;	  pNameOfAtom _ textRope _ RopeInline.NewText[size: ropeLength];	  pktLength _ Lupine.CopyFromPkt[pkt: pkt, pktLength: pktLength,	      dataAdr: BASE[DESCRIPTOR[textRope.text]], dataLength: Lupine.WordsForChars[ropeLength],	      alwaysOnePkt: FALSE];	  END;  -- IF ropeIsNIL.      b _ Atom.MakeAtom[--pName:-- pNameOfAtom];      END;  -- Unmarshal b.    Lupine.CheckPktLength[pkt: pkt, pktLength: pktLength];    RETURN[a, b];    END;  -- Simple.-- Remote public signals and errors.  Exception: PUBLIC ERROR [why: Reason] = CODE;  Consultation: PUBLIC SIGNAL = CODE;-- Public signal and error dispatcher.  ClientDispatcher: --PROCEDURE [pkt: RPCPkt, callLength: DataLength,      -- lastPkt: BOOLEAN, localConversation: Conversation] RETURNS [returnLength:      -- DataLength]-- RpcPrivate.Dispatcher =    BEGIN    SELECT LOOPHOLE[pkt.data[0], RpcControl.SignalIndex] FROM      Exception => RETURN[	ExceptionStub[pkt: pkt, callLength: callLength, lastPkt: lastPkt,	    localConversation: localConversation]];      Consultation => RETURN[	ConsultationStub[pkt: pkt, callLength: callLength, lastPkt:	    lastPkt, localConversation: localConversation]];      ENDCASE => RETURN[Lupine.DispatchingError[]];    END;  -- ClientDispatcher-- Public signal and error dispatcher stubs.  ExceptionStub: --ERROR [why: Reason]-- RpcPrivate.Dispatcher =    INLINE BEGIN    ArgumentOverlay: TYPE = MACHINE DEPENDENT RECORD [	transferIndex (0): RpcControl.SignalIndex, why (1): Reason];    argPkt: LONG POINTER TO ArgumentOverlay = @pkt.data[0];    Lupine.CheckPktLength[pkt: pkt, pktLength: 2];    ERROR Exception[argPkt.why];    END;  -- ExceptionStub.  ConsultationStub: --SIGNAL-- RpcPrivate.Dispatcher =    INLINE BEGIN    pktLength: RpcPrivate.DataLength;    Lupine.CheckPktLength[pkt: pkt, pktLength: 1];    SIGNAL Consultation[];    pktLength _ 0;    RETURN[returnLength: pktLength];    END;  -- ConsultationStub.-- No module initialization.  END.  -- TargetRpcClientImpl.d3008e12k792\f8-- Stub file TargetRpcServerImpl.mesa was translated on  8-Jul-82     -- 9:59:52 PDT by Lupine of  7-Jul-82 17:14:26 PDT.-- Source interface Target came from file Target.bcd, which was created    -- on  8-Jul-82  9:59:46 PDT with version stamp 52#64#37310473537 from    -- source of  8-Jul-82  9:33:34 PDT.-- The RPC stub modules for Target are:    -- TargetRpcControl.mesa;    -- TargetRpcClientImpl.mesa;    -- TargetRpcBinderImpl.mesa;    -- TargetRpcServerImpl.mesa.-- The parameters for this translation are:    -- Target language = Cedar;    -- Default parameter passing = VALUE;    -- Deallocate server heap arguments = TRUE;    -- Inline RpcServerImpl dispatcher stubs = TRUE;    -- Maximum number of dynamic heap NEWs = 50, MDS NEWs = 50;    -- Acceptable parameter protocols = VersionRange[1,1].DIRECTORY  Rope,  Target,  TargetRpcControl USING [InterMdsCallsOnly, LupineProtocolVersion,      ProcedureIndex, SignalIndex],  RPC USING [EncryptionKey, InterfaceName, Principal, standardZones,      Zones],  RPCLupine --USING SOME OF [Call, DataLength, Dispatcher, ExportHandle,      -- ExportInterface, GetStubPkt, maxDataLength, maxPrincipalLength,      -- maxShortStringLength, pktOverhead, ReceiveExtraPkt, SendPrelimPkt,      -- StartCall, StartSignal, StubPkt, UnexportInterface]--,  LupineRuntime --USING SOME OF [BindingError, CheckPktLength, CopyFromPkt,      -- CopyFromMultiplePkts, CopyToPkt, CopyToMultiplePkts, DispatchingError,      -- FinishThisPkt, ListHeader, MarshalingError, MarshalingExprError,      -- NilHeader, ProtocolError, RopeHeader, RpcPktDoubleWord, RuntimeError,      -- SequenceHeader, SHORT, StartNextPkt, StringHeader, StubPktDoubleWord,      -- TranslationError, UnmarshalingError, UnmarshalingExprError, WordsForChars]--,  Atom --USING SOME OF [GetPName, MakeAtom]--,  ConvertUnsafe USING [AppendRope],  Heap USING [systemMDSZone],  RopeInline --USING SOME OF [InlineFlatten, NewText]--,  SafeStorage USING [GetSystemZone],  UnsafeStorage USING [GetSystemUZone];TargetRpcServerImpl: MONITOR  IMPORTS Target, RpcPrivate: RPCLupine, Lupine: LupineRuntime, Atom,      ConvertUnsafe, Heap, RopeInline, SafeStorage, UnsafeStorage  EXPORTS TargetRpcControl  SHARES  Target, TargetRpcControl, Rope  = BEGIN OPEN Target, RpcControl: TargetRpcControl, RpcPublic: RPC;-- Standard remote binding routines.  bound: BOOLEAN _ FALSE;  myInterface: RpcPrivate.ExportHandle _ NULL;  paramZones: RpcPublic.Zones _ RpcPublic.standardZones;  ExportInterface: PUBLIC ENTRY SAFE PROCEDURE [        interfaceName: RpcPublic.InterfaceName,        user: RpcPublic.Principal,        password: RpcPublic.EncryptionKey,        parameterStorage: RpcPublic.Zones ] =    TRUSTED BEGIN ENABLE UNWIND => NULL;    IsNull: PROCEDURE [string: LONG STRING] RETURNS [BOOLEAN] =      INLINE {RETURN[ string=NIL OR string.length=0 ]};    IF bound THEN Lupine.BindingError;    BEGIN    type: STRING = [RpcPrivate.maxShortStringLength];    instance: STRING = [RpcPrivate.maxShortStringLength];    userString: STRING = [RpcPrivate.maxPrincipalLength];    ConvertUnsafe.AppendRope[to: type, from: interfaceName.type];    ConvertUnsafe.AppendRope[to: instance, from: interfaceName.instance];    ConvertUnsafe.AppendRope[to: userString, from: user];    myInterface _ RpcPrivate.ExportInterface [      interface: [        type: IF ~IsNull[type]          THEN type ELSE "Target~52#64#37310473537"L,        instance: instance,        version: interfaceName.version ],      user: userString,  password: password,      dispatcher: ServerDispatcher,      localOnly: RpcControl.InterMdsCallsOnly,      stubProtocol: RpcControl.LupineProtocolVersion ];    END;    paramZones _ [      gc: IF parameterStorage.gc # NIL        THEN parameterStorage.gc ELSE SafeStorage.GetSystemZone[],      heap: IF parameterStorage.heap # NIL        THEN parameterStorage.heap ELSE UnsafeStorage.GetSystemUZone[],      mds: IF parameterStorage.mds # NIL        THEN parameterStorage.mds ELSE Heap.systemMDSZone ];    bound _ TRUE;    END;  UnexportInterface: PUBLIC ENTRY SAFE PROCEDURE =    TRUSTED BEGIN ENABLE UNWIND => NULL;    IF ~bound THEN Lupine.BindingError;    myInterface _ RpcPrivate.UnexportInterface[myInterface];    paramZones _ RpcPublic.standardZones;    bound _ FALSE;    END;-- Public procedure dispatcher and public signal and error catcher.  ServerDispatcher: --PROCEDURE [pkt: RPCPkt, callLength: DataLength,      -- lastPkt: BOOLEAN, localConversation: Conversation] RETURNS [returnLength:      -- DataLength]-- RpcPrivate.Dispatcher =    BEGIN    -- Catch public signals.      ENABLE BEGIN      Exception --ERROR [why: Reason]-- =>	BEGIN	ArgumentOverlay: TYPE = MACHINE DEPENDENT RECORD [	    transferIndex (0): RpcControl.SignalIndex _ Exception, why	    (1): Reason];	argPkt: LONG POINTER TO ArgumentOverlay = @pkt.data[0];	pktLength: RpcPrivate.DataLength _ 2;	lastPkt: BOOLEAN;	RpcPrivate.StartSignal[signalPkt: pkt];	argPkt^ _ [why: why];	[returnLength: , lastPkt: lastPkt] _	  RpcPrivate.Call[ pkt: pkt, callLength: pktLength,	      maxReturnLength: 0];	Lupine.RuntimeError;  -- Impossible to RESUME an ERROR.	END;  -- Exception.      Consultation --SIGNAL-- =>	BEGIN	ArgumentOverlay: TYPE = MACHINE DEPENDENT RECORD [	    transferIndex (0): RpcControl.SignalIndex _ Consultation];	argPkt: LONG POINTER TO ArgumentOverlay = @pkt.data[0];	pktLength: RpcPrivate.DataLength _ 1;	lastPkt: BOOLEAN;	RpcPrivate.StartSignal[signalPkt: pkt];	argPkt.transferIndex _ Consultation;	[returnLength: , lastPkt: lastPkt] _	  RpcPrivate.Call[ pkt: pkt, callLength: pktLength,	      maxReturnLength: 0];	Lupine.CheckPktLength[pkt: pkt, pktLength: 0];	RESUME[];	END;  -- Consultation.      END;  -- Catch public signals.    -- Call public procedures (still in dispatcher).    SELECT LOOPHOLE[pkt.data[0], RpcControl.ProcedureIndex] FROM      Basic => RETURN[	BasicStub[pkt: pkt, callLength: callLength, lastPkt: lastPkt,	    localConversation: localConversation]];      Simple => RETURN[	SimpleStub[pkt: pkt, callLength: callLength, lastPkt: lastPkt,	    localConversation: localConversation]];      ENDCASE => RETURN[Lupine.DispatchingError[]];    END;  -- ServerDispatcher-- Public procedure dispatcher stubs.  BasicStub: --PROCEDURE-- RpcPrivate.Dispatcher =    INLINE BEGIN    pktLength: RpcPrivate.DataLength;    Lupine.CheckPktLength[pkt: pkt, pktLength: 1];    Basic[];    pktLength _ 0;    RETURN[returnLength: pktLength];    END;  -- BasicStub.  SimpleStub: --PROCEDURE [first: INT, second: REF INT] RETURNS [a:      -- Rope.ROPE, b: ATOM]-- RpcPrivate.Dispatcher =    INLINE BEGIN    second: REF INT;    a: Rope.ROPE;    b: ATOM;    ArgumentOverlay: TYPE = MACHINE DEPENDENT RECORD [	transferIndex (0): RpcControl.ProcedureIndex, first (1): INT];    argPkt: LONG POINTER TO ArgumentOverlay = @pkt.data[0];    pktLength: RpcPrivate.DataLength _ 3;    BEGIN  -- Unmarshal second: REF INT from pkt.data[pktLength].      isNIL: Lupine.NilHeader;      isNIL _ pkt.data[pktLength];  pktLength _ pktLength+1;      IF isNIL	THEN second _ NIL	ELSE BEGIN	  second _ (paramZones.gc.NEW[INT]);	  BEGIN	  second^ _ Lupine.RpcPktDoubleWord[pkt, pktLength]^;	  pktLength _ pktLength + 2;	  END;	  END;  -- IF isNIL.      END;  -- Unmarshal second.    Lupine.CheckPktLength[pkt: pkt, pktLength: pktLength];    [a, b] _      Simple[argPkt.first, second];    pktLength _ 0;    BEGIN  -- Marshal a: Rope.ROPE to pkt.data[pktLength].      IF pktLength+2 > RpcPrivate.maxDataLength	THEN pktLength _ Lupine.StartNextPkt[pkt: pkt, pktLength: pktLength];      pkt.data[pktLength] _ a=NIL;  pktLength _ pktLength+1;      IF a # NIL	THEN BEGIN	  textRope: Rope.Text = RopeInline.InlineFlatten[r: a];	  pkt.data[pktLength] _ textRope.length;  pktLength _ pktLength+1;	  pktLength _ Lupine.CopyToPkt[pkt: pkt, pktLength: pktLength,	      dataAdr: BASE[DESCRIPTOR[textRope.text]], dataLength: Lupine.WordsForChars[textRope.length],	      alwaysOnePkt: FALSE];	  END;  -- IF a # NIL.      END;  -- Marshal a.    BEGIN  -- Marshal b: ATOM to pkt.data[pktLength].      pNameOfAtom: Rope.Text = Atom.GetPName[atom: b];      IF pktLength+2 > RpcPrivate.maxDataLength	THEN pktLength _ Lupine.StartNextPkt[pkt: pkt, pktLength: pktLength];      pkt.data[pktLength] _ pNameOfAtom=NIL;  pktLength _ pktLength+1;      IF pNameOfAtom # NIL	THEN BEGIN	  textRope: Rope.Text = RopeInline.InlineFlatten[r: pNameOfAtom];	  pkt.data[pktLength] _ textRope.length;  pktLength _ pktLength+1;	  pktLength _ Lupine.CopyToPkt[pkt: pkt, pktLength: pktLength,	      dataAdr: BASE[DESCRIPTOR[textRope.text]], dataLength: Lupine.WordsForChars[textRope.length],	      alwaysOnePkt: FALSE];	  END;  -- IF pNameOfAtom # NIL.      END;  -- Marshal b.    RETURN[returnLength: pktLength];    END;  -- SimpleStub.-- No module initialization.  END.  -- TargetRpcServerImpl.d3008e12k792\f8-- Stub file TargetRpcBinderImpl.mesa was translated on  8-Jul-82     -- 9:59:51 PDT by Lupine of  7-Jul-82 17:14:26 PDT.-- Source interface Target came from file Target.bcd, which was created    -- on  8-Jul-82  9:59:46 PDT with version stamp 52#64#37310473537 from    -- source of  8-Jul-82  9:33:34 PDT.-- The RPC stub modules for Target are:    -- TargetRpcControl.mesa;    -- TargetRpcClientImpl.mesa;    -- TargetRpcBinderImpl.mesa;    -- TargetRpcServerImpl.mesa.-- The parameters for this translation are:    -- Target language = Cedar;    -- Default parameter passing = VALUE;    -- Deallocate server heap arguments = TRUE;    -- Inline RpcServerImpl dispatcher stubs = TRUE;    -- Maximum number of dynamic heap NEWs = 50, MDS NEWs = 50;    -- Acceptable parameter protocols = VersionRange[1,1].-- NOTE: Discard this module unless you use dynamic client binding.DIRECTORY  TargetRpcControl USING [InterfaceRecord, InterfaceRecordObject],  TargetRpcClientImpl,  RPC USING [InterfaceName, Zones],  RTTypesBasic USING [EstablishFinalization, FinalizationQueue, FQEmpty,      FQNext, NewFQ];TargetRpcBinderImpl: MONITOR  IMPORTS ClientPrototype: TargetRpcClientImpl, RTT: RTTypesBasic  EXPORTS TargetRpcControl  SHARES  TargetRpcControl  = BEGIN OPEN RpcControl: TargetRpcControl, RpcPublic: RPC;-- Dynamic instantiation and binding routines.  ImportNewInterface: PUBLIC SAFE PROCEDURE [        interfaceName: RpcPublic.InterfaceName,        parameterStorage: RpcPublic.Zones ]      RETURNS [interfaceRecord: RpcControl.InterfaceRecord] =    TRUSTED BEGIN    interfaceRecord _ NewInterface[];    LupineDetails[interfaceRecord].module.ImportInterface [        interfaceName: interfaceName,        parameterStorage: parameterStorage      ! UNWIND => FreeInterface[interfaceRecord] ];    END;  UnimportNewInterface: SAFE PROCEDURE [      interfaceRecord: RpcControl.InterfaceRecord ] =    TRUSTED BEGIN    LupineDetails[interfaceRecord].module.UnimportInterface[];    FreeInterface[interfaceRecord];    END;-- Utility routines for interface instantiation and caching.  ConcreteLupineDetails: TYPE = REF LupineDetailsObject;  LupineDetailsObject:  PUBLIC TYPE = RECORD [	module: ClientModule_NIL,	next: RpcControl.InterfaceRecord_NIL,	self: RpcControl.InterfaceRecord_NIL ];  LupineDetails: PROCEDURE [abstractInterface: RpcControl.InterfaceRecord]      RETURNS [ConcreteLupineDetails] =    INLINE {RETURN[abstractInterface.lupineDetails]};  ClientModule: TYPE = POINTER TO FRAME[TargetRpcClientImpl];  clientInterfaceCache: RpcControl.InterfaceRecord _ NIL;  NewInterface: PROCEDURE RETURNS [interface: RpcControl.InterfaceRecord]=    BEGIN    GetCachedInterface: ENTRY PROCEDURE        RETURNS [cachedIR: RpcControl.InterfaceRecord] =      INLINE BEGIN ENABLE UNWIND => NULL;      IF (cachedIR_clientInterfaceCache) # NIL        THEN clientInterfaceCache _ LupineDetails[clientInterfaceCache].next;      END;    ReclaimInterfaces;    IF (interface _ GetCachedInterface[]) = NIL      THEN BEGIN        module: ClientModule = NEW ClientPrototype;        interface _ NEW[          RpcControl.InterfaceRecordObject _ [	      Basic: module.Basic, Simple: module.Simple, Exception: module.Exception,	      Consultation: module.Consultation]];        interface.lupineDetails _ NEW[          LupineDetailsObject _ [module: module, self: interface]];        END;    END;  FreeInterface: ENTRY PROCEDURE [interface: RpcControl.InterfaceRecord]=    INLINE BEGIN ENABLE UNWIND => NULL;    LupineDetails[interface].next _ clientInterfaceCache;    clientInterfaceCache _ interface;    END;-- Finalization for dynamic interfaces.  Just cache and reuse for now.  freedInterfaces: RTT.FinalizationQueue = RTT.NewFQ[20];  ReclaimInterfaces: PROCEDURE =    INLINE BEGIN    WHILE ~RTT.FQEmpty[freedInterfaces] DO      UnimportNewInterface[        interfaceRecord: NARROW[RTT.FQNext[freedInterfaces]] ];      ENDLOOP;    END;-- Module initialization.  RTT.EstablishFinalization[    type: CODE[RpcControl.InterfaceRecordObject],    npr: 1,  fq: freedInterfaces ];  END.  -- TargetRpcBinderImpl.d3008e12k792\f8