Skip to main content

base_endpoint/tls/rustls/
rustls_connector.rs

1// Released under the MIT License.
2// Copyright, 2026, by Samuel Williams.
3
4use super::{RustlsConnection, establish, tls_error};
5use crate::tls::TlsConnector;
6use ::rustls::{ClientConfig, ClientConnection, pki_types::ServerName};
7use base_scheduler::{
8    Cancellation, OperationResult, SocketClose, SocketStreamReading, SocketStreamWriting,
9};
10use std::{io, sync::Arc};
11
12/// A rustls client provider using application-supplied trust, identity and ALPN configuration. DNS names and IP literals are verified by the configuration's certificate verifier. No system trust roots are loaded implicitly.
13#[derive(Clone, Debug)]
14pub struct RustlsConnector {
15    config: Arc<ClientConfig>,
16}
17
18impl RustlsConnector {
19    /// Share an explicitly configured rustls client configuration. The optional feature enables rustls's ring crypto provider; applications can also supply a configuration built with another explicitly selected rustls crypto provider.
20    pub fn new(config: Arc<ClientConfig>) -> Self {
21        Self { config }
22    }
23}
24
25impl<S> TlsConnector<S, S::Socket> for RustlsConnector
26where
27    S: SocketStreamReading + SocketStreamWriting + SocketClose + ?Sized,
28    S::Socket: 'static,
29{
30    type Connection = RustlsConnection<S::Socket>;
31
32    async fn connect(
33        &self,
34        scheduler: &S,
35        connection: S::Socket,
36        server_name: &str,
37        cancellation: &Cancellation,
38    ) -> OperationResult<Self::Connection> {
39        let state = (|| {
40            cancellation.check()?;
41            let name = ServerName::try_from(server_name.to_owned())
42                .map_err(|error| io::Error::new(io::ErrorKind::InvalidInput, error))?;
43            Ok(ClientConnection::new(self.config.clone(), name)
44                .map_err(tls_error)?
45                .into())
46        })();
47        establish(scheduler, connection, state, cancellation).await
48    }
49}