<> <> <<>> DIRECTORY XNSCHName, Rope, AlpInstance, AlpineEnvironment, AlpineEnvironmentP2201V1, XNS, XNSCH, XNSAuth, AlpineP2202V1, AlpInstanceCourier, AuthenticationP14V2, UserCredentials, CrRPC, RPC, Booting; AlpInstanceCourierImpl: CEDAR MONITOR IMPORTS XNSCHName, Rope, CrRPC, XNSCH, XNSAuth, AlpineP2202V1, RPC, UserCredentials, Booting EXPORTS AlpInstance ~ BEGIN OPEN AE: AlpineEnvironment, AlpI: AlpInstance; objectCache: LIST OF CacheRec _ NIL; CacheRec: TYPE = RECORD [ object: AlpI.Handle _ NIL, caller: AE.Principal _ NIL ]; FindObjectInCache: INTERNAL PROCEDURE[fileStore: AE.FileStore, caller: AE.Principal, key: RPC.EncryptionKey, pwd: Rope.ROPE, identity: XNSAuth.Identity] RETURNS[handle: AlpI.Handle _ NIL] = BEGIN fileStoreName: XNSCHName.Name; connectionProblem: AlpineP2202V1.ConnectionProblem; authenticationProblem: AuthenticationP14V2.Problem; crReason: CrRPC.ErrorReason; realFileStore: Rope.ROPE _ fileStore; <> alpinePos: INT _ Rope.FindBackward[s1: fileStore, s2: ".alpine", case: FALSE]; IF fileStore.Length[] - alpinePos = 7 THEN realFileStore _ fileStore.Substr[len: alpinePos]; <> fileStoreName _ XNSCHName.NameFromRope[realFileStore]; <> realFileStore _ XNSCHName.RopeFromName[fileStoreName]; FOR list: LIST OF CacheRec _ objectCache, list.rest UNTIL list = NIL DO IF Rope.Equal[list.first.object.fileStore, fileStore, FALSE] THEN BEGIN IF Rope.Equal[list.first.caller, caller, FALSE] AND (key = list.first.object.key) THEN RETURN[list.first.object]; END; ENDLOOP; handle _ NEW[AlpI.Object _ [ <> trans: NIL, file: NIL, owner: NIL, volume: NIL, otherInterfaces: NIL, conversation: NIL, key: key, fileStore: fileStore]]; { ENABLE { AlpineP2202V1.ConnectionError => {connectionProblem _ problem; GOTO connection}; AlpineP2202V1.AuthenticationError => { authenticationProblem _ problem; GOTO auth }; CrRPC.Error => SELECT errorReason FROM unknown, unknownClass, argsError, resultsError, bulkDataError, notImplemented, unknownOperation, notServerHandle, notClientHandle, addressInappropriateForClass, other => REJECT; ENDCASE => { crReason _ errorReason; GOTO rpcErr}; }; serverAddress: REF XNS.Address ~ NEW[XNS.Address _ XNSCH.LookupAddressFromRope[realFileStore].address]; courierHandle: CrRPC.Handle ~ CrRPC.CreateClientHandle[$SPP, serverAddress]; authenticatedConversation: XNSAuth.Conversation ~ XNSAuth.Initiate[identity, fileStoreName]; credentials: XNSAuth.Credentials ~ XNSAuth.GetCredentials[authenticatedConversation]; verifier: XNSAuth.Verifier _ XNSAuth.GetNextVerifier[authenticatedConversation]; session: AlpineP2202V1.Session; [session, verifier] _ AlpineP2202V1.Logon[courierHandle, fileStoreName, credentials, [caller, pwd], verifier]; handle.otherInterfaces _ LIST[NEW[AlpInstanceCourier.InstanceObject _ [ , courierHandle, authenticatedConversation, credentials, session]]]; EXITS connection => ERROR RPC.ImportFailed[communications]; auth => ERROR RPC.AuthenticateFailed[badCaller]; -- no appropriate reason available. rpcErr => SELECT crReason FROM rejectedNoSuchProgram => ERROR RPC.ImportFailed[unbound]; rejectedNoSuchVersion, rejectedNoSuchProcedure => ERROR RPC.ImportFailed[wrongVersion]; communicationFailure, remoteClose, cantConnectToRemote => ERROR RPC.ImportFailed[communications]; courierVersionMismatch, rejectedInvalidArgument, rejectedUnspecified, remoteError, protocolError => ERROR RPC.ImportFailed[stubProtocol]; ENDCASE => ERROR; }; objectCache _ CONS[ [handle, caller], objectCache]; END; Create: PUBLIC ENTRY PROC [fileStore: AE.FileStore, caller: AE.Principal, key: RPC.EncryptionKey] RETURNS [handle: AlpI.Handle] ~ { ENABLE UNWIND => NULL; identity: XNSAuth.Identity; psw: Rope.ROPE; <> <> BEGIN [caller, psw] _ UserCredentials.Get[]; TRUSTED BEGIN key _ RPC.MakeKey[psw]; END; END; identity _ UserCredentials.GetIdentity[]; handle _ FindObjectInCache[fileStore, caller, key, psw, identity]; }; AlpRollbackProcedure: ENTRY Booting.RollbackProc = -- TYPE = PROC[clientData: REF ANY]; <> <> BEGIN ENABLE { UNWIND => NULL }; objectCache _ NIL; END; TRUSTED { Booting.RegisterProcs[c: , r: AlpRollbackProcedure]; }; END.