/rust/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-rustls-0.26.4/src/client.rs
Line | Count | Source |
1 | | use std::future::Future; |
2 | | #[cfg(unix)] |
3 | | use std::os::unix::io::{AsRawFd, RawFd}; |
4 | | #[cfg(windows)] |
5 | | use std::os::windows::io::{AsRawSocket, RawSocket}; |
6 | | use std::pin::Pin; |
7 | | #[cfg(feature = "early-data")] |
8 | | use std::task::Waker; |
9 | | use std::task::{Context, Poll}; |
10 | | use std::{ |
11 | | io::{self, BufRead as _}, |
12 | | sync::Arc, |
13 | | }; |
14 | | |
15 | | use rustls::{pki_types::ServerName, ClientConfig, ClientConnection}; |
16 | | use tokio::io::{AsyncBufRead, AsyncRead, AsyncWrite, ReadBuf}; |
17 | | |
18 | | use crate::common::{IoSession, MidHandshake, Stream, TlsState}; |
19 | | |
20 | | /// A wrapper around a `rustls::ClientConfig`, providing an async `connect` method. |
21 | | #[derive(Clone)] |
22 | | pub struct TlsConnector { |
23 | | inner: Arc<ClientConfig>, |
24 | | #[cfg(feature = "early-data")] |
25 | | early_data: bool, |
26 | | } |
27 | | |
28 | | impl TlsConnector { |
29 | | /// Enable 0-RTT. |
30 | | /// |
31 | | /// If you want to use 0-RTT, |
32 | | /// You must also set `ClientConfig.enable_early_data` to `true`. |
33 | | #[cfg(feature = "early-data")] |
34 | | pub fn early_data(mut self, flag: bool) -> Self { |
35 | | self.early_data = flag; |
36 | | self |
37 | | } |
38 | | |
39 | | #[inline] |
40 | 0 | pub fn connect<IO>(&self, domain: ServerName<'static>, stream: IO) -> Connect<IO> |
41 | 0 | where |
42 | 0 | IO: AsyncRead + AsyncWrite + Unpin, |
43 | | { |
44 | 0 | self.connect_impl(domain, stream, None, |_| ()) |
45 | 0 | } Unexecuted instantiation: <tokio_rustls::client::TlsConnector>::connect::<hyper_util::rt::tokio::TokioIo<hyper_util::rt::tokio::TokioIo<tokio::net::tcp::stream::TcpStream>>> Unexecuted instantiation: <tokio_rustls::client::TlsConnector>::connect::<hyper_util::rt::tokio::TokioIo<hyper_util::rt::tokio::TokioIo<tokio::net::unix::stream::UnixStream>>> Unexecuted instantiation: <tokio_rustls::client::TlsConnector>::connect::<hyper_util::rt::tokio::TokioIo<hyper_rustls::stream::MaybeHttpsStream<hyper_util::rt::tokio::TokioIo<tokio::net::tcp::stream::TcpStream>>>> Unexecuted instantiation: <tokio_rustls::client::TlsConnector>::connect::<_> |
46 | | |
47 | | #[inline] |
48 | 0 | pub fn connect_with<IO, F>(&self, domain: ServerName<'static>, stream: IO, f: F) -> Connect<IO> |
49 | 0 | where |
50 | 0 | IO: AsyncRead + AsyncWrite + Unpin, |
51 | 0 | F: FnOnce(&mut ClientConnection), |
52 | | { |
53 | 0 | self.connect_impl(domain, stream, None, f) |
54 | 0 | } |
55 | | |
56 | 0 | fn connect_impl<IO, F>( |
57 | 0 | &self, |
58 | 0 | domain: ServerName<'static>, |
59 | 0 | stream: IO, |
60 | 0 | alpn_protocols: Option<Vec<Vec<u8>>>, |
61 | 0 | f: F, |
62 | 0 | ) -> Connect<IO> |
63 | 0 | where |
64 | 0 | IO: AsyncRead + AsyncWrite + Unpin, |
65 | 0 | F: FnOnce(&mut ClientConnection), |
66 | | { |
67 | 0 | let alpn = alpn_protocols.unwrap_or_else(|| self.inner.alpn_protocols.clone()); Unexecuted instantiation: <tokio_rustls::client::TlsConnector>::connect_impl::<hyper_util::rt::tokio::TokioIo<hyper_util::rt::tokio::TokioIo<tokio::net::tcp::stream::TcpStream>>, <tokio_rustls::client::TlsConnector>::connect<hyper_util::rt::tokio::TokioIo<hyper_util::rt::tokio::TokioIo<tokio::net::tcp::stream::TcpStream>>>::{closure#0}>::{closure#0}Unexecuted instantiation: <tokio_rustls::client::TlsConnector>::connect_impl::<hyper_util::rt::tokio::TokioIo<hyper_util::rt::tokio::TokioIo<tokio::net::unix::stream::UnixStream>>, <tokio_rustls::client::TlsConnector>::connect<hyper_util::rt::tokio::TokioIo<hyper_util::rt::tokio::TokioIo<tokio::net::unix::stream::UnixStream>>>::{closure#0}>::{closure#0}Unexecuted instantiation: <tokio_rustls::client::TlsConnector>::connect_impl::<hyper_util::rt::tokio::TokioIo<hyper_rustls::stream::MaybeHttpsStream<hyper_util::rt::tokio::TokioIo<tokio::net::tcp::stream::TcpStream>>>, <tokio_rustls::client::TlsConnector>::connect<hyper_util::rt::tokio::TokioIo<hyper_rustls::stream::MaybeHttpsStream<hyper_util::rt::tokio::TokioIo<tokio::net::tcp::stream::TcpStream>>>>::{closure#0}>::{closure#0}Unexecuted instantiation: <tokio_rustls::client::TlsConnector>::connect_impl::<_, _>::{closure#0} |
68 | 0 | let mut session = match ClientConnection::new_with_alpn(self.inner.clone(), domain, alpn) { |
69 | 0 | Ok(session) => session, |
70 | 0 | Err(error) => { |
71 | 0 | return Connect(MidHandshake::Error { |
72 | 0 | io: stream, |
73 | 0 | // TODO(eliza): should this really return an `io::Error`? |
74 | 0 | // Probably not... |
75 | 0 | error: io::Error::new(io::ErrorKind::Other, error), |
76 | 0 | }); |
77 | | } |
78 | | }; |
79 | 0 | f(&mut session); |
80 | | |
81 | 0 | Connect(MidHandshake::Handshaking(TlsStream { |
82 | 0 | io: stream, |
83 | 0 |
|
84 | 0 | #[cfg(not(feature = "early-data"))] |
85 | 0 | state: TlsState::Stream, |
86 | 0 |
|
87 | 0 | #[cfg(feature = "early-data")] |
88 | 0 | state: if self.early_data && session.early_data().is_some() { |
89 | 0 | TlsState::EarlyData(0, Vec::new()) |
90 | 0 | } else { |
91 | 0 | TlsState::Stream |
92 | 0 | }, |
93 | 0 |
|
94 | 0 | need_flush: false, |
95 | 0 |
|
96 | 0 | #[cfg(feature = "early-data")] |
97 | 0 | early_waker: None, |
98 | 0 |
|
99 | 0 | session, |
100 | 0 | })) |
101 | 0 | } Unexecuted instantiation: <tokio_rustls::client::TlsConnector>::connect_impl::<hyper_util::rt::tokio::TokioIo<hyper_util::rt::tokio::TokioIo<tokio::net::tcp::stream::TcpStream>>, <tokio_rustls::client::TlsConnector>::connect<hyper_util::rt::tokio::TokioIo<hyper_util::rt::tokio::TokioIo<tokio::net::tcp::stream::TcpStream>>>::{closure#0}>Unexecuted instantiation: <tokio_rustls::client::TlsConnector>::connect_impl::<hyper_util::rt::tokio::TokioIo<hyper_util::rt::tokio::TokioIo<tokio::net::unix::stream::UnixStream>>, <tokio_rustls::client::TlsConnector>::connect<hyper_util::rt::tokio::TokioIo<hyper_util::rt::tokio::TokioIo<tokio::net::unix::stream::UnixStream>>>::{closure#0}>Unexecuted instantiation: <tokio_rustls::client::TlsConnector>::connect_impl::<hyper_util::rt::tokio::TokioIo<hyper_rustls::stream::MaybeHttpsStream<hyper_util::rt::tokio::TokioIo<tokio::net::tcp::stream::TcpStream>>>, <tokio_rustls::client::TlsConnector>::connect<hyper_util::rt::tokio::TokioIo<hyper_rustls::stream::MaybeHttpsStream<hyper_util::rt::tokio::TokioIo<tokio::net::tcp::stream::TcpStream>>>>::{closure#0}>Unexecuted instantiation: <tokio_rustls::client::TlsConnector>::connect_impl::<_, _> |
102 | | |
103 | 0 | pub fn with_alpn(&self, alpn_protocols: Vec<Vec<u8>>) -> TlsConnectorWithAlpn<'_> { |
104 | 0 | TlsConnectorWithAlpn { |
105 | 0 | inner: self, |
106 | 0 | alpn_protocols, |
107 | 0 | } |
108 | 0 | } |
109 | | |
110 | | /// Get a read-only reference to underlying config |
111 | 0 | pub fn config(&self) -> &Arc<ClientConfig> { |
112 | 0 | &self.inner |
113 | 0 | } |
114 | | } |
115 | | |
116 | | impl From<Arc<ClientConfig>> for TlsConnector { |
117 | 0 | fn from(inner: Arc<ClientConfig>) -> Self { |
118 | 0 | Self { |
119 | 0 | inner, |
120 | 0 | #[cfg(feature = "early-data")] |
121 | 0 | early_data: false, |
122 | 0 | } |
123 | 0 | } |
124 | | } |
125 | | |
126 | | pub struct TlsConnectorWithAlpn<'c> { |
127 | | inner: &'c TlsConnector, |
128 | | alpn_protocols: Vec<Vec<u8>>, |
129 | | } |
130 | | |
131 | | impl TlsConnectorWithAlpn<'_> { |
132 | | #[inline] |
133 | 0 | pub fn connect<IO>(self, domain: ServerName<'static>, stream: IO) -> Connect<IO> |
134 | 0 | where |
135 | 0 | IO: AsyncRead + AsyncWrite + Unpin, |
136 | | { |
137 | 0 | self.inner |
138 | 0 | .connect_impl(domain, stream, Some(self.alpn_protocols), |_| ()) |
139 | 0 | } |
140 | | |
141 | | #[inline] |
142 | 0 | pub fn connect_with<IO, F>(self, domain: ServerName<'static>, stream: IO, f: F) -> Connect<IO> |
143 | 0 | where |
144 | 0 | IO: AsyncRead + AsyncWrite + Unpin, |
145 | 0 | F: FnOnce(&mut ClientConnection), |
146 | | { |
147 | 0 | self.inner |
148 | 0 | .connect_impl(domain, stream, Some(self.alpn_protocols), f) |
149 | 0 | } |
150 | | } |
151 | | |
152 | | /// Future returned from `TlsConnector::connect` which will resolve |
153 | | /// once the connection handshake has finished. |
154 | | pub struct Connect<IO>(MidHandshake<TlsStream<IO>>); |
155 | | |
156 | | impl<IO> Connect<IO> { |
157 | | #[inline] |
158 | 0 | pub fn into_fallible(self) -> FallibleConnect<IO> { |
159 | 0 | FallibleConnect(self.0) |
160 | 0 | } |
161 | | |
162 | 0 | pub fn get_ref(&self) -> Option<&IO> { |
163 | 0 | match &self.0 { |
164 | 0 | MidHandshake::Handshaking(sess) => Some(sess.get_ref().0), |
165 | 0 | MidHandshake::SendAlert { io, .. } => Some(io), |
166 | 0 | MidHandshake::Error { io, .. } => Some(io), |
167 | 0 | MidHandshake::End => None, |
168 | | } |
169 | 0 | } |
170 | | |
171 | 0 | pub fn get_mut(&mut self) -> Option<&mut IO> { |
172 | 0 | match &mut self.0 { |
173 | 0 | MidHandshake::Handshaking(sess) => Some(sess.get_mut().0), |
174 | 0 | MidHandshake::SendAlert { io, .. } => Some(io), |
175 | 0 | MidHandshake::Error { io, .. } => Some(io), |
176 | 0 | MidHandshake::End => None, |
177 | | } |
178 | 0 | } |
179 | | } |
180 | | |
181 | | impl<IO: AsyncRead + AsyncWrite + Unpin> Future for Connect<IO> { |
182 | | type Output = io::Result<TlsStream<IO>>; |
183 | | |
184 | | #[inline] |
185 | 0 | fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { |
186 | 0 | Pin::new(&mut self.0).poll(cx).map_err(|(err, _)| err) |
187 | 0 | } Unexecuted instantiation: <tokio_rustls::client::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::client::Connect<hyper_util::rt::tokio::TokioIo<hyper_util::rt::tokio::TokioIo<tokio::net::unix::stream::UnixStream>>> as core::future::future::Future>::poll Unexecuted instantiation: <tokio_rustls::client::Connect<hyper_util::rt::tokio::TokioIo<hyper_rustls::stream::MaybeHttpsStream<hyper_util::rt::tokio::TokioIo<tokio::net::tcp::stream::TcpStream>>>> as core::future::future::Future>::poll Unexecuted instantiation: <tokio_rustls::client::Connect<_> as core::future::future::Future>::poll |
188 | | } |
189 | | |
190 | | impl<IO: AsyncRead + AsyncWrite + Unpin> Future for FallibleConnect<IO> { |
191 | | type Output = Result<TlsStream<IO>, (io::Error, IO)>; |
192 | | |
193 | | #[inline] |
194 | 0 | fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { |
195 | 0 | Pin::new(&mut self.0).poll(cx) |
196 | 0 | } |
197 | | } |
198 | | |
199 | | /// Like [Connect], but returns `IO` on failure. |
200 | | pub struct FallibleConnect<IO>(MidHandshake<TlsStream<IO>>); |
201 | | |
202 | | /// A wrapper around an underlying raw stream which implements the TLS or SSL |
203 | | /// protocol. |
204 | | #[derive(Debug)] |
205 | | pub struct TlsStream<IO> { |
206 | | pub(crate) io: IO, |
207 | | pub(crate) session: ClientConnection, |
208 | | pub(crate) state: TlsState, |
209 | | pub(crate) need_flush: bool, |
210 | | |
211 | | #[cfg(feature = "early-data")] |
212 | | pub(crate) early_waker: Option<Waker>, |
213 | | } |
214 | | |
215 | | impl<IO> TlsStream<IO> { |
216 | | #[inline] |
217 | 0 | pub fn get_ref(&self) -> (&IO, &ClientConnection) { |
218 | 0 | (&self.io, &self.session) |
219 | 0 | } Unexecuted instantiation: <tokio_rustls::client::TlsStream<hyper_util::rt::tokio::TokioIo<hyper_util::rt::tokio::TokioIo<tokio::net::tcp::stream::TcpStream>>>>::get_ref Unexecuted instantiation: <tokio_rustls::client::TlsStream<hyper_util::rt::tokio::TokioIo<hyper_util::rt::tokio::TokioIo<tokio::net::unix::stream::UnixStream>>>>::get_ref Unexecuted instantiation: <tokio_rustls::client::TlsStream<hyper_util::rt::tokio::TokioIo<hyper_rustls::stream::MaybeHttpsStream<hyper_util::rt::tokio::TokioIo<tokio::net::tcp::stream::TcpStream>>>>>::get_ref Unexecuted instantiation: <tokio_rustls::client::TlsStream<hyper_util::rt::tokio::TokioIo<hyper_rustls::stream::MaybeHttpsStream<hyper_util::rt::tokio::TokioIo<tokio::net::unix::stream::UnixStream>>>>>::get_ref Unexecuted instantiation: <tokio_rustls::client::TlsStream<_>>::get_ref |
220 | | |
221 | | #[inline] |
222 | 0 | pub fn get_mut(&mut self) -> (&mut IO, &mut ClientConnection) { |
223 | 0 | (&mut self.io, &mut self.session) |
224 | 0 | } |
225 | | |
226 | | #[inline] |
227 | 0 | pub fn into_inner(self) -> (IO, ClientConnection) { |
228 | 0 | (self.io, self.session) |
229 | 0 | } |
230 | | } |
231 | | |
232 | | #[cfg(unix)] |
233 | | impl<S> AsRawFd for TlsStream<S> |
234 | | where |
235 | | S: AsRawFd, |
236 | | { |
237 | 0 | fn as_raw_fd(&self) -> RawFd { |
238 | 0 | self.get_ref().0.as_raw_fd() |
239 | 0 | } |
240 | | } |
241 | | |
242 | | #[cfg(windows)] |
243 | | impl<S> AsRawSocket for TlsStream<S> |
244 | | where |
245 | | S: AsRawSocket, |
246 | | { |
247 | | fn as_raw_socket(&self) -> RawSocket { |
248 | | self.get_ref().0.as_raw_socket() |
249 | | } |
250 | | } |
251 | | |
252 | | impl<IO> IoSession for TlsStream<IO> { |
253 | | type Io = IO; |
254 | | type Session = ClientConnection; |
255 | | |
256 | | #[inline] |
257 | 0 | fn skip_handshake(&self) -> bool { |
258 | 0 | self.state.is_early_data() |
259 | 0 | } Unexecuted instantiation: <tokio_rustls::client::TlsStream<hyper_util::rt::tokio::TokioIo<hyper_util::rt::tokio::TokioIo<tokio::net::tcp::stream::TcpStream>>> as tokio_rustls::common::handshake::IoSession>::skip_handshake Unexecuted instantiation: <tokio_rustls::client::TlsStream<hyper_util::rt::tokio::TokioIo<hyper_util::rt::tokio::TokioIo<tokio::net::unix::stream::UnixStream>>> as tokio_rustls::common::handshake::IoSession>::skip_handshake Unexecuted instantiation: <tokio_rustls::client::TlsStream<hyper_util::rt::tokio::TokioIo<hyper_rustls::stream::MaybeHttpsStream<hyper_util::rt::tokio::TokioIo<tokio::net::tcp::stream::TcpStream>>>> as tokio_rustls::common::handshake::IoSession>::skip_handshake Unexecuted instantiation: <tokio_rustls::client::TlsStream<_> as tokio_rustls::common::handshake::IoSession>::skip_handshake |
260 | | |
261 | | #[inline] |
262 | 0 | fn get_mut(&mut self) -> (&mut TlsState, &mut Self::Io, &mut Self::Session, &mut bool) { |
263 | 0 | ( |
264 | 0 | &mut self.state, |
265 | 0 | &mut self.io, |
266 | 0 | &mut self.session, |
267 | 0 | &mut self.need_flush, |
268 | 0 | ) |
269 | 0 | } Unexecuted instantiation: <tokio_rustls::client::TlsStream<hyper_util::rt::tokio::TokioIo<hyper_util::rt::tokio::TokioIo<tokio::net::tcp::stream::TcpStream>>> as tokio_rustls::common::handshake::IoSession>::get_mut Unexecuted instantiation: <tokio_rustls::client::TlsStream<hyper_util::rt::tokio::TokioIo<hyper_util::rt::tokio::TokioIo<tokio::net::unix::stream::UnixStream>>> as tokio_rustls::common::handshake::IoSession>::get_mut Unexecuted instantiation: <tokio_rustls::client::TlsStream<hyper_util::rt::tokio::TokioIo<hyper_rustls::stream::MaybeHttpsStream<hyper_util::rt::tokio::TokioIo<tokio::net::tcp::stream::TcpStream>>>> as tokio_rustls::common::handshake::IoSession>::get_mut Unexecuted instantiation: <tokio_rustls::client::TlsStream<_> as tokio_rustls::common::handshake::IoSession>::get_mut |
270 | | |
271 | | #[inline] |
272 | 0 | fn into_io(self) -> Self::Io { |
273 | 0 | self.io |
274 | 0 | } Unexecuted instantiation: <tokio_rustls::client::TlsStream<hyper_util::rt::tokio::TokioIo<hyper_util::rt::tokio::TokioIo<tokio::net::tcp::stream::TcpStream>>> as tokio_rustls::common::handshake::IoSession>::into_io Unexecuted instantiation: <tokio_rustls::client::TlsStream<hyper_util::rt::tokio::TokioIo<hyper_util::rt::tokio::TokioIo<tokio::net::unix::stream::UnixStream>>> as tokio_rustls::common::handshake::IoSession>::into_io Unexecuted instantiation: <tokio_rustls::client::TlsStream<hyper_util::rt::tokio::TokioIo<hyper_rustls::stream::MaybeHttpsStream<hyper_util::rt::tokio::TokioIo<tokio::net::tcp::stream::TcpStream>>>> as tokio_rustls::common::handshake::IoSession>::into_io Unexecuted instantiation: <tokio_rustls::client::TlsStream<_> as tokio_rustls::common::handshake::IoSession>::into_io |
275 | | } |
276 | | |
277 | | #[cfg(feature = "early-data")] |
278 | | impl<IO> TlsStream<IO> |
279 | | where |
280 | | IO: AsyncRead + AsyncWrite + Unpin, |
281 | | { |
282 | | fn poll_early_data(&mut self, cx: &mut Context<'_>) { |
283 | | // In the EarlyData state, we have not really established a Tls connection. |
284 | | // Before writing data through `AsyncWrite` and completing the tls handshake, |
285 | | // we ignore read readiness and return to pending. |
286 | | // |
287 | | // In order to avoid event loss, |
288 | | // we need to register a waker and wake it up after tls is connected. |
289 | | if self |
290 | | .early_waker |
291 | | .as_ref() |
292 | | .filter(|waker| cx.waker().will_wake(waker)) |
293 | | .is_none() |
294 | | { |
295 | | self.early_waker = Some(cx.waker().clone()); |
296 | | } |
297 | | } |
298 | | } |
299 | | |
300 | | impl<IO> AsyncRead for TlsStream<IO> |
301 | | where |
302 | | IO: AsyncRead + AsyncWrite + Unpin, |
303 | | { |
304 | 0 | fn poll_read( |
305 | 0 | mut self: Pin<&mut Self>, |
306 | 0 | cx: &mut Context<'_>, |
307 | 0 | buf: &mut ReadBuf<'_>, |
308 | 0 | ) -> Poll<io::Result<()>> { |
309 | 0 | let data = ready!(self.as_mut().poll_fill_buf(cx))?; |
310 | 0 | let len = data.len().min(buf.remaining()); |
311 | 0 | buf.put_slice(&data[..len]); |
312 | 0 | self.consume(len); |
313 | 0 | Poll::Ready(Ok(())) |
314 | 0 | } Unexecuted instantiation: <tokio_rustls::client::TlsStream<hyper_util::rt::tokio::TokioIo<hyper_util::rt::tokio::TokioIo<tokio::net::tcp::stream::TcpStream>>> as tokio::io::async_read::AsyncRead>::poll_read Unexecuted instantiation: <tokio_rustls::client::TlsStream<hyper_util::rt::tokio::TokioIo<hyper_util::rt::tokio::TokioIo<tokio::net::unix::stream::UnixStream>>> as tokio::io::async_read::AsyncRead>::poll_read Unexecuted instantiation: <tokio_rustls::client::TlsStream<hyper_util::rt::tokio::TokioIo<hyper_rustls::stream::MaybeHttpsStream<hyper_util::rt::tokio::TokioIo<tokio::net::tcp::stream::TcpStream>>>> as tokio::io::async_read::AsyncRead>::poll_read Unexecuted instantiation: <tokio_rustls::client::TlsStream<_> as tokio::io::async_read::AsyncRead>::poll_read |
315 | | } |
316 | | |
317 | | impl<IO> AsyncBufRead for TlsStream<IO> |
318 | | where |
319 | | IO: AsyncRead + AsyncWrite + Unpin, |
320 | | { |
321 | 0 | fn poll_fill_buf(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<&[u8]>> { |
322 | 0 | match self.state { |
323 | | #[cfg(feature = "early-data")] |
324 | | TlsState::EarlyData(..) => { |
325 | | self.get_mut().poll_early_data(cx); |
326 | | Poll::Pending |
327 | | } |
328 | | TlsState::Stream | TlsState::WriteShutdown => { |
329 | 0 | let this = self.get_mut(); |
330 | 0 | let stream = |
331 | 0 | Stream::new(&mut this.io, &mut this.session).set_eof(!this.state.readable()); |
332 | | |
333 | 0 | match stream.poll_fill_buf(cx) { |
334 | 0 | Poll::Ready(Ok(buf)) => { |
335 | 0 | if buf.is_empty() { |
336 | 0 | this.state.shutdown_read(); |
337 | 0 | } |
338 | | |
339 | 0 | Poll::Ready(Ok(buf)) |
340 | | } |
341 | 0 | Poll::Ready(Err(err)) if err.kind() == io::ErrorKind::ConnectionAborted => { |
342 | 0 | this.state.shutdown_read(); |
343 | 0 | Poll::Ready(Err(err)) |
344 | | } |
345 | 0 | output => output, |
346 | | } |
347 | | } |
348 | 0 | TlsState::ReadShutdown | TlsState::FullyShutdown => Poll::Ready(Ok(&[])), |
349 | | } |
350 | 0 | } Unexecuted instantiation: <tokio_rustls::client::TlsStream<hyper_util::rt::tokio::TokioIo<hyper_util::rt::tokio::TokioIo<tokio::net::tcp::stream::TcpStream>>> as tokio::io::async_buf_read::AsyncBufRead>::poll_fill_buf Unexecuted instantiation: <tokio_rustls::client::TlsStream<hyper_util::rt::tokio::TokioIo<hyper_util::rt::tokio::TokioIo<tokio::net::unix::stream::UnixStream>>> as tokio::io::async_buf_read::AsyncBufRead>::poll_fill_buf Unexecuted instantiation: <tokio_rustls::client::TlsStream<hyper_util::rt::tokio::TokioIo<hyper_rustls::stream::MaybeHttpsStream<hyper_util::rt::tokio::TokioIo<tokio::net::tcp::stream::TcpStream>>>> as tokio::io::async_buf_read::AsyncBufRead>::poll_fill_buf Unexecuted instantiation: <tokio_rustls::client::TlsStream<_> as tokio::io::async_buf_read::AsyncBufRead>::poll_fill_buf |
351 | | |
352 | 0 | fn consume(mut self: Pin<&mut Self>, amt: usize) { |
353 | 0 | self.session.reader().consume(amt); |
354 | 0 | } Unexecuted instantiation: <tokio_rustls::client::TlsStream<hyper_util::rt::tokio::TokioIo<hyper_util::rt::tokio::TokioIo<tokio::net::tcp::stream::TcpStream>>> as tokio::io::async_buf_read::AsyncBufRead>::consume Unexecuted instantiation: <tokio_rustls::client::TlsStream<hyper_util::rt::tokio::TokioIo<hyper_util::rt::tokio::TokioIo<tokio::net::unix::stream::UnixStream>>> as tokio::io::async_buf_read::AsyncBufRead>::consume Unexecuted instantiation: <tokio_rustls::client::TlsStream<hyper_util::rt::tokio::TokioIo<hyper_rustls::stream::MaybeHttpsStream<hyper_util::rt::tokio::TokioIo<tokio::net::tcp::stream::TcpStream>>>> as tokio::io::async_buf_read::AsyncBufRead>::consume Unexecuted instantiation: <tokio_rustls::client::TlsStream<_> as tokio::io::async_buf_read::AsyncBufRead>::consume |
355 | | } |
356 | | |
357 | | impl<IO> AsyncWrite for TlsStream<IO> |
358 | | where |
359 | | IO: AsyncRead + AsyncWrite + Unpin, |
360 | | { |
361 | | /// Note: that it does not guarantee the final data to be sent. |
362 | | /// To be cautious, you must manually call `flush`. |
363 | 0 | fn poll_write( |
364 | 0 | self: Pin<&mut Self>, |
365 | 0 | cx: &mut Context<'_>, |
366 | 0 | buf: &[u8], |
367 | 0 | ) -> Poll<io::Result<usize>> { |
368 | 0 | let this = self.get_mut(); |
369 | 0 | let mut stream = Stream::new(&mut this.io, &mut this.session) |
370 | 0 | .set_eof(!this.state.readable()) |
371 | 0 | .set_need_flush(this.need_flush); |
372 | | |
373 | | #[cfg(feature = "early-data")] |
374 | | { |
375 | | let bufs = [io::IoSlice::new(buf)]; |
376 | | let written = poll_handle_early_data( |
377 | | &mut this.state, |
378 | | &mut stream, |
379 | | &mut this.early_waker, |
380 | | cx, |
381 | | &bufs, |
382 | | )?; |
383 | | match written { |
384 | | Poll::Ready(0) => {} |
385 | | Poll::Ready(written) => return Poll::Ready(Ok(written)), |
386 | | Poll::Pending => { |
387 | | this.need_flush = stream.need_flush; |
388 | | return Poll::Pending; |
389 | | } |
390 | | } |
391 | | } |
392 | | |
393 | 0 | stream.as_mut_pin().poll_write(cx, buf) |
394 | 0 | } Unexecuted instantiation: <tokio_rustls::client::TlsStream<hyper_util::rt::tokio::TokioIo<hyper_util::rt::tokio::TokioIo<tokio::net::tcp::stream::TcpStream>>> as tokio::io::async_write::AsyncWrite>::poll_write Unexecuted instantiation: <tokio_rustls::client::TlsStream<hyper_util::rt::tokio::TokioIo<hyper_util::rt::tokio::TokioIo<tokio::net::unix::stream::UnixStream>>> as tokio::io::async_write::AsyncWrite>::poll_write Unexecuted instantiation: <tokio_rustls::client::TlsStream<hyper_util::rt::tokio::TokioIo<hyper_rustls::stream::MaybeHttpsStream<hyper_util::rt::tokio::TokioIo<tokio::net::tcp::stream::TcpStream>>>> as tokio::io::async_write::AsyncWrite>::poll_write Unexecuted instantiation: <tokio_rustls::client::TlsStream<_> as tokio::io::async_write::AsyncWrite>::poll_write |
395 | | |
396 | | /// Note: that it does not guarantee the final data to be sent. |
397 | | /// To be cautious, you must manually call `flush`. |
398 | 0 | fn poll_write_vectored( |
399 | 0 | self: Pin<&mut Self>, |
400 | 0 | cx: &mut Context<'_>, |
401 | 0 | bufs: &[io::IoSlice<'_>], |
402 | 0 | ) -> Poll<io::Result<usize>> { |
403 | 0 | let this = self.get_mut(); |
404 | 0 | let mut stream = Stream::new(&mut this.io, &mut this.session) |
405 | 0 | .set_eof(!this.state.readable()) |
406 | 0 | .set_need_flush(this.need_flush); |
407 | | |
408 | | #[cfg(feature = "early-data")] |
409 | | { |
410 | | let written = poll_handle_early_data( |
411 | | &mut this.state, |
412 | | &mut stream, |
413 | | &mut this.early_waker, |
414 | | cx, |
415 | | bufs, |
416 | | )?; |
417 | | match written { |
418 | | Poll::Ready(0) => {} |
419 | | Poll::Ready(written) => return Poll::Ready(Ok(written)), |
420 | | Poll::Pending => { |
421 | | this.need_flush = stream.need_flush; |
422 | | return Poll::Pending; |
423 | | } |
424 | | } |
425 | | } |
426 | | |
427 | 0 | stream.as_mut_pin().poll_write_vectored(cx, bufs) |
428 | 0 | } Unexecuted instantiation: <tokio_rustls::client::TlsStream<hyper_util::rt::tokio::TokioIo<hyper_util::rt::tokio::TokioIo<tokio::net::tcp::stream::TcpStream>>> as tokio::io::async_write::AsyncWrite>::poll_write_vectored Unexecuted instantiation: <tokio_rustls::client::TlsStream<hyper_util::rt::tokio::TokioIo<hyper_util::rt::tokio::TokioIo<tokio::net::unix::stream::UnixStream>>> as tokio::io::async_write::AsyncWrite>::poll_write_vectored Unexecuted instantiation: <tokio_rustls::client::TlsStream<hyper_util::rt::tokio::TokioIo<hyper_rustls::stream::MaybeHttpsStream<hyper_util::rt::tokio::TokioIo<tokio::net::tcp::stream::TcpStream>>>> as tokio::io::async_write::AsyncWrite>::poll_write_vectored Unexecuted instantiation: <tokio_rustls::client::TlsStream<_> as tokio::io::async_write::AsyncWrite>::poll_write_vectored |
429 | | |
430 | | #[inline] |
431 | 0 | fn is_write_vectored(&self) -> bool { |
432 | 0 | true |
433 | 0 | } Unexecuted instantiation: <tokio_rustls::client::TlsStream<hyper_util::rt::tokio::TokioIo<hyper_util::rt::tokio::TokioIo<tokio::net::tcp::stream::TcpStream>>> as tokio::io::async_write::AsyncWrite>::is_write_vectored Unexecuted instantiation: <tokio_rustls::client::TlsStream<hyper_util::rt::tokio::TokioIo<hyper_util::rt::tokio::TokioIo<tokio::net::unix::stream::UnixStream>>> as tokio::io::async_write::AsyncWrite>::is_write_vectored Unexecuted instantiation: <tokio_rustls::client::TlsStream<hyper_util::rt::tokio::TokioIo<hyper_rustls::stream::MaybeHttpsStream<hyper_util::rt::tokio::TokioIo<tokio::net::tcp::stream::TcpStream>>>> as tokio::io::async_write::AsyncWrite>::is_write_vectored Unexecuted instantiation: <tokio_rustls::client::TlsStream<_> as tokio::io::async_write::AsyncWrite>::is_write_vectored |
434 | | |
435 | 0 | fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> { |
436 | 0 | let this = self.get_mut(); |
437 | 0 | let mut stream = Stream::new(&mut this.io, &mut this.session) |
438 | 0 | .set_eof(!this.state.readable()) |
439 | 0 | .set_need_flush(this.need_flush); |
440 | | |
441 | | #[cfg(feature = "early-data")] |
442 | | { |
443 | | let written = poll_handle_early_data( |
444 | | &mut this.state, |
445 | | &mut stream, |
446 | | &mut this.early_waker, |
447 | | cx, |
448 | | &[], |
449 | | )?; |
450 | | if written.is_pending() { |
451 | | this.need_flush = stream.need_flush; |
452 | | return Poll::Pending; |
453 | | } |
454 | | } |
455 | | |
456 | 0 | stream.as_mut_pin().poll_flush(cx) |
457 | 0 | } Unexecuted instantiation: <tokio_rustls::client::TlsStream<hyper_util::rt::tokio::TokioIo<hyper_util::rt::tokio::TokioIo<tokio::net::tcp::stream::TcpStream>>> as tokio::io::async_write::AsyncWrite>::poll_flush Unexecuted instantiation: <tokio_rustls::client::TlsStream<hyper_util::rt::tokio::TokioIo<hyper_util::rt::tokio::TokioIo<tokio::net::unix::stream::UnixStream>>> as tokio::io::async_write::AsyncWrite>::poll_flush Unexecuted instantiation: <tokio_rustls::client::TlsStream<hyper_util::rt::tokio::TokioIo<hyper_rustls::stream::MaybeHttpsStream<hyper_util::rt::tokio::TokioIo<tokio::net::tcp::stream::TcpStream>>>> as tokio::io::async_write::AsyncWrite>::poll_flush Unexecuted instantiation: <tokio_rustls::client::TlsStream<_> as tokio::io::async_write::AsyncWrite>::poll_flush |
458 | | |
459 | 0 | fn poll_shutdown(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> { |
460 | | #[cfg(feature = "early-data")] |
461 | | { |
462 | | // complete handshake |
463 | | if matches!(self.state, TlsState::EarlyData(..)) { |
464 | | ready!(self.as_mut().poll_flush(cx))?; |
465 | | } |
466 | | } |
467 | | |
468 | 0 | if self.state.writeable() { |
469 | 0 | self.session.send_close_notify(); |
470 | 0 | self.state.shutdown_write(); |
471 | 0 | } |
472 | | |
473 | 0 | let this = self.get_mut(); |
474 | 0 | let mut stream = |
475 | 0 | Stream::new(&mut this.io, &mut this.session).set_eof(!this.state.readable()); |
476 | 0 | stream.as_mut_pin().poll_shutdown(cx) |
477 | 0 | } Unexecuted instantiation: <tokio_rustls::client::TlsStream<hyper_util::rt::tokio::TokioIo<hyper_util::rt::tokio::TokioIo<tokio::net::tcp::stream::TcpStream>>> as tokio::io::async_write::AsyncWrite>::poll_shutdown Unexecuted instantiation: <tokio_rustls::client::TlsStream<hyper_util::rt::tokio::TokioIo<hyper_util::rt::tokio::TokioIo<tokio::net::unix::stream::UnixStream>>> as tokio::io::async_write::AsyncWrite>::poll_shutdown Unexecuted instantiation: <tokio_rustls::client::TlsStream<hyper_util::rt::tokio::TokioIo<hyper_rustls::stream::MaybeHttpsStream<hyper_util::rt::tokio::TokioIo<tokio::net::tcp::stream::TcpStream>>>> as tokio::io::async_write::AsyncWrite>::poll_shutdown Unexecuted instantiation: <tokio_rustls::client::TlsStream<_> as tokio::io::async_write::AsyncWrite>::poll_shutdown |
478 | | } |
479 | | |
480 | | #[cfg(feature = "early-data")] |
481 | | fn poll_handle_early_data<IO>( |
482 | | state: &mut TlsState, |
483 | | stream: &mut Stream<IO, ClientConnection>, |
484 | | early_waker: &mut Option<Waker>, |
485 | | cx: &mut Context<'_>, |
486 | | bufs: &[io::IoSlice<'_>], |
487 | | ) -> Poll<io::Result<usize>> |
488 | | where |
489 | | IO: AsyncRead + AsyncWrite + Unpin, |
490 | | { |
491 | | if let TlsState::EarlyData(pos, data) = state { |
492 | | use std::io::Write; |
493 | | |
494 | | // write early data |
495 | | if let Some(mut early_data) = stream.session.early_data() { |
496 | | let mut written = 0; |
497 | | |
498 | | for buf in bufs { |
499 | | if buf.is_empty() { |
500 | | continue; |
501 | | } |
502 | | |
503 | | let len = match early_data.write(buf) { |
504 | | Ok(0) => break, |
505 | | Ok(n) => n, |
506 | | Err(err) => return Poll::Ready(Err(err)), |
507 | | }; |
508 | | |
509 | | written += len; |
510 | | data.extend_from_slice(&buf[..len]); |
511 | | |
512 | | if len < buf.len() { |
513 | | break; |
514 | | } |
515 | | } |
516 | | |
517 | | if written != 0 { |
518 | | return Poll::Ready(Ok(written)); |
519 | | } |
520 | | } |
521 | | |
522 | | // complete handshake |
523 | | while stream.session.is_handshaking() { |
524 | | ready!(stream.handshake(cx))?; |
525 | | } |
526 | | |
527 | | // write early data (fallback) |
528 | | if !stream.session.is_early_data_accepted() { |
529 | | while *pos < data.len() { |
530 | | let len = ready!(stream.as_mut_pin().poll_write(cx, &data[*pos..]))?; |
531 | | *pos += len; |
532 | | } |
533 | | } |
534 | | |
535 | | // end |
536 | | *state = TlsState::Stream; |
537 | | |
538 | | if let Some(waker) = early_waker.take() { |
539 | | waker.wake(); |
540 | | } |
541 | | } |
542 | | |
543 | | Poll::Ready(Ok(0)) |
544 | | } |