xtc_net(3)

---

xtc_net(3)

networking helpers

XTC_NET(3) Library Functions Manual XTC_NET(3)

xtc_net_listen, xtc_net_dial, xtc_net_apply_tcp_opts, xtc_net_setnonblock, xtc_net_close, xtc_net_unix_listen, xtc_net_unix_dial, xtc_net_unix_send_creds, xtc_net_unix_recv_creds, xtc_net_send_frame, xtc_net_recv_frame, xtc_net_udp_socket, xtc_net_udp_sendto, xtc_net_udp_recvfrom, xtc_dns_resolvenetworking helpers

#include <xtc.h>
#include <xtc_net.h>

int
xtc_net_listen(xtc_net_family_t fam, const char *host, int port, const xtc_tcp_opts_t *opts, int *out_fd);

int
xtc_net_dial(xtc_net_family_t fam, const char *host, int port, const xtc_tcp_opts_t *opts, int *out_fd);

int
xtc_net_apply_tcp_opts(int fd, const xtc_tcp_opts_t *opts);

int
xtc_net_setnonblock(int fd);

void
xtc_net_close(int fd);

int
xtc_net_unix_listen(const char *path, int *out_fd);

int
xtc_net_unix_dial(const char *path, int *out_fd);

int
xtc_net_unix_send_creds(int fd, const void *buf, size_t buflen);

int
xtc_net_unix_recv_creds(int fd, void *buf, size_t buflen, uint32_t *out_uid, uint32_t *out_gid, size_t *out_n);

int
xtc_net_send_frame(int fd, const void *buf, size_t len);

int
xtc_net_recv_frame(int fd, void **out, size_t *out_len, size_t max_len, int64_t timeout_ns);

int
xtc_net_udp_socket(xtc_net_family_t fam, const char *host, int port, int *out_fd);

int
xtc_net_udp_sendto(int fd, const void *buf, size_t len, const char *host, int port);

int
xtc_net_udp_recvfrom(int fd, void *buf, size_t buflen, char *out_host, size_t out_host_size, int *out_port, size_t *out_n);

int
xtc_dns_resolve(const char *hostname, int port, xtc_net_family_t fam, char *out_addr, size_t out_addr_size);

xtc_net provides convenience wrappers around the standard networking syscalls. The actual I/O multiplexing happens through xtc_io(3) and xtc_proc_wait_fd(3);

() and () exchange a 4-byte big-endian length prefix followed by the payload. On a non-blocking fd they yield the calling fiber on partial I/O instead of blocking the loop, so many connections share one loop; off a loop they fall back to poll(2). xtc_net_recv_frame() allocates the frame (free it with ()), and rejects a claimed length above max_len (0 = no cap) with XTC_E_RANGE so a peer cannot force an unbounded allocation; it returns XTC_E_AGAIN on timeout and XTC_E_INVAL if the peer closed mid-frame. A zero-length frame yields XTC_OK with *out set to NULL. these helpers handle socket creation, address resolution, knob setting, and credential passing.

() opens a UDP datagram socket bound to host:port (host NULL means wildcard, port 0 means kernel-assigned) in non-blocking, close-on-exec mode. () sends one datagram to host:port, returning XTC_E_AGAIN if the kernel buffer is full. () receives one datagram, filling out_host (of out_host_size bytes), out_port, and out_n with the peer address and byte count.

() resolves hostname:port for family fam to a printable address string in out_addr (of out_addr_size bytes). It uses getaddrinfo(3) on a blocking thread, so run it from a proc whose thread is allowed to block.

controlled by xtc_tcp_opts_t include:

nodelay
: disable Nagle's algorithm. Default 1.
reuseaddr
.
reuseport
on Linux/BSD; no-op elsewhere.
keepalive
plus optional keepidle_s, keepintvl_s, keepcnt on Linux.
user_timeout_ms
on Linux.

() opens a non-blocking listening socket bound to host:port. fam selects address family (XTC_NET_INET, XTC_NET_INET6, or XTC_NET_UNIX). The fd is non-blocking with FD_CLOEXEC; caller can register it with xtc_io_reg_fd(3) or pass to xtc_proc_wait_fd(3).

() opens a non-blocking TCP connection. The connect is in flight when the call returns; caller polls for XTC_IO_WRITABLE to detect completion.

() applies the knobs to an already-open socket. Useful for sockets returned by accept(2).

() sets O_NONBLOCK + FD_CLOEXEC on a fd (POSIX path or) FIONBIO (Windows path).

() and () open AF_UNIX SOCK_STREAM sockets at the given filesystem path. Listeners auto-unlink the path on bind failure.

on Unix sockets: () sends a buffer; the receiver, via (), gets the buffer plus the sender's UID and GID using SO_PEERCRED (Linux) or LOCAL_PEERCRED (BSD). On platforms where neither is available, UID/GID return as 0 without error.

Linux
, io_uring + epoll backends.
FreeBSD/macOS
, kqueue backend.
illumos
emulated via getpeerucred 3C; event ports backend.
Windows
Winsock2; UDS not supported. TCP only.

xtc_tcp_opts_t opts = XTC_TCP_OPTS_DEFAULT;
opts.keepalive = 1;
opts.keepidle_s = 60;

int listen_fd;
xtc_net_listen(XTC_NET_INET, "0.0.0.0", 8080, &opts, &listen_fd);

for (;;) {
    uint32_t revents;
    int conn_fd;
    xtc_proc_wait_fd(listen_fd, XTC_IO_READABLE, -1, &revents);
    conn_fd = accept(listen_fd, NULL, NULL);
    if (conn_fd < 0) continue;
    xtc_net_setnonblock(conn_fd);
    xtc_net_apply_tcp_opts(conn_fd, &opts);
    /* spawn a per-conn xtc_proc... */
}

xtc_io(3), xtc_proc(3), xtc_tls(3), xtc(7)

Appeared in xtc 0.1.

May 28, 2026 Debian

View the mdoc source