actix_tls/accept/
rustls_0_23.rs1use core::future::{ready, Ready as FutReady};
6use std::{
7 convert::Infallible,
8 future::Future,
9 io::{self, IoSlice},
10 pin::Pin,
11 sync::Arc,
12 task::{Context, Poll},
13 time::Duration,
14};
15
16use actix_rt::{
17 net::{ActixStream, Ready},
18 time::{sleep, Sleep},
19};
20use actix_service::{Service, ServiceFactory};
21use actix_utils::counter::{Counter, CounterGuard};
22use pin_project_lite::pin_project;
23use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};
24use tokio_rustls::{Accept, TlsAcceptor};
25use tokio_rustls_026 as tokio_rustls;
26
27use super::{TlsError, DEFAULT_TLS_HANDSHAKE_TIMEOUT, MAX_CONN_COUNTER};
28
29pub mod reexports {
30 pub use tokio_rustls_026::rustls::ServerConfig;
33}
34
35pub struct TlsStream<IO>(tokio_rustls::server::TlsStream<IO>);
37
38impl_more::impl_from!(<IO> in tokio_rustls::server::TlsStream<IO> => TlsStream<IO>);
39impl_more::impl_deref_and_mut!(<IO> in TlsStream<IO> => tokio_rustls::server::TlsStream<IO>);
40
41impl<IO: ActixStream> AsyncRead for TlsStream<IO> {
42 fn poll_read(
43 self: Pin<&mut Self>,
44 cx: &mut Context<'_>,
45 buf: &mut ReadBuf<'_>,
46 ) -> Poll<io::Result<()>> {
47 Pin::new(&mut **self.get_mut()).poll_read(cx, buf)
48 }
49}
50
51impl<IO: ActixStream> AsyncWrite for TlsStream<IO> {
52 fn poll_write(
53 self: Pin<&mut Self>,
54 cx: &mut Context<'_>,
55 buf: &[u8],
56 ) -> Poll<io::Result<usize>> {
57 Pin::new(&mut **self.get_mut()).poll_write(cx, buf)
58 }
59
60 fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
61 Pin::new(&mut **self.get_mut()).poll_flush(cx)
62 }
63
64 fn poll_shutdown(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
65 Pin::new(&mut **self.get_mut()).poll_shutdown(cx)
66 }
67
68 fn poll_write_vectored(
69 self: Pin<&mut Self>,
70 cx: &mut Context<'_>,
71 bufs: &[IoSlice<'_>],
72 ) -> Poll<io::Result<usize>> {
73 Pin::new(&mut **self.get_mut()).poll_write_vectored(cx, bufs)
74 }
75
76 fn is_write_vectored(&self) -> bool {
77 (**self).is_write_vectored()
78 }
79}
80
81impl<IO: ActixStream> ActixStream for TlsStream<IO> {
82 fn poll_read_ready(&self, cx: &mut Context<'_>) -> Poll<io::Result<Ready>> {
83 IO::poll_read_ready((**self).get_ref().0, cx)
84 }
85
86 fn poll_write_ready(&self, cx: &mut Context<'_>) -> Poll<io::Result<Ready>> {
87 IO::poll_write_ready((**self).get_ref().0, cx)
88 }
89}
90
91pub struct Acceptor {
93 config: Arc<reexports::ServerConfig>,
94 handshake_timeout: Duration,
95}
96
97impl Acceptor {
98 pub fn new(config: reexports::ServerConfig) -> Self {
100 Acceptor {
101 config: Arc::new(config),
102 handshake_timeout: DEFAULT_TLS_HANDSHAKE_TIMEOUT,
103 }
104 }
105
106 pub fn set_handshake_timeout(&mut self, handshake_timeout: Duration) -> &mut Self {
110 self.handshake_timeout = handshake_timeout;
111 self
112 }
113}
114
115impl Clone for Acceptor {
116 fn clone(&self) -> Self {
117 Self {
118 config: self.config.clone(),
119 handshake_timeout: self.handshake_timeout,
120 }
121 }
122}
123
124impl<IO: ActixStream> ServiceFactory<IO> for Acceptor {
125 type Response = TlsStream<IO>;
126 type Error = TlsError<io::Error, Infallible>;
127 type Config = ();
128 type Service = AcceptorService;
129 type InitError = ();
130 type Future = FutReady<Result<Self::Service, Self::InitError>>;
131
132 fn new_service(&self, _: ()) -> Self::Future {
133 let res = MAX_CONN_COUNTER.with(|conns| {
134 Ok(AcceptorService {
135 acceptor: self.config.clone().into(),
136 conns: conns.clone(),
137 handshake_timeout: self.handshake_timeout,
138 })
139 });
140
141 ready(res)
142 }
143}
144
145pub struct AcceptorService {
147 acceptor: TlsAcceptor,
148 conns: Counter,
149 handshake_timeout: Duration,
150}
151
152impl<IO: ActixStream> Service<IO> for AcceptorService {
153 type Response = TlsStream<IO>;
154 type Error = TlsError<io::Error, Infallible>;
155 type Future = AcceptFut<IO>;
156
157 fn poll_ready(&self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
158 if self.conns.available(cx) {
159 Poll::Ready(Ok(()))
160 } else {
161 Poll::Pending
162 }
163 }
164
165 fn call(&self, req: IO) -> Self::Future {
166 AcceptFut {
167 fut: self.acceptor.accept(req),
168 timeout: sleep(self.handshake_timeout),
169 _guard: self.conns.get(),
170 }
171 }
172}
173
174pin_project! {
175 #[doc(hidden)]
177 pub struct AcceptFut<IO: ActixStream> {
178 fut: Accept<IO>,
179 #[pin]
180 timeout: Sleep,
181 _guard: CounterGuard,
182 }
183}
184
185impl<IO: ActixStream> Future for AcceptFut<IO> {
186 type Output = Result<TlsStream<IO>, TlsError<io::Error, Infallible>>;
187
188 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
189 let mut this = self.project();
190 match Pin::new(&mut this.fut).poll(cx) {
191 Poll::Ready(Ok(stream)) => Poll::Ready(Ok(TlsStream(stream))),
192 Poll::Ready(Err(err)) => Poll::Ready(Err(TlsError::Tls(err))),
193 Poll::Pending => this.timeout.poll(cx).map(|_| Err(TlsError::Timeout)),
194 }
195 }
196}