Skip to content

Upgrade pion and make its ICE, DTLS and SCTP defaults tunable - #478

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

myleshorton merged 2 commits into
mainfrom
feat/pion-latest

Conversation

@myleshorton

@myleshorton myleshorton commented Oct 24, 2026 •

Copy link
Copy Markdown
Contributor

Upgrades pion to the latest releases, and adds WebRTCOptions.Tuning so the server can tune pion's ICE, DTLS and SCTP defaults per track instead of per release.

Module Before After
pion/webrtc/v4 v4.2.11 v4.2.25
pion/ice/v4 v4.2.2 v4.4.8
pion/sctp v1.9.4 v1.12.0
pion/dtls/v3 v3.1.2 v3.1.15
pion/transport v4.0.1 v5.1.1

Builds on #477 (-dtls-retransmit for rtcprobe, now merged). Rebased onto main: the two commits are unchanged apart from the base, which now includes #477's review fix.

Why

About 27% of volunteer attempts reach "ICE connected" and then stall before the data channel opens. Our consumer makes the offer, so it's the DTLS server. Several pion fixes since v3.1.2 target exactly that side on lossy paths:

  • dtls v3.1.12: "Retransmit server flight on repeated CH";
  • dtls v3.1.9: "Reassemble re-fragmented handshake retransmits";
  • dtls v3.1.4: "Fix handshake hang on Finish in retransmit state".

On the ICE side:

  • ice v4.4.2: "Retransmit STUN binding requests per RFC 5389";
  • ice v4.2.3: "Match libwebrtc's nomination attribute".

Evidence

These are rtcprobe runs from Frankfurt to Newark, with UDP loss on both hosts and a 15 s window.

Same pion on both ends, at 20% loss: v3.1.2 connected 10/20 with 5 DTLS stalls; the latest connected 17/20 with 1. Across every lossy run, DTLS stalls fell from 21 to 7, and connections rose from 82 to 97, out of 120.

Mixed versions, 20% loss, with the probe as consumer and DTLS server:

Consumer pion Other side Connected DTLS stalls
old old 16/26 6
old new 22/30 4
new old 27/30 1
new new 25/30 2

So the gain comes from upgrading the consumer; browser volunteers run Chrome's DTLS and don't need to change. Separately, a 200 ms DTLS retransmit at 20% loss cut the median DTLS time after ICE from about 1.2 s to about 0.4 s. That's the first knob worth tuning live.

Changes

  • Commit 1: the pion upgrade.

    • go.mod / go.sum: the bumps above, with go mod tidy.
    • clientcore/settings.go, webrtc_api.go, webrtc_api_js.go: pion moved to transport/v5, so WebRTCOptions.Net is now a transport/v5.Net. This breaks the build of anything that implements Net. lantern-box does, and its companion migration builds and passes its tests against this branch.
  • Commit 2: WebRTCOptions.Tuning (clientcore/tuning*.go, applied in consumer.go and producer.go). It overrides pion's defaults on native consumers and producers. A zero field keeps the default, so the zero value changes nothing; browsers ignore it, since their stack can't be tuned.

    Field pion default
    ICEMaxBindingRequests 7
    STUNGatherTimeout 5 s
    ICEDisconnectedTimeout / ICEFailedTimeout / ICEKeepaliveInterval 5 s / 25 s / 2 s (setting any one sets all three)
    SrflxAcceptanceMinWait 500 ms
    DTLSRetransmitInterval 1 s, doubling
    SCTPRTOMax 60 s
    SCTPMaxReceiveBuffer 1 MiB

    lantern-box will carry these as an open-ended tuning map that ignores unknown keys. Once a client supports it, the server can add knobs without further client changes, and lantern-cloud can send it to the clients that advertise support.

