libs (impls-libstd | net)
net2_mutators
RFC 1158 proposed the addition
of more functionality for the TcpStream
, TcpListener
and UdpSocket
types,
but was declined so that those APIs could be built up out of tree in the net2
crate. This RFC proposes pulling portions of
net2's APIs into the standard library.
The functionality provided by the standard library's wrappers around standard
networking types is fairly limited, and there is a large set of well supported,
standard functionality that is not currently implemented in std::net
but has
existed in net2 for some time.
All of the methods to be added map directly to equivalent system calls.
This does not cover the entirety of net2's APIs. In particular, this RFC does not propose to touch the builder types.
The following methods will be added:
impl TcpStream {
fn set_nodelay(&self, nodelay: bool) -> io::Result<()>;
fn nodelay(&self) -> io::Result<bool>;
fn set_ttl(&self, ttl: u32) -> io::Result<()>;
fn ttl(&self) -> io::Result<u32>;
fn set_only_v6(&self, only_v6: bool) -> io::Result<()>;
fn only_v6(&self) -> io::Result<bool>;
fn take_error(&self) -> io::Result<Option<io::Error>>;
fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()>;
}
impl TcpListener {
fn set_ttl(&self, ttl: u32) -> io::Result<()>;
fn ttl(&self) -> io::Result<u32>;
fn set_only_v6(&self, only_v6: bool) -> io::Result<()>;
fn only_v6(&self) -> io::Result<bool>;
fn take_error(&self) -> io::Result<Option<io::Error>>;
fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()>;
}
impl UdpSocket {
fn set_broadcast(&self, broadcast: bool) -> io::Result<()>;
fn broadcast(&self) -> io::Result<bool>;
fn set_multicast_loop_v4(&self, multicast_loop_v4: bool) -> io::Result<()>;
fn multicast_loop_v4(&self) -> io::Result<bool>;
fn set_multicast_ttl_v4(&self, multicast_ttl_v4: u32) -> io::Result<()>;
fn multicast_ttl_v4(&self) -> io::Result<u32>;
fn set_multicast_loop_v6(&self, multicast_loop_v6: bool) -> io::Result<()>;
fn multicast_loop_v6(&self) -> io::Result<bool>;
fn set_ttl(&self, ttl: u32) -> io::Result<()>;
fn ttl(&self) -> io::Result<u32>;
fn set_only_v6(&self, only_v6: bool) -> io::Result<()>;
fn only_v6(&self) -> io::Result<bool>;
fn join_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()>;
fn join_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()>;
fn leave_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()>;
fn leave_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()>;
fn connect<A: ToSocketAddrs>(&self, addr: A) -> Result<()>;
fn send(&self, buf: &[u8]) -> Result<usize>;
fn recv(&self, buf: &mut [u8]) -> Result<usize>;
fn take_error(&self) -> io::Result<Option<io::Error>>;
fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()>;
}
The traditional approach would be to add these as unstable, inherent methods. However, since inherent methods take precedence over trait methods, this would cause all code using the extension traits in net2 to start reporting stability errors. Instead, we have two options:
Option 2 seems like the safer approach unless people feel comfortable with these APIs.
This is a fairly significant increase in the surface areas of these APIs, and most users will never touch some of the more obscure functionality that these provide.
We can leave some or all of this functionality in net2.
The stabilization path (see above).