/rust/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-rustls-0.26.1/src/lib.rs
Line | Count | Source |
1 | | //! Asynchronous TLS/SSL streams for Tokio using [Rustls](https://github.com/rustls/rustls). |
2 | | //! |
3 | | //! # Why do I need to call `poll_flush`? |
4 | | //! |
5 | | //! Most TLS implementations will have an internal buffer to improve throughput, |
6 | | //! and rustls is no exception. |
7 | | //! |
8 | | //! When we write data to `TlsStream`, we always write rustls buffer first, |
9 | | //! then take out rustls encrypted data packet, and write it to data channel (like TcpStream). |
10 | | //! When data channel is pending, some data may remain in rustls buffer. |
11 | | //! |
12 | | //! `tokio-rustls` To keep it simple and correct, [TlsStream] will behave like `BufWriter`. |
13 | | //! For `TlsStream<TcpStream>`, this means that data written by `poll_write` is not guaranteed to be written to `TcpStream`. |
14 | | //! You must call `poll_flush` to ensure that it is written to `TcpStream`. |
15 | | //! |
16 | | //! You should call `poll_flush` at the appropriate time, |
17 | | //! such as when a period of `poll_write` write is complete and there is no more data to write. |
18 | | //! |
19 | | //! ## Why don't we write during `poll_read`? |
20 | | //! |
21 | | //! We did this in the early days of `tokio-rustls`, but it caused some bugs. |
22 | | //! We can solve these bugs through some solutions, but this will cause performance degradation (reverse false wakeup). |
23 | | //! |
24 | | //! And reverse write will also prevent us implement full duplex in the future. |
25 | | //! |
26 | | //! see <https://github.com/tokio-rs/tls/issues/40> |
27 | | //! |
28 | | //! ## Why can't we handle it like `native-tls`? |
29 | | //! |
30 | | //! When data channel returns to pending, `native-tls` will falsely report the number of bytes it consumes. |
31 | | //! This means that if data written by `poll_write` is not actually written to data channel, it will not return `Ready`. |
32 | | //! Thus avoiding the call of `poll_flush`. |
33 | | //! |
34 | | //! but which does not conform to convention of `AsyncWrite` trait. |
35 | | //! This means that if you give inconsistent data in two `poll_write`, it may cause unexpected behavior. |
36 | | //! |
37 | | //! see <https://github.com/tokio-rs/tls/issues/41> |
38 | | |
39 | | use std::future::Future; |
40 | | use std::io; |
41 | | #[cfg(unix)] |
42 | | use std::os::unix::io::{AsRawFd, RawFd}; |
43 | | #[cfg(windows)] |
44 | | use std::os::windows::io::{AsRawSocket, RawSocket}; |
45 | | use std::pin::Pin; |
46 | | use std::sync::Arc; |
47 | | use std::task::{Context, Poll}; |
48 | | |
49 | | pub use rustls; |
50 | | |
51 | | use rustls::pki_types::ServerName; |
52 | | use rustls::server::AcceptedAlert; |
53 | | use rustls::{ClientConfig, ClientConnection, CommonState, ServerConfig, ServerConnection}; |
54 | | use tokio::io::{AsyncRead, AsyncWrite, ReadBuf}; |
55 | | |
56 | | macro_rules! ready { |
57 | | ( $e:expr ) => { |
58 | | match $e { |
59 | | std::task::Poll::Ready(t) => t, |
60 | | std::task::Poll::Pending => return std::task::Poll::Pending, |
61 | | } |
62 | | }; |
63 | | } |
64 | | |
65 | | pub mod client; |
66 | | mod common; |
67 | | use common::{MidHandshake, TlsState}; |
68 | | pub mod server; |
69 | | |
70 | | /// A wrapper around a `rustls::ClientConfig`, providing an async `connect` method. |
71 | | #[derive(Clone)] |
72 | | pub struct TlsConnector { |
73 | | inner: Arc<ClientConfig>, |
74 | | #[cfg(feature = "early-data")] |
75 | | early_data: bool, |
76 | | } |
77 | | |
78 | | /// A wrapper around a `rustls::ServerConfig`, providing an async `accept` method. |
79 | | #[derive(Clone)] |
80 | | pub struct TlsAcceptor { |
81 | | inner: Arc<ServerConfig>, |
82 | | } |
83 | | |
84 | | impl From<Arc<ClientConfig>> for TlsConnector { |
85 | 0 | fn from(inner: Arc<ClientConfig>) -> TlsConnector { |
86 | 0 | TlsConnector { |
87 | 0 | inner, |
88 | 0 | #[cfg(feature = "early-data")] |
89 | 0 | early_data: false, |
90 | 0 | } |
91 | 0 | } |
92 | | } |
93 | | |
94 | | impl From<Arc<ServerConfig>> for TlsAcceptor { |
95 | 0 | fn from(inner: Arc<ServerConfig>) -> TlsAcceptor { |
96 | 0 | TlsAcceptor { inner } |
97 | 0 | } |
98 | | } |
99 | | |
100 | | impl TlsConnector { |
101 | | /// Enable 0-RTT. |
102 | | /// |
103 | | /// If you want to use 0-RTT, |
104 | | /// You must also set `ClientConfig.enable_early_data` to `true`. |
105 | | #[cfg(feature = "early-data")] |
106 | | pub fn early_data(mut self, flag: bool) -> TlsConnector { |
107 | | self.early_data = flag; |
108 | | self |
109 | | } |
110 | | |
111 | | #[inline] |
112 | 0 | pub fn connect<IO>(&self, domain: ServerName<'static>, stream: IO) -> Connect<IO> |
113 | 0 | where |
114 | 0 | IO: AsyncRead + AsyncWrite + Unpin, |
115 | | { |
116 | 0 | self.connect_with(domain, stream, |_| ()) |
117 | 0 | } Unexecuted instantiation: <tokio_rustls::TlsConnector>::connect::<hyper_util::rt::tokio::TokioIo<hyper_util::rt::tokio::TokioIo<tokio::net::tcp::stream::TcpStream>>> Unexecuted instantiation: <tokio_rustls::TlsConnector>::connect::<ztunnel::proxy::h2::TokioH2Stream> Unexecuted instantiation: <tokio_rustls::TlsConnector>::connect::<tokio::net::tcp::stream::TcpStream> Unexecuted instantiation: <tokio_rustls::TlsConnector>::connect::<_> |
118 | | |
119 | 0 | pub fn connect_with<IO, F>(&self, domain: ServerName<'static>, stream: IO, f: F) -> Connect<IO> |
120 | 0 | where |
121 | 0 | IO: AsyncRead + AsyncWrite + Unpin, |
122 | 0 | F: FnOnce(&mut ClientConnection), |
123 | | { |
124 | 0 | let mut session = match ClientConnection::new(self.inner.clone(), domain) { |
125 | 0 | Ok(session) => session, |
126 | 0 | Err(error) => { |
127 | 0 | return Connect(MidHandshake::Error { |
128 | 0 | io: stream, |
129 | 0 | // TODO(eliza): should this really return an `io::Error`? |
130 | 0 | // Probably not... |
131 | 0 | error: io::Error::new(io::ErrorKind::Other, error), |
132 | 0 | }); |
133 | | } |
134 | | }; |
135 | 0 | f(&mut session); |
136 | | |
137 | 0 | Connect(MidHandshake::Handshaking(client::TlsStream { |
138 | 0 | io: stream, |
139 | 0 |
|
140 | 0 | #[cfg(not(feature = "early-data"))] |
141 | 0 | state: TlsState::Stream, |
142 | 0 |
|
143 | 0 | #[cfg(feature = "early-data")] |
144 | 0 | state: if self.early_data && session.early_data().is_some() { |
145 | 0 | TlsState::EarlyData(0, Vec::new()) |
146 | 0 | } else { |
147 | 0 | TlsState::Stream |
148 | 0 | }, |
149 | 0 |
|
150 | 0 | #[cfg(feature = "early-data")] |
151 | 0 | early_waker: None, |
152 | 0 |
|
153 | 0 | session, |
154 | 0 | })) |
155 | 0 | } Unexecuted instantiation: <tokio_rustls::TlsConnector>::connect_with::<hyper_util::rt::tokio::TokioIo<hyper_util::rt::tokio::TokioIo<tokio::net::tcp::stream::TcpStream>>, <tokio_rustls::TlsConnector>::connect<hyper_util::rt::tokio::TokioIo<hyper_util::rt::tokio::TokioIo<tokio::net::tcp::stream::TcpStream>>>::{closure#0}>Unexecuted instantiation: <tokio_rustls::TlsConnector>::connect_with::<ztunnel::proxy::h2::TokioH2Stream, <tokio_rustls::TlsConnector>::connect<ztunnel::proxy::h2::TokioH2Stream>::{closure#0}>Unexecuted instantiation: <tokio_rustls::TlsConnector>::connect_with::<tokio::net::tcp::stream::TcpStream, <tokio_rustls::TlsConnector>::connect<tokio::net::tcp::stream::TcpStream>::{closure#0}>Unexecuted instantiation: <tokio_rustls::TlsConnector>::connect_with::<_, _> |
156 | | } |
157 | | |
158 | | impl TlsAcceptor { |
159 | | #[inline] |
160 | 0 | pub fn accept<IO>(&self, stream: IO) -> Accept<IO> |
161 | 0 | where |
162 | 0 | IO: AsyncRead + AsyncWrite + Unpin, |
163 | | { |
164 | 0 | self.accept_with(stream, |_| ()) |
165 | 0 | } Unexecuted instantiation: <tokio_rustls::TlsAcceptor>::accept::<tokio::net::tcp::stream::TcpStream> Unexecuted instantiation: <tokio_rustls::TlsAcceptor>::accept::<_> |
166 | | |
167 | 0 | pub fn accept_with<IO, F>(&self, stream: IO, f: F) -> Accept<IO> |
168 | 0 | where |
169 | 0 | IO: AsyncRead + AsyncWrite + Unpin, |
170 | 0 | F: FnOnce(&mut ServerConnection), |
171 | | { |
172 | 0 | let mut session = match ServerConnection::new(self.inner.clone()) { |
173 | 0 | Ok(session) => session, |
174 | 0 | Err(error) => { |
175 | 0 | return Accept(MidHandshake::Error { |
176 | 0 | io: stream, |
177 | 0 | // TODO(eliza): should this really return an `io::Error`? |
178 | 0 | // Probably not... |
179 | 0 | error: io::Error::new(io::ErrorKind::Other, error), |
180 | 0 | }); |
181 | | } |
182 | | }; |
183 | 0 | f(&mut session); |
184 | | |
185 | 0 | Accept(MidHandshake::Handshaking(server::TlsStream { |
186 | 0 | session, |
187 | 0 | io: stream, |
188 | 0 | state: TlsState::Stream, |
189 | 0 | })) |
190 | 0 | } Unexecuted instantiation: <tokio_rustls::TlsAcceptor>::accept_with::<tokio::net::tcp::stream::TcpStream, <tokio_rustls::TlsAcceptor>::accept<tokio::net::tcp::stream::TcpStream>::{closure#0}>Unexecuted instantiation: <tokio_rustls::TlsAcceptor>::accept_with::<_, _> |
191 | | } |
192 | | |
193 | | pub struct LazyConfigAcceptor<IO> { |
194 | | acceptor: rustls::server::Acceptor, |
195 | | io: Option<IO>, |
196 | | alert: Option<(rustls::Error, AcceptedAlert)>, |
197 | | } |
198 | | |
199 | | impl<IO> LazyConfigAcceptor<IO> |
200 | | where |
201 | | IO: AsyncRead + AsyncWrite + Unpin, |
202 | | { |
203 | | #[inline] |
204 | 0 | pub fn new(acceptor: rustls::server::Acceptor, io: IO) -> Self { |
205 | 0 | Self { |
206 | 0 | acceptor, |
207 | 0 | io: Some(io), |
208 | 0 | alert: None, |
209 | 0 | } |
210 | 0 | } |
211 | | |
212 | | /// Takes back the client connection. Will return `None` if called more than once or if the |
213 | | /// connection has been accepted. |
214 | | /// |
215 | | /// # Example |
216 | | /// |
217 | | /// ```no_run |
218 | | /// # fn choose_server_config( |
219 | | /// # _: rustls::server::ClientHello, |
220 | | /// # ) -> std::sync::Arc<rustls::ServerConfig> { |
221 | | /// # unimplemented!(); |
222 | | /// # } |
223 | | /// # #[allow(unused_variables)] |
224 | | /// # async fn listen() { |
225 | | /// use tokio::io::AsyncWriteExt; |
226 | | /// let listener = tokio::net::TcpListener::bind("127.0.0.1:4443").await.unwrap(); |
227 | | /// let (stream, _) = listener.accept().await.unwrap(); |
228 | | /// |
229 | | /// let acceptor = tokio_rustls::LazyConfigAcceptor::new(rustls::server::Acceptor::default(), stream); |
230 | | /// tokio::pin!(acceptor); |
231 | | /// |
232 | | /// match acceptor.as_mut().await { |
233 | | /// Ok(start) => { |
234 | | /// let clientHello = start.client_hello(); |
235 | | /// let config = choose_server_config(clientHello); |
236 | | /// let stream = start.into_stream(config).await.unwrap(); |
237 | | /// // Proceed with handling the ServerConnection... |
238 | | /// } |
239 | | /// Err(err) => { |
240 | | /// if let Some(mut stream) = acceptor.take_io() { |
241 | | /// stream |
242 | | /// .write_all( |
243 | | /// format!("HTTP/1.1 400 Invalid Input\r\n\r\n\r\n{:?}\n", err) |
244 | | /// .as_bytes() |
245 | | /// ) |
246 | | /// .await |
247 | | /// .unwrap(); |
248 | | /// } |
249 | | /// } |
250 | | /// } |
251 | | /// # } |
252 | | /// ``` |
253 | 0 | pub fn take_io(&mut self) -> Option<IO> { |
254 | 0 | self.io.take() |
255 | 0 | } |
256 | | } |
257 | | |
258 | | impl<IO> Future for LazyConfigAcceptor<IO> |
259 | | where |
260 | | IO: AsyncRead + AsyncWrite + Unpin, |
261 | | { |
262 | | type Output = Result<StartHandshake<IO>, io::Error>; |
263 | | |
264 | 0 | fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { |
265 | 0 | let this = self.get_mut(); |
266 | | loop { |
267 | 0 | let io = match this.io.as_mut() { |
268 | 0 | Some(io) => io, |
269 | | None => { |
270 | 0 | return Poll::Ready(Err(io::Error::new( |
271 | 0 | io::ErrorKind::Other, |
272 | 0 | "acceptor cannot be polled after acceptance", |
273 | 0 | ))) |
274 | | } |
275 | | }; |
276 | | |
277 | 0 | if let Some((err, mut alert)) = this.alert.take() { |
278 | 0 | match alert.write(&mut common::SyncWriteAdapter { io, cx }) { |
279 | 0 | Err(e) if e.kind() == io::ErrorKind::WouldBlock => { |
280 | 0 | this.alert = Some((err, alert)); |
281 | 0 | return Poll::Pending; |
282 | | } |
283 | | Ok(0) | Err(_) => { |
284 | 0 | return Poll::Ready(Err(io::Error::new(io::ErrorKind::InvalidData, err))) |
285 | | } |
286 | | Ok(_) => { |
287 | 0 | this.alert = Some((err, alert)); |
288 | 0 | continue; |
289 | | } |
290 | | }; |
291 | 0 | } |
292 | | |
293 | 0 | let mut reader = common::SyncReadAdapter { io, cx }; |
294 | 0 | match this.acceptor.read_tls(&mut reader) { |
295 | 0 | Ok(0) => return Err(io::ErrorKind::UnexpectedEof.into()).into(), |
296 | 0 | Ok(_) => {} |
297 | 0 | Err(e) if e.kind() == io::ErrorKind::WouldBlock => return Poll::Pending, |
298 | 0 | Err(e) => return Err(e).into(), |
299 | | } |
300 | | |
301 | 0 | match this.acceptor.accept() { |
302 | 0 | Ok(Some(accepted)) => { |
303 | 0 | let io = this.io.take().unwrap(); |
304 | 0 | return Poll::Ready(Ok(StartHandshake { accepted, io })); |
305 | | } |
306 | 0 | Ok(None) => {} |
307 | 0 | Err((err, alert)) => { |
308 | 0 | this.alert = Some((err, alert)); |
309 | 0 | } |
310 | | } |
311 | | } |
312 | 0 | } |
313 | | } |
314 | | |
315 | | pub struct StartHandshake<IO> { |
316 | | accepted: rustls::server::Accepted, |
317 | | io: IO, |
318 | | } |
319 | | |
320 | | impl<IO> StartHandshake<IO> |
321 | | where |
322 | | IO: AsyncRead + AsyncWrite + Unpin, |
323 | | { |
324 | 0 | pub fn client_hello(&self) -> rustls::server::ClientHello<'_> { |
325 | 0 | self.accepted.client_hello() |
326 | 0 | } |
327 | | |
328 | 0 | pub fn into_stream(self, config: Arc<ServerConfig>) -> Accept<IO> { |
329 | 0 | self.into_stream_with(config, |_| ()) |
330 | 0 | } |
331 | | |
332 | 0 | pub fn into_stream_with<F>(self, config: Arc<ServerConfig>, f: F) -> Accept<IO> |
333 | 0 | where |
334 | 0 | F: FnOnce(&mut ServerConnection), |
335 | | { |
336 | 0 | let mut conn = match self.accepted.into_connection(config) { |
337 | 0 | Ok(conn) => conn, |
338 | 0 | Err((error, alert)) => { |
339 | 0 | return Accept(MidHandshake::SendAlert { |
340 | 0 | io: self.io, |
341 | 0 | alert, |
342 | 0 | // TODO(eliza): should this really return an `io::Error`? |
343 | 0 | // Probably not... |
344 | 0 | error: io::Error::new(io::ErrorKind::InvalidData, error), |
345 | 0 | }); |
346 | | } |
347 | | }; |
348 | 0 | f(&mut conn); |
349 | | |
350 | 0 | Accept(MidHandshake::Handshaking(server::TlsStream { |
351 | 0 | session: conn, |
352 | 0 | io: self.io, |
353 | 0 | state: TlsState::Stream, |
354 | 0 | })) |
355 | 0 | } |
356 | | } |
357 | | |
358 | | /// Future returned from `TlsConnector::connect` which will resolve |
359 | | /// once the connection handshake has finished. |
360 | | pub struct Connect<IO>(MidHandshake<client::TlsStream<IO>>); |
361 | | |
362 | | /// Future returned from `TlsAcceptor::accept` which will resolve |
363 | | /// once the accept handshake has finished. |
364 | | pub struct Accept<IO>(MidHandshake<server::TlsStream<IO>>); |
365 | | |
366 | | /// Like [Connect], but returns `IO` on failure. |
367 | | pub struct FallibleConnect<IO>(MidHandshake<client::TlsStream<IO>>); |
368 | | |
369 | | /// Like [Accept], but returns `IO` on failure. |
370 | | pub struct FallibleAccept<IO>(MidHandshake<server::TlsStream<IO>>); |
371 | | |
372 | | impl<IO> Connect<IO> { |
373 | | #[inline] |
374 | 0 | pub fn into_fallible(self) -> FallibleConnect<IO> { |
375 | 0 | FallibleConnect(self.0) |
376 | 0 | } |
377 | | |
378 | 0 | pub fn get_ref(&self) -> Option<&IO> { |
379 | 0 | match &self.0 { |
380 | 0 | MidHandshake::Handshaking(sess) => Some(sess.get_ref().0), |
381 | 0 | MidHandshake::SendAlert { io, .. } => Some(io), |
382 | 0 | MidHandshake::Error { io, .. } => Some(io), |
383 | 0 | MidHandshake::End => None, |
384 | | } |
385 | 0 | } |
386 | | |
387 | 0 | pub fn get_mut(&mut self) -> Option<&mut IO> { |
388 | 0 | match &mut self.0 { |
389 | 0 | MidHandshake::Handshaking(sess) => Some(sess.get_mut().0), |
390 | 0 | MidHandshake::SendAlert { io, .. } => Some(io), |
391 | 0 | MidHandshake::Error { io, .. } => Some(io), |
392 | 0 | MidHandshake::End => None, |
393 | | } |
394 | 0 | } |
395 | | } |
396 | | |
397 | | impl<IO> Accept<IO> { |
398 | | #[inline] |
399 | 0 | pub fn into_fallible(self) -> FallibleAccept<IO> { |
400 | 0 | FallibleAccept(self.0) |
401 | 0 | } |
402 | | |
403 | 0 | pub fn get_ref(&self) -> Option<&IO> { |
404 | 0 | match &self.0 { |
405 | 0 | MidHandshake::Handshaking(sess) => Some(sess.get_ref().0), |
406 | 0 | MidHandshake::SendAlert { io, .. } => Some(io), |
407 | 0 | MidHandshake::Error { io, .. } => Some(io), |
408 | 0 | MidHandshake::End => None, |
409 | | } |
410 | 0 | } |
411 | | |
412 | 0 | pub fn get_mut(&mut self) -> Option<&mut IO> { |
413 | 0 | match &mut self.0 { |
414 | 0 | MidHandshake::Handshaking(sess) => Some(sess.get_mut().0), |
415 | 0 | MidHandshake::SendAlert { io, .. } => Some(io), |
416 | 0 | MidHandshake::Error { io, .. } => Some(io), |
417 | 0 | MidHandshake::End => None, |
418 | | } |
419 | 0 | } |
420 | | } |
421 | | |
422 | | impl<IO: AsyncRead + AsyncWrite + Unpin> Future for Connect<IO> { |
423 | | type Output = io::Result<client::TlsStream<IO>>; |
424 | | |
425 | | #[inline] |
426 | 0 | fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { |
427 | 0 | Pin::new(&mut self.0).poll(cx).map_err(|(err, _)| err) |
428 | 0 | } Unexecuted instantiation: <tokio_rustls::Connect<hyper_util::rt::tokio::TokioIo<hyper_util::rt::tokio::TokioIo<tokio::net::tcp::stream::TcpStream>>> as core::future::future::Future>::poll Unexecuted instantiation: <tokio_rustls::Connect<ztunnel::proxy::h2::TokioH2Stream> as core::future::future::Future>::poll Unexecuted instantiation: <tokio_rustls::Connect<tokio::net::tcp::stream::TcpStream> as core::future::future::Future>::poll Unexecuted instantiation: <tokio_rustls::Connect<_> as core::future::future::Future>::poll |
429 | | } |
430 | | |
431 | | impl<IO: AsyncRead + AsyncWrite + Unpin> Future for Accept<IO> { |
432 | | type Output = io::Result<server::TlsStream<IO>>; |
433 | | |
434 | | #[inline] |
435 | 0 | fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { |
436 | 0 | Pin::new(&mut self.0).poll(cx).map_err(|(err, _)| err) |
437 | 0 | } Unexecuted instantiation: <tokio_rustls::Accept<tokio::net::tcp::stream::TcpStream> as core::future::future::Future>::poll Unexecuted instantiation: <tokio_rustls::Accept<_> as core::future::future::Future>::poll |
438 | | } |
439 | | |
440 | | impl<IO: AsyncRead + AsyncWrite + Unpin> Future for FallibleConnect<IO> { |
441 | | type Output = Result<client::TlsStream<IO>, (io::Error, IO)>; |
442 | | |
443 | | #[inline] |
444 | 0 | fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { |
445 | 0 | Pin::new(&mut self.0).poll(cx) |
446 | 0 | } |
447 | | } |
448 | | |
449 | | impl<IO: AsyncRead + AsyncWrite + Unpin> Future for FallibleAccept<IO> { |
450 | | type Output = Result<server::TlsStream<IO>, (io::Error, IO)>; |
451 | | |
452 | | #[inline] |
453 | 0 | fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { |
454 | 0 | Pin::new(&mut self.0).poll(cx) |
455 | 0 | } |
456 | | } |
457 | | |
458 | | /// Unified TLS stream type |
459 | | /// |
460 | | /// This abstracts over the inner `client::TlsStream` and `server::TlsStream`, so you can use |
461 | | /// a single type to keep both client- and server-initiated TLS-encrypted connections. |
462 | | #[allow(clippy::large_enum_variant)] // https://github.com/rust-lang/rust-clippy/issues/9798 |
463 | | #[derive(Debug)] |
464 | | pub enum TlsStream<T> { |
465 | | Client(client::TlsStream<T>), |
466 | | Server(server::TlsStream<T>), |
467 | | } |
468 | | |
469 | | impl<T> TlsStream<T> { |
470 | 0 | pub fn get_ref(&self) -> (&T, &CommonState) { |
471 | | use TlsStream::*; |
472 | 0 | match self { |
473 | 0 | Client(io) => { |
474 | 0 | let (io, session) = io.get_ref(); |
475 | 0 | (io, session) |
476 | | } |
477 | 0 | Server(io) => { |
478 | 0 | let (io, session) = io.get_ref(); |
479 | 0 | (io, session) |
480 | | } |
481 | | } |
482 | 0 | } |
483 | | |
484 | 0 | pub fn get_mut(&mut self) -> (&mut T, &mut CommonState) { |
485 | | use TlsStream::*; |
486 | 0 | match self { |
487 | 0 | Client(io) => { |
488 | 0 | let (io, session) = io.get_mut(); |
489 | 0 | (io, &mut *session) |
490 | | } |
491 | 0 | Server(io) => { |
492 | 0 | let (io, session) = io.get_mut(); |
493 | 0 | (io, &mut *session) |
494 | | } |
495 | | } |
496 | 0 | } |
497 | | } |
498 | | |
499 | | impl<T> From<client::TlsStream<T>> for TlsStream<T> { |
500 | 0 | fn from(s: client::TlsStream<T>) -> Self { |
501 | 0 | Self::Client(s) |
502 | 0 | } |
503 | | } |
504 | | |
505 | | impl<T> From<server::TlsStream<T>> for TlsStream<T> { |
506 | 0 | fn from(s: server::TlsStream<T>) -> Self { |
507 | 0 | Self::Server(s) |
508 | 0 | } |
509 | | } |
510 | | |
511 | | #[cfg(unix)] |
512 | | impl<S> AsRawFd for TlsStream<S> |
513 | | where |
514 | | S: AsRawFd, |
515 | | { |
516 | 0 | fn as_raw_fd(&self) -> RawFd { |
517 | 0 | self.get_ref().0.as_raw_fd() |
518 | 0 | } |
519 | | } |
520 | | |
521 | | #[cfg(windows)] |
522 | | impl<S> AsRawSocket for TlsStream<S> |
523 | | where |
524 | | S: AsRawSocket, |
525 | | { |
526 | | fn as_raw_socket(&self) -> RawSocket { |
527 | | self.get_ref().0.as_raw_socket() |
528 | | } |
529 | | } |
530 | | |
531 | | impl<T> AsyncRead for TlsStream<T> |
532 | | where |
533 | | T: AsyncRead + AsyncWrite + Unpin, |
534 | | { |
535 | | #[inline] |
536 | 0 | fn poll_read( |
537 | 0 | self: Pin<&mut Self>, |
538 | 0 | cx: &mut Context<'_>, |
539 | 0 | buf: &mut ReadBuf<'_>, |
540 | 0 | ) -> Poll<io::Result<()>> { |
541 | 0 | match self.get_mut() { |
542 | 0 | TlsStream::Client(x) => Pin::new(x).poll_read(cx, buf), |
543 | 0 | TlsStream::Server(x) => Pin::new(x).poll_read(cx, buf), |
544 | | } |
545 | 0 | } |
546 | | } |
547 | | |
548 | | impl<T> AsyncWrite for TlsStream<T> |
549 | | where |
550 | | T: AsyncRead + AsyncWrite + Unpin, |
551 | | { |
552 | | #[inline] |
553 | 0 | fn poll_write( |
554 | 0 | self: Pin<&mut Self>, |
555 | 0 | cx: &mut Context<'_>, |
556 | 0 | buf: &[u8], |
557 | 0 | ) -> Poll<io::Result<usize>> { |
558 | 0 | match self.get_mut() { |
559 | 0 | TlsStream::Client(x) => Pin::new(x).poll_write(cx, buf), |
560 | 0 | TlsStream::Server(x) => Pin::new(x).poll_write(cx, buf), |
561 | | } |
562 | 0 | } |
563 | | |
564 | | #[inline] |
565 | 0 | fn poll_write_vectored( |
566 | 0 | self: Pin<&mut Self>, |
567 | 0 | cx: &mut Context<'_>, |
568 | 0 | bufs: &[io::IoSlice<'_>], |
569 | 0 | ) -> Poll<io::Result<usize>> { |
570 | 0 | match self.get_mut() { |
571 | 0 | TlsStream::Client(x) => Pin::new(x).poll_write_vectored(cx, bufs), |
572 | 0 | TlsStream::Server(x) => Pin::new(x).poll_write_vectored(cx, bufs), |
573 | | } |
574 | 0 | } |
575 | | |
576 | | #[inline] |
577 | 0 | fn is_write_vectored(&self) -> bool { |
578 | 0 | match self { |
579 | 0 | TlsStream::Client(x) => x.is_write_vectored(), |
580 | 0 | TlsStream::Server(x) => x.is_write_vectored(), |
581 | | } |
582 | 0 | } |
583 | | |
584 | | #[inline] |
585 | 0 | fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> { |
586 | 0 | match self.get_mut() { |
587 | 0 | TlsStream::Client(x) => Pin::new(x).poll_flush(cx), |
588 | 0 | TlsStream::Server(x) => Pin::new(x).poll_flush(cx), |
589 | | } |
590 | 0 | } |
591 | | |
592 | | #[inline] |
593 | 0 | fn poll_shutdown(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> { |
594 | 0 | match self.get_mut() { |
595 | 0 | TlsStream::Client(x) => Pin::new(x).poll_shutdown(cx), |
596 | 0 | TlsStream::Server(x) => Pin::new(x).poll_shutdown(cx), |
597 | | } |
598 | 0 | } |
599 | | } |