1 //! `UnixDatagram` owned split support.
2 //!
3 //! A `UnixDatagram` can be split into an `OwnedSendHalf` and a `OwnedRecvHalf`
4 //! with the `UnixDatagram::into_split` method.
5 
6 use crate::future::poll_fn;
7 use crate::net::UnixDatagram;
8 
9 use std::error::Error;
10 use std::net::Shutdown;
11 use std::os::unix::net::SocketAddr;
12 use std::path::Path;
13 use std::sync::Arc;
14 use std::{fmt, io};
15 
split_owned(socket: UnixDatagram) -> (OwnedRecvHalf, OwnedSendHalf)16 pub(crate) fn split_owned(socket: UnixDatagram) -> (OwnedRecvHalf, OwnedSendHalf) {
17     let shared = Arc::new(socket);
18     let send = shared.clone();
19     let recv = shared;
20     (
21         OwnedRecvHalf { inner: recv },
22         OwnedSendHalf {
23             inner: send,
24             shutdown_on_drop: true,
25         },
26     )
27 }
28 
29 /// Owned send half of a [`UnixDatagram`], created by [`into_split`].
30 ///
31 /// [`UnixDatagram`]: UnixDatagram
32 /// [`into_split`]: UnixDatagram::into_split()
33 #[derive(Debug)]
34 pub struct OwnedSendHalf {
35     inner: Arc<UnixDatagram>,
36     shutdown_on_drop: bool,
37 }
38 
39 /// Owned receive half of a [`UnixDatagram`], created by [`into_split`].
40 ///
41 /// [`UnixDatagram`]: UnixDatagram
42 /// [`into_split`]: UnixDatagram::into_split()
43 #[derive(Debug)]
44 pub struct OwnedRecvHalf {
45     inner: Arc<UnixDatagram>,
46 }
47 
48 /// Error indicating that two halves were not from the same socket, and thus could
49 /// not be `reunite`d.
50 #[derive(Debug)]
51 pub struct ReuniteError(pub OwnedSendHalf, pub OwnedRecvHalf);
52 
53 impl fmt::Display for ReuniteError {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result54     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
55         write!(
56             f,
57             "tried to reunite halves that are not from the same socket"
58         )
59     }
60 }
61 
62 impl Error for ReuniteError {}
63 
reunite(s: OwnedSendHalf, r: OwnedRecvHalf) -> Result<UnixDatagram, ReuniteError>64 fn reunite(s: OwnedSendHalf, r: OwnedRecvHalf) -> Result<UnixDatagram, ReuniteError> {
65     if Arc::ptr_eq(&s.inner, &r.inner) {
66         s.forget();
67         // Only two instances of the `Arc` are ever created, one for the
68         // receiver and one for the sender, and those `Arc`s are never exposed
69         // externally. And so when we drop one here, the other one must be the
70         // only remaining one.
71         Ok(Arc::try_unwrap(r.inner).expect("UnixDatagram: try_unwrap failed in reunite"))
72     } else {
73         Err(ReuniteError(s, r))
74     }
75 }
76 
77 impl OwnedRecvHalf {
78     /// Attempts to put the two "halves" of a `UnixDatagram` back together and
79     /// recover the original socket. Succeeds only if the two "halves"
80     /// originated from the same call to [`into_split`].
81     ///
82     /// [`into_split`]: UnixDatagram::into_split()
reunite(self, other: OwnedSendHalf) -> Result<UnixDatagram, ReuniteError>83     pub fn reunite(self, other: OwnedSendHalf) -> Result<UnixDatagram, ReuniteError> {
84         reunite(other, self)
85     }
86 
87     /// Receives data from the socket.
recv_from(&mut self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)>88     pub async fn recv_from(&mut self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
89         poll_fn(|cx| self.inner.poll_recv_from_priv(cx, buf)).await
90     }
91 
92     /// Receives data from the socket.
recv(&mut self, buf: &mut [u8]) -> io::Result<usize>93     pub async fn recv(&mut self, buf: &mut [u8]) -> io::Result<usize> {
94         poll_fn(|cx| self.inner.poll_recv_priv(cx, buf)).await
95     }
96 }
97 
98 impl OwnedSendHalf {
99     /// Attempts to put the two "halves" of a `UnixDatagram` back together and
100     /// recover the original socket. Succeeds only if the two "halves"
101     /// originated from the same call to [`into_split`].
102     ///
103     /// [`into_split`]: UnixDatagram::into_split()
reunite(self, other: OwnedRecvHalf) -> Result<UnixDatagram, ReuniteError>104     pub fn reunite(self, other: OwnedRecvHalf) -> Result<UnixDatagram, ReuniteError> {
105         reunite(self, other)
106     }
107 
108     /// Sends data on the socket to the specified address.
send_to<P>(&mut self, buf: &[u8], target: P) -> io::Result<usize> where P: AsRef<Path> + Unpin,109     pub async fn send_to<P>(&mut self, buf: &[u8], target: P) -> io::Result<usize>
110     where
111         P: AsRef<Path> + Unpin,
112     {
113         poll_fn(|cx| self.inner.poll_send_to_priv(cx, buf, target.as_ref())).await
114     }
115 
116     /// Sends data on the socket to the socket's peer.
send(&mut self, buf: &[u8]) -> io::Result<usize>117     pub async fn send(&mut self, buf: &[u8]) -> io::Result<usize> {
118         poll_fn(|cx| self.inner.poll_send_priv(cx, buf)).await
119     }
120 
121     /// Destroy the send half, but don't close the send half of the stream
122     /// until the receive half is dropped. If the read half has already been
123     /// dropped, this closes the stream.
forget(mut self)124     pub fn forget(mut self) {
125         self.shutdown_on_drop = false;
126         drop(self);
127     }
128 }
129 
130 impl Drop for OwnedSendHalf {
drop(&mut self)131     fn drop(&mut self) {
132         if self.shutdown_on_drop {
133             let _ = self.inner.shutdown(Shutdown::Write);
134         }
135     }
136 }
137 
138 impl AsRef<UnixDatagram> for OwnedSendHalf {
as_ref(&self) -> &UnixDatagram139     fn as_ref(&self) -> &UnixDatagram {
140         &self.inner
141     }
142 }
143 
144 impl AsRef<UnixDatagram> for OwnedRecvHalf {
as_ref(&self) -> &UnixDatagram145     fn as_ref(&self) -> &UnixDatagram {
146         &self.inner
147     }
148 }
149