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