wasmtime_wasi_tls/providers/
rustls.rs1use crate::{BoxFutureTlsStream, Error, TlsProvider, TlsStream, TlsTransport};
4use rustls::pki_types::ServerName;
5use std::sync::{Arc, LazyLock};
6
7impl crate::TlsStream for tokio_rustls::client::TlsStream<Box<dyn TlsTransport>> {}
8
9pub struct RustlsProvider {
11 client_config: Arc<rustls::ClientConfig>,
12}
13
14impl TlsProvider for RustlsProvider {
15 fn connect(&self, server_name: String, transport: Box<dyn TlsTransport>) -> BoxFutureTlsStream {
16 let client_config = Arc::clone(&self.client_config);
17 Box::pin(async move {
18 let domain =
19 ServerName::try_from(server_name).map_err(|_| Error::msg("invalid server name"))?;
20
21 let stream = tokio_rustls::TlsConnector::from(client_config)
22 .connect(domain, transport)
23 .await
24 .map_err(rustls_to_wasi_error)?;
25 Ok(Box::new(stream) as Box<dyn TlsStream>)
26 })
27 }
28}
29
30impl Default for RustlsProvider {
31 fn default() -> Self {
32 static CONFIG: LazyLock<Arc<rustls::ClientConfig>> = LazyLock::new(|| {
33 let roots = rustls::RootCertStore {
34 roots: webpki_roots::TLS_SERVER_ROOTS.into(),
35 };
36 let config = rustls::ClientConfig::builder()
37 .with_root_certificates(roots)
38 .with_no_client_auth();
39 Arc::new(config)
40 });
41
42 Self {
43 client_config: Arc::clone(&CONFIG),
44 }
45 }
46}
47
48impl From<rustls::Error> for Error {
49 fn from(e: rustls::Error) -> Self {
50 Error::msg(e.to_string())
51 }
52}
53
54fn rustls_to_wasi_error(e: std::io::Error) -> Error {
55 match e.downcast::<rustls::Error>() {
56 Ok(e) => e.into(),
57 Err(io_err) => Error::msg(io_err),
58 }
59}