-- File: TcpMgr.mesa - last edit:
-- AOF 3-Mar-88 14:14:48
-- JAV 4-May-87 11:59:34
-- SMA 14-Apr-86 12:19:10
-- Copyright (C) 1985, 1986, 1987, 1988 by Xerox Corporation. All rights reserved.
DIRECTORY
ArpaFlags USING [doDebug],
ArpaPort USING [AssignPort, nullPort],
ArpaPortInternal USING [AddrMatch, BuildMasks],
ArpaRouter USING [InternetAddress, GetAddress, unknownInternetAddress, Port],
ArpaTypes USING [InternetAddress, Port],
CommHeap USING [zone],
Driver USING [Glitch],
Environment USING [Block],
Runtime USING [GlobalFrame, UnNew],
TcpImpl USING [connection, start, stop],
TcpStream USING [defaultWaitTime, FailureReason, Handle,
infiniteWaitTime, NotifyListenStartedProc, Precedence, Security,
SuspendReason, WaitTime];
TcpMgr: MONITOR
IMPORTS
ArpaPort, ArpaPortInternal, ArpaRouter, CommHeap, Driver,
Runtime, tcpStrmInst: TcpImpl, TcpStream
EXPORTS ArpaRouter, TcpStream =
BEGIN
InternetAddress: PUBLIC <<ArpaRouter>> TYPE = ArpaTypes.InternetAddress;
Port: PUBLIC <<ArpaRouter>> TYPE = ArpaTypes.Port;
Instance: TYPE = LONG POINTER TO FRAME[TcpImpl];
instance0: Instance ← NIL;
connection: PUBLIC RECORD[
head: ConnTableEntry,
active: CARDINAL] ← [NIL, 0];
ConnTableEntry: TYPE = LONG POINTER TO ConnTableObject;
ConnTableObject: TYPE = RECORD [
next: ConnTableEntry,
remote: InternetAddress,
remotePort: Port];
infiniteWaitTime: PUBLIC TcpStream.WaitTime ← LAST[TcpStream.WaitTime];
uniqueAddr: PUBLIC InternetAddress ← ArpaRouter.unknownInternetAddress;
uniquePort: PUBLIC Port ← ArpaPort.nullPort;
--Errors and glitches
NotInConnectionTable: ERROR = CODE;
ListenTimeout: PUBLIC SIGNAL = CODE;
Suspended: PUBLIC ERROR [why: TcpStream.SuspendReason] = CODE;
Failed: PUBLIC SIGNAL [why: TcpStream.FailureReason] = CODE;
Closing: PUBLIC SIGNAL = CODE;
Closed: PUBLIC ERROR = CODE;
ConnectionAlreadyThere: PUBLIC ENTRY PROC[
remote: InternetAddress, remotePort: Port]
RETURNS [BOOLEAN] =
BEGIN
e: ConnTableEntry;
FOR e ← connection.head, e.next UNTIL e = NIL DO
IF (ArpaPortInternal.AddrMatch[
ArpaPortInternal.BuildMasks[e.remote].hostMask, e.remote, remote])
AND (e.remotePort = remotePort) THEN
RETURN[TRUE];
ENDLOOP;
RETURN[FALSE];
END; --ConnectionAlreadyThere
Destroy: PUBLIC PROC [tsH: TcpStream.Handle] =
BEGIN
instanceN: Instance ← GlobalFrameFromStream[tsH];
remote: InternetAddress ← instanceN.connection.remoteAddr;
remotePort: Port ← instanceN.connection.remotePort;
instanceN.stop[]; --stop the instance
UnnewInstance[instanceN]; --delete his frame, maybe
RemoveConnection[remote, remotePort]; --remove state
END; --Destroy
GlobalFrameFromStream: PUBLIC PROC [tsH: TcpStream.Handle]
RETURNS[LONG POINTER --TO FRAME[TcpImpl]--] =
{RETURN[LOOPHOLE[Runtime.GlobalFrame[LOOPHOLE[tsH.get]]]]};
InsertConnection: ENTRY PROC[remote: InternetAddress, remotePort: Port] =
BEGIN
ENABLE UNWIND => NULL;
e: ConnTableEntry;
connection.active ← connection.active + 1;
e ← CommHeap.zone.NEW[ConnTableObject ← [
next: connection.head, remote: remote, remotePort: remotePort]];
connection.head ← e;
END; --InsertConnection
Listen: PUBLIC PROC [
localPort: ArpaRouter.Port,
listenTimeout: TcpStream.WaitTime ← TcpStream.infiniteWaitTime,
receiveTimeout: TcpStream.WaitTime ← TcpStream.defaultWaitTime,
precedence: TcpStream.Precedence ← routine,
security: TcpStream.Security ← NIL,
options: Environment.Block ← [NIL, 0, 0],
notifyListenerStarted: TcpStream.NotifyListenStartedProc ← NIL]
RETURNS [tsH: TcpStream.Handle] =
BEGIN
me: InternetAddress ← ArpaRouter.GetAddress[];
tsH ← Make[me, ArpaRouter.unknownInternetAddress, localPort,
ArpaPort.nullPort, FALSE, listenTimeout, precedence, security, options, notifyListenerStarted];
tsH.setWaitTime[receiveTimeout];
END; --Listen
Make: PUBLIC PROC[local, remote: InternetAddress,
localPort, remotePort: Port, establishConnection: BOOLEAN,
timeout: TcpStream.WaitTime, precedence: TcpStream.Precedence,
security: TcpStream.Security, options: Environment.Block,
notifyListenerStarted: TcpStream.NotifyListenStartedProc ← NIL]
RETURNS [tsH: TcpStream.Handle] =
BEGIN
GetInstance: ENTRY PROC = INLINE
{IF instance0 # NIL THEN instanceN ← NEW tcpStrmInst
ELSE instance0 ← instanceN ← tcpStrmInst};
instanceN: Instance;
estdRemotePort: Port;
estdRemoteAddr: InternetAddress;
GetInstance[]; --get instance's global frame
BEGIN
ENABLE UNWIND => {instanceN.stop[]; UnnewInstance[instanceN]};
IF instanceN # instance0 THEN START instanceN; --make the globals real
IF local = ArpaRouter.unknownInternetAddress THEN
local ← ArpaRouter.GetAddress[];
IF localPort = Port[0] THEN localPort ← ArpaPort.AssignPort[];
[tsH, estdRemoteAddr, estdRemotePort] ← instanceN.start[
local, remote, localPort, remotePort, timeout, precedence, security,
options, establishConnection, notifyListenerStarted];
tsH.destroy ← Destroy; --this is not instance oriented
InsertConnection[estdRemoteAddr, estdRemotePort];
END;
END; --Make
RemoveConnection: ENTRY PROC[remote: InternetAddress, remotePort: Port] =
BEGIN
e, prev: ConnTableEntry;
e ← connection.head;
UNTIL e = NIL DO
IF (ArpaPortInternal.AddrMatch[
ArpaPortInternal.BuildMasks[e.remote].hostMask, e.remote, remote])
AND (e.remotePort = remotePort) THEN
BEGIN
IF e = connection.head THEN connection.head ← e.next
ELSE prev.next ← e.next;
CommHeap.zone.FREE[@e];
connection.active ← connection.active - 1;
RETURN;
END;
prev ← e;
e ← e.next;
ENDLOOP;
IF ArpaFlags.doDebug THEN Driver.Glitch[NotInConnectionTable];
END; --RemoveConnection
UnnewInstance: ENTRY PROC [nth: Instance] = INLINE
{IF nth = instance0 THEN instance0 ← NIL ELSE Runtime.UnNew[LOOPHOLE[nth]]};
--initialization
START tcpStrmInst; --always start the first copy
END..
LOG
13-Nov-85 15:12:32 SMA Created file.
10-Jan-86 10:39:17 SMA ALL compares via AddrMatch or AddrMismatch.
3-Mar-88 13:59:43 AOF Use of global start/stop procs and export ArpaPort types.