Testing

  • go test -race ./clientcore/... ./common/... ./freddie/... ./rtcprobe/... ./egress/...: ok. New clientcore tests:
    • the zero tuning sets nothing;
    • each field counts as set;
    • a consumer and a producer with every knob set really connect and open a data channel.
  • go build ./... and GOOS=js GOARCH=wasm go build ./cmd: ok. Each commit builds and tests on its own.
  • lantern-box against this branch: builds, and its unbounded and tuning tests pass.
  • The rtcprobe loss runs above.

Risk

Medium, because this is a dependency upgrade across ICE, DTLS and SCTP.

  • Riskiest change: the transport/v5 move, a compile-time break for implementers of Net. The lantern-box companion covers it.
  • Behaviour: with no loss, connect times match the old pion. The default SCTP MTU drops to 1,191, which only lowers the payload per packet. Tuning is a no-op unless set.
  • Rollout:
    • The widget rebuilds on merge, but its DTLS is Chrome's.
    • Freddie and the egress get the new pion with their next bump.
    • Consumers get the fix with a Lantern release that includes the lantern-box PR.

How to revert

Revert the merge commit, and the lantern-box companion if it has merged, since it needs the transport/v5 Net and WebRTCTuning.

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=53
  • Reviewed at: 7cc9e9d, which is eebf937 before the rebase onto main (no conflicts, same diff). It checked each tuning knob against its pion setter and default, read lantern-box's net.go, outbound.go and tuning.go, and compared both pion versions in the module cache.
  • Exit: approve
  • Step back: not needed
  • Fixed: none in this round. An earlier draft of this branch had an upgrade commit that didn't build on its own; the commits were rebuilt so each one does.
  • Dismissed, carried from the earlier review of the upgrade commit:
    • clientcore/settings.go:13 — transport/v5 breaks lantern-box's v4 rtcNet. This is a coordinated migration: lantern-box's feat/unbounded-pion-latest moves rtcNet to v5 and is tested against this branch. An adapter would only postpone the same change.
  • 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 controls for ICE, STUN, DTLS, and SCTP settings on native builds. Positive values customize transport behavior; unset values preserve defaults.
    • Applied tuning options to both consumer and producer connections. WebAssembly builds remain unchanged.

Copilot AI balanced review requested due to automatic review settings October 24, 2026 16:06
@coderabbitai

coderabbitai Bot commented Oct 24, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

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: 0359688e-0ab6-4d99-986f-605b2092b646
Commits

Reviewing files that changed from the base of the PR and between 0a80b31 and eebf937.

