async_nats_tokio_rustls_deps/
lib.rs1macro_rules! ready {
44 ( $e:expr ) => {
45 match $e {
46 std::task::Poll::Ready(t) => t,
47 std::task::Poll::Pending => return std::task::Poll::Pending,
48 }
49 };
50}
51
52pub mod client;
53mod common;
54pub mod server;
55
56use common::{MidHandshake, Stream, TlsState};
57use rustls::{ClientConfig, ClientConnection, CommonState, ServerConfig, ServerConnection};
58use std::future::Future;
59use std::io;
60#[cfg(unix)]
61use std::os::unix::io::{AsRawFd, RawFd};
62#[cfg(windows)]
63use std::os::windows::io::{AsRawSocket, RawSocket};
64use std::pin::Pin;
65use std::sync::Arc;
66use std::task::{Context, Poll};
67use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};
68
69pub use rustls;
70pub use webpki;
71
72#[derive(Clone)]
74pub struct TlsConnector {
75 inner: Arc<ClientConfig>,
76 #[cfg(feature = "early-data")]
77 early_data: bool,
78}
79
80#[derive(Clone)]
82pub struct TlsAcceptor {
83 inner: Arc<ServerConfig>,
84}
85
86impl From<Arc<ClientConfig>> for TlsConnector {
87 fn from(inner: Arc<ClientConfig>) -> TlsConnector {
88 TlsConnector {
89 inner,
90 #[cfg(feature = "early-data")]
91 early_data: false,
92 }
93 }
94}
95
96impl From<Arc<ServerConfig>> for TlsAcceptor {
97 fn from(inner: Arc<ServerConfig>) -> TlsAcceptor {
98 TlsAcceptor { inner }
99 }
100}
101
102impl TlsConnector {
103 #[cfg(feature = "early-data")]
108 pub fn early_data(mut self, flag: bool) -> TlsConnector {
109 self.early_data = flag;
110 self
111 }
112
113 #[inline]
114 pub fn connect<IO>(&self, domain: rustls::ServerName, stream: IO) -> Connect<IO>
115 where
116 IO: AsyncRead + AsyncWrite + Unpin,
117 {
118 self.connect_with(domain, stream, |_| ())
119 }
120
121 pub fn connect_with<IO, F>(&self, domain: rustls::ServerName, stream: IO, f: F) -> Connect<IO>
122 where
123 IO: AsyncRead + AsyncWrite + Unpin,
124 F: FnOnce(&mut ClientConnection),
125 {
126 let mut session = match ClientConnection::new(self.inner.clone(), domain) {
127 Ok(session) => session,
128 Err(error) => {
129 return Connect(MidHandshake::Error {
130 io: stream,
131 error: io::Error::new(io::ErrorKind::Other, error),
134 });
135 }
136 };
137 f(&mut session);
138
139 Connect(MidHandshake::Handshaking(client::TlsStream {
140 io: stream,
141
142 #[cfg(not(feature = "early-data"))]
143 state: TlsState::Stream,
144
145 #[cfg(feature = "early-data")]
146 state: if self.early_data && session.early_data().is_some() {
147 TlsState::EarlyData(0, Vec::new())
148 } else {
149 TlsState::Stream
150 },
151
152 #[cfg(feature = "early-data")]
153 early_waker: None,
154
155 session,
156 }))
157 }
158}
159
160impl TlsAcceptor {
161 #[inline]
162 pub fn accept<IO>(&self, stream: IO) -> Accept<IO>
163 where
164 IO: AsyncRead + AsyncWrite + Unpin,
165 {
166 self.accept_with(stream, |_| ())
167 }
168
169 pub fn accept_with<IO, F>(&self, stream: IO, f: F) -> Accept<IO>
170 where
171 IO: AsyncRead + AsyncWrite + Unpin,
172 F: FnOnce(&mut ServerConnection),
173 {
174 let mut session = match ServerConnection::new(self.inner.clone()) {
175 Ok(session) => session,
176 Err(error) => {
177 return Accept(MidHandshake::Error {
178 io: stream,
179 error: io::Error::new(io::ErrorKind::Other, error),
182 });
183 }
184 };
185 f(&mut session);
186
187 Accept(MidHandshake::Handshaking(server::TlsStream {
188 session,
189 io: stream,
190 state: TlsState::Stream,
191 }))
192 }
193}
194
195pub struct LazyConfigAcceptor<IO> {
196 acceptor: rustls::server::Acceptor,
197 io: Option<IO>,
198}
199
200impl<IO> LazyConfigAcceptor<IO>
201where
202 IO: AsyncRead + AsyncWrite + Unpin,
203{
204 #[inline]
205 pub fn new(acceptor: rustls::server::Acceptor, io: IO) -> Self {
206 Self {
207 acceptor,
208 io: Some(io),
209 }
210 }
211}
212
213impl<IO> Future for LazyConfigAcceptor<IO>
214where
215 IO: AsyncRead + AsyncWrite + Unpin,
216{
217 type Output = Result<StartHandshake<IO>, io::Error>;
218
219 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
220 let this = self.get_mut();
221 loop {
222 let io = match this.io.as_mut() {
223 Some(io) => io,
224 None => {
225 return Poll::Ready(Err(io::Error::new(
226 io::ErrorKind::Other,
227 "acceptor cannot be polled after acceptance",
228 )))
229 }
230 };
231
232 let mut reader = common::SyncReadAdapter { io, cx };
233 match this.acceptor.read_tls(&mut reader) {
234 Ok(0) => return Err(io::ErrorKind::UnexpectedEof.into()).into(),
235 Ok(_) => {}
236 Err(e) if e.kind() == io::ErrorKind::WouldBlock => return Poll::Pending,
237 Err(e) => return Err(e).into(),
238 }
239
240 match this.acceptor.accept() {
241 Ok(Some(accepted)) => {
242 let io = this.io.take().unwrap();
243 return Poll::Ready(Ok(StartHandshake { accepted, io }));
244 }
245 Ok(None) => continue,
246 Err(err) => {
247 return Poll::Ready(Err(io::Error::new(io::ErrorKind::InvalidInput, err)))
248 }
249 }
250 }
251 }
252}
253
254pub struct StartHandshake<IO> {
255 accepted: rustls::server::Accepted,
256 io: IO,
257}
258
259impl<IO> StartHandshake<IO>
260where
261 IO: AsyncRead + AsyncWrite + Unpin,
262{
263 pub fn client_hello(&self) -> rustls::server::ClientHello<'_> {
264 self.accepted.client_hello()
265 }
266
267 pub fn into_stream(self, config: Arc<ServerConfig>) -> Accept<IO> {
268 self.into_stream_with(config, |_| ())
269 }
270
271 pub fn into_stream_with<F>(self, config: Arc<ServerConfig>, f: F) -> Accept<IO>
272 where
273 F: FnOnce(&mut ServerConnection),
274 {
275 let mut conn = match self.accepted.into_connection(config) {
276 Ok(conn) => conn,
277 Err(error) => {
278 return Accept(MidHandshake::Error {
279 io: self.io,
280 error: io::Error::new(io::ErrorKind::Other, error),
283 });
284 }
285 };
286 f(&mut conn);
287
288 Accept(MidHandshake::Handshaking(server::TlsStream {
289 session: conn,
290 io: self.io,
291 state: TlsState::Stream,
292 }))
293 }
294}
295
296pub struct Connect<IO>(MidHandshake<client::TlsStream<IO>>);
299
300pub struct Accept<IO>(MidHandshake<server::TlsStream<IO>>);
303
304pub struct FallibleConnect<IO>(MidHandshake<client::TlsStream<IO>>);
306
307pub struct FallibleAccept<IO>(MidHandshake<server::TlsStream<IO>>);
309
310impl<IO> Connect<IO> {
311 #[inline]
312 pub fn into_fallible(self) -> FallibleConnect<IO> {
313 FallibleConnect(self.0)
314 }
315
316 pub fn get_ref(&self) -> Option<&IO> {
317 match &self.0 {
318 MidHandshake::Handshaking(sess) => Some(sess.get_ref().0),
319 MidHandshake::Error { io, .. } => Some(io),
320 MidHandshake::End => None,
321 }
322 }
323
324 pub fn get_mut(&mut self) -> Option<&mut IO> {
325 match &mut self.0 {
326 MidHandshake::Handshaking(sess) => Some(sess.get_mut().0),
327 MidHandshake::Error { io, .. } => Some(io),
328 MidHandshake::End => None,
329 }
330 }
331}
332
333impl<IO> Accept<IO> {
334 #[inline]
335 pub fn into_fallible(self) -> FallibleAccept<IO> {
336 FallibleAccept(self.0)
337 }
338
339 pub fn get_ref(&self) -> Option<&IO> {
340 match &self.0 {
341 MidHandshake::Handshaking(sess) => Some(sess.get_ref().0),
342 MidHandshake::Error { io, .. } => Some(io),
343 MidHandshake::End => None,
344 }
345 }
346
347 pub fn get_mut(&mut self) -> Option<&mut IO> {
348 match &mut self.0 {
349 MidHandshake::Handshaking(sess) => Some(sess.get_mut().0),
350 MidHandshake::Error { io, .. } => Some(io),
351 MidHandshake::End => None,
352 }
353 }
354}
355
356impl<IO: AsyncRead + AsyncWrite + Unpin> Future for Connect<IO> {
357 type Output = io::Result<client::TlsStream<IO>>;
358
359 #[inline]
360 fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
361 Pin::new(&mut self.0).poll(cx).map_err(|(err, _)| err)
362 }
363}
364
365impl<IO: AsyncRead + AsyncWrite + Unpin> Future for Accept<IO> {
366 type Output = io::Result<server::TlsStream<IO>>;
367
368 #[inline]
369 fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
370 Pin::new(&mut self.0).poll(cx).map_err(|(err, _)| err)
371 }
372}
373
374impl<IO: AsyncRead + AsyncWrite + Unpin> Future for FallibleConnect<IO> {
375 type Output = Result<client::TlsStream<IO>, (io::Error, IO)>;
376
377 #[inline]
378 fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
379 Pin::new(&mut self.0).poll(cx)
380 }
381}
382
383impl<IO: AsyncRead + AsyncWrite + Unpin> Future for FallibleAccept<IO> {
384 type Output = Result<server::TlsStream<IO>, (io::Error, IO)>;
385
386 #[inline]
387 fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
388 Pin::new(&mut self.0).poll(cx)
389 }
390}
391
392#[allow(clippy::large_enum_variant)] #[derive(Debug)]
398pub enum TlsStream<T> {
399 Client(client::TlsStream<T>),
400 Server(server::TlsStream<T>),
401}
402
403impl<T> TlsStream<T> {
404 pub fn get_ref(&self) -> (&T, &CommonState) {
405 use TlsStream::*;
406 match self {
407 Client(io) => {
408 let (io, session) = io.get_ref();
409 (io, session)
410 }
411 Server(io) => {
412 let (io, session) = io.get_ref();
413 (io, session)
414 }
415 }
416 }
417
418 pub fn get_mut(&mut self) -> (&mut T, &mut CommonState) {
419 use TlsStream::*;
420 match self {
421 Client(io) => {
422 let (io, session) = io.get_mut();
423 (io, &mut *session)
424 }
425 Server(io) => {
426 let (io, session) = io.get_mut();
427 (io, &mut *session)
428 }
429 }
430 }
431}
432
433impl<T> From<client::TlsStream<T>> for TlsStream<T> {
434 fn from(s: client::TlsStream<T>) -> Self {
435 Self::Client(s)
436 }
437}
438
439impl<T> From<server::TlsStream<T>> for TlsStream<T> {
440 fn from(s: server::TlsStream<T>) -> Self {
441 Self::Server(s)
442 }
443}
444
445#[cfg(unix)]
446impl<S> AsRawFd for TlsStream<S>
447where
448 S: AsRawFd,
449{
450 fn as_raw_fd(&self) -> RawFd {
451 self.get_ref().0.as_raw_fd()
452 }
453}
454
455#[cfg(windows)]
456impl<S> AsRawSocket for TlsStream<S>
457where
458 S: AsRawSocket,
459{
460 fn as_raw_socket(&self) -> RawSocket {
461 self.get_ref().0.as_raw_socket()
462 }
463}
464
465impl<T> AsyncRead for TlsStream<T>
466where
467 T: AsyncRead + AsyncWrite + Unpin,
468{
469 #[inline]
470 fn poll_read(
471 self: Pin<&mut Self>,
472 cx: &mut Context<'_>,
473 buf: &mut ReadBuf<'_>,
474 ) -> Poll<io::Result<()>> {
475 match self.get_mut() {
476 TlsStream::Client(x) => Pin::new(x).poll_read(cx, buf),
477 TlsStream::Server(x) => Pin::new(x).poll_read(cx, buf),
478 }
479 }
480}
481
482impl<T> AsyncWrite for TlsStream<T>
483where
484 T: AsyncRead + AsyncWrite + Unpin,
485{
486 #[inline]
487 fn poll_write(
488 self: Pin<&mut Self>,
489 cx: &mut Context<'_>,
490 buf: &[u8],
491 ) -> Poll<io::Result<usize>> {
492 match self.get_mut() {
493 TlsStream::Client(x) => Pin::new(x).poll_write(cx, buf),
494 TlsStream::Server(x) => Pin::new(x).poll_write(cx, buf),
495 }
496 }
497
498 #[inline]
499 fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
500 match self.get_mut() {
501 TlsStream::Client(x) => Pin::new(x).poll_flush(cx),
502 TlsStream::Server(x) => Pin::new(x).poll_flush(cx),
503 }
504 }
505
506 #[inline]
507 fn poll_shutdown(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
508 match self.get_mut() {
509 TlsStream::Client(x) => Pin::new(x).poll_shutdown(cx),
510 TlsStream::Server(x) => Pin::new(x).poll_shutdown(cx),
511 }
512 }
513}