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