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