DEV Community

Peter wang
Peter wang

Posted on

AnLiu 1.0: an encrypted, multi-stream, frame-aware UDP transport for real-time media and games

Today we released AnLiu (暗流, "undercurrent") v1.0.0, the first stable version. The wire format is frozen as of this release.

AnLiu is a transport protocol on top of UDP for latency-sensitive applications, such as real-time audio/video and online games. These applications need to carry real-time data and reliable data over one connection. AnLiu follows the style of KCP:

  • Two files: anliu.h / anliu.c, C99, no dependencies.
  • No socket handling: packets go out through a callback and come in through anl_input, and the application drives the clock.
  • Easy to adopt: copy the two files into your project, or install with CMake and use find_package(AnLiu).

Where it fits

Real-time audio/video

Video calls, remote monitoring and live contribution all share one property: a video frame that arrives 500 ms late is as useless as a lost one.

  • Frames are a protocol concept: frames older than max_age_ms are dropped whole, not retransmitted, so latency does not pile up.
  • Key-frame dependencies: when an I-frame is lost, the P-frames that depend on it are neither sent nor delivered.
  • Audio, video and signaling on one connection: each gets its own stream and priority. Audio and signaling do not queue behind video.
  • Adaptive FEC: on long or lossy paths, losses are repaired on the spot instead of waiting a round trip for a retransmission. On clean paths no parity is sent.
  • Bitrate guidance: a callback tells the encoder what rate to use when the bandwidth changes.

Online games

Game state traffic is small, frequent and sensitive to latency and jitter. It also mixes data that must arrive with data where only the latest value matters.

  • Two kinds of data, one connection:
    • Position and state updates go on a semi-reliable stream with a short max_age_ms. Stale updates are dropped and never block newer ones.
    • Commands, chat and results go on a reliable stream.
    • Each stream has its own priority.
  • Steadier on poor networks: FEC repairs random loss on mobile and cross-region links. BBR-style congestion control paces at the measured bottleneck rate instead of filling queues.
  • Small overhead: a 23-byte datagram header, including the authentication tag and packet number, and a 6–7 byte base DATA segment header.
  • Authenticated by default: tampered, replayed and forged packets are dropped.

Cloud gaming / game streaming

High-bitrate video goes down and controller input goes up, and players feel every millisecond between input and picture.

  • High bitrate, measured on real networks (4–20 Mbps video):
    • Without loss, video extra delay P95 is 2–8 ms.
    • With 1–3% loss, ≥ 99.83% of video frames are on time.
  • Input first: input travels on a high-priority stream and never waits behind a large video frame.
  • No "catch-up fast-forward": late frames are dropped, and the stream resumes at the next key frame.

Remote desktop / remote control

One session carries screen updates, keyboard and mouse input, clipboard data and file transfers.

  • One stream per kind of data: screen frames on a semi-reliable frame stream, input on a high-priority stream, clipboard and files on a reliable stream.
  • No interference: a large file copy does not stall the cursor, because all streams share congestion control and are scheduled by priority.
  • Usable across regions: FEC repairs loss without waiting for a retransmission.
  • Encrypted by default: screen contents and keystrokes travel only inside the encrypted connection.

Drone / robot video links and control

Video, telemetry and control commands share one 4G/5G or wireless link, with frequent loss and swinging bandwidth.

  • Traffic split by importance: control commands on the highest-priority reliable stream, telemetry on a latest-value stream, video on a frame stream. When the link degrades, video frames are dropped first.
  • Loss and bandwidth swings: adaptive FEC handles random loss, and the rate callback lets the encoder back off when bandwidth drops.
  • Embedded-friendly: two C files, no dependencies, no socket code.
  • Spoof-resistant: every packet is authenticated.

Note: AnLiu is only the transport. Fail-safes for safety-critical control remain the job of the system itself.

Features

Feature Details
Encryption and anti-fingerprinting SIV construction from ChaCha20 + SipHash-2-4 with a 12-byte tag; whole-datagram authentication; everything after conv is encrypted; per-direction keys; random padding
Multiple streams Up to 64 streams per connection, each with its own reliability mode and priority; shared congestion control, merged ACKs, weighted scheduling
Semi-reliable frame delivery Whole-frame dropping by age, key-frame dependency handling, receiver-side frame skipping
Per-stream FEC Reed–Solomon, fixed or deadline-aware adaptive
Congestion control and bandwidth estimation BBRv2 with BBRv3-style probing, token-bucket pacing, and a target-rate callback for the encoder
Loss recovery SACK + RACK time-based loss detection + reordering adaptation

A taste of the API, with sockets, clock and error handling omitted:

anl_config cfg;
anl_config_default(&cfg, ANL_ROLE_CLIENT);   /* the peer uses ANL_ROLE_SERVER */
memcpy(cfg.psk, my_psk, 32);
anl_t *w = anl_create(conv, &cfg, NULL);
anl_setoutput(w, udp_out);
anl_update(w, now_ms);

/* default stream: reliable, strict priority, good for signaling */
anl_send(w, "hello", 5);

/* video stream: semi-reliable; frames older than 500 ms are not sent or retransmitted,
   and after a loss it drops until the next key frame */
anl_stream_opt o;
anl_stream_opt_default(&o, ANL_SEMI);
o.prio = 1; o.max_age_ms = 500; o.drop_until_key = 1;
anl_stream_t *video = anl_stream_open(w, &o, NULL);
anl_stream_send_frame(video, is_key ? ANL_FRAME_KEY : 0, frame, frame_len, NULL);

