-
Notifications
You must be signed in to change notification settings - Fork 0
UDP Datagram Socket
JNode's bridge between
java.net.DatagramSocketand the native UDP stack, providing connectionless datagram send/receive with socket options and port bindings.
UDPDatagramSocketImpl is the core socket implementation that bridges the standard java.net.DatagramSocket API to JNode's native UDP stack. It extends AbstractDatagramSocketImpl which provides the receive queue, socket options (TOS, broadcast, timeout, interface), and device binding. The class delegates to UDPProtocol for port binding, checksum computation, and packet transmission.
Two concrete implementations exist: UDPDatagramSocketImpl (direct) and PlainUDPDatagramSocketImpl (wrapping via GNU Classpath primitives). Both are created by UDPDatagramSocketImplFactory when a Java application creates a DatagramSocket.
| Class / File | Role |
|---|---|
net/src/net/org/jnode/net/ipv4/udp/UDPDatagramSocketImpl.java |
Primary socket implementation extending AbstractDatagramSocketImpl
|
net/src/net/org/jnode/net/ipv4/udp/PlainUDPDatagramSocketImpl.java |
GNU Classpath-compatible wrapper using inner class pattern |
net/src/net/org/jnode/net/ipv4/udp/UDPDatagramSocketImplFactory.java |
Factory creating socket instances for the Java socket layer |
net/src/net/org/jnode/net/ipv4/udp/UDPControlBlock.java |
Per-socket control/blocking state extending IPv4ControlBlock
|
net/src/net/util/AbstractDatagramSocketImpl.java |
Base class with receive queue, socket options, device binding |
net/src/net/org/jnode/net/ipv4/udp/UDPProtocol.java |
Central coordinator managing port bindings and packet delivery |
java.net.DatagramSocketImpl (JDK)
└── AbstractDatagramSocketImpl (JNode) // receiveQueue, socket options, device
└── UDPDatagramSocketImpl // doBind/doClose/send/onReceive
└── PlainUDPDatagramSocketImpl$MyUDPDatagramSocketImpl // inner subclass
AbstractDatagramSocketImpl provides: receive queue (Queue<SocketBuffer>), socket options (TOS, broadcast, timeout, bind address, interface), device binding, and the synchronized receive() method that dequeues from the receive queue.
UDPDatagramSocketImpl.doBind() delegates directly to UDPProtocol.bind(), which registers the socket in its HashMap<Integer, UDPDatagramSocketImpl> keyed by local port:
// UDPDatagramSocketImpl.java:58-60
protected void doBind(int lport, InetAddress laddr) throws SocketException {
protocol.bind(this);
}When DatagramSocket binds to port 0, UDPProtocol.bind() randomly selects an ephemeral port from 1024–65535 and calls socket.setLocalPort() to update the socket's port field.
UDPDatagramSocketImpl.send() constructs the IP and UDP headers and delegates to protocol.send():
// UDPDatagramSocketImpl.java:91-108
protected void send(DatagramPacket p) throws IOException {
final IPv4Address dstAddress = new IPv4Address(p.getAddress());
final IPv4Header ipHdr;
ipHdr = new IPv4Header(getTos(), getTimeToLive(), IPPROTO_UDP, dstAddress,
p.getLength() + UDP_HLEN);
if (!getLocalAddress().isAnyLocalAddress() || (getDevice() != null)) {
ipHdr.setSource(new IPv4Address(getLocalAddress()));
}
final UDPHeader udpHdr;
final int srcPort = getLocalPort();
udpHdr = new UDPHeader(srcPort, p.getPort(), p.getLength());
final SocketBuffer skbuf = new SocketBuffer(p.getData(), p.getOffset(), p.getLength());
skbuf.setDevice(getDevice());
protocol.send(ipHdr, udpHdr, skbuf);
}Key behaviors:
- Source address is set to
getLocalAddress()unless it is "any local address" AND no device is bound — in that case the IP layer determines the source. - TTL and TOS are read from socket options via
getTimeToLive()andgetTos(). - The device is attached to the
SocketBufferso the link layer knows which NIC to transmit on.
protocol.send() prefixes the UDP header (8 bytes) and passes to IPv4Service.transmit(). The UDP checksum is computed in UDPHeader.finalizeHeader() using a pseudo-header over the IP addresses.
When a datagram arrives, UDPProtocol.receive() parses the UDPHeader, validates the checksum, and calls deliver(). deliver() looks up the destination port in the socket map and calls socket.deliverReceived(skbuf), which queues the SocketBuffer in AbstractDatagramSocketImpl.receiveQueue:
// AbstractDatagramSocketImpl.java:268-275
public final boolean deliverReceived(SocketBuffer skbuf) {
if (!closed) {
receiveQueue.add(skbuf);
return true;
} else {
return false;
}
}AbstractDatagramSocketImpl.receive() dequeues from this queue with optional timeout:
// AbstractDatagramSocketImpl.java:245-259
protected final void receive(DatagramPacket p) throws IOException {
if (closed) throw new SocketException("DatagramSocket has been closed");
final SocketBuffer skbuf = (SocketBuffer) receiveQueue.get(timeout);
if (skbuf == null) {
if (closed) throw new SocketException("DatagramSocket has been closed");
else throw new SocketTimeoutException("Timeout in receive");
} else {
onReceive(p, skbuf);
}
}UDPDatagramSocketImpl.onReceive() extracts the data and addressing from the SocketBuffer:
// UDPDatagramSocketImpl.java:80-86
protected void onReceive(DatagramPacket p, SocketBuffer skbuf) throws IOException {
final IPv4Header ipHdr = (IPv4Header) skbuf.getNetworkLayerHeader();
final UDPHeader udpHdr = (UDPHeader) skbuf.getTransportLayerHeader();
p.setData(skbuf.toByteArray(), 0, skbuf.getSize());
p.setAddress(ipHdr.getSource().toInetAddress());
p.setPort(udpHdr.getSrcPort());
}During UDPProtocol construction, the factory is registered with the JDK:
// UDPProtocol.java:100-108
dsiFactory = new UDPDatagramSocketImplFactory(this);
AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
public Object run() throws IOException {
DatagramSocket.setDatagramSocketImplFactory(dsiFactory);
PlainDatagramSocketImpl.setUDPFactory(dsiFactory);
return null;
}
});This ensures all DatagramSocket instances in JNode use JNode's UDP implementation instead of a host-JDK fallback.
AbstractDatagramSocketImpl provides:
| Option | Type | Behavior |
|---|---|---|
IP_TOS |
int | Type of Service field in outgoing IP header |
SO_BROADCAST |
boolean | Allow sending to broadcast addresses (default: true) |
SO_BINDADDR |
InetAddress | Local bind address (read-only) |
SO_TIMEOUT |
int | Receive timeout in milliseconds (0 = infinite) |
SO_TRANSMIT_IF |
NetworkInterface | Outgoing network interface/device |
SO_RCVBUF |
int | Returns ETH_FRAME_LEN (stub) |
SO_SNDBUF |
int | Returns ETH_FRAME_LEN (stub) |
TTL is managed separately via getTimeToLive()/setTimeToLive().
UDPDatagramSocketImpl.doClose() calls protocol.unbind() which removes the socket from the port map. AbstractDatagramSocketImpl.close() sets closed = true and closes the receive queue.
-
Connectionless by design: Unlike
TCPSocketImpl,UDPDatagramSocketImplhas no connection state. There is noconnect()call that creates session state —connect()on a UDP socket only sets the default destination. -
Data copy on receive:
onReceive()callsskbuf.toByteArray()which copies the payload into a new byte array for theDatagramPacket. This is unavoidable sinceDatagramPacket.datais a fixedbyte[]. -
TTL/TOS stubs:
getTTL()andsetTTL(byte)inUDPDatagramSocketImplare empty stubs — they read/write thettlfield (fromAbstractDatagramSocketImpl) butsend()reads viagetTimeToLive()which returns theintfield. -
No multicast support:
join()/leave()/joinGroup()/leaveGroup()are all stubs inAbstractDatagramSocketImpl. Multicast is not implemented. -
PlainUDPDatagramSocketImpl debug output: Contains
System.out.printlncalls for "udp:" and "packet:" which should be removed or replaced with proper logging. -
Source port comment: A TODO in
send()notes uncertainty about whethersrcPortshould come from the socket's local port or the packet's port — the current code usesgetLocalPort(). -
Receive queue is unbounded: The
Queue<SocketBuffer>has no capacity limit. A flood of incoming datagrams could exhaust memory. Applications expecting high traffic should usesetOption(SO_TIMEOUT, ...)to prevent unbounded blocking onreceive().
- UDP-Protocol — The underlying UDP transport protocol, header format, checksum calculation, port management
-
Sockets-Implementation — Hub page bridging
java.netAPI to the native network stack - Network-Stack — Hub page for JNode's complete network architecture
- Network-Layers — SocketBuffer pipeline, protocol layering model