Skip to content

[Tracking] WebRTC ICE as a second Runtime Host direct path #4382

Description

@M4n5ter
English

Outcome

Add WebRTC ICE as an experimental second direct upgrade inside Maka's existing native Runtime Host peer endpoint.

This is not a second Remote product, peer network, identity, application protocol, or fallback authority. The existing Rust libp2p Swarm, PeerId, Runtime Host credential/Root ID checks, QUIC/DCUtR path, and approved Peer Mesh member transit remain canonical.

This tracker follows the completed Peer Mesh work in #3842. Phase 0 is complete and yields a bounded GO for implementation.

User result

When two authenticated Maka peers can coordinate over Circuit Relay v2 and WebRTC ICE can establish a direct path that QUIC/DCUtR cannot, Maka may use the WebRTC direct connection automatically. Existing direct paths and approved member transit remain available. Users see direct/transit/unreachable state, not a protocol selector.

Phase 0 evidence

The complete source, locked dependencies, Docker topology, JS conformance peer, reproduction commands, results, and limitations are published at:

Decision-relevant results:

Controlled topology/check DCUtR WebRTC Meaning
Two UDP-cone NATs, TCP coordination relay 0/10 10/10 Decisive incremental topology
Double UDP-cone NAT, TCP coordination relay failed succeeded Increment survives an extra NAT layer
Same double NAT, QUIC coordination relay 175 ms 1,033 ms WebRTC must not replace a faster existing path
Symmetric NAT pair failed failed Approved transit or honest failure remains necessary
UDP blocked failed failed No TURN coverage is claimed
Double NAT, WAN profile, old webrtc 0.20.4 12/13 Reproduced a post-connect first-stream tail failure
Same WAN profile, exact fixed revision 20/20 Supports the temporary dependency pin

The controlled topology uses two isolated private networks, independent conntrack/NAT routers, a separate TCP Circuit Relay v2 coordination node, and STUN. It explicitly rejects cross-private routing so Docker host routing cannot create an accidental LAN path.

Two independent 60-second samples of Maka's existing dynamic relay discovery, one on macOS and one on Linux, selected four active reservations; all four selected routes were TCP. This is not a population estimate. It only establishes that TCP-only coordination is a real product topology rather than a Docker-only premise.

The prototype also passed:

  • standard /webrtc-signaling/0.0.1 interoperability in both directions with libp2p 3.3.10 / @libp2p/webrtc 6.0.31;
  • authenticated expected PeerId and intact application echo after closing the relayed connection;
  • explicit cancellation while preserving the existing CRv2 path;
  • Rust 1.98 fmt, clippy with warnings denied, six focused tests, and ASF license checks;
  • native Linux x64 build/run, macOS arm64 run, macOS x64 compile, Linux arm64 link, and Windows x64 GNU link.

Synthetic NAT evidence is not a claim about public-network success rates. Native Windows load/stop, real household/mobile/IPv6/interface-change samples, packaged artifact/RSS, and integrated teardown remain implementation gates.

