1 //! Owned and borrowed OS sockets.
3 #![unstable(feature = "io_safety", issue = "87074")]
5 use super::raw::{AsRawSocket, FromRawSocket, IntoRawSocket, RawSocket};
8 use crate::marker::PhantomData;
10 use crate::mem::forget;
15 /// A borrowed socket.
17 /// This has a lifetime parameter to tie it to the lifetime of something that
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
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)]
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))]
34 target_pointer_width = "64",
35 rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FF_FF_FF_FF_FE)
37 #[unstable(feature = "io_safety", issue = "87074")]
38 pub struct BorrowedSocket<'socket> {
40 _phantom: PhantomData<&'socket OwnedSocket>,
45 /// This closes the socket on drop.
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
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))]
56 target_pointer_width = "64",
57 rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FF_FF_FF_FF_FE)
59 #[unstable(feature = "io_safety", issue = "87074")]
60 pub struct OwnedSocket {
64 impl BorrowedSocket<'_> {
65 /// Return a `BorrowedSocket` holding the given raw socket.
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
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 }
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>() };
86 c::WSADuplicateSocketW(self.as_raw_socket(), c::GetCurrentProcessId(), &mut info)
88 sys::net::cvt(result)?;
96 c::WSA_FLAG_OVERLAPPED | c::WSA_FLAG_NO_HANDLE_INHERIT,
100 if socket != c::INVALID_SOCKET {
101 unsafe { Ok(OwnedSocket::from_raw_socket(socket)) }
103 let error = unsafe { c::WSAGetLastError() };
105 if error != c::WSAEPROTOTYPE && error != c::WSAEINVAL {
106 return Err(io::Error::from_raw_os_error(error));
109 let socket = unsafe {
116 c::WSA_FLAG_OVERLAPPED,
120 if socket == c::INVALID_SOCKET {
121 return Err(last_error());
125 let socket = OwnedSocket::from_raw_socket(socket);
126 socket.set_no_inherit()?;
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<()> {
136 c::SetHandleInformation(self.as_raw_socket() as c::HANDLE, c::HANDLE_FLAG_INHERIT, 0)
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"))
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() })
152 impl AsRawSocket for BorrowedSocket<'_> {
154 fn as_raw_socket(&self) -> RawSocket {
159 impl AsRawSocket for OwnedSocket {
161 fn as_raw_socket(&self) -> RawSocket {
166 impl IntoRawSocket for OwnedSocket {
168 fn into_raw_socket(self) -> RawSocket {
169 let socket = self.socket;
175 impl FromRawSocket for OwnedSocket {
177 unsafe fn from_raw_socket(socket: RawSocket) -> Self {
178 debug_assert_ne!(socket, c::INVALID_SOCKET as RawSocket);
183 impl Drop for OwnedSocket {
187 let _ = c::closesocket(self.socket);
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()
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()
204 /// A trait to borrow the socket from an underlying object.
205 #[unstable(feature = "io_safety", issue = "87074")]
207 /// Borrows the socket.
208 fn as_socket(&self) -> BorrowedSocket<'_>;
211 #[unstable(feature = "io_safety", issue = "87074")]
212 impl<T: AsSocket> AsSocket for &T {
214 fn as_socket(&self) -> BorrowedSocket<'_> {
219 #[unstable(feature = "io_safety", issue = "87074")]
220 impl<T: AsSocket> AsSocket for &mut T {
222 fn as_socket(&self) -> BorrowedSocket<'_> {
227 impl AsSocket for BorrowedSocket<'_> {
229 fn as_socket(&self) -> BorrowedSocket<'_> {
234 impl AsSocket for OwnedSocket {
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
240 unsafe { BorrowedSocket::borrow_raw(self.as_raw_socket()) }
244 impl AsSocket for crate::net::TcpStream {
246 fn as_socket(&self) -> BorrowedSocket<'_> {
247 unsafe { BorrowedSocket::borrow_raw(self.as_raw_socket()) }
251 impl From<crate::net::TcpStream> for OwnedSocket {
253 fn from(tcp_stream: crate::net::TcpStream) -> OwnedSocket {
254 unsafe { OwnedSocket::from_raw_socket(tcp_stream.into_raw_socket()) }
258 impl From<OwnedSocket> for crate::net::TcpStream {
260 fn from(owned: OwnedSocket) -> Self {
261 unsafe { Self::from_raw_socket(owned.into_raw_socket()) }
265 impl AsSocket for crate::net::TcpListener {
267 fn as_socket(&self) -> BorrowedSocket<'_> {
268 unsafe { BorrowedSocket::borrow_raw(self.as_raw_socket()) }
272 impl From<crate::net::TcpListener> for OwnedSocket {
274 fn from(tcp_listener: crate::net::TcpListener) -> OwnedSocket {
275 unsafe { OwnedSocket::from_raw_socket(tcp_listener.into_raw_socket()) }
279 impl From<OwnedSocket> for crate::net::TcpListener {
281 fn from(owned: OwnedSocket) -> Self {
282 unsafe { Self::from_raw_socket(owned.into_raw_socket()) }
286 impl AsSocket for crate::net::UdpSocket {
288 fn as_socket(&self) -> BorrowedSocket<'_> {
289 unsafe { BorrowedSocket::borrow_raw(self.as_raw_socket()) }
293 impl From<crate::net::UdpSocket> for OwnedSocket {
295 fn from(udp_socket: crate::net::UdpSocket) -> OwnedSocket {
296 unsafe { OwnedSocket::from_raw_socket(udp_socket.into_raw_socket()) }
300 impl From<OwnedSocket> for crate::net::UdpSocket {
302 fn from(owned: OwnedSocket) -> Self {
303 unsafe { Self::from_raw_socket(owned.into_raw_socket()) }