Skip to main content

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