browser wasm
This commit is contained in:
parent
28fab2509b
commit
e8630528af
24 changed files with 2490 additions and 100 deletions
|
|
@ -43,11 +43,33 @@ namespace Crafter::HTTP3 {
|
|||
export inline constexpr std::uint64_t kFrameData = 0x00;
|
||||
export inline constexpr std::uint64_t kFrameHeaders = 0x01;
|
||||
export inline constexpr std::uint64_t kFrameSettings = 0x04;
|
||||
// WebTransport bidirectional stream frame type (draft-ietf-webtrans-http3).
|
||||
// Distinct from normal HTTP/3 frames — its body is unbounded (runs to FIN)
|
||||
// rather than length-prefixed, and the first bytes of the body are the
|
||||
// session id varint.
|
||||
export inline constexpr std::uint64_t kFrameWtStream = 0x41;
|
||||
|
||||
// ---------------- Unidirectional stream types (RFC 9114 §6.2) ----------------
|
||||
export inline constexpr std::uint64_t kStreamControl = 0x00;
|
||||
export inline constexpr std::uint64_t kStreamQpackEnc = 0x02;
|
||||
export inline constexpr std::uint64_t kStreamQpackDec = 0x03;
|
||||
// WebTransport unidirectional stream type (draft-ietf-webtrans-http3).
|
||||
// After this varint comes a session id varint, then opaque payload to FIN.
|
||||
export inline constexpr std::uint64_t kStreamWt = 0x54;
|
||||
|
||||
// ---------------- SETTINGS parameter identifiers ----------------
|
||||
// Required to negotiate WebTransport over HTTP/3 + HTTP/3 datagrams.
|
||||
export inline constexpr std::uint64_t kSettingQpackMaxTableCapacity = 0x01; // RFC 9204
|
||||
export inline constexpr std::uint64_t kSettingQpackBlockedStreams = 0x07; // RFC 9204
|
||||
export inline constexpr std::uint64_t kSettingEnableConnectProtocol = 0x08; // RFC 9220
|
||||
export inline constexpr std::uint64_t kSettingH3Datagram = 0x33; // RFC 9297
|
||||
// Legacy identifiers from older WebTransport / H3-DATAGRAM drafts. Chrome
|
||||
// (as of M120-ish) advertises and looks for the draft-02 / draft-04 ids
|
||||
// alongside the RFC ones; if we only send the modern ids it decides we
|
||||
// don't support WebTransport and aborts with ERR_METHOD_NOT_SUPPORTED.
|
||||
export inline constexpr std::uint64_t kSettingH3DatagramDraft04 = 0xffd277; // draft-ietf-masque-h3-datagram-04
|
||||
export inline constexpr std::uint64_t kSettingEnableWebTransport = 0x2b603742; // draft-02 boolean
|
||||
export inline constexpr std::uint64_t kSettingWtMaxSessions = 0xc671706a; // draft-ietf-webtrans-http3 (-07+)
|
||||
|
||||
// ---------------- Errors ----------------
|
||||
export class HTTP3ProtocolError : public std::runtime_error {
|
||||
|
|
@ -575,4 +597,55 @@ namespace Crafter::HTTP3 {
|
|||
EncodeVarint(0, out); // frame length 0
|
||||
return out;
|
||||
}
|
||||
|
||||
// Server-side variant that advertises WebTransport-over-HTTP/3 support
|
||||
// to the peer. Without these three SETTINGS the browser silently rejects
|
||||
// the extended CONNECT and the WebTransport.ready promise never resolves.
|
||||
// `maxSessions` becomes the value of SETTINGS_WT_MAX_SESSIONS.
|
||||
export inline std::vector<std::uint8_t> BuildWebTransportControlStreamPrelude(
|
||||
std::uint64_t maxSessions = 1)
|
||||
{
|
||||
// Encode the SETTINGS body first so we can write its length. The two
|
||||
// QPACK settings declare we run with no dynamic table — sent
|
||||
// explicitly because some HTTP/3 stacks (Chrome among them) refuse
|
||||
// to consider the peer ready for extended-CONNECT until they have
|
||||
// seen a baseline QPACK configuration. The draft-02 ENABLE_WEBTRANSPORT
|
||||
// and draft-04 H3_DATAGRAM ids are sent alongside their RFC counterparts
|
||||
// for compatibility with current Chrome (which still negotiates the
|
||||
// draft form even when advertising RFC support).
|
||||
std::vector<std::uint8_t> body;
|
||||
EncodeVarint(kSettingQpackMaxTableCapacity, body); EncodeVarint(0, body);
|
||||
EncodeVarint(kSettingQpackBlockedStreams, body); EncodeVarint(0, body);
|
||||
EncodeVarint(kSettingEnableConnectProtocol, body); EncodeVarint(1, body);
|
||||
EncodeVarint(kSettingH3Datagram, body); EncodeVarint(1, body);
|
||||
EncodeVarint(kSettingH3DatagramDraft04, body); EncodeVarint(1, body);
|
||||
EncodeVarint(kSettingEnableWebTransport, body); EncodeVarint(1, body);
|
||||
EncodeVarint(kSettingWtMaxSessions, body); EncodeVarint(maxSessions, body);
|
||||
|
||||
std::vector<std::uint8_t> out;
|
||||
EncodeVarint(kStreamControl, out);
|
||||
WriteFrame(out, kFrameSettings, body.data(), body.size());
|
||||
return out;
|
||||
}
|
||||
|
||||
// Prefix bytes that go on the front of an outgoing WT bidi stream — the
|
||||
// peer reads these to know which session the stream belongs to. After
|
||||
// this prefix the stream contains opaque WebTransport payload until FIN
|
||||
// (there is no length field — WT_STREAM is the only HTTP/3 frame whose
|
||||
// body runs to end-of-stream).
|
||||
export inline std::vector<std::uint8_t> BuildWtBidiPrefix(std::uint64_t sessionId) {
|
||||
std::vector<std::uint8_t> out;
|
||||
EncodeVarint(kFrameWtStream, out);
|
||||
EncodeVarint(sessionId, out);
|
||||
return out;
|
||||
}
|
||||
|
||||
// Prefix bytes that go on the front of an outgoing WT unidi stream
|
||||
// (server-initiated → client). Stream-type varint then session id.
|
||||
export inline std::vector<std::uint8_t> BuildWtUnidiPrefix(std::uint64_t sessionId) {
|
||||
std::vector<std::uint8_t> out;
|
||||
EncodeVarint(kStreamWt, out);
|
||||
EncodeVarint(sessionId, out);
|
||||
return out;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue