Skip to content

<net/socket.h>

Sockets: TCP and UDP through netd, over shared-memory rings.

Each app attaches to netd once, lazily on its first SockOpen(). Every socket is a memory object shared with netd that holds a SockShm header and one ring per direction; data never goes through IPC. The app rings netd's doorbell event after writing or reading, and netd signals the app's event when a socket changes. netd notices the app's death through a port the app owns.

Socket numbers are small integers local to the app, not handles.

#include <net/socket.h>

Constants

Name Value Description
SOCK_RING_SIZE 8192u Bytes in each ring, per direction; a power of two.
SOCK_CMD_BASE 0x100u First socket command number. netd's service port also speaks the one-byte NetdOpcode protocol, so socket commands live above it.
SOCK_IS_CMD(c) Tells whether a command number is a socket command.
SOCK_ATTACH (SOCK_CMD_BASE + 1) Attach an app to netd. SockAttachRequest; grants the app's liveness port (PERM_WAIT | PERM_TXFR). Replies SockAttachReply and grants netd's doorbell.
SOCK_NOTIFY (SOCK_CMD_BASE + 2) Give netd the app's event. SockNotifyRequest; grants the event.
SOCK_OPEN (SOCK_CMD_BASE + 3) Open a socket. SockOpenRequest; grants its memory object. Replies SockOpenReply.
SOCK_BIND (SOCK_CMD_BASE + 4) Bind a socket to a local port. SockRequest {sock, port}; port 0 picks an ephemeral one.
SOCK_LISTEN (SOCK_CMD_BASE + 5) Listen on a port. SockRequest {sock, port, backlog}; TCP only.
SOCK_CONNECT (SOCK_CMD_BASE + 6) Connect to a peer. SockRequest {sock, ip, port}; completes asynchronously.
SOCK_ACCEPT (SOCK_CMD_BASE + 7) Take a pending connection. SockRequest {sock}; grants the new socket's memory object. Replies SockOpenReply, or fails with ERR_BUFEMPTY if none is pending.
SOCK_CLOSE (SOCK_CMD_BASE + 9) Close a socket. SockRequest {sock}.
SOCK_F_EOF (1u << 0) SockShm::flags: the peer closed; the rx ring holds the last bytes.
SOCK_F_TX_KICK (1u << 1) SockShm::flags: netd drained tx and wants a doorbell on the next write.
SOCK_F_RX_KICK (1u << 2) SockShm::flags: rx was full; netd wants a doorbell after the app reads.
SOCK_HDR_BYTES 256u Bytes reserved for SockShm before the rings.
SOCK_MEM_BYTES (SOCK_HDR_BYTES + (2u * SOCK_RING_SIZE)) Size of a socket's shared memory: header, tx ring, rx ring.
SOCK_MEM_PAGES ((SOCK_MEM_BYTES + 4095u) / 4096u) Pages in a socket's memory object.
SOCK_DGRAM_MAX 1472u Largest UDP payload: a 1500-byte MTU minus IP and UDP headers.

Enumerations

SockType

Socket kind.

Name Value Description
SOCK_KIND_TCP 1 Stream socket.
SOCK_KIND_UDP 2 Datagram socket.

SockState

Socket state, as netd publishes it in SockShm::state.

Name Value Description
SOCK_STATE_OPEN 0 Created, not bound or connected.
SOCK_STATE_BOUND 1 Bound to a local port.
SOCK_STATE_LISTENING 2 Accepting connections.
SOCK_STATE_CONNECTING 3 Connect in progress.
SOCK_STATE_ESTABLISHED 4 Connected.
SOCK_STATE_CLOSED 5 Finished; SockShm::error says why, ZUZU_OK for an orderly end.

Structures

SockShm

Header at the start of a socket's shared memory.

Field Type Description
tx ShmRingHdr App produces, netd consumes.
rx ShmRingHdr netd produces, app consumes.
state volatile uint32_t A SockState.
error volatile int32_t Why the socket closed, once state is SOCK_STATE_CLOSED.
flags volatile uint32_t SOCK_F_* bits.
rx_dropped volatile uint32_t UDP datagrams dropped on a full rx ring.
accept_pending volatile uint32_t Connections waiting for SockAccept() on a listener.
local_ip uint32_t Local address.
remote_ip uint32_t Peer address, once connected.
local_port uint16_t Local port.
remote_port uint16_t Peer port, once connected.

SockDgramHdr

Record header in a UDP ring; len payload bytes follow, padded to 4 bytes.

Field Type Description
peer_ip uint32_t Sender (rx) or destination (tx) address.
peer_port uint16_t Sender or destination port.
len uint16_t Payload length.

SockAttachRequest

SOCK_ATTACH request.

Field Type Description
cmd uint32_t SOCK_ATTACH.

SockAttachReply

SOCK_ATTACH reply.

Field Type Description
status Err ZUZU_OK, or why attaching failed.
session uint32_t Session id for later requests.
bit uint32_t Bit to ring on netd's doorbell.

SockNotifyRequest

SOCK_NOTIFY request.

Field Type Description
cmd uint32_t SOCK_NOTIFY.
session uint32_t Session from SockAttachReply.
bit uint32_t Bit netd rings on the app's event.

SockOpenRequest

SOCK_OPEN request.

Field Type Description
cmd uint32_t SOCK_OPEN.
session uint32_t Session from SockAttachReply.
kind uint32_t A SockType.

SockOpenReply

SOCK_OPEN and SOCK_ACCEPT reply.

Field Type Description
status Err ZUZU_OK, or why it failed.
sock uint32_t netd's id for the socket.

SockRequest

