1#[cfg(feature = "tls-native-tls")]
4pub use native_tls;
5
6#[cfg(feature = "tls-rustls")]
7pub use {rustls, rustls_pki_types};
8
9#[cfg(tls)]
10pub use tls::TlsOptions;
11
12#[cfg(tls)]
13pub(crate) use tls::{TlsBackend, TlsKind};
14
15#[cfg(tls)]
16mod tls {
17 #[cfg(feature = "tls-native-tls")]
18 use native_tls::TlsConnector;
19
20 #[cfg(feature = "tls-rustls")]
21 pub use rustls::ClientConfig;
22
23 #[derive(Clone, Copy, Debug, Default, PartialEq)]
24 pub enum TlsKind {
25 #[default]
26 Plain,
27 Tls,
28 StartTls,
29 }
30
31 #[derive(Debug)]
32 pub enum TlsBackend {
33 #[cfg(feature = "tls-native-tls")]
34 Native(TlsConnector),
35 #[cfg(feature = "tls-rustls")]
36 Rustls(ClientConfig),
37 }
38
39 impl Default for TlsBackend {
40 #[cfg(feature = "tls-native-tls")]
41 fn default() -> Self {
42 Self::Native(TlsConnector::new().unwrap())
43 }
44
45 #[cfg(all(feature = "tls-rustls", not(feature = "tls-native-tls")))]
46 fn default() -> Self {
47 pub static CA_CERTS: once_cell::sync::Lazy<rustls::RootCertStore> = once_cell::sync::Lazy::new(|| {
48 let certs = rustls_native_certs::load_native_certs()
49 .certs
50 .into_iter()
51 .map(|c| c)
52 .collect::<Vec<_>>();
53 let mut store = rustls::RootCertStore::empty();
54 store.add_parsable_certificates(certs);
55 store
56 });
57
58 Self::Rustls(
59 ClientConfig::builder()
60 .with_root_certificates(CA_CERTS.clone())
61 .with_no_client_auth(),
62 )
63 }
64 }
65
66 #[derive(Default, Debug)]
68 pub struct TlsOptions {
69 pub(crate) backend: Option<TlsBackend>,
70 pub(crate) kind: TlsKind,
71 pub(crate) domain_name: Option<String>,
72 }
73
74 impl TlsOptions {
75 fn new(kind: TlsKind) -> Self {
76 Self {
77 backend: None,
78 kind,
79 domain_name: None,
80 }
81 }
82
83 pub fn tls() -> Self {
85 Self::new(TlsKind::Tls)
86 }
87
88 pub fn start_tls() -> Self {
90 Self::new(TlsKind::StartTls)
91 }
92
93 #[cfg(feature = "tls-rustls")]
94 pub fn client_config(mut self, client_config: ClientConfig) -> Self {
96 self.backend = Some(TlsBackend::Rustls(client_config));
97 self
98 }
99
100 #[cfg(feature = "tls-native-tls")]
101 pub fn tls_connector(mut self, tls_connector: TlsConnector) -> Self {
103 self.backend = Some(TlsBackend::Native(tls_connector));
104 self
105 }
106
107 pub fn domain_name<S: AsRef<str>>(mut self, domain_name: S) -> Self {
109 self.domain_name = Some(domain_name.as_ref().to_owned());
110 self
111 }
112 }
113}