1 //! The following is derived from Rust's
2 //! library/std/src/os/windows/io/socket.rs
3 //! at revision
4 //! 4f9b394c8a24803e57ba892fa00e539742ebafc0.
5 //!
6 //! All code in this file is licensed MIT or Apache 2.0 at your option.
7 
8 use super::raw::*;
9 use crate::backend::c;
10 use crate::backend::fd::LibcFd as LibcSocket;
11 use core::fmt;
12 use core::marker::PhantomData;
13 use core::mem::forget;
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 #[cfg_attr(staged_api, rustc_layout_scalar_valid_range_start(0))]
31 // This is -2, in two's complement. -1 is `INVALID_SOCKET`.
32 #[cfg_attr(
33     all(staged_api, target_pointer_width = "32"),
34     rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FE)
35 )]
36 #[cfg_attr(
37     all(staged_api, target_pointer_width = "64"),
38     rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FF_FF_FF_FF_FE)
39 )]
40 #[cfg_attr(staged_api, rustc_nonnull_optimization_guaranteed)]
41 #[cfg_attr(staged_api, stable(feature = "io_safety", since = "1.63.0"))]
42 pub struct BorrowedSocket<'socket> {
43     socket: RawSocket,
44     _phantom: PhantomData<&'socket OwnedSocket>,
45 }
46 
47 /// An owned socket.
48 ///
49 /// This closes the socket on drop.
50 ///
51 /// This uses `repr(transparent)` and has the representation of a host socket,
52 /// so it can be used in FFI in places where a socket is passed as a consumed
53 /// argument or returned as an owned value, and it never has the value
54 /// `INVALID_SOCKET`.
55 #[repr(transparent)]
56 #[cfg_attr(staged_api, rustc_layout_scalar_valid_range_start(0))]
57 // This is -2, in two's complement. -1 is `INVALID_SOCKET`.
58 #[cfg_attr(
59     all(staged_api, target_pointer_width = "32"),
60     rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FE)
61 )]
62 #[cfg_attr(
63     all(staged_api, target_pointer_width = "64"),
64     rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FF_FF_FF_FF_FE)
65 )]
66 #[cfg_attr(staged_api, rustc_nonnull_optimization_guaranteed)]
67 #[cfg_attr(staged_api, stable(feature = "io_safety", since = "1.63.0"))]
68 pub struct OwnedSocket {
69     socket: RawSocket,
70 }
71 
72 impl BorrowedSocket<'_> {
73     /// Return a `BorrowedSocket` holding the given raw socket.
74     ///
75     /// # Safety
76     ///
77     /// The resource pointed to by `raw` must remain open for the duration of
78     /// the returned `BorrowedSocket`, and it must not have the value
79     /// `INVALID_SOCKET`.
80     #[inline]
81     #[cfg_attr(
82         staged_api,
83         rustc_const_stable(feature = "io_safety", since = "1.63.0")
84     )]
85     #[cfg_attr(staged_api, stable(feature = "io_safety", since = "1.63.0"))]
borrow_raw(socket: RawSocket) -> Self86     pub const unsafe fn borrow_raw(socket: RawSocket) -> Self {
87         assert!(socket != c::INVALID_SOCKET as RawSocket);
88         Self {
89             socket,
90             _phantom: PhantomData,
91         }
92     }
93 }
94 
95 #[cfg_attr(staged_api, stable(feature = "io_safety", since = "1.63.0"))]
96 impl AsRawSocket for BorrowedSocket<'_> {
97     #[inline]
as_raw_socket(&self) -> RawSocket98     fn as_raw_socket(&self) -> RawSocket {
99         self.socket
100     }
101 }
102 
103 #[cfg_attr(staged_api, stable(feature = "io_safety", since = "1.63.0"))]
104 impl AsRawSocket for OwnedSocket {
105     #[inline]
as_raw_socket(&self) -> RawSocket106     fn as_raw_socket(&self) -> RawSocket {
107         self.socket
108     }
109 }
110 
111 #[cfg_attr(staged_api, stable(feature = "io_safety", since = "1.63.0"))]
112 impl IntoRawSocket for OwnedSocket {
113     #[inline]
into_raw_socket(self) -> RawSocket114     fn into_raw_socket(self) -> RawSocket {
115         let socket = self.socket;
116         forget(self);
117         socket
118     }
119 }
120 
121 #[cfg_attr(staged_api, stable(feature = "io_safety", since = "1.63.0"))]
122 impl FromRawSocket for OwnedSocket {
123     #[inline]
from_raw_socket(socket: RawSocket) -> Self124     unsafe fn from_raw_socket(socket: RawSocket) -> Self {
125         debug_assert_ne!(socket, c::INVALID_SOCKET as RawSocket);
126         Self { socket }
127     }
128 }
129 
130 #[cfg_attr(staged_api, stable(feature = "io_safety", since = "1.63.0"))]
131 impl Drop for OwnedSocket {
132     #[inline]
drop(&mut self)133     fn drop(&mut self) {
134         unsafe {
135             let _ = c::closesocket(self.socket as LibcSocket);
136         }
137     }
138 }
139 
140 #[cfg_attr(staged_api, stable(feature = "io_safety", since = "1.63.0"))]
141 impl fmt::Debug for BorrowedSocket<'_> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result142     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
143         f.debug_struct("BorrowedSocket")
144             .field("socket", &self.socket)
145             .finish()
146     }
147 }
148 
149 #[cfg_attr(staged_api, stable(feature = "io_safety", since = "1.63.0"))]
150 impl fmt::Debug for OwnedSocket {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result151     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
152         f.debug_struct("OwnedSocket")
153             .field("socket", &self.socket)
154             .finish()
155     }
156 }
157 
158 /// A trait to borrow the socket from an underlying object.
159 #[cfg_attr(staged_api, stable(feature = "io_safety", since = "1.63.0"))]
160 pub trait AsSocket {
161     /// Borrows the socket.
162     #[cfg_attr(staged_api, stable(feature = "io_safety", since = "1.63.0"))]
as_socket(&self) -> BorrowedSocket<'_>163     fn as_socket(&self) -> BorrowedSocket<'_>;
164 }
165 
166 #[cfg_attr(staged_api, stable(feature = "io_safety", since = "1.63.0"))]
167 impl<T: AsSocket> AsSocket for &T {
168     #[inline]
as_socket(&self) -> BorrowedSocket<'_>169     fn as_socket(&self) -> BorrowedSocket<'_> {
170         T::as_socket(self)
171     }
172 }
173 
174 #[cfg_attr(staged_api, stable(feature = "io_safety", since = "1.63.0"))]
175 impl<T: AsSocket> AsSocket for &mut T {
176     #[inline]
as_socket(&self) -> BorrowedSocket<'_>177     fn as_socket(&self) -> BorrowedSocket<'_> {
178         T::as_socket(self)
179     }
180 }
181 
182 #[cfg_attr(staged_api, stable(feature = "io_safety", since = "1.63.0"))]
183 impl AsSocket for BorrowedSocket<'_> {
184     #[inline]
as_socket(&self) -> BorrowedSocket<'_>185     fn as_socket(&self) -> BorrowedSocket<'_> {
186         *self
187     }
188 }
189 
190 #[cfg_attr(staged_api, stable(feature = "io_safety", since = "1.63.0"))]
191 impl AsSocket for OwnedSocket {
192     #[inline]
as_socket(&self) -> BorrowedSocket<'_>193     fn as_socket(&self) -> BorrowedSocket<'_> {
194         // Safety: `OwnedSocket` and `BorrowedSocket` have the same validity
195         // invariants, and the `BorrowdSocket` is bounded by the lifetime
196         // of `&self`.
197         unsafe { BorrowedSocket::borrow_raw(self.as_raw_socket()) }
198     }
199 }
200