Skip to content

std::net wishlist issue #957

Open
Open
@stepancheg

Description

@stepancheg

std::net could be better. Here is a list of things that could be added or changed to std::net.

Some changes need to be made before 1.0, because they are not backward compatible.

The list:

TcpListener::from_socket and into_socket

Sometimes a socket is got from outside, for example, from another process, or just created with custom options. For that case TcpListener needs TcpListener::from_socket constructor.

And similarly, TcpListener needs into_socket reverse operation.

nginx http server can upgrade to new executable without losing and single connection. It clears FD_CLOEXEC flag and execs. To make such code possible in rust, from_socket and into_socket operations are necessary.

TcpListener::bind: make it cross-platform

Currently, there's a huge difference in TcpListener::bind between Windows and other OSes.

Rust on Windows creates a socket with flag IPV6_V6ONLY set to true (that's default behavior on Windows), and false on other OSes.

So on Linux developer can create one socket to serve both IPV4 and IPv6 clients, and developers on Windows need two sockets.

Latter issue could be resolved but allowing socket customization in some form, but I think it is very important for Rust to be as cross-platform as possible by default.

I have a patch set that resolves this issue.

TcpListener::bind_to_port

There's need for simple fn TcpListener::bind_to_port that creates a socket, capable of simply serving on port, hiding implementation details from end user.

Listening on port is the most common operation, so it deserves a shortcut.

Such shortcut exists in Java, it is ServerSocket(int) constructor.

Option to disable IPv6

Sometimes systems (especially on servers) have IPv6 enabled but incorrectly configured. On such systems it is useful to have a simple option to disable IPv6.

For example, a server may have both IPv4 and IPv6 addresses, and IPv6 is blocked by a firewall. It a client connects to the IPv6 address first, they may need to wait 2 minutes until the first connect times out.

In Java such a mode can be set with the -Djava.net.preferIPv4Stack=true property.

I think Rust could use an environment variable like RUST_PREFER_IPV4=true.

Turning on such an option would make these changes:

  • bind_on_port binds only on IPv4
  • connect("host:port") will connect only to IPv4 hosts
  • lookup would return only IPv4 addresses

However, when IPv6 explicitly requested in code, it should work, e. g. connect("[2a03:2880:2130:cf05:face:b00c::1]:80") should work regardless of that option.

This option won't be needed in 10 years after widespread adoption of IPv6, but now it is useful for quick-and-dirty fixes.

TcpListener::bind should fail if there's more than one address.

Currently TcpListener::bind resolves parameter to a list of IPs, and binds to them until one first successful bind. This is dangerous. Consider a situation. You call bind with param like TcpListener::bind("foo:80"), and foo is resolved to both IPv4 and IPv6 addresses. Depending on your luck, you get a socket bound to IPv4 only or both IPv4/IPv6 addresses (on Linux). Fail-fast would be better here.

Better behavior is report an error host foo is resolved to more than one address.

IpAddrFamily enum

IpAddrFamily enum is trivial and useful. Rust should have it.

pub enum IpAddrFamily {
    V4,
    V6
}

lookup_host_as_family utility

fn lookup_host_as_family(host: &str, family: IpAddrFamily) ...

Sometimes it is useful to resolve host as specific address family (for example, when you know server only talks to IPv4).

This could be done by calling filter function on resulting iterator, but having this function is convenient. So the issue is minor.

Terminating UdpSocket::recv_from remotely

detailed in rust-lang/rust#23272

Reverse DNS

see rust-lang/rust#23419 and rust-lang/rust#22608

More socket options

There's lots of stuff you can do with sockets before they're bound or connected, and right now the convenience methods we provide package a lot of these steps into one bundle when they should be separable. This would probably manifest itself as some form of Socket API which just deals with generic sockets and such.

Metadata

Metadata

Assignees

No one assigned

    Labels

    T-libs-apiRelevant to the library API team, which will review and decide on the RFC.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions