browser wasm
This commit is contained in:
parent
28fab2509b
commit
e8630528af
24 changed files with 2490 additions and 100 deletions
|
|
@ -19,7 +19,9 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|||
*/
|
||||
|
||||
module;
|
||||
#ifndef CRAFTER_NETWORK_BROWSER
|
||||
#include <msquic.h>
|
||||
#endif
|
||||
export module Crafter.Network:ClientQUIC;
|
||||
import std;
|
||||
|
||||
|
|
@ -45,9 +47,16 @@ namespace Crafter {
|
|||
};
|
||||
|
||||
// Client-side credential validation. By default we require a real cert.
|
||||
// insecureNoServerValidation disables peer cert checks — only for dev.
|
||||
// insecureNoServerValidation disables peer cert checks — only for dev,
|
||||
// and silently ignored in the browser build (browsers enforce their own
|
||||
// certificate policy). For browser dev against a self-signed listener,
|
||||
// populate serverCertificateHash with the SHA-256 of the server's DER
|
||||
// certificate; on the browser it is forwarded to WebTransport's
|
||||
// serverCertificateHashes option. A zeroed array means "unused" — the
|
||||
// browser will then require a publicly trusted cert.
|
||||
export struct QUICClientCredentials {
|
||||
bool insecureNoServerValidation = false;
|
||||
std::array<std::uint8_t, 32> serverCertificateHash{};
|
||||
};
|
||||
|
||||
export class ClientQUIC;
|
||||
|
|
@ -60,8 +69,10 @@ namespace Crafter {
|
|||
// for inbound streams initiated by the peer.
|
||||
export class QUICStream {
|
||||
public:
|
||||
#ifndef CRAFTER_NETWORK_BROWSER
|
||||
// Underlying msquic HQUIC handle. Treated as opaque by callers.
|
||||
HQUIC handle = nullptr;
|
||||
#endif
|
||||
|
||||
// The connection that owns this stream (non-owning).
|
||||
ClientQUIC* connection = nullptr;
|
||||
|
|
@ -72,12 +83,22 @@ namespace Crafter {
|
|||
bool canReceive = true;
|
||||
|
||||
QUICStream();
|
||||
#ifndef CRAFTER_NETWORK_BROWSER
|
||||
QUICStream(HQUIC handle, ClientQUIC* connection);
|
||||
#else
|
||||
// Browser-only constructor: wraps a JS-side WebTransport stream
|
||||
// identified by its integer handle. Used by ClientQUIC::OpenStream
|
||||
// and by the incoming-stream dispatcher in the JS bridge — not
|
||||
// intended for direct use.
|
||||
QUICStream(std::int32_t handle, ClientQUIC* connection,
|
||||
bool canSend, bool canReceive);
|
||||
#endif
|
||||
~QUICStream();
|
||||
QUICStream(const QUICStream&) = delete;
|
||||
QUICStream(QUICStream&&) noexcept;
|
||||
QUICStream& operator=(QUICStream&&) noexcept;
|
||||
|
||||
#ifndef CRAFTER_NETWORK_BROWSER
|
||||
// Send a buffer. If finish=true, the send-side of the stream is closed
|
||||
// after the buffer is delivered (peer will see graceful shutdown).
|
||||
// Blocks until msquic accepts the buffer; throws on stream/conn close.
|
||||
|
|
@ -93,12 +114,36 @@ namespace Crafter {
|
|||
|
||||
// Read exactly bufferSize bytes; throws if the peer closes early.
|
||||
std::vector<char> RecieveUntilFullSync(std::uint32_t bufferSize);
|
||||
#endif
|
||||
|
||||
// Async variants: dispatched on Crafter.Thread's ThreadPool.
|
||||
// Send a buffer. If finish=true, the send-side is closed after the
|
||||
// buffer is delivered. onSent fires once the transport has accepted
|
||||
// the buffer (native) or the WritableStream writer has resolved
|
||||
// (browser). Available on both native and browser builds.
|
||||
void SendAsync(const void* buffer, std::uint32_t size, bool finish,
|
||||
std::function<void()> onSent);
|
||||
|
||||
// Async receive variants. Dispatched on Crafter.Thread's ThreadPool
|
||||
// (native) or driven by a per-stream JS reader loop (browser).
|
||||
void RecieveAsync(std::function<void(std::vector<char>)> recieveCallback);
|
||||
void RecieveUntilCloseAsync(std::function<void(std::vector<char>)> recieveCallback);
|
||||
void RecieveUntilFullAsync(std::uint32_t bufferSize, std::function<void(std::vector<char>)> recieveCallback);
|
||||
|
||||
#ifndef CRAFTER_NETWORK_BROWSER
|
||||
// Advanced: re-inject already-consumed bytes at the front of the
|
||||
// receive queue so the next Recieve* call sees them. Used by
|
||||
// protocol demuxers (e.g. the WebTransport stream router in
|
||||
// ListenerHTTP) that need to peek a prefix off the wire, then hand
|
||||
// the stream to user code as if the prefix had never been read.
|
||||
void PrependReceived(std::vector<char> bytes);
|
||||
|
||||
// Underlying QUIC stream id. Stable for the stream's lifetime.
|
||||
// Browsers identify WT streams by the session's CONNECT stream id,
|
||||
// so the server has to query and remember it at session creation
|
||||
// time. Throws if the stream is not yet started.
|
||||
std::uint64_t GetStreamId() const;
|
||||
#endif
|
||||
|
||||
// Cleanly shut down the stream (both directions).
|
||||
void Stop();
|
||||
|
||||
|
|
@ -109,8 +154,9 @@ namespace Crafter {
|
|||
};
|
||||
|
||||
// A QUIC connection. On the client side, constructing one initiates the
|
||||
// handshake and blocks until it succeeds (or throws on failure). On the
|
||||
// server side, ListenerQUIC instantiates these for accepted peers.
|
||||
// handshake and (on native) blocks until it succeeds, or throws on
|
||||
// failure. On the server side, ListenerQUIC instantiates these for
|
||||
// accepted peers.
|
||||
//
|
||||
// A connection multiplexes:
|
||||
// - Reliable, ordered streams (open via OpenStream() / observe inbound
|
||||
|
|
@ -120,10 +166,28 @@ namespace Crafter {
|
|||
// Lifetime: ~ClientQUIC closes the connection. Streams obtained from
|
||||
// OpenStream() are scoped to the connection and must be destroyed (or
|
||||
// moved out) before the ClientQUIC.
|
||||
//
|
||||
// Browser build: the only QUIC-shaped API the browser exposes is
|
||||
// WebTransport, which is HTTP/3-based and reached at a fixed URL. Here:
|
||||
// - The constructor returns immediately; the connection is opened in
|
||||
// the background. Operations issued before the connection is ready
|
||||
// are queued JS-side until WebTransport's "ready" promise resolves
|
||||
// (or fail with QUICClosedException if the connection rejects).
|
||||
// - `alpn` is mapped to the URL path: new WebTransport(
|
||||
// `https://${host}:${port}/${alpn}`). The QUIC-layer ALPN itself
|
||||
// is fixed to "h3" by the browser and cannot be customised.
|
||||
// - The server side must accept WebTransport sessions (HTTP/3 extended
|
||||
// CONNECT) on the path equal to `alpn`. Plain QUIC with a custom
|
||||
// ALPN — what ListenerQUIC offers today — is not reachable from a
|
||||
// browser.
|
||||
// - Synchronous send/receive methods are not compiled. Use the *Async
|
||||
// variants instead.
|
||||
export class ClientQUIC {
|
||||
public:
|
||||
// ALPN identifier exchanged in the handshake. Both peers must agree.
|
||||
// For 3DForts use e.g. "f3d/1" or similar — a short stable token.
|
||||
// On the browser build, this is the WebTransport URL path instead
|
||||
// of an ALPN token; see the class comment above.
|
||||
std::string alpn;
|
||||
|
||||
// Client constructor: connects to host:port using QUIC. ALPN must
|
||||
|
|
@ -133,10 +197,12 @@ namespace Crafter {
|
|||
ClientQUIC(std::string host, std::uint16_t port, std::string alpn,
|
||||
QUICClientCredentials creds = {});
|
||||
|
||||
#ifndef CRAFTER_NETWORK_BROWSER
|
||||
// Server-side constructor used by ListenerQUIC for accepted peers.
|
||||
// Takes ownership of an already-accepted msquic connection handle
|
||||
// and the server configuration handle. Not intended for direct use.
|
||||
ClientQUIC(HQUIC connectionHandle, HQUIC serverConfiguration, std::string alpn);
|
||||
#endif
|
||||
|
||||
~ClientQUIC();
|
||||
ClientQUIC(const ClientQUIC&) = delete;
|
||||
|
|
@ -162,15 +228,19 @@ namespace Crafter {
|
|||
// msquic worker; copy/queue and return promptly.
|
||||
void OnDatagram(std::function<void(std::vector<char>)> callback);
|
||||
|
||||
#ifndef CRAFTER_NETWORK_BROWSER
|
||||
// Block the caller until the next datagram arrives; returns it.
|
||||
// Throws QUICClosedException if the connection closes first.
|
||||
std::vector<char> RecieveDatagramSync();
|
||||
#endif
|
||||
|
||||
// Cleanly shut down the connection.
|
||||
void Stop();
|
||||
|
||||
#ifndef CRAFTER_NETWORK_BROWSER
|
||||
// Underlying handle for advanced use (parameter queries, etc.).
|
||||
HQUIC GetHandle() const;
|
||||
#endif
|
||||
|
||||
private:
|
||||
struct Impl;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue