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