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}
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy