3 unstable releases
0.7.0-alpha.2 | Aug 16, 2024 |
---|---|
0.7.0-alpha.1 | Jul 30, 2024 |
0.6.0 | Jul 30, 2024 |
#199 in Game dev
320KB
5.5K
SLoC
aeronet_webtransport
A WebTransport transport implementation of aeronet, which uses the QUIC protocol under the hood to provide reliable streams and unreliable datagrams.
This is a good all-around choice for a generic transport library.
Features
- Client-side WASM support
- Uses
aeronet_proto
for reliability + ordering - Built on top of QUIC
- Encryption via SSL certificates
- Encrypted and resilient datagrams
- Connection over a single UDP socket multiplexed into multiple QUIC streams
- Server can allow or reject clients before they establish a connection
- Read client headers, authority, origin, path, etc.
Getting started
Manifest
Add the crates to your Cargo.toml
:
aeronet = "version"
aeronet_webtransport = "version"
For native clients: to avoid having to manually generate and manage certificates, you can
disable certificate authentication for testing purposes only via the dangerous-configuration
feature.
See the Certificates section to learn how to properly manage certificates.
Runtime
The WebTransport client and server use a specific runtime, the WebTransportRuntime
, to run the
async task which manages the actual connections and endpoints. To connect or open any client or
server, you will first need one of these runtimes.
You can use the Default
impl to create one of these runtimes, or in Bevy, insert the runtime as
a resource using App::init_resource::<WebTransportRuntime>()
.
Client
Create a disconnected WebTransportClient
using WebTransportClient::new
, and use
WebTransportClient::connect
to start establishing a connection to a server, passing in your
connection configuration (i.e. what URL to connect to, timeout duration, lanes).
In Bevy, you can use App::init_resource::<WebTransportClient>()
to automatically insert a
disconnected client into your app.
use bevy::prelude::*;
use aeronet_webtransport::{
client::{WebTransportClient, ClientConfig},
runtime::WebTransportRuntime,
};
use aeronet_webtransport::proto::session::SessionConfig;
App::new()
.init_resource::<WebTransportRuntime>()
.init_resource::<WebTransportClient>()
.add_systems(Startup, connect);
fn connect(mut client: ResMut<WebTransportClient>, runtime: Res<WebTransportRuntime>) {
let net_config = create_net_config();
let session_config = create_session_config();
client.connect(
runtime.as_ref(),
net_config,
session_config,
"https://[::1]:1234",
)
.expect("failed to connect client");
}
// this will change depending on whether you target native or WASM
fn create_net_config() -> ClientConfig { unimplemented!() }
fn create_session_config() -> SessionConfig { unimplemented!() }
Server
Create a closed WebTransportServer
using WebTransportServer::new
, and use
WebTransportServer::open
to start opening this server and have it listen for client connections,
passing in your server configuration (i.e. what port to bind to).
In Bevy, you can use App::init_resource::<WebTransportServer>()
to automatically insert a
closed server into your app.
Important: after receiving a ServerEvent::Connecting
, you must manually decide whether to
accept or reject the client.
- Use
server::Connecting
to decide whether to accept this client based on their path, authority, HTTP headers etc. - Use
WebTransportServer::respond_to_request
to decide whether this client is allowed to connect or not.
use bevy::prelude::*;
use aeronet_webtransport::{
server::{WebTransportServer, ServerConfig},
runtime::WebTransportRuntime,
};
use aeronet_webtransport::proto::session::SessionConfig;
App::new()
.init_resource::<WebTransportRuntime>()
.init_resource::<WebTransportServer>()
.add_systems(Startup, open);
fn open(mut server: ResMut<WebTransportServer>, runtime: Res<WebTransportRuntime>) {
let net_config = create_net_config();
let session_config = create_session_config();
server.open(
runtime.as_ref(),
net_config,
session_config,
)
.expect("failed to open server");
}
fn create_net_config() -> ServerConfig { unimplemented!() }
fn create_session_config() -> SessionConfig { unimplemented!() }
Certificates
Since WebTransport uses TLS, and therefore SSL certificates, for encrypting the connection, you must manage these certificates to make sure clients can connect to your server.
Signed by a certificate authority
If you already have an SSL certificate which is signed by a certificate authority, you can configure your server to use that certificate. Clients which trust that CA (either native or WASM) will be able to connect to your server without any extra configuration.
Self-signed
Module: cert
If you wish to generate your own self-signed certificates, unconfigured clients will not be able to connect to your server by default, since the certificates are not signed by a CA that the client trusts (since you're self-signing, it doesn't trust your server).
Once you generate the certificates, you can get from them:
- the certificate hash - a SHA-256 digest of the DER of the certificate
- the SPKI fingerprint - a SHA-256 digest of the certificate's public key
WebTransport provides a mechanism specifically for connecting to servers which are ephemeral or cannot easily be routed to (e.g. virtual machines or virtual servers which can be spun up/down on demand). You can specify a list of certificate hashes which the client will implicitly trust (some restrictions on these certificates apply - see the WebTransport documentation).
On the server side, use cert::hash_to_b64
on your server's certificate to generate a base 64
encoded version of the certificate hash.
On the client side, use cert::hash_from_b64
to decode the base 64 string into bytes of the
certificate hash. You can use this certificate hash value in either the ClientConfigBuilder
(on native) or WebTransportOptions
(on WASM) to have the client trust this certificate.
Alternatively, you can configure your browser to trust all certificates signed with a given public key. This is what the SPKI fingerprint is used for.
On Chromium, use the flags:
chromium \
--webtransport-developer-mode \
--ignore-certificate-errors-spki-list=[SPKI fingerprint]
On Firefox, I don't know what the equivalent flags are. PRs open!
Dependencies
~5–20MB
~300K SLoC