-- File: PacketStreamMgr.mesa - last edit: -- AOF 9-Sep-87 8:27:47 -- SMA 22-May-86 11:50:37 -- MXI 3-Nov-87 9:56:39 -- Copyright (C) 1984, 1985, 1986, 1987 by Xerox Corporation. All rights reserved. -- Function: The implementation module for the manager of Pilot Packet Streams. DIRECTORY CommunicationInternal USING [], CommFlags USING [doDebug], CommHeap USING [zone], Driver USING [Glitch], Inline USING [LowHalf], NewNetworkStream USING [NegotiationParameters, TSap], NSTypes USING [ConnectionID, WaitTime], PacketStream USING [ FailureReason, Handle, SuspendReason, ClassOfService, WaitTime, unknownConnID], NetworkStream USING [], NetworkStreamImpl USING [ connection, controlObject, newStartPacketStream, packetStreamObject, probe, startPacketStream, stopPacketStream, xmtr], Router USING [AssignDestinationRelativeAddress], Runtime USING [GlobalFrame, UnNew], SppNegotiation USING [NegotiationHints], SppOps USING [GlobalFrameFromByteStream, SppSpyProc], Socket USING [infiniteWaitTime], SocketInternal USING [SocketHandle], Stream USING [Handle], System USING [GetClockPulses, NetworkAddress, nullNetworkAddress]; PacketStreamMgr: MONITOR IMPORTS CommHeap, Driver, Inline, pktStrmInst: NetworkStreamImpl, Router, Runtime, SppOps, System EXPORTS CommunicationInternal, NetworkStream, PacketStream, SppNegotiation, SppOps = BEGIN sppWindowSize: PUBLIC <<SppOps>> CARDINAL[0..12] ← 4; --set default Instance: TYPE = LONG POINTER TO FRAME[NetworkStreamImpl]; ConnectionID: PUBLIC TYPE = NSTypes.ConnectionID; infiniteWaitTime: PUBLIC PacketStream.WaitTime ← Socket.infiniteWaitTime; --LEVEL 2 PROTOCOL SPY PROC sppSpy: SppOps.SppSpyProc ← NIL; --CONNECTION PARAMETERS connection: PUBLIC RECORD[ spareID: ConnectionID, head: ConnectionTableEntry, maximum, active: CARDINAL] ← [[0], NIL, 40, 0]; instance0: Instance ← NIL; ConnectionTableEntry: TYPE = LONG POINTER TO ConnectionTableObject; ConnectionTableObject: TYPE = RECORD [ next: ConnectionTableEntry, rAddr: System.NetworkAddress, rConnID: ConnectionID]; --various Glitches. NotInConnectionTable: ERROR = CODE; ConnectionSuspended: PUBLIC ERROR [why: PacketStream.SuspendReason] = CODE; ConnectionFailed: PUBLIC SIGNAL [why: PacketStream.FailureReason] = CODE; ConnectionAlreadyThere: PUBLIC ENTRY PROC[ remote: System.NetworkAddress, remoteConnID: ConnectionID] RETURNS [BOOLEAN] = BEGIN e: ConnectionTableEntry; FOR e ← connection.head, e.next UNTIL e = NIL DO IF (e.rAddr.host = remote.host) AND (e.rAddr.socket = remote.socket) AND (e.rConnID = remoteConnID) THEN RETURN[TRUE]; ENDLOOP; RETURN[FALSE]; END; --ConnectionAlreadyThere Destroy: PUBLIC PROC[psH: PacketStream.Handle] = BEGIN instanceN: Instance ← GlobalFrameFromPacketStream[psH]; remote: System.NetworkAddress ← instanceN.connection.remoteAddr; remoteConnID: ConnectionID ← instanceN.connection.remoteID; IF sppSpy # NIL THEN sppSpy[LOOPHOLE[instanceN], delete]; instanceN.stopPacketStream[]; --stop the proceses, etc UnnewInstance[instanceN]; --unload the frame RemoveConnection[remote, remoteConnID]; END; --Destroy DisableChecksums: PUBLIC <<SppOps>> PROC[psH: PacketStream.Handle] = BEGIN gf: Instance = NARROW[GlobalFrameFromPacketStream[psH]]; sH: SocketInternal.SocketHandle = LOOPHOLE[gf.connection.socket]; gf.xmtr.checksums ← FALSE; --that take care of local case sH.checksums ← FALSE; --and that takes care of all other cases END; --DisableChecksums EnableChecksums: PUBLIC <<SppOps>> PROC[psH: PacketStream.Handle] = BEGIN gf: Instance = NARROW[GlobalFrameFromPacketStream[psH]]; sH: SocketInternal.SocketHandle = LOOPHOLE[gf.connection.socket]; gf.xmtr.checksums ← TRUE; --that take care of local case sH.checksums ← TRUE; --and that takes care of all other cases END; --EnableChecksums DisableProbes: PUBLIC <<SppOps>> PROC[psH: PacketStream.Handle] = {NARROW[GlobalFrameFromPacketStream[psH], Instance].probe.probing ← FALSE}; EnableProbes: PUBLIC <<SppOps>> PROC[psH: PacketStream.Handle] = {NARROW[GlobalFrameFromPacketStream[psH], Instance].probe.probing ← TRUE}; GetUniqueConnectionID: PUBLIC ENTRY PROC RETURNS [iD: ConnectionID] = << Some day the connection IDs in use will be kept around, so that on wrap around an unused ID will be assigned. >> BEGIN iD ← connection.spareID; connection.spareID ← [connection.spareID + 1]; IF connection.spareID = PacketStream.unknownConnID THEN connection.spareID ← ConnectionID[1]; END; --GetUniqueConnectionID GlobalFrameFromPacketStream: PUBLIC <<SppOps>> PROC[psH: PacketStream.Handle] RETURNS[LONG POINTER --TO FRAME[NetworkStreamImpl]--] = {RETURN[LOOPHOLE[Runtime.GlobalFrame[LOOPHOLE[psH.get]]]]}; PacketStreamFromByteStream: PUBLIC <<SppOps>> PROC[sH: Stream.Handle] RETURNS[PacketStream.Handle] = BEGIN gf: Instance = SppOps.GlobalFrameFromByteStream[sH]; RETURN[@gf.packetStreamObject]; END; --PacketStreamFromByteStream ByteStreamFromPacketStream: PUBLIC <<SppOps>> PROC[psH: PacketStream.Handle] RETURNS[Stream.Handle] = BEGIN gf: Instance = GlobalFrameFromPacketStream[psH]; RETURN[@gf.controlObject.streamObject]; END; --ByteStreamFromPacketStream InsertConnection: ENTRY PROC[ remote: System.NetworkAddress, remoteConnID: ConnectionID] RETURNS [BOOLEAN] = BEGIN ENABLE UNWIND => NULL; e: ConnectionTableEntry; IF connection.active >= connection.maximum THEN RETURN[FALSE]; connection.active ← connection.active + 1; e ← CommHeap.zone.NEW[ConnectionTableObject ← [ next: connection.head, rAddr: remote, rConnID: remoteConnID]]; connection.head ← e; RETURN[TRUE]; END; --InsertConnection InsertIntoConnectionTable: PUBLIC PROC[ remote: System.NetworkAddress, remoteConnID: ConnectionID] = BEGIN UNTIL InsertConnection[remote, remoteConnID] DO SIGNAL ConnectionFailed[tooManyConnections]; ENDLOOP; END; --InsertIntoConnectionTable Make: PUBLIC PROC[ local, remote: System.NetworkAddress, localConnID, remoteConnID: ConnectionID, establishConnection: BOOLEAN, timeout: NSTypes.WaitTime, classOfService: PacketStream.ClassOfService] RETURNS [psH: PacketStream.Handle] = BEGIN GetInstance: ENTRY PROC = INLINE {IF instance0 # NIL THEN instanceN ← NEW pktStrmInst ELSE instance0 ← instanceN ← pktStrmInst}; instanceN: Instance; estdRemoteConnID: ConnectionID; estdRemoteAddr: System.NetworkAddress; GetInstance[]; --get instance's global frame BEGIN ENABLE UNWIND => BEGIN instanceN.stopPacketStream[]; --stop the protocol UnnewInstance[instanceN]; --unload the frame END; --If we do not have a local address we pick one with a network number that --is a good way to get to the destination and therefore a good way to get --back to us! IF local = System.nullNetworkAddress THEN local ← Router.AssignDestinationRelativeAddress[remote.net]; IF localConnID = PacketStream.unknownConnID THEN localConnID ← GetUniqueConnectionID[]; IF instanceN # instance0 THEN START instanceN; --only copied frames [psH, estdRemoteAddr, estdRemoteConnID] ← instanceN.startPacketStream[ local, remote, localConnID, remoteConnID, timeout, classOfService, establishConnection]; psH.destroy ← Destroy; --this is not instance oriented UNTIL InsertConnection[estdRemoteAddr, estdRemoteConnID] DO SIGNAL ConnectionFailed[tooManyConnections]; ENDLOOP; IF sppSpy # NIL THEN sppSpy[LOOPHOLE[instanceN], create]; END; END; --Make NewMake: PUBLIC PROC[ local, remote: NewNetworkStream.TSap, negotiationParameters: NewNetworkStream.NegotiationParameters, hints: SppNegotiation.NegotiationHints, timeout: NSTypes.WaitTime] RETURNS [psH: PacketStream.Handle] = BEGIN GetInstance: ENTRY PROC = INLINE {IF instance0 # NIL THEN instanceN ← NEW pktStrmInst ELSE instance0 ← instanceN ← pktStrmInst}; instanceN: Instance; GetInstance[]; --get instance's global frame BEGIN ENABLE UNWIND => BEGIN instanceN.stopPacketStream[]; --stop the protocol UnnewInstance[instanceN]; --unload the frame END; --If we do not have a local address we pick one with a network number that --is a good way to get to the destination and therefore a good way to get --back to us! IF local.address = System.nullNetworkAddress THEN local.address ← Router.AssignDestinationRelativeAddress[remote.address.net]; IF local.connectionID = LOOPHOLE[PacketStream.unknownConnID] THEN local.connectionID ← GetUniqueConnectionID[]; IF instanceN # instance0 THEN START instanceN; --only copied frames [psH] ← instanceN.newStartPacketStream[ local, remote, negotiationParameters, hints, timeout]; psH.destroy ← Destroy; --this is not instance oriented UNTIL InsertConnection[remote.address, remote.connectionID] DO SIGNAL ConnectionFailed[tooManyConnections]; ENDLOOP; IF sppSpy # NIL THEN sppSpy[LOOPHOLE[instanceN], create]; END; END; --NewMake PacketStreamsGo: PUBLIC ENTRY PROC= BEGIN UNTIL connection.spareID # PacketStream.unknownConnID DO connection.spareID ← Inline.LowHalf[System.GetClockPulses[]]; ENDLOOP; END; --PacketStreamsGo RemoveConnection: ENTRY PROC[ remote: System.NetworkAddress, remoteConnID: ConnectionID] = BEGIN e, prev: ConnectionTableEntry; e ← connection.head; UNTIL e = NIL DO IF (e.rAddr.host = remote.host) AND (e.rAddr.socket = remote.socket) AND (e.rConnID = remoteConnID) 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 CommFlags.doDebug THEN Driver.Glitch[NotInConnectionTable]; END; --RemoveConnection RemoveFromConnectionTable: PUBLIC PROC[ remote: System.NetworkAddress, remoteConnID: ConnectionID] = {[] ← RemoveConnection[remote, remoteConnID]}; SetSppSpy: PUBLIC <<SppOps>> ENTRY PROC[spy: SppOps.SppSpyProc] RETURNS [oldSpy: SppOps.SppSpyProc] = {oldSpy ← sppSpy; sppSpy ← spy}; SetWindow: PUBLIC <<SppOps>> PROC[window: CARDINAL[0..12]] = {sppWindowSize ← window}; --affects all new streams UnnewInstance: ENTRY PROC[nth: Instance] = INLINE {IF nth = instance0 THEN instance0 ← NIL ELSE Runtime.UnNew[LOOPHOLE[nth]]}; --initialization START pktStrmInst; --always start the first copy END. --of PacketStreamMgr module LOG 17-May-84 11:07:07 AOF Post Klamath 4-Dec-85 17:35:24 AOF Adding some hacks for probing & buffering 11-Apr-86 9:21:46 AOF Procs to enable/disable checksums for local net 22-May-86 11:49:40 SMA No exports to SpecialCommunication. 9-Nov-86 11:39:30 AOF enable/disable checksums in socket too. 9-Nov-86 12:05:18 AOF Getting psH and sH from the other. 9-Sep-87 8:27:05 AOF User proc variables to start spp instance 3-Nov-87 9:56:51 MXI Added NewMake for SPP negotiation