tls_api_native_tls/
connector.rs

1use std::str;
2
3use crate::handshake::HandshakeFuture;
4
5use std::future::Future;
6use tls_api::async_as_sync::AsyncIoAsSyncIo;
7use tls_api::spi_connector_common;
8use tls_api::AsyncSocket;
9use tls_api::AsyncSocketBox;
10use tls_api::ImplInfo;
11
12pub struct TlsConnectorBuilder {
13    pub builder: native_tls::TlsConnectorBuilder,
14    pub verify_hostname: bool,
15}
16
17pub struct TlsConnector {
18    pub connector: native_tls::TlsConnector,
19    pub verify_hostname: bool,
20}
21
22impl tls_api::TlsConnectorBuilder for TlsConnectorBuilder {
23    type Connector = TlsConnector;
24
25    type Underlying = native_tls::TlsConnectorBuilder;
26
27    fn underlying_mut(&mut self) -> &mut native_tls::TlsConnectorBuilder {
28        &mut self.builder
29    }
30
31    fn set_alpn_protocols(&mut self, protocols: &[&[u8]]) -> anyhow::Result<()> {
32        let protocols: Vec<&str> = protocols
33            .iter()
34            .map(|p| str::from_utf8(p).map_err(|e| crate::Error::AlpnProtocolNotUtf8(e).into()))
35            .collect::<anyhow::Result<_>>()?;
36        self.builder.request_alpns(&protocols);
37        Ok(())
38    }
39
40    fn set_verify_hostname(&mut self, verify: bool) -> anyhow::Result<()> {
41        self.builder.danger_accept_invalid_hostnames(!verify);
42        self.verify_hostname = verify;
43        Ok(())
44    }
45
46    fn add_root_certificate(&mut self, cert: &[u8]) -> anyhow::Result<()> {
47        let cert = native_tls::Certificate::from_der(cert).map_err(anyhow::Error::new)?;
48
49        self.builder.add_root_certificate(cert);
50
51        Ok(())
52    }
53
54    fn build(self) -> anyhow::Result<TlsConnector> {
55        let connector = self.builder.build().map_err(anyhow::Error::new)?;
56        Ok(TlsConnector {
57            connector,
58            verify_hostname: self.verify_hostname,
59        })
60    }
61}
62
63impl TlsConnector {
64    pub fn connect_impl<'a, S>(
65        &'a self,
66        domain: &'a str,
67        stream: S,
68    ) -> impl Future<Output = anyhow::Result<crate::TlsStream<S>>> + 'a
69    where
70        S: AsyncSocket,
71    {
72        HandshakeFuture::Initial(
73            move |s| self.connector.connect(domain, s),
74            AsyncIoAsSyncIo::new(stream),
75        )
76    }
77}
78
79impl tls_api::TlsConnector for TlsConnector {
80    type Builder = TlsConnectorBuilder;
81
82    type Underlying = native_tls::TlsConnector;
83    type TlsStream = crate::TlsStream<AsyncSocketBox>;
84
85    fn underlying_mut(&mut self) -> &mut Self::Underlying {
86        &mut self.connector
87    }
88
89    const IMPLEMENTED: bool = true;
90    const SUPPORTS_ALPN: bool = true;
91
92    fn info() -> ImplInfo {
93        crate::info()
94    }
95
96    fn builder() -> anyhow::Result<TlsConnectorBuilder> {
97        let builder = native_tls::TlsConnector::builder();
98        Ok(TlsConnectorBuilder {
99            builder,
100            verify_hostname: true,
101        })
102    }
103
104    spi_connector_common!(crate::TlsStream<S>);
105}