Skip to content

Networking

The oveRTOS networking subsystem provides a portable BSD-like socket API, DNS resolution, TLS encryption, and higher-level protocol clients (HTTP, MQTT) and servers (HTTPD with WebSocket support). The stack runs on all four backends with zero-heap support throughout.

All networking modules require CONFIG_OVE_NET. When it is not set, every function is replaced by a static inline stub that returns OVE_ERR_NOT_SUPPORTED.

Architecture

graph TD
    APP["Application"]
    HTTP["HTTP Client<br/><small>ove/net_http.h</small>"]
    MQTT["MQTT Client<br/><small>ove/net_mqtt.h</small>"]
    HTTPD["HTTP Server<br/><small>ove/net_httpd.h</small>"]
    SNTP["SNTP Client<br/><small>ove/net_sntp.h</small>"]
    TLS["TLS (mbedTLS)<br/><small>ove/net_tls.h</small>"]
    SOCK["Sockets + DNS<br/><small>ove/net.h</small>"]
    BACK["Backend<br/><small>lwIP · Zephyr zsock · NuttX · POSIX</small>"]

    APP --> HTTP
    APP --> MQTT
    APP --> HTTPD
    APP --> SNTP
    APP --> SOCK
    HTTP --> TLS
    MQTT --> TLS
    HTTP --> SOCK
    MQTT --> SOCK
    HTTPD --> SOCK
    SNTP --> SOCK
    TLS --> SOCK
    SOCK --> BACK

Each layer only depends on the layer directly below it. The socket layer is the only backend-specific code; everything above it is portable C shared across all RTOSes.

Kconfig Options

Option Default Description
CONFIG_OVE_NET n Core socket API, DNS, network interface
CONFIG_OVE_NET_TLS n TLS sessions via mbedTLS
CONFIG_OVE_NET_HTTP n HTTP/1.1 client
CONFIG_OVE_NET_MQTT n MQTT 3.1.1 client
CONFIG_OVE_NET_HTTPD n Embedded HTTP server
CONFIG_OVE_NET_HTTPD_WS n WebSocket support for HTTPD
CONFIG_OVE_NET_SNTP n Simple NTP time sync
CONFIG_OVE_NET_TLS_HEAP_SIZE 32768 Static TLS heap size (zero-heap mode)
CONFIG_OVE_NET_HTTP_MAX_RESPONSE 8192 Max HTTP response buffer
CONFIG_OVE_NET_HTTPD_MAX_BODY 1024 Max POST body for HTTPD
CONFIG_OVE_NET_MQTT_RX_BUF 1024 MQTT receive buffer
CONFIG_OVE_NET_MQTT_TX_BUF 512 MQTT transmit buffer

Networking Error Codes

In addition to the common error codes, networking functions may return:

Constant Value Meaning
OVE_ERR_NET_REFUSED -8 Connection refused by remote host
OVE_ERR_NET_UNREACHABLE -9 Network or host unreachable
OVE_ERR_NET_ADDR_IN_USE -10 Local address already bound
OVE_ERR_NET_RESET -11 Connection reset by peer
OVE_ERR_NET_DNS_FAIL -12 DNS name resolution failed
OVE_ERR_NET_CLOSED -13 Connection closed by peer

Address and Network Interface

Address Type

ove_sockaddr_t holds an IPv4 or IPv6 address with port. Use the helper to construct IPv4 addresses:

ove_sockaddr_t addr;
ove_sockaddr_ipv4(&addr, 192, 168, 1, 100, 8080);

Network Interface

Before any networking, bring up the interface with static IP or DHCP:

ove_netif_t netif;
ove_netif_storage_t storage;
ove_netif_init(&netif, &storage);

ove_netif_config_t cfg = {0};
cfg.use_dhcp = 0;
ove_sockaddr_ipv4(&cfg.static_ip, 172, 1, 1, 2, 0);
ove_sockaddr_ipv4(&cfg.netmask,   255, 255, 255, 0, 0);
ove_sockaddr_ipv4(&cfg.gateway,   172, 1, 1, 1, 0);
ove_sockaddr_ipv4(&cfg.dns,       8, 8, 8, 8, 0);

