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