Skip to content

TCP Socket Impl

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

TCP-Socket-Impl

JNode's bridge between java.net.SocketImpl and the native TCP stack, providing lazy stream creation, socket options, and stream closure semantics.

Overview

TCPSocketImpl is the core socket implementation that bridges the standard java.net.SocketImpl API to JNode's native TCP stack. It wraps a TCPControlBlock as the underlying state machine and lazily creates TCPInputStream/TCPOutputStream on first access. The class is instantiated by TCPSocketImplFactory when a Java application creates a Socket or ServerSocket.

Key Components

Class / File Role
net/src/net/org/jnode/net/ipv4/tcp/TCPSocketImpl.java Bridge implementing java.net.SocketImpl, delegating to TCPControlBlock
net/src/net/org/jnode/net/ipv4/tcp/TCPInputStream.java Input stream wrapping TCPControlBlock.appRead(); closing closes the socket
net/src/net/org/jnode/net/ipv4/tcp/TCPOutputStream.java Output stream wrapping TCPControlBlock.appSendData(); closing closes the socket
net/src/net/org/jnode/net/ipv4/tcp/TCPConstants.java TCP flags, connection states (LISTEN, SYN_SENT, ESTABLISHED, etc.), default constants
net/src/net/org/jnode/net/ipv4/tcp/TCPProtocol.java Transport layer entry point that registers TCPSocketImplFactory

How It Works

Initialization and Binding

TCPSocketImpl holds a reference to the shared TCPProtocol instance (passed at construction) and a TCPControlBlock (created lazily on bind() or connect()):

new TCPSocketImpl(TCPProtocol)
  → protocol field set

bind(localAddr, port)
  → controlBlock = protocol.bind(IPv4Address, port)

connect(remoteAddr, port)
  → bind(InetAddress.getLocalHost(), 0) if controlBlock == null
  → controlBlock.appConnect(IPv4Address, port)

Lazy Stream Creation

Streams are created on demand — not in create(boolean stream), which does nothing:

getInputStream()
  → if is == null: is = new TCPInputStream(controlBlock, this)
  → return is

getOutputStream()
  → if os == null: os = new TCPOutputStream(controlBlock, this)
  → return os

This means streams are not available until after connect() or bind()+listen()+accept() has been called.

Stream Closure Semantics

Both TCPInputStream.close() and TCPOutputStream.close() call impl.close(), which shuts down the entire socket:

// TCPSocketImpl.close()
synchronized close() {
    if (is != null) { is.close(); }
    if (os != null) { os.close(); }
    if (controlBlock != null) {
        controlBlock.appClose();
        controlBlock = null;
    }
}

Closing either stream triggers the FIN handshake via controlBlock.appClose(), destroying the controlBlock. Subsequent stream operations will throw IOException: Connect first.

Socket Options

TCPSocketImpl implements getOption() for reading socket options:

Option Source
SO_BINDADDR controlBlock.getLocalAddress().toInetAddress()
SO_RCVBUF controlBlock.getReceiveBufferSize()
SO_SNDBUF controlBlock.getSendBufferSize()
SO_TIMEOUT Always returns 0 (not implemented)

setOption() is stubbed with // TODO Auto-generated method stub — no options can currently be set.

Accept Flow

ServerSocket.accept()
  → TCPSocketImpl.accept(SocketImpl s)
      → impl.controlBlock.appAccept()   // blocks until connection ready
      → s.controlBlock = accepted block

The passed SocketImpl (which is always a TCPSocketImpl) receives the accepted control block.

Gotchas

  • Streams tied to socket lifetime: Once either stream is created, closing the stream closes the socket. Applications that keep both streams open must not close either stream prematurely.
  • controlBlock null before connect: Calling getInputStream() or getOutputStream() before connect() throws IOException: Connect first.
  • create(boolean stream) is a no-op: Unlike platform implementations, TCPSocketImpl.create() does nothing. Resource allocation is deferred to bind().
  • Double-close protection: close() nulls controlBlock after calling appClose(). Subsequent calls are no-ops for each field.
  • setOption not implemented: Attempting to set socket options (e.g., SO_KEEPALIVE, SO_LINGER) has no effect.
  • sendUrgentData stubbed: sendUrgentData() is empty — urgent data is not supported.

Related Pages

  • Sockets-Implementation — Hub page covering the full socket bridge from java.net to native stack
  • TCP-Protocol — TCP state machine, connection lifecycle, reliable data transfer
  • Network-Stack — Hub page for the complete network stack architecture

Clone this wiki locally