1pub 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#[allow(clippy::large_enum_variant)]
33pub enum Stream {
34 Tcp(TcpStream),
36
37 #[cfg(unix)]
39 Uds(UnixStream),
40
41 #[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