-- File:  Sequin.mesa
-- Last edited by Levin:   3-Feb-82  9:25:20
-- Derived (after extensive discussions with Wobber) from Butterfield's
--    SequinDefs of October 27, 1978  10:24 AM.

DIRECTORY
  Environment USING [Byte],
  PupTypes USING [PupType],
  PupDefs USING [PupAddress];

Sequin: DEFINITIONS =

  BEGIN


  -- A Sequin is a full-duplex, sequential stream of packets.  This interface provides
  -- simplified access to the Sequin facilities, and may be extended to span more of
  -- them in the future.


  -- Types and Related Constants --

  Handle: TYPE[2];

  Buffer: TYPE = RECORD [
    data: -- READONLY -- LONG POINTER TO BufferData,
    nBytes: CARDINAL,
    maxBytes: -- READONLY -- CARDINAL];
  -- A Buffer is used to describe the data to be passed over a Sequin.  All actual
  -- storage management is provided by the Sequin implementation; clients may not
  -- fabricate their own Buffer descriptions and pass them in.  (In reality, a Buffer
  -- is part of a Pup buffer; therefore, no copying of data occurs within the Sequin
  -- implementation.)  The client obtains a Buffer either from 'Get', 'GetIfAvailable',
  -- or 'GetEmptyBuffer' and is considered to be using the buffer until it is passed
  -- back via 'Put' or 'ReleaseBuffer'.  The 'nBytes' field indicates the number of
  -- valid bytes of data presently contained in the buffer; the 'maxBytes' field is the
  -- number of bytes of space available, beginning at address 'data'.

  BufferData: TYPE = RECORD [
    SELECT OVERLAID * FROM
      words => [words: ARRAY [0..0) OF WORD],
      bytes => [bytes: ARRAY [0..0) OF Environment.Byte],
      chars => [chars: ARRAY [0..0) OF CHARACTER],
      ENDCASE];

  noBuffer: Buffer = [NIL, 0, 0];


  -- Procedures and Signals --

  Broken: ERROR;
  -- the Sequin connection has been broken.  This exception may be raised by 'Get',
  -- 'GetIfAvailable', or 'Put' (not by 'Create' or 'Destroy').

  SetZone: PROCEDURE [z: UNCOUNTED ZONE] RETURNS [UNCOUNTED ZONE];
  -- alters the default zone for internal storage allocation, returning the zone
  -- that was previously in use.  This procedure may be called only when no
  -- Sequins exist.

  Create: PROCEDURE [dest: PupDefs.PupAddress, pupType: PupTypes.PupType]
    RETURNS [Handle];
  -- creates a Sequin with the port specified by 'dest'.  All packets exchanged
  -- over this connection will have pupType 'pupType', which is intended to suggest
  -- to the server what higher-level protocol (e.g., Leaf) is being used to structure
  -- the data passed through the Sequin.

  Destroy: PROCEDURE [sequin: Handle];
  -- The connection to the destination site is abandoned and the data structures
  -- for the indicated Sequin are destroyed.

  Get: PROCEDURE [sequin: Handle] RETURNS [Buffer];
  -- waits until incoming data is available from the Sequin, then returns a Buffer
  -- containing it.  If the server fails to respond in an appropriate amount of
  -- time, 'Broken' is raised.

  GetIfAvailable: PROCEDURE [sequin: Handle] RETURNS [Buffer];
  -- This procedure is similar to 'Get' except that it never waits.  If data is
  -- presently available from the server, an appropriate Buffer will be returned.
  -- Otherwise, 'noBuffer' will be returned. 

  Put: PROCEDURE [sequin: Handle, buffer: Buffer];
  -- The 'buffer' is transmitted to the destination site and subsequently released.
  -- The Sequin implementation is responsible for ensuring reliable transmission.  If
  -- the operation cannot be performed, 'Broken' will be raised (in which case an
  -- implicit 'ReleaseBuffer' will have occurred).

  GetEmptyBuffer: PROCEDURE RETURNS [Buffer];
  -- obtains a Buffer whose 'nBytes' field is zero.

  ReleaseBuffer: PROCEDURE [buffer: Buffer];
  -- The client is finished using 'buffer'.

  END.