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 #[allow(clippy::large_enum_variant)]
32 #[derive(Debug)]
33 pub enum TlsBackend {
34 #[cfg(feature = "tls-native-tls")]
35 Native(TlsConnector),
36 #[cfg(feature = "tls-rustls")]
37 Rustls(ClientConfig),
38 }
39
40 impl Default for TlsBackend {
41 #[cfg(feature = "tls-native-tls")]
42 fn default() -> Self {
43 Self::Native(TlsConnector::new().unwrap())
44 }
45
46 #[cfg(all(feature = "tls-rustls", not(feature = "tls-native-tls")))]
47 fn default() -> Self {
48 pub static CA_CERTS: once_cell::sync::Lazy<rustls::RootCertStore> = once_cell::sync::Lazy::new(|| {
49 let certs = rustls_native_certs::load_native_certs()
50 .certs
51 .into_iter()
52 .map(|c| c)
53 .collect::<Vec<_>>();
54 let mut store = rustls::RootCertStore::empty();
55 store.add_parsable_certificates(certs);
56 store
57 });
58
59 Self::Rustls(
60 ClientConfig::builder()
61 .with_root_certificates(CA_CERTS.clone())
62 .with_no_client_auth(),
63 )
64 }
65 }
66
67 #[derive(Default, Debug)]
69 pub struct TlsOptions {
70 pub(crate) backend: Option<TlsBackend>,
71 pub(crate) kind: TlsKind,
72 pub(crate) domain_name: Option<String>,
73 }
74
75 impl TlsOptions {
76 fn new(kind: TlsKind) -> Self {
77 Self {
78 backend: None,
79 kind,
80 domain_name: None,
81 }
82 }
83
84 pub fn tls() -> Self {
86 Self::new(TlsKind::Tls)
87 }
88
89 pub fn start_tls() -> Self {
91 Self::new(TlsKind::StartTls)
92 }
93
94 #[cfg(feature = "tls-rustls")]
95 pub fn client_config(mut self, client_config: ClientConfig) -> Self {
97 self.backend = Some(TlsBackend::Rustls(client_config));
98 self
99 }
100
101 #[cfg(feature = "tls-native-tls")]
102 pub fn tls_connector(mut self, tls_connector: TlsConnector) -> Self {
104 self.backend = Some(TlsBackend::Native(tls_connector));
105 self
106 }
107
108 pub fn domain_name<S: AsRef<str>>(mut self, domain_name: S) -> Self {
110 self.domain_name = Some(domain_name.as_ref().to_owned());
111 self
112 }
113 }
114}