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