Skip to content

Conversation

@datagutt
Copy link
Member

@datagutt datagutt commented Dec 6, 2025

Add backwards-compatible extended KEEPALIVE packet format that embeds connection telemetry data directly in keepalive packets, eliminating the need for separate extension negotiation (EXT_HELLO/EXT_ACK) and connection info packets (CONN_INFO).

Extended KEEPALIVE format (42 bytes):

  • Bytes 0-9: Standard KEEPALIVE (type + timestamp)
  • Bytes 10-11: Magic number (0xC01F) for format detection
  • Bytes 12-13: Version (0x0001)
  • Bytes 14-41: Connection info (conn_id, window, in_flight, rtt_us, nak_count, bitrate)

Backwards compatibility:

  • Old receivers read first 10 bytes and ignore the rest
  • New receivers detect magic number and parse connection info
  • Combined magic + version check provides ~1 in 4 billion false positive rate

Benefits over previous extension system:

  • No negotiation handshake required
  • Telemetry available immediately after connection
  • Simpler implementation (eliminates extension negotiation module)
  • Fewer packet types (one instead of three)
  • More reliable (no dependency on EXT_ACK response)

BREAKING CHANGE: Senders now always send 42-byte extended keepalives instead of 10-byte standard keepalives. This is backwards compatible with existing receivers but changes the wire format.

Summary by CodeRabbit

  • New Features

    • Introduces an extended KEEPALIVE packet carrying per-connection telemetry (connection ID, window, in-flight, RTT, NAK count, bitrate).
    • Maintains backward compatibility so older peers ignore the extension.
  • Documentation

    • Added comprehensive spec describing the extended KEEPALIVE format, validation, compatibility, usage examples, security considerations, and testing guidance.

✏️ Tip: You can customize this high-level summary in your review settings.

Add backwards-compatible extended KEEPALIVE packet format that embeds
connection telemetry data directly in keepalive packets, eliminating
the need for separate extension negotiation (EXT_HELLO/EXT_ACK) and
connection info packets (CONN_INFO).

Extended KEEPALIVE format (42 bytes):
- Bytes 0-9: Standard KEEPALIVE (type + timestamp)
- Bytes 10-11: Magic number (0xC01F) for format detection
- Bytes 12-13: Version (0x0001)
- Bytes 14-41: Connection info (conn_id, window, in_flight, rtt_us,
  nak_count, bitrate)

Backwards compatibility:
- Old receivers read first 10 bytes and ignore the rest
- New receivers detect magic number and parse connection info
- Combined magic + version check provides ~1 in 4 billion false
  positive rate

Benefits over previous extension system:
- No negotiation handshake required
- Telemetry available immediately after connection
- Simpler implementation (eliminates extension negotiation module)
- Fewer packet types (one instead of three)
- More reliable (no dependency on EXT_ACK response)

BREAKING CHANGE: Senders now always send 42-byte extended keepalives
instead of 10-byte standard keepalives. This is backwards compatible
with existing receivers but changes the wire format.
@coderabbitai
Copy link

coderabbitai bot commented Dec 6, 2025

Walkthrough

Adds a backwards-compatible 42-byte extended KEEPALIVE packet for SRTLA with per-connection telemetry; documents the format and parsing rules; implements encoding/decoding and unit tests in src/protocol.rs; updates src/connection/mod.rs to send the extended packet; adds docs/EXTENDED_KEEPALIVE.md.

Changes

Cohort / File(s) Summary
Extended KEEPALIVE Documentation
docs/EXTENDED_KEEPALIVE.md
New spec describing the 42-byte extended KEEPALIVE packet (magic/version, big-endian fields: conn_id, window, in_flight, rtt_us, nak_count, bitrate_bytes_per_sec), compatibility rules, examples, implementation sketches, testing and security notes.
Protocol Layer Implementation
src/protocol.rs
Added public constants SRTLA_KEEPALIVE_MAGIC, SRTLA_KEEPALIVE_EXT_LEN, SRTLA_KEEPALIVE_EXT_VERSION; new ConnectionInfo struct; create_keepalive_packet_ext() to build 42-byte packets; extract_keepalive_conn_info() to validate/parse extended payload; unit tests for roundtrip, compatibility, and error cases.
Connection Module Integration
src/connection/mod.rs
Replaced static atomic conn-id generator with random 64-bit conn_id; send_keepalive() now builds a ConnectionInfo (conn_id, window, in_flight, rtt_us, nak_count, bitrate_bytes_per_sec) and uses create_keepalive_packet_ext() to send extended KEEPALIVE.
Build / Receiver Context
receiver/...
Added ../srtla entry to receiver context (single-line change; no functional code edits).

