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, ProcessIdentity};
23#[cfg(unix)]
24use super::unix::{unix_recvmsg, unixgram_recvmsg};
25
26#[pin_project(project = ConnectionProjected)]
31pub enum Connection {
32 Tcp(#[pin] TcpStream, SocketAddr),
34
35 #[cfg(unix)]
37 Unix(#[pin] tokio::net::UnixStream),
38
39 #[cfg(windows)]
41 NamedPipe(#[pin] NamedPipeServer),
42}
43
44impl Connection {
45 async fn receive<B: BufMut>(&mut self, buf: &mut B) -> io::Result<(usize, ConnectionAddress)> {
46 match self {
47 Self::Tcp(inner, addr) => inner.read_buf(buf).await.map(|n| (n, (*addr).into())),
48 #[cfg(unix)]
49 Self::Unix(inner) => unix_recvmsg(inner, buf).await,
50 #[cfg(windows)]
51 Self::NamedPipe(inner) => inner
52 .read_buf(buf)
53 .await
54 .map(|n| (n, ConnectionAddress::ProcessLike(ProcessIdentity::Unavailable))),
55 }
56 }
57
58 pub(super) fn remote_addr(&self) -> ConnectionAddress {
59 match self {
60 Self::Tcp(_, addr) => ConnectionAddress::SocketLike(*addr),
61 #[cfg(unix)]
62 Self::Unix(_) => ConnectionAddress::ProcessLike(ProcessIdentity::Unavailable),
63 #[cfg(windows)]
64 Self::NamedPipe(_) => ConnectionAddress::ProcessLike(ProcessIdentity::Unavailable),
65 }
66 }
67}
68
69impl AsyncRead for Connection {
70 fn poll_read(self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &mut ReadBuf<'_>) -> Poll<io::Result<()>> {
71 match self.project() {
72 ConnectionProjected::Tcp(inner, _) => inner.poll_read(cx, buf),
73 #[cfg(unix)]
74 ConnectionProjected::Unix(inner) => inner.poll_read(cx, buf),
75 #[cfg(windows)]
76 ConnectionProjected::NamedPipe(inner) => inner.poll_read(cx, buf),
77 }
78 }
79}
80
81impl AsyncWrite for Connection {
82 fn poll_write(self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &[u8]) -> Poll<io::Result<usize>> {
83 match self.project() {
84 ConnectionProjected::Tcp(inner, _) => inner.poll_write(cx, buf),
85 #[cfg(unix)]
86 ConnectionProjected::Unix(inner) => inner.poll_write(cx, buf),
87 #[cfg(windows)]
88 ConnectionProjected::NamedPipe(inner) => inner.poll_write(cx, buf),
89 }
90 }
91
92 fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
93 match self.project() {
94 ConnectionProjected::Tcp(inner, _) => inner.poll_flush(cx),
95 #[cfg(unix)]
96 ConnectionProjected::Unix(inner) => inner.poll_flush(cx),
97 #[cfg(windows)]
98 ConnectionProjected::NamedPipe(inner) => inner.poll_flush(cx),
99 }
100 }
101
102 fn poll_shutdown(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
103 match self.project() {
104 ConnectionProjected::Tcp(inner, _) => inner.poll_shutdown(cx),
105 #[cfg(unix)]
106 ConnectionProjected::Unix(inner) => inner.poll_shutdown(cx),
107 #[cfg(windows)]
108 ConnectionProjected::NamedPipe(inner) => inner.poll_shutdown(cx),
109 }
110 }
111}
112
113pub(crate) struct SubleasedSocket<T> {
123 socket: Arc<T>,
130
131 _sublease: Option<Sublease>,
135}
136
137impl<T> SubleasedSocket<T> {
138 pub(crate) fn new(socket: Arc<T>, sublease: Option<Sublease>) -> Self {
139 Self {
140 socket,
141 _sublease: sublease,
142 }
143 }
144}
145
146impl<T> Deref for SubleasedSocket<T> {
147 type Target = T;
148
149 fn deref(&self) -> &Self::Target {
150 &self.socket
151 }
152}
153
154enum Connectionless {
159 Udp(SubleasedSocket<UdpSocket>),
161
162 #[cfg(unix)]
164 Unixgram(SubleasedSocket<tokio::net::UnixDatagram>),
165}
166
167impl Connectionless {
168 async fn receive<B: BufMut>(&mut self, buf: &mut B) -> io::Result<(usize, ConnectionAddress)> {
169 match self {
170 Self::Udp(inner) => inner.recv_buf_from(buf).await.map(|(n, addr)| (n, addr.into())),
171 #[cfg(unix)]
172 Self::Unixgram(inner) => unixgram_recvmsg(inner, buf).await,
173 }
174 }
175}
176
177enum StreamInner {
178 Connection { socket: Connection },
179 Connectionless { socket: Connectionless },
180}
181
182pub struct Stream {
202 inner: StreamInner,
203}
204
205impl Stream {
206 pub fn is_connectionless(&self) -> bool {
208 matches!(self.inner, StreamInner::Connectionless { .. })
209 }
210
211 pub async fn receive<B: BufMut>(&mut self, buf: &mut B) -> io::Result<(usize, ConnectionAddress)> {
219 match &mut self.inner {
220 StreamInner::Connection { socket } => socket.receive(buf).await,
221 StreamInner::Connectionless { socket } => socket.receive(buf).await,
222 }
223 }
224
225 #[cfg(test)]
226 pub(crate) fn recv_buffer_size(&self) -> io::Result<usize> {
227 match &self.inner {
228 StreamInner::Connection { socket } => match socket {
229 Connection::Tcp(inner, _) => socket2::SockRef::from(inner).recv_buffer_size(),
230 #[cfg(unix)]
231 Connection::Unix(inner) => socket2::SockRef::from(inner).recv_buffer_size(),
232 #[cfg(windows)]
233 Connection::NamedPipe(_) => Ok(0),
234 },
235 StreamInner::Connectionless { socket } => match socket {
236 Connectionless::Udp(inner) => socket2::SockRef::from(&**inner).recv_buffer_size(),
237 #[cfg(unix)]
238 Connectionless::Unixgram(inner) => socket2::SockRef::from(&**inner).recv_buffer_size(),
239 },
240 }
241 }
242}
243
244impl From<(TcpStream, SocketAddr)> for Stream {
245 fn from((stream, remote_addr): (TcpStream, SocketAddr)) -> Self {
246 Self {
247 inner: StreamInner::Connection {
248 socket: Connection::Tcp(stream, remote_addr),
249 },
250 }
251 }
252}
253
254impl From<SubleasedSocket<UdpSocket>> for Stream {
255 fn from(socket: SubleasedSocket<UdpSocket>) -> Self {
256 Self {
257 inner: StreamInner::Connectionless {
258 socket: Connectionless::Udp(socket),
259 },
260 }
261 }
262}
263
264impl From<Arc<UdpSocket>> for Stream {
265 fn from(socket: Arc<UdpSocket>) -> Self {
266 Self::from(SubleasedSocket::new(socket, None))
267 }
268}
269
270impl From<UdpSocket> for Stream {
271 fn from(socket: UdpSocket) -> Self {
272 Self::from(Arc::new(socket))
273 }
274}
275
276#[cfg(unix)]
277impl From<SubleasedSocket<UnixDatagram>> for Stream {
278 fn from(socket: SubleasedSocket<UnixDatagram>) -> Self {
279 Self {
280 inner: StreamInner::Connectionless {
281 socket: Connectionless::Unixgram(socket),
282 },
283 }
284 }
285}
286
287#[cfg(unix)]
288impl From<Arc<UnixDatagram>> for Stream {
289 fn from(socket: Arc<UnixDatagram>) -> Self {
290 Self::from(SubleasedSocket::new(socket, None))
291 }
292}
293
294#[cfg(unix)]
295impl From<UnixDatagram> for Stream {
296 fn from(socket: UnixDatagram) -> Self {
297 Self::from(Arc::new(socket))
298 }
299}
300
301#[cfg(unix)]
302impl From<UnixStream> for Stream {
303 fn from(stream: UnixStream) -> Self {
304 Self {
305 inner: StreamInner::Connection {
306 socket: Connection::Unix(stream),
307 },
308 }
309 }
310}
311
312#[cfg(windows)]
313impl From<NamedPipeServer> for Stream {
314 fn from(stream: NamedPipeServer) -> Self {
315 Self {
316 inner: StreamInner::Connection {
317 socket: Connection::NamedPipe(stream),
318 },
319 }
320 }
321}