Files
2026-05-27 23:47:53 +01:00

12 KiB

@suaveplan/drive-transport-webrtc - WebRTC datachannel transport for the drive mesh. Implements DriveTransport over @suaveplan/drive-webrtc's WebRTCClient + DataChannelManager with a length-prefixed binary framing protocol.

Summary

WebRTC datachannel transport for the drive mesh. Implements the canonical DriveTransport interface from @suaveplan/drive-mesh over a @suaveplan/drive-webrtc WebRTCClient + DataChannelManager pair, multiplexing chunk requests, chunk responses, and presence advertisements over a single named data-channel label per peer.

This package re-exports DriveTransport / ChunkAdvertisement / AdvertisementHandler / Unsubscribe from @suaveplan/drive-mesh — there is no local interface mirror. A drive-mesh DriveMesh instance slots a WebRTCDriveTransport into its transport plane and consumes this transport's requestChunk / advertise / onAdvertisement / peers surface directly. For the HTTPS / server-fallback path, mesh ships its own built-in ServerFallback (no separate transport package).

Documentation tree

  • error-codes — Defines the typed error-code registry and DriveTransportWebRtcError class used by every public boundary of `@suavepla…
    • error-codes — Defines the typed error-code registry and DriveTransportWebRtcError class used by every public boundary of `@suavepla…
  • frame — (no submodules)
    • frame — (no submodules)
  • schemas — (no submodules)
  • webrtc-transport — (no submodules)
    • bitset-codec — Provides the gzip codec used to compress advertisement bitsets before they hit the wire. Bitsets describing which chunk…
    • hex — Boundary helpers converting between the on-the-wire 32-byte file id representation and the hex-encoded form used by eve…
    • payload-codec — Implements the byte-level encoder/decoder for the two structured frame bodies the WebRTC drive transport carries: chunk…
    • webrtc-transport — (no submodules)
- [frame](./src/framing/frame/frame.md) — _(no submodules)_- [schemas](./src/schemas/frame.schemas.md) — _(no submodules)_- [frame.schemas](./src/schemas/frame.schemas.md) — _(no submodules)_- [webrtc-transport](./src/transport/webrtc-transport/webrtc-transport.md) — _(no submodules)_- [bitset-codec](./src/transport/webrtc-transport/bitset-codec.md) — Provides the gzip codec used to compress advertisement bitsets before they hit the wire. Bitsets describing which chunk…
  • hex — Boundary helpers converting between the on-the-wire 32-byte file id representation and the hex-encoded form used by eve…
  • payload-codec — Implements the byte-level encoder/decoder for the two structured frame bodies the WebRTC drive transport carries: chunk…
  • webrtc-transport — (no submodules)- error-codes — Defines the typed error-code registry and DriveTransportWebRtcError class used by every public boundary of `@suavepla…
  • frame — (no submodules)- schemas — (no submodules)- frame.schemas — (no submodules)- webrtc-transport — (no submodules)- bitset-codec — Provides the gzip codec used to compress advertisement bitsets before they hit the wire. Bitsets describing which chunk…
    • hex — Boundary helpers converting between the on-the-wire 32-byte file id representation and the hex-encoded form used by eve…
    • payload-codec — Implements the byte-level encoder/decoder for the two structured frame bodies the WebRTC drive transport carries: chunk…
    • webrtc-transport — (no submodules)- error-codes — Defines the typed error-code registry and DriveTransportWebRtcError class used by every public boundary of `@suavepla…
  • frame — (no submodules)- schemas — (no submodules)- frame.schemas — (no submodules)- webrtc-transport — (no submodules)- bitset-codec — Provides the gzip codec used to compress advertisement bitsets before they hit the wire. Bitsets describing which chunk…
    • hex — Boundary helpers converting between the on-the-wire 32-byte file id representation and the hex-encoded form used by eve…
    • payload-codec — Implements the byte-level encoder/decoder for the two structured frame bodies the WebRTC drive transport carries: chunk…
    • webrtc-transport — (no submodules)- error-codes — Defines the typed error-code registry and DriveTransportWebRtcError class used by every public boundary of `@suavepla…
  • frame — (no submodules)- schemas — (no submodules) - frame.schemas — (no submodules)- webrtc-transport — (no submodules) - bitset-codec — Provides the gzip codec used to compress advertisement bitsets before they hit the wire. Bitsets describing which chunk…
    • hex — Boundary helpers converting between the on-the-wire 32-byte file id representation and the hex-encoded form used by eve…
    • payload-codec — Implements the byte-level encoder/decoder for the two structured frame bodies the WebRTC drive transport carries: chunk…
    • webrtc-transport — (no submodules)- error-codes — Defines the typed error-code registry and DriveTransportWebRtcError class used by every public boundary of `@suavepla…