Frozen architecture decisions

  1. One connection authority. native/runtime-host-peer remains the only production peer endpoint and owns the direct-path attempt lifecycle.
  2. One identity. WebRTC uses the same local PeerId. The expected remote PeerId comes from the existing Noise-authenticated signaling connection; the WebRTC SDP fingerprint is verified by DTLS before the new connection is admitted. DTLS identity does not become a Maka identity.
  3. One application protocol. Runtime Host framing, compatibility, credential, Root ID, Session authority, grants, and backpressure do not vary by path.
  4. Standard signaling. Use /webrtc-signaling/0.0.1 over the already authenticated CRv2 connection. Do not invent a Maka signaling service or private wire protocol.
  5. WebRTC is an untrusted route until verified. Only a completed, expected-PeerId connection that can open the existing application stream may win.
  6. Race or preserve existing direct paths. WebRTC supplements QUIC/DCUtR; it does not replace it. When multiple authenticated direct candidates are already established, Maka ranks them deterministically (QUIC → TCP → WebRTC → other direct); one application stream commits once and closes the losers. Callback timing does not choose between simultaneously available paths.
  7. Fallback authority is unchanged. External/public CRv2 nodes coordinate hole punching; they do not carry Runtime Host application streams. Only an explicitly approved Mesh member may provide application transit.
  8. No replay or live migration. Path loss closes the affected connection and uses canonical recovery. Result-unknown mutations are never silently resent.
  9. Ephemeral route state. SDP and ICE candidates are bounded, memory-only, redacted from diagnostics, and removed with the attempt. They do not enter Mesh identity, invitations, or durable state.
  10. No protocol UX. Normal UI exposes connecting/direct/member transit/unreachable. Protocol and bounded failure reason belong only in advanced diagnostics.
  11. STUN only in this scope. Product defaults require provider/license review, no-SLA disclosure, disable/override controls, and a total gathering deadline. TURN, central signaling, Maka-operated relay, and WebSocket relay are separate feature decisions.
  12. JavaScript is a test oracle only. The JS peer independently checks standard interoperability. A production JS sidecar would duplicate Swarm, PeerId, connection manager, lifecycle, resource limits, and packaging authority, so it is rejected.
  13. No speculative framework. Do not add a general transport registry, route-policy DSL, second reconnect loop, or generic provider abstraction for this feature.

Dependency decision

Formal implementation may temporarily pin:

webrtc = git revision e132552fc67b84c30e63c5ce916a9a63e2484b6f
└── rtc revision 7df0a825c53155850b4e76dda03815c9902a801f

webrtc v0.21.0-rc.1 is not sufficient: its rtc submodule is 51558ffb..., before rtc#226 and rtc#228. The latter matches the reproduced post-connect DataChannel readiness failure (rtc#227). The exact pin is reproducible and includes the fix. Replace it with the first published release containing those commits as a dependency-only follow-up; never track a floating branch.

Implementation status (2026-09-01)

The implementation is split into four reviewable layers:

  1. refactor(runtime-host): fence peer connection attempts #4403 — shared, fenced direct-attempt lifecycle.
  2. feat(runtime-host): accept WebRTC direct upgrades #4404 — bounded native WebRTC direct upgrade on the existing Swarm and PeerId.
  3. feat(runtime-host): race WebRTC direct upgrades #4405 — adaptive QUIC/TCP/WebRTC race with one application-stream commit.
  4. feat(desktop): surface adaptive peer connectivity #4406 — Desktop/managed-Host policy, diagnostics, disclosure, and UX closure.

Exact verification evidence and affected-suite results live in each PR body; the Phase 0 evidence above remains the immutable architecture baseline.

Stacked delivery

PR 1 — Direct-attempt authority

  • Reuse or minimally complete the existing closed attempt lifecycle: immutable target, deadline, cancellation, one winner, stale-result rejection.
  • Preserve current behavior; skip this PR if main already provides the complete seam.
  • High-value tests: one winner; cancellation reclaims children; a stale result cannot commit; direct failure does not damage transit.

PR 2 — Experimental native WebRTC direct upgrade

  • Add the chosen Rust WebRTC implementation inside runtime-host-peer.
  • Implement bounded standard signaling, fingerprint/PeerId binding, DataChannel byte adaptation, capability negotiation, explicit close/cancel, and stable reason codes.
  • Developer/experimental only; no Desktop UI, TURN, or durable Mesh schema.
  • High-value tests: bounds/identity mismatch; existing application stream over WebRTC; old peer skips safely; shutdown leaves no task.

PR 3 — Adaptive direct-path race

  • Run QUIC/DCUtR and WebRTC direct attempts under the same attempt authority without serial timeout stacking.
  • Preserve current member-transit timing and admission; rank simultaneously established direct candidates deterministically and commit one application stream once.
  • Add bounded winning-route diagnostics; no live migration or mutation replay.
  • High-value tests: winner cancels loser; WebRTC hang cannot delay fallback; both direct failures still permit approved transit.

