DIRECTORY Allocator USING [NHeaderP, NormalHeader], Basics USING [BITAND, bytesPerFWord, bytesPerHWord, bytesPerWord, Card16FromH, HFromCard16, HWORD, LowHalf], BasicTime USING [GetClockPulses], Checksum USING [ComputeChecksum], CommBuffer USING [Direction, Encapsulation], CommDriver USING [AllocBuffer, Buffer, BufferObject, FreeBuffer, GetNetworkChain, Network], 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, BasicTime, Checksum, CommDriver, 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 ~ Basics.HWORD; bytesPerHWord: NAT ~ Basics.bytesPerHWord; bytesPerFWord: NAT ~ Basics.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] }; uniqueNumberLock: Handle ~ NEW[Object _ [local~, remote~, sendBuffersAllocated~, recvBuffersAllocated~, receiveProc~NIL]]; uniqueLocalSocketNumber: CARD16 _ 0; NextLocalSocket: ENTRY PROC [handle: Handle _ uniqueNumberLock] RETURNS [Socket] ~ { IF uniqueLocalSocketNumber = 0 THEN uniqueLocalSocketNumber _ Basics.Card16FromH[LOOPHOLE[XNSWKS.last]]; uniqueLocalSocketNumber _ uniqueLocalSocketNumber.SUCC; RETURN [LOOPHOLE[Basics.HFromCard16[uniqueLocalSocketNumber]]] }; unique16: CARD16 _ Basics.LowHalf[BasicTime.GetClockPulses[]]; GetUnique16: PUBLIC PROC RETURNS [CARD16] ~ { RETURN [EntryGetUnique16[uniqueNumberLock]] }; EntryGetUnique16: ENTRY PROC [handle: Handle] RETURNS [CARD16] ~ { RETURN [unique16 _ unique16.SUCC] }; unique32: CARD32 _ BasicTime.GetClockPulses[]; GetUnique32: PUBLIC PROC RETURNS [CARD32] ~ { RETURN [EntryGetUnique32[uniqueNumberLock]] }; EntryGetUnique32: ENTRY PROC [handle: Handle] RETURNS [CARD32] ~ { RETURN [unique32 _ unique32.SUCC] }; GetBytesRounded: PROC [b: Buffer] RETURNS [CARDINAL] ~ INLINE { RETURN[Basics.BITAND[(1+Basics.Card16FromH[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 ~ Basics.HFromCard16[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[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; }; InnerAllocBuffer: ENTRY PROC [handle: Handle] ~ { ENABLE UNWIND => NULL; UNTIL handle.sendBuffersInUse < handle.sendBuffersAllocated DO WAIT handle.waitForSendBuffer; ENDLOOP; handle.sendBuffersInUse _ handle.sendBuffersInUse + 1; }; SetUserBits: PUBLIC PROC [b: Buffer, bits: [0 .. XNSBuf.maxBodyBytes*BITS[BYTE]]] ~ { b.hdr1.length _ Basics.HFromCard16[(bits/BITS[BYTE]) + XNSBuf.hdrBytes]; }; SetUserBytes: PUBLIC PROC [b: Buffer, bytes: [0 .. XNSBuf.maxBodyBytes]] ~ { b.hdr1.length _ Basics.HFromCard16[bytes + XNSBuf.hdrBytes]; }; SetUserHWords: PUBLIC PROC [b: Buffer, hWords: [0 .. XNSBuf.maxBodyHWords]] ~ { b.hdr1.length _ Basics.HFromCard16[hWords*bytesPerHWord + XNSBuf.hdrBytes]; }; SetUserFWords: PUBLIC PROC [b: Buffer, fWords: [0 .. XNSBuf.maxBodyFWords]] ~ { b.hdr1.length _ Basics.HFromCard16[fWords*bytesPerFWord + XNSBuf.hdrBytes]; }; 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 }; }; GetUserBits: PUBLIC PROC [b: Buffer] RETURNS [bits: [0 .. XNSBuf.maxBodyBytes*BITS[BYTE]]] ~ { bits _ Basics.Card16FromH[b.hdr1.length]*BITS[BYTE] - XNSBuf.hdrBytes; }; GetUserBytes: PUBLIC PROC [b: Buffer] RETURNS [bytes: [0 .. XNSBuf.maxBodyBytes]] ~ { bytes _ Basics.Card16FromH[b.hdr1.length] - XNSBuf.hdrBytes; }; GetUserHWords: PUBLIC PROC [b: Buffer] RETURNS [hWords: [0 .. XNSBuf.maxBodyHWords]] ~ { bytes: [0 .. XNSBuf.maxBodyBytes] _ Basics.Card16FromH[b.hdr1.length] - XNSBuf.hdrBytes; hWords _ bytes/bytesPerHWord; }; GetUserFWords: PUBLIC PROC [b: Buffer] RETURNS [fWords: [0 .. XNSBuf.maxBodyFWords]] ~ { bytes: [0 .. XNSBuf.maxBodyBytes] _ Basics.Card16FromH[b.hdr1.length] - XNSBuf.hdrBytes; fWords _bytes/bytesPerFWord; }; FreeBuffer: PUBLIC PROC [b: Buffer] ~ { h: Handle ~ NARROW[b.ovh.socket]; FreeBufferInner: ENTRY PROC [handle: Handle] ~ { SELECT b.ovh.direction FROM send => { handle.sendBuffersInUse _ handle.sendBuffersInUse - 1; NOTIFY handle.waitForSendBuffer }; recv => handle.recvBuffersInUse _ handle.recvBuffersInUse - 1; ENDCASE => ERROR; }; IF h # NIL THEN FreeBufferInner[h]; 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 (Basics.Card16FromH[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; -- WHAT IN GOD'S NAME IS THIS DOING HERE ???? [receiveProc, receiveClientData] _ GetReceiveProc[handle]; IF receiveProc # NIL THEN { b _ receiveProc[handle, b, receiveClientData]; IF b # NIL THEN DecrementRecvBuffersInUse[handle]; 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] 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[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 20, 1986 12:28:40 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 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˜—š  œžœžœžœžœ˜BKšžœžœ˜$K˜—Kšœ žœ˜.K˜š   œžœžœžœžœ˜-Kšžœ(˜.K˜—š  œžœžœžœžœ˜BKšžœžœ˜$K˜——™š  œžœ žœžœžœ˜?K™YKšžœžœ3˜G—K˜š œžœžœ žœžœžœžœ˜^KšœK™KKšžœžœžœ™5K™Gšžœ ˜ šžœ˜Kšœžœ*˜9Kšœ žœžœ˜-KšœC˜C—šžœ˜Kšœ&˜&——K˜K˜—š œžœžœžœžœžœžœ˜WKšœK™KK™1Kšžœžœžœ™5K™Gšžœ$˜&šžœ˜Kšœžœ*˜9Kšœ žœJ˜[Kšžœ#˜)—Kšžœžœžœ˜—K˜K™—š  œžœžœ˜(Kšœ+˜+—K˜—š ™š œžœžœ˜Kšœžœ˜%Kšœ žœ˜Kšœ žœ˜Kšœ!˜!Kšœžœ˜#Kšžœ˜K˜Kšœ˜K˜1Kšžœ žœžœ(˜=Kšžœ žœžœ˜<šœ žœ ˜Kšœ9˜9Kšœ˜Kšœ!˜!Kšœ!˜!Kšœ˜—šžœ˜ Kšœ+˜+Kšœ2˜2—Kšœ"˜"Kšœ˜Icode2šœ'˜'K˜—˜K˜—š œž œžœ˜CKšžœ˜K˜—K˜š œž œžœ˜DKšžœ˜K˜—K˜š œž œ'˜DKšœ˜Kšœžœ‘˜0K˜—K˜š  œž œ'˜AKšœžœ˜šžœž˜Kšœ(žœ˜-šœžœ˜"Kšœ0˜0—šœžœžœžœ˜KšœF˜F—šžœžœ˜KšœN˜N——Kšœ˜—K™š œž œžœ˜KKšœ˜Kšœ˜K˜K™—š  œž œžœžœ˜DKšœ˜Kšœ˜—K˜š œžœžœžœ˜,Kšžœ˜K˜K™—š œžœžœžœ˜/Kšœžœ˜šžœžœž˜ Kšœ˜Kšœ˜Kšœ6˜6Kšœ+˜+Kšžœ˜—Kšœžœ‘˜4šžœžœžœ˜TKšžœžœžœžœ˜C—K™3K˜K˜—š  œžœ˜'Kšœ6˜6Kšœ0˜0Kšžœžœ˜4šžœžœž˜GKšœ˜Kšžœ˜—K™3K˜——š ™š  œžœžœžœ˜AKšœ˜Kšœ2˜2Kšœ žœ˜Kšœ˜Kšœ˜K™—š œžœžœ˜1Kšžœžœžœ˜šžœ7ž˜>Kšžœ˜Kšžœ˜—Kšœ6˜6Kšœ˜K˜—š   œžœžœ-žœžœ˜UKšœ)žœžœ˜HKšœ˜—š  œž œ3˜LKšœ<˜˜>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˜šž˜šžœžœ6žœ˜XKšœžœ˜#Kšžœ˜ —šžœžœžœžœ˜NKšœ žœ˜%Jšœ9žœ‘'˜dKšžœ˜ —Kšœ!˜!šžœ žœžœ˜Kšœžœ˜#Jšœ/žœ˜3Kšžœ˜ —šžœ žœ˜Kšœ"žœ˜'šžœžœž˜Jšœ1žœ˜7—Kšžœ˜ —šžœžœžœ$žœ˜HKšœ$žœ˜)Jšœ2žœ˜6Kšžœ˜ —Kšœ žœ‘-˜?Kšœ:˜:šžœžœžœ˜Kšœ.˜.Kšžœžœžœ#˜2Kšžœ˜ —Kšœ$žœ˜)šžœžœž˜Kšœ7žœ˜=—Kšžœ˜ šž˜Kšœžœ˜ —Kšžœ˜—Kš žœžœžœžœžœžœ˜7K˜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˜—…—Kjh|