-- File: TcpUtilImpl.mesa - last edit: -- JAV 19-Nov-87 14:04:54 -- AOF 2-Jun-87 12:18:06 -- sma 9-Feb-87 14:51:11 -- Copyright (C) 1985, 1986, 1987 by Xerox Corporation. All rights reserved. DIRECTORY ArpaBuffer USING [Body, Buffer], ArpaPort USING [ GetAssignedAddress, GetBufferPool, SetIPLengths, SetWaitTime, WaitTime], ArpaPortInternal USING [AddrMismatch, BuildMasks, GetSubnetMask], ArpaRouter USING [InternetAddress, Port, unknownInternetAddress], ArpaTypes USING [InternetAddress, Port], CommUtil USING [PulsesToTicks], Environment USING [Block, bytesPerPage, bytesPerWord], File USING [nullFile], Process USING [DisableTimeout, EnableAborts, MsecToTicks, SetTimeout], Protocol1 USING [GetFamilyUnit], Runtime USING [GetCaller], Space USING [Map], System USING [GetClockPulses, MicrosecondsToPulses], TcpImpl USING [connection, rcvr, rexmtr, xmtr], TcpPort USING [CreateTcpPort], TcpStream USING [Precedence, Security, WaitTime], TcpStreamInternal USING [ LowHalf, inputSpacePages, rcvrDefaults, rexmtrDefaults, maxTcpDataBytes, xmtrAlloc, send, receive, tos, ttl, fragAllowed, minTcpHeaderBytes]; TcpUtilImpl: MONITOR IMPORTS ArpaPort, ArpaPortInternal, ArpaRouter, CommUtil, Process, Protocol1, Runtime, Space, System, TcpPort, TcpStreamInternal EXPORTS ArpaRouter, TcpStreamInternal = BEGIN seed: WORD ¬ TcpStreamInternal.LowHalf[System.GetClockPulses[]]; Port: PUBLIC --ArpaRouter-- TYPE = ArpaTypes.Port; InternetAddress: PUBLIC --ArpaRouter-- TYPE = ArpaTypes.InternetAddress; bpp: NATURAL = Environment.bytesPerPage; bpw: NATURAL = Environment.bytesPerWord; InitStream: PUBLIC PROC [local, remote: ArpaRouter.InternetAddress, localPort, remotePort: ArpaRouter.Port, timeout: TcpStream.WaitTime, precedence: TcpStream.Precedence, security: TcpStream.Security, options: Environment.Block] = BEGIN time: LONG CARDINAL = System.GetClockPulses[]; mask: InternetAddress = ArpaPortInternal.BuildMasks[local].netMask; -- set based on whether these guys are on the same network delayToRemote: CARDINAL = IF ArpaPortInternal.AddrMismatch[ IF ArpaPortInternal.GetSubnetMask[] # ArpaRouter.unknownInternetAddress THEN ArpaPortInternal.GetSubnetMask[] ELSE mask, local, remote] THEN 1 ELSE 0; him: LONG POINTER TO FRAME[TcpImpl] = LOOPHOLE[Runtime.GetCaller[]]; him.rcvr.nextSeq ¬ 0; him.rcvr.maxSeq ¬ him.rcvr.irs ¬ 0; --set for real when connection request arrives. him.rcvr.ackInterval ¬ System.MicrosecondsToPulses[LONG[1000] * LONG[ TcpStreamInternal.rcvrDefaults.ackInterval]]; him.rcvr.remoteBlocked ¬ FALSE; him.rcvr.urgSig ¬ FALSE; --ditto. him.rcvr.urg ¬ 0; Process.EnableAborts[@him.rcvr.urgArrived]; Process.DisableTimeout[@him.rcvr.urgArrived]; him.rcvr.pushSig ¬ FALSE; him.rcvr.push ¬ 0; --ditto. him.rcvr.finSig ¬ FALSE; him.rcvr.fin ¬ 0; --ditto. him.rcvr.lastConsumed ¬ 0; him.rcvr.inputSpace.size ¬ (bpp * TcpStreamInternal.inputSpacePages) - ((bpp * TcpStreamInternal.inputSpacePages) MOD TcpStreamInternal.maxTcpDataBytes); him.rcvr.inputSpace.space ¬ Space.Map[[File.nullFile, 0, TcpStreamInternal.inputSpacePages]]; him.rcvr.inuse ¬ [NIL, 0]; him.rcvr.avail ¬ [NIL, 0]; him.rcvr.process ¬ NIL; Process.EnableAborts[@him.rcvr.newInput]; Process.DisableTimeout[@him.rcvr.newInput]; him.rexmtr.list ¬ [0, NIL]; him.rexmtr.ceiling ¬ System.MicrosecondsToPulses[ LONG[TcpStreamInternal.rexmtrDefaults.ceiling]*LONG[1000]]; him.rexmtr.floor ¬ System.MicrosecondsToPulses[ LONG[TcpStreamInternal.rexmtrDefaults.floor]*LONG[1000]]; him.rexmtr.giveUp ¬ TcpStreamInternal.rexmtrDefaults.giveUp; him.rexmtr.count ¬ 0; him.rexmtr.delay ¬ 0; him.rexmtr.interval ¬ System.MicrosecondsToPulses[ IF delayToRemote = 0 THEN LONG[TcpStreamInternal.rexmtrDefaults.initialLocal] * 1000 ELSE LONG[TcpStreamInternal.rexmtrDefaults.initialRemote] * 1000]; him.rexmtr.calculationInterval ¬ System.MicrosecondsToPulses[ LONG[TcpStreamInternal.rexmtrDefaults.calculationInterval] * 1000]; him.rexmtr.calculation ¬ time; him.rexmtr.process ¬ NIL; Process.EnableAborts[@him.rexmtr.condition]; Process.SetTimeout[ @him.rexmtr.condition, CommUtil.PulsesToTicks[[him.rexmtr.floor/2]]]; --set for real when syn comes in. him.xmtr.iss ¬ him.xmtr.maxSeq ¬ him.xmtr.unackedSeq ¬ him.xmtr.nextSeq ¬ 0; him.xmtr.maxAlloc ¬ TcpStreamInternal.xmtrAlloc; him.xmtr.blocked ¬ [NIL, 0]; him.xmtr.clientProcess ¬ NIL; him.xmtr.timeWaitStart ¬ 0; him.xmtr.context ¬ NIL; Process.DisableTimeout[@him.xmtr.newAllocation]; Process.EnableAborts[@him.xmtr.newAllocation]; him.connection.state ¬ closed; him.connection.stateBeforeSuspension ¬ closed; him.connection.whySuspended ¬ notSuspended; him.connection.offNet ¬ FALSE; him.connection.pleaseStop ¬ FALSE; --may be changed by max size option exchange. him.rcvr.maxTcpBytes ¬ him.xmtr.maxTcpBytes ¬ TcpStreamInternal.maxTcpDataBytes; Process.SetTimeout[@him.connection.isEstablished, Process.MsecToTicks[2000]]; Process.EnableAborts[@him.connection.isEstablished]; him.connection.port ¬ TcpPort.CreateTcpPort[port: localPort, send: TcpStreamInternal.send, receive: TcpStreamInternal.receive, remote: remote, remotePort: remotePort]; him.connection.localAddr ¬ ArpaPort.GetAssignedAddress[him.connection.port]; him.connection.remoteAddr ¬ remote; IF delayToRemote # 0 THEN him.connection.offNet ¬ TRUE ELSE him.connection.offNet ¬ FALSE; him.connection.localPort ¬ localPort; him.connection.remotePort ¬ remotePort; him.connection.timeout ¬ timeout; him.connection.precedence ¬ precedence; him.connection.security ¬ security; --options are ignored right now, since the only actual option is max size, --set by us (not the client), in the connection request only. him.connection.options ¬ options; ArpaPort.SetWaitTime[him.connection.port, LAST[ArpaPort.WaitTime]]; him.connection.pool ¬ ArpaPort.GetBufferPool[him.connection.port]; him.connection.family ¬ Protocol1.GetFamilyUnit[arpa]; --pointer to family END; --InitStream GetDataLength: PUBLIC PROC [body: ArpaBuffer.Body] RETURNS [l: CARDINAL, p: LONG POINTER] = --returns the data length in bytes and a pointer to the data in the buffer. BEGIN p ¬ @body.ipData + (body.tcp.dataOffset * 2); l ¬ (body.ipHeader.ihl * 4) + (body.tcp.dataOffset * 4); --headers length --we don't want l going negative if remote screwed up. IF l > body.ipHeader.length THEN l ¬ 0 ELSE l ¬ body.ipHeader.length - l; END; --GetDataLength PrecedenceMatch: PUBLIC PROC [body: ArpaBuffer.Body] RETURNS [BOOLEAN] = BEGIN RETURN[TRUE]; END; --PrecedenceMatch SecurityMatch: PUBLIC PROC [body: ArpaBuffer.Body] RETURNS [BOOLEAN] = BEGIN RETURN[TRUE]; END; --SecurityMatch SetHeaderFields: PUBLIC PROC[ b: ArpaBuffer.Buffer, dataLen, optionsLen: CARDINAL] = BEGIN << PROCESS: RECEIVER, CLIENT SENDER Sets the header fields (IP and TCP) of the packet. >> headerBytes: CARDINAL; --for setting length, .. tcp header may be padded ipOptionsSize: CARDINAL ¬ 0; body: ArpaBuffer.Body = b.arpa; him: LONG POINTER TO FRAME[TcpImpl] = LOOPHOLE[Runtime.GetCaller[]]; b.fo.time ¬ System.GetClockPulses[]; --record packet send time b.fo.tries ¬ 1; --number of times we transmitted this packet. body.ipHeader.protocol ¬ tcp; body.ipHeader.destination ¬ him.connection.remoteAddr; body.ipHeader.service ¬ TcpStreamInternal.tos; body.ipHeader.identification ¬ UniquePktID[]; --for frag/reassembly. body.ipHeader.lifetime ¬ TcpStreamInternal.ttl; body.ipHeader.flags.dontFragment ¬ ~TcpStreamInternal.fragAllowed; IF him.connection.security # NIL THEN BEGIN securityPtr: TcpStream.Security ¬ LOOPHOLE[@body.ipHeader.options]; securityPtr­ ¬ him.connection.security­; ipOptionsSize ¬ SIZE[TcpStream.Security] * bpw; END; body.tcp.reserved ¬ 0; headerBytes ¬ optionsLen + TcpStreamInternal.minTcpHeaderBytes; body.tcp.dataOffset ¬ (headerBytes + 3) / 4; body.tcp.destinationPort ¬ him.connection.remotePort; --we set lengths here because we needed all the other header info first. ArpaPort.SetIPLengths[body, ipOptionsSize, headerBytes + dataLen]; --checksum is set when the packet is sent. END; --SetHeaderFields UniquePktID: PUBLIC ENTRY PROC RETURNS [WORD] = {RETURN[(seed ¬ SUCC[seed])]}; END.. LOG 3-Oct-85 9:48:32 SMA Created file - stateless procs from TcpImpl. 30-Jan-86 11:57:03 SMA GetDataLen returns length and pointer to data. 18-Jul-86 11:37:36 AOF 32-bit math procs use 'INT' rather than 'INTEGER'. 2-Feb-87 11:36:35 SMA Moved stuff from TcpImpl to shut up compiler. 5-Feb-87 10:49:50 SMA xmtr.blocked for allocation probing. 11-Mar-87 10:00:46 AOF Funston buffer management. 11-Mar-87 10:04:28 AOF made UniquePktID a random seed, montonic­ function. 11-Mar-87 10:18:05 AOF Made low-level functions INLINEs in interface. 2-Jun-87 10:58:40 AOF Caching of DataObject entries.