/* main loop */
anl_update(w, now_ms);
anl_input(w, pkt, pkt_len);
Enter fullscreen mode Exit fullscreen mode

Performance on real networks

All numbers come from real networks, not simulation:

  • Setup: 4 cloud hosts; paths with an RTT of about 1 / 100 / 185 / 275 ms; 600-second rounds.
  • Loss: random loss applied by tc in both directions.
  • Load: synthetic audio/video frames.

Reliable streams

  • 90.6–93.8% of the link rate at 0.8–10 Mbps.
  • Without a rate limit, the host egress is saturated (27.8–28.2 Mbps on a ~30 Mbit egress).
  • 18.66 GB byte-verified with zero errors; the longest receive gap was 0.92 s.

Audio/video with auto FEC (the default)

Path RTT Random loss Audio on time Video on time
~1 ms up to 15% — 100%
~100 ms up to 15% ≥ 99.83% ≥ 99.92%
~185 ms up to 15% ≥ 99.64% ≥ 99.36%
~275 ms up to 10% — ≥ 98.0%

What auto FEC buys you

  • Free when not needed: without loss, the send rate is within 1.3% of FEC off.
  • Faster delivery: at ~100 ms RTT with 10–15% loss, video P95 extra delay is 122–148 ms, against 199–239 ms with retransmission only.
  • Keeps the bitrate on long paths: at ~275 ms with 10–15% loss, the encoder keeps 91–99% of its rate, against 23–68% with retransmission only.

High bitrate (4 / 8 / 15 / 20 Mbps video + 64 kbps audio)

  • Without loss, video extra delay P95 is 2–8 ms and protocol overhead is 5.6–6.6%.
  • With 1–3% loss, ≥ 99.83% of video frames are on time.

How it compares with SRT

We ran AnLiu and SRT 1.5.4 side by side on the same paths at the same time.

The two deliver differently:

  • SRT holds every packet until "send time + latency" and drops whatever misses that point.
  • AnLiu delivers a frame as soon as it is complete.

To be fair, both were scored through the same playout buffer, with its delay set to SRT's latency.

  • On time:
    • AnLiu with FEC kept audio ≥ 99.03% on time at 1–10% loss, and decodable video ≥ 99.57% at 1–5% loss.
    • On the same ~185 ms path, SRT's audio was about 1 − loss, and its decodable video was 51–98% with a 250 ms video latency.
  • Bandwidth:
    • Without loss, AnLiu used 5–20% less than SRT.
    • On the ~185 ms path at SRT's recommended latency with 1–5% loss, AnLiu with FEC still used 9–11% less, because SRT's own retransmission overhead is high there.
  • Latency:
    • Without loss, AnLiu needed only an 83–89 ms playout buffer to make 99.9% of video frames decodable, while SRT was configured at 120–776 ms.
    • SRT's actual playout delay often drifted from its configured latency, by up to +69 ms on short paths.

Security

  • Threat model: an on-path attacker without the key can neither read plaintext nor make either end accept injected or modified data.
  • Replay protection: a 32-bit packet number inside the encrypted part, a 4096-packet replay window, and a timestamp window.
  • Adversarial tests (test_attack.c, part of CTest):
    • Replay, reflection, bit flips across the whole datagram, truncation, ciphertext malleability and cross-connection injection are all rejected.
    • 0 of 4,000,000 random forgeries were accepted.
  • No amplification: unauthenticated input changes no state and triggers 0 bytes of response, so AnLiu cannot be used as a reflection-DDoS amplifier.
  • Fuzzing: the authenticated parser was fuzzed with libFuzzer + ASan/UBSan for about 14.6 M executions, with no crash or leak. Fuzzing found one defect, a single datagram that could permanently end the default stream, which is now fixed.

Please know before deploying

  • AnLiu uses a 32-byte pre-shared key. There is no key exchange and no forward secrecy. Rotate the key before 2^40 datagrams.
  • The cipher construction is a custom SIV built from standard primitives. It has no formal proof; the stated security goals and the audit are in docs/SECURITY_AUDIT.md.
  • Servers must check conv before creating a connection (see the audit, §5).

Coming soon: NPF, built on AnLiu

AnLiu answers "how do we carry data over one connection". On top of it we built NPF (Network Passage Fabric), which launches soon. NPF is secure connectivity for devices and applications:

  • Reach devices across networks: sessions by device number with automatic NAT traversal. Direct connections when hole punching succeeds; UDP or WebSocket relays otherwise. UDP paths use AnLiu.
  • One session, many channels: port forwarding, a reliable application data channel, and audio/video frame streams that open and close independently.
  • Secure by design: device identity, password pairing on first contact, and public-key pinning. Data is end-to-end encrypted between peers, and relays forward ciphertext.
  • Flexible access: -L / -R forwarding, a SOCKS5 proxy (-D), and public port mappings.
  • Embeddable: libnpf offers one C API for identities, sessions, data and media.
  • Cross-platform and self-hostable: Linux, macOS and Windows; CLI, local web console and service modes; self-hosted servers.

Repository: https://github.com/wanghengwen/npf

Try it

cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build --parallel
ctest --test-dir build --output-on-failure
Enter fullscreen mode Exit fullscreen mode

The design document, performance report, SRT comparison, security audit and all test tools are in the repository, so every number above can be reproduced. The documents are currently in Chinese, with an English README. Issues, questions and stars are v
ery welcome.

Top comments (0)