<> <> <> <> DIRECTORY Basics USING [LongNumber], BufferDefs USING [BufferAccessHandle, FreeBufferPool, MakeBufferPool, OisBuffer, QueueInitialize, QueueCleanup, QueueObject], CommunicationInternal USING [], CommUtilDefs USING [MaybeShorten, EnableAborts], DriverDefs USING [PutOnGlobalDoneQueue], OISCP USING [DequeueOis, uniqueAddress, unknownHostID, unknownNetID, unknownSocketID], Process USING [InitializeCondition, MsecToTicks, SecondsToTicks, SetTimeout, Ticks], ProcessorFace USING [GetClockPulses, microsecondsPerHundredPulses], Router USING [AddSocket, AssignOisAddress, BroadcastThisPacket, FindDestinationRelativeNetID, FindMyHostID, RemoveSocket, socketRouterLock, SendPacket, XmitStatus], Socket USING [defaultWaitTime, SocketStatus, WaitTime], SocketInternal USING [SocketHandle, SocketObject], NSAddress USING [HostNumber, NetworkAddress, NetworkNumber, nullNetworkAddress]; SocketImpl: MONITOR LOCKS Router.socketRouterLock IMPORTS BufferDefs, DriverDefs, CommUtilDefs, OISCP, Process, Router, ProcessorFace EXPORTS CommunicationInternal, Socket, SocketInternal SHARES BufferDefs = BEGIN OPEN OISCP, Socket, SocketInternal; <> ChannelHandle: TYPE = REF ChannelObject; ChannelObject: PUBLIC TYPE = SocketInternal.SocketObject; NetworkAddress: PUBLIC TYPE = NSAddress.NetworkAddress; -- others uniqueNetworkAddr: PUBLIC NSAddress.NetworkAddress _ NSAddress.nullNetworkAddress; <> <> <> <> myHostID: NSAddress.HostNumber; <> TimeOut: PUBLIC ERROR = CODE; ChannelAborted: PUBLIC ERROR = CODE; ChannelError: PUBLIC ERROR = CODE; <> GetPulsesIntervalTime: PROCEDURE [startTime: LONG CARDINAL] RETURNS [LONG CARDINAL] = INLINE BEGIN RETURN[ProcessorFace.GetClockPulses[] - startTime]; END; -- GetPulsesIntervalTime <> <> <> PutPacket: PUBLIC PROCEDURE [cH: ChannelHandle, b: BufferDefs.OisBuffer] = BEGIN PutLocked: ENTRY PROCEDURE = INLINE BEGIN IF cH.channelState # active THEN RETURN WITH ERROR ChannelAborted; b.status _ LOOPHOLE[Router.XmitStatus[goodCompletion]]; <> END; -- PutLocked <> PutLocked[]; b.ois.source _ cH.localAddr; IF b.ois.source.net = unknownNetID THEN b.ois.source.net _ Router.FindDestinationRelativeNetID[b.ois.destination.net]; IF b.ois.destination.host = unknownHostID OR b.ois.destination.socket = unknownSocketID THEN BEGIN b.status _ LOOPHOLE[Router.XmitStatus[invalidDestAddr]]; -- this is safe! DriverDefs.PutOnGlobalDoneQueue[b]; RETURN; END; Router.SendPacket[b]; END; -- PutPacket <> <> <> <> PutPacketToAllConnectedNets: PUBLIC PROCEDURE [cH: ChannelHandle, b: BufferDefs.OisBuffer] = BEGIN PutLocked: ENTRY PROCEDURE = INLINE BEGIN IF cH.channelState # active THEN RETURN WITH ERROR ChannelAborted; b.status _ LOOPHOLE[Router.XmitStatus[goodCompletion]]; <> END; -- PutLocked <> PutLocked[]; b.ois.source _ cH.localAddr; IF b.ois.destination.socket = unknownSocketID THEN BEGIN b.status _ LOOPHOLE[Router.XmitStatus[invalidDestAddr]]; -- this is safe! DriverDefs.PutOnGlobalDoneQueue[b]; RETURN; END; Router.BroadcastThisPacket[b]; END; -- PutPacketToAllConnectedNets <> GetPacket: PUBLIC ENTRY PROCEDURE [sH: ChannelHandle] RETURNS [b: BufferDefs.OisBuffer] = BEGIN ENABLE UNWIND => NULL; startTime: LONG CARDINAL _ ProcessorFace.GetClockPulses[]; IF (sH.channelState = aborted) THEN RETURN WITH ERROR ChannelAborted; WHILE (b _ DequeueOis[sH.completedUserGetQueue]) = NIL DO IF GetPulsesIntervalTime[startTime] > sH.waitTime THEN RETURN WITH ERROR TimeOut; WAIT sH.newUserInput; -- propogate ERROR ABORTED IF (sH.channelState = aborted) THEN RETURN WITH ERROR ChannelAborted; ENDLOOP; END; <> <> AssignNetworkAddress: PUBLIC PROCEDURE RETURNS [NSAddress.NetworkAddress] = BEGIN RETURN[Router.AssignOisAddress[]]; END; -- AssignNetworkAddress <> <> <> <> Create: PUBLIC PROCEDURE [ local: NetworkAddress, send, receive, reserve: CARDINAL, privateBuffers: BOOLEAN _ TRUE] RETURNS [sH: SocketHandle] = BEGIN totalBuffers: CARDINAL _ IF privateBuffers THEN send + receive + reserve ELSE 0; sH _ NEW[SocketObject]; <> <> <> sH.pool _ BufferDefs.MakeBufferPool[ totalBuffers, send, receive, reserve, ~privateBuffers]; sH.localAddr _ IF local = OISCP.uniqueAddress THEN Router.AssignOisAddress[] ELSE local; sH.channelState _ active; sH.waitTime _ MilliSecondsToPulses[Socket.defaultWaitTime]; <> sH.completedUserGetQueue _ NEW[BufferDefs.QueueObject]; BufferDefs.QueueInitialize[sH.completedUserGetQueue]; Process.InitializeCondition[ CommUtilDefs.MaybeShorten[@sH.newUserInput], Process.MsecToTicks[LOOPHOLE[Socket.defaultWaitTime, Basics.LongNumber].lowbits] + 1]; CommUtilDefs.EnableAborts[CommUtilDefs.MaybeShorten[@sH.newUserInput]]; <> Router.AddSocket[sH]; END; -- Create <> <> Delete: PUBLIC PROCEDURE [sH: ChannelHandle] = BEGIN DeleteLocked: ENTRY PROCEDURE = INLINE BEGIN ENABLE UNWIND => NULL; BufferDefs.QueueCleanup[sH.completedUserGetQueue]; BufferDefs.FreeBufferPool[sH.pool]; END; -- DeleteLocked <> <> <> Router.RemoveSocket[sH]; DeleteLocked[]; <> END; -- <> Abort: PUBLIC ENTRY PROCEDURE [sH: ChannelHandle] = BEGIN temp: CONDITION; sH.channelState _ aborted; BROADCAST sH.newUserInput; -- tell all potential waiters Process.InitializeCondition[@temp, Process.MsecToTicks[10]]; WAIT temp; -- Yield to let waiter leave the MONITOR END; -- Abort Reset: PUBLIC ENTRY PROCEDURE [sH: ChannelHandle] = BEGIN sH.channelState _ active; END; <> GetStatus: PUBLIC ENTRY PROCEDURE [sH: ChannelHandle] RETURNS [status: SocketStatus] = BEGIN status _ [localAddr: sH.localAddr, state: sH.channelState, incompleteGets: sH.completedUserGetQueue.length]; END; -- GetStatus <> SetWaitTime: PUBLIC ENTRY PROCEDURE [cH: ChannelHandle, time: WaitTime] = BEGIN ticks: Process.Ticks; condTime: CARDINAL _ LOOPHOLE[time, Basics.LongNumber].lowbits; lastCard: LONG CARDINAL = LAST[CARDINAL]; -- no, not last LONG CARDINAL !! cH.waitTime _ MilliSecondsToPulses[time]; <> <> IF time > lastCard THEN BEGIN timeInSeconds: LONG CARDINAL _ time/1000; IF timeInSeconds > lastCard THEN condTime _ LAST[CARDINAL] - 1 <> ELSE condTime _ LOOPHOLE[timeInSeconds, Basics.LongNumber].lowbits; ticks _ Process.SecondsToTicks[condTime]; END ELSE ticks _ Process.MsecToTicks[condTime] + 1; Process.SetTimeout[CommUtilDefs.MaybeShorten[@cH.newUserInput], ticks]; Process.SetTimeout[CommUtilDefs.MaybeShorten[@cH.newUserInput], ticks]; END; -- SetWaitTime MilliSecondsToPulses: PROCEDURE [ms: LONG CARDINAL] RETURNS [pulses: LONG CARDINAL] = BEGIN <> <> micro: LONG CARDINAL = MIN[LAST[LONG CARDINAL]/1000,ms] * 1000; hundreds: LONG CARDINAL = micro / ProcessorFace.microsecondsPerHundredPulses; pulses _ MIN[LAST[LONG CARDINAL]/100,hundreds]*100; END; -- end MilliSecondsToPulses <> GetBufferPool: PUBLIC PROCEDURE [sH: SocketHandle] RETURNS [BufferDefs.BufferAccessHandle] = BEGIN RETURN[sH.pool]; END; <> <> <> <> <> SocketOn: PUBLIC PROCEDURE = BEGIN <> myHostID _ Router.FindMyHostID[]; END; -- SocketOn <> END. -- SocketImpl module LOG Time: January 7, 1980 3:11 PM By: Dalal Action: converted to new SocketInternal. Time: January 21, 1980 5:47 PM By: Dalal Action: all sockets under one lock. Time: March 12, 1980 5:32 PM By: BLyon Action: added send, receive to CreateInternal. Time: March 18, 1980 12:07 PM By: BLyon Action: Added Reset, Getpacket, PutPacket (body identicle to old Put), modified Put. Modified TransferWait & TransferWaitAny to abort like PutPacket. Modified Abort. Time: June 3, 1980 3:43 PM By: BLyon Action: Replace SimpleHeap references with Heap. Time: June 3, 1980 3:43 PM By: HGM Action: Add MaybeShortens. Time: June 18, 1980 2:44 PM By: BLyon Action: Added EXPORTED TYPES. Time: September 18, 1980 3:45 PM By: BLyon Action: flushed primaryNetID concept. Time: October 8, 1980 9:10 AM By: BLyon Action: Time units are now pulses and not milliseconds. Time: November 19, 1980 5:12 PM By: BLyon Action: Post Mokelumne rework. Time: January 23, 1981 4:27 PM By: BLyon Action: Added ability to abort GetPacket.