ove_netif_up(netif, &cfg);

For DHCP, set cfg.use_dhcp = 1 and leave the address fields zeroed.

Network Interface API

Function Description
ove_netif_init Initialise from caller-supplied storage
ove_netif_deinit Release resources
ove_netif_create Heap-allocate and initialise (heap mode)
ove_netif_destroy Destroy heap-allocated interface
ove_netif_up Bring interface up with config
ove_netif_down Tear down interface
ove_netif_get_addr Query current IP, gateway, netmask

Sockets (TCP and UDP)

Socket Lifecycle

sequenceDiagram
    participant App
    participant Socket

    App->>Socket: ove_socket_open (TCP or UDP)
    App->>Socket: ove_socket_connect (TCP) or ove_socket_bind (UDP)
    loop Data exchange
        App->>Socket: ove_socket_send / ove_socket_recv
    end
    App->>Socket: ove_socket_close

TCP Example

ove_socket_t sock;
ove_socket_storage_t storage;
ove_socket_open(&sock, &storage, OVE_AF_INET, OVE_SOCK_STREAM);

ove_sockaddr_t dest;
ove_dns_resolve("example.com", &dest, 5000);
dest.port = 80;
ove_socket_connect(sock, &dest, 5000);

const char *req = "GET / HTTP/1.0\r\nHost: example.com\r\n\r\n";
size_t sent;
ove_socket_send(sock, req, strlen(req), &sent);

char buf[512];
size_t received;
ove_socket_recv(sock, buf, sizeof(buf), &received, 5000);

ove_socket_close(sock);

UDP Example

ove_socket_t sock;
ove_socket_storage_t storage;
ove_socket_open(&sock, &storage, OVE_AF_INET, OVE_SOCK_DGRAM);

ove_sockaddr_t local = {0};
ove_sockaddr_ipv4(&local, 0, 0, 0, 0, 9999);
ove_socket_bind(sock, &local);

ove_sockaddr_t dest;
ove_sockaddr_ipv4(&dest, 127, 0, 0, 1, 9999);
size_t sent;
ove_socket_sendto(sock, "hello", 5, &sent, &dest);

char buf[64];
size_t received;
ove_sockaddr_t src;
ove_socket_recvfrom(sock, buf, sizeof(buf), &received, &src, 2000);

ove_socket_close(sock);

Socket API

Function Description
ove_socket_open Open a socket with caller-supplied storage
ove_socket_close Close a socket
ove_socket_connect Connect to a remote address (TCP)
ove_socket_bind Bind to a local address
ove_socket_listen Mark socket as listening (TCP server)
ove_socket_accept Accept an incoming connection
ove_socket_send Send data on a connected socket
ove_socket_recv Receive data with timeout
ove_socket_sendto Send a datagram to a destination (UDP)
ove_socket_recvfrom Receive a datagram with source address
ove_socket_create Heap-allocate a socket (heap mode)
ove_socket_destroy Destroy a heap-allocated socket

DNS

ove_sockaddr_t addr;
int rc = ove_dns_resolve("example.com", &addr, 10000);
if (rc == OVE_OK) {
    /* addr.addr[0..3] contains the IPv4 address */
    addr.port = 80;  /* set port for subsequent connect */
}

The hostname must be a null-terminated C string. The timeout is in milliseconds.

TLS

TLS wraps an existing TCP socket with mbedTLS encryption. Requires CONFIG_OVE_NET_TLS.

ove_tls_t tls;
ove_tls_storage_t tls_storage;
ove_tls_init(&tls, &tls_storage);

ove_tls_config_t cfg = {0};
cfg.hostname = "example.com";  /* SNI hostname for verification */

ove_tls_handshake(tls, sock, &cfg);  /* sock is an already-connected TCP socket */

size_t sent;
ove_tls_send(tls, "GET / HTTP/1.1\r\n...", len, &sent);

char buf[512];
size_t received;
ove_tls_recv(tls, buf, sizeof(buf), &received);

ove_tls_close(tls);
ove_tls_deinit(tls);