PR 4 — Desktop UX and evidence closure

  • Surface direct/member-transit/unreachable state and immediate cancellation; protocol details remain advanced diagnostics.
  • Explain STUN metadata/no-SLA behavior and offer disable/custom controls without exposing a persistent WebRTC protocol toggle.
  • Provide before/after screenshots and real macOS/Windows/Linux evidence.
  • Tests cover state projection and cancellation only; do not test animations or duplicate wording.

Acceptance gates

  • Same Swarm and PeerId; no second identity, authority, or durable route state.
  • WebRTC failure, timeout, cancellation, sleep/wake, and losing-race cleanup do not delay or corrupt QUIC/transit.
  • Bounded signaling/candidate/message resources and redacted diagnostics.
  • macOS arm64, Windows x64, Linux x64/arm64 packaged helper build/load/stop smoke.
  • License, NOTICE, source-release, provenance, and SBOM closure for the exact git dependency.
  • Real-network matrix records mutually exclusive DCUtR/WebRTC outcomes and connect latency; NAT success-rate tests stay out of flaky CI.

Explicitly out of scope

TURN; Maka-operated relay/signaling; production js-libp2p; a second Swarm or PeerId; browser clients; media/SFU; live stream migration; automatic replay; generic transport/plugin policy; protocol selector UI; new account/identity/grant authority.

Reopen architecture review when

  • adding TURN, a central service, or a new application-traffic relay;
  • introducing another Swarm, identity, durable route authority, or signaling wire;
  • changing Runtime Host application/resource authority by transport;
  • attempting live migration or automatic replay;
  • making WebRTC the sole/direct-path replacement rather than a bounded second attempt.
中文

结论

在 Maka 现有 native Runtime Host peer endpoint 内增加 WebRTC ICE,作为实验性的第二条直连升级路径

它不是第二套 Remote 产品、Peer 网络、身份、应用协议或 fallback authority。现有 Rust libp2p Swarm、PeerId、Runtime Host credential/Root ID 校验、QUIC/DCUtR 路径和已批准的 Peer Mesh 成员转发仍是唯一权威。

本 tracker 承接已完成的 #3842。Phase 0 已结束,结论是允许按下述边界开始实现。

用户结果

当两个已认证的 Maka peer 能通过 Circuit Relay v2 协调,且 WebRTC ICE 能建立 QUIC/DCUtR 无法建立的直连时,Maka 可以自动使用该 WebRTC 直连。已有直连和获批成员转发继续存在。用户看到的是直连/成员转发/不可达,而不是协议选择器。

Phase 0 证据

完整源码、锁定依赖、Docker 拓扑、JS 协议对照 peer、复现命令、结果与局限已发布:

影响决策的结果:

受控 topology/检查 DCUtR WebRTC 含义
双 UDP-cone NAT、TCP coordination relay 0/10 10/10 决定性的增量 topology
双层 UDP-cone NAT、TCP coordination relay 失败 成功 多一层 NAT 后增量仍可复现
相同双层 NAT、QUIC coordination relay 175 ms 1,033 ms WebRTC 不能替换更快的既有路径
双 symmetric NAT 失败 失败 仍需获批 transit 或诚实失败
UDP blocked 失败 失败 不宣称 TURN 覆盖
双层 NAT + WAN profile,旧 webrtc 0.20.4 12/13 复现 Connected 后首 stream 尾部失败
相同 WAN profile,精确修复 revision 20/20 支持临时依赖 pin

受控环境包含两个隔离私网、独立 conntrack/NAT router、单独 TCP Circuit Relay v2 协调节点和 STUN;它显式拒绝两个私网之间的路由,避免 Docker host 路由泄漏把测试变成伪 LAN。

另外分别在 macOS 和 Linux 上运行当前 Maka 动态 relay discovery 60 秒,两次共选出四条 active reservation,四条均为 TCP。这不是公网 pool 的比例统计;它只证明 TCP-only coordination 是真实产品 topology,而不是 Docker 人造前提。

