TCPOps.mesa
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
Hal Murray July 16, 1985 4:39:19 pm PDT
John Larson, April 14, 1986 11:18:30 pm PST
DIRECTORY
BasicTime USING [GetClockPulses, Pulses],
IPDefs USING [Byte, Datagram, DByte, Address, maxDataLength],
PrincOps USING [zEXCH],
TCP USING [Reason, TCPInfo];
Constants and types
sendBufferLength: INT ~ 4000; -- 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 ~ IPDefs.maxDataLength - tcpHdrByteLength;
ourLocalAddress: IPDefs.Address;
defaultReceiveWindow: INT;
repacketizing: BOOL; -- TRUE if data to be repacketized when retransmitted
tcpSegmentLife: INT ~ 60; -- value for time to live
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
The layout of the TCP header in a datagram. One gets a TCPHeaderP by saying LOOPHOLE[@datagram.data].
TCPHeaderP: TYPE = LONG POINTER TO TCPHeader;
TCPHeader:
TYPE =
MACHINE
DEPENDENT
RECORD [
sourcePort (0): IPDefs.DByte, -- source port number
dstnPort (1): IPDefs.DByte, -- 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): IPDefs.DByte, -- window of packets to send
checksum (8): IPDefs.DByte, -- for header and pseudo header
urgentPtr (9): IPDefs.DByte ← 0, -- ptr to byte following urgent data
options (10): ARRAY INT [1..40] OF IPDefs.Byte]; -- options
The information about a TCP connection.
TCPHandle: TYPE ~ REF TCPHandleRec;
TCPHandleRec:
TYPE ~
MONITORED
RECORD [
localPort: IPDefs.DByte, -- TCP port
foreignAddr: IPDefs.Address, -- internet foreign address
foreignPort: IPDefs.DByte, -- TCP port
matchForeignAddr: BOOL, -- true to use foreign addr
matchForeignPort: BOOL, -- true to use foreign port
state: ConnectionState, -- state of connection
reason: TCP.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
Send state:
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..sendBufferLength) ← 0, -- for repacketizing
sendSlot: INT [0..sendBufferLength) ← 0, -- for repacketizing
sendBuffer: ARRAY INT [0..sendBufferLength) OF IPDefs.Byte, -- for repacketizing
nBytesToSend: INT [0..sendBufferLength] ← 0, -- number of filled slots in sendBuffer
Receive state:
rcvNxt: INT ← 0, -- next seq number to receive
rcvWnd: INT, -- receive window
rcvUp: INT ← 0, -- receive urgent pointer
irs: INT ← 0, -- initial receive sequence number
urgentMode: BOOL ← FALSE, -- rcvd urgent data and not passed to user
Random:
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 (IPDefs.Datagrams)
rexmitQueue: LIST OF REF ANY, -- packets to retransmit to net (TCPSendBuffers)
currentOutputDatagram: IPDefs.Datagram, -- 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
These describe packets that have been received from the net.
TCPRcvBuffer:
TYPE ~
RECORD [
offsetSeqNo: INT, -- for use by TCP
datagramPtr: IPDefs.Datagram, -- 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
And these describe packets that have been sent once, but may need to be retransmitted.
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: IPDefs.Datagram]; -- datagram sent to net
TCPControlSet:
TYPE ~
RECORD [
urg, ack, psh, rst, syn, fin: BOOL ← FALSE];
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.
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: IPDefs.Datagram]
RETURNS [checksum: IPDefs.DByte];
Find the checksum to be used in the TCP header. Call when data.dataLength is the correct length of the packet.
ChecksumsMatch:
PROC [c1, c2: IPDefs.DByte]
RETURNS [
BOOL];
True if c1 and c2 are the same checksum, i.e. they are equal or are both one's complement representations of zero.
SetTimeout:
PROC [delta:
INT, base: BasicTime.Pulses ← BasicTime.GetClockPulses[]]
RETURNS [BasicTime.Pulses];
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.
TimedOut:
PROC [timeoutTime: BasicTime.Pulses]
RETURNS [
BOOL];
Returns true if the specified time has been reached.
END.