1use std::{
4 convert::Infallible,
5 error::Error,
6 fmt,
7 sync::atomic::{AtomicUsize, Ordering},
8};
9
10use actix_utils::counter::Counter;
11
12#[cfg(feature = "openssl")]
13pub mod openssl;
14
15#[cfg(feature = "rustls-0_20")]
16pub mod rustls_0_20;
17
18#[doc(hidden)]
19#[cfg(feature = "rustls-0_20")]
20pub use rustls_0_20 as rustls;
21
22#[cfg(feature = "rustls-0_21")]
23pub mod rustls_0_21;
24
25#[cfg(feature = "rustls-0_22")]
26pub mod rustls_0_22;
27
28#[cfg(feature = "rustls-0_23")]
29pub mod rustls_0_23;
30
31#[cfg(feature = "native-tls")]
32pub mod native_tls;
33
34pub(crate) static MAX_CONN: AtomicUsize = AtomicUsize::new(256);
35
36#[cfg(any(
37 feature = "openssl",
38 feature = "rustls-0_20",
39 feature = "rustls-0_21",
40 feature = "rustls-0_22",
41 feature = "rustls-0_23",
42 feature = "native-tls",
43))]
44pub(crate) const DEFAULT_TLS_HANDSHAKE_TIMEOUT: std::time::Duration =
45 std::time::Duration::from_secs(3);
46
47thread_local! {
48 static MAX_CONN_COUNTER: Counter = Counter::new(MAX_CONN.load(Ordering::Relaxed));
49}
50
51pub fn max_concurrent_tls_connect(num: usize) {
58 MAX_CONN.store(num, Ordering::Relaxed);
59}
60
61#[derive(Debug)]
68pub enum TlsError<TlsErr, SvcErr> {
69 Timeout,
71
72 Tls(TlsErr),
74
75 Service(SvcErr),
77}
78
79impl<TlsErr> TlsError<TlsErr, Infallible> {
80 pub fn into_service_error<SvcErr>(self) -> TlsError<TlsErr, SvcErr> {
90 match self {
91 Self::Timeout => TlsError::Timeout,
92 Self::Tls(err) => TlsError::Tls(err),
93 Self::Service(err) => match err {},
94 }
95 }
96}
97
98impl<TlsErr, SvcErr> fmt::Display for TlsError<TlsErr, SvcErr> {
99 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
100 match self {
101 Self::Timeout => f.write_str("TLS handshake has timed-out"),
102 Self::Tls(_) => f.write_str("TLS handshake error"),
103 Self::Service(_) => f.write_str("Service error"),
104 }
105 }
106}
107
108impl<TlsErr, SvcErr> Error for TlsError<TlsErr, SvcErr>
109where
110 TlsErr: Error + 'static,
111 SvcErr: Error + 'static,
112{
113 fn source(&self) -> Option<&(dyn Error + 'static)> {
114 match self {
115 TlsError::Tls(err) => Some(err),
116 TlsError::Service(err) => Some(err),
117 TlsError::Timeout => None,
118 }
119 }
120}
121
122#[cfg(test)]
123mod tests {
124 use super::*;
125
126 #[test]
127 fn tls_service_error_inference() {
128 let a: TlsError<u32, Infallible> = TlsError::Tls(42);
129 let _b: TlsError<u32, u64> = a.into_service_error();
130 }
131}