Initial Commit

This commit is contained in:
2026-05-27 23:47:53 +01:00
parent fbc70f96e6
commit 9b28db724f
18103 changed files with 1600554 additions and 0 deletions

View File

@@ -0,0 +1,180 @@
# @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).
<!-- begin:auto-docs -->
## Documentation tree
- [error-codes](./src/error-codes/error-codes.md) — Defines the typed error-code registry and `DriveTransportWebRtcError` class used by every public boundary of `@suavepla…
- [error-codes](./src/error-codes/error-codes.md) — Defines the typed error-code registry and `DriveTransportWebRtcError` class used by every public boundary of `@suavepla…
- [frame](./src/framing/frame/frame.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
- [frame](./src/framing/frame/frame.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
- [schemas](./src/schemas/frame.schemas.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
- [frame.schemas](./src/schemas/frame.schemas.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
- [webrtc-transport](./src/transport/webrtc-transport/webrtc-transport.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
- [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](./src/transport/webrtc-transport/hex.md) — Boundary helpers converting between the on-the-wire 32-byte file id representation and the hex-encoded form used by eve…
- [payload-codec](./src/transport/webrtc-transport/payload-codec.md) — Implements the byte-level encoder/decoder for the two structured frame bodies the WebRTC drive transport carries: chunk…
- [webrtc-transport](./src/transport/webrtc-transport/webrtc-transport.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
<!-- end:auto-docs --> - [frame](./src/framing/frame/frame.md) — <!-- begin:auto-docs --> _(no submodules)_- [schemas](./src/schemas/frame.schemas.md) — <!-- begin:auto-docs --> _(no submodules)_- [frame.schemas](./src/schemas/frame.schemas.md) — <!-- begin:auto-docs --> _(no submodules)_- [webrtc-transport](./src/transport/webrtc-transport/webrtc-transport.md) — <!-- begin:auto-docs --> _(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](./src/transport/webrtc-transport/hex.md) — Boundary helpers converting between the on-the-wire 32-byte file id representation and the hex-encoded form used by eve…
- [payload-codec](./src/transport/webrtc-transport/payload-codec.md) — Implements the byte-level encoder/decoder for the two structured frame bodies the WebRTC drive transport carries: chunk…
- [webrtc-transport](./src/transport/webrtc-transport/webrtc-transport.md) — <!-- begin:auto-docs --> _(no submodules)_- [error-codes](./src/error-codes.md) — Defines the typed error-code registry and `DriveTransportWebRtcError` class used by every public boundary of `@suavepla…
- [frame](./src/framing/frame/frame.md) — <!-- begin:auto-docs --> _(no submodules)_- [schemas](./src/schemas/frame.schemas.md) — <!-- begin:auto-docs --> _(no submodules)_- [frame.schemas](./src/schemas/frame.schemas.md) — <!-- begin:auto-docs --> _(no submodules)_- [webrtc-transport](./src/transport/webrtc-transport/webrtc-transport.md) — <!-- begin:auto-docs --> _(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](./src/transport/webrtc-transport/hex.md) — Boundary helpers converting between the on-the-wire 32-byte file id representation and the hex-encoded form used by eve…
- [payload-codec](./src/transport/webrtc-transport/payload-codec.md) — Implements the byte-level encoder/decoder for the two structured frame bodies the WebRTC drive transport carries: chunk…
- [webrtc-transport](./src/transport/webrtc-transport/webrtc-transport.md) — <!-- begin:auto-docs --> _(no submodules)_- [error-codes](./src/error-codes.md) — Defines the typed error-code registry and `DriveTransportWebRtcError` class used by every public boundary of `@suavepla…
- [frame](./src/framing/frame/frame.md) — <!-- begin:auto-docs --> _(no submodules)_- [schemas](./src/schemas/frame.schemas.md) — <!-- begin:auto-docs --> _(no submodules)_- [frame.schemas](./src/schemas/frame.schemas.md) — <!-- begin:auto-docs --> _(no submodules)_- [webrtc-transport](./src/transport/webrtc-transport/webrtc-transport.md) — <!-- begin:auto-docs --> _(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](./src/transport/webrtc-transport/hex.md) — Boundary helpers converting between the on-the-wire 32-byte file id representation and the hex-encoded form used by eve…
- [payload-codec](./src/transport/webrtc-transport/payload-codec.md) — Implements the byte-level encoder/decoder for the two structured frame bodies the WebRTC drive transport carries: chunk…
- [webrtc-transport](./src/transport/webrtc-transport/webrtc-transport.md) — <!-- begin:auto-docs --> _(no submodules)_- [error-codes](./src/error-codes.md) — Defines the typed error-code registry and `DriveTransportWebRtcError` class used by every public boundary of `@suavepla…
- [frame](./src/framing/frame/frame.md) — <!-- begin:auto-docs --> _(no submodules)_- [schemas](./src/schemas/frame.schemas.md) — <!-- begin:auto-docs --> _(no submodules)_ - [frame.schemas](./src/schemas/frame.schemas.md) — <!-- begin:auto-docs --> _(no submodules)_- [webrtc-transport](./src/transport/webrtc-transport/webrtc-transport.md) — <!-- begin:auto-docs --> _(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](./src/transport/webrtc-transport/hex.md) — Boundary helpers converting between the on-the-wire 32-byte file id representation and the hex-encoded form used by eve…
- [payload-codec](./src/transport/webrtc-transport/payload-codec.md) — Implements the byte-level encoder/decoder for the two structured frame bodies the WebRTC drive transport carries: chunk…
- [webrtc-transport](./src/transport/webrtc-transport/webrtc-transport.md) — <!-- begin:auto-docs --> _(no submodules)_- [error-codes](./src/error-codes.md) — Defines the typed error-code registry and `DriveTransportWebRtcError` class used by every public boundary of `@suavepla…
## Quick start
```ts
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:
```ts
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:
```text
+--------+--------+----------------------+
| 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