Skip to content

TCP Protocol

opencode-agent[bot] edited this page May 10, 2026 · 1 revision

TCP Protocol

TCP (Transmission Control Protocol) with full state machine implementation.

Overview

TCP provides reliable, ordered, error-checked delivery of data between processes on different hosts in JNode's network stack. It is a connection-oriented protocol built on top of IP, implementing a complex state machine to manage connection lifecycle, flow control, and reliable data transfer. JNode's TCP implementation follows RFC 793 closely, with support for the standard TCP states: CLOSED, LISTEN, SYN_SENT, SYN_RECV, ESTABLISHED, FIN_WAIT_1, FIN_WAIT_2, CLOSING, TIME_WAIT, CLOSE_WAIT, and LAST_ACK.

The TCP layer sits above the IPv4 layer and below the socket abstraction. When a segment arrives, TCPProtocol receives it, validates the checksum, looks up the corresponding TCPControlBlock (or creates one for a listening socket), and processes the segment according to the current connection state. The implementation uses TCPTimer for retransmission and timeout handling, and maintains separate TCPInChannel and TCPOutChannel objects for each connection to handle data flow.

Key Components

Class / File Role
net/src/net/org/jnode/net/ipv4/tcp/TCPProtocol.java Main TCP protocol handler; implements IPv4Protocol interface; manages control blocks, timers, and socket factory
net/src/net/org/jnode/net/ipv4/tcp/TCPHeader.java TCP header parsing and construction; handles flags (SYN, ACK, FIN, RST, PSH, URG), sequence/ack numbers, window size
net/src/net/org/jnode/net/ipv4/tcp/TCPControlBlock.java Connection state machine; manages per-connection state, receive/send channels, timeouts
net/src/net/org/jnode/net/ipv4/tcp/TCPConstants.java TCP constants: flags, state values, timeouts, buffer sizes
net/src/net/org/jnode/net/ipv4/tcp/TCPInChannel.java Incoming data handling; sequence number validation, reassembly, receive buffer
net/src/net/org/jnode/net/ipv4/tcp/TCPOutChannel.java Outgoing data handling; segment transmission, retransmission, acknowledgment processing
net/src/net/org/jnode/net/ipv4/tcp/TCPTimer.java Timer for retransmission timeouts, keep-alive, and connection state transitions
net/src/net/org/jnode/net/ipv4/tcp/TCPSocketImpl.java Bridge between java.net.Socket API and TCPControlBlock

How It Works

Connection Establishment

TCP connections are established via a three-way handshake:

  1. Client sends SYN: Client calls appConnect(), which sends a SYN segment with an initial sequence number (ISN) from TCPOutChannel, transitioning state to SYN_SENT
  2. Server responds with SYN-ACK: Server's listening TCPControlBlock receives SYN, creates a child connection, sends SYN-ACK, and transitions to SYN_RECV
  3. Client sends ACK: Client receives SYN-ACK, transitions to ESTABLISHED; server receives ACK and also transitions to ESTABLISHED

In JNode, this is implemented in TCPControlBlock:

  • Active open: appConnect() sends SYN and waits for ESTABLISHED state (with TCP_MAXCONNECT retries)
  • Passive open: appListen() sets state to LISTEN; receiveListen() creates child control blocks on SYN receipt

Data Transfer

Once ESTABLISHED, data flows bidirectionally:

  • appSendData() breaks data into chunks (up to MSS), creates TCP headers with current sequence/ack numbers, and sends via TCPOutChannel
  • appRead() reads from TCPInChannel receive buffer, blocking until data is available
  • Each segment carries a sequence number; received data is acknowledged via ACK segments
  • Flow control uses the window size field: receiver advertises available buffer space

Connection Teardown

Connection closure uses a four-way handshake:

  1. Active closer sends FIN: appClose() sends FIN, transitions to FIN_WAIT_1 (or LAST_ACK if in CLOSE_WAIT)
  2. Peer acknowledges FIN: Peer sends ACK; active closer transitions to FIN_WAIT_2
  3. Peer sends FIN: After its application closes, peer sends FIN
  4. Active closer acknowledges FIN: Sends final ACK, transitions to TIME_WAIT for 2MSL (2 * Maximum Segment Lifetime), then to CLOSED

In JNode, receiveEstablished(), receiveFinWait1(), receiveFinWait2() handle incoming FIN segments and state transitions. The TIME_WAIT state waits 400ms (simulating 2MSL) before closing.

Header Structure

TCPHeader parses the 20-byte (minimum) TCP header from SocketBuffer:

  • Source/destination ports (16-bit each)
  • Sequence and acknowledgment numbers (32-bit each)
  • Flags: URG, ACK, PSH, RST, SYN, FIN (6 bits)
  • Window size (16-bit): flow control advertisement
  • Checksum (16-bit): covers pseudo-header + TCP header + data
  • Urgent pointer (16-bit)

The checksum uses a pseudo-header derived from the IPv4 header (source/destination addresses, protocol, TCP length).

Gotchas & Non-Obvious Behavior

  • State machine complexity: The 11 TCP states and their transitions are complex; incorrect segment handling can leave connections in inconsistent states. JNode handles most RFC 793 cases but some edge cases may behave unexpectedly.

  • Retransmission timing: TCPTimer runs every 500ms (TCP_TIMER_PERIOD); retransmission timeout is critical for performance. Too aggressive retransmission causes unnecessary traffic; too conservative causes delays.

  • Window size: Default TCP_MAXWIN is 1024 bytes, which is quite small compared to modern networks. This limits throughput on high-bandwidth connections.

  • No congestion control: The current implementation does not implement sophisticated congestion control (slow start, congestion avoidance). It uses a simple retransmission model without CWND management.

  • Maximum Segment Size: Default TCP_DEFAULT_MSS is 536 bytes, limiting single-send chunk sizes. Actual MSS may be limited by underlying network MTU.

  • Checksum validation: TCPHeader validates the checksum on receive; invalid segments are dropped and stat.badsum incremented. The checksum uses IPv4 pseudo-header.

  • Reset handling: RST segments can arrive at any time; receiveProcessReset() handles state-specific responses (notifying connection refused/reset to waiting threads).

  • Blocking operations: appConnect(), appAccept(), appRead(), appSendData() can block; timeout is TCP_DEFAULT_TIMEOUT (10 seconds).

Related Pages

Clone this wiki locally