rust-lang / rust-lang/rfcs

std::net wishlist issue

Open
#957 14 comments 4 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

T-libs
Dominant language
Markdown
Stars
6.6k
Forks
1.7k
Avg merge
16h 14m
Merged PRs (30d)
1

Description

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 https://github.com/rust-lang/rust/issues/23272

Reverse DNS

see https://github.com/rust-lang/rust/pull/23419 and https://github.com/rust-lang/rust/issues/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.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the API wishlist in this issue and read linked issue 23272, issue 22608, pull request 23161, and pull request 23419. Compare the proposed socket, address-family, DNS, and socket-option changes before splitting the scope; done would require a decided, implementable proposal rather than this open-ended list.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
networking
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
20/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.