Sequence Diagram(s)

sequenceDiagram
    autonumber
    participant Conn as Connection (sender)
    participant Proto as Protocol (encoder)
    participant Net as Network
    participant Recv as Receiver
    participant Parser as Protocol (extractor)

    Conn->>Proto: build ConnectionInfo (conn_id, window, in_flight, rtt_us, nak_count, bitrate)
    Proto-->>Conn: 42-byte extended KEEPALIVE packet
    Conn->>Net: send KEEPALIVE packet
    Net->>Recv: deliver packet bytes
    Recv->>Parser: call extract_keepalive_conn_info(buf)
    alt magic/version valid & length == 42
      Parser-->>Recv: ConnectionInfo parsed
    else not extended or older sender
      Parser-->>Recv: None (fall back to extract_keepalive_timestamp)
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • Attention areas:
    • Byte offsets, big-endian encoding/decoding and alignment in create_keepalive_packet_ext() / extract_keepalive_conn_info().
    • Unit tests correctness and coverage for magic/version, length checks, and backward compatibility.
    • Random conn_id replacement: ensure uniqueness expectations and any places assuming sequential IDs are updated.
    • Integration in src/connection/mod.rs: correct sourcing of metrics (bitrate, in_flight, nak_count) and no regressions in RTT/send logic.

Possibly related PRs

  • Test suite #1 — adds src/utils.rs with now_ms() and updates modules to use it; related because timing utilities are used in keepalive/RTT logic.
  • Refactoring, enhanced logging and mimalloc #7 — modifies src/connection/mod.rs and protocol keepalive handling; directly related to connection ID and keepalive packet changes.

Poem

🐰 I tunneled bytes beneath the hill,

a magic tag, a version still.
Telemetry tucked in forty-two,
I hop — connection health I view.
Cheers to packets, small and new! 🥕

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately and concisely summarizes the primary change: introducing an extended KEEPALIVE packet format with embedded connection information.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/keepalive-conn-info

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
docs/EXTENDED_KEEPALIVE.md (1)

20-25: Add language specifiers to code blocks for linting compliance.

The packet layout diagrams at lines 20, 29, and 235 lack language specifiers. Use text or plaintext to satisfy markdown linters.

-```
+```text
 Offset | Size | Field
 -------|------|------------------
 0-1    | 2    | Packet type (0x9000)
 2-9    | 8    | Timestamp (u64 ms, big-endian)

Apply the same fix to the other two occurrences (lines 29 and 235).

</blockquote></details>
<details>
<summary>src/protocol.rs (1)</summary><blockquote>

`317-401`: **Test suite provides good coverage.**

The tests verify the key scenarios: roundtrip encoding/decoding, backwards compatibility with standard keepalives, and rejection of packets with wrong magic or version.


Consider adding a test case with negative `window` and `in_flight` values to verify signed integer serialization roundtrips correctly:

