-
Notifications
You must be signed in to change notification settings - Fork 0
Sockets Implementation
How JNode bridges the standard
java.netAPI to its native TCP/IP stack.
JNode implements a complete network stack in pure Java because it runs directly on bare hardware without a host OS. The socket implementation layer bridges standard Java networking classes (java.net.Socket, ServerSocket) to JNode's internal TransportLayer state machines. When a Java application calls Socket.connect(), the call flows through a custom SocketImplFactory into TCPControlBlock and eventually sends raw IP packets via the network device driver.
| Class / File | Role |
|---|---|
net/src/net/org/jnode/net/ipv4/tcp/TCPProtocol.java |
Transport layer entry point; registers SocketImplFactory with the JVM |
net/src/net/org/jnode/net/ipv4/tcp/TCPSocketImplFactory.java |
Factory creating TCPSocketImpl instances for Socket/ServerSocket
|
net/src/net/org/jnode/net/ipv4/tcp/TCPSocketImpl.java |
Core bridge: implements java.net.SocketImpl, delegates to TCPControlBlock
|
net/src/net/org/jnode/net/ipv4/tcp/TCPControlBlock.java |
Per-connection state machine; manages TCP state transitions and data flow |
net/src/net/org/jnode/net/ipv4/tcp/TCPInChannel.java |
Manages incoming data buffering, sequence numbers, out-of-order segments |
net/src/net/org/jnode/net/ipv4/tcp/TCPOutChannel.java |
Manages outgoing data buffering, retransmission, ACK processing |
net/src/net/org/jnode/net/ipv4/tcp/TCPInputStream.java |
Wraps TCPControlBlock.appRead() as java.io.InputStream
|
net/src/net/org/jnode/net/ipv4/tcp/TCPOutputStream.java |
Wraps TCPControlBlock.appSendData() as java.io.OutputStream
|
net/src/net/org/jnode/net/ipv4/tcp/TCPConstants.java |
TCP flags, connection states (LISTEN, SYN_SENT, ESTABLISHED, etc.) |
At initialization, TCPProtocol creates a TCPSocketImplFactory and registers it with the JVM via Socket.setSocketImplFactory() and ServerSocket.setSocketFactory(). From this point on, any new Socket() or new ServerSocket() will produce a TCPSocketImpl instead of the platform default.
TCPProtocol.<init>
→ new TCPSocketImplFactory(this)
→ Socket.setSocketImplFactory(factory) // privileged
→ ServerSocket.setSocketFactory(factory)
Client side (connect()):
Socket.connect(host, port)
→ TCPSocketImpl.connect(InetAddress, port)
→ controlBlock.appConnect(IPv4Address, port)
→ sendSYN() → state = SYN_SENT
→ waitUntilState(ESTABLISHED, timeout)
Server side (accept()):
ServerSocket.accept()
→ TCPSocketImpl.accept(SocketImpl)
→ controlBlock.appAccept()
→ wait for readyToAcceptList notification
→ return accepted TCPSocketImpl
TCPControlBlock implements the full TCP state machine (defined in TCPConstants):
CLOSED → LISTEN (appListen) → SYN_RECV (SYN received) → ESTABLISHED (ACK received)
CLOSED → SYN_SENT (SYN sent) → ESTABLISHED (ACK+SYN received)
ESTABLISHED → FIN_WAIT_1 → FIN_WAIT_2 → TIME_WAIT → CLOSED
ESTABLISHED → CLOSE_WAIT → LAST_ACK → CLOSED
Each receive() call dispatches based on curState to the appropriate handler method (e.g., receiveEstablished(), receiveFinWait1()).
Sending (OutputStream.write()):
TCPOutputStream.write(buf, off, len)
→ controlBlock.appSendData(buf, off, len)
→ chunks data into MSS-sized segments
→ TCPOutChannel.send() → TCPOutSegment → TCPProtocol.send() → IPv4Service.transmit()
Receiving (InputStream.read()):
TCPInputStream.read(buf, off, len)
→ controlBlock.appRead(buf, off, len)
→ TCPInChannel.read() blocks until data available
→ dataBuffer.getData() copied to user buffer
TCPInputStream and TCPOutputStream wrap the control block's appRead()/appSendData() methods. Closing either stream triggers impl.close(), which calls controlBlock.appClose() initiating the FIN handshake.
-
SYN retransmission: On connection failure,
appConnect()retries up toTCP_MAXCONNECT(3) times with the default 10-secondTCP_DEFAULT_TIMEOUTper attempt. -
Out-of-order segments:
TCPInChannelbuffers out-of-order segments infutureSegments(aLinkedList<TCPInSegment>) and processes them only when the expected sequence number arrives. -
FIN_WAIT_2 timeout: In
FIN_WAIT_2state, the implementation blocks for a hardcoded 400ms before transitioning toTIME_WAIT, rather than using the full 2MSL timeout. -
Port unreachable: When a segment arrives for an unbound port,
TCPProtocol.processPortUnreachable()sends a RST+ACK rather than just dropping the packet. -
Privileged registration: The
SocketImplFactoryregistration must run insideAccessController.doPrivileged()becauseSocket.setSocketImplFactory()requires security permission.
- Network-Stack — Hub page for the complete network stack architecture
- NetAPI-Implementation — Application network API for device enumeration, address resolution, DNS
- TCP-Socket-Impl — Core bridge class, lazy streams, socket options
- Driver-Framework — How network device drivers integrate with the stack