Skip to content
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
111 changes: 98 additions & 13 deletions text/0517-io-os-reform.md
Original file line number Diff line number Diff line change
Expand Up @@ -1370,6 +1370,91 @@ The contents of `std::io::net` submodules `tcp`, `udp`, `ip` and
the other modules are being moved or removed and are described
elsewhere.

#### InetAddr

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't like how similar IpAddr and InetAddr are, and I think it's not obvious which one is which, just from looking at the names.

Could we choose either Inet or Ip and have, say, InetAddr (host address) and InetSocketAddr?


The composition of an `IpAddr` and a port. It has the following interface:

```rust
impl InetAddr {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just to clarify, did this purposefully omit the new function?

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah. I don't know what arguments a new function would take to make it work for both address types.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops, ignore that. I thought you were talking about IpAddr.

/// Returns a new InetAddr composed of an unspecified v4 IP and a 0
/// port
fn any_v4() -> InetAddr;

/// Returns a new InetAddr composed of an unspecified v6 IP and a 0
/// port
fn any_v6() -> InetAddr;

fn ip(&self) -> IpAddr;
fn port(&self) -> u16;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that port is part of udp and tcp, not part of inet (ip or ipv6) itself. It's possible to have an ip protocol without anything like a u16 port number.

That said: I'm not sure such a protocol exists.


/// Returns true if the IpAddr is unspecified and port == 0
fn is_unspecified(&self) -> bool;
}
```

#### IpAddr

Represents an IP address. It has the following interface:

```rust
impl IpAddr {
fn new_v4(a: u8, b: u8, c: u8, d: u8) -> IpAddr;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason there isn't a new that accepts an Ipv4Addr? Or is there a conversion provided that I'm overlooking?

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a ToIpAddr trait that the version-specific structures implement (or something similarly named... I think it has to_ipaddr()).

fn any_v4() -> IpAddr;

fn new_v6(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16, h: u16) -> IpAddr;
fn any_v6() -> IpAddr;

// The following functions proxy to the versioned IP address value
fn is_unspecified(&self) -> bool;
fn is_loopback(&self) -> bool;
fn is_global(&self) -> bool;
fn is_private(&self) -> bool;
fn is_multicast(&self) -> bool;
}
```

#### Ipv4Addr

Represents a version 4 IP address. It has the following interface:

```rust
impl Ipv4Addr {
fn new(a: u8, b: u8, c: u8, d: u8) -> Ipv4Addr;
fn any() -> Ipv4Addr;
fn octets(&self) -> [u8; 4];
fn is_unspecified(&self) -> bool;
fn is_loopback(&self) -> bool;
fn is_private(&self) -> bool;
fn is_link_local(&self) -> bool;
fn is_global(&self) -> bool;
fn is_multicast(&self) -> bool;
fn to_ipv6_compatible(&self) -> Ipv6Addr;
fn to_ipv6_mapped(&self) -> Ipv6Addr;
}
```

#### Ipv6Addr

Represents a version 6 IP address. It has the following interface:

```rust
impl Ipv6Addr {
fn new(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16, h: u16) -> Ipv6Addr;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason new takes separate parameters instead of a [u16; 8] ?

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only that this made it easier for users to switch from the old enum-based IpAddr::Ipv6Addr. Otherwise they'd need to do more than a simple addition of ::new. But that's not a good enough reason, and I think making callers pack the integers into a slice (just add brackets?) is better than making callers who already have a slice break that slice into separate arguments. So I'd change it to [u16; 8], as you said.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

... and the appropriate changes for Ipv4Addr and the new_v4-style functions.

fn any() -> Ipv6Addr;
fn segments(&self) -> [u16; 8]
fn is_unspecified(&self) -> bool;
fn is_loopback(&self) -> bool;
fn is_global(&self) -> bool;
fn is_unique_local(&self) -> bool;
fn is_unicast_link_local(&self) -> bool;
fn is_unicast_site_local(&self) -> bool;
fn is_unicast_global(&self) -> bool;
fn multicast_scope(&self) -> Option<Ipv6MulticastScope>;
fn is_multicast(&self) -> bool;
fn to_ipv4(&self) -> Option<Ipv4Addr>;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we're going to spell this out in the RFC I think we may want to hold off on some of these methods. These are pretty ambitious and a more conservative design would only have new and segments, for example. We can always add more over time but I think we may want to start off conservative.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(same for the v4 addr)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would keep is_unspecific, to_ipv4 and maybe is_multicast, but +1 for marking the others as experimental or removing them, at least until more people can read through the IP RFCs and validate the code.

}
```

#### TCP
[TCP]: #tcp

Expand All @@ -1380,9 +1465,9 @@ following interface:
// TcpStream, which contains both a reader and a writer

impl TcpStream {
fn connect<A: ToSocketAddrs>(addr: &A) -> io::Result<TcpStream>;
fn peer_addr(&self) -> io::Result<SocketAddr>;
fn socket_addr(&self) -> io::Result<SocketAddr>;
fn connect<A: ToInetAddrs>(addr: &A) -> io::Result<TcpStream>;
fn peer_addr(&self) -> io::Result<InetAddr>;
fn inet_addr(&self) -> io::Result<InetAddr>;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps we should take this opportunity to rename inet_addr to something that is more clearly the other side of peer_addr, maybe local_addr or our_addr? (of course, this would run into the issue of udp not having a peer_addr)

fn shutdown(&self, how: Shutdown) -> io::Result<()>;
fn duplicate(&self) -> io::Result<TcpStream>;
}
Expand Down Expand Up @@ -1420,10 +1505,10 @@ into the `TcpListener` structure. Specifically, this will be the resulting API:

```rust
impl TcpListener {
fn bind<A: ToSocketAddrs>(addr: &A) -> io::Result<TcpListener>;
fn socket_addr(&self) -> io::Result<SocketAddr>;
fn bind<A: ToInetAddrs>(addr: &A) -> io::Result<TcpListener>;
fn inet_addr(&self) -> io::Result<InetAddr>;
fn duplicate(&self) -> io::Result<TcpListener>;
fn accept(&self) -> io::Result<(TcpStream, SocketAddr)>;
fn accept(&self) -> io::Result<(TcpStream, InetAddr)>;
fn incoming(&self) -> Incoming;
}

Expand All @@ -1447,10 +1532,10 @@ Some major changes from today's API include:
date with a more robust interface.
* The `set_timeout` functionality has also been removed in favor of returning at
a later date in a more robust fashion with `select`.
* The `accept` function no longer takes `&mut self` and returns `SocketAddr`.
* The `accept` function no longer takes `&mut self` and returns `InetAddr`.
The change in mutability is done to express that multiple `accept` calls can
happen concurrently.
* For convenience the iterator does not yield the `SocketAddr` from `accept`.
* For convenience the iterator does not yield the `InetAddr` from `accept`.

The `TcpListener` type will also adhere to `Send` and `Sync`.

Expand All @@ -1462,10 +1547,10 @@ infrastructure will:

```rust
impl UdpSocket {
fn bind<A: ToSocketAddrs>(addr: &A) -> io::Result<UdpSocket>;
fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)>;
fn send_to<A: ToSocketAddrs>(&self, buf: &[u8], addr: &A) -> io::Result<usize>;
fn socket_addr(&self) -> io::Result<SocketAddr>;
fn bind<A: ToInetAddrs>(addr: &A) -> io::Result<UdpSocket>;
fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, InetAddr)>;
fn send_to<A: ToInetAddrs>(&self, buf: &[u8], addr: &A) -> io::Result<usize>;
fn inet_addr(&self) -> io::Result<InetAddr>;
fn duplicate(&self) -> io::Result<UdpSocket>;
}

Expand Down Expand Up @@ -1514,7 +1599,7 @@ For the current `addrinfo` module:

For the current `ip` module:

* The `ToSocketAddr` trait should become `ToSocketAddrs`
* The `ToInetAddr` trait should become `ToInetAddrs`

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There doesn't seem to be an existing ToInetAddr in rust at the moment, perhaps find-and-replace went a bit too far here?

Assuming that is the case, might also want to mention how ToInetAddrs differs from ToSocketAddr and/or ToSocketAddrs. (I presume it will just be changing the Iter type and the to_socket_addrs() function name)

* The default `to_socket_addr_all` method should be removed.

The actual address structures could use some scrutiny, but any
Expand Down