RPCInternal.mesa
Copyright Ó 1985, 1986, 1987 by Xerox Corporation. All rights reserved.
RPC: Internal interface
Andrew Birrell September 7, 1983 4:12 pm
Bob Hagmann February 8, 1985 3:33:38 pm PST
Hal Murray, May 12, 1986 11:56:13 am PDT
Swinehart, January 17, 1987 2:08:23 pm PST
DIRECTORY
PupBuffer USING [Buffer],
DESFace USING [Block, IV, Key],
PupWKS USING [rpc],
RPC USING [Conversation, InterfaceName, Principal, SecurityLevel, VersionRange],
RPCLupine USING [DataLength, Dispatcher, RPCPkt],
RPCPkt USING [CallCount, ConnectionID, ConversationID, DispatcherDetails, DispatcherID, ExportHandle, Header, PktConversationID, PktID, Machine];
RPCInternal: DEFINITIONS =
BEGIN
******** Start-up sequence. Main control is RPCPktIO ********
StartRPCBinding: PROC [RPCPkt.Machine];
StartRPCSecurity: PROC [RPCPkt.Machine];
StartRPCPktStreams: PROC [RPCPkt.Machine];
RollbackRPCBinding: PROC;
RollbackRPCSecurity: PROC;
RollbackRPCPktStreams: PROC;
******** Binding: exported by RPCBinding ********
ExportInstance:
TYPE =
RECORD[
Exporter's record of exported interface
id: RPCPkt.DispatcherID,
dispatcher: RPCLupine.Dispatcher,
name: RPC.InterfaceName,
stubProtocol: RPC.VersionRange ];
ExportTable:
TYPE =
RECORD[
used: CARDINAL,
entries: SEQUENCE length: RPCPkt.ExportHandle OF ExportInstance];
exportTable: REF ExportTable;
ImportInstance:
TYPE =
RECORD[
Importer's record of successful binding
host: RPCPkt.Machine,
dispatcher: RPCPkt.DispatcherDetails ];
******** Authentication/Security: exported by RPCSecurity ********
ConversationObject:
TYPE =
RECORD[
next: REF ConversationObject,
id: RPCPkt.ConversationID,
level: RPC.SecurityLevel,
key: DESFace.Key, -- conversation key --
iv: DESFace.IV,
originator: RPC.Principal,
responder: RPC.Principal,
authenticator: Authenticator,
Can be set through RPCTimeouts.SetMaxTransmissions[] to override the standard maximum number of unacknowledged packet retransmissions before timing out. Some calls must complete quickly or are best abandoned. If 0, the standard value is used.
maxTransmissions: CARDINAL ← 0,
Can be set through RPCTimeouts.SetMaxTransmissions[] to override the determination of whether unacknowledged packet retransmissions are ever timed out. When distributed systems are being developed, sometimes they are unresponsive for long periods of time. always means that timeouts will raise an error signal. never means that RPC will try forever to complete the call. If dontCare, the standard value is used.
timeoutEnable: TimeoutEnable ← dontCare
];
TimeoutEnable: TYPE = { dontCare, always, never };
Authenticator: TYPE = REF AuthenticatorObject;
AuthenticatorObject:
TYPE =
RECORD[
Allocated storage for an authenticator. For A talking to B using key CK, contains: {KY}KB, spare, { {CK}KB, spare, time, A }KY . The keys are single cipher blocks. The rest is encrypted with CBC-check using a zero IV
SEQUENCE nBlks: CARDINAL OF DESFace.Block ];
firstConversation: RPCPkt.PktConversationID; -- for unencrypted conversations --
EncryptPkt:
PROC[pkt: RPCLupine.RPCPkt, l: RPCLupine.DataLength]
RETURNS[CARDINAL];
Encrypts packet using pkt.convHandle; "l" is data length of pkt; returns Pup length of packet.
DecryptPkt:
PROC[header:
LONG
POINTER
TO RPCPkt.Header,
convHandle: RPC.Conversation]
RETURNS[ok: BOOLEAN, l: RPCLupine.DataLength];
Decrypts packet using pkt.convHandle; ok iff checksum matches; returns data length of packet
GetConnectionState: PROC[ decrypted: BOOLEAN, callPkt: RPCLupine.RPCPkt]
GetConnectionState:
PROC[ callPkt: RPCLupine.RPCPkt]
RETURNS[ ok:
BOOLEAN,
id: RPCPkt.ConnectionID,
call: RPCPkt.CallCount,
conv: RPC.Conversation,
l: RPCLupine.DataLength ];
On exit, if "ok" and not decrypted, returns pkt data length in "l". Sends RFA and accepts response; results valid iff "ok"
ReplyToRFA:
PROC [b: PupBuffer.Buffer,
-- incoming packet --
callHeader: LONG POINTER TO RPCPkt.Header, -- encrypted --
callPktID: RPCPkt.PktID-- clear --,
convHandle: RPC.Conversation]
RETURNS[BOOLEAN];
Generates RFA response packet if request matches thisPktID
******** Packet stream functions: exported by RPCPktStream ********
DoSignal:
PROC [b: PupBuffer.Buffer, pktLength: RPCLupine.DataLength,
signalHandler: RPCLupine.Dispatcher,
convHandle: RPC.Conversation]
RETURNS[resumePkt: RPCLupine.RPCPkt,
resumeLength: RPCLupine.DataLength,
myLocalFrame: POINTER];
Called from inside PktExchange to handle signal-back packets
ServerMain:
PROCEDURE;
FORK'ed when needed by RPCPktIO, to maintain an adequate stock of them
******** For some Voice kludgery that I don't understand /HGM, Jan 86 ********
CopyPrincipal: PROC [from: RPC.Principal, to: LONG POINTER];
EntryGenerate:
PROC [ level:
RPC.SecurityLevel, iv: DESFace.
IV, originator, responder:
RPC.Principal, convKey: DESFace.Key, auth: RPCInternal.Authenticator]
RETURNS [ conversation: REF RPCInternal.ConversationObject ];
AddToExportTable: PROC [interface: RPC.InterfaceName, dispatcher: RPCLupine.Dispatcher, stubProtocol: RPC.VersionRange] RETURNS [ instance: RPCPkt.ExportHandle ];
******** For new Communication package /HGM, Jan 86 ********
AllocBuffer: PROC RETURNS [b: PupBuffer.Buffer];
GiveBackBuffer: PROC [b: PupBuffer.Buffer];
SendBuffer: PROC [b: PupBuffer.Buffer];
******** Moved from RPCPkt /HGM, Apr 86 ********
pktLengthOverhead: RPCLupine.DataLength =
SIZE[RPCPkt.Header] + 1
--checksum--;
Difference between RPCLupine.DataLength and transmitted Pup length for unencrypted packets
SetupResponse:
PROC [header:
LONG
POINTER
TO RPCPkt.Header] =
INLINE
BEGIN
header.destHost ← header.srceHost;
header.destSoc ← PupWKS.rpc;
header.destPSB ← header.srcePSB;
header.outcome ← result;
END;
PktExchangeState: TYPE = { receiving, sending, call, endCall, authReq };
PktExchange:
PROC[inPkt: RPCLupine.RPCPkt, length: RPCLupine.DataLength,
maxlength: RPCLupine.DataLength,
state: PktExchangeState,
signalHandler: RPCLupine.Dispatcher ← NIL]
RETURNS[newPkt: BOOLEAN, newLength: RPCLupine.DataLength];
Reliable transmission of given packet, and receipt of next packet; "newLength" is data length of incoming packet, if any.
IdleReceive:
PROC[pkt: RPCLupine.RPCPkt, maxlength:
CARDINAL];
Returns when new packet arrives; "maxlength" is number of words in the pkt buffer starting from pkt.header (total, including all overheads)
EnqueueAgain:
PROC [b: PupBuffer.Buffer];
Dispatches packet to appropriate process; used by idler processes to requeue pkt that had incorrect destPSB.
IsDecrypted:
PROC[header:
LONG
POINTER
TO RPCPkt.Header]
RETURNS [decrypted: BOOL] = INLINE {
RETURN[header.type.subType = decryptedRpc];
};
SetDecrypted:
PROC[header:
LONG
POINTER
TO RPCPkt.Header] =
INLINE {
header.type.subType ← decryptedRpc;
};
END.
Swinehart, January 16, 1987 5:59:12 pm PST
state of encryption is now reliably encoded in received packets.
changes to: EnqueueAgain, IsDecrypted, END, IsDecrypted