Skip to main content

interprocess/os/unix/uds_local_socket/
stream.rs

1use {
2    super::{dispatch_name, CONN_TIMEOUT_MSG},
3    crate::{
4        error::ReuniteError,
5        local_socket::{
6            prelude::*,
7            traits::{self, ReuniteResult},
8            ConcurrencyDetector, ConnectOptions, LocalSocketSite,
9        },
10        os::unix::{c_wrappers, unixprelude::*},
11        ConnectWaitMode, Sealed, TryClone,
12    },
13    std::{
14        io::{self, prelude::*, IoSlice, IoSliceMut},
15        os::unix::net::UnixStream,
16        sync::Arc,
17        time::Duration,
18    },
19};
20
21/// Wrapper around [`UnixStream`] that implements [`Stream`](traits::Stream).
22#[derive(Debug)]
23pub struct Stream(pub(super) UnixStream, ConcurrencyDetector<LocalSocketSite>);
24impl Sealed for Stream {}
25impl traits::Stream for Stream {
26    type RecvHalf = RecvHalf;
27    type SendHalf = SendHalf;
28
29    fn from_options(mut opts: &ConnectOptions<'_>) -> io::Result<Self> {
30        let nonblocking_connect = matches!(
31            opts.get_wait_mode(),
32            ConnectWaitMode::Timeout(..) | ConnectWaitMode::Deferred
33        );
34        let (stream, inprog) = dispatch_name(
35            &mut opts,
36            false,
37            |&mut opts| opts.name.borrow(),
38            |_| None,
39            |addr, _| c_wrappers::create_client(addr, nonblocking_connect),
40        )?;
41        if let ConnectWaitMode::Timeout(timeout) = opts.get_wait_mode() {
42            if inprog {
43                c_wrappers::wait_for_connect(stream.as_fd(), Some(timeout), CONN_TIMEOUT_MSG)?;
44            }
45        }
46        if opts.get_nonblocking_stream() != nonblocking_connect {
47            c_wrappers::fast_set_nonblocking(stream.as_fd(), opts.get_nonblocking_stream())?;
48        }
49        Ok(stream.into())
50    }
51
52    #[inline]
53    fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
54        c_wrappers::set_nonblocking(self.as_fd(), nonblocking)
55    }
56
57    #[inline]
58    fn set_recv_timeout(&self, timeout: Option<Duration>) -> io::Result<()> {
59        self.0.set_read_timeout(timeout)
60    }
61    #[inline]
62    fn set_send_timeout(&self, timeout: Option<Duration>) -> io::Result<()> {
63        self.0.set_write_timeout(timeout)
64    }
65
66    #[inline]
67    fn split(self) -> (RecvHalf, SendHalf) {
68        let arc = Arc::new(self);
69        (RecvHalf(Arc::clone(&arc)), SendHalf(arc))
70    }
71    #[inline]
72    #[allow(clippy::unwrap_in_result)]
73    fn reunite(rh: RecvHalf, sh: SendHalf) -> ReuniteResult<Self> {
74        if !Arc::ptr_eq(&rh.0, &sh.0) {
75            return Err(ReuniteError { rh, sh });
76        }
77        drop(rh);
78        let inner = Arc::into_inner(sh.0).expect("stream half inexplicably copied");
79        Ok(inner)
80    }
81}
82impl traits::StreamCommon for Stream {
83    #[inline]
84    fn take_error(&self) -> io::Result<Option<io::Error>> { c_wrappers::take_error(self.as_fd()) }
85}
86
87impl Read for &Stream {
88    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
89        let _guard = self.1.lock();
90        (&mut &self.0).read(buf)
91    }
92    fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
93        let _guard = self.1.lock();
94        (&mut &self.0).read_vectored(bufs)
95    }
96    // FUTURE is_read_vectored
97}
98impl Write for &Stream {
99    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
100        let _guard = self.1.lock();
101        (&mut &self.0).write(buf)
102    }
103    fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
104        let _guard = self.1.lock();
105        (&mut &self.0).write_vectored(bufs)
106    }
107    #[inline]
108    fn flush(&mut self) -> io::Result<()> { Ok(()) }
109    // FUTURE is_write_vectored
110}
111
112/// Access to the underlying implementation.
113impl Stream {
114    /// Borrows the [`UnixStream`] contained within, granting access to operations defined on it.
115    #[inline(always)]
116    pub fn inner(&self) -> &UnixStream { &self.0 }
117    /// Mutably borrows the [`UnixStream`] contained within, granting access to operations defined
118    /// on it.
119    ///
120    /// This may allow for non-portable concurrent I/O. Please use [`inner`](Self::inner) instead
121    /// if you can.
122    #[inline(always)]
123    pub fn inner_mut(&mut self) -> &mut UnixStream { &mut self.0 }
124}
125
126/// Creates a fresh concurrency detector and thus may allow for non-portable concurrent I/O.
127impl From<UnixStream> for Stream {
128    fn from(s: UnixStream) -> Self { Self(s, ConcurrencyDetector::new()) }
129}
130
131impl From<OwnedFd> for Stream {
132    fn from(fd: OwnedFd) -> Self { UnixStream::from(fd).into() }
133}
134
135impl TryClone for Stream {
136    #[inline]
137    fn try_clone(&self) -> std::io::Result<Self> { self.0.try_clone().map(Self::from) }
138}
139
140multimacro! {
141    Stream,
142    forward_asinto_handle(unix),
143    derive_sync_mut_rw,
144}
145
146macro_rules! arc_accessors {
147    ($ty:ty) => {
148        /// [`Arc`] accessors.
149        impl $ty {
150            /// Borrows the [`Stream`] within the `Arc`.
151            #[inline]
152            pub fn as_stream(&self) -> &Stream { &self.0 }
153            /// Extracts the underlying `Arc<Stream>`.
154            #[inline]
155            pub fn into_arc(self) -> Arc<Stream> { self.0 }
156            /// Borrows the underlying `Arc<Stream>`, granting access to extra information about
157            /// the `Arc`.
158            #[inline]
159            pub fn as_arc(&self) -> &Arc<Stream> { &self.0 }
160        }
161    };
162}
163
164/// [`Stream`]'s receive half, implemented using [`Arc`].
165#[derive(Clone, Debug)]
166pub struct RecvHalf(pub(super) Arc<Stream>);
167impl Sealed for RecvHalf {}
168impl traits::RecvHalf for RecvHalf {
169    type Stream = Stream;
170
171    #[inline]
172    fn set_timeout(&self, timeout: Option<Duration>) -> io::Result<()> {
173        self.0.set_recv_timeout(timeout)
174    }
175}
176multimacro! {
177    RecvHalf,
178    forward_rbv(Stream, *),
179    arc_accessors,
180    forward_sync_ref_read,
181    forward_as_handle,
182    derive_sync_mut_read,
183}
184
185/// [`Stream`]'s send half, implemented using [`Arc`].
186#[derive(Clone, Debug)]
187pub struct SendHalf(pub(super) Arc<Stream>);
188impl Sealed for SendHalf {}
189impl traits::SendHalf for SendHalf {
190    type Stream = Stream;
191
192    #[inline]
193    fn set_timeout(&self, timeout: Option<Duration>) -> io::Result<()> {
194        self.0.set_send_timeout(timeout)
195    }
196}
197multimacro! {
198    SendHalf,
199    forward_rbv(Stream, *),
200    arc_accessors,
201    forward_sync_ref_write,
202    forward_as_handle,
203    derive_sync_mut_write,
204}