use std::fmt;
use std::io::{self, Read, Write};
#[cfg(not(target_os = "redox"))]
use std::io::{IoSlice, IoSliceMut};
use std::mem::MaybeUninit;
use std::net::{self, Ipv4Addr, Ipv6Addr, Shutdown};
#[cfg(unix)]
use std::os::unix::io::{FromRawFd, IntoRawFd};
#[cfg(windows)]
use std::os::windows::io::{FromRawSocket, IntoRawSocket};
use std::time::Duration;
use crate::sys::{self, c_int, getsockopt, setsockopt, Bool};
use crate::{Domain, Protocol, SockAddr, TcpKeepalive, Type};
#[cfg(not(target_os = "redox"))]
use crate::{MaybeUninitSlice, RecvFlags};
pub struct Socket {
pub(crate) inner: sys::Socket,
}
impl Socket {
pub fn new(domain: Domain, ty: Type, protocol: Option<Protocol>) -> io::Result<Socket> {
let ty = set_common_type(ty);
Socket::new_raw(domain, ty, protocol).and_then(set_common_flags)
}
pub fn new_raw(domain: Domain, ty: Type, protocol: Option<Protocol>) -> io::Result<Socket> {
let protocol = protocol.map(|p| p.0).unwrap_or(0);
sys::socket(domain.0, ty.0, protocol).map(|inner| Socket { inner })
}
#[cfg(all(feature = "all", unix))]
pub fn pair(
domain: Domain,
ty: Type,
protocol: Option<Protocol>,
) -> io::Result<(Socket, Socket)> {
let ty = set_common_type(ty);
let (a, b) = Socket::pair_raw(domain, ty, protocol)?;
let a = set_common_flags(a)?;
let b = set_common_flags(b)?;
Ok((a, b))
}
#[cfg(all(feature = "all", unix))]
pub fn pair_raw(
domain: Domain,
ty: Type,
protocol: Option<Protocol>,
) -> 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] }))
}
pub fn bind(&self, address: &SockAddr) -> io::Result<()> {
sys::bind(self.inner, address)
}
pub fn connect(&self, address: &SockAddr) -> io::Result<()> {
sys::connect(self.inner, address)
}
pub fn connect_timeout(&self, addr: &SockAddr, timeout: Duration) -> io::Result<()> {
self.set_nonblocking(true)?;
let res = self.connect(addr);
self.set_nonblocking(false)?;
match res {
Ok(()) => return Ok(()),
Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {}
#[cfg(unix)]
Err(ref e) if e.raw_os_error() == Some(libc::EINPROGRESS) => {}
Err(e) => return Err(e),
}
sys::poll_connect(self, timeout)
}
pub fn listen(&self, backlog: c_int) -> io::Result<()> {
sys::listen(self.inner, backlog)
}
pub fn accept(&self) -> io::Result<(Socket, SockAddr)> {
#[cfg(any(
target_os = "android",
target_os = "dragonfly",
target_os = "freebsd",
target_os = "fuchsia",
target_os = "illumos",
target_os = "linux",
target_os = "netbsd",
target_os = "openbsd",
))]
return self._accept4(libc::SOCK_CLOEXEC);
#[cfg(not(any(
target_os = "android",
target_os = "dragonfly",
target_os = "freebsd",
target_os = "fuchsia",
target_os = "illumos",
target_os = "linux",
target_os = "netbsd",
target_os = "openbsd",
)))]
{
let (socket, addr) = self.accept_raw()?;
set_common_flags(socket).map(|socket| (socket, addr))
}
}
pub fn accept_raw(&self) -> io::Result<(Socket, SockAddr)> {
sys::accept(self.inner).map(|(inner, addr)| (Socket { inner }, addr))
}
pub fn local_addr(&self) -> io::Result<SockAddr> {
sys::getsockname(self.inner)
}
pub fn peer_addr(&self) -> io::Result<SockAddr> {
sys::getpeername(self.inner)
}
pub fn try_clone(&self) -> io::Result<Socket> {
sys::try_clone(self.inner).map(|inner| Socket { inner })
}
pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
sys::set_nonblocking(self.inner, nonblocking)
}
pub fn shutdown(&self, how: Shutdown) -> io::Result<()> {
sys::shutdown(self.inner, how)
}
pub fn recv(&self, buf: &mut [MaybeUninit<u8>]) -> io::Result<usize> {
self.recv_with_flags(buf, 0)
}
pub fn recv_out_of_band(&self, buf: &mut [MaybeUninit<u8>]) -> io::Result<usize> {
self.recv_with_flags(buf, sys::MSG_OOB)
}
pub fn recv_with_flags(
&self,
buf: &mut [MaybeUninit<u8>],
flags: sys::c_int,
) -> io::Result<usize> {
sys::recv(self.inner, buf, flags)
}
#[cfg(not(target_os = "redox"))]
pub fn recv_vectored(
&self,
bufs: &mut [MaybeUninitSlice<'_>],
) -> io::Result<(usize, RecvFlags)> {
self.recv_vectored_with_flags(bufs, 0)
}
#[cfg(not(target_os = "redox"))]
pub fn recv_vectored_with_flags(
&self,
bufs: &mut [MaybeUninitSlice<'_>],
flags: c_int,
) -> io::Result<(usize, RecvFlags)> {
sys::recv_vectored(self.inner, bufs, flags)
}
pub fn peek(&self, buf: &mut [MaybeUninit<u8>]) -> io::Result<usize> {
self.recv_with_flags(buf, sys::MSG_PEEK)
}
pub fn recv_from(&self, buf: &mut [MaybeUninit<u8>]) -> io::Result<(usize, SockAddr)> {
self.recv_from_with_flags(buf, 0)
}
pub fn recv_from_with_flags(
&self,
buf: &mut [MaybeUninit<u8>],
flags: c_int,
) -> io::Result<(usize, SockAddr)> {
sys::recv_from(self.inner, buf, flags)
}
#[cfg(not(target_os = "redox"))]
pub fn recv_from_vectored(
&self,
bufs: &mut [MaybeUninitSlice<'_>],
) -> io::Result<(usize, RecvFlags, SockAddr)> {
self.recv_from_vectored_with_flags(bufs, 0)
}
#[cfg(not(target_os = "redox"))]
pub fn recv_from_vectored_with_flags(
&self,
bufs: &mut [MaybeUninitSlice<'_>],
flags: c_int,
) -> io::Result<(usize, RecvFlags, SockAddr)> {
sys::recv_from_vectored(self.inner, bufs, flags)
}
pub fn peek_from(&self, buf: &mut [MaybeUninit<u8>]) -> io::Result<(usize, SockAddr)> {
self.recv_from_with_flags(buf, sys::MSG_PEEK)
}
pub fn send(&self, buf: &[u8]) -> io::Result<usize> {
self.send_with_flags(buf, 0)
}
pub fn send_with_flags(&self, buf: &[u8], flags: c_int) -> io::Result<usize> {
sys::send(self.inner, buf, flags)
}
#[cfg(not(target_os = "redox"))]
pub fn send_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
self.send_vectored_with_flags(bufs, 0)
}
#[cfg(not(target_os = "redox"))]
pub fn send_vectored_with_flags(
&self,
bufs: &[IoSlice<'_>],
flags: c_int,
) -> io::Result<usize> {
sys::send_vectored(self.inner, bufs, flags)
}
pub fn send_out_of_band(&self, buf: &[u8]) -> io::Result<usize> {
self.send_with_flags(buf, sys::MSG_OOB)
}
pub fn send_to(&self, buf: &[u8], addr: &SockAddr) -> io::Result<usize> {
self.send_to_with_flags(buf, addr, 0)
}
pub fn send_to_with_flags(
&self,
buf: &[u8],
addr: &SockAddr,
flags: c_int,
) -> io::Result<usize> {
sys::send_to(self.inner, buf, addr, flags)
}
#[cfg(not(target_os = "redox"))]
pub fn send_to_vectored(&self, bufs: &[IoSlice<'_>], addr: &SockAddr) -> io::Result<usize> {
self.send_to_vectored_with_flags(bufs, addr, 0)
}
#[cfg(not(target_os = "redox"))]
pub fn send_to_vectored_with_flags(
&self,
bufs: &[IoSlice<'_>],
addr: &SockAddr,
flags: c_int,
) -> io::Result<usize> {
sys::send_to_vectored(self.inner, bufs, addr, flags)
}
}
#[inline(always)]
fn set_common_type(ty: Type) -> Type {
#[cfg(any(
target_os = "android",
target_os = "dragonfly",
target_os = "freebsd",
target_os = "fuchsia",
target_os = "illumos",
target_os = "linux",
target_os = "netbsd",
target_os = "openbsd",
))]
let ty = ty._cloexec();
#[cfg(windows)]
let ty = ty._no_inherit();
ty
}
#[inline(always)]
fn set_common_flags(socket: Socket) -> io::Result<Socket> {
#[cfg(all(
unix,
not(any(
target_os = "android",
target_os = "dragonfly",
target_os = "freebsd",
target_os = "fuchsia",
target_os = "illumos",
target_os = "linux",
target_os = "netbsd",
target_os = "openbsd",
))
))]
socket._set_cloexec(true)?;
#[cfg(target_vendor = "apple")]
socket._set_nosigpipe(true)?;
Ok(socket)
}
impl Socket {
pub fn broadcast(&self) -> io::Result<bool> {
unsafe {
getsockopt::<c_int>(self.inner, sys::SOL_SOCKET, sys::SO_BROADCAST)
.map(|broadcast| broadcast != 0)
}
}
pub fn set_broadcast(&self, broadcast: bool) -> io::Result<()> {
unsafe {
setsockopt(
self.inner,
sys::SOL_SOCKET,
sys::SO_BROADCAST,
broadcast as c_int,
)
}
}
pub fn take_error(&self) -> io::Result<Option<io::Error>> {
match unsafe { getsockopt::<c_int>(self.inner, 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),
}
}
pub fn keepalive(&self) -> io::Result<bool> {
unsafe {
getsockopt::<Bool>(self.inner, sys::SOL_SOCKET, sys::SO_KEEPALIVE)
.map(|keepalive| keepalive != 0)
}
}
pub fn set_keepalive(&self, keepalive: bool) -> io::Result<()> {
unsafe {
setsockopt(
self.inner,
sys::SOL_SOCKET,
sys::SO_KEEPALIVE,
keepalive as c_int,
)
}
}
pub fn linger(&self) -> io::Result<Option<Duration>> {
unsafe {
getsockopt::<sys::linger>(self.inner, sys::SOL_SOCKET, sys::SO_LINGER).map(from_linger)
}
}
pub fn set_linger(&self, linger: Option<Duration>) -> io::Result<()> {
let linger = into_linger(linger);
unsafe { setsockopt(self.inner, sys::SOL_SOCKET, sys::SO_LINGER, linger) }
}
#[cfg(not(target_os = "redox"))]
pub fn out_of_band_inline(&self) -> io::Result<bool> {
unsafe {
getsockopt::<c_int>(self.inner, sys::SOL_SOCKET, sys::SO_OOBINLINE)
.map(|oob_inline| oob_inline != 0)
}
}
#[cfg(not(target_os = "redox"))]
pub fn set_out_of_band_inline(&self, oob_inline: bool) -> io::Result<()> {
unsafe {
setsockopt(
self.inner,
sys::SOL_SOCKET,
sys::SO_OOBINLINE,
oob_inline as c_int,
)
}
}
pub fn recv_buffer_size(&self) -> io::Result<usize> {
unsafe {
getsockopt::<c_int>(self.inner, sys::SOL_SOCKET, sys::SO_RCVBUF)
.map(|size| size as usize)
}
}
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) }
}
pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
sys::timeout_opt(self.inner, sys::SOL_SOCKET, sys::SO_RCVTIMEO)
}
pub fn set_read_timeout(&self, duration: Option<Duration>) -> io::Result<()> {
sys::set_timeout_opt(self.inner, sys::SOL_SOCKET, sys::SO_RCVTIMEO, duration)
}
pub fn reuse_address(&self) -> io::Result<bool> {
unsafe {
getsockopt::<c_int>(self.inner, sys::SOL_SOCKET, sys::SO_REUSEADDR)
.map(|reuse| reuse != 0)
}
}
pub fn set_reuse_address(&self, reuse: bool) -> io::Result<()> {
unsafe {
setsockopt(
self.inner,
sys::SOL_SOCKET,
sys::SO_REUSEADDR,
reuse as c_int,
)
}
}
pub fn send_buffer_size(&self) -> io::Result<usize> {
unsafe {
getsockopt::<c_int>(self.inner, sys::SOL_SOCKET, sys::SO_SNDBUF)
.map(|size| size as usize)
}
}
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) }
}
pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
sys::timeout_opt(self.inner, sys::SOL_SOCKET, sys::SO_SNDTIMEO)
}
pub fn set_write_timeout(&self, duration: Option<Duration>) -> io::Result<()> {
sys::set_timeout_opt(self.inner, sys::SOL_SOCKET, sys::SO_SNDTIMEO, duration)
}
}
fn from_linger(linger: sys::linger) -> Option<Duration> {
if linger.l_onoff == 0 {
None
} else {
Some(Duration::from_secs(linger.l_linger as u64))
}
}
fn into_linger(duration: Option<Duration>) -> sys::linger {
match duration {
Some(duration) => sys::linger {
l_onoff: 1,
l_linger: duration.as_secs() as _,
},
None => sys::linger {
l_onoff: 0,
l_linger: 0,
},
}
}
impl Socket {
pub fn join_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()> {
let mreq = sys::IpMreq {
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) }
}
pub fn leave_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()> {
let mreq = sys::IpMreq {
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) }
}
pub fn multicast_if_v4(&self) -> io::Result<Ipv4Addr> {
unsafe {
getsockopt(self.inner, sys::IPPROTO_IP, sys::IP_MULTICAST_IF).map(sys::from_in_addr)
}
}
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) }
}
pub fn multicast_loop_v4(&self) -> io::Result<bool> {
unsafe {
getsockopt::<c_int>(self.inner, sys::IPPROTO_IP, sys::IP_MULTICAST_LOOP)
.map(|loop_v4| loop_v4 != 0)
}
}
pub fn set_multicast_loop_v4(&self, loop_v4: bool) -> io::Result<()> {
unsafe {
setsockopt(
self.inner,
sys::IPPROTO_IP,
sys::IP_MULTICAST_LOOP,
loop_v4 as c_int,
)
}
}
pub fn multicast_ttl_v4(&self) -> io::Result<u32> {
unsafe {
getsockopt::<c_int>(self.inner, sys::IPPROTO_IP, sys::IP_MULTICAST_TTL)
.map(|ttl| ttl as u32)
}
}
pub fn set_multicast_ttl_v4(&self, ttl: u32) -> io::Result<()> {
unsafe {
setsockopt(
self.inner,
sys::IPPROTO_IP,
sys::IP_MULTICAST_TTL,
ttl as c_int,
)
}
}
pub fn ttl(&self) -> io::Result<u32> {
unsafe {
getsockopt::<c_int>(self.inner, sys::IPPROTO_IP, sys::IP_TTL).map(|ttl| ttl as u32)
}
}
pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
unsafe { setsockopt(self.inner, sys::IPPROTO_IP, sys::IP_TTL, ttl as c_int) }
}
}
impl Socket {
pub fn join_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> {
let mreq = sys::Ipv6Mreq {
ipv6mr_multiaddr: sys::to_in6_addr(multiaddr),
ipv6mr_interface: interface as _,
};
unsafe {
setsockopt(
self.inner,
sys::IPPROTO_IPV6,
sys::IPV6_ADD_MEMBERSHIP,
mreq,
)
}
}
pub fn leave_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> {
let mreq = sys::Ipv6Mreq {
ipv6mr_multiaddr: sys::to_in6_addr(multiaddr),
ipv6mr_interface: interface as _,
};
unsafe {
setsockopt(
self.inner,
sys::IPPROTO_IPV6,
sys::IPV6_DROP_MEMBERSHIP,
mreq,
)
}
}
pub fn multicast_hops_v6(&self) -> io::Result<u32> {
unsafe {
getsockopt::<c_int>(self.inner, sys::IPPROTO_IPV6, sys::IPV6_MULTICAST_HOPS)
.map(|hops| hops as u32)
}
}
pub fn set_multicast_hops_v6(&self, hops: u32) -> io::Result<()> {
unsafe {
setsockopt(
self.inner,
sys::IPPROTO_IPV6,
sys::IPV6_MULTICAST_HOPS,
hops as c_int,
)
}
}
pub fn multicast_if_v6(&self) -> io::Result<u32> {
unsafe {
getsockopt::<c_int>(self.inner, sys::IPPROTO_IPV6, sys::IPV6_MULTICAST_IF)
.map(|interface| interface as u32)
}
}
pub fn set_multicast_if_v6(&self, interface: u32) -> io::Result<()> {
unsafe {
setsockopt(
self.inner,
sys::IPPROTO_IPV6,
sys::IPV6_MULTICAST_IF,
interface as c_int,
)
}
}
pub fn multicast_loop_v6(&self) -> io::Result<bool> {
unsafe {
getsockopt::<c_int>(self.inner, sys::IPPROTO_IPV6, sys::IPV6_MULTICAST_LOOP)
.map(|loop_v6| loop_v6 != 0)
}
}
pub fn set_multicast_loop_v6(&self, loop_v6: bool) -> io::Result<()> {
unsafe {
setsockopt(
self.inner,
sys::IPPROTO_IPV6,
sys::IPV6_MULTICAST_LOOP,
loop_v6 as c_int,
)
}
}
pub fn unicast_hops_v6(&self) -> io::Result<u32> {
unsafe {
getsockopt::<c_int>(self.inner, sys::IPPROTO_IPV6, sys::IPV6_UNICAST_HOPS)
.map(|hops| hops as u32)
}
}
pub fn set_unicast_hops_v6(&self, hops: u32) -> io::Result<()> {
unsafe {
setsockopt(
self.inner,
sys::IPPROTO_IPV6,
sys::IPV6_UNICAST_HOPS,
hops as c_int,
)
}
}
pub fn only_v6(&self) -> io::Result<bool> {
unsafe {
getsockopt::<c_int>(self.inner, sys::IPPROTO_IPV6, sys::IPV6_V6ONLY)
.map(|only_v6| only_v6 != 0)
}
}
pub fn set_only_v6(&self, only_v6: bool) -> io::Result<()> {
unsafe {
setsockopt(
self.inner,
sys::IPPROTO_IPV6,
sys::IPV6_V6ONLY,
only_v6 as c_int,
)
}
}
}
impl Socket {
#[cfg(all(feature = "all", not(windows)))]
pub fn keepalive_time(&self) -> io::Result<Duration> {
sys::keepalive_time(self.inner)
}
#[cfg(all(
feature = "all",
any(
target_os = "android",
target_os = "dragonfly",
target_os = "freebsd",
target_os = "fuchsia",
target_os = "illumos",
target_os = "linux",
target_os = "netbsd",
target_vendor = "apple",
)
))]
pub fn keepalive_interval(&self) -> io::Result<Duration> {
unsafe {
getsockopt::<c_int>(self.inner, sys::IPPROTO_TCP, sys::TCP_KEEPINTVL)
.map(|secs| Duration::from_secs(secs as u64))
}
}
#[cfg(all(
feature = "all",
any(
target_os = "android",
target_os = "dragonfly",
target_os = "freebsd",
target_os = "fuchsia",
target_os = "illumos",
target_os = "linux",
target_os = "netbsd",
target_vendor = "apple",
)
))]
pub fn keepalive_retries(&self) -> io::Result<u32> {
unsafe {
getsockopt::<c_int>(self.inner, sys::IPPROTO_TCP, sys::TCP_KEEPCNT)
.map(|retries| retries as u32)
}
}
pub fn set_tcp_keepalive(&self, params: &TcpKeepalive) -> io::Result<()> {
self.set_keepalive(true)?;
sys::set_tcp_keepalive(self.inner, params)
}
pub fn nodelay(&self) -> io::Result<bool> {
unsafe {
getsockopt::<Bool>(self.inner, sys::IPPROTO_TCP, sys::TCP_NODELAY)
.map(|nodelay| nodelay != 0)
}
}
pub fn set_nodelay(&self, nodelay: bool) -> io::Result<()> {
unsafe {
setsockopt(
self.inner,
sys::IPPROTO_TCP,
sys::TCP_NODELAY,
nodelay as c_int,
)
}
}
}
impl Read for Socket {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
let buf = unsafe { &mut *(buf as *mut [u8] as *mut [MaybeUninit<u8>]) };
self.recv(buf)
}
#[cfg(not(target_os = "redox"))]
fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
let bufs = unsafe { &mut *(bufs as *mut [IoSliceMut<'_>] as *mut [MaybeUninitSlice<'_>]) };
self.recv_vectored(bufs).map(|(n, _)| n)
}
}
impl<'a> Read for &'a Socket {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
let buf = unsafe { &mut *(buf as *mut [u8] as *mut [MaybeUninit<u8>]) };
self.recv(buf)
}
#[cfg(not(target_os = "redox"))]
fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
let bufs = unsafe { &mut *(bufs as *mut [IoSliceMut<'_>] as *mut [MaybeUninitSlice<'_>]) };
self.recv_vectored(bufs).map(|(n, _)| n)
}
}
impl Write for Socket {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.send(buf)
}
#[cfg(not(target_os = "redox"))]
fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
self.send_vectored(bufs)
}
fn flush(&mut self) -> io::Result<()> {
Ok(())
}
}
impl<'a> Write for &'a Socket {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.send(buf)
}
#[cfg(not(target_os = "redox"))]
fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
self.send_vectored(bufs)
}
fn flush(&mut self) -> io::Result<()> {
Ok(())
}
}
impl fmt::Debug for Socket {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Socket")
.field("raw", &self.inner)
.field("local_addr", &self.local_addr().ok())
.field("peer_addr", &self.peer_addr().ok())
.finish()
}
}
from!(net::TcpStream, Socket);
from!(net::TcpListener, Socket);
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);
}
}