]> git.lizzy.rs Git - rust.git/blob - library/std/src/os/windows/io/socket.rs
Auto merge of #107843 - bjorn3:sync_cg_clif-2023-02-09, r=bjorn3
[rust.git] / library / std / src / os / windows / io / socket.rs
1 //! Owned and borrowed OS sockets.
2
3 #![stable(feature = "io_safety", since = "1.63.0")]
4
5 use super::raw::{AsRawSocket, FromRawSocket, IntoRawSocket, RawSocket};
6 use crate::fmt;
7 use crate::io;
8 use crate::marker::PhantomData;
9 use crate::mem;
10 use crate::mem::forget;
11 use crate::sys;
12 use crate::sys::c;
13 #[cfg(not(target_vendor = "uwp"))]
14 use crate::sys::cvt;
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_layout_scalar_valid_range_start(0)]
32 // This is -2, in two's complement. -1 is `INVALID_SOCKET`.
33 #[cfg_attr(target_pointer_width = "32", rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FE))]
34 #[cfg_attr(
35     target_pointer_width = "64",
36     rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FF_FF_FF_FF_FE)
37 )]
38 #[rustc_nonnull_optimization_guaranteed]
39 #[stable(feature = "io_safety", since = "1.63.0")]
40 pub struct BorrowedSocket<'socket> {
41     socket: RawSocket,
42     _phantom: PhantomData<&'socket OwnedSocket>,
43 }
44
45 /// An owned socket.
46 ///
47 /// This closes the socket on drop.
48 ///
49 /// This uses `repr(transparent)` and has the representation of a host socket,
50 /// so it can be used in FFI in places where a socket is passed as a consumed
51 /// argument or returned as an owned value, and it never has the value
52 /// `INVALID_SOCKET`.
53 #[repr(transparent)]
54 #[rustc_layout_scalar_valid_range_start(0)]
55 // This is -2, in two's complement. -1 is `INVALID_SOCKET`.
56 #[cfg_attr(target_pointer_width = "32", rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FE))]
57 #[cfg_attr(
58     target_pointer_width = "64",
59     rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FF_FF_FF_FF_FE)
60 )]
61 #[rustc_nonnull_optimization_guaranteed]
62 #[stable(feature = "io_safety", since = "1.63.0")]
63 pub struct OwnedSocket {
64     socket: RawSocket,
65 }
66
67 impl BorrowedSocket<'_> {
68     /// Return a `BorrowedSocket` holding the given raw socket.
69     ///
70     /// # Safety
71     ///
72     /// The resource pointed to by `raw` must remain open for the duration of
73     /// the returned `BorrowedSocket`, and it must not have the value
74     /// `INVALID_SOCKET`.
75     #[inline]
76     #[rustc_const_stable(feature = "io_safety", since = "1.63.0")]
77     #[stable(feature = "io_safety", since = "1.63.0")]
78     pub const unsafe fn borrow_raw(socket: RawSocket) -> Self {
79         assert!(socket != c::INVALID_SOCKET as RawSocket);
80         Self { socket, _phantom: PhantomData }
81     }
82 }
83
84 impl OwnedSocket {
85     /// Creates a new `OwnedSocket` instance that shares the same underlying
86     /// object as the existing `OwnedSocket` instance.
87     #[stable(feature = "io_safety", since = "1.63.0")]
88     pub fn try_clone(&self) -> io::Result<Self> {
89         self.as_socket().try_clone_to_owned()
90     }
91
92     // FIXME(strict_provenance_magic): we defined RawSocket to be a u64 ;-;
93     #[allow(fuzzy_provenance_casts)]
94     #[cfg(not(target_vendor = "uwp"))]
95     pub(crate) fn set_no_inherit(&self) -> io::Result<()> {
96         cvt(unsafe {
97             c::SetHandleInformation(self.as_raw_socket() as c::HANDLE, c::HANDLE_FLAG_INHERIT, 0)
98         })
99         .map(drop)
100     }
101
102     #[cfg(target_vendor = "uwp")]
103     pub(crate) fn set_no_inherit(&self) -> io::Result<()> {
104         Err(io::const_io_error!(io::ErrorKind::Unsupported, "Unavailable on UWP"))
105     }
106 }
107
108 impl BorrowedSocket<'_> {
109     /// Creates a new `OwnedSocket` instance that shares the same underlying
110     /// object as the existing `BorrowedSocket` instance.
111     #[stable(feature = "io_safety", since = "1.63.0")]
112     pub fn try_clone_to_owned(&self) -> io::Result<OwnedSocket> {
113         let mut info = unsafe { mem::zeroed::<c::WSAPROTOCOL_INFO>() };
114         let result = unsafe {
115             c::WSADuplicateSocketW(self.as_raw_socket(), c::GetCurrentProcessId(), &mut info)
116         };
117         sys::net::cvt(result)?;
118         let socket = unsafe {
119             c::WSASocketW(
120                 info.iAddressFamily,
121                 info.iSocketType,
122                 info.iProtocol,
123                 &mut info,
124                 0,
125                 c::WSA_FLAG_OVERLAPPED | c::WSA_FLAG_NO_HANDLE_INHERIT,
126             )
127         };
128
129         if socket != c::INVALID_SOCKET {
130             unsafe { Ok(OwnedSocket::from_raw_socket(socket)) }
131         } else {
132             let error = unsafe { c::WSAGetLastError() };
133
134             if error != c::WSAEPROTOTYPE && error != c::WSAEINVAL {
135                 return Err(io::Error::from_raw_os_error(error));
136             }
137
138             let socket = unsafe {
139                 c::WSASocketW(
140                     info.iAddressFamily,
141                     info.iSocketType,
142                     info.iProtocol,
143                     &mut info,
144                     0,
145                     c::WSA_FLAG_OVERLAPPED,
146                 )
147             };
148
149             if socket == c::INVALID_SOCKET {
150                 return Err(last_error());
151             }
152
153             unsafe {
154                 let socket = OwnedSocket::from_raw_socket(socket);
155                 socket.set_no_inherit()?;
156                 Ok(socket)
157             }
158         }
159     }
160 }
161
162 /// Returns the last error from the Windows socket interface.
163 fn last_error() -> io::Error {
164     io::Error::from_raw_os_error(unsafe { c::WSAGetLastError() })
165 }
166
167 #[stable(feature = "io_safety", since = "1.63.0")]
168 impl AsRawSocket for BorrowedSocket<'_> {
169     #[inline]
170     fn as_raw_socket(&self) -> RawSocket {
171         self.socket
172     }
173 }
174
175 #[stable(feature = "io_safety", since = "1.63.0")]
176 impl AsRawSocket for OwnedSocket {
177     #[inline]
178     fn as_raw_socket(&self) -> RawSocket {
179         self.socket
180     }
181 }
182
183 #[stable(feature = "io_safety", since = "1.63.0")]
184 impl IntoRawSocket for OwnedSocket {
185     #[inline]
186     fn into_raw_socket(self) -> RawSocket {
187         let socket = self.socket;
188         forget(self);
189         socket
190     }
191 }
192
193 #[stable(feature = "io_safety", since = "1.63.0")]
194 impl FromRawSocket for OwnedSocket {
195     #[inline]
196     unsafe fn from_raw_socket(socket: RawSocket) -> Self {
197         debug_assert_ne!(socket, c::INVALID_SOCKET as RawSocket);
198         Self { socket }
199     }
200 }
201
202 #[stable(feature = "io_safety", since = "1.63.0")]
203 impl Drop for OwnedSocket {
204     #[inline]
205     fn drop(&mut self) {
206         unsafe {
207             let _ = c::closesocket(self.socket);
208         }
209     }
210 }
211
212 #[stable(feature = "io_safety", since = "1.63.0")]
213 impl fmt::Debug for BorrowedSocket<'_> {
214     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
215         f.debug_struct("BorrowedSocket").field("socket", &self.socket).finish()
216     }
217 }
218
219 #[stable(feature = "io_safety", since = "1.63.0")]
220 impl fmt::Debug for OwnedSocket {
221     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
222         f.debug_struct("OwnedSocket").field("socket", &self.socket).finish()
223     }
224 }
225
226 /// A trait to borrow the socket from an underlying object.
227 #[stable(feature = "io_safety", since = "1.63.0")]
228 pub trait AsSocket {
229     /// Borrows the socket.
230     #[stable(feature = "io_safety", since = "1.63.0")]
231     fn as_socket(&self) -> BorrowedSocket<'_>;
232 }
233
234 #[stable(feature = "io_safety", since = "1.63.0")]
235 impl<T: AsSocket> AsSocket for &T {
236     #[inline]
237     fn as_socket(&self) -> BorrowedSocket<'_> {
238         T::as_socket(self)
239     }
240 }
241
242 #[stable(feature = "io_safety", since = "1.63.0")]
243 impl<T: AsSocket> AsSocket for &mut T {
244     #[inline]
245     fn as_socket(&self) -> BorrowedSocket<'_> {
246         T::as_socket(self)
247     }
248 }
249
250 #[stable(feature = "io_safety", since = "1.63.0")]
251 impl AsSocket for BorrowedSocket<'_> {
252     #[inline]
253     fn as_socket(&self) -> BorrowedSocket<'_> {
254         *self
255     }
256 }
257
258 #[stable(feature = "io_safety", since = "1.63.0")]
259 impl AsSocket for OwnedSocket {
260     #[inline]
261     fn as_socket(&self) -> BorrowedSocket<'_> {
262         // Safety: `OwnedSocket` and `BorrowedSocket` have the same validity
263         // invariants, and the `BorrowdSocket` is bounded by the lifetime
264         // of `&self`.
265         unsafe { BorrowedSocket::borrow_raw(self.as_raw_socket()) }
266     }
267 }
268
269 #[stable(feature = "io_safety", since = "1.63.0")]
270 impl AsSocket for crate::net::TcpStream {
271     #[inline]
272     fn as_socket(&self) -> BorrowedSocket<'_> {
273         unsafe { BorrowedSocket::borrow_raw(self.as_raw_socket()) }
274     }
275 }
276
277 #[stable(feature = "io_safety", since = "1.63.0")]
278 impl From<crate::net::TcpStream> for OwnedSocket {
279     #[inline]
280     fn from(tcp_stream: crate::net::TcpStream) -> OwnedSocket {
281         unsafe { OwnedSocket::from_raw_socket(tcp_stream.into_raw_socket()) }
282     }
283 }
284
285 #[stable(feature = "io_safety", since = "1.63.0")]
286 impl From<OwnedSocket> for crate::net::TcpStream {
287     #[inline]
288     fn from(owned: OwnedSocket) -> Self {
289         unsafe { Self::from_raw_socket(owned.into_raw_socket()) }
290     }
291 }
292
293 #[stable(feature = "io_safety", since = "1.63.0")]
294 impl AsSocket for crate::net::TcpListener {
295     #[inline]
296     fn as_socket(&self) -> BorrowedSocket<'_> {
297         unsafe { BorrowedSocket::borrow_raw(self.as_raw_socket()) }
298     }
299 }
300
301 #[stable(feature = "io_safety", since = "1.63.0")]
302 impl From<crate::net::TcpListener> for OwnedSocket {
303     #[inline]
304     fn from(tcp_listener: crate::net::TcpListener) -> OwnedSocket {
305         unsafe { OwnedSocket::from_raw_socket(tcp_listener.into_raw_socket()) }
306     }
307 }
308
309 #[stable(feature = "io_safety", since = "1.63.0")]
310 impl From<OwnedSocket> for crate::net::TcpListener {
311     #[inline]
312     fn from(owned: OwnedSocket) -> Self {
313         unsafe { Self::from_raw_socket(owned.into_raw_socket()) }
314     }
315 }
316
317 #[stable(feature = "io_safety", since = "1.63.0")]
318 impl AsSocket for crate::net::UdpSocket {
319     #[inline]
320     fn as_socket(&self) -> BorrowedSocket<'_> {
321         unsafe { BorrowedSocket::borrow_raw(self.as_raw_socket()) }
322     }
323 }
324
325 #[stable(feature = "io_safety", since = "1.63.0")]
326 impl From<crate::net::UdpSocket> for OwnedSocket {
327     #[inline]
328     fn from(udp_socket: crate::net::UdpSocket) -> OwnedSocket {
329         unsafe { OwnedSocket::from_raw_socket(udp_socket.into_raw_socket()) }
330     }
331 }
332
333 #[stable(feature = "io_safety", since = "1.63.0")]
334 impl From<OwnedSocket> for crate::net::UdpSocket {
335     #[inline]
336     fn from(owned: OwnedSocket) -> Self {
337         unsafe { Self::from_raw_socket(owned.into_raw_socket()) }
338     }
339 }