-- 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.