DIRECTORY Allocator USING [NHeaderP, NormalHeader], Basics USING [BITAND, bytesPerWord], Checksum USING [ComputeChecksum], CommBuffer USING [Direction, Encapsulation], CommDriver USING [AllocBuffer, Buffer, BufferObject, FreeBuffer, GetNetworkChain, Network], Endian USING [bytesPerFWord, bytesPerHWord, CardFromH, HFromCard, HWORD], PrincOpsUtils USING [LongMove], Process USING [Detach, DisableTimeout, EnableAborts, MsecToTicks, Pause, priorityBackground, SecondsToTicks, SetPriority, SetTimeout, Ticks], SafeStorage USING [EnableFinalization, EstablishFinalization, FinalizationQueue, FQNext, NewFQ], XNS USING [Address, broadcastHost, broadcastNet, GetThisHost, Host, Net, Socket, unknownAddress, unknownNet, unknownSocket], XNSBuf USING [Buffer, BufferObject, hdrBytes, maxBodyBytes, maxBodyFWords, maxBodyHWords], XNSErrorBuf USING [Buffer, hdrBytes], XNSErrorTypes USING [badChecksumErr, ErrorType, noSocketErr, nullParam, resourceLimitsErr, unspecifiedInRouteErr], XNSRouterPrivate USING [Route], XNSSocket USING [dontWait, Milliseconds, waitForever], XNSSocketBackdoor USING [ReceiveProc], XNSWKS USING [last]; XNSSocketImpl: CEDAR MONITOR LOCKS handle USING handle: Handle IMPORTS Basics, Checksum, CommDriver, Endian, XNS, XNSRouterPrivate, PrincOpsUtils, Process, SafeStorage EXPORTS XNSRouterPrivate, XNSSocket, XNSSocketBackdoor ~ { Address: TYPE ~ XNS.Address; Net: TYPE ~ XNS.Net; Host: TYPE ~ XNS.Host; Socket: TYPE ~ XNS.Socket; Buffer: TYPE ~ XNSBuf.Buffer; Network: TYPE ~ CommDriver.Network; Milliseconds: TYPE ~ XNSSocket.Milliseconds; ReceiveProc: TYPE ~ XNSSocketBackdoor.ReceiveProc; Direction: TYPE ~ CommBuffer.Direction; HWORD: TYPE ~ Endian.HWORD; bytesPerHWord: NAT ~ Endian.bytesPerHWord; bytesPerFWord: NAT ~ Endian.bytesPerFWord; bytesPerWord: NAT ~ Basics.bytesPerWord; thisHost: Host ~ XNS.GetThisHost[]; RealDriverBuffer: PROC [b: Buffer] RETURNS [CommDriver.Buffer] = TRUSTED INLINE { nhp: Allocator.NHeaderP _ LOOPHOLE[b, Allocator.NHeaderP]-SIZE[Allocator.NormalHeader]; nhp.type _ CODE[CommDriver.BufferObject]; b.ovh.direction _ none; b.ovh.socket _ NIL; RETURN[LOOPHOLE[b]]; }; TempDriverBuffer: PROC [b: Buffer] RETURNS [CommDriver.Buffer] = TRUSTED INLINE { RETURN[LOOPHOLE[b]]; }; RealXNSBuffer: PROC [b: CommDriver.Buffer, d: Direction] RETURNS [Buffer] = TRUSTED INLINE { nhp: Allocator.NHeaderP _ LOOPHOLE[b, Allocator.NHeaderP]-SIZE[Allocator.NormalHeader]; nhp.type _ CODE[XNSBuf.BufferObject]; b.ovh.next _ NIL; b.ovh.direction _ d; RETURN[LOOPHOLE[b]]; }; Next: PROC [b: Buffer] RETURNS [Buffer] = TRUSTED INLINE { RETURN[LOOPHOLE[b.ovh.next]]; }; Handle: TYPE ~ REF Object; Object: PUBLIC TYPE ~ MONITORED RECORD [ local, remote: Address, sendBuffersInUse: CARDINAL _ 0, sendBuffersAllocated: CARDINAL, recvBuffersInUse: CARDINAL _ 0, recvBuffersAllocated: CARDINAL, routingCache: Routing _ NIL, receiveProc: ReceiveProc _, receiveClientData: REF ANY _ NIL, sendChecksum, recvChecksum: BOOL _ TRUE, dead, noErrors: BOOL _ FALSE, dontWait: BOOL _ FALSE, waitForInput, waitForSendBuffer: CONDITION, firstInput, lastInput: Buffer _ NIL, next: Handle _ NIL ]; Routing: TYPE ~ REF RoutingInfo; RoutingInfo: TYPE ~ RECORD [ network: Network, immediate: Host, -- Not Necessary ???? encap: CommBuffer.Encapsulation ]; numHashHeaders: CARDINAL ~ 64; HashIndex: TYPE ~ [0 .. numHashHeaders); ObjectTable: TYPE ~ REF ObjectTableRep; ObjectTableRep: TYPE ~ ARRAY HashIndex OF Handle; objectTable: ObjectTable ~ NEW[ObjectTableRep]; objectTableLock: Handle ~ NEW[Object _ [local~, remote~, sendBuffersAllocated~, recvBuffersAllocated~, receiveProc~NIL]]; Hash: PROC [socket: Socket] RETURNS [HashIndex] ~ INLINE { RETURN [socket.b MOD numHashHeaders] }; AddNewHandle: ENTRY PROC [handle: Handle _ objectTableLock, newHandle: Handle] ~ { i: HashIndex ~ Hash[newHandle.local.socket]; newHandle.next _ objectTable^[i]; objectTable^[i] _ newHandle; }; RemoveOldHandle: ENTRY PROC [handle: Handle _ objectTableLock, oldHandle: Handle] ~ { i: HashIndex ~ Hash[oldHandle.local.socket]; IF oldHandle = objectTable^[i] THEN { objectTable^[i] _ oldHandle.next } ELSE { prev: Handle; FOR prev _ objectTable^[i], prev.next WHILE prev.next # oldHandle DO NULL ENDLOOP; prev.next _ oldHandle.next }; oldHandle.next _ NIL; -- Help finalization of oldHandle.next^ }; FindHandle: PROC [localSocket: Socket] RETURNS [Handle] ~ { i: HashIndex ~ Hash[localSocket]; FOR handle: Handle _ objectTable^[i], handle.next UNTIL handle = NIL DO -- ATOMIC IF handle.local.socket = localSocket THEN RETURN[handle]; ENDLOOP; RETURN[NIL] }; uniqueSocketLock: Handle ~ NEW[Object _ [local~[net~, host~, socket~XNSWKS.last], remote~, sendBuffersAllocated~, recvBuffersAllocated~, receiveProc~NIL]]; NextLocalSocket: ENTRY PROC [handle: Handle _ uniqueSocketLock] RETURNS [Socket] ~ TRUSTED { temp: HWORD _ LOOPHOLE[uniqueSocketLock.local.socket]; temp _ Endian.HFromCard[Endian.CardFromH[temp] + 1]; RETURN [uniqueSocketLock.local.socket _ LOOPHOLE[temp]] }; noChecksum: Endian.HWORD ~ 0FFFFH; -- Should move to XNSBuf ???? GetBytesRounded: PROC [b: Buffer] RETURNS [CARDINAL] ~ INLINE { RETURN[Basics.BITAND[(1+Endian.CardFromH[b.hdr1.length]),0FFFEH]]; }; InlineSetChecksum: PROC [b: Buffer, bytes: CARDINAL, computed: BOOL _ TRUE] ~ TRUSTED INLINE { IF computed THEN { words: CARDINAL _ (bytes - bytesPerHWord) / bytesPerWord; checksumLoc: LONG POINTER _ @b.hdr1.checksum; checksumLoc^ _ Checksum.ComputeChecksum[0, words, @b.hdr1.length] } ELSE { b.hdr1.checksum _ noChecksum }; }; InlineTestChecksum: PROC [b: Buffer, bytes: CARDINAL] RETURNS [BOOL] ~ TRUSTED INLINE { IF b.hdr1.checksum # noChecksum THEN { words: CARDINAL ~ (bytes - bytesPerHWord) / bytesPerWord; myChecksum: HWORD ~ Checksum.ComputeChecksum[0, words, @b.hdr1.length]; RETURN [ b.hdr1.checksum = myChecksum ] } ELSE RETURN[TRUE]; }; SetChecksum: PUBLIC PROC [b: Buffer] ~ { InlineSetChecksum[b, GetBytesRounded[b]] }; Create: PUBLIC PROC [ remote: Address _ XNS.unknownAddress, sendBuffers: NAT _ 1, recvBuffers: NAT _ 5, getTimeout: Milliseconds _ 10000, local: Socket _ XNS.unknownSocket ] RETURNS [handle: Handle] ~ { network: Network; network _ XNSRouterPrivate.Route[remote].network; IF network = NIL THEN network _ CommDriver.GetNetworkChain[]; IF local = XNS.unknownSocket THEN local _ NextLocalSocket[]; handle _ NEW [Object _ [ local~[net~network.xns.net, host~thisHost, socket~local], remote~remote, sendBuffersAllocated~sendBuffers, recvBuffersAllocated~recvBuffers, receiveProc~NormalReceive ] ]; TRUSTED { Process.EnableAborts[@handle.waitForInput]; Process.EnableAborts[@handle.waitForSendBuffer] }; SetGetTimeout[handle, getTimeout]; AddNewHandle[newHandle~handle]; SafeStorage.EnableFinalization[handle]; }; GetLocalAddress: PUBLIC PROC [handle: Handle] RETURNS [Address] ~ { RETURN[handle.local]; }; GetRemoteAddress: PUBLIC PROC [handle: Handle] RETURNS [Address] ~ { RETURN[handle.remote]; }; SetRemoteAddress: PUBLIC PROC [handle: Handle, address: Address] ~ { handle.remote _ address; }; SetGetTimeout: PUBLIC PROC [handle: Handle, ms: Milliseconds] ~ { handle.dontWait _ FALSE; SELECT ms FROM XNSSocket.dontWait => handle.dontWait _ TRUE; XNSSocket.waitForever => TRUSTED { Process.DisableTimeout[@handle.waitForInput]; }; < CARDINAL.LAST => TRUSTED { Process.SetTimeout[@handle.waitForInput, Process.MsecToTicks[ms] ]; }; ENDCASE => TRUSTED { Process.SetTimeout[@handle.waitForInput, Process.SecondsToTicks[ms/1000] ]; }; }; SetSoftwareChecksumming: PUBLIC PROC [handle: Handle, send, recv: BOOL] ~ { handle.sendChecksum _ send; handle.recvChecksum _ recv; }; SetNoErrors: PUBLIC PROC [handle: Handle, noErrors: BOOL _ TRUE] ~ { handle.noErrors _ noErrors; }; Kick: PUBLIC ENTRY PROC [handle: Handle] ~ { NOTIFY handle.waitForInput; }; Destroy: PUBLIC ENTRY PROC [handle: Handle] ~ { handle.dead _ TRUE; UNTIL handle.firstInput = NIL DO b: Buffer _ handle.firstInput; handle.firstInput _ Next[b]; handle.recvBuffersInUse _ handle.recvBuffersInUse - 1; CommDriver.FreeBuffer[RealDriverBuffer[b]]; ENDLOOP; handle.lastInput _ NIL; -- Help Buffer finalization. IF handle.noErrors OR (handle.recvBuffersInUse # 0) OR (handle.sendBuffersInUse # 0) THEN TRUSTED { Process.Detach[FORK DestroyDally[handle]]; RETURN }; }; DestroyDally: PROC [handle: Handle] ~ { oneSecond: Process.Ticks = Process.SecondsToTicks[10]; Process.SetPriority[Process.priorityBackground]; IF handle.noErrors THEN Process.Pause[10*oneSecond]; WHILE (handle.recvBuffersInUse # 0) OR (handle.sendBuffersInUse # 0) DO Process.Pause[oneSecond]; ENDLOOP; }; AllocBuffer: PUBLIC PROC [handle: Handle] RETURNS [b: Buffer] ~ { InnerAllocBuffer[handle]; b _ RealXNSBuffer[CommDriver.AllocBuffer[], send]; b.ovh.next _ NIL; b.ovh.socket _ handle; -- needed for finalization }; InnerAllocBuffer: ENTRY PROC [handle: Handle] ~ { ENABLE UNWIND => NULL; UNTIL handle.sendBuffersInUse < handle.sendBuffersAllocated DO WAIT handle.waitForSendBuffer; ENDLOOP; handle.sendBuffersInUse _ handle.sendBuffersInUse + 1; }; SetUserBytes: PUBLIC PROC [b: Buffer, bytes: [0 .. XNSBuf.maxBodyBytes]] ~ { b.hdr1.length _ Endian.HFromCard[bytes + XNSBuf.hdrBytes]; }; SetUserHWords: PUBLIC PROC [b: Buffer, hWords: [0 .. XNSBuf.maxBodyHWords]] ~ { b.hdr1.length _ Endian.HFromCard[hWords*bytesPerHWord + XNSBuf.hdrBytes]; }; SetUserFWords: PUBLIC PROC [b: Buffer, fWords: [0 .. XNSBuf.maxBodyFWords]] ~ { b.hdr1.length _ Endian.HFromCard[fWords*bytesPerFWord + XNSBuf.hdrBytes]; }; SetUserSize: PUBLIC PROC [b: Buffer, sizeUnits: NAT] ~ { b.hdr1.length _ Endian.HFromCard[sizeUnits*bytesPerWord + XNSBuf.hdrBytes]; -- Fix when BYTES[...] is implemented }; Broadcast: PUBLIC PROC [handle: Handle, b: Buffer, socket: Socket] ~ { bytes: CARDINAL ~ GetBytesRounded[b]; b.hdr1.transportCtl _ [trace~FALSE, filler~0, hopCount~0]; b.hdr1.dest.socket _ socket; b.hdr1.dest.host _ XNS.broadcastHost; b.hdr1.source _ handle.local; FOR network: Network _ CommDriver.GetNetworkChain[], network.next UNTIL network = NIL DO b.ovh.encap _ network.xns.getEncapsulation[network, XNS.broadcastHost]; b.hdr1.dest.net _ network.xns.net; b.hdr1.source.net _ network.xns.net; InlineSetChecksum[b, bytes, handle.sendChecksum]; network.xns.send[network, TempDriverBuffer[b], bytes]; ENDLOOP; FreeBuffer[handle, b]; }; Put: PUBLIC PROC [handle: Handle, b: Buffer] ~ { Send[handle, b, handle.remote]; -- What if it's UNKNOWN??? }; Send: PUBLIC PROC [handle: Handle, b: Buffer, dest: Address] ~ { bytes: CARDINAL = GetBytesRounded[b]; network: Network; immediate: Host; IF (dest.net = XNS.broadcastNet) AND (dest.host = XNS.broadcastHost) THEN { Broadcast[handle, b, dest.socket]; RETURN; }; b.hdr1.transportCtl _ [trace~FALSE, filler~0, hopCount~0]; b.hdr1.dest _ dest; b.hdr1.source _ handle.local; [network, immediate] _ XNSRouterPrivate.Route[dest]; IF network # NIL THEN { b.ovh.encap _ network.xns.getEncapsulation[network, immediate]; InlineSetChecksum[b, bytes, handle.sendChecksum]; network.xns.send[network, TempDriverBuffer[b], bytes]; }; FreeBuffer[handle, b]; }; PutCached: PUBLIC PROC [handle: Handle, b: Buffer] ~ { bytes: CARDINAL = GetBytesRounded[b]; network: Network; immediate: Host; routingCache: Routing _ handle.routingCache; IF routingCache = NIL THEN { [network, immediate] _ XNSRouterPrivate.Route[handle.remote]; IF network = NIL THEN RETURN; handle.routingCache _ routingCache _ NEW [RoutingInfo _ [network~network, immediate~immediate, encap~network.xns.getEncapsulation[network, immediate]]]; }; b.hdr1.transportCtl _ [trace~FALSE, filler~0, hopCount~0]; b.hdr1.dest _ handle.remote; b.hdr1.source _ handle.local; b.ovh.encap _ routingCache.encap; InlineSetChecksum[b, bytes, handle.sendChecksum]; routingCache.network.xns.send[routingCache.network, TempDriverBuffer[b], bytes]; }; FlushCache: PUBLIC PROC [handle: Handle] ~ { handle.routingCache _ NIL; }; Get: PUBLIC ENTRY PROC [handle: Handle] RETURNS [b: Buffer] ~ { ENABLE UNWIND => NULL; IF (handle.firstInput = NIL) AND NOT handle.dontWait THEN WAIT handle.waitForInput; IF (b _ handle.firstInput) # NIL THEN { handle.firstInput _ Next[b]; b.ovh.socket _ handle; -- needed for finalization }; }; GetUserBytes: PUBLIC PROC [b: Buffer] RETURNS [bytes: [0 .. XNSBuf.maxBodyBytes]] ~ { bytes _ Endian.CardFromH[b.hdr1.length] - XNSBuf.hdrBytes; }; GetUserHWords: PUBLIC PROC [b: Buffer] RETURNS [hWords: [0 .. XNSBuf.maxBodyHWords]] ~ { bytes: [0 .. XNSBuf.maxBodyBytes] _ Endian.CardFromH[b.hdr1.length] - XNSBuf.hdrBytes; hWords _ bytes/bytesPerHWord; }; GetUserFWords: PUBLIC PROC [b: Buffer] RETURNS [fWords: [0 .. XNSBuf.maxBodyFWords]] ~ { bytes: [0 .. XNSBuf.maxBodyBytes] _ Endian.CardFromH[b.hdr1.length] - XNSBuf.hdrBytes; fWords _bytes/bytesPerFWord; }; GetUserSize: PUBLIC PROC [b: Buffer] RETURNS [sizeUnits: NAT] ~ { bytes: [0 .. XNSBuf.maxBodyBytes] _ Endian.CardFromH[b.hdr1.length] - XNSBuf.hdrBytes; sizeUnits _ bytes/bytesPerWord; -- Fix when BYTES[...] is implemented. }; FreeBuffer: PUBLIC ENTRY PROC [handle: Handle, b: Buffer] ~ { SELECT b.ovh.direction FROM send => { handle.sendBuffersInUse _ handle.sendBuffersInUse - 1; NOTIFY handle.waitForSendBuffer }; recv => handle.recvBuffersInUse _ handle.recvBuffersInUse - 1; ENDCASE => ERROR; CommDriver.FreeBuffer[RealDriverBuffer[b]]; }; FixupSourceAndDest: PUBLIC PROC [b: Buffer] ~ { network: Network _ NARROW[b.ovh.network]; IF b.hdr1.source.net = XNS.unknownNet THEN b.hdr1.source.net _ network.xns.net; IF b.hdr1.dest.net = XNS.unknownNet THEN b.hdr1.dest.net _ network.xns.net; IF b.hdr1.dest.host = XNS.broadcastHost THEN b.hdr1.dest.host _ thisHost; }; useOldReturn: BOOL _ TRUE; -- DEBUG ReturnToSender: PUBLIC PROC [handle: Handle, b: Buffer] ~ { bytes: CARDINAL ~ GetBytesRounded[b]; sendChecksum: BOOL ~ IF handle = NIL THEN TRUE ELSE handle.sendChecksum; network: Network ~ NARROW[b.ovh.network]; FixupSourceAndDest[b]; b.hdr1.transportCtl _ [trace~FALSE, filler~0, hopCount~0]; { temp: Address ~ b.hdr1.source; b.hdr1.source _ b.hdr1.dest; b.hdr1.dest _ temp }; InlineSetChecksum[b, bytes, sendChecksum]; IF useOldReturn THEN { network: Network; immediate: Host; [network, immediate] _ XNSRouterPrivate.Route[b.hdr1.dest]; IF network # NIL THEN { b.ovh.encap _ network.xns.getEncapsulation[network, immediate]; network.xns.send[network, TempDriverBuffer[b], bytes] }; IF handle # NIL THEN FreeBuffer[handle, b]; RETURN }; network.xns.return[network, TempDriverBuffer[b], bytes]; IF handle # NIL THEN FreeBuffer[handle, b]; }; ReturnError: PUBLIC PROC [handle: Handle, b: Buffer, type: XNSErrorTypes.ErrorType] ~ { bodyBytes: CARDINAL ~ 42; -- Should be XNSErrorBuf.minBytesToCopy ???? eb: XNSErrorBuf.Buffer; IF (b.hdr1.type = error) OR (b.hdr1.dest.host = XNS.broadcastHost) THEN { IF handle # NIL THEN FreeBuffer[handle, b]; -- Hack for internal use RETURN; }; b.hdr1.type _ error; TRUSTED { -- ???? WORD-SIZE DEPENDENT ???? eb _ LOOPHOLE[b]; PrincOpsUtils.LongMove[ from: @b.hdr1, nwords: bodyBytes*2, to: @eb.body]; }; eb.hdr2.type _ type; eb.hdr2.param _ XNSErrorTypes.nullParam; SetUserBytes[b, XNSErrorBuf.hdrBytes + bodyBytes]; ReturnToSender[handle, b]; }; SetDirectReceive: PUBLIC ENTRY PROC [handle: Handle, receiveProc: ReceiveProc, clientData: REF ANY] ~ { handle.receiveProc _ (IF receiveProc # NIL THEN receiveProc ELSE NormalReceive); handle.receiveClientData _ clientData; }; errorTooShort: INT _ 0; errorNoGateway: INT _ 0; errorNoSocket: INT _ 0; errorDeadSocket: INT _ 0; errorBadChecksum: INT _ 0; errorBuffersFull: INT _ 0; TakeThis: PUBLIC PROC [network: Network, buffer: CommDriver.Buffer, bytes: NAT] RETURNS [CommDriver.Buffer] ~ { b: Buffer _ RealXNSBuffer[buffer, recv]; bytesNeeded: CARDINAL ~ GetBytesRounded[b]; dest: Address _ b.hdr1.dest; localSocket: Socket ~ dest.socket; handle: Handle; receiveProc: ReceiveProc; receiveClientData: REF ANY; BEGIN IF (bytes < bytesNeeded) OR (Endian.CardFromH[b.hdr1.length] < XNSBuf.hdrBytes) THEN { errorTooShort _ errorTooShort.SUCC; GOTO Out; }; IF b.hdr1.dest.host # thisHost AND b.hdr1.dest.host # XNS.broadcastHost THEN { errorNoGateway _ errorNoGateway.SUCC; ReturnError[NIL, b, XNSErrorTypes.unspecifiedInRouteErr]; -- What's the RIGHT error to use here? GOTO Out; }; handle _ FindHandle[localSocket]; IF handle = NIL THEN { errorNoSocket _ errorNoSocket.SUCC; ReturnError[NIL, b, XNSErrorTypes.noSocketErr]; GOTO Out; }; IF handle.dead THEN { errorDeadSocket _ errorDeadSocket.SUCC; IF NOT handle.noErrors THEN ReturnError[NIL, b, XNSErrorTypes.noSocketErr]; GOTO Out; }; IF handle.recvChecksum AND NOT InlineTestChecksum[b, bytesNeeded] THEN { errorBadChecksum _ errorBadChecksum.SUCC; ReturnError[NIL, b, XNSErrorTypes.badChecksumErr]; GOTO Out; }; b.ovh.next _ NIL; [receiveProc, receiveClientData] _ GetReceiveProc[handle]; IF receiveProc # NIL THEN { b _ receiveProc[handle, b, receiveClientData]; IF b = NIL THEN GOTO OutNIL; DecrementRecvBuffersInUse[handle]; GOTO Out; }; errorBuffersFull _ errorBuffersFull.SUCC; IF NOT handle.noErrors THEN ReturnError[NIL, b, XNSErrorTypes.resourceLimitsErr]; GOTO Out; EXITS Out => RETURN[RealDriverBuffer[b]]; OutNIL => RETURN[NIL]; END; }; GetReceiveProc: ENTRY PROC [handle: Handle] RETURNS [ReceiveProc, REF ANY] ~ { IF handle.recvBuffersInUse >= handle.recvBuffersAllocated THEN RETURN [NIL, NIL]; handle.recvBuffersInUse _ handle.recvBuffersInUse.SUCC; RETURN [handle.receiveProc, handle.receiveClientData]; }; NormalReceive: PUBLIC ENTRY ReceiveProc ~ { IF handle.firstInput = NIL THEN handle.firstInput _ b ELSE handle.lastInput.ovh.next _ b; handle.lastInput _ b; NOTIFY handle.waitForInput; RETURN[NIL]; }; DecrementRecvBuffersInUse: ENTRY PROC [handle: Handle] ~ { handle.recvBuffersInUse _ handle.recvBuffersInUse.PRED; }; droppedSockets: INT _ 0; finishedSockets: INT _ 0; droppedBuffers: INT _ 0; ofq: SafeStorage.FinalizationQueue ~ SafeStorage.NewFQ[]; -- for Objects bfq: SafeStorage.FinalizationQueue ~ SafeStorage.NewFQ[]; -- for Buffers ObjectFinalizer: PROC = { Process.SetPriority[Process.priorityBackground]; DO handle: Handle _ NARROW[SafeStorage.FQNext[ofq]]; IF NOT handle.dead THEN { -- User forgot to call Destroy SafeStorage.EnableFinalization[handle]; Destroy[handle]; droppedSockets _ droppedSockets.SUCC; } ELSE { -- Normal end of life RemoveOldHandle[oldHandle~handle]; finishedSockets _ finishedSockets.SUCC; }; handle _ NIL; ENDLOOP; }; BufferFinalizer: PROC = { Process.SetPriority[Process.priorityBackground]; DO b: Buffer _ NARROW[SafeStorage.FQNext[bfq]]; handle: Handle _ NARROW[b.ovh.socket]; SafeStorage.EnableFinalization[b]; FreeBuffer[handle, b]; b _ NIL; droppedBuffers _ droppedBuffers.SUCC; ENDLOOP; }; SafeStorage.EstablishFinalization[type: CODE[Object], npr: 1, fq: ofq]; SafeStorage.EstablishFinalization[type: CODE[XNSBuf.BufferObject], npr: 1, fq: bfq]; TRUSTED { Process.Detach[FORK ObjectFinalizer[]] }; TRUSTED { Process.Detach[FORK BufferFinalizer[]] }; }. €XNSSocketImpl.mesa Copyright c 1986 by Xerox Corporation. All rights reserved. Hal Murray, January 21, 1986 2:41:44 pm PST Demers, June 5, 1986 11:21:24 pm PDT Stuff for smashing types of buffers between CommDriver.Buffer and XNSBuf.Buffer. See the comments near CommDriver.Buffer. BEWARE: this stuff may be word size dependent. Socket Objects Hash Table for Socket Objects Insert newHandle in hash table. Called before finalization of newHandle is enabled. Delete oldHandle from hash table. Called during finalization of oldHandle. Unique Local Socket Numbers Checksum Utilities Get packet bytes, rounded up to include the garbage byte if this is an odd length packet. Caller must already have rounded bytes up, e.g. by using GetBytesRounded[b] BEWARE: word-size dependent, LONG POINTERs to HWORDs. I believe the checksum calculation is NOT byte-order dependent, though! Caller must already have rounded bytes up, e.g. by using GetBytesRounded[b] Return TRUE if checksum is correct or noChecksum. BEWARE: word-size dependent, LONG POINTERs to HWORDs. I believe the checksum calculation is NOT byte-order dependent, though! Creation and parameter setting Drop handle, let finalization remove it from table. Drop handle, let finalization remove it from table. Sending Backdoor Sending Receiving Return buffer to sender. If handle # NIL (for external use), free the buffer updating handle's quota; if handle = NIL (for internal use) the caller keeps control of the buffer. DEBUG until network.ns.return works Backdoor Receive See also NormalReceive, below. Incoming packets from Drivers Error Statistics. Finalization Statistics Beware: See the comments near CommDriver.Buffer Κ&˜codešœ™Kšœ Οmœ1™Kšžœ˜Kšžœ˜—Kšœ6˜6Kšœ˜K˜—š  œž œ3˜LKšœ:˜:Kšœ˜—š  œž œ5˜OKšœI˜IKšœ˜—š  œž œ5˜OKšœI˜IKšœ˜—š  œž œžœ˜8KšœL‘%˜qKšœ˜K™—š  œž œ0˜FKšœžœ˜%K˜Kšœžœ˜:Kšœ˜Kšœžœ˜%K˜šžœ?žœ žœž˜XKšœ4žœ˜GKšœ"˜"Kšœ$˜$Kšœ1˜1Kšœ6˜6Kšžœ˜—Kšœ˜Kšœ˜K˜—š œžœžœ ˜0Kšœ ‘˜:K˜K™—š œž œ/˜@Kšœžœ˜%Kšœ˜K˜šžœ žœžœžœ˜DKšžœ&žœ˜4—Kšœžœ˜:Kšœ˜K˜Kšœ4˜4šžœ žœžœ˜Kšœ?˜?Kšœ1˜1Kšœ6˜6Kšœ˜—Kšœ˜Kšœ˜—K˜—™š  œž œ ˜6Kšœžœ˜%Kšœ˜K˜Kšœ,˜,šžœžœžœ˜Kšœ=˜=Kšžœ žœžœžœ˜šœ$˜$Kšžœp˜s—K˜—Kšœžœ˜:Kšœ˜K˜Kšœ!˜!Kšœ1˜1KšœP˜PKšœ˜—K˜š  œž œ˜,Kšœžœ˜K˜——š  ™ š  œžœžœžœžœ˜?Kšžœžœžœ˜šžœžœ˜4Kšž œ˜—šžœžœžœ˜'Kšœ˜Kšœ‘˜1K˜—Kšœ˜—K™š  œž œ žœ(˜UKšœ:˜:Kšœ˜—š  œž œ žœ*˜XKšœV˜VKšœ˜Kšœ˜—š  œž œ žœ*˜XKšœV˜VKšœ˜Kšœ˜—š   œžœžœ žœ žœ˜AKšœV˜VKšœ ‘&˜FK˜—K˜š  œžœžœžœ ˜=šžœž˜šœ ˜ Kšœ6˜6Kšžœ˜"—Kšœ>˜>Kšžœžœ˜—Kšœ+˜+Kšœ˜K™—š œžœžœ˜/Kšœžœ˜)Kšžœžœ žœ%˜OKšžœžœ žœ#˜KKšžœžœžœ˜IKšœ˜K™—Kšœžœžœ‘˜#K˜š œžœžœ ˜;K™K™—Kšœžœ˜%Kš œžœžœ žœžœžœžœ˜HKšœžœ˜)K˜Kšœ˜Kšœžœ˜:K˜UKšœ*˜*šœ#™#šžœžœ˜Kšœ˜K˜K˜;šžœ žœžœ˜Kšœ?˜?Kšœ8˜8—Kšžœ žœžœ˜+Kšžœ˜ ——Kšœ8˜8Kšžœ žœžœ˜+K˜K™—š  œž œ?˜WKšœ žœ‘,˜FK˜šžœžœžœžœ˜IKšžœ žœžœ‘˜DKšžœ˜ —K˜šžœ‘ ˜*Kšœžœ˜šœ˜Kšœ˜Kšœ˜Kšœ˜—Kšœ˜—Kšœ˜Kšœ(˜(Kšœ2˜2Kšœ˜K˜—J™—™š  œžœžœžœ8žœžœ˜gKš œžœžœžœ žœ˜PKšœ&˜&K˜—K˜K™—šœ™™Kšœžœ˜Kšœžœ˜Kšœžœ˜Kšœžœ˜Kšœžœ˜Kšœžœ˜—K˜š  œžœžœ6žœžœ˜oKšœ(˜(Kšœ žœ˜+Kšœ˜Kšœ"˜"Kšœ˜K˜Kšœžœžœ˜K˜šž˜šžœžœ4žœ˜VKšœžœ˜#Kšžœ˜ —šžœžœžœžœ˜NKšœ žœ˜%Jšœ žœ+‘&˜`Kšžœ˜ —Kšœ!˜!šžœ žœžœ˜Kšœžœ˜#Jšœ žœ ˜/Kšžœ˜ —šžœ žœ˜Kšœ"žœ˜'Jšžœžœžœ žœ ˜KKšžœ˜ —šžœžœžœ$žœ˜HKšœ$žœ˜)Jšœ žœ#˜2Kšžœ˜ —Kšœ žœ˜Kšœ:˜:šžœžœžœ˜Kšœ.˜.Kšžœžœžœžœ˜Kšœ#˜#Kšžœ˜ —Kšœ$žœ˜)Kšžœžœžœ žœ&˜QKšžœ˜ šž˜Kšœžœ˜#Kšœ žœžœ˜—Kšžœ˜—K˜K™—š  œžœžœžœžœžœ˜NKš žœ8žœžœžœžœ˜QKšœ2žœ˜7Kšžœ0˜6K˜—K˜š  œž œ˜+šžœž˜Kšžœ˜Kšžœ˜#—Kšœ˜Kšžœ˜Kšžœžœ˜ Kšœ˜—K˜š œžœžœ˜:Kšœ2žœ˜7Kšœ˜——™ ™ Kšœžœ˜Kšœžœ˜Kšœžœ˜—K˜Kšœ:‘˜HKšœ:‘˜HK˜š œžœ˜Kšœ0˜0šž˜Kšœžœ˜1šžœžœ ˜šžœ‘˜%Kšœ'˜'Kšœ˜Kšœ žœ˜'—šžœ‘˜Kšœ"˜"Kšœ"žœ˜*——Kšœ žœ˜ Kšžœ˜—Kšžœ˜K˜—š œžœ˜Kšœ/™/Kšœ0˜0šž˜Kšœ žœ˜,Kšœžœ˜&Kšœ"˜"Kšœ˜Kšœžœ˜Kšœ žœ˜%Kšžœ˜—Kšžœ˜K˜K˜—Kšœ(žœ˜GKšœ(žœ(˜TKšžœžœ˜3Kšžœžœ˜3K˜—Kšœ˜K˜—J˜—…—IΜf–