1use std::{
2 io,
3 net::SocketAddr,
4 ops::Deref,
5 pin::Pin,
6 sync::Arc,
7 task::{Context, Poll},
8};
9
10use bytes::BufMut;
11use pin_project::pin_project;
12use saluki_core::runtime::state::Sublease;
13#[cfg(windows)]
14use tokio::net::windows::named_pipe::NamedPipeServer;
15#[cfg(unix)]
16use tokio::net::{UnixDatagram, UnixStream};
17use tokio::{
18 io::{AsyncRead, AsyncReadExt as _, AsyncWrite, ReadBuf},
19 net::{TcpStream, UdpSocket},
20};
21
22use super::addr::ConnectionAddress;
23#[cfg(windows)]
24use super::addr::ProcessIdentity;
25#[cfg(unix)]
26use super::unix::{unix_peer_identity, unix_recvmsg, unixgram_recvmsg};
27
28#[pin_project(project = ConnectionProjected)]
33pub enum Connection {
34 Tcp(#[pin] TcpStream, SocketAddr),
36
37 #[cfg(unix)]
39 Unix(#[pin] tokio::net::UnixStream),
40
41 #[cfg(windows)]
43 NamedPipe(#[pin] NamedPipeServer),
44}
45
46impl Connection {
47 async fn receive<B: BufMut>(&mut self, buf: &mut B) -> io::Result<(usize, ConnectionAddress)> {
48 match self {
49 Self::Tcp(inner, addr) => inner.read_buf(buf).await.map(|n| (n, (*addr).into())),
50 #[cfg(unix)]
51 Self::Unix(inner) => unix_recvmsg(inner, buf).await,
52 #[cfg(windows)]
53 Self::NamedPipe(inner) => inner
54 .read_buf(buf)
55 .await
56 .map(|n| (n, ConnectionAddress::ProcessLike(ProcessIdentity::Unavailable))),
57 }
58 }
59
60 pub(super) fn remote_addr(&self) -> ConnectionAddress {
65 match self {
66 Self::Tcp(_, addr) => ConnectionAddress::SocketLike(*addr),
67 #[cfg(unix)]
68 Self::Unix(inner) => ConnectionAddress::ProcessLike(unix_peer_identity(inner)),
69 #[cfg(windows)]
70 Self::NamedPipe(_) => ConnectionAddress::ProcessLike(ProcessIdentity::Unavailable),
71 }
72 }
73}
74
75impl AsyncRead for Connection {
76 fn poll_read(self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &mut ReadBuf<'_>) -> Poll<io::Result<()>> {
77 match self.project() {
78 ConnectionProjected::Tcp(inner, _) => inner.poll_read(cx, buf),
79 #[cfg(unix)]
80 ConnectionProjected::Unix(inner) => inner.poll_read(cx, buf),
81 #[cfg(windows)]
82 ConnectionProjected::NamedPipe(inner) => inner.poll_read(cx, buf),
83 }
84 }
85}
86
87impl AsyncWrite for Connection {
88 fn poll_write(self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &[u8]) -> Poll<io::Result<usize>> {
89 match self.project() {
90 ConnectionProjected::Tcp(inner, _) => inner.poll_write(cx, buf),
91 #[cfg(unix)]
92 ConnectionProjected::Unix(inner) => inner.poll_write(cx, buf),
93 #[cfg(windows)]
94 ConnectionProjected::NamedPipe(inner) => inner.poll_write(cx, buf),
95 }
96 }
97
98 fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
99 match self.project() {
100 ConnectionProjected::Tcp(inner, _) => inner.poll_flush(cx),
101 #[cfg(unix)]
102 ConnectionProjected::Unix(inner) => inner.poll_flush(cx),
103 #[cfg(windows)]
104 ConnectionProjected::NamedPipe(inner) => inner.poll_flush(cx),
105 }
106 }
107
108 fn poll_shutdown(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
109 match self.project() {
110 ConnectionProjected::Tcp(inner, _) => inner.poll_shutdown(cx),
111 #[cfg(unix)]
112 ConnectionProjected::Unix(inner) => inner.poll_shutdown(cx),
113 #[cfg(windows)]
114 ConnectionProjected::NamedPipe(inner) => inner.poll_shutdown(cx),
115 }
116 }
117}
118
119pub(crate) struct SubleasedSocket<T> {
129 socket: Arc<T>,
136
137 _sublease: Option<Sublease>,
141}
142
143impl<T> SubleasedSocket<T> {
144 pub(crate) fn new(socket: Arc<T>, sublease: Option<Sublease>) -> Self {
145 Self {
146 socket,
147 _sublease: sublease,
148 }
149 }
150}
151
152impl<T> Deref for SubleasedSocket<T> {
153 type Target = T;
154
155 fn deref(&self) -> &Self::Target {
156 &self.socket
157 }
158}
159
160enum Connectionless {
165 Udp(SubleasedSocket<UdpSocket>),
167
168 #[cfg(unix)]
170 Unixgram(SubleasedSocket<tokio::net::UnixDatagram>),
171}
172
173impl Connectionless {
174 async fn receive<B: BufMut>(&mut self, buf: &mut B) -> io::Result<(usize, ConnectionAddress)> {
175 match self {
176 Self::Udp(inner) => inner.recv_buf_from(buf).await.map(|(n, addr)| (n, addr.into())),
177 #[cfg(unix)]
178 Self::Unixgram(inner) => unixgram_recvmsg(inner, buf).await,
179 }
180 }
181}
182
183enum StreamInner {
184 Connection { socket: Connection },
185 Connectionless { socket: Connectionless },
186}
187
188pub struct Stream {
208 inner: StreamInner,
209}
210
211impl Stream {
212 pub fn is_connectionless(&self) -> bool {
214 matches!(self.inner, StreamInner::Connectionless { .. })
215 }
216
217 pub async fn receive<B: BufMut>(&mut self, buf: &mut B) -> io::Result<(usize, ConnectionAddress)> {
225 match &mut self.inner {
226 StreamInner::Connection { socket } => socket.receive(buf).await,
227 StreamInner::Connectionless { socket } => socket.receive(buf).await,
228 }
229 }
230
231 #[cfg(test)]
232 pub(crate) fn recv_buffer_size(&self) -> io::Result<usize> {
233 match &self.inner {
234 StreamInner::Connection { socket } => match socket {
235 Connection::Tcp(inner, _) => socket2::SockRef::from(inner).recv_buffer_size(),
236 #[cfg(unix)]
237 Connection::Unix(inner) => socket2::SockRef::from(inner).recv_buffer_size(),
238 #[cfg(windows)]
239 Connection::NamedPipe(_) => Ok(0),
240 },
241 StreamInner::Connectionless { socket } => match socket {
242 Connectionless::Udp(inner) => socket2::SockRef::from(&**inner).recv_buffer_size(),
243 #[cfg(unix)]
244 Connectionless::Unixgram(inner) => socket2::SockRef::from(&**inner).recv_buffer_size(),
245 },
246 }
247 }
248}
249
250impl From<(TcpStream, SocketAddr)> for Stream {
251 fn from((stream, remote_addr): (TcpStream, SocketAddr)) -> Self {
252 Self {
253 inner: StreamInner::Connection {
254 socket: Connection::Tcp(stream, remote_addr),
255 },
256 }
257 }
258}
259
260impl From<SubleasedSocket<UdpSocket>> for Stream {
261 fn from(socket: SubleasedSocket<UdpSocket>) -> Self {
262 Self {
263 inner: StreamInner::Connectionless {
264 socket: Connectionless::Udp(socket),
265 },
266 }
267 }
268}
269
270impl From<Arc<UdpSocket>> for Stream {
271 fn from(socket: Arc<UdpSocket>) -> Self {
272 Self::from(SubleasedSocket::new(socket, None))
273 }
274}
275
276impl From<UdpSocket> for Stream {
277 fn from(socket: UdpSocket) -> Self {
278 Self::from(Arc::new(socket))
279 }
280}
281
282#[cfg(unix)]
283impl From<SubleasedSocket<UnixDatagram>> for Stream {
284 fn from(socket: SubleasedSocket<UnixDatagram>) -> Self {
285 Self {
286 inner: StreamInner::Connectionless {
287 socket: Connectionless::Unixgram(socket),
288 },
289 }
290 }
291}
292
293#[cfg(unix)]
294impl From<Arc<UnixDatagram>> for Stream {
295 fn from(socket: Arc<UnixDatagram>) -> Self {
296 Self::from(SubleasedSocket::new(socket, None))
297 }
298}
299
300#[cfg(unix)]
301impl From<UnixDatagram> for Stream {
302 fn from(socket: UnixDatagram) -> Self {
303 Self::from(Arc::new(socket))
304 }
305}
306
307#[cfg(unix)]
308impl From<UnixStream> for Stream {
309 fn from(stream: UnixStream) -> Self {
310 Self {
311 inner: StreamInner::Connection {
312 socket: Connection::Unix(stream),
313 },
314 }
315 }
316}
317
318#[cfg(windows)]
319impl From<NamedPipeServer> for Stream {
320 fn from(stream: NamedPipeServer) -> Self {
321 Self {
322 inner: StreamInner::Connection {
323 socket: Connection::NamedPipe(stream),
324 },
325 }
326 }
327}