Initial Commit
This commit is contained in:
180
packages/networking/drive/drive-transport-webrtc/README.md
Normal file
180
packages/networking/drive/drive-transport-webrtc/README.md
Normal 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
|
||||
|
||||
Reference in New Issue
Block a user