Quick start

import {
    DataChannelManager,
    WebRTCClient,
} from "@suaveplan/drive-webrtc";
import { WebRTCDriveTransport } from "@suaveplan/drive-transport-webrtc";

const client = new WebRTCClient({
    peerId: "self",
    config: { signaling: { url: "wss://signal.example.com" } },
});
const channels = new DataChannelManager({ client });

// negotiate connection out of band via SignalingClient ...

const transport = new WebRTCDriveTransport({
    client,
    dataChannels: channels,
    defaultLabel: "drive-chunks",
    maxConcurrentRequests: 16,
    requestTimeoutMs: 10_000,
});

// pull a chunk from a peer (fileId is the hex-encoded 32-byte digest)
const fileId = "ab".repeat(32);
const bytes = await transport.requestChunk("bob", fileId, 0);

// broadcast presence — single `ChunkAdvertisement` object
await transport.advertise("bob", {
    fileId,
    bitset: ourBitset,
    totalChunks: 1024,
});

// subscribe to incoming advertisements (peerId + advert two-arg form)
const unsubscribe = transport.onAdvertisement((peerId, advert) => {
    presenceIndex.update(peerId, advert.fileId, advert.bitset);
});

// teardown
await transport.dispose();
unsubscribe();

Integration with drive-mesh

WebRTCDriveTransport implements the canonical DriveTransport contract from @suaveplan/drive-mesh. A mesh instance accepts a list of DriveTransport implementations:

import { DriveMesh } from "@suaveplan/drive-mesh";
import { WebRTCDriveTransport } from "@suaveplan/drive-transport-webrtc";

const mesh = new DriveMesh({
    transports: [
        new WebRTCDriveTransport({ client, dataChannels }),
    ],
    // ...peer registry, signed-chunk source, optional ServerFallback
});

The HTTPS / server-fallback path lives inside drive-mesh itself (ServerFallback — see @suaveplan/drive-mesh's ./server-fallback/server-fallback module), so there is no companion drive-transport-https package to plug in.

Wire framing

Every datachannel message is a length-prefixed binary frame:

+--------+--------+----------------------+
|  4 B   |  1 B   |     frameLen - 1 B   |
| length | type   |       payload        |
+--------+--------+----------------------+
  • length — big-endian uint32 byte count of type + payload.
  • type — 0x01 chunk-request, 0x02 chunk-response, 0x03 advertisement.
  • payload shape varies by type:
    • Chunk request: fileId(32 raw bytes) ‖ chunkId(4 BE uint32).
    • Chunk response: raw chunk bytes (length is already known from the outer header).
    • Advertisement: fileId(32 raw bytes) ‖ totalChunks(4 BE uint32) ‖ gzip(bitset).

Public API takes / returns the hex-encoded form (fileId: string, 64 lowercase hex chars). The codec converts to / from raw bytes at the boundary; on-the-wire bytes are unchanged from the pre-rewrite representation except for the new 4-byte totalChunks field.

Frame bodies are capped at 16 MiB. Malformed frames are dropped on the receive side and surface as DriveTransportWebRtcError(FRAME_INVALID) on the send side.

Backpressure

Outgoing sends route through DataChannelManager.send, which pauses when bufferedAmount exceeds the data-channel high-water mark and resumes on the bufferedamountlow event. No additional flow-control state is held in this package.

OTel surface

Instrument Kind Attributes
drive.transport.webrtc.requests_total counter outcome ∈ ok / timeout / aborted / send_failed / rejected_overflow
drive.transport.webrtc.advertisements_total counter direction ∈ inbound / outbound
drive.transport.webrtc.request_duration_ms histogram outcome
drive.transport.webrtc.frame_size_bytes histogram type ∈ chunk-request / advertisement

Error codes

All errors are instances of DriveTransportWebRtcError:

  • FRAME_INVALID — frame header or payload failed validation.
  • FRAME_TOO_LARGE — frame body exceeded the 16 MiB cap.
  • REQUEST_TIMEOUT — chunk request did not receive a response in time.
  • PEER_NOT_CONNECTED — no data channel could be opened for the peer.
  • DATA_CHANNEL_CLOSED — channel closed before / during send.
  • BITSET_COMPRESSION_FAILED — gzip codec failed.
  • ABORTED — AbortSignal fired or transport was disposed.

License

MIT