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}