```rust
#[test]
fn test_extended_keepalive_negative_values() {
    let info = ConnectionInfo {
        conn_id: 1,
        window: -5000,
        in_flight: -10,
        rtt_us: 50_000,
        nak_count: 0,
        bitrate_bytes_per_sec: 500_000,
    };

    let pkt = create_keepalive_packet_ext(info);
    let extracted = extract_keepalive_conn_info(&pkt).unwrap();
    assert_eq!(extracted, info);
}
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 212b2b8 and 40e37bb.

📒 Files selected for processing (3)
  • docs/EXTENDED_KEEPALIVE.md (1 hunks)
  • src/connection/mod.rs (1 hunks)
  • src/protocol.rs (5 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.rs

📄 CodeRabbit inference engine (AGENTS.md)

**/*.rs: All Rust code must pass cargo fmt --all -- --check
All Rust code must pass clippy with -D warnings (no warnings allowed)
Use anyhow::Result for error propagation
Group imports as std → external → crate with module-level granularity (imports_granularity = "Module", group_imports = "StdExternalCrate")
Follow naming conventions: constants SCREAMING_SNAKE_CASE
Follow naming conventions: structs PascalCase
Follow naming conventions: functions snake_case
Follow naming conventions: modules snake_case (file/module names)
Use tracing macros (debug!, info!, warn!, etc.) for logging
Use Tokio for async runtime (net, time, io, signal) and async operations
Keep code self-documenting; add doc comments for public API when necessary

Files:

  • src/connection/mod.rs
  • src/protocol.rs
src/**/*.rs

📄 CodeRabbit inference engine (AGENTS.md)

Expose internal fields for testing only behind #[cfg(feature = "test-internals")]

Files:

  • src/connection/mod.rs
  • src/protocol.rs
🧬 Code graph analysis (1)
src/connection/mod.rs (1)
src/protocol.rs (1)
  • create_keepalive_packet_ext (124-143)
🪛 markdownlint-cli2 (0.18.1)
docs/EXTENDED_KEEPALIVE.md

20-20: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


29-29: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


235-235: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Test (Windows)
  • GitHub Check: Test
🔇 Additional comments (6)
src/connection/mod.rs (1)

160-169: Extended keepalive construction looks correct.

The ConnectionInfo population correctly maps connection state to the protocol fields. The RTT conversion (ms × 1000 → μs) and bitrate conversion (bps ÷ 8 → bytes/sec) are accurate.

Minor observation: conn_id is truncated from u64 to u32 on line 162. Since NEXT_CONN_ID starts at 1 and increments atomically, this is safe in practice (you'd need 4+ billion connections to wrap). If this sender is intended for very long-running or high-churn deployments, consider either:

  • Changing SrtlaConnection::conn_id to u32, or
  • Documenting the truncation behavior

Otherwise, this is fine as-is.

docs/EXTENDED_KEEPALIVE.md (1)

1-271: Documentation is comprehensive and accurate.

The packet format, field definitions, and compatibility behavior are well-documented and align with the implementation. The security considerations section appropriately notes the lack of authentication and recommends rate-limiting.

src/protocol.rs (4)

45-48: Constants are well-defined and follow naming conventions.

The magic number 0xc01f ("C01F" mnemonic for "Connection Info") is a reasonable choice. Version 0x0001 allows for future extensibility as documented.


96-105: ConnectionInfo struct is well-designed.

The struct is appropriately sized (28 bytes), derives Copy for efficient passing, and uses Eq (valid since all fields are integral). The public fields align with the documented packet format.


124-143: Packet creation is correct and well-documented.

The function correctly serializes all fields in big-endian format at the documented offsets. The use of copy_from_slice with to_be_bytes() is idiomatic and efficient.


167-205: Extraction function has robust validation.

The validation sequence (length → type → magic → version) correctly prevents out-of-bounds access and gracefully handles standard keepalives or corrupted packets. The parsing logic mirrors the creation function exactly.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
receiver (1)

1-1: External symlink-style target likely to be fragile (../srtla).

Line 1 makes receiver look like a Git symlink pointing outside this repo (to ../srtla). Anyone cloning this repo standalone will end up with a broken link unless they also have a sibling srtla directory arranged exactly the same way. This can easily break builds, tooling, or editor navigation that expect receiver to be self-contained.

Consider one of:

  • If this should link to code inside this repo, adjust the target to a path within the repo.
  • If this is meant to pull in another project, prefer a Git submodule/subtree or documented dependency instead of a relative symlink escaping the repo root.

Can you confirm that this external path is intentional and works in your intended deployment/CI environments?

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 40e37bb and edbe08c.

📒 Files selected for processing (2)
  • receiver (1 hunks)
  • src/connection/mod.rs (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/connection/mod.rs
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Test (Windows)
  • GitHub Check: Test

@datagutt datagutt merged commit 160ad0b into main Dec 9, 2025
6 checks passed
@datagutt datagutt deleted the feat/keepalive-conn-info branch December 26, 2025 02:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants