Skip to main content

std/os/windows/net/
stream.rs

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