Request for the commands that act on an open socket.

Field Type Description
cmd uint32_t SOCK_BIND, SOCK_LISTEN, SOCK_CONNECT, SOCK_ACCEPT or SOCK_CLOSE.
session uint32_t Session from SockAttachReply.
sock uint32_t netd's socket id.
a uint32_t First argument: port (bind, listen) or IP address (connect).
b uint32_t Second argument: backlog (listen) or port (connect).

Functions

SockOpen

int SockOpen(SockType kind);

Opens a socket, attaching to netd first if this is the app's first one.

Parameter Direction Description
kind in SOCK_KIND_TCP or SOCK_KIND_UDP.

Returns: The socket number, or a negative error code.

Error Condition
ERR_SYSDOWN /svc/netd is not registered.
ERR_NOMEM Out of memory or handles.

SockBind

Err SockBind(int sock, uint16_t port);

Binds a socket to a local port.

Parameter Direction Description
sock in Socket number.
port in Local port, or 0 for an ephemeral one.

Returns: ZUZU_OK, or an error code.

Error Condition
ERR_BADARG sock is not an open socket.

SockSendTo

Err SockSendTo(int sock, uint32_t ip, uint16_t port, const void *buf, uint16_t len);

Queues one UDP datagram and rings netd.

Does not block.

Parameter Direction Description
sock in Socket number.
ip in Destination address.
port in Destination port.
buf in Payload.
len in Payload length, at most SOCK_DGRAM_MAX.

Returns: ZUZU_OK, or an error code.

Error Condition
ERR_BADARG sock is not an open socket.
ERR_OVERFLOW len is larger than SOCK_DGRAM_MAX.
ERR_NOTCONN The socket is closed.
ERR_BUFFULL The tx ring has no room; try again later.

SockRecvFrom

int SockRecvFrom(int sock, void *buf, uint16_t cap, uint32_t *ip, uint16_t *port, Duration timeout);

Receives one UDP datagram.

A datagram longer than cap is truncated and the rest discarded. While nothing has arrived it waits for socket activity; each wait may last up to timeout.

Parameter Direction Description
sock in Socket number.
buf out Payload.
cap in Size of buf.
ip out Sender address; may be NULL.
port out Sender port; may be NULL.
timeout in Milliseconds, TIMEOUT_POLL or TIMEOUT_INFINITE.

Returns: Bytes copied into buf, or a negative error code.

Error Condition
ERR_BADARG sock is not an open socket.
ERR_NOTCONN The socket is closed.
ERR_TIMEOUT Nothing arrived in time.
ERR_MALFORMED The rx ring was corrupt; it has been emptied.

SockClose

Err SockClose(int sock);

Closes a socket and releases its shared memory, even if netd reports an error.

Parameter Direction Description
sock in Socket number.

Returns: netd's answer to the close.

Error Condition
ERR_BADARG sock is not an open socket.

SockConnect

Err SockConnect(int sock, uint32_t ip, uint16_t port, Duration timeout);

Connects a TCP socket and waits until it is established or fails.

Parameter Direction Description
sock in Socket number.
ip in Peer address.
port in Peer port.
timeout in Limit on each wait for progress: milliseconds, TIMEOUT_POLL or TIMEOUT_INFINITE.

Returns: ZUZU_OK once established, or an error code.

Error Condition
ERR_BADARG sock is not an open socket.
ERR_TIMEOUT Still connecting.
ERR_NOTCONN The connection failed without a more specific error.

SockListen

Err SockListen(int sock, uint16_t port, int backlog);

Makes a TCP socket accept connections on a port.

Parameter Direction Description
sock in Socket number.
port in Local port.
backlog in Connections netd queues before refusing more.

Returns: ZUZU_OK, or an error code.

Error Condition
ERR_BADARG sock is not an open socket.

SockAccept

int SockAccept(int sock, Duration timeout);

Takes the next connection from a listening socket.

Parameter Direction Description
sock in Listening socket number.
timeout in Limit on each wait for a connection: milliseconds, TIMEOUT_POLL or TIMEOUT_INFINITE.

Returns: The new connection's socket number, or a negative error code.

Error Condition
ERR_BADARG sock is not an open socket.
ERR_TIMEOUT No connection arrived in time.
ERR_NOMEM Out of memory or handles.

SockSend

int SockSend(int sock, const void *buf, uint32_t len);

Writes all of buf to a TCP socket, blocking while the tx ring is full.

Parameter Direction Description
sock in Socket number.
buf in Data.
len in Bytes to send.

Returns: len, or a negative error code.

Error Condition
ERR_BADARG sock is not an open socket.
ERR_NOTCONN The socket closed without a more specific error.

SockRecv

int SockRecv(int sock, void *buf, uint32_t cap, Duration timeout);

Reads whatever a TCP socket has, up to cap bytes, waiting if it has nothing.

Parameter Direction Description
sock in Socket number.
buf out Data.
cap in Size of buf.
timeout in Limit on each wait for data: milliseconds, TIMEOUT_POLL or TIMEOUT_INFINITE.

Returns: Bytes read, 0 at end of stream, or a negative error code.

Error Condition
ERR_BADARG sock is not an open socket.
ERR_TIMEOUT No data arrived in time.

SockWait

Err SockWait(Duration timeout);

Waits until netd signals activity on any of the app's sockets.

Parameter Direction Description
timeout in Milliseconds, TIMEOUT_POLL or TIMEOUT_INFINITE.

Returns: ZUZU_OK, or an error code.

Error Condition
ERR_NOTCONN No socket has been opened yet.
ERR_TIMEOUT Nothing happened in time.