-- Copyright (C) 1982, 1984  by Xerox Corporation. All rights reserved. 
-- RPCPkt.mesa, HGM, 21-Jan-84 20:39:05
-- Cedar 5, HGM, 21-Jan-84 20:38:14

-- RPC: layout of packets

-- [Ivy]<Birrell>RPC>RPCPkt.mesa

-- Andrew Birrell  16-Mar-82 11:46:26

DIRECTORY
  PSB USING [PsbIndex],
  Buffer USING [PupBuffer],
  PupTypes USING [PupHostID, PupNetID, PupSocketID],
  MesaRPCLupine USING [DataLength, Dispatcher, RPCPkt],
  RPCPrivate USING [rpcSocket];

RPCPkt: DEFINITIONS SHARES MesaRPCLupine =

  BEGIN


  -- ******** Layout of stub-packets ******** --

  Header: TYPE = MACHINE DEPENDENT RECORD [
    length(0:0..14): [0..77777B],
    oddByte(0:15..15): {no(0), yes(1)},
    type(1): PktType,
    destPSB(2): PSB.PsbIndex,  -- field has 6 extra bits
    srcePSB(3): PSB.PsbIndex,  -- field has 6 extra bits
    destHost(4): Machine,
    destSoc(5): PupTypes.PupSocketID,
    srceHost(7): Machine,
    srceSoc(8): PupTypes.PupSocketID,
    -- end of standard Pup header --
    conv(10): PktConversationID,
    -- For secure conversations, the remainder of the packet must be encrypted --
    pktID(12): PktID,
    call(16): SELECT OVERLAID * FROM
      calling => [dispatcher(16): DispatcherDetails],
      responding => [
        outcome(16): Outcome,
        fill(17): ARRAY [SIZE[Outcome]..SIZE[DispatcherDetails]) OF WORD],
      ENDCASE];

  PktType: TYPE = MACHINE DEPENDENT RECORD [  -- "type" word of a Pup --
    transport(0:0..7): [0..255],  -- should be zero before sending --
    subType(0:8..10): {rpc(3B), (7B)},
    eom(0:11..11): {end(0), notEnd(1)},
    ack(0:12..12): {dontAck(0), pleaseAck(1)},
    class(0:13..15): {call(0), data(1), ack(2), rfa(4), (7)}];

  -- Mapping from Pup pkt types to RPC pkt types:
  --   140B = [end,    dontAck,   call ]
  --   141B = [end,    dontAck,   data ]
  --   142B = [,       dontAck,   ack  ] (also 162B)
  --   143B = unused (also 163B)
  --   144B = [,       dontAck,   rfa  ] (also 164B)
  --   150B = [end,    pleaseAck, call ]
  --   151B = [end,    pleaseAck, data ]
  --   152B = [,       pleaseAck, ack  ] (also 172B)
  --   153B = unused (also 173B)
  --   154B = [,       pleaseAck, rfa  ] (also 174B)
  --   160B = [notEnd, dontAck,   call ]
  --   161B = [notEnd, dontAck,   data ]
  --   170B = [notEnd, pleaseAck, call ]
  --   171B = [notEnd, pleaseAck, data ]

  pktLengthOverhead: MesaRPCLupine.DataLength = SIZE[Header] + 1 --checksum-- ;
  -- Difference between MesaRPCLupine.DataLength and transmitted Pup length
  -- for unencrypted packets --

  Machine: TYPE = MACHINE DEPENDENT RECORD [
    -- Unambiguous name of a host
    net: PupTypes.PupNetID, host: PupTypes.PupHostID];

  HostConversationID: TYPE = MACHINE DEPENDENT RECORD [
    -- Host-relative ID of a conversation; unique for all time --
    ls(0): CARDINAL, ms(1): [0..77777B]];

  ConversationID: TYPE = RECORD [
    -- Absolute ID of a conversation; unique for all hosts and all time --
    originator: Machine, count: HostConversationID];

  PktConversationID: TYPE = MACHINE DEPENDENT RECORD [
    -- Same as ConversationID, but abbreviated for within a packet --
    -- Assumes originator is always caller or callee --
    ls(0): CARDINAL,
    originator(1:0..0): {caller, callee},
    ms(1:1..15): [0..77777B]];

  ConnectionID: TYPE = MACHINE DEPENDENT RECORD [
    -- Uniquely identifies an independent sequence of calls --
    conv(0): PktConversationID, caller(2): Machine, activity(3): PSB.PsbIndex];

  CallCount: TYPE = LONG CARDINAL
  -- [ConnectionID,CallCount] uniquely identifies call for all hosts and time -- ;

  PktID: TYPE = MACHINE DEPENDENT RECORD [
    -- [ConversationID,PktID] uniquely identifies pkt for all hosts and time --
    activity(0): PSB.PsbIndex,  -- field has 6 extra bits--
    callSeq(1): CallCount,
    pktSeq(3): CARDINAL];

  Outcome: TYPE = MACHINE DEPENDENT{  -- possible responses to call or signal --
    result(0), -- normal -- unbound(1),  -- dispatcher not known --
    signal(2),  -- signal propagation --
    unwind(3),  -- signal is unwinding --
    protocol(4),  -- stub protocol error detected --
    (LAST[CARDINAL])  -- room for expansion? --
    };

  DispatcherDetails: TYPE = MACHINE DEPENDENT RECORD [
    mds: CARDINAL,  -- top half of dispatcher's MDS base address --
    dispatcherID: DispatcherID,  -- exporter-relative UID of interface instance --
    dispatcherHint: ExportHandle -- hint to exporter host's export table -- ];

  DispatcherID: TYPE = LONG CARDINAL;
  noDispatcher: DispatcherID = 0;
  ExportHandle: TYPE = CARDINAL;

  SetupResponse: PROC [header: LONG POINTER TO Header] = INLINE
    BEGIN
    header.destHost ← header.srceHost;
    header.destSoc ← RPCPrivate.rpcSocket;
    header.destPSB ← header.srcePSB;
    header.outcome ← result;
    END;



  -- ******** Single-packet communication: exported by RPCPktIO ******** --

  PktExchangeState: TYPE = {receiving, sending, call, endCall, authReq};

  PktExchange: PROC [
    inPkt: MesaRPCLupine.RPCPkt, length: MesaRPCLupine.DataLength,
    maxlength: MesaRPCLupine.DataLength, state: PktExchangeState,
    signalHandler: MesaRPCLupine.Dispatcher ← NIL]
    RETURNS [newPkt: BOOLEAN, newLength: MesaRPCLupine.DataLength];
  -- Reliable transmission of given packet, and receipt of next packet;
  -- "newLength" is data length of incoming packet, if any. --

  IdleReceive: PROC [pkt: MesaRPCLupine.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: PUBLIC PROC [b: Buffer.PupBuffer];

  END.