Files ignored due to path filters: 1
  • go.sum is excluded by !**/*.sum
Files selected for processing: 10
  • clientcore/consumer.go
  • clientcore/producer.go
  • clientcore/settings.go
  • clientcore/tuning.go
  • clientcore/tuning_native.go
  • clientcore/tuning_test.go
  • clientcore/tuning_wasm.go
  • clientcore/webrtc_api.go
  • clientcore/webrtc_api_js.go
  • go.mod

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 pull request adds WebRTCTuning to configure ICE, STUN, DTLS, and SCTP settings. Consumer and producer setup now pass tuning to Pion. Native and WebAssembly builds use platform-specific implementations.

Changes: WebRTC transport tuning

Layer / File(s) Summary
Tuning contract and platform behavior
clientcore/tuning.go, clientcore/tuning_native.go, clientcore/tuning_wasm.go, clientcore/tuning_test.go, go.mod
Adds tuning fields and ICE timer defaults. Native builds apply positive tuning values; WebAssembly leaves the setting engine unchanged. Tests cover zero values and individual tuning fields. Pion dependencies are upgraded.
Tuning in consumer and producer setup
clientcore/settings.go, clientcore/consumer.go, clientcore/producer.go, clientcore/webrtc_api.go, clientcore/webrtc_api_js.go, clientcore/tuning_test.go
Adds tuning to WebRTCOptions and passes it into consumer API and producer peer-connection setup. The integration test checks that tuned peers open a data channel.

Priority: Normal

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

Change: Feature

Possibly related PRs

  • getlantern/unbounded#477: Adds DTLS retransmission tuning to Pion SettingEngine instances in rtcprobe; this pull request adds the corresponding setting to consumer and producer WebRTC setup.

Suggested reviewers: noahlevenson

Merge Risk: Minimal · up to eebf9

No merge-blocking issue was established for this change; it is ready for normal checks.

Pre-merge checks: Passed 4 · Failed 1

Failed Failed checks: 1 warning

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 18.18% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 11 functions across 9 files. (1 skipped: … 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 clearly and concisely summarizes the two main changes: upgrading Pion and adding tunable ICE, DTLS, and SCTP defaults.
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: Docstring Coverage

Explanation

Docstring coverage is 18.18% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 11 functions across 9 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 multi-layer protocol upgrade and coordinated breaking transport/v5 migration require final human validation of downstream compatibility and network behavior.

No open issues 🎉

What changed in this PR

Upgrades the Pion WebRTC stack to improve connections on lossy networks and adds configurable transport tuning for native consumers and producers, following the rtcprobe work in #477.

Changes:

  • Updates Pion dependencies and migrates the public network interface to transport/v5.
  • Adds ICE, DTLS, and SCTP tuning options; zero values preserve defaults, and browser builds ignore tuning.
  • Adds tests for tuning activation and a tuned peer-to-peer data-channel handshake.
File Description
go.sum Updates dependency checksums for the upgraded stack.
go.mod Upgrades Pion modules and related dependencies.
clientcore/​webrtc_api.go Applies native tuning and adopts transport v5.
clientcore/​webrtc_api_js.go Aligns the browser helper signature and transport import.
clientcore/​tuning.go Defines tuning options and ICE fallback defaults.
clientcore/​tuning_wasm.go Makes tuning a no-op in browser builds.
clientcore/​tuning_test.go Tests tuning activation and data-channel connectivity.
clientcore/​tuning_native.go Maps tuning options to Pion settings.
clientcore/​settings.go Exposes tuning through WebRTCOptions.
clientcore/​producer.go Applies tuning when creating producer connections.
clientcore/​consumer.go Passes consumer tuning into API creation.

Review effort: Balanced

myleshorton and others added 2 commits October 24, 2026 17:17
webrtc v4.2.11 -> v4.2.25, ice v4.2.2 -> v4.4.8, sctp v1.9.4 -> v1.12.0,
dtls v3.1.2 -> v3.1.15. pion moved to transport/v5, so clientcore's Net
option is now a transport/v5.Net.

The DTLS fixes matter for our consumers, which are the DTLS server: dtls
v3.1.12 retransmits the server flight when the client repeats its
ClientHello, and v3.1.9 reassembles re-fragmented handshake retransmits.
In rtcprobe runs at 20% UDP loss with only the consumer upgraded,
connections went from 16/26 to 27/30 and DTLS stalls from 6 to 1.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019DnqgLJf7p4sK87dDvktjx
WebRTCOptions.Tuning overrides, on native consumers and producers:
ICE's binding-request cap, STUN gather timeout, liveness timers and srflx
nomination wait; DTLS's initial handshake retransmission interval; and
SCTP's maximum retransmission timeout and receive buffer. A zero field
keeps pion's default, so the zero value changes nothing, and browsers,
whose stack can't be tuned, ignore it.

These are the knobs our failure buckets point at, and having them in
options lets the server tune them per track instead of per release. In
rtcprobe runs at 20% UDP loss, a 200ms DTLS retransmit cut the median
DTLS time after ICE from about 1.2s to 0.4s.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019DnqgLJf7p4sK87dDvktjx
@myleshorton
myleshorton changed the base branch from feat/rtcprobe-dtls-rtx to main October 24, 2026 23:20
@myleshorton
myleshorton merged commit ae5d221 into main Oct 25, 2026
4 checks passed
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