1use std::{
2 io,
3 net::SocketAddr,
4 pin::Pin,
5 task::{Context, Poll},
6};
7
8use bytes::BufMut;
9use pin_project::pin_project;
10#[cfg(windows)]
11use tokio::net::windows::named_pipe::NamedPipeServer;
12use tokio::{
13 io::{AsyncRead, AsyncReadExt as _, AsyncWrite, ReadBuf},
14 net::{TcpStream, UdpSocket},
15};
16
17use super::addr::{ConnectionAddress, ProcessIdentity};
18#[cfg(unix)]
19use super::unix::{unix_recvmsg, unixgram_recvmsg};
20
21#[pin_project(project = ConnectionProjected)]
26pub enum Connection {
27 Tcp(#[pin] TcpStream, SocketAddr),
29
30 #[cfg(unix)]
32 Unix(#[pin] tokio::net::UnixStream),
33
34 #[cfg(windows)]
36 NamedPipe(#[pin] NamedPipeServer),
37}
38
39impl Connection {
40 async fn receive<B: BufMut>(&mut self, buf: &mut B) -> io::Result<(usize, ConnectionAddress)> {
41 match self {
42 Self::Tcp(inner, addr) => inner.read_buf(buf).await.map(|n| (n, (*addr).into())),
43 #[cfg(unix)]
44 Self::Unix(inner) => unix_recvmsg(inner, buf).await,
45 #[cfg(windows)]
46 Self::NamedPipe(inner) => inner
47 .read_buf(buf)
48 .await
49 .map(|n| (n, ConnectionAddress::ProcessLike(ProcessIdentity::Unavailable))),
50 }
51 }
52
53 pub(super) fn remote_addr(&self) -> ConnectionAddress {
54 match self {
55 Self::Tcp(_, addr) => ConnectionAddress::SocketLike(*addr),
56 #[cfg(unix)]
57 Self::Unix(_) => ConnectionAddress::ProcessLike(ProcessIdentity::Unavailable),
58 #[cfg(windows)]
59 Self::NamedPipe(_) => ConnectionAddress::ProcessLike(ProcessIdentity::Unavailable),
60 }
61 }
62}
63
64impl AsyncRead for Connection {
65 fn poll_read(self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &mut ReadBuf<'_>) -> Poll<io::Result<()>> {
66 match self.project() {
67 ConnectionProjected::Tcp(inner, _) => inner.poll_read(cx, buf),
68 #[cfg(unix)]
69 ConnectionProjected::Unix(inner) => inner.poll_read(cx, buf),
70 #[cfg(windows)]
71 ConnectionProjected::NamedPipe(inner) => inner.poll_read(cx, buf),
72 }
73 }
74}
75
76impl AsyncWrite for Connection {
77 fn poll_write(self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &[u8]) -> Poll<io::Result<usize>> {
78 match self.project() {
79 ConnectionProjected::Tcp(inner, _) => inner.poll_write(cx, buf),
80 #[cfg(unix)]
81 ConnectionProjected::Unix(inner) => inner.poll_write(cx, buf),
82 #[cfg(windows)]
83 ConnectionProjected::NamedPipe(inner) => inner.poll_write(cx, buf),
84 }
85 }
86
87 fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
88 match self.project() {
89 ConnectionProjected::Tcp(inner, _) => inner.poll_flush(cx),
90 #[cfg(unix)]
91 ConnectionProjected::Unix(inner) => inner.poll_flush(cx),
92 #[cfg(windows)]
93 ConnectionProjected::NamedPipe(inner) => inner.poll_flush(cx),
94 }
95 }
96
97 fn poll_shutdown(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
98 match self.project() {
99 ConnectionProjected::Tcp(inner, _) => inner.poll_shutdown(cx),
100 #[cfg(unix)]
101 ConnectionProjected::Unix(inner) => inner.poll_shutdown(cx),
102 #[cfg(windows)]
103 ConnectionProjected::NamedPipe(inner) => inner.poll_shutdown(cx),
104 }
105 }
106}
107
108enum Connectionless {
113 Udp(UdpSocket),
115
116 #[cfg(unix)]
118 Unixgram(tokio::net::UnixDatagram),
119}
120
121impl Connectionless {
122 async fn receive<B: BufMut>(&mut self, buf: &mut B) -> io::Result<(usize, ConnectionAddress)> {
123 match self {
124 Self::Udp(inner) => inner.recv_buf_from(buf).await.map(|(n, addr)| (n, addr.into())),
125 #[cfg(unix)]
126 Self::Unixgram(inner) => unixgram_recvmsg(inner, buf).await,
127 }
128 }
129}
130
131enum StreamInner {
132 Connection { socket: Connection },
133 Connectionless { socket: Connectionless },
134}
135
136pub struct Stream {
156 inner: StreamInner,
157}
158
159impl Stream {
160 pub fn is_connectionless(&self) -> bool {
162 matches!(self.inner, StreamInner::Connectionless { .. })
163 }
164
165 pub async fn receive<B: BufMut>(&mut self, buf: &mut B) -> io::Result<(usize, ConnectionAddress)> {
173 match &mut self.inner {
174 StreamInner::Connection { socket } => socket.receive(buf).await,
175 StreamInner::Connectionless { socket } => socket.receive(buf).await,
176 }
177 }
178
179 #[cfg(test)]
180 pub(crate) fn recv_buffer_size(&self) -> io::Result<usize> {
181 match &self.inner {
182 StreamInner::Connection { socket } => match socket {
183 Connection::Tcp(inner, _) => socket2::SockRef::from(inner).recv_buffer_size(),
184 #[cfg(unix)]
185 Connection::Unix(inner) => socket2::SockRef::from(inner).recv_buffer_size(),
186 #[cfg(windows)]
187 Connection::NamedPipe(_) => Ok(0),
188 },
189 StreamInner::Connectionless { socket } => match socket {
190 Connectionless::Udp(inner) => socket2::SockRef::from(inner).recv_buffer_size(),
191 #[cfg(unix)]
192 Connectionless::Unixgram(inner) => socket2::SockRef::from(inner).recv_buffer_size(),
193 },
194 }
195 }
196}
197
198impl From<(TcpStream, SocketAddr)> for Stream {
199 fn from((stream, remote_addr): (TcpStream, SocketAddr)) -> Self {
200 Self {
201 inner: StreamInner::Connection {
202 socket: Connection::Tcp(stream, remote_addr),
203 },
204 }
205 }
206}
207
208impl From<UdpSocket> for Stream {
209 fn from(socket: UdpSocket) -> Self {
210 Self {
211 inner: StreamInner::Connectionless {
212 socket: Connectionless::Udp(socket),
213 },
214 }
215 }
216}
217
218#[cfg(unix)]
219impl From<tokio::net::UnixDatagram> for Stream {
220 fn from(socket: tokio::net::UnixDatagram) -> Self {
221 Self {
222 inner: StreamInner::Connectionless {
223 socket: Connectionless::Unixgram(socket),
224 },
225 }
226 }
227}
228
229#[cfg(unix)]
230impl From<tokio::net::UnixStream> for Stream {
231 fn from(stream: tokio::net::UnixStream) -> Self {
232 Self {
233 inner: StreamInner::Connection {
234 socket: Connection::Unix(stream),
235 },
236 }
237 }
238}
239
240#[cfg(windows)]
241impl From<NamedPipeServer> for Stream {
242 fn from(stream: NamedPipeServer) -> Self {
243 Self {
244 inner: StreamInner::Connection {
245 socket: Connection::NamedPipe(stream),
246 },
247 }
248 }
249}