-- PacketStreamMgr.mesa (last edited by: Garlick on: January 23, 1981  4:17 PM)
-- Function: The implementation module for the manager of Pilot Packet Streams.

DIRECTORY
  CommunicationInternal USING [],
  CommFlags USING [doDebug],
  DriverDefs USING [Glitch],
  NetworkStream USING [],
  OISCP USING [uniqueAddress, unknownConnID],
  OISCPTypes USING [ConnectionID, WaitTime],
  PacketStream USING [
    FailureReason, Handle, SuspendReason, ClassOfService, WaitTime,
    defaultWaitTime],
  PacketStreamInstance USING [Delete],
  Router USING [AssignDestinationRelativeOisAddress],
  Runtime USING [GlobalFrame],
  SpecialSystem USING [NetworkAddress];

PacketStreamMgr: MONITOR
  IMPORTS Runtime, DriverDefs, pktStrmInst: PacketStreamInstance, Router
  EXPORTS CommunicationInternal, NetworkStream, PacketStream =
  BEGIN OPEN Router, PacketStream;

  -- These variables must eventually live in outerspace so that multiple MDSs
  -- access the same packet stream variables.  The module in the primary MDS will
  -- perform the initialization of the "globals", while the others will not.

  -- This module is a monitor in order to protect the value of spareConnectionID and the
  -- ConnectionTable.  Some day the connection IDs in use will be remembered across wrap
  -- around.

  primaryMDS: PUBLIC BOOLEAN ← TRUE; -- we are in the primary MDS.
  infiniteWaitTime: PUBLIC WaitTime ← LAST[WaitTime];
  initialSpareConnectionID: OISCPTypes.ConnectionID = [500];
  -- monitor data
  -- connectionID parameters
  spareConnectionID: OISCPTypes.ConnectionID;
  -- connectionTable parameters and types
  ConnectionTable: ARRAY (0..maxConnectionNumber] OF ConnectionTableEntry;
  maxConnectionNumber: CARDINAL = 20;
  index: CARDINAL ← 0;
  ConnectionTableEntry: TYPE = RECORD [
    rAddr: SpecialSystem.NetworkAddress, rConnID: OISCPTypes.ConnectionID];

  -- various Glitches.
  ConnectionTableFull: ERROR = CODE;
  NotInConnectionTable: ERROR = CODE;

  ConnectionSuspended: PUBLIC ERROR [why: SuspendReason] = CODE;
  ConnectionFailed: PUBLIC SIGNAL [why: FailureReason] = CODE;
  AttentionTimeout: PUBLIC ERROR = CODE;

  -- Cool Procedures

  -- This procedure creates a packet stream instance.  The local and remote addresses
  -- must be correctly specified, or else we pick defaults when possible.
  Make: PUBLIC PROCEDURE [
    local, remote: SpecialSystem.NetworkAddress,
    localConnID, remoteConnID: OISCPTypes.ConnectionID,
    establishConnection: BOOLEAN, timeout: OISCPTypes.WaitTime ← defaultWaitTime,
    classOfService: ClassOfService ← bulk] RETURNS [psH: PacketStream.Handle] =
    BEGIN
    estdRemoteAddr: SpecialSystem.NetworkAddress;
    estdRemoteConnID: OISCPTypes.ConnectionID;
    newPktStrmInst: POINTER TO FRAME[PacketStreamInstance] ← NEW pktStrmInst;
    BEGIN
    ENABLE UNWIND => newPktStrmInst.Delete[];
    -- If we do not have a local address we pick one with a network number that is a
    -- good way to get to the destinationand therefore a good way to get back to us!
    IF local = OISCP.uniqueAddress THEN
      local ← Router.AssignDestinationRelativeOisAddress[remote.net];
    IF localConnID = OISCP.unknownConnID THEN
      localConnID ← GetUniqueConnectionID[];
    [psH, estdRemoteAddr, estdRemoteConnID] ← START newPktStrmInst[
      local, remote, localConnID, remoteConnID, establishConnection, timeout,
      classOfService];
    InsertIntoConnectionTable[estdRemoteAddr, estdRemoteConnID];
    END;
    END; -- Create

  -- This procedure deletes the specified packet stream instance.

  Destroy: PUBLIC PROCEDURE [psH: PacketStream.Handle] =
    BEGIN
    oldPktStrmInst: POINTER TO FRAME[PacketStreamInstance] ←
      LOOPHOLE[Runtime.GlobalFrame[psH.get], POINTER];
    remote: SpecialSystem.NetworkAddress ← oldPktStrmInst.remoteAddr;
    remoteConnID: OISCPTypes.ConnectionID ← oldPktStrmInst.remoteConnectionID;
    oldPktStrmInst.Delete[];
    RemoveFromConnectionTable[remote, remoteConnID];
    END; -- Delete

  -- This procedure returns a unique connection ID.  Some day the active connection IDs
  -- in use will be kept around, so that on wrap around an unused ID will be assigned.

  GetUniqueConnectionID: ENTRY PROCEDURE RETURNS [iD: OISCPTypes.ConnectionID] =
    BEGIN
    iD ← spareConnectionID;
    IF (spareConnectionID ← [spareConnectionID + 1]) = OISCPTypes.ConnectionID[0]
      THEN spareConnectionID ← initialSpareConnectionID;
    END; -- GetUniqueConnectionID

  -- This procedure inserts a connection into the connectionTable.

  InsertIntoConnectionTable: PUBLIC ENTRY PROCEDURE [
    remote: SpecialSystem.NetworkAddress, remoteConnID: OISCPTypes.ConnectionID] =
    BEGIN
    IF (index ← index + 1) > maxConnectionNumber THEN
      IF CommFlags.doDebug THEN DriverDefs.Glitch[ConnectionTableFull];
    ConnectionTable[index] ← ConnectionTableEntry[remote, remoteConnID];
    END; -- InsertIntoConnectionTable

  -- This procedure removes a connection from the connectionTable.

  RemoveFromConnectionTable: PUBLIC ENTRY PROCEDURE [
    remote: SpecialSystem.NetworkAddress, remoteConnID: OISCPTypes.ConnectionID] =
    BEGIN
    i: CARDINAL;
    FOR i IN (0..index] DO
      IF ConnectionTable[i].rAddr.host = remote.host AND ConnectionTable[
	i].rAddr.socket = remote.socket AND ConnectionTable[i].rConnID =
	remoteConnID THEN
	BEGIN
	ConnectionTable[i] ← ConnectionTable[index];
	index ← index - 1;
	RETURN;
	END;
      ENDLOOP;
    IF CommFlags.doDebug THEN DriverDefs.Glitch[NotInConnectionTable];
    END; -- RemoveFromConnectionTable

  -- This procedure checks if there is a similar connection in the connectionTable.

  ConnectionAlreadyThere: PUBLIC ENTRY PROCEDURE [
    remote: SpecialSystem.NetworkAddress, remoteConnID: OISCPTypes.ConnectionID]
    RETURNS [BOOLEAN] =
    BEGIN
    i: CARDINAL;
    FOR i IN (0..index] DO
      IF ConnectionTable[i].rAddr.host = remote.host AND ConnectionTable[
	i].rAddr.socket = remote.socket AND ConnectionTable[i].rConnID =
	remoteConnID THEN RETURN[TRUE];
      ENDLOOP;
    RETURN[FALSE];
    END; -- ConnectionAlreadyThere

  -- initialization

  IF primaryMDS THEN spareConnectionID ← initialSpareConnectionID;

  END. -- of PacketStreamMgr module

LOG
Time: January 23, 1981  4:17 PM   By: Garlick   Action: added classOfService to Make.