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