Skip to content

refactor(webtransport): maConn owns session#3498

Draft
paschal533 wants to merge 3 commits into
libp2p:mainfrom
paschal533:refactor/webtransport-session-ownership
Draft

refactor(webtransport): maConn owns session#3498
paschal533 wants to merge 3 commits into
libp2p:mainfrom
paschal533:refactor/webtransport-session-ownership

Conversation

@paschal533
Copy link
Copy Markdown
Contributor

@paschal533 paschal533 commented May 12, 2026

Summary

Supersedes #3489 (closed). Based on feedback from @tabcat, the WebTransport transport needs a structural refactor rather than a targeted patch.

The WebTransportSessionMultiaddrConnection now directly owns the WebTransport session, mirroring how RTCPeerConnectionMultiaddrConnection owns RTCPeerConnection in the WebRTC transport. The old approach stored the session in a closure inside dial() and passed a cleanUpWTSession callback to the maConn requiring a closed flag to coordinate five call sites racing to call wt.close().

Changes

session-to-conn.ts (rewritten to match WebRTC pattern):

  • webTransport: WebTransport field replaces the cleanUpWTSession callback
  • wt.closed.then/.catch wired in constructor, clean close → onTransportClosed(), error → abort(err), mirroring WebRTC's onconnectionstatechange
  • sendClose/sendReset call wt.close() directly with try/catch
  • sessionClosedByUs flag prevents false remote_close metric increments when the local side initiates the close

index.ts (simplified dial()):

  • Removed: WebTransportSessionCleanup type, cleanUpWTSession closure, closed flag, standalone wt.closed.then/.catch block
  • abortListener delegates to maConn.abort() when maConn exists, otherwise closes wt directly
  • Catch block guards against double metric-counting when the abort signal fires (timeout label already incremented by the listener)

muxer.ts (error handling from #3489, retained):

  • onCreateStream: catch DOMException from createBidirectionalStream(), abort both muxer and maConn before rethrowing, triggers full connection-manager cleanup chain
  • Incoming stream reader: same abort-on-failure pattern for the inbound path

test/muxer.spec.ts (new, from #3489):

  • Covers the createBidirectionalStream throw path
  • Covers the incoming stream reader failure path

Test plan

  • npx aegir test -t node, 2 muxer unit tests pass
  • TypeScript: npx tsc --noEmit, no errors
  • Manual: connect to a WebTransport peer, sleep the laptop, resume, connection is cleaned up from the connection manager

Closes #1982

… pattern

The WebTransport maConn now directly owns the WebTransport session,
mirroring how RTCPeerConnectionMultiaddrConnection owns RTCPeerConnection
in the WebRTC transport.

Before this change, the session lived in a closure inside dial() via a
cleanUpWTSession callback, requiring a closed flag to coordinate five
call sites that could all race to call wt.close(). The wt.closed
promise handlers were also wired in dial() rather than in the class
responsible for the connection lifecycle.

Changes:

session-to-conn.ts:
- Replace cleanUpWTSession callback with webTransport: WebTransport field
- Wire wt.closed.then/.catch in the constructor, mirroring WebRTC's
  onconnectionstatechange handler — clean close calls onTransportClosed(),
  error calls abort(err)
- sendClose/sendReset call wt.close() directly (with try/catch) instead
  of delegating to a closure
- sessionClosedByUs flag prevents incorrect remote_close metric
  increments when the local side initiates the close

index.ts:
- Remove WebTransportSessionCleanup type, cleanUpWTSession closure,
  closed flag, and the standalone wt.closed.then/.catch block
- abortListener delegates to maConn.abort() when maConn exists,
  otherwise closes wt directly
- Catch block guards against double metric-counting when the abort
  signal fired (timeout label already incremented by the listener)

muxer.ts:
- onCreateStream: catch DOMException from createBidirectionalStream()
  and call abort on both the muxer and maConn before rethrowing,
  triggering the full connection-manager cleanup chain
- Incoming stream reader: same abort-on-failure pattern for the
  inbound path

Closes libp2p#1982
@paschal533 paschal533 requested a review from a team as a code owner May 12, 2026 15:38
@paschal533 paschal533 changed the title refactor(transport-webtransport): align session lifecycle with WebRTC pattern fix(transport-webtransport): move WebTransport session ownership into maConn May 12, 2026
@paschal533 paschal533 changed the title fix(transport-webtransport): move WebTransport session ownership into maConn refactor(transport-webtransport): move session ownership into maConn May 12, 2026
@paschal533 paschal533 marked this pull request as draft May 12, 2026 16:23
…uxer.spec

- Move WebTransport import before @libp2p/interface to satisfy import/order
- Use method shorthand syntax for onSessionClose and createBidirectionalStream
  to satisfy @typescript-eslint/method-signature-style
@tabcat tabcat changed the title refactor(transport-webtransport): move session ownership into maConn refactor(webtransport): maConn owns session May 16, 2026
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.

WebTransport throws NetworkError when creating a new stream on a (very) old connection

1 participant