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, IsMulticastHost, Net, Socket, unknownAddress, unknownNet, unknownSocket], XNSBuf USING [Buffer, BufferObject, hdrBytes, maxBodyBytes, maxBodyFWords, maxBodyHWords, noChecksum], XNSErrorBuf USING [Buffer, hdrBytes, minBodyBytes], 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]] }; 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 _ XNSBuf.noChecksum }; }; InlineTestChecksum: PROC [b: Buffer, bytes: CARDINAL] RETURNS [BOOL] ~ TRUSTED INLINE { IF b.hdr1.checksum # XNSBuf.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; handle.routingCache _ NIL; -- FlushCache[handle] }; 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[1]; 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; }; 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 [b: Buffer, socket: Socket] ~ { handle: Handle ~ NARROW[b.ovh.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[b]; }; Put: PUBLIC PROC [b: Buffer] ~ { handle: Handle ~ NARROW[b.ovh.socket]; Send[b, handle.remote]; -- What if it's UNKNOWN??? }; Send: PUBLIC PROC [b: Buffer, dest: Address] ~ { handle: Handle ~ NARROW[b.ovh.socket]; bytes: CARDINAL = GetBytesRounded[b]; network: Network; immediate: Host; IF (dest.net = XNS.broadcastNet) AND (dest.host = XNS.broadcastHost) THEN { Broadcast[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[b]; }; PutCached: PUBLIC PROC [b: Buffer] ~ { handle: Handle ~ NARROW[b.ovh.socket]; 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. }; AccountForReturnedBuffer: 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; }; FreeBuffer: PUBLIC PROC [b: Buffer] ~ { h: Handle ~ NARROW[b.ovh.socket]; IF h # NIL THEN AccountForReturnedBuffer[h, b]; 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; }; ReturnToSender: PUBLIC PROC [b: Buffer] ~ { handle: Handle ~ NARROW[b.ovh.socket]; bytes: CARDINAL ~ GetBytesRounded[b]; sendChecksum: BOOL ~ IF handle = NIL THEN TRUE ELSE handle.sendChecksum; network: Network ~ NARROW[b.ovh.network]; FixupSourceAndDest[b]; { temp: Address ~ b.hdr1.source; b.hdr1.source _ b.hdr1.dest; b.hdr1.dest _ temp }; IF XNS.IsMulticastHost[b.hdr1.dest.host] THEN { FreeBuffer[b]; RETURN }; b.hdr1.transportCtl _ [trace~FALSE, filler~0, hopCount~0]; InlineSetChecksum[b, bytes, sendChecksum]; network.xns.return[network, TempDriverBuffer[b], bytes]; FreeBuffer[b]; }; ReturnError: PUBLIC PROC [b: Buffer, type: XNSErrorTypes.ErrorType] ~ { bodyBytes: CARDINAL ~ XNSErrorBuf.minBodyBytes; eb: XNSErrorBuf.Buffer; IF b.hdr1.type = error OR XNS.IsMulticastHost[b.hdr1.dest.host] THEN { FreeBuffer[b]; RETURN }; TRUSTED { -- ???? WORD-SIZE DEPENDENT ???? eb _ LOOPHOLE[b]; PrincOpsUtils.LongMove[ from: @b.hdr1, nwords: (bodyBytes+1)/2, to: @eb.body]; }; b.hdr1.type _ error; eb.hdr2.type _ type; eb.hdr2.param _ XNSErrorTypes.nullParam; SetUserBytes[b, XNSErrorBuf.hdrBytes + bodyBytes]; ReturnToSender[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[b, XNSErrorTypes.unspecifiedInRouteErr]; b _ NIL; -- What's the RIGHT error to use here? GOTO Out; }; handle _ FindHandle[localSocket]; IF handle = NIL THEN { errorNoSocket _ errorNoSocket.SUCC; ReturnError[b, XNSErrorTypes.noSocketErr]; b _ NIL; GOTO Out; }; IF handle.dead THEN { errorDeadSocket _ errorDeadSocket.SUCC; IF NOT handle.noErrors THEN { ReturnError[b, XNSErrorTypes.noSocketErr]; b _ NIL }; GOTO Out; }; IF handle.recvChecksum AND NOT InlineTestChecksum[b, bytesNeeded] THEN { errorBadChecksum _ errorBadChecksum.SUCC; ReturnError[b, XNSErrorTypes.badChecksumErr]; b _ NIL; GOTO Out; }; b.ovh.next _ NIL; -- This can't hurt, but what is it doing here ???? [receiveProc, receiveClientData] _ GetReceiveProc[handle, b]; IF receiveProc # NIL THEN { b _ receiveProc[handle, b, receiveClientData]; IF (b # NIL) AND (b.ovh.socket # NIL) THEN AccountForReturnedBuffer[NARROW[b.ovh.socket], b]; GOTO Out; }; errorBuffersFull _ errorBuffersFull.SUCC; IF NOT handle.noErrors THEN { ReturnError[b, XNSErrorTypes.resourceLimitsErr]; b _ NIL }; GOTO Out; EXITS Out => NULL; END; RETURN[ IF b = NIL THEN NIL ELSE RealDriverBuffer[b] ]; }; GetReceiveProc: ENTRY PROC [handle: Handle, b: Buffer] RETURNS [ReceiveProc, REF ANY] ~ { IF handle.recvBuffersInUse >= handle.recvBuffersAllocated THEN RETURN [NIL, NIL]; handle.recvBuffersInUse _ handle.recvBuffersInUse.SUCC; b.ovh.socket _ handle; 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]; }; 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[b]; b _ NIL; droppedBuffers _ droppedBuffers.SUCC; ENDLOOP; }; SafeStorage.EstablishFinalization[type: CODE[Object], npr: 1, fq: ofq]; SafeStorage.EstablishFinalization[type: CODE[XNSBuf.BufferObject], npr: 0, 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, December 19, 1986 6:28:41 pm PST 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, unless it was multicast or sender is (invalidly) multicast. 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™—š  œž œ ˜6Kšœžœ˜&Kšœžœ˜%K˜Kšœžœ˜:Kšœ˜Kšœžœ˜%K˜šžœ?žœ žœž˜XKšœ4žœ˜GKšœ"˜"Kšœ$˜$Kšœ1˜1Kšœ6˜6Kšžœ˜—Kšœ˜Kšœ˜K˜—š œžœžœ˜ Kšœžœ˜&Kšœ‘˜2K˜K™—š œž œ˜0Kšœžœ˜&Kšœžœ˜%Kšœ˜K˜šžœ žœžœžœ˜DKšžœžœ˜,—Kšœžœ˜:Kšœ˜K˜Kšœ4˜4šžœ žœžœ˜Kšœ?˜?Kšœ1˜1Kšœ6˜6Kšœ˜—Kšœ˜Kšœ˜—K˜—™š  œž œ˜&Kšœžœ˜&Kšœžœ˜%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˜š œžœžœ ˜Dšžœž˜šœ ˜ Kšœ6˜6Kšžœ˜"—Kšœ>˜>Kšžœžœ˜—K˜K˜—š  œžœžœ˜'Kšœ žœ˜!Kšžœžœžœ ˜/Kšœ+˜+Kšœ˜K™—š œžœžœ˜/Kšœžœ˜)Kšžœžœ žœ%˜OKšžœžœ žœ#˜KKšžœžœžœ˜IKšœ˜K™—š œžœžœ˜+K™TKšœžœ˜&Kšœžœ˜%Kš œžœžœ žœžœžœžœ˜HKšœžœ˜)Kšœ˜K˜UKšžœžœ"žœžœ˜HKšœžœ˜:Kšœ*˜*Kšœ8˜8Kšœ˜K˜K™—š  œž œ/˜GKšœ žœ˜/K˜šžœžœžœ"˜?Kšžœžœ˜—šžœ‘ ˜*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šœ9žœ‘'˜dKšžœ˜ —Kšœ!˜!šžœ žœžœ˜Kšœžœ˜#Jšœ/žœ˜3Kšžœ˜ —šžœ žœ˜Kšœ"žœ˜'šžœžœž˜Jšœ1žœ˜7—Kšžœ˜ —šžœžœžœ$žœ˜HKšœ$žœ˜)Jšœ2žœ˜6Kšžœ˜ —Kšœ žœ‘2˜DKšœ=˜=šžœžœžœ˜Kšœ.˜.Kš žœžœžœžœžœžœ˜]Kšžœ˜ —Kšœ$žœ˜)šžœžœž˜Kšœ7žœ˜=—Kšžœ˜ šž˜Kšœžœ˜ —Kšžœ˜—Kš žœžœžœžœžœžœ˜7K˜K™—š  œžœžœžœžœžœ˜YKš žœ8žœžœžœžœ˜QKšœ2žœ˜7K˜Kšžœ0˜6K˜—K˜š  œž œ˜+šžœž˜Kšžœ˜Kšžœ˜#—Kšœ˜Kšžœ˜Kšžœžœ˜ Kšœ˜——™ ™ 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˜—…—I0eY