|
4 | 4 |
|
5 | 5 | Pulse speaks **ENet/UDP only** today. Native (Unity) clients can use it, but **browsers cannot open raw UDP/ENet sockets** — the only way a browser reaches a UDP-based game server is **WebTransport** (HTTP/3 over QUIC). To let the Decentraland **web explorer** connect to Pulse, we add WebTransport as a *second, coexisting* transport **alongside** ENet — not a replacement. ENet remains the path for native clients; WebTransport unlocks the browser. |
6 | 6 |
|
7 | | -Groundwork is already on branch `feat/webtransport`: shared transport contracts were extracted into the new `src/DCLPulse.Transport.Shared` project (`PacketMode`, `DisconnectReason`, `ENetChannel`, and the ENet managed binding `ENet.cs`). |
| 7 | +Groundwork is already on branch `feat/webtransport`: shared transport contracts were extracted into the new `src/DCLPulse.Transport` project (`PacketMode`, `DisconnectReason`, `ENetChannel`, and the ENet managed binding `ENet.cs`). |
8 | 8 |
|
9 | 9 | **Decisions (confirmed):** |
10 | 10 | - Primary audience: **browser clients** (drives the TLS/cert strategy below). |
@@ -81,7 +81,7 @@ WebTransport mandates TLS over QUIC. Browsers validate two ways: a **CA-signed c |
81 | 81 |
|
82 | 82 | ## 2. Reliability model & how it affects Pulse |
83 | 83 |
|
84 | | -WebTransport offers two primitives; map `PacketMode` ([`PacketMode.cs`](src/DCLPulse.Transport.Shared/Runtime/PacketMode.cs)) onto them: |
| 84 | +WebTransport offers two primitives; map `PacketMode` ([`PacketMode.cs`](src/DCLPulse.Transport/Package/Runtime/PacketMode.cs)) onto them: |
85 | 85 |
|
86 | 86 | | `PacketMode` | ENet today | WebTransport mapping | Notes | |
87 | 87 | |---|---|---|---| |
@@ -141,7 +141,7 @@ Existing transport metrics ([`PulseMetrics.Transport.cs`](src/DCLPulse/Metrics/P |
141 | 141 | ## 4. Code layout, config, and wiring |
142 | 142 |
|
143 | 143 | - **`WebTransportHostedService`** in `src/DCLPulse/Transport/` next to `ENetHostedService`, implementing `ITransport` ([`ITransport.cs`](src/DCLPulse/Transport/ITransport.cs)). Its loop mirrors ENet: `wt_host_service` drain → on Connect `TryAllocate` + `PreAuthAdmission.TryAdmit` + `OnPeerConnected`; on data parse `ClientMessage` (`CorruptedPacketLimiter.RecordCorruption` on failure) + `OnDataReceived`; on Disconnect `MarkPending` + `OnPeerDisconnected` + hardening `Release`; outgoing drain maps `PacketMode` → stream/datagram. |
144 | | -- **Channel-semantics helper** (stream length-framing + datagram seq/dedup) in `DCLPulse.Transport.Shared` (a `WebTransport/` subfolder) so it's unit-testable in isolation. Keep `PacketMode`/`DisconnectReason` where they are; leave `ENet.cs` in place (don't refactor ENet to avoid churn). |
| 144 | +- **Channel-semantics helper** (stream length-framing + datagram seq/dedup) in `DCLPulse.Transport` (a `WebTransport/` subfolder) so it's unit-testable in isolation. Keep `PacketMode`/`DisconnectReason` where they are; leave `ENet.cs` in place (don't refactor ENet to avoid churn). |
145 | 145 | - **Package reference**: simplest is to add the `Decentraland.RustWebTransport` `PackageReference` directly to `DCLPulse.csproj` (or a dedicated `src/DCLWebTransport` project the way `DCLAuth` holds the RustEthereum reference). Prefer adding it to the project that owns `WebTransportHostedService`. |
146 | 146 | - **Config**: a `WebTransport` section in `appsettings*.json` (`Enabled`, `Port`, `CertPath`/`KeyPath` or ACME settings, `MaxDatagramBytes`, send-queue bounds), overridable via Docker env (`WebTransport__Enabled`, …) like the existing `Peers__ResyncWithDelta`. Both transports start independently; either can be disabled. |
147 | 147 |
|
|
0 commit comments