-- Copyright (C) 1981, 1984  by Xerox Corporation. All rights reserved. 
-- MesaRPC.mesa, HGM, 21-Jan-84 21:39:48
-- Cedar 5, HGM, 21-Jan-84 20:35:44

-- MesaRPC.mesa is the Mesa-compatible public interface to the RPC runtime.
-- RPC.mesa defines the Cedar-compatible interface.

-- 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 = LONG STRING;


  -- Types for Import/Export calls

  InterfaceName: TYPE = RECORD [
    type: ShortSTRING ← NIL,  -- e.g. "AlpineAccess.Alpine"
    instance: 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 [gc, heap: UNCOUNTED ZONE ← NIL, mds: MDSZone ← NIL];

  standardZones: Zones = [];

  -- Encryption and Authentication facilities

  maxPrincipalLength: CARDINAL = MIN[  -- Limit on length of strings used for Principal
    maxShortStringLength, BodyDefs.maxRNameLength];

  Principal: TYPE = 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.