For certificate verification, set cfg.ca_cert and cfg.ca_cert_len to a PEM or DER certificate.

HTTP Client

Requires CONFIG_OVE_NET_HTTP. Handles DNS, TCP connection, optional TLS, request formatting, and response parsing internally.

ove_http_client_t client;
ove_http_client_storage_t storage;
ove_http_client_init(&client, &storage);

ove_http_response_t resp;
ove_http_get(client, "http://example.com/", &resp);
/* resp.status = 200, resp.body = "...", resp.body_len = 540 */
ove_http_response_free(&resp);

ove_http_post(client, "http://httpbin.org/post",
              "application/json", "{\"key\":\"value\"}", 15, &resp);
ove_http_response_free(&resp);

ove_http_client_deinit(client);

HTTP Methods

Method Enum Value
GET OVE_HTTP_GET
POST OVE_HTTP_POST
PUT OVE_HTTP_PUT
DELETE OVE_HTTP_DELETE
PATCH OVE_HTTP_PATCH

HTTP Client API

Function Description
ove_http_client_init Initialise from caller-supplied storage
ove_http_client_deinit Release resources
ove_http_get Perform a GET request
ove_http_post Perform a POST request
ove_http_request Generic request with method, body, content type
ove_http_request_ex Extended request with custom headers
ove_http_response_free Free response body/header buffers

MQTT Client

Requires CONFIG_OVE_NET_MQTT. Implements MQTT 3.1.1 with QoS 0 and 1.

static void on_message(const char *topic, size_t topic_len,
                       const void *payload, size_t payload_len,
                       void *user_data)
{
    OVE_LOG_INF("MQTT: [%.*s] %.*s", (int)topic_len, topic,
                (int)payload_len, (const char *)payload);
}

ove_mqtt_client_t mqtt;
ove_mqtt_client_storage_t storage;
ove_mqtt_client_init(&mqtt, &storage);

ove_mqtt_config_t cfg = {
    .host = "test.mosquitto.org",
    .port = 1883,
    .client_id = "my-device",
    .keep_alive_s = 30,
    .on_message = on_message,
};
ove_mqtt_connect(mqtt, &cfg);

ove_mqtt_subscribe(mqtt, "my/topic", OVE_MQTT_QOS0);
ove_mqtt_publish(mqtt, "my/topic", "hello", 5, OVE_MQTT_QOS1);

/* Call periodically to process incoming messages and send keep-alive */
ove_mqtt_loop(mqtt, 500);

ove_mqtt_disconnect(mqtt);
ove_mqtt_client_deinit(mqtt);

MQTT Client API

Function Description
ove_mqtt_connect Connect to broker with config
ove_mqtt_disconnect Disconnect from broker
ove_mqtt_publish Publish a message (QoS 0 or 1)
ove_mqtt_subscribe Subscribe to a topic filter
ove_mqtt_unsubscribe Unsubscribe from a topic
ove_mqtt_loop Process packets and send keep-alive

HTTP Server

Requires CONFIG_OVE_NET_HTTPD. Single-threaded HTTP/1.1 server with path-based routing and a built-in Tasmota-style web dashboard.

ove_httpd_config_t cfg = { .port = 80, .max_body_size = 1024 };
ove_httpd_start(&cfg);
ove_httpd_register_builtin_routes();  /* /api/info, /api/leds, /api/gpio, etc. */

Custom Routes

static int my_handler(ove_httpd_req_t *req, ove_httpd_resp_t *resp)
{
    const char *path = ove_httpd_req_path(req);
    const char *seg  = ove_httpd_req_segment(req, 1); /* e.g. "0" from /api/items/0 */
    return ove_httpd_resp_json(resp, 200, "{\"status\":\"ok\"}");
}

ove_httpd_route("GET", "/api/items/*", my_handler);

Built-in Dashboard Routes

Route Method Description
/ GET Web dashboard (HTML/CSS/JS)
/api/info GET Device info (RTOS, board, uptime, memory)
/api/leds GET/POST LED state query and control
/api/gpio GET/POST GPIO pin read/write
/api/network GET Network interface status
/api/log GET Recent log messages

