Skip to main content

std/os/windows/net/
stream.rs

1#![unstable(feature = "windows_unix_domain_sockets", issue = "150487")]
2use crate::net::Shutdown;
3use crate::os::windows::io::{
4    AsRawSocket, AsSocket, BorrowedSocket, FromRawSocket, IntoRawSocket, RawSocket,
5};
6use crate::os::windows::net::SocketAddr;
7use crate::path::Path;
8#[cfg(not(doc))]
9use crate::sys::c::{
10    AF_UNIX, SO_RCVTIMEO, SO_SNDTIMEO, SOCK_STREAM, connect, getpeername, getsockname,
11};
12use crate::sys::net::Socket;
13#[cfg(not(doc))]
14use crate::sys::winsock::startup;
15use crate::sys::{AsInner, cvt_nz};
16use crate::time::Duration;
17use crate::{fmt, io};
18/// A Unix stream socket.
19///
20/// # Examples
21///
22/// ```no_run
23/// #![feature(windows_unix_domain_sockets)]
24/// use std::os::windows::net::UnixStream;
25/// use std::io::prelude::*;
26///
27/// fn main() -> std::io::Result<()> {
28///     let mut stream = UnixStream::connect("/path/to/my/socket")?;
29///     stream.write_all(b"hello world")?;
30///     let mut response = String::new();
31///     stream.read_to_string(&mut response)?;
32///     println!("{response}");
33///     Ok(())
34/// }
35/// ```
36pub struct UnixStream(pub(super) Socket);
37impl fmt::Debug for UnixStream {
38    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
39        let mut builder = fmt.debug_struct("UnixStream");
40        builder.field("sock", self.0.as_inner());
41        if let Ok(addr) = self.local_addr() {
42            builder.field("local", &addr);
43        }
44        if let Ok(addr) = self.peer_addr() {
45            builder.field("peer", &addr);
46        }
47        builder.finish()
48    }
49}
50impl UnixStream {
51    /// Connects to the socket named by `path`.
52    ///
53    /// # Examples
54    ///
55    /// ```no_run
56    /// #![feature(windows_unix_domain_sockets)]
57    /// use std::os::windows::net::UnixStream;
58    ///
59    /// let socket = match UnixStream::connect("/tmp/sock") {
60    ///     Ok(sock) => sock,
61    ///     Err(e) => {
62    ///         println!("Couldn't connect: {e:?}");
63    ///         return
64    ///     }
65    /// };
66    /// ```
67    pub fn connect<P: AsRef<Path>>(path: P) -> io::Result<UnixStream> {
68        let socket_addr = SocketAddr::from_pathname(path)?;
69        Self::connect_addr(&socket_addr)
70    }
71
72    /// Connects to the socket specified by [`address`].
73    ///
74    /// [`address`]: crate::os::windows::net::SocketAddr
75    ///
76    /// # Examples
77    ///
78    /// ```no_run
79    /// #![feature(windows_unix_domain_sockets)]
80    /// use std::os::windows::net::{UnixListener, UnixStream};
81    ///
82    /// fn main() -> std::io::Result<()> {
83    ///     let listener = UnixListener::bind("/path/to/the/socket")?;
84    ///     let addr = listener.local_addr()?;
85    ///
86    ///     let sock = match UnixStream::connect_addr(&addr) {
87    ///         Ok(sock) => sock,
88    ///         Err(e) => {
89    ///             println!("Couldn't connect: {e:?}");
90    ///             return Err(e)
91    ///         }
92    ///     };
93    ///     Ok(())
94    /// }
95    /// ````
96    pub fn connect_addr(socket_addr: &SocketAddr) -> io::Result<UnixStream> {
97        startup();
98        let inner = Socket::new(AF_UNIX as _, SOCK_STREAM)?;
99        unsafe {
100            cvt_nz(connect(
101                inner.as_raw(),
102                &raw const socket_addr.addr as *const _,
103                socket_addr.len as _,
104            ))?;
105        }
106        Ok(UnixStream(inner))
107    }
108
109    /// Returns the socket address of the local half of this connection.
110    ///
111    /// # Examples
112    ///
113    /// ```no_run
114    /// #![feature(windows_unix_domain_sockets)]
115    /// use std::os::windows::net::UnixStream;
116    ///
117    /// fn main() -> std::io::Result<()> {
118    ///     let socket = UnixStream::connect("/tmp/sock")?;
119    ///     let addr = socket.local_addr().expect("Couldn't get local address");
120    ///     Ok(())
121    /// }
122    /// ```
123    pub fn local_addr(&self) -> io::Result<SocketAddr> {
124        SocketAddr::new(|addr, len| unsafe { getsockname(self.0.as_raw(), addr, len) })
125    }
126
127    /// Returns the socket address of the remote half of this connection.
128    ///
129    /// # Examples
130    ///
131    /// ```no_run
132    /// #![feature(windows_unix_domain_sockets)]
133    /// use std::os::windows::net::UnixStream;
134    ///
135    /// fn main() -> std::io::Result<()> {
136    ///     let socket = UnixStream::connect("/tmp/sock")?;
137    ///     let addr = socket.peer_addr().expect("Couldn't get peer address");
138    ///     Ok(())
139    /// }
140    /// ```
141    pub fn peer_addr(&self) -> io::Result<SocketAddr> {
142        SocketAddr::new(|addr, len| unsafe { getpeername(self.0.as_raw(), addr, len) })
143    }
144
145    /// Returns the read timeout of this socket.
146    ///
147    /// # Examples
148    ///
149    /// ```no_run
150    /// #![feature(windows_unix_domain_sockets)]
151    /// use std::os::windows::net::UnixStream;
152    /// use std::time::Duration;
153    ///
154    /// fn main() -> std::io::Result<()> {
155    ///     let socket = UnixStream::connect("/tmp/sock")?;
156    ///     socket.set_read_timeout(Some(Duration::new(1, 0))).expect("Couldn't set read timeout");
157    ///     assert_eq!(socket.read_timeout()?, Some(Duration::new(1, 0)));
158    ///     Ok(())
159    /// }
160    /// ```
161    pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
162        self.0.timeout(SO_RCVTIMEO)
163    }
164
165    /// Moves the socket into or out of nonblocking mode.
166    ///
167    /// # Examples
168    ///
169    /// ```no_run
170    /// #![feature(windows_unix_domain_sockets)]
171    /// use std::os::windows::net::UnixStream;
172    ///
173    /// fn main() -> std::io::Result<()> {
174    ///     let socket = UnixStream::connect("/tmp/sock")?;
175    ///     socket.set_nonblocking(true).expect("Couldn't set nonblocking");
176    ///     Ok(())
177    /// }
178    /// ```
179    pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
180        self.0.set_nonblocking(nonblocking)
181    }
182
183    /// Sets the read timeout for the socket.
184    ///
185    /// If the provided value is [`None`], then [`read`] calls will block
186    /// indefinitely. An [`Err`] is returned if the zero [`Duration`] is passed to this
187    /// method.
188    ///
189    /// [`read`]: io::Read::read
190    ///
191    /// # Examples
192    ///
193    /// ```no_run
194    /// #![feature(windows_unix_domain_sockets)]
195    /// use std::os::windows::net::UnixStream;
196    /// use std::time::Duration;
197    ///
198    /// fn main() -> std::io::Result<()> {
199    ///     let socket = UnixStream::connect("/tmp/sock")?;
200    ///     socket.set_read_timeout(Some(Duration::new(1, 0))).expect("Couldn't set read timeout");
201    ///     Ok(())
202    /// }
203    /// ```
204    ///
205    /// An [`Err`] is returned if the zero [`Duration`] is passed to this
206    /// method:
207    ///
208    /// ```no_run
209    /// #![feature(windows_unix_domain_sockets)]
210    /// use std::io;
211    /// use std::os::windows::net::UnixStream;
212    /// use std::time::Duration;
213    ///
214    /// fn main() -> std::io::Result<()> {
215    ///     let socket = UnixStream::connect("/tmp/sock")?;
216    ///     let result = socket.set_read_timeout(Some(Duration::new(0, 0)));
217    ///     let err = result.unwrap_err();
218    ///     assert_eq!(err.kind(), io::ErrorKind::InvalidInput);
219    ///     Ok(())
220    /// }
221    /// ```
222    pub fn set_read_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
223        self.0.set_timeout(dur, SO_RCVTIMEO)
224    }
225
226    /// Sets the write timeout for the socket.
227    ///
228    /// If the provided value is [`None`], then [`write`] calls will block
229    /// indefinitely. An [`Err`] is returned if the zero [`Duration`] is
230    /// passed to this method.
231    ///
232    /// [`read`]: io::Read::read
233    ///
234    /// # Examples
235    ///
236    /// ```no_run
237    /// #![feature(windows_unix_domain_sockets)]
238    /// use std::os::windows::net::UnixStream;
239    /// use std::time::Duration;
240    ///
241    /// fn main() -> std::io::Result<()> {
242    ///     let socket = UnixStream::connect("/tmp/sock")?;
243    ///     socket.set_write_timeout(Some(Duration::new(1, 0)))
244    ///         .expect("Couldn't set write timeout");
245    ///     Ok(())
246    /// }
247    /// ```
248    ///
249    /// An [`Err`] is returned if the zero [`Duration`] is passed to this
250    /// method:
251    ///
252    /// ```no_run
253    /// #![feature(windows_unix_domain_sockets)]
254    /// use std::io;
255    /// use std::os::windows::net::UnixStream;
256    /// use std::time::Duration;
257    ///
258    /// fn main() -> std::io::Result<()> {
259    ///     let socket = UnixStream::connect("/tmp/sock")?;
260    ///     let result = socket.set_write_timeout(Some(Duration::new(0, 0)));
261    ///     let err = result.unwrap_err();
262    ///     assert_eq!(err.kind(), io::ErrorKind::InvalidInput);
263    ///     Ok(())
264    /// }
265    /// ```
266    pub fn set_write_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
267        self.0.set_timeout(dur, SO_SNDTIMEO)
268    }
269
270    /// Shuts down the read, write, or both halves of this connection.
271    ///
272    /// This function will cause all pending and future I/O calls on the
273    /// specified portions to immediately return with an appropriate value
274    /// (see the documentation of [`Shutdown`]).
275    ///
276    /// # Examples
277    ///
278    /// ```no_run
279    /// #![feature(windows_unix_domain_sockets)]
280    /// use std::os::windows::net::UnixStream;
281    /// use std::net::Shutdown;
282    ///
283    /// fn main() -> std::io::Result<()> {
284    ///     let socket = UnixStream::connect("/tmp/sock")?;
285    ///     socket.shutdown(Shutdown::Both).expect("shutdown function failed");
286    ///     Ok(())
287    /// }
288    /// ```
289    pub fn shutdown(&self, how: Shutdown) -> io::Result<()> {
290        self.0.shutdown(how)
291    }
292
293    /// Returns the value of the `SO_ERROR` option.
294    ///
295    /// # Examples
296    ///
297    /// ```no_run
298    /// #![feature(windows_unix_domain_sockets)]
299    /// use std::os::windows::net::UnixStream;
300    ///
301    /// fn main() -> std::io::Result<()> {
302    ///     let socket = UnixStream::connect("/tmp/sock")?;
303    ///     if let Ok(Some(err)) = socket.take_error() {
304    ///         println!("Got error: {err:?}");
305    ///     }
306    ///     Ok(())
307    /// }
308    /// ```
309    pub fn take_error(&self) -> io::Result<Option<io::Error>> {
310        self.0.take_error()
311    }
312
313    /// Creates a new independently owned handle to the underlying socket.
314    ///
315    /// The returned `UnixStream` is a reference to the same stream that this
316    /// object references. Both handles will read and write the same stream of
317    /// data, and options set on one stream will be propagated to the other
318    /// stream.
319    ///
320    /// # Examples
321    ///
322    /// ```no_run
323    /// #![feature(windows_unix_domain_sockets)]
324    /// use std::os::windows::net::UnixStream;
325    ///
326    /// fn main() -> std::io::Result<()> {
327    ///     let socket = UnixStream::connect("/tmp/sock")?;
328    ///     let sock_copy = socket.try_clone().expect("Couldn't clone socket");
329    ///     Ok(())
330    /// }
331    /// ```
332    pub fn try_clone(&self) -> io::Result<UnixStream> {
333        self.0.duplicate().map(UnixStream)
334    }
335
336    /// Returns the write timeout of this socket.
337    ///
338    /// # Examples
339    ///
340    /// ```no_run
341    /// #![feature(windows_unix_domain_sockets)]
342    /// use std::os::windows::net::UnixStream;
343    /// use std::time::Duration;
344    ///
345    /// fn main() -> std::io::Result<()> {
346    ///     let socket = UnixStream::connect("/tmp/sock")?;
347    ///     socket.set_write_timeout(Some(Duration::new(1, 0)))
348    ///         .expect("Couldn't set write timeout");
349    ///     assert_eq!(socket.write_timeout()?, Some(Duration::new(1, 0)));
350    ///     Ok(())
351    /// }
352    /// ```
353    pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
354        self.0.timeout(SO_SNDTIMEO)
355    }
356}
357
358impl io::Read for UnixStream {
359    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
360        io::Read::read(&mut &*self, buf)
361    }
362}
363
364impl<'a> io::Read for &'a UnixStream {
365    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
366        self.0.read(buf)
367    }
368}
369
370impl io::Write for UnixStream {
371    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
372        io::Write::write(&mut &*self, buf)
373    }
374
375    fn flush(&mut self) -> io::Result<()> {
376        io::Write::flush(&mut &*self)
377    }
378}
379impl<'a> io::Write for &'a UnixStream {
380    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
381        self.write_vectored(&[io::IoSlice::new(buf)])
382    }
383    #[inline]
384    fn flush(&mut self) -> io::Result<()> {
385        Ok(())
386    }
387    fn write_vectored(&mut self, bufs: &[io::IoSlice<'_>]) -> io::Result<usize> {
388        self.0.write_vectored(bufs)
389    }
390    #[inline]
391    fn is_write_vectored(&self) -> bool {
392        self.0.is_write_vectored()
393    }
394}
395
396impl AsSocket for UnixStream {
397    #[inline]
398    fn as_socket(&self) -> BorrowedSocket<'_> {
399        self.0.as_socket()
400    }
401}
402
403impl AsRawSocket for UnixStream {
404    #[inline]
405    fn as_raw_socket(&self) -> RawSocket {
406        self.0.as_raw_socket()
407    }
408}
409
410impl FromRawSocket for UnixStream {
411    #[inline]
412    unsafe fn from_raw_socket(sock: RawSocket) -> Self {
413        unsafe { UnixStream(Socket::from_raw_socket(sock)) }
414    }
415}
416
417impl IntoRawSocket for UnixStream {
418    fn into_raw_socket(self) -> RawSocket {
419        self.0.into_raw_socket()
420    }
421}