AlpInstanceCourierImpl.mesa
Carl Hauser, November 11, 1987 6:43:24 pm PST
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;
Remove any .alpine from the name -- backward compatibility hack
alpinePos: INT ← Rope.FindBackward[s1: fileStore, s2: ".alpine", case: FALSE];
IF fileStore.Length[] - alpinePos = 7 THEN realFileStore ← fileStore.Substr[len: alpinePos];
First, get a three part name for the fileStore (completing the domain and organization)
fileStoreName ← XNSCHName.NameFromRope[realFileStore];
subsequently, use the Rope version of the fully qualified name
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 ← [
This is a terrible abuse of AlpInstance.Objects; for Courier we don't need trans, file, owner, and volume because we are never doing a local import. On the other hand, we need a place to hang our Courier handle and conversation so we'll use otherInterfaces in a stylized way.
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 => { authenticationProblemproblem; 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;
IF caller = NIL THEN
have to ignore caller for now because can't make an RPC password out of a key. Change the Alpine interface so it takes a key instead of a password and this can change back.
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];
non system-fatal errors:
none.
BEGIN
ENABLE {
UNWIND => NULL
};
objectCache ← NIL;
END;
TRUSTED { Booting.RegisterProcs[c: , r: AlpRollbackProcedure]; };
END.