-- File: PupRouterDefs.Mesa,  Last Edit:
  -- MAS  April 17, 1980  8:38 PM
  -- HGM  October 15, 1979  10:42 PM
  -- Taft  April 18, 1983  1:59 PM

-- Copyright  Xerox Corporation 1979, 1980

DIRECTORY
  DriverDefs: FROM "DriverDefs" USING [Network],
  BufferDefs: FROM "BufferDefs" USING [PupBuffer, Byte, PupHostID, PupNetID, QueueObject],
  PupTypes: FROM "PupTypes" USING [Pair, PupAddress, PupErrorCode];

PupRouterDefs: DEFINITIONS =
BEGIN OPEN DriverDefs, BufferDefs;


BeSurePupIsOn: PROCEDURE;

NextPupConnectionID: PROCEDURE RETURNS [PupTypes.Pair];
PupRouterKnowAboutSocket: PROCEDURE [PupRouterSocket];
PupRouterForgetAboutSocket: PROCEDURE [PupRouterSocket];
GetFirstPupSocket: PROCEDURE RETURNS [PupRouterSocket];
PupRouterSocket: TYPE = POINTER TO PupRouterSocketObject;
PupRouterSocketObject: TYPE = RECORD [
  next: PupRouterSocket,
  local: PupTypes.PupAddress,
  remote: PupTypes.PupAddress,  -- this lives here only for debugging
  ready: CONDITION,
  input: QueueObject,
  checkit: BOOLEAN,
  id: PupTypes.Pair ]; -- only used by listeners

SetPupChecksum: PROCEDURE [PupBuffer];
TestPupChecksum: PROCEDURE [PupBuffer] RETURNS [BOOLEAN];
SetBadPupProc: PROCEDURE [PROCEDURE[PupBuffer]];

PupGatewaySee: PROCEDURE [PupBuffer] RETURNS [BOOLEAN];

GetPupRoutingTableEntry: PROCEDURE [
  net: PupNetID, ifMissing: IfMissing ← probeAndWait, promote: BOOLEAN ← TRUE]
  RETURNS [PupRoutingTableEntry];
IfMissing: TYPE = {return, probeAndReturn, probeAndWait};
PupRoutingTableEntry: TYPE = RECORD [
  hop: Byte,
  time: Byte,
  route: PupHostID,
  network: DriverDefs.Network ];
maxHop: CARDINAL = 15;

-- Format of one slot of routing info from gateways, in routing info pups.
PupGateInfo: TYPE = MACHINE DEPENDENT RECORD [net, viaNet, viaHost, hop: Byte];

-- Dispatcher interface
PupInputer: PROCEDURE [PupBuffer];
PupBroadcaster: PROCEDURE [PupBuffer];
ForwardThisPupBuffer: PROCEDURE [PupBuffer];
SneakySendUnlocked: PROCEDURE [PupBuffer];
RejectPupWithBadChecksum: PROCEDURE [PupBuffer];
Reject: PROCEDURE [PupBuffer, PupErrorCode];
Timeout: PROCEDURE;
Prober: PROCEDURE;

-- misc routines
PupErrorCode: TYPE = PupTypes.PupErrorCode;
BuildErrorPup: PROCEDURE [PupBuffer, PupErrorCode, STRING] RETURNS [ok: BOOLEAN];


-- SemiPublic things from PupRouter

-- These must be called from within the monitor
GetRoutingCacheEntry: PROCEDURE [
  net: PupNetID, ifMissing: IfMissing ← probeAndWait, promote: BOOLEAN ← TRUE]
  RETURNS [POINTER TO RoutingCacheEntry];
InsertRoutingCacheEntry: PROCEDURE [net: PupNetID]
  RETURNS [POINTER TO RoutingCacheEntry];
DeleteRoutingCacheEntry: PROCEDURE [net: PupNetID];

RoutingCacheEntry: TYPE = RECORD [
  next: POINTER TO RoutingCacheEntry,
  net: CARDINAL, -- net number, or emptyCacheEntry if entry not in use
  entry: PupRoutingTableEntry];

emptyCacheEntry: CARDINAL = LAST[CARDINAL];

routerLock: MONITORLOCK;
routingTableUpdateTimeout: CONDITION;
probeResponse: CONDITION;
pleaseProbe: CONDITION;
probeRetransmitTimeout: CONDITION;
probesLeftToDo: CARDINAL;
routingCacheHead, routingCacheTail: POINTER TO RoutingCacheEntry;
numberOfRoutingCacheEntries: CARDINAL;
dataWordsPerPup: CARDINAL;
pupRouterIsActive: BOOLEAN;
firstSocket: PupRouterSocket;

outThings: OutThings;
OutThings: TYPE = RECORD [
  outStormy: BOOLEAN,
  showOut: BOOLEAN,
  outShower: PROCEDURE [CARDINAL,PupBuffer] ];

inThings: InThings;
InThings: TYPE = RECORD [
  inStormy: BOOLEAN,
  watcherIsWatching: BOOLEAN,
  watcherSeesBroadcast: BOOLEAN,
  watcherCallsThis: PROCEDURE [PupBuffer] RETURNS [BOOLEAN],
  badChecksumProc: PROCEDURE [PupBuffer],
  showIn: BOOLEAN,
  inShower: PROCEDURE [CARDINAL,PupBuffer] ];

Checksum: TYPE = {none, software, alto};
checksum: Checksum;

PupRouterCold, PupRouterOut, PupRouterIn, PupChecksums: PROGRAM;
PupSockets, PupErrors: PROGRAM;

END.