protwrap/tokio/
client.rs

1//! Helpers for working on the end-points initiating connection requests.
2
3pub mod connector;
4
5use std::{
6  pin::Pin,
7  task::{Context, Poll}
8};
9
10use tokio::{
11  io::{AsyncRead, AsyncWrite, ReadBuf, Result},
12  net::TcpStream
13};
14
15#[cfg(unix)]
16use tokio::net::UnixStream;
17
18#[cfg(feature = "tls")]
19use tokio_rustls::client::TlsStream;
20
21pub use connector::{Connector, TcpConnInfo};
22
23#[cfg(unix)]
24pub use connector::UdsConnInfo;
25
26#[cfg(feature = "tls")]
27pub use connector::TlsTcpConnInfo;
28
29
30/// Representation of a stream acting as a client end-point (actively
31/// established connection).
32#[allow(clippy::large_enum_variant)]
33pub enum Stream {
34  /// TCP-based client stream.
35  Tcp(TcpStream),
36
37  /// Unix local domain client stream.
38  #[cfg(unix)]
39  Uds(UnixStream),
40
41  /// TLS, based on TCP, client stream.
42  #[cfg(feature = "tls")]
43  TlsTcp(TlsStream<TcpStream>)
44}
45
46impl Stream {
47  #[inline]
48  pub const fn reqflush(&self) -> bool {
49    match self {
50      Self::Tcp(_) => false,
51      #[cfg(unix)]
52      Self::Uds(_) => false,
53      #[cfg(feature = "tls")]
54      Self::TlsTcp(_) => true
55    }
56  }
57
58  pub fn ciphersuite(&self) -> Option<String> {
59    match self {
60      #[cfg(feature = "tls")]
61      Self::TlsTcp(ref strm) => {
62        let (_, conn) = strm.get_ref();
63        let ciphersuite = conn.negotiated_cipher_suite()?;
64        Some(format!("{:?}", ciphersuite.suite()))
65      }
66      _ => None
67    }
68  }
69}
70
71macro_rules! delegate_call {
72  ($self:ident.$method:ident($($args:ident),+)) => {
73    unsafe {
74      match $self.get_unchecked_mut() {
75        Self::Tcp(s) => Pin::new_unchecked(s).$method($($args),+),
76        #[cfg(unix)]
77        Self::Uds(s) => Pin::new_unchecked(s).$method($($args),+),
78        #[cfg(feature = "tls")]
79        Self::TlsTcp(s) => Pin::new_unchecked(s).$method($($args),+),
80      }
81    }
82  }
83}
84
85impl AsyncRead for Stream {
86  fn poll_read(
87    self: Pin<&mut Self>,
88    cx: &mut Context<'_>,
89    buf: &mut ReadBuf<'_>
90  ) -> Poll<Result<()>> {
91    delegate_call!(self.poll_read(cx, buf))
92  }
93}
94
95impl AsyncWrite for Stream {
96  fn poll_write(
97    self: Pin<&mut Self>,
98    cx: &mut Context<'_>,
99    buf: &[u8]
100  ) -> Poll<Result<usize>> {
101    delegate_call!(self.poll_write(cx, buf))
102  }
103
104  fn poll_flush(
105    self: Pin<&mut Self>,
106    cx: &mut Context<'_>
107  ) -> Poll<tokio::io::Result<()>> {
108    delegate_call!(self.poll_flush(cx))
109  }
110
111  fn poll_shutdown(
112    self: Pin<&mut Self>,
113    cx: &mut Context<'_>
114  ) -> Poll<tokio::io::Result<()>> {
115    delegate_call!(self.poll_shutdown(cx))
116  }
117}
118
119// vim: set ft=rust et sw=2 ts=2 sts=2 cinoptions=2 tw=79 :