HTTPD API

Function Description
ove_httpd_start Start the HTTP server
ove_httpd_stop Stop the server
ove_httpd_route Register a route handler
ove_httpd_register_builtin_routes Register the built-in dashboard
ove_httpd_req_method Get request method string
ove_httpd_req_path Get request path
ove_httpd_req_query Get query string
ove_httpd_req_body Get POST body
ove_httpd_req_segment Get path segment by index
ove_httpd_resp_json Send JSON response
ove_httpd_resp_html Send HTML response
ove_httpd_resp_send Send response with content type
ove_httpd_resp_error Send error response

WebSocket Support

When CONFIG_OVE_NET_HTTPD_WS is enabled, the server supports RFC 6455 WebSocket connections:

static int ws_on_message(ove_httpd_ws_conn_t *conn,
                         const void *data, size_t len)
{
    /* Echo back */
    return ove_httpd_ws_send(conn, data, len);
}

ove_httpd_ws_route("/ws", ws_on_message, NULL);
ove_httpd_ws_broadcast("/ws", "hello", 5);

SNTP

Requires CONFIG_OVE_NET_SNTP. Performs a single NTP query to get UTC time.

ove_sntp_config_t cfg = { .server = "pool.ntp.org", .timeout_ms = 5000 };
ove_sntp_sync(&cfg);

uint32_t utc_s;
ove_sntp_get_utc(&utc_s);  /* seconds since 1970-01-01 */

Zero-Heap Networking

When CONFIG_OVE_ZERO_HEAP is enabled, the entire networking stack operates without any dynamic memory allocation:

  • lwIP (FreeRTOS): Uses static memory pools for PCBs, packet buffers, and ARP entries
  • mbedTLS: Uses MBEDTLS_MEMORY_BUFFER_ALLOC_C with a static buffer (CONFIG_OVE_NET_TLS_HEAP_SIZE)
  • HTTP client: Response buffer embedded in the client storage struct
  • MQTT client: Socket storage embedded in the client struct
  • All sockets: Use _init()/_deinit() with caller-supplied ove_*_storage_t

The _create()/_destroy() convenience macros automatically expand to static storage in zero-heap mode (see Allocation Strategies).

Language Bindings

All four languages provide equivalent networking APIs. Key type mappings:

Concept C C++ Rust Zig
Address ove_sockaddr_t ove::net::Address ove::net::Address ove.Address
Net interface ove_netif_t ove::net::NetIf ove::net::NetIf ove.NetIf
TCP socket ove_socket_t ove::net::TcpSocket ove::net::TcpStream ove.TcpStream
UDP socket ove_socket_t ove::net::UdpSocket ove::net::UdpSocket ove.UdpSocket
DNS resolve ove_dns_resolve() ove::net::dns::resolve() ove::net::dns_resolve() ove.net.dns.resolve()
HTTP client ove_http_client_t ove::http::Client ove::net_http::Client ove.HttpClient
MQTT client ove_mqtt_client_t ove::mqtt::Client ove::net_mqtt::Client ove.MqttClient
TLS session ove_tls_t ove::tls::Session ove::net_tls::Session ove.TlsSession
HTTPD start ove_httpd_start() ove::httpd::start() ove::net_httpd::start() ove.net_httpd.start()
Cleanup _deinit() / _destroy() Destructor Drop trait defer obj.destroy()

RAII Patterns by Language

  • C: Manual _init()/_deinit() or _create()/_destroy()
  • C++: Automatic via destructor; move-only types (no copy)
  • Rust: Automatic via Drop trait; Result<T> error handling
  • Zig: Explicit destroy() with defer; Error!T return types; comptime zero-heap dispatch

MQTT Callback Patterns

Language Pattern
C Function pointer: void (*)(topic, topic_len, payload, payload_len, user_data)
C++ std::function<void(std::string_view topic, std::span<const uint8_t> payload)>
Rust fn(&str, &[u8]) via trampoline (zero unsafe in app code)
Zig comptime fn([]const u8, []const u8) void via trampoline, or connectWithContext() for typed state