diff --git a/src/socket.rs b/src/socket.rs index 6e09f37f..ef8781f5 100644 --- a/src/socket.rs +++ b/src/socket.rs @@ -68,11 +68,26 @@ use crate::{MaybeUninitSlice, RecvFlags}; /// # Ok(()) } /// ``` pub struct Socket { - // The `sys` module most have access to the socket. - pub(crate) inner: sys::Socket, + inner: Inner, } +/// Store a `TcpStream` internally to take advantage of its niche optimizations on Unix platforms. +pub(crate) type Inner = std::net::TcpStream; + +// The `sys` module must have access to the below three functions. impl Socket { + pub(crate) fn from_raw(raw: sys::Socket) -> Socket { + Socket { + inner: sys::socket_from_raw(raw), + } + } + pub(crate) fn as_raw(&self) -> sys::Socket { + sys::socket_as_raw(&self.inner) + } + pub(crate) fn into_raw(self) -> sys::Socket { + sys::socket_into_raw(self.inner) + } + /// Creates a new socket and sets common flags. /// /// This function corresponds to `socket(2)` on Unix and `WSASocketW` on @@ -94,7 +109,7 @@ impl Socket { /// Windows and simply creates a new socket, no other configuration is done. pub fn new_raw(domain: Domain, ty: Type, protocol: Option) -> io::Result { let protocol = protocol.map(|p| p.0).unwrap_or(0); - sys::socket(domain.0, ty.0, protocol).map(|inner| Socket { inner }) + sys::socket(domain.0, ty.0, protocol).map(Socket::from_raw) } /// Creates a pair of sockets which are connected to each other. @@ -135,7 +150,7 @@ impl Socket { ) -> io::Result<(Socket, Socket)> { let protocol = protocol.map(|p| p.0).unwrap_or(0); sys::socketpair(domain.0, ty.0, protocol) - .map(|fds| (Socket { inner: fds[0] }, Socket { inner: fds[1] })) + .map(|[a, b]| (Socket::from_raw(a), Socket::from_raw(b))) } /// Binds this socket to the specified address. @@ -143,7 +158,7 @@ impl Socket { /// This function directly corresponds to the `bind(2)` function on Windows /// and Unix. pub fn bind(&self, address: &SockAddr) -> io::Result<()> { - sys::bind(self.inner, address) + sys::bind(self.as_raw(), address) } /// Initiate a connection on this socket to the specified address. @@ -161,7 +176,7 @@ impl Socket { /// set *while connecting*. This will cause errors on Windows. Socket /// options can be safely set before and after connecting the socket. pub fn connect(&self, address: &SockAddr) -> io::Result<()> { - sys::connect(self.inner, address) + sys::connect(self.as_raw(), address) } /// Initiate a connection on this socket to the specified address, only @@ -208,7 +223,7 @@ impl Socket { /// An error will be returned if `listen` or `connect` has already been /// called on this builder. pub fn listen(&self, backlog: c_int) -> io::Result<()> { - sys::listen(self.inner, backlog) + sys::listen(self.as_raw(), backlog) } /// Accept a new incoming connection from this listener. @@ -254,7 +269,7 @@ impl Socket { /// This function directly corresponds to the `accept(2)` function on /// Windows and Unix. pub fn accept_raw(&self) -> io::Result<(Socket, SockAddr)> { - sys::accept(self.inner).map(|(inner, addr)| (Socket { inner }, addr)) + sys::accept(self.as_raw()).map(|(inner, addr)| (Socket::from_raw(inner), addr)) } /// Returns the socket address of the local half of this socket. @@ -266,7 +281,7 @@ impl Socket { /// /// [bound]: Socket::bind pub fn local_addr(&self) -> io::Result { - sys::getsockname(self.inner) + sys::getsockname(self.as_raw()) } /// Returns the socket address of the remote peer of this socket. @@ -277,13 +292,13 @@ impl Socket { /// /// [`connect`ed]: Socket::connect pub fn peer_addr(&self) -> io::Result { - sys::getpeername(self.inner) + sys::getpeername(self.as_raw()) } /// Returns the [`Type`] of this socket by checking the `SO_TYPE` option on /// this socket. pub fn r#type(&self) -> io::Result { - unsafe { getsockopt::(self.inner, sys::SOL_SOCKET, sys::SO_TYPE).map(Type) } + unsafe { getsockopt::(self.as_raw(), sys::SOL_SOCKET, sys::SO_TYPE).map(Type) } } /// Creates a new independently owned handle to the underlying socket. @@ -300,7 +315,7 @@ impl Socket { /// QOS-enabled socket, see /// . pub fn try_clone(&self) -> io::Result { - sys::try_clone(self.inner).map(|inner| Socket { inner }) + sys::try_clone(self.as_raw()).map(Socket::from_raw) } /// Moves this TCP stream into or out of nonblocking mode. @@ -312,7 +327,7 @@ impl Socket { /// On Windows this corresponds to calling `ioctlsocket` (un)setting /// `FIONBIO`. pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { - sys::set_nonblocking(self.inner, nonblocking) + sys::set_nonblocking(self.as_raw(), nonblocking) } /// Shuts down the read, write, or both halves of this connection. @@ -320,7 +335,7 @@ impl Socket { /// This function will cause all pending and future I/O on the specified /// portions to return immediately with an appropriate value. pub fn shutdown(&self, how: Shutdown) -> io::Result<()> { - sys::shutdown(self.inner, how) + sys::shutdown(self.as_raw(), how) } /// Receives data on the socket from the remote address to which it is @@ -367,7 +382,7 @@ impl Socket { buf: &mut [MaybeUninit], flags: sys::c_int, ) -> io::Result { - sys::recv(self.inner, buf, flags) + sys::recv(self.as_raw(), buf, flags) } /// Receives data on the socket from the remote address to which it is @@ -420,7 +435,7 @@ impl Socket { bufs: &mut [MaybeUninitSlice<'_>], flags: c_int, ) -> io::Result<(usize, RecvFlags)> { - sys::recv_vectored(self.inner, bufs, flags) + sys::recv_vectored(self.as_raw(), bufs, flags) } /// Receives data on the socket from the remote adress to which it is @@ -462,7 +477,7 @@ impl Socket { buf: &mut [MaybeUninit], flags: c_int, ) -> io::Result<(usize, SockAddr)> { - sys::recv_from(self.inner, buf, flags) + sys::recv_from(self.as_raw(), buf, flags) } /// Receives data from the socket. Returns the amount of bytes read, the @@ -502,7 +517,7 @@ impl Socket { bufs: &mut [MaybeUninitSlice<'_>], flags: c_int, ) -> io::Result<(usize, RecvFlags, SockAddr)> { - sys::recv_from_vectored(self.inner, bufs, flags) + sys::recv_from_vectored(self.as_raw(), bufs, flags) } /// Receives data from the socket, without removing it from the queue. @@ -538,7 +553,7 @@ impl Socket { /// /// [`send`]: #method.send pub fn send_with_flags(&self, buf: &[u8], flags: c_int) -> io::Result { - sys::send(self.inner, buf, flags) + sys::send(self.as_raw(), buf, flags) } /// Send data to the connected peer. Returns the amount of bytes written. @@ -557,7 +572,7 @@ impl Socket { bufs: &[IoSlice<'_>], flags: c_int, ) -> io::Result { - sys::send_vectored(self.inner, bufs, flags) + sys::send_vectored(self.as_raw(), bufs, flags) } /// Sends out-of-band (OOB) data on the socket to connected peer @@ -589,7 +604,7 @@ impl Socket { addr: &SockAddr, flags: c_int, ) -> io::Result { - sys::send_to(self.inner, buf, addr, flags) + sys::send_to(self.as_raw(), buf, addr, flags) } /// Send data to a peer listening on `addr`. Returns the amount of bytes @@ -610,7 +625,7 @@ impl Socket { addr: &SockAddr, flags: c_int, ) -> io::Result { - sys::send_to_vectored(self.inner, bufs, addr, flags) + sys::send_to_vectored(self.as_raw(), bufs, addr, flags) } } @@ -677,7 +692,7 @@ impl Socket { /// [`set_broadcast`]: Socket::set_broadcast pub fn broadcast(&self) -> io::Result { unsafe { - getsockopt::(self.inner, sys::SOL_SOCKET, sys::SO_BROADCAST) + getsockopt::(self.as_raw(), sys::SOL_SOCKET, sys::SO_BROADCAST) .map(|broadcast| broadcast != 0) } } @@ -689,7 +704,7 @@ impl Socket { pub fn set_broadcast(&self, broadcast: bool) -> io::Result<()> { unsafe { setsockopt( - self.inner, + self.as_raw(), sys::SOL_SOCKET, sys::SO_BROADCAST, broadcast as c_int, @@ -703,7 +718,7 @@ impl Socket { /// the field in the process. This can be useful for checking errors between /// calls. pub fn take_error(&self) -> io::Result> { - match unsafe { getsockopt::(self.inner, sys::SOL_SOCKET, sys::SO_ERROR) } { + match unsafe { getsockopt::(self.as_raw(), sys::SOL_SOCKET, sys::SO_ERROR) } { Ok(0) => Ok(None), Ok(errno) => Ok(Some(io::Error::from_raw_os_error(errno))), Err(err) => Err(err), @@ -717,7 +732,7 @@ impl Socket { /// [`set_keepalive`]: Socket::set_keepalive pub fn keepalive(&self) -> io::Result { unsafe { - getsockopt::(self.inner, sys::SOL_SOCKET, sys::SO_KEEPALIVE) + getsockopt::(self.as_raw(), sys::SOL_SOCKET, sys::SO_KEEPALIVE) .map(|keepalive| keepalive != 0) } } @@ -728,7 +743,7 @@ impl Socket { pub fn set_keepalive(&self, keepalive: bool) -> io::Result<()> { unsafe { setsockopt( - self.inner, + self.as_raw(), sys::SOL_SOCKET, sys::SO_KEEPALIVE, keepalive as c_int, @@ -743,7 +758,8 @@ impl Socket { /// [`set_linger`]: Socket::set_linger pub fn linger(&self) -> io::Result> { unsafe { - getsockopt::(self.inner, sys::SOL_SOCKET, sys::SO_LINGER).map(from_linger) + getsockopt::(self.as_raw(), sys::SOL_SOCKET, sys::SO_LINGER) + .map(from_linger) } } @@ -763,7 +779,7 @@ impl Socket { /// On Apple platforms (e.g. macOS, iOS, etc) this uses `SO_LINGER_SEC`. pub fn set_linger(&self, linger: Option) -> io::Result<()> { let linger = into_linger(linger); - unsafe { setsockopt(self.inner, sys::SOL_SOCKET, sys::SO_LINGER, linger) } + unsafe { setsockopt(self.as_raw(), sys::SOL_SOCKET, sys::SO_LINGER, linger) } } /// Get value for the `SO_OOBINLINE` option on this socket. @@ -774,7 +790,7 @@ impl Socket { #[cfg(not(target_os = "redox"))] pub fn out_of_band_inline(&self) -> io::Result { unsafe { - getsockopt::(self.inner, sys::SOL_SOCKET, sys::SO_OOBINLINE) + getsockopt::(self.as_raw(), sys::SOL_SOCKET, sys::SO_OOBINLINE) .map(|oob_inline| oob_inline != 0) } } @@ -789,7 +805,7 @@ impl Socket { pub fn set_out_of_band_inline(&self, oob_inline: bool) -> io::Result<()> { unsafe { setsockopt( - self.inner, + self.as_raw(), sys::SOL_SOCKET, sys::SO_OOBINLINE, oob_inline as c_int, @@ -804,7 +820,7 @@ impl Socket { /// [`set_recv_buffer_size`]: Socket::set_recv_buffer_size pub fn recv_buffer_size(&self) -> io::Result { unsafe { - getsockopt::(self.inner, sys::SOL_SOCKET, sys::SO_RCVBUF) + getsockopt::(self.as_raw(), sys::SOL_SOCKET, sys::SO_RCVBUF) .map(|size| size as usize) } } @@ -814,7 +830,14 @@ impl Socket { /// Changes the size of the operating system's receive buffer associated /// with the socket. pub fn set_recv_buffer_size(&self, size: usize) -> io::Result<()> { - unsafe { setsockopt(self.inner, sys::SOL_SOCKET, sys::SO_RCVBUF, size as c_int) } + unsafe { + setsockopt( + self.as_raw(), + sys::SOL_SOCKET, + sys::SO_RCVBUF, + size as c_int, + ) + } } /// Get value for the `SO_RCVTIMEO` option on this socket. @@ -822,7 +845,7 @@ impl Socket { /// If the returned timeout is `None`, then `read` and `recv` calls will /// block indefinitely. pub fn read_timeout(&self) -> io::Result> { - sys::timeout_opt(self.inner, sys::SOL_SOCKET, sys::SO_RCVTIMEO) + sys::timeout_opt(self.as_raw(), sys::SOL_SOCKET, sys::SO_RCVTIMEO) } /// Set value for the `SO_RCVTIMEO` option on this socket. @@ -830,7 +853,7 @@ impl Socket { /// If `timeout` is `None`, then `read` and `recv` calls will block /// indefinitely. pub fn set_read_timeout(&self, duration: Option) -> io::Result<()> { - sys::set_timeout_opt(self.inner, sys::SOL_SOCKET, sys::SO_RCVTIMEO, duration) + sys::set_timeout_opt(self.as_raw(), sys::SOL_SOCKET, sys::SO_RCVTIMEO, duration) } /// Get the value of the `SO_REUSEADDR` option on this socket. @@ -840,7 +863,7 @@ impl Socket { /// [`set_reuse_address`]: Socket::set_reuse_address pub fn reuse_address(&self) -> io::Result { unsafe { - getsockopt::(self.inner, sys::SOL_SOCKET, sys::SO_REUSEADDR) + getsockopt::(self.as_raw(), sys::SOL_SOCKET, sys::SO_REUSEADDR) .map(|reuse| reuse != 0) } } @@ -853,7 +876,7 @@ impl Socket { pub fn set_reuse_address(&self, reuse: bool) -> io::Result<()> { unsafe { setsockopt( - self.inner, + self.as_raw(), sys::SOL_SOCKET, sys::SO_REUSEADDR, reuse as c_int, @@ -868,7 +891,7 @@ impl Socket { /// [`set_send_buffer_size`]: Socket::set_send_buffer_size pub fn send_buffer_size(&self) -> io::Result { unsafe { - getsockopt::(self.inner, sys::SOL_SOCKET, sys::SO_SNDBUF) + getsockopt::(self.as_raw(), sys::SOL_SOCKET, sys::SO_SNDBUF) .map(|size| size as usize) } } @@ -878,7 +901,14 @@ impl Socket { /// Changes the size of the operating system's send buffer associated with /// the socket. pub fn set_send_buffer_size(&self, size: usize) -> io::Result<()> { - unsafe { setsockopt(self.inner, sys::SOL_SOCKET, sys::SO_SNDBUF, size as c_int) } + unsafe { + setsockopt( + self.as_raw(), + sys::SOL_SOCKET, + sys::SO_SNDBUF, + size as c_int, + ) + } } /// Get value for the `SO_SNDTIMEO` option on this socket. @@ -886,7 +916,7 @@ impl Socket { /// If the returned timeout is `None`, then `write` and `send` calls will /// block indefinitely. pub fn write_timeout(&self) -> io::Result> { - sys::timeout_opt(self.inner, sys::SOL_SOCKET, sys::SO_SNDTIMEO) + sys::timeout_opt(self.as_raw(), sys::SOL_SOCKET, sys::SO_SNDTIMEO) } /// Set value for the `SO_SNDTIMEO` option on this socket. @@ -894,7 +924,7 @@ impl Socket { /// If `timeout` is `None`, then `write` and `send` calls will block /// indefinitely. pub fn set_write_timeout(&self, duration: Option) -> io::Result<()> { - sys::set_timeout_opt(self.inner, sys::SOL_SOCKET, sys::SO_SNDTIMEO, duration) + sys::set_timeout_opt(self.as_raw(), sys::SOL_SOCKET, sys::SO_SNDTIMEO, duration) } } @@ -937,7 +967,7 @@ impl Socket { imr_multiaddr: sys::to_in_addr(multiaddr), imr_interface: sys::to_in_addr(interface), }; - unsafe { setsockopt(self.inner, sys::IPPROTO_IP, sys::IP_ADD_MEMBERSHIP, mreq) } + unsafe { setsockopt(self.as_raw(), sys::IPPROTO_IP, sys::IP_ADD_MEMBERSHIP, mreq) } } /// Leave a multicast group using `IP_DROP_MEMBERSHIP` option on this socket. @@ -950,7 +980,14 @@ impl Socket { imr_multiaddr: sys::to_in_addr(multiaddr), imr_interface: sys::to_in_addr(interface), }; - unsafe { setsockopt(self.inner, sys::IPPROTO_IP, sys::IP_DROP_MEMBERSHIP, mreq) } + unsafe { + setsockopt( + self.as_raw(), + sys::IPPROTO_IP, + sys::IP_DROP_MEMBERSHIP, + mreq, + ) + } } /// Get the value of the `IP_MULTICAST_IF` option for this socket. @@ -960,7 +997,7 @@ impl Socket { /// [`set_multicast_if_v4`]: Socket::set_multicast_if_v4 pub fn multicast_if_v4(&self) -> io::Result { unsafe { - getsockopt(self.inner, sys::IPPROTO_IP, sys::IP_MULTICAST_IF).map(sys::from_in_addr) + getsockopt(self.as_raw(), sys::IPPROTO_IP, sys::IP_MULTICAST_IF).map(sys::from_in_addr) } } @@ -969,7 +1006,14 @@ impl Socket { /// Specifies the interface to use for routing multicast packets. pub fn set_multicast_if_v4(&self, interface: &Ipv4Addr) -> io::Result<()> { let interface = sys::to_in_addr(interface); - unsafe { setsockopt(self.inner, sys::IPPROTO_IP, sys::IP_MULTICAST_IF, interface) } + unsafe { + setsockopt( + self.as_raw(), + sys::IPPROTO_IP, + sys::IP_MULTICAST_IF, + interface, + ) + } } /// Get the value of the `IP_MULTICAST_LOOP` option for this socket. @@ -979,7 +1023,7 @@ impl Socket { /// [`set_multicast_loop_v4`]: Socket::set_multicast_loop_v4 pub fn multicast_loop_v4(&self) -> io::Result { unsafe { - getsockopt::(self.inner, sys::IPPROTO_IP, sys::IP_MULTICAST_LOOP) + getsockopt::(self.as_raw(), sys::IPPROTO_IP, sys::IP_MULTICAST_LOOP) .map(|loop_v4| loop_v4 != 0) } } @@ -991,7 +1035,7 @@ impl Socket { pub fn set_multicast_loop_v4(&self, loop_v4: bool) -> io::Result<()> { unsafe { setsockopt( - self.inner, + self.as_raw(), sys::IPPROTO_IP, sys::IP_MULTICAST_LOOP, loop_v4 as c_int, @@ -1006,7 +1050,7 @@ impl Socket { /// [`set_multicast_ttl_v4`]: Socket::set_multicast_ttl_v4 pub fn multicast_ttl_v4(&self) -> io::Result { unsafe { - getsockopt::(self.inner, sys::IPPROTO_IP, sys::IP_MULTICAST_TTL) + getsockopt::(self.as_raw(), sys::IPPROTO_IP, sys::IP_MULTICAST_TTL) .map(|ttl| ttl as u32) } } @@ -1021,7 +1065,7 @@ impl Socket { pub fn set_multicast_ttl_v4(&self, ttl: u32) -> io::Result<()> { unsafe { setsockopt( - self.inner, + self.as_raw(), sys::IPPROTO_IP, sys::IP_MULTICAST_TTL, ttl as c_int, @@ -1036,7 +1080,7 @@ impl Socket { /// [`set_ttl`]: Socket::set_ttl pub fn ttl(&self) -> io::Result { unsafe { - getsockopt::(self.inner, sys::IPPROTO_IP, sys::IP_TTL).map(|ttl| ttl as u32) + getsockopt::(self.as_raw(), sys::IPPROTO_IP, sys::IP_TTL).map(|ttl| ttl as u32) } } @@ -1045,7 +1089,7 @@ impl Socket { /// This value sets the time-to-live field that is used in every packet sent /// from this socket. pub fn set_ttl(&self, ttl: u32) -> io::Result<()> { - unsafe { setsockopt(self.inner, sys::IPPROTO_IP, sys::IP_TTL, ttl as c_int) } + unsafe { setsockopt(self.as_raw(), sys::IPPROTO_IP, sys::IP_TTL, ttl as c_int) } } } @@ -1070,7 +1114,7 @@ impl Socket { }; unsafe { setsockopt( - self.inner, + self.as_raw(), sys::IPPROTO_IPV6, sys::IPV6_ADD_MEMBERSHIP, mreq, @@ -1093,7 +1137,7 @@ impl Socket { }; unsafe { setsockopt( - self.inner, + self.as_raw(), sys::IPPROTO_IPV6, sys::IPV6_DROP_MEMBERSHIP, mreq, @@ -1108,7 +1152,7 @@ impl Socket { /// [`set_multicast_hops_v6`]: Socket::set_multicast_hops_v6 pub fn multicast_hops_v6(&self) -> io::Result { unsafe { - getsockopt::(self.inner, sys::IPPROTO_IPV6, sys::IPV6_MULTICAST_HOPS) + getsockopt::(self.as_raw(), sys::IPPROTO_IPV6, sys::IPV6_MULTICAST_HOPS) .map(|hops| hops as u32) } } @@ -1121,7 +1165,7 @@ impl Socket { pub fn set_multicast_hops_v6(&self, hops: u32) -> io::Result<()> { unsafe { setsockopt( - self.inner, + self.as_raw(), sys::IPPROTO_IPV6, sys::IPV6_MULTICAST_HOPS, hops as c_int, @@ -1136,7 +1180,7 @@ impl Socket { /// [`set_multicast_if_v6`]: Socket::set_multicast_if_v6 pub fn multicast_if_v6(&self) -> io::Result { unsafe { - getsockopt::(self.inner, sys::IPPROTO_IPV6, sys::IPV6_MULTICAST_IF) + getsockopt::(self.as_raw(), sys::IPPROTO_IPV6, sys::IPV6_MULTICAST_IF) .map(|interface| interface as u32) } } @@ -1149,7 +1193,7 @@ impl Socket { pub fn set_multicast_if_v6(&self, interface: u32) -> io::Result<()> { unsafe { setsockopt( - self.inner, + self.as_raw(), sys::IPPROTO_IPV6, sys::IPV6_MULTICAST_IF, interface as c_int, @@ -1164,7 +1208,7 @@ impl Socket { /// [`set_multicast_loop_v6`]: Socket::set_multicast_loop_v6 pub fn multicast_loop_v6(&self) -> io::Result { unsafe { - getsockopt::(self.inner, sys::IPPROTO_IPV6, sys::IPV6_MULTICAST_LOOP) + getsockopt::(self.as_raw(), sys::IPPROTO_IPV6, sys::IPV6_MULTICAST_LOOP) .map(|loop_v6| loop_v6 != 0) } } @@ -1176,7 +1220,7 @@ impl Socket { pub fn set_multicast_loop_v6(&self, loop_v6: bool) -> io::Result<()> { unsafe { setsockopt( - self.inner, + self.as_raw(), sys::IPPROTO_IPV6, sys::IPV6_MULTICAST_LOOP, loop_v6 as c_int, @@ -1189,7 +1233,7 @@ impl Socket { /// Specifies the hop limit for ipv6 unicast packets pub fn unicast_hops_v6(&self) -> io::Result { unsafe { - getsockopt::(self.inner, sys::IPPROTO_IPV6, sys::IPV6_UNICAST_HOPS) + getsockopt::(self.as_raw(), sys::IPPROTO_IPV6, sys::IPV6_UNICAST_HOPS) .map(|hops| hops as u32) } } @@ -1200,7 +1244,7 @@ impl Socket { pub fn set_unicast_hops_v6(&self, hops: u32) -> io::Result<()> { unsafe { setsockopt( - self.inner, + self.as_raw(), sys::IPPROTO_IPV6, sys::IPV6_UNICAST_HOPS, hops as c_int, @@ -1215,7 +1259,7 @@ impl Socket { /// [`set_only_v6`]: Socket::set_only_v6 pub fn only_v6(&self) -> io::Result { unsafe { - getsockopt::(self.inner, sys::IPPROTO_IPV6, sys::IPV6_V6ONLY) + getsockopt::(self.as_raw(), sys::IPPROTO_IPV6, sys::IPV6_V6ONLY) .map(|only_v6| only_v6 != 0) } } @@ -1231,7 +1275,7 @@ impl Socket { pub fn set_only_v6(&self, only_v6: bool) -> io::Result<()> { unsafe { setsockopt( - self.inner, + self.as_raw(), sys::IPPROTO_IPV6, sys::IPV6_V6ONLY, only_v6 as c_int, @@ -1253,7 +1297,7 @@ impl Socket { /// operating systems. #[cfg(all(feature = "all", not(windows)))] pub fn keepalive_time(&self) -> io::Result { - sys::keepalive_time(self.inner) + sys::keepalive_time(self.as_raw()) } /// Get the value of the `TCP_KEEPINTVL` option on this socket. @@ -1276,7 +1320,7 @@ impl Socket { ))] pub fn keepalive_interval(&self) -> io::Result { unsafe { - getsockopt::(self.inner, sys::IPPROTO_TCP, sys::TCP_KEEPINTVL) + getsockopt::(self.as_raw(), sys::IPPROTO_TCP, sys::TCP_KEEPINTVL) .map(|secs| Duration::from_secs(secs as u64)) } } @@ -1301,7 +1345,7 @@ impl Socket { ))] pub fn keepalive_retries(&self) -> io::Result { unsafe { - getsockopt::(self.inner, sys::IPPROTO_TCP, sys::TCP_KEEPCNT) + getsockopt::(self.as_raw(), sys::IPPROTO_TCP, sys::TCP_KEEPCNT) .map(|retries| retries as u32) } } @@ -1346,7 +1390,7 @@ impl Socket { /// pub fn set_tcp_keepalive(&self, params: &TcpKeepalive) -> io::Result<()> { self.set_keepalive(true)?; - sys::set_tcp_keepalive(self.inner, params) + sys::set_tcp_keepalive(self.as_raw(), params) } /// Get the value of the `TCP_NODELAY` option on this socket. @@ -1356,7 +1400,7 @@ impl Socket { /// [`set_nodelay`]: Socket::set_nodelay pub fn nodelay(&self) -> io::Result { unsafe { - getsockopt::(self.inner, sys::IPPROTO_TCP, sys::TCP_NODELAY) + getsockopt::(self.as_raw(), sys::IPPROTO_TCP, sys::TCP_NODELAY) .map(|nodelay| nodelay != 0) } } @@ -1371,7 +1415,7 @@ impl Socket { pub fn set_nodelay(&self, nodelay: bool) -> io::Result<()> { unsafe { setsockopt( - self.inner, + self.as_raw(), sys::IPPROTO_TCP, sys::TCP_NODELAY, nodelay as c_int, @@ -1447,7 +1491,7 @@ impl<'a> Write for &'a Socket { impl fmt::Debug for Socket { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("Socket") - .field("raw", &self.inner) + .field("raw", &self.as_raw()) .field("local_addr", &self.local_addr().ok()) .field("peer_addr", &self.peer_addr().ok()) .finish() @@ -1460,9 +1504,3 @@ from!(net::UdpSocket, Socket); from!(Socket, net::TcpStream); from!(Socket, net::TcpListener); from!(Socket, net::UdpSocket); - -impl Drop for Socket { - fn drop(&mut self) { - sys::close(self.inner); - } -} diff --git a/src/sockref.rs b/src/sockref.rs index 84157189..279e6878 100644 --- a/src/sockref.rs +++ b/src/sockref.rs @@ -105,7 +105,7 @@ where impl fmt::Debug for SockRef<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("SockRef") - .field("raw", &self.socket.inner) + .field("raw", &self.socket.as_raw()) .field("local_addr", &self.socket.local_addr().ok()) .field("peer_addr", &self.socket.peer_addr().ok()) .finish() diff --git a/src/sys/unix.rs b/src/sys/unix.rs index bde007b0..49a63e91 100644 --- a/src/sys/unix.rs +++ b/src/sys/unix.rs @@ -482,6 +482,18 @@ impl SockAddr { pub(crate) type Socket = c_int; +pub(crate) fn socket_from_raw(socket: Socket) -> crate::socket::Inner { + unsafe { crate::socket::Inner::from_raw_fd(socket) } +} + +pub(crate) fn socket_as_raw(socket: &crate::socket::Inner) -> Socket { + socket.as_raw_fd() +} + +pub(crate) fn socket_into_raw(socket: crate::socket::Inner) -> Socket { + socket.into_raw_fd() +} + pub(crate) fn socket(family: c_int, ty: c_int, protocol: c_int) -> io::Result { syscall!(socket(family, ty, protocol)) } @@ -504,7 +516,7 @@ pub(crate) fn poll_connect(socket: &crate::Socket, timeout: Duration) -> io::Res let start = Instant::now(); let mut pollfd = libc::pollfd { - fd: socket.inner, + fd: socket.as_raw(), events: libc::POLLIN | libc::POLLOUT, revents: 0, }; @@ -884,12 +896,6 @@ pub(crate) unsafe fn setsockopt( .map(|_| ()) } -pub(crate) fn close(fd: Socket) { - unsafe { - let _ = libc::close(fd); - } -} - pub(crate) fn to_in_addr(addr: &Ipv4Addr) -> in_addr { // `s_addr` is stored as BE on all machines, and the array is in BE order. // So the native endian conversion method is used so that it's never @@ -953,8 +959,8 @@ impl crate::Socket { // Safety: `accept4` initialises the `SockAddr` for us. unsafe { SockAddr::init(|storage, len| { - syscall!(accept4(self.inner, storage.cast(), len, flags)) - .map(|inner| crate::Socket { inner }) + syscall!(accept4(self.as_raw(), storage.cast(), len, flags)) + .map(crate::Socket::from_raw) }) } } @@ -971,9 +977,19 @@ impl crate::Socket { pub(crate) fn _set_cloexec(&self, close_on_exec: bool) -> io::Result<()> { if close_on_exec { - fcntl_add(self.inner, libc::F_GETFD, libc::F_SETFD, libc::FD_CLOEXEC) + fcntl_add( + self.as_raw(), + libc::F_GETFD, + libc::F_SETFD, + libc::FD_CLOEXEC, + ) } else { - fcntl_remove(self.inner, libc::F_GETFD, libc::F_SETFD, libc::FD_CLOEXEC) + fcntl_remove( + self.as_raw(), + libc::F_GETFD, + libc::F_SETFD, + libc::FD_CLOEXEC, + ) } } @@ -991,7 +1007,7 @@ impl crate::Socket { pub(crate) fn _set_nosigpipe(&self, nosigpipe: bool) -> io::Result<()> { unsafe { setsockopt( - self.inner, + self.as_raw(), libc::SOL_SOCKET, libc::SO_NOSIGPIPE, nosigpipe as c_int, @@ -1007,7 +1023,7 @@ impl crate::Socket { #[cfg(all(feature = "all", not(target_os = "redox")))] pub fn mss(&self) -> io::Result { unsafe { - getsockopt::(self.inner, libc::IPPROTO_TCP, libc::TCP_MAXSEG) + getsockopt::(self.as_raw(), libc::IPPROTO_TCP, libc::TCP_MAXSEG) .map(|mss| mss as u32) } } @@ -1020,7 +1036,7 @@ impl crate::Socket { pub fn set_mss(&self, mss: u32) -> io::Result<()> { unsafe { setsockopt( - self.inner, + self.as_raw(), libc::IPPROTO_TCP, libc::TCP_MAXSEG, mss as c_int, @@ -1041,7 +1057,8 @@ impl crate::Socket { ))] pub fn is_listener(&self) -> io::Result { unsafe { - getsockopt::(self.inner, libc::SOL_SOCKET, libc::SO_ACCEPTCONN).map(|v| v != 0) + getsockopt::(self.as_raw(), libc::SOL_SOCKET, libc::SO_ACCEPTCONN) + .map(|v| v != 0) } } @@ -1058,7 +1075,7 @@ impl crate::Socket { ) ))] pub fn domain(&self) -> io::Result { - unsafe { getsockopt::(self.inner, libc::SOL_SOCKET, libc::SO_DOMAIN).map(Domain) } + unsafe { getsockopt::(self.as_raw(), libc::SOL_SOCKET, libc::SO_DOMAIN).map(Domain) } } /// Returns the [`Protocol`] of this socket by checking the `SO_PROTOCOL` @@ -1074,7 +1091,8 @@ impl crate::Socket { ))] pub fn protocol(&self) -> io::Result> { unsafe { - getsockopt::(self.inner, libc::SOL_SOCKET, libc::SO_PROTOCOL).map(|v| match v { + getsockopt::(self.as_raw(), libc::SOL_SOCKET, libc::SO_PROTOCOL).map(|v| match v + { 0 => None, p => Some(Protocol(p)), }) @@ -1094,7 +1112,8 @@ impl crate::Socket { ))] pub fn mark(&self) -> io::Result { unsafe { - getsockopt::(self.inner, libc::SOL_SOCKET, libc::SO_MARK).map(|mark| mark as u32) + getsockopt::(self.as_raw(), libc::SOL_SOCKET, libc::SO_MARK) + .map(|mark| mark as u32) } } @@ -1111,7 +1130,14 @@ impl crate::Socket { any(target_os = "android", target_os = "fuchsia", target_os = "linux") ))] pub fn set_mark(&self, mark: u32) -> io::Result<()> { - unsafe { setsockopt::(self.inner, libc::SOL_SOCKET, libc::SO_MARK, mark as c_int) } + unsafe { + setsockopt::( + self.as_raw(), + libc::SOL_SOCKET, + libc::SO_MARK, + mark as c_int, + ) + } } /// Gets the value for the `SO_BINDTODEVICE` option on this socket. @@ -1130,7 +1156,7 @@ impl crate::Socket { let mut len = buf.len() as libc::socklen_t; unsafe { syscall!(getsockopt( - self.inner, + self.as_raw(), libc::SOL_SOCKET, libc::SO_BINDTODEVICE, buf.as_mut_ptr().cast(), @@ -1166,7 +1192,7 @@ impl crate::Socket { (ptr::null(), 0) }; syscall!(setsockopt( - self.inner, + self.as_raw(), libc::SOL_SOCKET, libc::SO_BINDTODEVICE, value.cast(), @@ -1185,7 +1211,7 @@ impl crate::Socket { #[cfg(all(feature = "all", any(target_os = "linux")))] pub fn cpu_affinity(&self) -> io::Result { unsafe { - getsockopt::(self.inner, libc::SOL_SOCKET, libc::SO_INCOMING_CPU) + getsockopt::(self.as_raw(), libc::SOL_SOCKET, libc::SO_INCOMING_CPU) .map(|cpu| cpu as usize) } } @@ -1199,7 +1225,7 @@ impl crate::Socket { pub fn set_cpu_affinity(&self, cpu: usize) -> io::Result<()> { unsafe { setsockopt( - self.inner, + self.as_raw(), libc::SOL_SOCKET, libc::SO_INCOMING_CPU, cpu as c_int, @@ -1220,7 +1246,7 @@ impl crate::Socket { ))] pub fn reuse_port(&self) -> io::Result { unsafe { - getsockopt::(self.inner, libc::SOL_SOCKET, libc::SO_REUSEPORT) + getsockopt::(self.as_raw(), libc::SOL_SOCKET, libc::SO_REUSEPORT) .map(|reuse| reuse != 0) } } @@ -1239,7 +1265,7 @@ impl crate::Socket { pub fn set_reuse_port(&self, reuse: bool) -> io::Result<()> { unsafe { setsockopt( - self.inner, + self.as_raw(), libc::SOL_SOCKET, libc::SO_REUSEPORT, reuse as c_int, @@ -1260,7 +1286,7 @@ impl crate::Socket { ))] pub fn freebind(&self) -> io::Result { unsafe { - getsockopt::(self.inner, libc::SOL_SOCKET, libc::IP_FREEBIND) + getsockopt::(self.as_raw(), libc::SOL_SOCKET, libc::IP_FREEBIND) .map(|reuse| reuse != 0) } } @@ -1281,7 +1307,7 @@ impl crate::Socket { pub fn set_freebind(&self, reuse: bool) -> io::Result<()> { unsafe { setsockopt( - self.inner, + self.as_raw(), libc::SOL_SOCKET, libc::IP_FREEBIND, reuse as c_int, @@ -1344,7 +1370,7 @@ impl crate::Socket { }; syscall!(sendfile( file, - self.inner, + self.as_raw(), offset, &mut length, ptr::null_mut(), @@ -1366,7 +1392,7 @@ impl crate::Socket { None => 0x7ffff000, // 2,147,479,552 bytes. }; let mut offset = offset; - syscall!(sendfile(self.inner, file, &mut offset, count)).map(|n| n as usize) + syscall!(sendfile(self.as_raw(), file, &mut offset, count)).map(|n| n as usize) } #[cfg(all(feature = "all", target_os = "freebsd"))] @@ -1384,7 +1410,7 @@ impl crate::Socket { let mut sbytes: libc::off_t = 0; syscall!(sendfile( file, - self.inner, + self.as_raw(), offset, nbytes, ptr::null_mut(), @@ -1397,21 +1423,19 @@ impl crate::Socket { impl AsRawFd for crate::Socket { fn as_raw_fd(&self) -> c_int { - self.inner + self.as_raw() } } impl IntoRawFd for crate::Socket { fn into_raw_fd(self) -> c_int { - let fd = self.inner; - mem::forget(self); - fd + self.into_raw() } } impl FromRawFd for crate::Socket { unsafe fn from_raw_fd(fd: c_int) -> crate::Socket { - crate::Socket { inner: fd } + crate::Socket::from_raw(fd) } } diff --git a/src/sys/windows.rs b/src/sys/windows.rs index ad5cc723..6eeb0215 100644 --- a/src/sys/windows.rs +++ b/src/sys/windows.rs @@ -190,6 +190,18 @@ fn init() { pub(crate) type Socket = sock::SOCKET; +pub(crate) fn socket_from_raw(socket: Socket) -> crate::socket::Inner { + unsafe { crate::socket::Inner::from_raw_socket(socket as RawSocket) } +} + +pub(crate) fn socket_as_raw(socket: &crate::socket::Inner) -> Socket { + socket.as_raw_socket() as Socket +} + +pub(crate) fn socket_into_raw(socket: crate::socket::Inner) -> Socket { + socket.into_raw_socket() as Socket +} + pub(crate) fn socket(family: c_int, mut ty: c_int, protocol: c_int) -> io::Result { init(); @@ -227,7 +239,7 @@ pub(crate) fn poll_connect(socket: &crate::Socket, timeout: Duration) -> io::Res let start = Instant::now(); let mut fd_array = WSAPOLLFD { - fd: socket.inner, + fd: socket.as_raw(), events: POLLRDNORM | POLLWRNORM, revents: 0, }; @@ -698,12 +710,6 @@ fn ioctlsocket(socket: Socket, cmd: c_long, payload: &mut u_long) -> io::Result< .map(|_| ()) } -pub(crate) fn close(socket: Socket) { - unsafe { - let _ = sock::closesocket(socket); - } -} - pub(crate) fn to_in_addr(addr: &Ipv4Addr) -> IN_ADDR { let mut s_un: in_addr_S_un = unsafe { mem::zeroed() }; // `S_un` is stored as BE on all machines, and the array is in BE order. So @@ -741,7 +747,7 @@ impl crate::Socket { // `sock::` path. let res = unsafe { SetHandleInformation( - self.inner as HANDLE, + self.as_raw() as HANDLE, winbase::HANDLE_FLAG_INHERIT, !no_inherit as _, ) @@ -757,23 +763,19 @@ impl crate::Socket { impl AsRawSocket for crate::Socket { fn as_raw_socket(&self) -> RawSocket { - self.inner as RawSocket + self.as_raw() as RawSocket } } impl IntoRawSocket for crate::Socket { fn into_raw_socket(self) -> RawSocket { - let socket = self.inner; - mem::forget(self); - socket as RawSocket + self.into_raw() as RawSocket } } impl FromRawSocket for crate::Socket { unsafe fn from_raw_socket(socket: RawSocket) -> crate::Socket { - crate::Socket { - inner: socket as Socket, - } + crate::Socket::from_raw(socket as Socket) } } diff --git a/tests/socket.rs b/tests/socket.rs index 32efe8ed..5f39bd8d 100644 --- a/tests/socket.rs +++ b/tests/socket.rs @@ -14,8 +14,8 @@ use std::io::IoSlice; #[cfg(all(unix, feature = "all"))] use std::io::Read; use std::io::Write; -use std::mem::MaybeUninit; -use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4}; +use std::mem::{self, MaybeUninit}; +use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4, TcpStream}; #[cfg(not(target_os = "redox"))] use std::net::{Ipv6Addr, SocketAddrV6}; #[cfg(all( @@ -953,6 +953,13 @@ fn cpu_affinity() { assert_eq!(socket.cpu_affinity().unwrap(), want); } +#[test] +fn niche() { + if mem::size_of::>() == mem::size_of::() { + assert_eq!(mem::size_of::>(), mem::size_of::()); + } +} + fn any_ipv4() -> SockAddr { SocketAddrV4::new(Ipv4Addr::LOCALHOST, 0).into() }