-- Copyright (C) 1981, 1984, 1985  by Xerox Corporation. All rights reserved. 
-- Transport Mechanism - DEFS for communication protocols --
-- ProtocolDefs.mesa, HGM, 15-Sep-85  3:00:52

-- Andrew Birrell  21-Jan-81 17:27:35 --

DIRECTORY
  BodyDefs USING [
    Connect, ItemHeader, maxConnectLength, maxRemarkLength, oldestTime, Password,
    Remark, RName, Timestamp],
  PupTypes USING [PupAddress, PupSocketID],
  Stream USING [SubSequenceType, Handle];

ProtocolDefs: DEFINITIONS =
  BEGIN

  -- The following are defined for historical compatability.
  -- The definitions in BodyDefs should be used in preference.
  Connect: TYPE = BodyDefs.Connect;
  maxConnectLength: CARDINAL = BodyDefs.maxConnectLength;
  Remark: TYPE = BodyDefs.Remark;
  maxRemarkLength: CARDINAL = BodyDefs.maxRemarkLength;
  Password: TYPE = BodyDefs.Password;



  MakeKey: PROC [password: LONG STRING] RETURNS [key: BodyDefs.Password];
  -- makes DES encryption key; forces lower case --


  Init: PROC;
  -- initialize exported variables; extra calls ignored --

  SetTestingMode: PROC;
  -- set sockets for test-only mode; called before Init --


  RegServerEnquirySocket: READONLY PupTypes.PupSocketID;  -- [0, 50B] --
  -- for talking to the Registration Server.

  RegServerSpareSocket: READONLY PupTypes.PupSocketID;  -- [0, 51B] --

  RegServerPollingSocket: READONLY PupTypes.PupSocketID;  -- [0, 52B] --
  -- for single-packet protocols to RegServer --

  spareSocket: READONLY PupTypes.PupSocketID;  -- [0, 53B] --

  mailServerPollingSocket: READONLY PupTypes.PupSocketID;  -- [0,54B];
  -- For all single-packet protocols with mail server --

  mailServerServerSocket: READONLY PupTypes.PupSocketID;  -- [0,55B] --
  -- For ServerInput connections to mail server --

  mailServerInputSocket: READONLY PupTypes.PupSocketID;  -- [0,56B] --
  -- For ClientInput connections to mail server --

  mailServerOutputSocket: READONLY PupTypes.PupSocketID;  -- [0,57B] --
  -- For ReadMail connections to mail server --


  endSST: Stream.SubSequenceType = 1;
  -- used in Server-Server and ReadMail protocols --

  IsLocal: PROC [addr: PupTypes.PupAddress] RETURNS [BOOLEAN];
  -- Whether the address is on this host --

  Handle: TYPE = Stream.Handle;

  FailureReason: TYPE = {communicationError, noData, protocolError};
  -- communicationError means some error pup arrived
  -- noData means the stream is still there, but no data
  -- protocolError means we cant understand him

  Failed: ERROR [why: FailureReason];
  -- may be raised by any of the following procedures,
  -- except DestroyStream.

  CreateStream: PROC [addr: PupTypes.PupAddress, secs: CARDINAL ← 120]
    RETURNS [Handle];
  -- Create stream, with given timeout for data --

  DestroyStream: PROC [str: Handle];
  -- no signals --

  SendNow: PROC [str: Handle];
  -- Sends any data that has been buffered on the stream.


  -- The following procedures provide type-safe access to the communication
  -- protocols --


  SendAck: PROC [str: Handle] = INLINE {SendByte[str, 0]};

  ReceiveAck: PROC [str: Handle] = INLINE {[] ← ReceiveByte[str]};


  SendBoolean: PROC [str: Handle, bool: BOOLEAN] = INLINE {
    SendByte[str, IF bool THEN 1 ELSE 0]};

  ReceiveBoolean: PROC [str: Handle] RETURNS [BOOLEAN] = INLINE {
    RETURN[ReceiveByte[str] # 0]};


  Byte: TYPE = [0..256);

  SendByte: PROCEDURE [str: ProtocolDefs.Handle, byte: Byte];

  ReceiveByte: PROCEDURE [str: ProtocolDefs.Handle] RETURNS [byte: Byte];


  SendCount: PROC [str: Handle, count: CARDINAL];

  ReceiveCount: PROC [str: Handle] RETURNS [count: CARDINAL];


  SendItemHeader: PROC [str: Handle, header: BodyDefs.ItemHeader];
  -- transmits the header.

  ReceiveItemHeader: PROC [str: Handle] RETURNS [header: BodyDefs.ItemHeader];
  -- receive header of item from stream.


  SendTimestamp: PROC [str: Handle, stamp: BodyDefs.Timestamp];
  -- sends a Timestamp value over the stream.

  ReceiveTimestamp: PROC [str: Handle] RETURNS [BodyDefs.Timestamp];
  -- receives a timestamp from the stream.

  AppendTimestamp: PROC [s: LONG STRING, stamp: BodyDefs.Timestamp];
  -- appends a text form of the stamp to the string


  SendPassword: PROC [str: Handle, key, pw: BodyDefs.Password];
  -- encodes a password with a key, and sends the
  -- encrypted verion.

  ReceivePassword: PROC [str: Handle, key: BodyDefs.Password] RETURNS [Password];
  -- receives an encoded password from the stream, and
  -- returns the decoded value.


  SendRC: PROC [str: Handle, rc: ReturnCode];
  -- sends a return code value over the stream.

  ReceiveRC: PROC [str: Handle] RETURNS [ReturnCode];
  -- receives a return code value from the stream.


  SendMSOperation: PROC [str: Handle, op: MSOperation];

  ReceiveMSOperation: PROC [str: Handle] RETURNS [op: MSOperation];


  SendRSOperation: PROC [str: Handle, op: RSOperation];

  ReceiveRSOperation: PROC [str: Handle] RETURNS [op: RSOperation];


  SendBytes: PROC [str: ProtocolDefs.Handle, buffer: LONG POINTER, count: CARDINAL];

  ReceiveBytes: PROC [str: ProtocolDefs.Handle, buffer: LONG POINTER, count: CARDINAL];


  SendRName: PROC [str: Handle, name: BodyDefs.RName] = INLINE {
    SendString[str, name]};
  -- transmits the contents of the R-Name.

  ReceiveRName: PROC [str: Handle, name: BodyDefs.RName] = INLINE {
    ReceiveString[str, name]};
  -- reads from the stream into the R-Name storage.


  SendConnect: PROC [str: Handle, connect: BodyDefs.Connect] = INLINE {
    SendString[str, connect]};
  -- sends the connect-site name as a Mesa string --
  -- connect.length should be < maxConnectLength --

  ReceiveConnect: PROC [str: Handle, connect: BodyDefs.Connect] = INLINE {
    ReceiveString[str, connect]};
  -- receives a connect-site into the given storage --


  SendRemark: PROC [str: Handle, remark: BodyDefs.Remark] = INLINE {
    SendString[str, remark]};
  -- sends the remakr as a Mesa string --
  -- remark.length should be < maxRemarkLength --

  ReceiveRemark: PROC [str: Handle, remark: BodyDefs.Remark] = INLINE {
    ReceiveString[str, remark]};
  -- receives a remark into the given storage --


  SendString: PROC [str: ProtocolDefs.Handle, string: LONG STRING];

  ReceiveString: PROC [str: ProtocolDefs.Handle, string: LONG STRING];


  Enquire: PROC [
    str: Handle, op: RSOperation, name: BodyDefs.RName,
    oldStamp: BodyDefs.Timestamp ← BodyDefs.oldestTime]
    RETURNS [rc: ReturnCode, stamp: BodyDefs.Timestamp];
  -- Sends an enquiry on the stream --

  ReceiveRList: PROCEDURE [str: Handle, work: PROCEDURE [BodyDefs.RName]];
  -- receives a sequence of R-Names from the stream,
  -- calling "work" for each R-Name.  The sequence should
  -- have been sent by HeapDefs.SendComponent or its
  -- equivalent. See also HeapDefs.ReceiveComponent--


  MSOperation: TYPE = MACHINE DEPENDENT{

    openMBX(0), nextMessage(1), readTOC(2), readMessage(3), writeTOC(4),
    deleteMessage(5), flushMBX(6), restartMBX(7),

    startSend(20), addRecipient(21), checkValidity(22), startItem(23),
    addToItem(24), send(26), expand(27), (255)};


  RNameType: TYPE = MACHINE DEPENDENT{
    -- status of an RName, given in an R-Server reply.
    group(0),  -- group of names
    individual(1),  -- person or machine
    notFound(2),  -- the R-Name does not exist
    dead(3),  -- the R-Name has been deleted from the database
    (255)};


  Code: TYPE = MACHINE DEPENDENT{
    -- result of an R-Server operation.
    done(0),  -- operation succeeded
    noChange(1),  -- enquiry: given stamp was still valid
    -- update:  operation wouldn't change the database
    outOfDate(2),  -- update:  more recent info was in database (!)
    NotAllowed(3),  -- update:  operation prevented by access controls
    BadOperation(4),  -- unknown operation number
    BadProtocol(5),  -- protocol violation (e.g. list out of order)
    BadRName(6),  -- R-Name does not exist or has wrong type
    BadPassword(7),  -- what it says
    WrongServer(8),  -- the R-Name's registry is not in this R-Server
    AllDown(9),  -- remote R-Server was down for ACL enquiry
    (255)};


  ReturnCode: TYPE = MACHINE DEPENDENT RECORD [code: Code, type: RNameType];


  RSOperation: TYPE = MACHINE DEPENDENT{

    -- an "R-Name", "destn", "member", "owner", or "friend" has type BodyDefs.RName
    -- a "Connect" has type BodyDefs.Connect
    -- a "site" has type BodyDefs.RName (but may be an NLS name or net address)
    -- a "Remark" has type BodyDefs.Remark
    -- a "Password" has type BodyDefs.Password
    -- a "stamp" has type BodyDefs.Timestamp
    -- an "R-List" is a word count (CARDINAL) followed by sequence of R-Names;
    --	the R-Names are in alphabetical order.
    -- a "component" is a word count (CARDINAL) followed by sequence of words
    -- a "Membership" is a boolean ("TRUE" => is a member)


    --			arguments		results
    --			=========		=======
    --
    -- ENQUIRY OPERATIONS

    NoOp(0),  --	none			none

    Expand(1),  --	R-Name,stamp		code=done,stamp,R-List
    --				  group:      R-List=members
    --				  individual: R-List=sites
    --				  forwarded:  R-List=destn's,type=group
    --			or:	code=noChange
    --			or:	code=BadRName(dead,notFound)
    --			or:	code=WrongServer
    -- This also works for names of the form Owners-foo.pa

    ReadMembers(2),  --	R-Name,stamp		code=done,stamp,R-List
    --			or:	code=noChange
    --			or:	code=BadRName(#group)
    --			or:	code=WrongServer
    -- This also works for names of the form Owners-foo.pa

    ReadOwners(3),  --	R-Name,stamp		code=done,stamp,R-List
    --			or:	code=noChange
    --			or:	code=BadRName(#group)
    --			or:	code=WrongServer

    ReadFriends(4),  --	R-Name,stamp		code=done,stamp,R-List
    --			or:	code=noChange
    --			or:	code=BadRName(#group)
    --			or:	code=WrongServer

    ReadEntry(5),  --	R-Name,stamp		code=done,stamp,count,components
    --			or:	code=noChange
    --			or:	code=BadRName(notFound)
    --			or:	code=WrongServer

    CheckStamp(6),  --	R-Name,stamp		code=done,stamp
    --			or:	code=noChange
    --			or:	code=BadRName(notFound)
    --			or:	code=WrongServer
    -- This also works for names of the form Owners-foo.pa

    ReadConnect(7),  --	R-Name			code=done,connect
    --			or:	code=BadRName(#individual)
    --			or:	code=WrongServer

    ReadRemark(8),  --	R-Name			code=done,remark
    --			or:	code=BadRName(#group)
    --			or:	code=WrongServer

    Authenticate(9),  --	R-Name,Password		code=done
    --			or:	code=BadPassword
    --			or:	code=BadRName(#individual)
    --			or:	code=WrongServer

    -- more enquiries at 60: the grotty compiler won't let me put them here!

    -- UPDATE OPERATIONS

    CreateRegistry(10),  -- NOT IMPLEMENTED --

    DeleteRegistry(11),  -- NOT IMPLEMENTED --

    CreateIndividual(12),  --	R-Name,Password		code=done
    --			or:	code=NotAllowed
    --			or:	code=noChange
    --			or:	code=BadRName(group)
    --			or:	code=OutOfDate(!)
    --			or:	code=WrongServer

    DeleteIndividual(13),  --	R-Name			code=done
    --			or:	code=NotAllowed
    --			or:	code=noChange
    --			or:	code=BadRName(#individual)
    --			or:	code=OutOfDate(!)
    --			or:	code=WrongServer

    CreateGroup(14),  --	R-Name			code=done
    --			or:	code=NotAllowed
    --			or:	code=noChange
    --			or:	code=BadRName(individual)
    --			or:	code=OutOfDate(!)
    --			or:	code=WrongServer

    DeleteGroup(15),  --	R-Name			code=done
    --			or:	code=NotAllowed
    --			or:	code=noChange
    --			or:	code=BadRName(#group)
    --			or:	code=OutOfDate(!)
    --			or:	code=WrongServer

    ChangePassword(16),  --	R-Name,Password		code=done
    --			or:	code=NotAllowed
    --			or:	code=noChange
    --			or:	code=BadRName(#individual)
    --			or:	code=OutOfDate(!)
    --			or:	code=WrongServer

    ChangeConnect(17),  --	R-Name,Connect		code=done
    --			or:	code=NotAllowed
    --			or:	code=noChange
    --			or:	code=BadRName(#individual)
    --			or:	code=OutOfDate(!)
    --			or:	code=WrongServer

    ChangeRemark(18),  --	R-Name,Remark		code=done
    --			or:	code=NotAllowed
    --			or:	code=noChange
    --			or:	code=BadRName(#group)
    --			or:	code=OutOfDate(!)
    --			or:	code=WrongServer

    AddMember(19),  --	R-Name,member		code=done
    --			or:	code=NotAllowed
    --			or:	code=noChange
    --			or:	code=BadRName(#group)
    --			or:	code=OutOfDate(!)
    --			or:	code=WrongServer

    AddMailBox(20),  --	R-Name,site		code=done
    --			or:	code=NotAllowed
    --			or:	code=noChange
    --			or:	code=BadRName(#individual)
    --			or:	code=OutOfDate(!)
    --			or:	code=WrongServer

    AddForward(21),  --	R-Name,destn		code=done
    --			or:	code=NotAllowed
    --			or:	code=noChange
    --			or:	code=BadRName(#individual)
    --			or:	code=OutOfDate(!)
    --			or:	code=WrongServer

    AddOwner(22),  --	R-Name,owner		code=done
    --			or:	code=NotAllowed
    --			or:	code=noChange
    --			or:	code=BadRName(#group)
    --			or:	code=OutOfDate(!)
    --			or:	code=WrongServer

    AddFriend(23),  --	R-Name,friend		code=done
    --			or:	code=NotAllowed
    --			or:	code=noChange
    --			or:	code=BadRName(#group)
    --			or:	code=OutOfDate(!)
    --			or:	code=WrongServer

    DeleteMember(24),  --	R-Name,member		code=done
    --			or:	code=NotAllowed
    --			or:	code=noChange
    --			or:	code=BadRName(#group)
    --			or:	code=OutOfDate(!)
    --			or:	code=WrongServer

    DeleteMailBox(25),  --	R-Name,site		code=done
    --			or:	code=NotAllowed
    --			or:	code=noChange
    --			or:	code=BadRName(#individual)
    --			or:	code=OutOfDate(!)
    --			or:	code=WrongServer

    DeleteForward(26),  --	R-Name,destn		code=done
    --			or:	code=NotAllowed
    --			or:	code=noChange
    --			or:	code=BadRName(#individual)
    --			or:	code=OutOfDate(!)
    --			or:	code=WrongServer

    DeleteOwner(27),  --	R-Name,owner		code=done
    --			or:	code=NotAllowed
    --			or:	code=noChange
    --			or:	code=BadRName(#group)
    --			or:	code=OutOfDate(!)
    --			or:	code=WrongServer

    DeleteFriend(28),  --	R-Name,friend		code=done
    --			or:	code=NotAllowed
    --			or:	code=noChange
    --			or:	code=BadRName(#group)
    --			or:	code=OutOfDate(!)
    --			or:	code=WrongServer

    AddSelf(29),  --	R-Name			code=done
    --			or:	code=NotAllowed
    --			or:	code=noChange
    --			or:	code=BadRName(#group)
    --			or:	code=OutOfDate(!)
    --			or:	code=WrongServer

    DeleteSelf(30),  --	R-Name			code=done
    --			or:	code=NotAllowed
    --			or:	code=noChange
    --			or:	code=BadRName(#group)
    --			or:	code=OutOfDate(!)
    --			or:	code=WrongServer

    AddListOfMembers(31),  -- adds multiple members; R-List must be alphabetical
    --	R-Name,R-List		code=done
    --			or:	code=NotAllowed
    --			or:	code=noChange
    --			or:	code=BadRName(#group)
    --			or:	code=OutOfDate(!)
    --			or:	code=WrongServer
    --			or:	code=BadProtocol(out of order)

    NewName(32),  -- creates a new entry with same content as given one;
    -- R-Names must be in same registry
    --	R-Name(dest),R-Name(srce)
    --				code=done
    --			or:	code=NotAllowed
    --			or:	code=BadRName(srce:notFound)
    --			or:	code=BadRName(dest:#notFound)
    --			or:	code=OutOfDate(!)
    --			or:	code=WrongServer
    --			or:	code=BadProtocol(different registries)

    IdentifyCaller(33),  -- must be called to permit updates
    --	R-Name,Password		code=done
    --			or:	code=BadPassword
    --			or:	code=BadRName(#individual)
    --			or:	code=AllDown


    -- ACCESS CONTROL ENQUIRIES --

    IsMemberDirect(40),  --	R-Name,member		code=done,Membership
    --			or:	code=BadRName(#group)
    --			or:	code=WrongServer
    -- This also works for names of the form Owners-foo.pa

    IsOwnerDirect(41),  --	R-Name,member		code=done,Membership
    --			or:	code=BadRName(#group)
    --			or:	code=WrongServer

    IsFriendDirect(42),  --	R-Name,member		code=done,Membership
    --			or:	code=BadRName(#group)
    --			or:	code=WrongServer

    IsMemberClosure(43),  --	R-Name,member		code=done,Membership
    --			or:	code=BadRName(#group)
    --			or:	code=WrongServer
    --			or:	code=AllDown

    IsOwnerClosure(44),  --	R-Name,member		code=done,Membership
    --			or:	code=BadRName(#group)
    --			or:	code=WrongServer
    --			or:	code=AllDown

    IsFriendClosure(45),  --	R-Name,member		code=done,Membership
    --			or:	code=BadRName(#group)
    --			or:	code=WrongServer
    --			or:	code=AllDown

    IsInList(46),  -- R-Name, member,
    -- {it(0),itsRegistry(1)}: byte,
    -- {member(0),owner(1),friend(2)}: byte,
    -- {direct(0),closure(1)}: byte
    --				code=done,Membership
    --			or:	code=BadRName(#group)
    --			or:	code=WrongServer
    --			or:	code=AllDown(for closure)


    -- 60..69 reserved for enquiries: see above

    ReadMailboxes(60),  --	R-Name,stamp		code=done,stamp,R-List
    --			or:	code=noChange
    --			or:	code=BadRName(#individual)
    --			or:	code=WrongServer



    (255)  --	undefined operations:	code=BadOperation

    };


  END.