Rho Rho language and toolchain

Networking

A program that speaks MQTT, HTTP or a websocket should not carry a vendor's
networking stack in its source. robohub-common declares the contract such a
program is written against — robohub/net.h — and each platform implements it.
A protocol built on this compiles for a Pico W, an ESP32 or a Linux gateway
without a line changed.

The contract

/* Interface */
RoboHubError     robohub_net_wifi_connect(const RoboHubWiFiConfig* config);
RoboHubError     robohub_net_wifi_disconnect(void);
RoboHubNetStatus robohub_net_status(void);
RoboHubError     robohub_net_ip(char* out_ip, rh_size max_len);

/* Sockets */
RoboHubSocket robohub_socket_create(RoboHubSocketType type);
RoboHubError  robohub_socket_connect(RoboHubSocket socket, const char* host, rh_u16 port);
int           robohub_socket_send(RoboHubSocket socket, const void* data, rh_size len);
int           robohub_socket_recv(RoboHubSocket socket, void* data, rh_size len, rh_u32 timeout_ms);
void          robohub_socket_close(RoboHubSocket socket);

Every function has a weak default in robohub-common. A board with no network
links and runs: the default answers ROBOHUB_ERR_NOT_SUPPORTED, returns a null
socket, or reports a disconnected interface. A platform that implements the
contract defines these functions strongly and the linker prefers them — the same
mechanism the OSAL uses to choose an RTOS.

recv takes a timeout and must not block longer than it says. ROBOHUB_SOCKET_TIMEOUT
is returned when the time passed with nothing to read — a poll that came up empty,
not an error. A platform implements the wait as a non-blocking poll between OSAL
sleeps, so a network read never starves the control loop sharing its core.

How each platform supplies it

CapabilityESP32Pico WLinux / gateway
Interface controlesp_wifi + esp_eventcyw43_arch_wifi_connect_timeout_msNetworkManager / wpa_supplicant
IP stackLwIP via esp_netifLwIP via the Pico SDKPOSIX
SocketsLwIP BSD wrapperLwIP RAW API (tcp/udp pcbs)<sys/socket.h>
Name resolutiongetaddrinfo (LwIP)numeric IPv4 (ip4addr_aton)getaddrinfo

The Pico W column is not the BSD layer because its arch —
pico_cyw43_arch_lwip_threadsafe_background — runs LwIP bare-metal
(NO_SYS=1), and the BSD socket and netconn layers need an OS to block in. The
platform's pico_net.c therefore answers the socket contract over the RAW API,
with a single-producer/single-consumer ring the lwIP callbacks fill and a caller
drains; that is also what makes a receive the non-blocking poll the contract
asks for. Resolving a name would need dns_gethostbyname's asynchronous
callback, so connect takes a numeric address, as the POSIX reference does.

The POSIX column is the reference: tests/test_net_posix.c implements the
contract over <sys/socket.h> and drives it against a loopback socket, so the
contract itself is exercised without a board. A platform port follows the same
shape with its own stack beneath.

Enabling it

A project selects the contract with RH_NET; a platform's build then compiles
its implementation. A project that never opens a socket does not select it, and
pays nothing.