udp_prague 0.1.0

A Rust implementation of the Prague congestion control protocol for UDP-based applications.
Documentation
# Compatibility Notes

Use this page when you need to compare the Rust port against the original C++ project or depend on older compatibility aliases.

For project overview and usage guidance, see [../README.md](../README.md) and [embedding-guide.md](embedding-guide.md).

Older top-level module paths are still re-exported for compatibility. New code should prefer the structured module paths:

- `udp_prague::core`
- `udp_prague::congestion`
- `udp_prague::protocol`
- `udp_prague::net`
- `udp_prague::demo`

## Remaining Intentional Divergences

The Rust port aims to keep the Prague wire format, congestion-control behavior, and demo reporting surface close to the C++ reference. A small number of deliberate differences still remain.

### Demo reporting and JSON parity

The demo sender/receiver reporting path keeps the reference JSON-lines schema intentionally close to the C++ output:

- All JSON values remain strings, matching the original `json_writer.h` behavior.
- Field names and field order match the reference reporting code.
- Float-valued fields use six fractional digits, matching C++ `std::to_string(float)` output.
- Receiver JSON keeps the original key quirk: classic feedback reports `RTT`, while RFC8888 feedback reports `ATO`.
- RT sender JSON keeps the original extra `frame_inflight` and `frame_window` fields ahead of the packet-window fields.
- The `-j` CLI flag preserves the original filename validation quirk and rejects path separators, so it accepts bare filenames rather than arbitrary paths.

### Rust-side cleanups

These are intentional cleanups rather than bug-for-bug parity:

- String fields are escaped via `serde_json`, so quotes and newlines stay valid JSON even though the C++ writer would emit invalid JSON for those inputs.
- JSON dump failures are latched and warned once instead of being silently ignored.

### Runtime and socket robustness extensions

These are deliberate Rust-side robustness improvements around the runtime and socket boundary:

- The non-connected sender startup wait can optionally be bounded through `RunnerConfig::startup_wait_timeout_us` or the demo CLI flag `--startuptimeout`. Leaving that value unset preserves the reference behavior and waits indefinitely for the trigger packet.
- On Linux, the Unix socket backend intentionally accepts the real 1-byte IPv4 `IP_TOS` ancillary-data payload returned by `recvmsg()`. That is a socket-API robustness improvement rather than a wire-format divergence; the decoded low ECN bits remain semantically aligned with the C++ reference.