std/os/windows/io/
socket.rs

1//! Owned and borrowed OS sockets.
2
3#![stable(feature = "io_safety", since = "1.63.0")]
4
5use super::raw::{AsRawSocket, FromRawSocket, IntoRawSocket, RawSocket};
6use crate::marker::PhantomData;
7use crate::mem::{self, ManuallyDrop};
8#[cfg(not(target_vendor = "uwp"))]
9use crate::sys::cvt;
10use crate::{fmt, io, sys};
11
12// The max here is -2, in two's complement. -1 is `INVALID_SOCKET`.
13type ValidRawSocket = core::num::niche_types::NotAllOnes<RawSocket>;
14
15/// A borrowed socket.
16///
17/// This has a lifetime parameter to tie it to the lifetime of something that
18/// owns the socket.
19///
20/// This uses `repr(transparent)` and has the representation of a host socket,
21/// so it can be used in FFI in places where a socket is passed as an argument,
22/// it is not captured or consumed, and it never has the value
23/// `INVALID_SOCKET`.
24///
25/// This type's `.to_owned()` implementation returns another `BorrowedSocket`
26/// rather than an `OwnedSocket`. It just makes a trivial copy of the raw
27/// socket, which is then borrowed under the same lifetime.
28#[derive(Copy, Clone)]
29#[repr(transparent)]
30#[rustc_nonnull_optimization_guaranteed]
31#[stable(feature = "io_safety", since = "1.63.0")]
32pub struct BorrowedSocket<'socket> {
33    socket: ValidRawSocket,
34    _phantom: PhantomData<&'socket OwnedSocket>,
35}
36
37/// An owned socket.
38///
39/// This closes the socket on drop.
40///
41/// This uses `repr(transparent)` and has the representation of a host socket,
42/// so it can be used in FFI in places where a socket is passed as a consumed
43/// argument or returned as an owned value, and it never has the value
44/// `INVALID_SOCKET`.
45#[repr(transparent)]
46#[rustc_nonnull_optimization_guaranteed]
47#[stable(feature = "io_safety", since = "1.63.0")]
48pub struct OwnedSocket {
49    socket: ValidRawSocket,
50}
51
52impl BorrowedSocket<'_> {
53    /// Returns a `BorrowedSocket` holding the given raw socket.
54    ///
55    /// # Safety
56    ///
57    /// The resource pointed to by `raw` must remain open for the duration of
58    /// the returned `BorrowedSocket`, and it must not have the value
59    /// `INVALID_SOCKET`.
60    #[inline]
61    #[track_caller]
62    #[rustc_const_stable(feature = "io_safety", since = "1.63.0")]
63    #[stable(feature = "io_safety", since = "1.63.0")]
64    pub const unsafe fn borrow_raw(socket: RawSocket) -> Self {
65        Self { socket: ValidRawSocket::new(socket).expect("socket != -1"), _phantom: PhantomData }
66    }
67}
68
69impl OwnedSocket {
70    /// Creates a new `OwnedSocket` instance that shares the same underlying
71    /// object as the existing `OwnedSocket` instance.
72    #[stable(feature = "io_safety", since = "1.63.0")]
73    pub fn try_clone(&self) -> io::Result<Self> {
74        self.as_socket().try_clone_to_owned()
75    }
76
77    // FIXME(strict_provenance_magic): we defined RawSocket to be a u64 ;-;
78    #[allow(fuzzy_provenance_casts)]
79    #[cfg(not(target_vendor = "uwp"))]
80    pub(crate) fn set_no_inherit(&self) -> io::Result<()> {
81        cvt(unsafe {
82            sys::c::SetHandleInformation(
83                self.as_raw_socket() as sys::c::HANDLE,
84                sys::c::HANDLE_FLAG_INHERIT,
85                0,
86            )
87        })
88        .map(drop)
89    }
90
91    #[cfg(target_vendor = "uwp")]
92    pub(crate) fn set_no_inherit(&self) -> io::Result<()> {
93        Err(io::const_error!(io::ErrorKind::Unsupported, "Unavailable on UWP"))
94    }
95}
96
97impl BorrowedSocket<'_> {
98    /// Creates a new `OwnedSocket` instance that shares the same underlying
99    /// object as the existing `BorrowedSocket` instance.
100    #[stable(feature = "io_safety", since = "1.63.0")]
101    pub fn try_clone_to_owned(&self) -> io::Result<OwnedSocket> {
102        let mut info = unsafe { mem::zeroed::<sys::c::WSAPROTOCOL_INFOW>() };
103        let result = unsafe {
104            sys::c::WSADuplicateSocketW(
105                self.as_raw_socket() as sys::c::SOCKET,
106                sys::c::GetCurrentProcessId(),
107                &mut info,
108            )
109        };
110        sys::net::cvt(result)?;
111        let socket = unsafe {
112            sys::c::WSASocketW(
113                info.iAddressFamily,
114                info.iSocketType,
115                info.iProtocol,
116                &info,
117                0,
118                sys::c::WSA_FLAG_OVERLAPPED | sys::c::WSA_FLAG_NO_HANDLE_INHERIT,
119            )
120        };
121
122        if socket != sys::c::INVALID_SOCKET {
123            unsafe { Ok(OwnedSocket::from_raw_socket(socket as RawSocket)) }
124        } else {
125            let error = unsafe { sys::c::WSAGetLastError() };
126
127            if error != sys::c::WSAEPROTOTYPE && error != sys::c::WSAEINVAL {
128                return Err(io::Error::from_raw_os_error(error));
129            }
130
131            let socket = unsafe {
132                sys::c::WSASocketW(
133                    info.iAddressFamily,
134                    info.iSocketType,
135                    info.iProtocol,
136                    &info,
137                    0,
138                    sys::c::WSA_FLAG_OVERLAPPED,
139                )
140            };
141
142            if socket == sys::c::INVALID_SOCKET {
143                return Err(last_error());
144            }
145
146            unsafe {
147                let socket = OwnedSocket::from_raw_socket(socket as RawSocket);
148                socket.set_no_inherit()?;
149                Ok(socket)
150            }
151        }
152    }
153}
154
155/// Returns the last error from the Windows socket interface.
156fn last_error() -> io::Error {
157    io::Error::from_raw_os_error(unsafe { sys::c::WSAGetLastError() })
158}
159
160#[stable(feature = "io_safety", since = "1.63.0")]
161impl AsRawSocket for BorrowedSocket<'_> {
162    #[inline]
163    fn as_raw_socket(&self) -> RawSocket {
164        self.socket.as_inner()
165    }
166}
167
168#[stable(feature = "io_safety", since = "1.63.0")]
169impl AsRawSocket for OwnedSocket {
170    #[inline]
171    fn as_raw_socket(&self) -> RawSocket {
172        self.socket.as_inner()
173    }
174}
175
176#[stable(feature = "io_safety", since = "1.63.0")]
177impl IntoRawSocket for OwnedSocket {
178    #[inline]
179    fn into_raw_socket(self) -> RawSocket {
180        ManuallyDrop::new(self).socket.as_inner()
181    }
182}
183
184#[stable(feature = "io_safety", since = "1.63.0")]
185impl FromRawSocket for OwnedSocket {
186    #[inline]
187    #[track_caller]
188    unsafe fn from_raw_socket(socket: RawSocket) -> Self {
189        Self { socket: ValidRawSocket::new(socket).expect("socket != -1") }
190    }
191}
192
193#[stable(feature = "io_safety", since = "1.63.0")]
194impl Drop for OwnedSocket {
195    #[inline]
196    fn drop(&mut self) {
197        unsafe {
198            let _ = sys::c::closesocket(self.socket.as_inner() as sys::c::SOCKET);
199        }
200    }
201}
202
203#[stable(feature = "io_safety", since = "1.63.0")]
204impl fmt::Debug for BorrowedSocket<'_> {
205    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
206        f.debug_struct("BorrowedSocket").field("socket", &self.socket).finish()
207    }
208}
209
210#[stable(feature = "io_safety", since = "1.63.0")]
211impl fmt::Debug for OwnedSocket {
212    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
213        f.debug_struct("OwnedSocket").field("socket", &self.socket).finish()
214    }
215}
216
217/// A trait to borrow the socket from an underlying object.
218#[stable(feature = "io_safety", since = "1.63.0")]
219pub trait AsSocket {
220    /// Borrows the socket.
221    #[stable(feature = "io_safety", since = "1.63.0")]
222    fn as_socket(&self) -> BorrowedSocket<'_>;
223}
224
225#[stable(feature = "io_safety", since = "1.63.0")]
226impl<T: AsSocket> AsSocket for &T {
227    #[inline]
228    fn as_socket(&self) -> BorrowedSocket<'_> {
229        T::as_socket(self)
230    }
231}
232
233#[stable(feature = "io_safety", since = "1.63.0")]
234impl<T: AsSocket> AsSocket for &mut T {
235    #[inline]
236    fn as_socket(&self) -> BorrowedSocket<'_> {
237        T::as_socket(self)
238    }
239}
240
241#[stable(feature = "as_windows_ptrs", since = "1.71.0")]
242/// This impl allows implementing traits that require `AsSocket` on Arc.
243/// ```
244/// # #[cfg(windows)] mod group_cfg {
245/// # use std::os::windows::io::AsSocket;
246/// use std::net::UdpSocket;
247/// use std::sync::Arc;
248///
249/// trait MyTrait: AsSocket {}
250/// impl MyTrait for Arc<UdpSocket> {}
251/// impl MyTrait for Box<UdpSocket> {}
252/// # }
253/// ```
254impl<T: AsSocket> AsSocket for crate::sync::Arc<T> {
255    #[inline]
256    fn as_socket(&self) -> BorrowedSocket<'_> {
257        (**self).as_socket()
258    }
259}
260
261#[stable(feature = "as_windows_ptrs", since = "1.71.0")]
262impl<T: AsSocket> AsSocket for crate::rc::Rc<T> {
263    #[inline]
264    fn as_socket(&self) -> BorrowedSocket<'_> {
265        (**self).as_socket()
266    }
267}
268
269#[unstable(feature = "unique_rc_arc", issue = "112566")]
270impl<T: AsSocket + ?Sized> AsSocket for crate::rc::UniqueRc<T> {
271    #[inline]
272    fn as_socket(&self) -> BorrowedSocket<'_> {
273        (**self).as_socket()
274    }
275}
276
277#[stable(feature = "as_windows_ptrs", since = "1.71.0")]
278impl<T: AsSocket> AsSocket for Box<T> {
279    #[inline]
280    fn as_socket(&self) -> BorrowedSocket<'_> {
281        (**self).as_socket()
282    }
283}
284
285#[stable(feature = "io_safety", since = "1.63.0")]
286impl AsSocket for BorrowedSocket<'_> {
287    #[inline]
288    fn as_socket(&self) -> BorrowedSocket<'_> {
289        *self
290    }
291}
292
293#[stable(feature = "io_safety", since = "1.63.0")]
294impl AsSocket for OwnedSocket {
295    #[inline]
296    fn as_socket(&self) -> BorrowedSocket<'_> {
297        // Safety: `OwnedSocket` and `BorrowedSocket` have the same validity
298        // invariants, and the `BorrowedSocket` is bounded by the lifetime
299        // of `&self`.
300        unsafe { BorrowedSocket::borrow_raw(self.as_raw_socket()) }
301    }
302}
303
304#[stable(feature = "io_safety", since = "1.63.0")]
305impl AsSocket for crate::net::TcpStream {
306    #[inline]
307    fn as_socket(&self) -> BorrowedSocket<'_> {
308        unsafe { BorrowedSocket::borrow_raw(self.as_raw_socket()) }
309    }
310}
311
312#[stable(feature = "io_safety", since = "1.63.0")]
313impl From<crate::net::TcpStream> for OwnedSocket {
314    /// Takes ownership of a [`TcpStream`](crate::net::TcpStream)'s socket.
315    #[inline]
316    fn from(tcp_stream: crate::net::TcpStream) -> OwnedSocket {
317        unsafe { OwnedSocket::from_raw_socket(tcp_stream.into_raw_socket()) }
318    }
319}
320
321#[stable(feature = "io_safety", since = "1.63.0")]
322impl From<OwnedSocket> for crate::net::TcpStream {
323    #[inline]
324    fn from(owned: OwnedSocket) -> Self {
325        unsafe { Self::from_raw_socket(owned.into_raw_socket()) }
326    }
327}
328
329#[stable(feature = "io_safety", since = "1.63.0")]
330impl AsSocket for crate::net::TcpListener {
331    #[inline]
332    fn as_socket(&self) -> BorrowedSocket<'_> {
333        unsafe { BorrowedSocket::borrow_raw(self.as_raw_socket()) }
334    }
335}
336
337#[stable(feature = "io_safety", since = "1.63.0")]
338impl From<crate::net::TcpListener> for OwnedSocket {
339    /// Takes ownership of a [`TcpListener`](crate::net::TcpListener)'s socket.
340    #[inline]
341    fn from(tcp_listener: crate::net::TcpListener) -> OwnedSocket {
342        unsafe { OwnedSocket::from_raw_socket(tcp_listener.into_raw_socket()) }
343    }
344}
345
346#[stable(feature = "io_safety", since = "1.63.0")]
347impl From<OwnedSocket> for crate::net::TcpListener {
348    #[inline]
349    fn from(owned: OwnedSocket) -> Self {
350        unsafe { Self::from_raw_socket(owned.into_raw_socket()) }
351    }
352}
353
354#[stable(feature = "io_safety", since = "1.63.0")]
355impl AsSocket for crate::net::UdpSocket {
356    #[inline]
357    fn as_socket(&self) -> BorrowedSocket<'_> {
358        unsafe { BorrowedSocket::borrow_raw(self.as_raw_socket()) }
359    }
360}
361
362#[stable(feature = "io_safety", since = "1.63.0")]
363impl From<crate::net::UdpSocket> for OwnedSocket {
364    /// Takes ownership of a [`UdpSocket`](crate::net::UdpSocket)'s underlying socket.
365    #[inline]
366    fn from(udp_socket: crate::net::UdpSocket) -> OwnedSocket {
367        unsafe { OwnedSocket::from_raw_socket(udp_socket.into_raw_socket()) }
368    }
369}
370
371#[stable(feature = "io_safety", since = "1.63.0")]
372impl From<OwnedSocket> for crate::net::UdpSocket {
373    #[inline]
374    fn from(owned: OwnedSocket) -> Self {
375        unsafe { Self::from_raw_socket(owned.into_raw_socket()) }
376    }
377}