A Sans I/O, pure C WebRTC implementation for RTOS and embedded systems.
AI-native implementation: Every line of code in this repository — library source, tests, build system, CI, documentation, and examples — is written by AI coding agents. Humans steer architecture and verify correctness; agents execute. See How this project is built for details.
NanoRTC is a WebRTC protocol stack designed from the ground up for resource-constrained microcontrollers running FreeRTOS, Zephyr, RT-Thread, and other RTOS platforms.
Sans I/O architecture — Inspired by str0m (Rust), NanoRTC is a pure state machine. It never touches sockets, threads, memory allocation, or clocks. Your application owns the event loop and all I/O. This makes NanoRTC portable to any platform and testable without a network.
┌─────────────────────────┐
UDP bytes ────────►│ │──────► bytes to send
monotonic time ───►│ nanortc_t │──────► application events
user commands ────►│ (pure state machine) │──────► next timeout (ms)
│ │
│ No sockets. No threads.│
│ No malloc. No clocks. │
└─────────────────────────┘
- Orthogonal feature flags — Include only what you need:
| Configuration | Flash (.text) | RAM (sizeof) | Flags |
|---|---|---|---|
| Core only | 29.0 KB | 10.2 KB | DC=OFF AUDIO=OFF VIDEO=OFF |
| DataChannel | 38.8 KB | 19.4 KB | DC=ON |
| Audio only | 40.8 KB | 20.6 KB | DC=OFF AUDIO=ON |
| DataChannel + Audio | 50.6 KB | 29.9 KB | DC=ON AUDIO=ON |
| Media only (no DC) | 45.3 KB | 51.0 KB | DC=OFF AUDIO=ON VIDEO=ON |
| Full media | 55.0 KB | 60.3 KB | DC=ON AUDIO=ON VIDEO=ON |
Measured on ESP32-P4 (RISC-V HP), ESP-IDF 5.5 mbedTLS,
-Os(CONFIG_COMPILER_OPTIMIZATION_SIZE=y).sizeof(nanortc_t)is the full per-connection RAM — no heap allocation. Flash figures count only nanortc library code (libnanortc.a.text); mbedTLS and lwIP are separate and typically shared with the rest of the firmware. Sizes reflect the ESP-IDF Kconfig defaults — IoT-grade buffer/queue sizing baked in, full ICE stack intact (TURN relay, srflx discovery, IPv6 host candidates, TWCC/BWE perception, RFC 8445 hardening). Reproduce with./scripts/measure-sizes.sh --esp32 esp32p4; tune further viaidf.py menuconfigorNANORTC_CONFIG_FILE.
Any combination works — audio without DataChannel, video without audio, etc.
- ICE — Controlled (answerer) and controlling (offerer) roles, trickle ICE, ICE restart
- DTLS 1.2 — Via pluggable crypto provider (mbedtls or OpenSSL)
- SCTP — Minimal subset for WebRTC DataChannels (reliable + unreliable)
- DataChannel — DCEP protocol, reliable and unreliable modes
- RTP/RTCP/SRTP — Audio and video media transport, H.264 FU-A packetization
- SDP — Offer/answer negotiation, multi-track media
- NAT traversal — STUN server-reflexive discovery + TURN relay client (optional,
NANORTC_FEATURE_TURN) - Bandwidth estimation — REMB-based receiver BWE for adaptive video
- Single external dependency — Only mbedtls (built-in on ESP-IDF, Zephyr, RT-Thread, STM32)
# Build (Linux/macOS) — default: DataChannel only
cmake -B build -DCMAKE_BUILD_TYPE=Debug
cmake --build build -j$(nproc)
ctest --test-dir build --output-on-failure
# Enable audio + video
cmake -B build -DNANORTC_FEATURE_AUDIO=ON -DNANORTC_FEATURE_VIDEO=ON
# With OpenSSL (for Linux host development)
cmake -B build -DNANORTC_CRYPTO=openssl
# Build examples (full media)
cmake -B build -DNANORTC_FEATURE_DATACHANNEL=ON -DNANORTC_FEATURE_AUDIO=ON \
-DNANORTC_FEATURE_VIDEO=ON -DNANORTC_CRYPTO=openssl -DNANORTC_BUILD_EXAMPLES=ON
cmake --build build
# ESP-IDF
idf.py buildSignatures below are simplified for readability — optional out-parameters are omitted. See include/nanortc.h for the full API.
Configure, negotiate, drive:
#include "nanortc.h"
nanortc_t rtc;
nanortc_init(&rtc, &(nanortc_config_t){
.crypto = nanortc_crypto_mbedtls(), // or nanortc_crypto_openssl()
.role = NANORTC_ROLE_CONTROLLED, // or _CONTROLLING to offer
});
nanortc_add_local_candidate(&rtc, local_ip, local_port);
char sdp[4096];
nanortc_accept_offer(&rtc, remote_offer, sdp);
// Offerer: create_datachannel("chat") → create_offer(sdp) → accept_answer(remote_answer)The event loop is symmetric — drain outputs, feed inputs. You own the socket and clock:
for (;;) {
nanortc_output_t out;
while (nanortc_poll_output(&rtc, &out) == NANORTC_OK)
handle_output(&out); // send UDP, fire app event, note next wake-up
size_t len = recv_udp(fd, buf, sizeof buf, &src, wake_ms);
nanortc_handle_input(&rtc, &(nanortc_input_t){
.now_ms = now_ms(), .data = buf, .len = len, .src = src,
});
}One input struct in, one output struct out. No hidden state, no background threads.
For complete runnable examples — browser interop, macOS camera streaming, ESP32 DataChannel — see examples/.
| Platform | Status | Notes |
|---|---|---|
| Linux / macOS | Host development & testing | OpenSSL or mbedtls |
| ESP-IDF (ESP32) | Primary embedded target | Built-in mbedtls, lwIP |
| Zephyr | Supported | Built-in mbedtls, lwIP |
| RT-Thread | Supported | mbedtls package, lwIP |
| STM32 + FreeRTOS | Supported | ST-distributed mbedtls, lwIP |
| NuttX | Supported | POSIX-compatible sockets |
include/nanortc.h Single public API header
src/ Protocol modules (Sans I/O, no platform deps)
crypto/ Pluggable crypto providers (mbedtls, openssl)
tests/ Unit tests + end-to-end tests (no network needed)
tests/interop/ Interop tests against libdatachannel (C++)
examples/ Application templates
common/ Reusable event loop, signaling, media source
browser_interop/ DataChannel + media browser harness
macos_camera/ macOS camera/mic → browser streaming
esp32_{datachannel,audio,video,camera}/ ESP-IDF targets
rk3588_uvc_camera/ RK3588 UVC camera demo
tools/ Dev utilities
sample_data/ Media samples (git submodule)
docs/ Design docs, execution plans, engineering standards
See ARCHITECTURE.md for the module dependency graph and data flow.
NanoRTC is an experiment in AI-native software engineering, inspired by Harness Engineering. The entire codebase is generated by AI coding agents, following the principle: humans steer, agents execute.
What this means in practice:
- Architecture & design — Human decisions, captured in
docs/design-docs/ - All code — Written by AI agents: library source, tests, CI, build system, documentation
- Quality gates — Mechanically enforced via CI: forbidden includes, no malloc, symbol naming, format checks, 7-combo feature flag build matrix, AddressSanitizer
- RFC compliance — Protocol implementations follow RFCs as the authoritative standard, not reference code
- Continuous verification —
./scripts/ci-check.shruns the same checks locally that run in GitHub Actions. Auto-detectsccache, keeps build dirs across runs for incremental compilation, and exposes--fastfor tight pre-push loops (skips low-yield combos and the libdatachannel interop suite — seconds rather than minutes)
The repository structure itself is designed for agent legibility: AGENTS.md serves as the entry point, with progressive disclosure into deeper documentation. Constraints are enforced by code, not by convention.
| Document | Description |
|---|---|
| AGENTS.md | Agent entry point — build commands, mandatory rules |
| Build Guide | Build commands, feature flags, fuzz, coverage, ESP-IDF |
| ARCHITECTURE.md | Module dependency graph, layer model, data flow |
| Design Specification | Full authoritative design reference |
| Core Beliefs | Non-negotiable design principles |
| Execution Plans | Active and completed implementation plans |
| Quality Score | Per-module quality grades |
| Memory Profiles | RAM usage by configuration, tuning guide |
| Coding Standards | Naming, style, RFC testing requirements |
| Safe C Guidelines | Banned functions, buffer safety rules |
| RFC Index | Protocol specification references |
NanoRTC is in active development. The core protocol stack — DataChannel, Audio, Video/H.264, ICE+STUN+TURN with RFC 8445 compliance, SRTP, and TWCC/BWE perception — is code-complete and interop-verified against libdatachannel and Chromium. Phase 8 continued-optimization and Phase 3.5 H.265 are in flight; see docs/PLANS.md for current phase status. All 18 library modules at A grade — fuzz-tested, browser-verified, libdatachannel-interop-verified, 80%+ coverage.
Contributions welcome. Please read AGENTS.md for build instructions and mandatory rules before submitting changes.