DIRECTORY Arpa USING [Address], ArpaBuf USING [maxBodyBytes], ArpaIP USING [Buffers, Handle], ArpaTCP USING [DByte, Port, Reason, TCPInfo], BasicTime USING [GetClockPulses, Pulses], PrincOps USING [zEXCH]; ArpaTCPOps: CEDAR DEFINITIONS IMPORTS BasicTime ~ BEGIN maxSendBufferLength: INT ~ 4000; -- max bytes of unacked data to queue for transmission or retransmission to net sendBufferLength: INT; -- max bytes of unacked data to queue for transmission or retransmission to net recvBufferLength: INT ~ 4000; tcpHdrWordLength: INT ~ 5; tcpHdrByteLength: INT ~ tcpHdrWordLength*4; maxTCPDataLength: INT; -- TCP Maximum Segment Size sillyWindowLimit: INT ~ 40; -- try not to send when window is smaller than this probeTimeout: INT; -- time (ms) to wait on zero window before sending a probe defaultProbeTimeout: INT ~ 120000; -- 2 min. suggested by RFC793 ourLocalAddress: Arpa.Address; tcpIPHandle: ArpaIP.Handle; defaultReceiveWindow: INT; repacketizing: BOOL; -- TRUE if data to be repacketized when retransmitted tcpSegmentLife: INT ~ 60; -- value for time to live Buffer: TYPE = ArpaIP.Buffers; ConnectionState: TYPE = {closed, listen, synSent, synRcvd, established, finWait1, finWait2, closeWait, closing, lastAck, timeWait}; Pair: TYPE = MACHINE DEPENDENT RECORD [a, b: CARDINAL]; -- used for word swap TCPHeaderP: TYPE = LONG POINTER TO TCPHeader; TCPHeader: TYPE = MACHINE DEPENDENT RECORD [ sourcePort (0): ArpaTCP.Port, -- source port number dstnPort (1): ArpaTCP.Port, -- destination port number seqNumber (2): Pair, -- sequence number ackNumber (4): Pair, -- acknowledgement number dataWordOffset (6: 0..3): INT [0..15], -- size of header in 32-bit words unused (6: 4..9): INT [0..63] _ 0, urg (6: 10..10): BOOL _ FALSE, -- control flags, urgent ack (6: 11..11): BOOL _ FALSE, -- acknowledgement psh (6: 12..12): BOOL _ FALSE, -- push rst (6: 13..13): BOOL _ FALSE, -- reset syn (6: 14..14): BOOL _ FALSE, -- syn (first packet on connection) fin (6: 15..15): BOOL _ FALSE, -- fin (last packet on connection) window (7): ArpaTCP.DByte, -- window of packets to send checksum (8): ArpaTCP.DByte, -- for header and pseudo header urgentPtr (9): ArpaTCP.DByte _ 0, -- ptr to byte following urgent data options (10): ARRAY INT [1..40] OF BYTE]; -- options TCPHandle: TYPE ~ REF TCPHandleRec; TCPHandleRec: TYPE ~ MONITORED RECORD [ localPort: ArpaTCP.Port, -- TCP port foreignAddr: Arpa.Address, -- internet foreign address foreignPort: ArpaTCP.Port, -- TCP port matchForeignAddr: BOOL, -- true to use foreign addr matchForeignPort: BOOL, -- true to use foreign port state: ConnectionState, -- state of connection reason: ArpaTCP.Reason, -- why we closed this connection active: BOOL, -- active or passive open notListening: CONDITION, -- used to wait for connection when listening maxSegmentSize: INT, -- max bytes we can send in a datagram sndUna: INT _ 0, -- oldest unacked seq number sndNxt: INT _ 0, -- next seq number to send sndWnd: INT _ 0, -- send window sndWL1: INT _ 0, -- pkt seq used for last window update sndWL2: INT _ 0, -- pkt ack used for last window update iss: INT _ 0, -- initial send seq number sndUrgent: BOOL _ FALSE, -- true if trying to send urgent data sndUp: INT _ 0, -- where it is in the stream fillSlot: INT [0..maxSendBufferLength) _ 0, -- for repacketizing sendSlot: INT [0..maxSendBufferLength) _ 0, -- for repacketizing sendBuffer: ARRAY INT [0..maxSendBufferLength) OF BYTE, -- for repacketizing nBytesToSend: INT [0..maxSendBufferLength] _ 0, -- number of filled slots in sendBuffer rcvNxt: INT _ 0, -- next seq number to receive rcvWnd: INT, -- receive window rcvUp: INT _ 0, -- receive urgent pointer zeroRcvWnd: BOOL _ FALSE, -- last advertised receive window was zero irs: INT _ 0, -- initial receive sequence number urgentMode: BOOL _ FALSE, -- rcvd urgent data and not passed to user finSequence: INT _ 0, -- sequence number of fin sent dataTimeout: INT, -- in msecs, time to wait before signalling client timeWaitTime: BasicTime.Pulses, -- when to delete a handle in timeWait state fromNetQueue: LIST OF REF ANY, -- packets received from net (actually TCPRcvBuffers) readyToReadQueue: LIST OF REF ANY, -- packets processed and ready to hand to client (TCPRcvBuffers) currentInputBuffer: REF TCPRcvBuffer, -- buffer for doling out input dataAvailable: CONDITION, -- wait here for incoming data toNetQueue: LIST OF REF ANY, -- packets to send to net (ArpaIP.Bufferss) rexmitQueue: LIST OF REF ANY, -- packets to retransmit to net (TCPSendBuffers) currentOutputDatagram: ArpaIP.Buffers, -- next block of data to send currentOutputPtr: INT, -- index into currentOutputDatagram for data currentOutputLimit: INT, -- max size of datagram based on maxSegmentSize windowAvailable: CONDITION, -- wait here for quota on other end urgentAvailable: CONDITION]; -- wait here for urgent data TCPRcvBuffer: TYPE ~ RECORD [ offsetSeqNo: INT, -- for use by TCP datagramPtr: ArpaIP.Buffers, -- datagram received from net dataOffset: INT, -- Byte offset of data from dataPtr^ dataByteCount: INT, -- number of data bytes tcpHdrPtr: TCPHeaderP, -- pointer to TCP header (?) urg: BOOL, -- value of TCP URG field endUrgentData: INT]; -- index of byte following urgent data TCPSendBuffer: TYPE ~ RECORD [ dataByteCount: INT, -- count of data sent (not control) rexmitTime: BasicTime.Pulses, -- time to retransmit segment timeoutTime: BasicTime.Pulses, -- time to abort connection if segment not acked datagram: ArpaIP.Buffers]; -- datagram sent to net TCPControlSet: TYPE ~ RECORD [ urg, ack, psh, rst, syn, fin: BOOL _ FALSE]; pktsSent: INT; pktsRcvd: INT; pktsRexmitted: INT; pktsDuplicate: INT; pktsWithNoConnection: INT; pktsFromFuture: INT; pktsFromPast: INT; pktsWithBadChecksum: INT; Open: PROC [tcpInfo: ArpaTCP.TCPInfo] RETURNS [handle: TCPHandle]; Close: PROC [handle: TCPHandle]; Abort: PROC [handle: TCPHandle]; WaitForListenerOpen: PROC [handle: TCPHandle, timeout: INT]; SendCurrentDatagram: PROC [handle: TCPHandle, push: BOOL]; GetNextDatagram: PROC [handle: TCPHandle]; SetUrgent: PROC [handle: TCPHandle]; WaitForUrgentData: PROC [handle: TCPHandle] RETURNS [urgentIndex: INT]; Flip: PROC [Pair] RETURNS [INT] = TRUSTED MACHINE CODE BEGIN PrincOps.zEXCH; END; Flop: PROC [INT] RETURNS [Pair] = TRUSTED MACHINE CODE BEGIN PrincOps.zEXCH; END; TCPChecksum: PROC [data: ArpaIP.Buffers] RETURNS [checksum: ArpaTCP.DByte]; ChecksumsMatch: PROC [c1, c2: ArpaTCP.DByte] RETURNS [BOOL]; SetTimeout: PROC [delta: INT, base: BasicTime.Pulses _ BasicTime.GetClockPulses[]] RETURNS [BasicTime.Pulses]; TimedOut: PROC [timeoutTime: BasicTime.Pulses] RETURNS [BOOL]; END. πArpaTCPOps.mesa Copyright (C) 1983, 1985 by Xerox Corporation. All rights reserved. The following program was created in 1983 but has not been published within the meaning of the copyright law, is furnished under license, and may not be used, copied and/or disclosed except in accordance with the terms of said license. Last Edited by: Nichols, September 1, 1983 4:27 pm Last Edited by: Taft, January 3, 1984 9:45 am Last Edited by: HGM, March 23, 1984 10:01:40 am PST Doug Terry, November 20, 1987 11:43:19 am PST Hal Murray July 16, 1985 4:39:19 pm PDT John Larson, April 14, 1986 11:18:30 pm PST Constants and types The layout of the TCP header in a datagram. One gets a TCPHeaderP by saying LOOPHOLE[@datagram.data]. The information about a TCP connection. Send state: Receive state: Random: These describe packets that have been received from the net. And these describe packets that have been sent once, but may need to be retransmitted. Statistics Routines used by TCPMain Attempts to open a new TCP connection. Returns a TCPHandle to use or raises ArpaTCP.Error. Shut down the connection normally. Shut down the connection abnormally. Wait until the listening connection on this socket is open. The current datagram in the handle is ready to send. Push is true if the TCP push option should be used. Empty datagrams are ignored unless push is true. We are through with the current input datagram and would like another. Only returns when new datagram has usable data. The urgent pointer is set to the current position in the output stream. Wait asynchronously for urgent data indication. Routines internal to the TCP stuff The following two procedures swap the halves of a long int for the encapsulation. Stolen from the pup software. Find the checksum to be used in the TCP header. Call when data.dataLength is the correct length of the packet. True if c1 and c2 are the same checksum, i.e. they are equal or are both one's complement representations of zero. Returns a timeout time computed by adding delta milliseconds to the specified base time. If delta is negative, meaning "never time out", returns zero, which is specifically defined (in TimedOut) to mean "never time out" and is never otherwise returned. Returns true if the specified time has been reached. ΚΪ– "cedar" style˜head™Icode2šœ―™―Icodešœ2™2Jšœ-™-Jšœ3™3M™-Jšœ'™'M™+šΟk ˜ Lšœœ ˜Lšœœ˜Lšœœ˜Lšœœ ˜-Lšœ œ˜)Lšœ œ ˜——šΟn œœ ˜Lšœ ˜Lšœ˜—™Lšœœ ΟcP˜qLšœœŸP˜gLšœœ ˜Lšœœ˜Lšœœ˜+LšœœŸ˜3LšœœŸ3˜PLšœœŸ:˜NLšœœ Ÿ˜ALšœ˜Lšœ˜Lšœœ˜LšœœŸ5˜JLšœœŸ˜3Lšœœ˜Lšœœo˜„Lš œœœ œœœŸ˜MIbodyšœMœ™fLš œ œœœœ ˜.š œ œœ œœ˜,LšœŸ˜4LšœŸ˜7LšœŸ˜(LšœŸ˜/Lšœœ Ÿ"˜ILšœœ ˜"LšœœœŸ˜8LšœœœŸ˜2LšœœœŸ˜'LšœœœŸ ˜(LšœœœŸ$˜CLšœœœŸ#˜BLšœŸ˜8LšœŸ ˜=Lšœ"Ÿ%˜GLš œœœ œœŸ ˜5—N™'Lšœ œœ˜#šœœ œœ˜'LšœŸ ˜%LšœŸ˜7LšœŸ ˜'LšœœŸ˜4LšœœŸ˜4LšœŸ˜/LšœŸ ˜8LšœœŸ˜'Lšœ œŸ-˜FLšœœŸ&˜;™ LšœœŸ˜.LšœœŸ˜,LšœœŸ˜ LšœœŸ'˜8LšœœŸ'˜8LšœœŸ˜)Lšœ œœŸ%˜>LšœœŸ˜,Lšœ œŸ˜ALšœ œŸ˜ALš œ œœœœŸ˜MLšœœŸ'˜W—™LšœœŸ˜/LšœœŸ˜LšœœŸ˜*Lšœ œœŸ*˜ELšœœŸ#˜1Lšœ œœŸ*˜D—™Lšœ œŸ˜5Lšœ œŸ2˜DLšœ Ÿ,˜LLš œœœœœŸ5˜TLš œœœœœŸ@˜cLšœœŸ˜DLšœ œŸ˜8Lš œ œœœœŸ+˜HLš œ œœœœŸ0˜NLšœ'Ÿ˜DLšœœŸ,˜CLšœœŸ/˜HLšœ œŸ#˜?Lšœ œŸ˜9——N™<šœœœ˜Lšœ œŸ˜$LšœŸ˜;Lšœ œŸ%˜6LšœœŸ˜,LšœŸ˜4LšœœŸ˜%LšœœŸ'˜<—N™Všœœœ˜LšœœŸ$˜8LšœŸ˜L™4—Lšœ˜——…—*Μ