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}