prototype 还通过:

  • libp2p 3.3.10 / @libp2p/webrtc 6.0.31 双向标准 /webrtc-signaling/0.0.1 互操作;
  • 认证 expected PeerId,并在关闭 relay connection 后通过 WebRTC 完整 echo 现有应用协议;
  • 显式取消后既有 CRv2 path 仍可用;
  • Rust 1.98 fmt、clippy 零警告、六个聚焦测试和 ASF license check;
  • Linux x64 原生 build/run、macOS arm64 运行、macOS x64 compile、Linux arm64 link、Windows x64 GNU link。

合成 NAT 证据不等于公网成功率结论。Windows 原生 load/stop、真实家庭/移动/IPv6/网卡切换、打包后 artifact/RSS 和集成 teardown 仍是实现阶段 gate。

冻结的架构决策

  1. 一个 connection authority。 native/runtime-host-peer 仍是唯一生产 peer endpoint,并拥有 direct attempt lifecycle。
  2. 一个身份。 WebRTC 使用同一 local PeerId。expected remote PeerId 来自既有 Noise-authenticated signaling connection;SDP fingerprint 经 DTLS 验证后才能准入新 connection。DTLS identity 不成为 Maka 身份。
  3. 一个应用协议。 Runtime Host framing、compatibility、credential、Root ID、Session authority、grant 和 backpressure 不随路径分叉。
  4. 标准 signaling。 在已认证 CRv2 connection 上使用 /webrtc-signaling/0.0.1,不发明 Maka signaling service 或私有 wire。
  5. 验证前 WebRTC 只是非可信 route。 只有完成 expected-PeerId 验证并能打开现有应用 stream 的 connection 才能获胜。
  6. 竞速或保留既有直连。 WebRTC 补充而不替换 QUIC/DCUtR。当多个已认证 direct candidate 已同时建立时,Maka 按 QUIC → TCP → WebRTC → 其他直连 确定性排序;唯一 application stream 只提交一次并关闭 loser,不能由 callback 时序决定同时可用路径之间的胜负。
  7. fallback authority 不变。 外部/公共 CRv2 节点只协调打洞,不承载 Runtime Host application stream;只有明确批准的 Mesh member 可提供应用流量转发。
  8. 不 replay、不 live migrate。 路径断开后关闭受影响 connection 并使用 canonical recovery;结果未知的 mutation 绝不静默重发。
  9. 临时 route state。 SDP/ICE candidate 有界、只在内存、诊断脱敏并随 attempt 删除;不进入 Mesh identity、invitation 或 durable state。
  10. 无协议 UX。 普通 UI 只显示连接中/直连/成员转发/不可达;协议和有界失败原因仅在高级诊断。
  11. 本范围只有 STUN。 产品默认节点必须经过 provider/license 审查,明确无 SLA,允许关闭/覆盖,并受总收集 deadline 约束。TURN、中心 signaling、Maka 运营 relay 和 WebSocket relay 都是独立 feature 决策。
  12. JavaScript 只做测试 oracle。 JS peer 独立验证标准互操作。生产 JS sidecar 会重复 Swarm、PeerId、connection manager、lifecycle、resource limit 和 packaging authority,因此拒绝。
  13. 不造投机框架。 不为本功能增加通用 transport registry、route-policy DSL、第二 reconnect loop 或通用 provider abstraction。

依赖决策

正式实现可以暂时精确 pin:

webrtc = git revision e132552fc67b84c30e63c5ce916a9a63e2484b6f
└── rtc revision 7df0a825c53155850b4e76dda03815c9902a801f

webrtc v0.21.0-rc.1 不够:它的 rtc submodule 是 51558ffb...,早于 rtc#226rtc#228。后者与已复现的 Connected 后 DataChannel readiness 失败吻合(rtc#227)。精确 pin 可复现且包含修复。首个含这些提交的正式版本发布后,用纯依赖 follow-up 切回 release;禁止跟随浮动 branch。

实现状态(2026-09-01)

实现已拆成四个可独立审查的层次:

  1. refactor(runtime-host): fence peer connection attempts #4403 — 共享且带 fence 的 direct-attempt lifecycle。
  2. feat(runtime-host): accept WebRTC direct upgrades #4404 — 在既有 Swarm/PeerId 上加入有界 native WebRTC direct upgrade。
  3. feat(runtime-host): race WebRTC direct upgrades #4405 — QUIC/TCP/WebRTC 自适应竞速与唯一 application-stream 提交。
  4. feat(desktop): surface adaptive peer connectivity #4406 — Desktop/managed Host 策略、诊断、披露与 UX 闭环。

各 PR body 记录精确验证证据和受影响测试结果;上面的 Phase 0 证据仍是不可变的架构基线。

Stacked 实现

PR 1 — Direct-attempt authority

  • 复用或最小补齐当前 closed attempt lifecycle:immutable target、deadline、cancel、唯一 winner、stale result 拒绝。
  • 保持现有用户行为;如果 main 已完整具备 seam,则跳过该 PR。
  • 高价值测试:唯一 winner;取消回收所有 child;stale result 不得提交;direct failure 不破坏 transit。

PR 2 — 实验性 native WebRTC direct upgrade

  • runtime-host-peer 内加入选定的 Rust WebRTC 实现。
  • 实现有界标准 signaling、fingerprint/PeerId binding、DataChannel byte adaptation、capability negotiation、显式 close/cancel 和稳定 reason code。
  • 仅 developer/experimental;不加 Desktop UI、TURN 或 durable Mesh schema。
  • 高价值测试:bounds/identity mismatch;WebRTC 上运行现有 application stream;旧 peer 安全跳过;shutdown 无遗留 task。

PR 3 — 自适应 direct race

  • 让 QUIC/DCUtR 和 WebRTC direct attempt 处于同一 authority,不串行叠加 timeout。
  • 保持当前 member-transit 时机和 admission;对同时建立的 direct candidate 做确定性排序,并让唯一 application stream 只提交一次。
  • 加入有界 winning-route diagnostics;不做 live migration 或 mutation replay。
  • 高价值测试:winner 取消 loser;WebRTC hang 不拖延 fallback;两个 direct 都失败时仍可走获批 transit。

PR 4 — Desktop UX 与证据闭环

  • 展示直连/成员转发/不可达和立即取消;协议细节只进入高级诊断。
  • 诚实说明 STUN 网络元数据/无 SLA,并提供关闭和自定义,不暴露持久 WebRTC 协议开关。
  • 提供 before/after 截图和真实 macOS/Windows/Linux 证据。
  • 测试只覆盖状态投影和取消,不测动画或重复文案。

验收 gate

  • 同一 Swarm/PeerId;无第二 identity、authority 或 durable route state。
  • WebRTC failure/timeout/cancel/sleep-wake/losing-race cleanup 不延迟或污染 QUIC/transit。
  • signaling/candidate/message 资源有界,诊断脱敏。
  • macOS arm64、Windows x64、Linux x64/arm64 打包 helper build/load/stop smoke。
  • 精确 git dependency 的 license、NOTICE、source-release、provenance 和 SBOM 闭合。
  • 真实网络矩阵记录互斥 DCUtR/WebRTC 结果和建连时延;NAT 成功率测试不进入 flaky CI。

明确不做

TURN;Maka 运营 relay/signaling;生产 js-libp2p;第二 Swarm/PeerId;browser Client;媒体/SFU;live stream migration;自动 replay;通用 transport/plugin policy;协议选择 UI;新的账号/身份/grant authority。

以下情况必须重开架构审查

  • 增加 TURN、中心服务或新的 application-traffic relay;
  • 引入第二 Swarm、identity、durable route authority 或 signaling wire;
  • 让 transport 改变 Runtime Host application/resource authority;
  • 尝试 live migration 或自动 replay;
  • 把 WebRTC 变成唯一/替代式 direct path,而不是有界第二 attempt。

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions