webtrans_wasm/
client.rs

1use js_sys::{Object, Reflect, Uint8Array};
2use url::Url;
3use wasm_bindgen_futures::JsFuture;
4use web_sys::{WebTransport, WebTransportOptions};
5
6use crate::{Error, Session};
7
8pub use web_sys::WebTransportCongestionControl as CongestionControl;
9
10/// Builder wrapper for [`WebTransportOptions`].
11#[derive(Debug, Default)]
12pub struct ClientBuilder {
13    options: WebTransportOptions,
14}
15
16impl ClientBuilder {
17    pub fn new() -> Self {
18        Self::default()
19    }
20
21    /// Control whether the client/server is allowed to pool connections.
22    /// In practice, keep this disabled unless you have a specific need.
23    pub fn with_pooling(self, val: bool) -> Self {
24        self.options.set_allow_pooling(val);
25        self
26    }
27
28    /// `true` if QUIC is required, `false` if TCP is an acceptable fallback.
29    pub fn with_unreliable(self, val: bool) -> Self {
30        self.options.set_require_unreliable(val);
31        self
32    }
33
34    /// Hint at the desired congestion control algorithm.
35    pub fn with_congestion_control(self, control: CongestionControl) -> Self {
36        self.options.set_congestion_control(control);
37        self
38    }
39
40    /// Supply SHA-256 hashes for accepted certificates instead of using a root CA.
41    pub fn with_server_certificate_hashes(self, hashes: Vec<Vec<u8>>) -> Client {
42        // Expected format: [{ algorithm: "sha-256", value: hashValue }, ...].
43        let hashes = hashes
44            .into_iter()
45            .map(|hash| {
46                let hash = Uint8Array::from(&hash[..]);
47                let obj = Object::new();
48                Reflect::set(&obj, &"algorithm".into(), &"sha-256".into()).unwrap();
49                Reflect::set(&obj, &"value".into(), &hash.into()).unwrap();
50                obj
51            })
52            .collect::<js_sys::Array>();
53
54        self.options.set_server_certificate_hashes(&hashes);
55        Client {
56            options: self.options,
57        }
58    }
59
60    pub fn with_system_roots(self) -> Client {
61        Client {
62            options: self.options,
63        }
64    }
65}
66
67/// Build a client with the given URL and options.
68///
69/// See [`WebTransportOptions`].
70#[derive(Clone, Debug, Default)]
71pub struct Client {
72    options: WebTransportOptions,
73}
74
75impl Client {
76    /// Connect once the builder is configured.
77    pub async fn connect(&self, url: Url) -> Result<Session, Error> {
78        let inner = WebTransport::new_with_options(url.as_str(), &self.options)?;
79        JsFuture::from(inner.ready()).await?;
80
81        Ok(Session::new(inner, url))
82    }
83}