Skip to content

Retry a failed WebRTC upgrade (libdatachannel DTLS race) - #25

Merged
mkotelnikov merged 1 commit into
mainfrom
fix/webrtc-upgrade-retry
Oct 4, 2026
Merged

mkotelnikov merged 1 commit into
mainfrom
fix/webrtc-upgrade-retry

Conversation

@mkotelnikov

Copy link
Copy Markdown
Contributor

Problem

httpeers-conformance failed under CPU load: in most runs with every core busy, and often in the full parallel suite. Members fell back to their relay link (tests pinning direct failed), and calls to such members were reset (PeerStreamResetError), because members do not serve over a circuit.

Root cause

Traced through libp2p's and libdatachannel's own logs. Under Node, WebRTC is libdatachannel (node-datachannel). On the offerer, libdatachannel ≤ 0.24.5 hands the remote answer to the ICE agent before committing it as the remote description. ICE can complete immediately (the answerer has been sending checks), DTLS starts, and the fingerprint check finds no remote description:

DTLS alert: unknown CA
DTLS recv: Handshake failed: ... certificate verify failed

The peer connection fails and libp2p's dial times out. Fixed upstream in libdatachannel 0235225 ("fix: start DTLS after remote description", PR #1612), not yet in any node-datachannel release (0.33.4 bundles 0.24.5). Browsers are not affected.

Fix

dialWebRTC (httpeers-libp2p) tries a WebRTC upgrade up to 3 times; each attempt is an independent race. Used by reachHub, preDialPeer and the route ensurer. A WebRTC path that cannot come up still fails every attempt, and the relay fallback runs as before. Remove once node-datachannel ships the upstream fix.

Verification

  • Conformance under full CPU load (8 busy cores): 8/8 runs green (4/6 failed before).
  • Full parallel pnpm -r run test: 3/3 green (2–3 of 4 failed before).
  • Unit tests for dialWebRTC (retries, then rethrows the last failure).

Releases httpeers-libp2p 0.1.4 and httpeers-member 0.1.5 (published to npm before merge).

🤖 Generated with Claude Code

https://claude.ai/code/session_01DAiZN6XrTAdQpNN3eXEz2U

The httpeers-conformance tests failed under CPU load (most runs with
every core busy; often in the full parallel suite): members fell back to
the relay link, and calls to them were reset.

Root cause, traced with libdatachannel's own logs: on the OFFERER,
libdatachannel <= 0.24.5 hands the remote answer to the ICE agent before
committing it. ICE can complete at once (the answerer has been sending
checks), DTLS starts, and the fingerprint check finds no remote
description: "DTLS alert: unknown CA", "certificate verify failed", the
peer connection fails and libp2p's dial times out. Fixed upstream by
libdatachannel 0235225 ("start DTLS after remote description"), not yet
in any node-datachannel release (0.33.4 bundles 0.24.5). Browsers
implement WebRTC themselves and are not affected.

dialWebRTC (httpeers-libp2p) tries a WebRTC upgrade up to 3 times; each
attempt is an independent race. reachHub, preDialPeer and the route
ensurer use it. A WebRTC path that cannot come up still fails every
attempt and the relay fallback runs as before. Remove the retry once
node-datachannel ships the upstream fix.

Verified: conformance under full CPU load 8/8 runs green (4/6 failed
before); the full parallel suite 3/3 green (2-3/4 failed before).
httpeers-libp2p 0.1.4, httpeers-member 0.1.5.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DAiZN6XrTAdQpNN3eXEz2U
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.

1 participant