Skip to content

Upgrade Unbounded's pion and accept server tuning - #384

Merged
myleshorton merged 3 commits into
mainfrom
feat/unbounded-pion-latest
Oct 25, 2026
Merged

myleshorton merged 3 commits into
mainfrom
feat/unbounded-pion-latest

Conversation

@myleshorton

@myleshorton myleshorton commented Oct 24, 2026 •

Copy link
Copy Markdown
Contributor

Upgrades the Unbounded outbound to the latest pion, and adds a tuning option so the server can tune pion's ICE, DTLS and SCTP defaults per track instead of per release.

Depends on getlantern/unbounded#478, now merged. go.mod pins broflake to its merge commit (ae5d221).

Why

Our consumer makes the offer, so it's the DTLS server. About 27% of Unbounded attempts reach "ICE connected" and then stall in the handshake. In rtcprobe runs at 20% UDP loss, upgrading only the consumer's pion took connections from 16/26 to 27/30. That's because of the dtls fixes for lost server flights; details in unbounded#478. Browser volunteers run Chrome's DTLS, so this repo is where the fix reaches users.

Changes

  • go.mod / go.sum:

    • broflake bumped to the pion upgrade: webrtc v4.2.25, ice v4.4.8, sctp v1.12.0, dtls v3.1.15.
    • pion moved to pion/transport/v5.
  • protocol/unbounded/net.go: rtcNet now implements transport/v5.Net. The method set is unchanged; only the package path moved.

  • option/unbounded.go: a new tuning option, a map of named overrides given as decimal strings.

  • protocol/unbounded/tuning.go: parses the map into broflake's WebRTCTuning:

    Key Overrides (pion default)
    ice_max_binding_requests ICE checks per candidate pair (7)
    stun_gather_timeout_ms per-STUN-server gather wait (5 s)
    ice_disconnected_timeout_ms / ice_failed_timeout_ms / ice_keepalive_interval_ms ICE liveness timers (5 s / 25 s / 2 s)
    srflx_acceptance_min_wait_ms wait before nominating a srflx pair (500 ms)
    dtls_retransmit_ms initial DTLS handshake retransmit (1 s, doubling)
    sctp_rto_max_ms SCTP retransmission timeout cap (60 s)
    sctp_max_receive_buffer_bytes SCTP receive buffer (1 MiB)

    Each key has a floor and a cap, kept in one table with its setter. Durations are capped at 10 minutes; floors stop pion retransmitting in a tight loop (e.g. dtls_retransmit_ms ≥ 100, sctp_rto_max_ms ≥ 1000, since a cap below pion's 1 s RTO floor becomes the RTO). ice_max_binding_requests is capped at 100 and the buffer is limited to 64 KiB–64 MiB. An out-of-range or non-numeric value keeps pion's default.
    A keepalive at or above the disconnected timeout (explicit, or pion's 5 s default) would let idle connections flap, so that combination drops all three ICE liveness overrides.

  • protocol/unbounded/outbound.go: applies the parsed tuning and logs any ignored keys.

Why a map. It's what makes tuning open-ended: unknown keys are ignored, not rejected, so the server can add knobs without breaking clients that have this option. Clients older than this PR reject the tuning field outright, though, because sing-box rejects unknown outbound fields. So the server must send it only to clients that advertise common.CapabilityUnboundedTuning (getlantern/common, companion PR), which radiance will advertise once it carries this version.

Testing

  • make test, as CI runs it: passes with no failures.
  • New protocol/unbounded/tuning_test.go:
    • every key parses to the right field and unit;
    • unknown keys, non-numbers, zero, negative, below-floor and over-limit values are ignored and the defaults kept;
    • a keepalive at or above the disconnected timeout drops the ICE liveness overrides;
    • an empty map is a no-op;
    • a guard test fails if any key is missing from the every-key test input.
  • Not tested: a live tuned connection from this repo. broflake's TestTunedPeersConnect covers a real tuned handshake.

Risk

Medium: a pion upgrade across ICE, DTLS and SCTP. With no tuning set, the only behaviour change is the new pion itself. With no loss, connect times are unchanged in rtcprobe. The riskiest file is net.go, because rtcNet routes every pion socket through sing-box, and its overrides must still be the ones pion calls. They are, and the build would fail otherwise.

How to revert

Revert the merge commit. Revert it before any server sends tuning to clients built from it.

Pre-PR review (local Codex gate)

  • Rounds: 1, at high reasoning effort — final: CODEX GATE: verdict=approve critical=0 important=0 minor=0 preexisting=0 reviewed=27
  • Reviewed at: 5058bec. Coverage included broflake's tuning code at the pinned version, both pion transport versions, and pion's setters.
  • Exit: approve
  • Step back: not needed
  • Fixed: none
  • Dismissed: none
  • Pre-existing (not introduced here, worth filing): none
  • Proposed AGENTS.md additions: none

🤖 Generated with Claude Code

https://claude.ai/code/session_019DnqgLJf7p4sK87dDvktjx

Summary by CodeRabbit

  • New Features
    • Added optional WebRTC tuning settings, allowing supported clients to customize connection limits and timeouts. Valid values are applied; unknown or invalid settings are ignored, preserving default behavior for those options.
    • This setting is compatible only with clients that advertise support for unbounded tuning, so older clients should not receive it.

Bumps broflake to the pion upgrade (webrtc v4.2.25, ice v4.4.8, sctp
v1.12.0, dtls v3.1.15), which moves pion to transport/v5, so rtcNet now
implements transport/v5.Net. The consumer is the DTLS server, and the
dtls fixes for lost server flights took rtcprobe runs at 20% UDP loss
from 16/26 to 27/30 connections with only the consumer upgraded.

The new tuning option carries broflake's WebRTCTuning as a map of named
decimal strings: ICE, DTLS and SCTP timers and limits. Unknown keys are
logged and ignored, so a server can add knobs without breaking older
clients; out-of-range values keep pion's default.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019DnqgLJf7p4sK87dDvktjx
@coderabbitai

coderabbitai Bot commented Oct 24, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

Warning

Review limit reached

Only developers with an assigned seat can use this organization's usage-based review budget, and seats here are assigned manually. Ask an admin to assign a seat, or change the review continuation mode in Billing.

Next included review available in 46 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

Learn how review limits work.

Review configuration:

Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: f6573222-51e9-4c53-a8a2-42328a38c963
Commits

Reviewing files that changed from the base of the PR and between 5058bec and 8f8a412.

Files ignored due to path filters: 1
  • go.sum is excluded by !**/*.sum
Files selected for processing: 3
  • go.mod
  • protocol/unbounded/tuning.go
  • protocol/unbounded/tuning_test.go

No actionable comments were generated in the recent review.

Recent review info
Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 69889c65-56f9-4b61-a704-db6f4c2218ad
Commits

Reviewing files that changed from the base of the PR and between d01ea47 and 5058bec.

Files ignored due to path filters: 1
  • go.sum is excluded by !**/*.sum
Files selected for processing: 6
  • go.mod
  • option/unbounded.go
  • protocol/unbounded/net.go
  • protocol/unbounded/outbound.go
  • protocol/unbounded/tuning.go
  • protocol/unbounded/tuning_test.go

Included review availability: This review used your included allowance. Your plan provides up to 1 included review per hour; 0 remain after this review.

Walkthrough

The changes upgrade Pion dependencies and add optional tuning overrides to Unbounded outbound options. The outbound setup parses and validates the overrides, applies valid values to WebRTC options, and logs ignored entries.

Changes: Unbounded tuning

Layer / File(s) Summary
Upgrade Pion transport dependencies
go.mod, protocol/unbounded/net.go
The project updates Pion Transport and related WebRTC dependencies. The Unbounded network imports now use Transport v5.
Parse and apply tuning overrides
option/unbounded.go, protocol/unbounded/tuning.go, protocol/unbounded/outbound.go, protocol/unbounded/tuning_test.go
UnboundedOutboundOptions adds an optional tuning map. parseTuning validates recognized decimal-string values, applies valid values, and returns unknown or invalid entries. NewOutbound assigns the parsed tuning and logs ignored entries. Tests cover all nine keys, invalid values, unknown keys, and nil input.

Priority: Normal

Estimated code review effort: 3 (Moderate) | ~20 minutes

Change: Bug fix

Sequence Diagram(s)

sequenceDiagram
  participant UnboundedOutboundOptions
  participant NewOutbound
  participant parseTuning
  participant WebRTCOptions
  UnboundedOutboundOptions->>NewOutbound: provide tuning map
  NewOutbound->>parseTuning: parse tuning values
  parseTuning-->>NewOutbound: return tuning and ignored entries
  NewOutbound->>WebRTCOptions: assign parsed tuning
Loading

Possibly related issues

  • Issue 2374: The PR adds a tuning field and defines how unknown and invalid tuning values are handled. It does not include the issue’s general serialization cleanup.
  • Issue 2470: The PR adds a signaling field that older clients reject and documents capability gating for sending it. It does not implement the proposed hard fork.
Merge Risk: Minimal · up to 5058b

No concrete merge-blocking issue is established. Complete normal testing and the planned dependency repin before merging.

Pre-merge checks: Passed 4 · Failed 1

Failed Failed checks: 1 warning

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 28.57% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 7 functions across 5 files. (1 skipped: 1… Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed Passed checks: 4 passed
Check name Status Explanation
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check Passed The title names the two changes in the PR: upgrading Unbounded's Pion dependencies (go.mod, net.go, and the WebRTC/transport module bumps) and accepting server-provided tuning (the new Tuning option, …
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Full details: Title check

Explanation

The title names the two changes in the PR: upgrading Unbounded's Pion dependencies (go.mod, net.go, and the WebRTC/transport module bumps) and accepting server-provided tuning (the new Tuning option, outbound.go parsing, and tuning.go/tuning_test.go). Both match the changeset, so the title is fully related to the main change. It uses 7 words and no file lists or vague terms.

Full details: Docstring Coverage

Explanation

Docstring coverage is 28.57% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 7 functions across 5 files. (1 skipped: 1 unsupported.)

Resolution

Write docstrings for the functions missing them to satisfy the coverage threshold.

Finishing Touches: 💡 1
📝 Generate docstrings: 💡
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔵 Needs a closer look

The coordinated networking-stack upgrade needs final human review after the upstream dependency merges and broflake is re-pinned and revalidated.

No open issues 🎉

What changed in this PR

Upgrades Unbounded’s Pion networking stack to improve handshake reliability under packet loss and adds server-provided tuning without requiring a client release for each adjustment.

Changes:

  • Updates broflake and Pion dependencies and migrates rtcNet to transport/v5.
  • Adds bounded tuning overrides that preserve defaults for unknown or invalid values.
  • Tests key mappings, invalid inputs, and empty configuration.
File Description
protocol/​unbounded/​tuning.go Parses and validates named tuning overrides.
protocol/​unbounded/​tuning_test.go Tests parsing, ignored values, and key coverage.
protocol/​unbounded/​outbound.go Applies tuning and logs ignored options.
protocol/​unbounded/​net.go Switches transport imports to v5.
option/​unbounded.go Exposes the tuning map and documents capability gating.
go.sum Updates dependency checksums.
go.mod Pins upgraded broflake and Pion dependencies.

Review effort: Balanced

@myleshorton
myleshorton marked this pull request as ready for review October 25, 2026 05:35
A tuning value of 1ms passed every key, so a single bad server value could
make pion retransmit DTLS flights every millisecond or set the SCTP RTO to
1ms (an RTO cap below pion's 1s floor becomes the RTO). Each key now has a
floor as well as a cap, kept in one table beside its setter.

A keepalive interval at or above the disconnected timeout, explicit or
pion's 5s default that broflake fills in, let idle connections go
disconnected between keepalives. That combination now drops the ICE
liveness overrides. ice_max_binding_requests is capped at 100 rather than
65535, ignored keys are sorted for stable logs, and the key-coverage test
checks each key rather than a count.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017Auq9rzNksZsxJYbVVZu4m

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔵 Needs a closer look

The coordinated transport upgrade warrants final human validation after broflake is re-pinned to the upstream merge commit.

No open issues 🎉

Review effort: Balanced

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017Auq9rzNksZsxJYbVVZu4m
@myleshorton
myleshorton merged commit 946ec53 into main Oct 25, 2026
3 checks passed
@myleshorton
myleshorton deleted the feat/unbounded-pion-latest branch October 25, 2026 06:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants