<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. |