From f798674b86382929ca17c88de422a6e2fdb27f2a Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 13 Mar 2015 14:22:33 -0700 Subject: [PATCH] std: Stabilize the `net` module This commit performs a stabilization pass over the std::net module, incorporating the changes from RFC 923. Specifically, the following actions were taken: Stable functionality: * `net` (the name) * `Shutdown` * `Shutdown::{Read, Write, Both}` * `lookup_host` * `LookupHost` * `SocketAddr` * `SocketAddr::{V4, V6}` * `SocketAddr::port` * `SocketAddrV4` * `SocketAddrV4::{new, ip, port}` * `SocketAddrV6` * `SocketAddrV4::{new, ip, port, flowinfo, scope_id}` * Common trait impls for socket addr structures * `ToSocketAddrs` * `ToSocketAddrs::Iter` * `ToSocketAddrs::to_socket_addrs` * `ToSocketAddrs for {SocketAddr*, (Ipv*Addr, u16), str, (str, u16)}` * `Ipv4Addr` * `Ipv4Addr::{new, octets, to_ipv6_compatible, to_ipv6_mapped}` * `Ipv6Addr` * `Ipv6Addr::{new, segments, to_ipv4}` * `TcpStream` * `TcpStream::connect` * `TcpStream::{peer_addr, local_addr, shutdown, try_clone}` * `{Read,Write} for {TcpStream, &TcpStream}` * `TcpListener` * `TcpListener::bind` * `TcpListener::{local_addr, try_clone, accept, incoming}` * `Incoming` * `UdpSocket` * `UdpSocket::bind` * `UdpSocket::{recv_from, send_to, local_addr, try_clone}` Unstable functionality: * Extra methods on `Ipv{4,6}Addr` for various methods of inspecting the address and determining qualities of it. * Extra methods on `TcpStream` to configure various protocol options. * Extra methods on `UdpSocket` to configure various protocol options. Deprecated functionality: * The `socket_addr` method has been renamed to `local_addr` This commit is a breaking change due to the restructuring of the `SocketAddr` type as well as the renaming of the `socket_addr` method. Migration should be fairly straightforward, however, after accounting for the new level of abstraction in `SocketAddr` (protocol distinction at the socket address level, not the IP address). [breaking-change] --- src/compiletest/compiletest.rs | 1 - src/libstd/net/addr.rs | 395 ++++++++++++++++++++----------- src/libstd/net/ip.rs | 65 +++-- src/libstd/net/mod.rs | 17 +- src/libstd/net/parser.rs | 26 +- src/libstd/net/tcp.rs | 39 ++- src/libstd/net/test.rs | 11 +- src/libstd/net/udp.rs | 30 ++- src/libstd/sys/common/net2.rs | 32 +-- src/libstd/sys/unix/net.rs | 8 +- src/libstd/sys/windows/net.rs | 8 +- src/test/run-pass/issue-22577.rs | 5 +- 12 files changed, 408 insertions(+), 229 deletions(-) diff --git a/src/compiletest/compiletest.rs b/src/compiletest/compiletest.rs index 50e74a13ee2b7..5ef93cb569ec5 100644 --- a/src/compiletest/compiletest.rs +++ b/src/compiletest/compiletest.rs @@ -20,7 +20,6 @@ #![feature(std_misc)] #![feature(test)] #![feature(core)] -#![feature(net)] #![feature(path_ext)] #![deny(warnings)] diff --git a/src/libstd/net/addr.rs b/src/libstd/net/addr.rs index 101aae3eb248b..702f81db8e22f 100644 --- a/src/libstd/net/addr.rs +++ b/src/libstd/net/addr.rs @@ -15,150 +15,220 @@ use hash; use io; use libc::{self, socklen_t, sa_family_t}; use mem; -use net::{IpAddr, lookup_host, ntoh, hton}; +use net::{lookup_host, ntoh, hton, Ipv4Addr, Ipv6Addr}; use option; use sys_common::{FromInner, AsInner, IntoInner}; use vec; -/// Representation of a socket address for networking applications +/// Representation of a socket address for networking applications. /// -/// A socket address consists of at least an (ip, port) pair and may also -/// contain other information depending on the protocol. -#[derive(Copy, Clone, PartialEq, Eq, Hash)] -pub struct SocketAddr { - repr: Repr, +/// A socket address can either represent the IPv4 or IPv6 protocol and is +/// paired with at least a port number as well. Each protocol may have more +/// specific information about the address available to it as well. +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] +#[stable(feature = "rust1", since = "1.0.0")] +pub enum SocketAddr { + /// An IPv4 socket address which is a (ip, port) combination. + #[stable(feature = "rust1", since = "1.0.0")] + V4(SocketAddrV4), + /// An IPv6 socket address + #[stable(feature = "rust1", since = "1.0.0")] + V6(SocketAddrV6), } +/// An IPv4 socket address which is a (ip, port) combination. #[derive(Copy)] -enum Repr { - V4(libc::sockaddr_in), - V6(libc::sockaddr_in6), -} +#[stable(feature = "rust1", since = "1.0.0")] +pub struct SocketAddrV4 { inner: libc::sockaddr_in } + +/// An IPv6 socket address +#[derive(Copy)] +#[stable(feature = "rust1", since = "1.0.0")] +pub struct SocketAddrV6 { inner: libc::sockaddr_in6 } impl SocketAddr { + /// Gets the port number associated with this socket address + #[stable(feature = "rust1", since = "1.0.0")] + pub fn port(&self) -> u16 { + match *self { + SocketAddr::V4(ref a) => a.port(), + SocketAddr::V6(ref a) => a.port(), + } + } +} + +impl SocketAddrV4 { /// Creates a new socket address from the (ip, port) pair. - pub fn new(ip: IpAddr, port: u16) -> SocketAddr { - let repr = match ip { - IpAddr::V4(ref ip) => { - Repr::V4(libc::sockaddr_in { - sin_family: libc::AF_INET as sa_family_t, - sin_port: hton(port), - sin_addr: *ip.as_inner(), - .. unsafe { mem::zeroed() } - }) - } - IpAddr::V6(ref ip) => { - Repr::V6(libc::sockaddr_in6 { - sin6_family: libc::AF_INET6 as sa_family_t, - sin6_port: hton(port), - sin6_addr: *ip.as_inner(), - .. unsafe { mem::zeroed() } - }) - } - }; - SocketAddr { repr: repr } + #[stable(feature = "rust1", since = "1.0.0")] + pub fn new(ip: Ipv4Addr, port: u16) -> SocketAddrV4 { + SocketAddrV4 { + inner: libc::sockaddr_in { + sin_family: libc::AF_INET as sa_family_t, + sin_port: hton(port), + sin_addr: *ip.as_inner(), + .. unsafe { mem::zeroed() } + }, + } } /// Gets the IP address associated with this socket address. - pub fn ip(&self) -> IpAddr { - match self.repr { - Repr::V4(ref sa) => IpAddr::V4(FromInner::from_inner(sa.sin_addr)), - Repr::V6(ref sa) => IpAddr::V6(FromInner::from_inner(sa.sin6_addr)), + #[stable(feature = "rust1", since = "1.0.0")] + pub fn ip(&self) -> &Ipv4Addr { + unsafe { + &*(&self.inner.sin_addr as *const libc::in_addr as *const Ipv4Addr) } } /// Gets the port number associated with this socket address - pub fn port(&self) -> u16 { - match self.repr { - Repr::V4(ref sa) => ntoh(sa.sin_port), - Repr::V6(ref sa) => ntoh(sa.sin6_port), - } - } + #[stable(feature = "rust1", since = "1.0.0")] + pub fn port(&self) -> u16 { ntoh(self.inner.sin_port) } +} - fn set_port(&mut self, port: u16) { - match self.repr { - Repr::V4(ref mut sa) => sa.sin_port = hton(port), - Repr::V6(ref mut sa) => sa.sin6_port = hton(port), +impl SocketAddrV6 { + /// Creates a new socket address from the ip/port/flowinfo/scope_id + /// components. + #[stable(feature = "rust1", since = "1.0.0")] + pub fn new(ip: Ipv6Addr, port: u16, flowinfo: u32, scope_id: u32) + -> SocketAddrV6 { + SocketAddrV6 { + inner: libc::sockaddr_in6 { + sin6_family: libc::AF_INET6 as sa_family_t, + sin6_port: hton(port), + sin6_addr: *ip.as_inner(), + sin6_flowinfo: hton(flowinfo), + sin6_scope_id: hton(scope_id), + .. unsafe { mem::zeroed() } + }, } } -} -#[stable(feature = "rust1", since = "1.0.0")] -impl fmt::Display for SocketAddr { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self.repr { - Repr::V4(_) => write!(f, "{}:{}", self.ip(), self.port()), - Repr::V6(_) => write!(f, "[{}]:{}", self.ip(), self.port()), + /// Gets the IP address associated with this socket address. + #[stable(feature = "rust1", since = "1.0.0")] + pub fn ip(&self) -> &Ipv6Addr { + unsafe { + &*(&self.inner.sin6_addr as *const libc::in6_addr as *const Ipv6Addr) } } + + /// Gets the port number associated with this socket address + #[stable(feature = "rust1", since = "1.0.0")] + pub fn port(&self) -> u16 { ntoh(self.inner.sin6_port) } + + /// Gets scope ID associated with this address, corresponding to the + /// `sin6_flowinfo` field in C. + #[stable(feature = "rust1", since = "1.0.0")] + pub fn flowinfo(&self) -> u32 { ntoh(self.inner.sin6_flowinfo) } + + /// Gets scope ID associated with this address, corresponding to the + /// `sin6_scope_id` field in C. + #[stable(feature = "rust1", since = "1.0.0")] + pub fn scope_id(&self) -> u32 { ntoh(self.inner.sin6_scope_id) } } -impl FromInner for SocketAddr { - fn from_inner(addr: libc::sockaddr_in) -> SocketAddr { - SocketAddr { repr: Repr::V4(addr) } +impl FromInner for SocketAddrV4 { + fn from_inner(addr: libc::sockaddr_in) -> SocketAddrV4 { + SocketAddrV4 { inner: addr } } } -impl FromInner for SocketAddr { - fn from_inner(addr: libc::sockaddr_in6) -> SocketAddr { - SocketAddr { repr: Repr::V6(addr) } +impl FromInner for SocketAddrV6 { + fn from_inner(addr: libc::sockaddr_in6) -> SocketAddrV6 { + SocketAddrV6 { inner: addr } } } impl<'a> IntoInner<(*const libc::sockaddr, socklen_t)> for &'a SocketAddr { fn into_inner(self) -> (*const libc::sockaddr, socklen_t) { - match self.repr { - Repr::V4(ref a) => { + match *self { + SocketAddr::V4(ref a) => { (a as *const _ as *const _, mem::size_of_val(a) as socklen_t) } - Repr::V6(ref a) => { + SocketAddr::V6(ref a) => { (a as *const _ as *const _, mem::size_of_val(a) as socklen_t) } } } } -impl fmt::Debug for SocketAddr { +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Display for SocketAddr { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + SocketAddr::V4(ref a) => a.fmt(f), + SocketAddr::V6(ref a) => a.fmt(f), + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Display for SocketAddrV4 { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}:{}", self.ip(), self.port()) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Debug for SocketAddrV4 { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(self, fmt) } } -impl Clone for Repr { - fn clone(&self) -> Repr { *self } +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Display for SocketAddrV6 { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "[{}]:{}", self.ip(), self.port()) + } } -impl PartialEq for Repr { - fn eq(&self, other: &Repr) -> bool { - match (*self, *other) { - (Repr::V4(ref a), Repr::V4(ref b)) => { - a.sin_port == b.sin_port && - a.sin_addr.s_addr == b.sin_addr.s_addr - } - (Repr::V6(ref a), Repr::V6(ref b)) => { - a.sin6_port == b.sin6_port && - a.sin6_addr.s6_addr == b.sin6_addr.s6_addr && - a.sin6_flowinfo == b.sin6_flowinfo && - a.sin6_scope_id == b.sin6_scope_id - } - _ => false, - } +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Debug for SocketAddrV6 { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fmt::Display::fmt(self, fmt) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Clone for SocketAddrV4 { + fn clone(&self) -> SocketAddrV4 { *self } +} +#[stable(feature = "rust1", since = "1.0.0")] +impl Clone for SocketAddrV6 { + fn clone(&self) -> SocketAddrV6 { *self } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl PartialEq for SocketAddrV4 { + fn eq(&self, other: &SocketAddrV4) -> bool { + self.inner.sin_port == other.inner.sin_port && + self.inner.sin_addr.s_addr == other.inner.sin_addr.s_addr } } -impl Eq for Repr {} +#[stable(feature = "rust1", since = "1.0.0")] +impl PartialEq for SocketAddrV6 { + fn eq(&self, other: &SocketAddrV6) -> bool { + self.inner.sin6_port == other.inner.sin6_port && + self.inner.sin6_addr.s6_addr == other.inner.sin6_addr.s6_addr && + self.inner.sin6_flowinfo == other.inner.sin6_flowinfo && + self.inner.sin6_scope_id == other.inner.sin6_scope_id + } +} +#[stable(feature = "rust1", since = "1.0.0")] +impl Eq for SocketAddrV4 {} +#[stable(feature = "rust1", since = "1.0.0")] +impl Eq for SocketAddrV6 {} #[stable(feature = "rust1", since = "1.0.0")] -impl hash::Hash for Repr { +impl hash::Hash for SocketAddrV4 { fn hash(&self, s: &mut H) { - match *self { - Repr::V4(ref a) => { - (a.sin_family, a.sin_port, a.sin_addr.s_addr).hash(s) - } - Repr::V6(ref a) => { - (a.sin6_family, a.sin6_port, &a.sin6_addr.s6_addr, - a.sin6_flowinfo, a.sin6_scope_id).hash(s) - } - } + (self.inner.sin_port, self.inner.sin_addr.s_addr).hash(s) + } +} +#[stable(feature = "rust1", since = "1.0.0")] +impl hash::Hash for SocketAddrV6 { + fn hash(&self, s: &mut H) { + (self.inner.sin6_port, &self.inner.sin6_addr.s6_addr, + self.inner.sin6_flowinfo, self.inner.sin6_scope_id).hash(s) } } @@ -168,12 +238,13 @@ impl hash::Hash for Repr { /// This trait is used for generic address resolution when constructing network /// objects. By default it is implemented for the following types: /// -/// * `SocketAddr` - `to_socket_addrs` is identity function. +/// * `SocketAddr`, `SocketAddrV4`, `SocketAddrV6` - `to_socket_addrs` is +/// identity function. /// -/// * `(IpAddr, u16)` - `to_socket_addrs` constructs `SocketAddr` trivially. +/// * `(IpvNAddr, u16)` - `to_socket_addrs` constructs `SocketAddr` trivially. /// /// * `(&str, u16)` - the string should be either a string representation of an -/// IP address expected by `FromStr` implementation for `IpAddr` or a host +/// IP address expected by `FromStr` implementation for `IpvNAddr` or a host /// name. /// /// * `&str` - the string should be either a string representation of a @@ -192,18 +263,18 @@ impl hash::Hash for Repr { /// Some examples: /// /// ```no_run -/// use std::net::{IpAddr, SocketAddr, TcpStream, UdpSocket, TcpListener}; +/// use std::net::{SocketAddrV4, TcpStream, UdpSocket, TcpListener, Ipv4Addr}; /// /// fn main() { -/// let ip = IpAddr::new_v4(127, 0, 0, 1); +/// let ip = Ipv4Addr::new(127, 0, 0, 1); /// let port = 12345; /// /// // The following lines are equivalent modulo possible "localhost" name /// // resolution differences -/// let tcp_s = TcpStream::connect(&SocketAddr::new(ip, port)); -/// let tcp_s = TcpStream::connect(&(ip, port)); -/// let tcp_s = TcpStream::connect(&("127.0.0.1", port)); -/// let tcp_s = TcpStream::connect(&("localhost", port)); +/// let tcp_s = TcpStream::connect(SocketAddrV4::new(ip, port)); +/// let tcp_s = TcpStream::connect((ip, port)); +/// let tcp_s = TcpStream::connect(("127.0.0.1", port)); +/// let tcp_s = TcpStream::connect(("localhost", port)); /// let tcp_s = TcpStream::connect("127.0.0.1:12345"); /// let tcp_s = TcpStream::connect("localhost:12345"); /// @@ -211,13 +282,15 @@ impl hash::Hash for Repr { /// // behave similarly /// let tcp_l = TcpListener::bind("localhost:12345"); /// -/// let mut udp_s = UdpSocket::bind(&("127.0.0.1", port)).unwrap(); -/// udp_s.send_to(&[7], &(ip, 23451)); +/// let mut udp_s = UdpSocket::bind(("127.0.0.1", port)).unwrap(); +/// udp_s.send_to(&[7], (ip, 23451)); /// } /// ``` +#[stable(feature = "rust1", since = "1.0.0")] pub trait ToSocketAddrs { /// Returned iterator over socket addresses which this type may correspond /// to. + #[stable(feature = "rust1", since = "1.0.0")] type Iter: Iterator; /// Converts this object to an iterator of resolved `SocketAddr`s. @@ -231,9 +304,11 @@ pub trait ToSocketAddrs { /// # Errors /// /// Any errors encountered during resolution will be returned as an `Err`. + #[stable(feature = "rust1", since = "1.0.0")] fn to_socket_addrs(&self) -> io::Result; } +#[stable(feature = "rust1", since = "1.0.0")] impl ToSocketAddrs for SocketAddr { type Iter = option::IntoIter; fn to_socket_addrs(&self) -> io::Result> { @@ -241,31 +316,72 @@ impl ToSocketAddrs for SocketAddr { } } -impl ToSocketAddrs for (IpAddr, u16) { +#[stable(feature = "rust1", since = "1.0.0")] +impl ToSocketAddrs for SocketAddrV4 { + type Iter = option::IntoIter; + fn to_socket_addrs(&self) -> io::Result> { + SocketAddr::V4(*self).to_socket_addrs() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl ToSocketAddrs for SocketAddrV6 { + type Iter = option::IntoIter; + fn to_socket_addrs(&self) -> io::Result> { + SocketAddr::V6(*self).to_socket_addrs() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl ToSocketAddrs for (Ipv4Addr, u16) { + type Iter = option::IntoIter; + fn to_socket_addrs(&self) -> io::Result> { + let (ip, port) = *self; + SocketAddrV4::new(ip, port).to_socket_addrs() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl ToSocketAddrs for (Ipv6Addr, u16) { type Iter = option::IntoIter; fn to_socket_addrs(&self) -> io::Result> { let (ip, port) = *self; - Ok(Some(SocketAddr::new(ip, port)).into_iter()) + SocketAddrV6::new(ip, port, 0, 0).to_socket_addrs() } } fn resolve_socket_addr(s: &str, p: u16) -> io::Result> { let ips = try!(lookup_host(s)); let v: Vec<_> = try!(ips.map(|a| { - a.map(|mut a| { a.set_port(p); a }) + a.map(|a| { + match a { + SocketAddr::V4(ref a) => { + SocketAddr::V4(SocketAddrV4::new(*a.ip(), p)) + } + SocketAddr::V6(ref a) => { + SocketAddr::V6(SocketAddrV6::new(*a.ip(), p, a.flowinfo(), + a.scope_id())) + } + } + }) }).collect()); Ok(v.into_iter()) } +#[stable(feature = "rust1", since = "1.0.0")] impl<'a> ToSocketAddrs for (&'a str, u16) { type Iter = vec::IntoIter; fn to_socket_addrs(&self) -> io::Result> { let (host, port) = *self; - // try to parse the host as a regular IpAddr first - match host.parse().ok() { - Some(addr) => return Ok(vec![SocketAddr::new(addr, port)].into_iter()), - None => {} + // try to parse the host as a regular IP address first + if let Ok(addr) = host.parse::() { + let addr = SocketAddrV4::new(addr, port); + return Ok(vec![SocketAddr::V4(addr)].into_iter()) + } + if let Ok(addr) = host.parse::() { + let addr = SocketAddrV6::new(addr, port, 0, 0); + return Ok(vec![SocketAddr::V6(addr)].into_iter()) } resolve_socket_addr(host, port) @@ -273,6 +389,7 @@ impl<'a> ToSocketAddrs for (&'a str, u16) { } // accepts strings like 'localhost:12345' +#[stable(feature = "rust1", since = "1.0.0")] impl ToSocketAddrs for str { type Iter = vec::IntoIter; fn to_socket_addrs(&self) -> io::Result> { @@ -322,16 +439,16 @@ mod tests { assert_eq!(Ok(Ipv4Addr::new(0, 0, 0, 0)), "0.0.0.0".parse()); // out of range - let none: Option = "256.0.0.1".parse().ok(); + let none: Option = "256.0.0.1".parse().ok(); assert_eq!(None, none); // too short - let none: Option = "255.0.0".parse().ok(); + let none: Option = "255.0.0".parse().ok(); assert_eq!(None, none); // too long - let none: Option = "255.0.0.1.2".parse().ok(); + let none: Option = "255.0.0.1.2".parse().ok(); assert_eq!(None, none); // no number between dots - let none: Option = "255.0..1".parse().ok(); + let none: Option = "255.0..1".parse().ok(); assert_eq!(None, none); } @@ -347,19 +464,19 @@ mod tests { "2a02:6b8::11:11".parse()); // too long group - let none: Option = "::00000".parse().ok(); + let none: Option = "::00000".parse().ok(); assert_eq!(None, none); // too short - let none: Option = "1:2:3:4:5:6:7".parse().ok(); + let none: Option = "1:2:3:4:5:6:7".parse().ok(); assert_eq!(None, none); // too long - let none: Option = "1:2:3:4:5:6:7:8:9".parse().ok(); + let none: Option = "1:2:3:4:5:6:7:8:9".parse().ok(); assert_eq!(None, none); // triple colon - let none: Option = "1:2:::6:7:8".parse().ok(); + let none: Option = "1:2:::6:7:8".parse().ok(); assert_eq!(None, none); // two double colons - let none: Option = "1:2::6::8".parse().ok(); + let none: Option = "1:2::6::8".parse().ok(); assert_eq!(None, none); } @@ -375,24 +492,24 @@ mod tests { "2001:db8:122:c000:2:2100:192.0.2.33".parse()); // colon after v4 - let none: Option = "::127.0.0.1:".parse().ok(); + let none: Option = "::127.0.0.1:".parse().ok(); assert_eq!(None, none); // not enough groups - let none: Option = "1.2.3.4.5:127.0.0.1".parse().ok(); + let none: Option = "1.2.3.4.5:127.0.0.1".parse().ok(); assert_eq!(None, none); // too many groups - let none: Option = "1.2.3.4.5:6:7:127.0.0.1".parse().ok(); + let none: Option = "1.2.3.4.5:6:7:127.0.0.1".parse().ok(); assert_eq!(None, none); } #[test] fn test_from_str_socket_addr() { - assert_eq!(Ok(SocketAddr::new(IpAddr::new_v4(77, 88, 21, 11), 80)), - "77.88.21.11:80".parse()); - assert_eq!(Ok(SocketAddr::new(IpAddr::new_v6(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1), 53)), - "[2a02:6b8:0:1::1]:53".parse()); - assert_eq!(Ok(SocketAddr::new(IpAddr::new_v6(0, 0, 0, 0, 0, 0, 0x7F00, 1), 22)), - "[::127.0.0.1]:22".parse()); + assert_eq!(Ok(sa4(Ipv4Addr::new(77, 88, 21, 11), 80)), + "77.88.21.11:80".parse()); + assert_eq!(Ok(sa6(Ipv6Addr::new(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1), 53)), + "[2a02:6b8:0:1::1]:53".parse()); + assert_eq!(Ok(sa6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0x7F00, 1), 22)), + "[::127.0.0.1]:22".parse()); // without port let none: Option = "127.0.0.1".parse().ok(); @@ -555,39 +672,47 @@ mod tests { #[test] fn to_socket_addr_socketaddr() { - let a = SocketAddr::new(IpAddr::new_v4(77, 88, 21, 11), 12345); + let a = sa4(Ipv4Addr::new(77, 88, 21, 11), 12345); assert_eq!(Ok(vec![a]), tsa(a)); } + fn sa4(a: Ipv4Addr, p: u16) -> SocketAddr { + SocketAddr::V4(SocketAddrV4::new(a, p)) + } + + fn sa6(a: Ipv6Addr, p: u16) -> SocketAddr { + SocketAddr::V6(SocketAddrV6::new(a, p, 0, 0)) + } + #[test] fn to_socket_addr_ipaddr_u16() { - let a = IpAddr::new_v4(77, 88, 21, 11); + let a = Ipv4Addr::new(77, 88, 21, 11); let p = 12345; - let e = SocketAddr::new(a, p); + let e = SocketAddr::V4(SocketAddrV4::new(a, p)); assert_eq!(Ok(vec![e]), tsa((a, p))); } #[test] fn to_socket_addr_str_u16() { - let a = SocketAddr::new(IpAddr::new_v4(77, 88, 21, 11), 24352); + let a = sa4(Ipv4Addr::new(77, 88, 21, 11), 24352); assert_eq!(Ok(vec![a]), tsa(("77.88.21.11", 24352))); - let a = SocketAddr::new(IpAddr::new_v6(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1), 53); + let a = sa6(Ipv6Addr::new(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1), 53); assert_eq!(Ok(vec![a]), tsa(("2a02:6b8:0:1::1", 53))); - let a = SocketAddr::new(IpAddr::new_v4(127, 0, 0, 1), 23924); + let a = sa4(Ipv4Addr::new(127, 0, 0, 1), 23924); assert!(tsa(("localhost", 23924)).unwrap().contains(&a)); } #[test] fn to_socket_addr_str() { - let a = SocketAddr::new(IpAddr::new_v4(77, 88, 21, 11), 24352); + let a = sa4(Ipv4Addr::new(77, 88, 21, 11), 24352); assert_eq!(Ok(vec![a]), tsa("77.88.21.11:24352")); - let a = SocketAddr::new(IpAddr::new_v6(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1), 53); + let a = sa6(Ipv6Addr::new(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1), 53); assert_eq!(Ok(vec![a]), tsa("[2a02:6b8:0:1::1]:53")); - let a = SocketAddr::new(IpAddr::new_v4(127, 0, 0, 1), 23924); + let a = sa4(Ipv4Addr::new(127, 0, 0, 1), 23924); assert!(tsa("localhost:23924").unwrap().contains(&a)); } diff --git a/src/libstd/net/ip.rs b/src/libstd/net/ip.rs index d699886e57747..0c33343b0c617 100644 --- a/src/libstd/net/ip.rs +++ b/src/libstd/net/ip.rs @@ -8,6 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![unstable(feature = "ip", reason = "extra functionality has not been \ + scrutinized to the level that it should \ + be stable")] + use prelude::v1::*; use cmp::Ordering; @@ -19,12 +23,14 @@ use net::{hton, ntoh}; /// Representation of an IPv4 address. #[derive(Copy)] +#[stable(feature = "rust1", since = "1.0.0")] pub struct Ipv4Addr { inner: libc::in_addr, } /// Representation of an IPv6 address. #[derive(Copy)] +#[stable(feature = "rust1", since = "1.0.0")] pub struct Ipv6Addr { inner: libc::in6_addr, } @@ -41,46 +47,11 @@ pub enum Ipv6MulticastScope { Global } -/// Enumeration of possible IP addresses -#[derive(Copy, PartialEq, Eq, Clone, Hash, Debug)] -pub enum IpAddr { - /// An IPv4 address. - V4(Ipv4Addr), - /// An IPv6 address. - V6(Ipv6Addr) -} - -impl IpAddr { - /// Create a new IpAddr that contains an IPv4 address. - /// - /// The result will represent the IP address a.b.c.d - pub fn new_v4(a: u8, b: u8, c: u8, d: u8) -> IpAddr { - IpAddr::V4(Ipv4Addr::new(a, b, c, d)) - } - - /// Create a new IpAddr that contains an IPv6 address. - /// - /// The result will represent the IP address a:b:c:d:e:f - pub fn new_v6(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16, - h: u16) -> IpAddr { - IpAddr::V6(Ipv6Addr::new(a, b, c, d, e, f, g, h)) - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl fmt::Display for IpAddr { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - IpAddr::V4(v4) => v4.fmt(f), - IpAddr::V6(v6) => v6.fmt(f) - } - } -} - impl Ipv4Addr { /// Create a new IPv4 address from four eight-bit octets. /// /// The result will represent the IP address a.b.c.d + #[stable(feature = "rust1", since = "1.0.0")] pub fn new(a: u8, b: u8, c: u8, d: u8) -> Ipv4Addr { Ipv4Addr { inner: libc::in_addr { @@ -93,6 +64,7 @@ impl Ipv4Addr { } /// Returns the four eight-bit integers that make up this address + #[stable(feature = "rust1", since = "1.0.0")] pub fn octets(&self) -> [u8; 4] { let bits = ntoh(self.inner.s_addr); [(bits >> 24) as u8, (bits >> 16) as u8, (bits >> 8) as u8, bits as u8] @@ -148,6 +120,7 @@ impl Ipv4Addr { /// Convert this address to an IPv4-compatible IPv6 address /// /// a.b.c.d becomes ::a.b.c.d + #[stable(feature = "rust1", since = "1.0.0")] pub fn to_ipv6_compatible(&self) -> Ipv6Addr { Ipv6Addr::new(0, 0, 0, 0, 0, 0, ((self.octets()[0] as u16) << 8) | self.octets()[1] as u16, @@ -157,6 +130,7 @@ impl Ipv4Addr { /// Convert this address to an IPv4-mapped IPv6 address /// /// a.b.c.d becomes ::ffff:a.b.c.d + #[stable(feature = "rust1", since = "1.0.0")] pub fn to_ipv6_mapped(&self) -> Ipv6Addr { Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, ((self.octets()[0] as u16) << 8) | self.octets()[1] as u16, @@ -165,6 +139,7 @@ impl Ipv4Addr { } +#[stable(feature = "rust1", since = "1.0.0")] impl fmt::Display for Ipv4Addr { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { let octets = self.octets(); @@ -172,21 +147,26 @@ impl fmt::Display for Ipv4Addr { } } +#[stable(feature = "rust1", since = "1.0.0")] impl fmt::Debug for Ipv4Addr { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(self, fmt) } } +#[stable(feature = "rust1", since = "1.0.0")] impl Clone for Ipv4Addr { fn clone(&self) -> Ipv4Addr { *self } } +#[stable(feature = "rust1", since = "1.0.0")] impl PartialEq for Ipv4Addr { fn eq(&self, other: &Ipv4Addr) -> bool { self.inner.s_addr == other.inner.s_addr } } + +#[stable(feature = "rust1", since = "1.0.0")] impl Eq for Ipv4Addr {} #[stable(feature = "rust1", since = "1.0.0")] @@ -196,12 +176,14 @@ impl hash::Hash for Ipv4Addr { } } +#[stable(feature = "rust1", since = "1.0.0")] impl PartialOrd for Ipv4Addr { fn partial_cmp(&self, other: &Ipv4Addr) -> Option { Some(self.cmp(other)) } } +#[stable(feature = "rust1", since = "1.0.0")] impl Ord for Ipv4Addr { fn cmp(&self, other: &Ipv4Addr) -> Ordering { self.inner.s_addr.cmp(&other.inner.s_addr) @@ -221,6 +203,7 @@ impl Ipv6Addr { /// Create a new IPv6 address from eight 16-bit segments. /// /// The result will represent the IP address a:b:c:d:e:f + #[stable(feature = "rust1", since = "1.0.0")] pub fn new(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16, h: u16) -> Ipv6Addr { Ipv6Addr { @@ -232,6 +215,7 @@ impl Ipv6Addr { } /// Return the eight 16-bit segments that make up this address + #[stable(feature = "rust1", since = "1.0.0")] pub fn segments(&self) -> [u16; 8] { [ntoh(self.inner.s6_addr[0]), ntoh(self.inner.s6_addr[1]), @@ -324,6 +308,7 @@ impl Ipv6Addr { /// neither IPv4-compatible or IPv4-mapped. /// /// ::a.b.c.d and ::ffff:a.b.c.d become a.b.c.d + #[stable(feature = "rust1", since = "1.0.0")] pub fn to_ipv4(&self) -> Option { match self.segments() { [0, 0, 0, 0, 0, f, g, h] if f == 0 || f == 0xffff => { @@ -335,6 +320,7 @@ impl Ipv6Addr { } } +#[stable(feature = "rust1", since = "1.0.0")] impl fmt::Display for Ipv6Addr { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { match self.segments() { @@ -405,21 +391,26 @@ impl fmt::Display for Ipv6Addr { } } +#[stable(feature = "rust1", since = "1.0.0")] impl fmt::Debug for Ipv6Addr { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(self, fmt) } } +#[stable(feature = "rust1", since = "1.0.0")] impl Clone for Ipv6Addr { fn clone(&self) -> Ipv6Addr { *self } } +#[stable(feature = "rust1", since = "1.0.0")] impl PartialEq for Ipv6Addr { fn eq(&self, other: &Ipv6Addr) -> bool { self.inner.s6_addr == other.inner.s6_addr } } + +#[stable(feature = "rust1", since = "1.0.0")] impl Eq for Ipv6Addr {} #[stable(feature = "rust1", since = "1.0.0")] @@ -429,12 +420,14 @@ impl hash::Hash for Ipv6Addr { } } +#[stable(feature = "rust1", since = "1.0.0")] impl PartialOrd for Ipv6Addr { fn partial_cmp(&self, other: &Ipv6Addr) -> Option { Some(self.cmp(other)) } } +#[stable(feature = "rust1", since = "1.0.0")] impl Ord for Ipv6Addr { fn cmp(&self, other: &Ipv6Addr) -> Ordering { self.inner.s6_addr.cmp(&other.inner.s6_addr) diff --git a/src/libstd/net/mod.rs b/src/libstd/net/mod.rs index b8cb8cb528929..5f7c7babbcf74 100644 --- a/src/libstd/net/mod.rs +++ b/src/libstd/net/mod.rs @@ -14,7 +14,7 @@ //! > development. At this time it is still recommended to use the `old_io` //! > module while the details of this module shake out. -#![unstable(feature = "net")] +#![stable(feature = "rust1", since = "1.0.0")] use prelude::v1::*; @@ -22,8 +22,8 @@ use io::{self, Error, ErrorKind}; use num::Int; use sys_common::net2 as net_imp; -pub use self::ip::{IpAddr, Ipv4Addr, Ipv6Addr, Ipv6MulticastScope}; -pub use self::addr::{SocketAddr, ToSocketAddrs}; +pub use self::ip::{Ipv4Addr, Ipv6Addr, Ipv6MulticastScope}; +pub use self::addr::{SocketAddr, SocketAddrV4, SocketAddrV6, ToSocketAddrs}; pub use self::tcp::{TcpStream, TcpListener}; pub use self::udp::UdpSocket; @@ -37,23 +37,27 @@ mod parser; /// Possible values which can be passed to the `shutdown` method of `TcpStream` /// and `UdpSocket`. #[derive(Copy, Clone, PartialEq)] +#[stable(feature = "rust1", since = "1.0.0")] pub enum Shutdown { /// Indicates that the reading portion of this stream/socket should be shut /// down. All currently blocked and future reads will return `Ok(0)`. + #[stable(feature = "rust1", since = "1.0.0")] Read, /// Indicates that the writing portion of this stream/socket should be shut /// down. All currently blocked and future writes will return an error. + #[stable(feature = "rust1", since = "1.0.0")] Write, /// Shut down both the reading and writing portions of this stream. /// /// See `Shutdown::Read` and `Shutdown::Write` for more information. - Both + #[stable(feature = "rust1", since = "1.0.0")] + Both, } fn hton(i: I) -> I { i.to_be() } fn ntoh(i: I) -> I { Int::from_be(i) } -fn each_addr(addr: &A, mut f: F) -> io::Result +fn each_addr(addr: A, mut f: F) -> io::Result where F: FnMut(&SocketAddr) -> io::Result { let mut last_err = None; @@ -70,8 +74,10 @@ fn each_addr(addr: &A, mut f: F) -> io::Result< } /// An iterator over `SocketAddr` values returned from a host lookup operation. +#[stable(feature = "rust1", since = "1.0.0")] pub struct LookupHost(net_imp::LookupHost); +#[stable(feature = "rust1", since = "1.0.0")] impl Iterator for LookupHost { type Item = io::Result; fn next(&mut self) -> Option> { self.0.next() } @@ -94,6 +100,7 @@ impl Iterator for LookupHost { /// # Ok(()) /// # } /// ``` +#[stable(feature = "rust1", since = "1.0.0")] pub fn lookup_host(host: &str) -> io::Result { net_imp::lookup_host(host).map(LookupHost) } diff --git a/src/libstd/net/parser.rs b/src/libstd/net/parser.rs index aa54a432d625b..9843a1527180e 100644 --- a/src/libstd/net/parser.rs +++ b/src/libstd/net/parser.rs @@ -16,7 +16,7 @@ use prelude::v1::*; use str::FromStr; -use net::{Ipv4Addr, Ipv6Addr, IpAddr, SocketAddr}; +use net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6}; struct Parser<'a> { // parsing as ASCII, so can use byte array @@ -24,6 +24,11 @@ struct Parser<'a> { pos: usize, } +enum IpAddr { + V4(Ipv4Addr), + V6(Ipv6Addr), +} + impl<'a> Parser<'a> { fn new(s: &'a str) -> Parser<'a> { Parser { @@ -281,18 +286,13 @@ impl<'a> Parser<'a> { let port = |p: &mut Parser| p.read_number(10, 5, 0x10000).map(|n| n as u16); // host, colon, port - self.read_seq_3::(ip_addr, colon, port) - .map(|t| match t { (ip, _, port) => SocketAddr::new(ip, port) }) - } -} - -impl FromStr for IpAddr { - type Err = ParseError; - fn from_str(s: &str) -> Result { - match Parser::new(s).read_till_eof(|p| p.read_ip_addr()) { - Some(s) => Ok(s), - None => Err(ParseError), - } + self.read_seq_3(ip_addr, colon, port).map(|t| { + let (ip, _, port): (IpAddr, char, u16) = t; + match ip { + IpAddr::V4(ip) => SocketAddr::V4(SocketAddrV4::new(ip, port)), + IpAddr::V6(ip) => SocketAddr::V6(SocketAddrV6::new(ip, port, 0, 0)), + } + }) } } diff --git a/src/libstd/net/tcp.rs b/src/libstd/net/tcp.rs index 76c0483547330..501ba2dc2c178 100644 --- a/src/libstd/net/tcp.rs +++ b/src/libstd/net/tcp.rs @@ -8,6 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![unstable(feature = "tcp", reason = "remaining functions have not been \ + scrutinized enough to be stabilized")] + use prelude::v1::*; use io::prelude::*; @@ -35,6 +38,7 @@ use sys_common::AsInner; /// let _ = stream.read(&mut [0; 128]); // ignore here too /// } // the stream is closed here /// ``` +#[stable(feature = "rust1", since = "1.0.0")] pub struct TcpStream(net_imp::TcpStream); /// A structure representing a socket server. @@ -67,12 +71,14 @@ pub struct TcpStream(net_imp::TcpStream); /// // close the socket server /// drop(listener); /// ``` +#[stable(feature = "rust1", since = "1.0.0")] pub struct TcpListener(net_imp::TcpListener); /// An infinite iterator over the connections from a `TcpListener`. /// /// This iterator will infinitely yield `Some` of the accepted connections. It /// is equivalent to calling `accept` in a loop. +#[stable(feature = "rust1", since = "1.0.0")] pub struct Incoming<'a> { listener: &'a TcpListener } impl TcpStream { @@ -81,25 +87,36 @@ impl TcpStream { /// `addr` is an address of the remote host. Anything which implements /// `ToSocketAddrs` trait can be supplied for the address; see this trait /// documentation for concrete examples. - pub fn connect(addr: &A) -> io::Result { + #[stable(feature = "rust1", since = "1.0.0")] + pub fn connect(addr: A) -> io::Result { super::each_addr(addr, net_imp::TcpStream::connect).map(TcpStream) } /// Returns the socket address of the remote peer of this TCP connection. + #[stable(feature = "rust1", since = "1.0.0")] pub fn peer_addr(&self) -> io::Result { self.0.peer_addr() } /// Returns the socket address of the local half of this TCP connection. + #[unstable(feature = "net")] + #[deprecated(since = "1.0.0", reason = "renamed to local_addr")] pub fn socket_addr(&self) -> io::Result { self.0.socket_addr() } + /// Returns the socket address of the local half of this TCP connection. + #[stable(feature = "rust1", since = "1.0.0")] + pub fn local_addr(&self) -> io::Result { + self.0.socket_addr() + } + /// Shut down the read, write, or both halves of this connection. /// /// This function will cause all pending and future I/O on the specified /// portions to return immediately with an appropriate value (see the /// documentation of `Shutdown`). + #[stable(feature = "rust1", since = "1.0.0")] pub fn shutdown(&self, how: Shutdown) -> io::Result<()> { self.0.shutdown(how) } @@ -110,6 +127,7 @@ impl TcpStream { /// object references. Both handles will read and write the same stream of /// data, and options set on one stream will be propagated to the other /// stream. + #[stable(feature = "rust1", since = "1.0.0")] pub fn try_clone(&self) -> io::Result { self.0.duplicate().map(TcpStream) } @@ -129,16 +147,20 @@ impl TcpStream { } } +#[stable(feature = "rust1", since = "1.0.0")] impl Read for TcpStream { fn read(&mut self, buf: &mut [u8]) -> io::Result { self.0.read(buf) } } +#[stable(feature = "rust1", since = "1.0.0")] impl Write for TcpStream { fn write(&mut self, buf: &[u8]) -> io::Result { self.0.write(buf) } fn flush(&mut self) -> io::Result<()> { Ok(()) } } +#[stable(feature = "rust1", since = "1.0.0")] impl<'a> Read for &'a TcpStream { fn read(&mut self, buf: &mut [u8]) -> io::Result { self.0.read(buf) } } +#[stable(feature = "rust1", since = "1.0.0")] impl<'a> Write for &'a TcpStream { fn write(&mut self, buf: &[u8]) -> io::Result { self.0.write(buf) } fn flush(&mut self) -> io::Result<()> { Ok(()) } @@ -160,11 +182,20 @@ impl TcpListener { /// /// The address type can be any implementer of `ToSocketAddrs` trait. See /// its documentation for concrete examples. - pub fn bind(addr: &A) -> io::Result { + #[stable(feature = "rust1", since = "1.0.0")] + pub fn bind(addr: A) -> io::Result { super::each_addr(addr, net_imp::TcpListener::bind).map(TcpListener) } /// Returns the local socket address of this listener. + #[stable(feature = "rust1", since = "1.0.0")] + pub fn local_addr(&self) -> io::Result { + self.0.socket_addr() + } + + /// Deprecated, renamed to local_addr + #[unstable(feature = "net")] + #[deprecated(since = "1.0.0", reason = "renamed to local_addr")] pub fn socket_addr(&self) -> io::Result { self.0.socket_addr() } @@ -174,6 +205,7 @@ impl TcpListener { /// The returned `TcpListener` is a reference to the same socket that this /// object references. Both handles can be used to accept incoming /// connections and options set on one listener will affect the other. + #[stable(feature = "rust1", since = "1.0.0")] pub fn try_clone(&self) -> io::Result { self.0.duplicate().map(TcpListener) } @@ -183,6 +215,7 @@ impl TcpListener { /// This function will block the calling thread until a new TCP connection /// is established. When established, the corresponding `TcpStream` and the /// remote peer's address will be returned. + #[stable(feature = "rust1", since = "1.0.0")] pub fn accept(&self) -> io::Result<(TcpStream, SocketAddr)> { self.0.accept().map(|(a, b)| (TcpStream(a), b)) } @@ -192,11 +225,13 @@ impl TcpListener { /// /// The returned iterator will never returned `None` and will also not yield /// the peer's `SocketAddr` structure. + #[stable(feature = "rust1", since = "1.0.0")] pub fn incoming(&self) -> Incoming { Incoming { listener: self } } } +#[stable(feature = "rust1", since = "1.0.0")] impl<'a> Iterator for Incoming<'a> { type Item = io::Result; fn next(&mut self) -> Option> { diff --git a/src/libstd/net/test.rs b/src/libstd/net/test.rs index dbebede9f50e4..3d42472f0fc42 100644 --- a/src/libstd/net/test.rs +++ b/src/libstd/net/test.rs @@ -11,19 +11,20 @@ use prelude::v1::*; use env; -use net::{SocketAddr, IpAddr}; +use net::{SocketAddr, SocketAddrV4, SocketAddrV6, Ipv4Addr, Ipv6Addr}; use sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering}; static PORT: AtomicUsize = ATOMIC_USIZE_INIT; pub fn next_test_ip4() -> SocketAddr { - SocketAddr::new(IpAddr::new_v4(127, 0, 0, 1), - PORT.fetch_add(1, Ordering::SeqCst) as u16 + base_port()) + let port = PORT.fetch_add(1, Ordering::SeqCst) as u16 + base_port(); + SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), port)) } pub fn next_test_ip6() -> SocketAddr { - SocketAddr::new(IpAddr::new_v6(0, 0, 0, 0, 0, 0, 0, 1), - PORT.fetch_add(1, Ordering::SeqCst) as u16 + base_port()) + let port = PORT.fetch_add(1, Ordering::SeqCst) as u16 + base_port(); + SocketAddr::V6(SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), + port, 0, 0)) } // The bots run multiple builds at the same time, and these builds diff --git a/src/libstd/net/udp.rs b/src/libstd/net/udp.rs index 041e6551ff5ec..1ace195752658 100644 --- a/src/libstd/net/udp.rs +++ b/src/libstd/net/udp.rs @@ -8,10 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![unstable(feature = "udp", reason = "remaining functions have not been \ + scrutinized enough to be stabilized")] + use prelude::v1::*; use io::{self, Error, ErrorKind}; -use net::{ToSocketAddrs, SocketAddr, IpAddr}; +use net::{ToSocketAddrs, SocketAddr}; use sys_common::net2 as net_imp; use sys_common::AsInner; @@ -41,6 +44,7 @@ use sys_common::AsInner; /// # Ok(()) /// # } /// ``` +#[stable(feature = "rust1", since = "1.0.0")] pub struct UdpSocket(net_imp::UdpSocket); impl UdpSocket { @@ -48,12 +52,14 @@ impl UdpSocket { /// /// Address type can be any implementor of `ToSocketAddr` trait. See its /// documentation for concrete examples. - pub fn bind(addr: &A) -> io::Result { + #[stable(feature = "rust1", since = "1.0.0")] + pub fn bind(addr: A) -> io::Result { super::each_addr(addr, net_imp::UdpSocket::bind).map(UdpSocket) } /// Receives data from the socket. On success, returns the number of bytes /// read and the address from whence the data came. + #[stable(feature = "rust1", since = "1.0.0")] pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> { self.0.recv_from(buf) } @@ -63,8 +69,9 @@ impl UdpSocket { /// /// Address type can be any implementor of `ToSocketAddrs` trait. See its /// documentation for concrete examples. - pub fn send_to(&self, buf: &[u8], addr: &A) - -> io::Result { + #[stable(feature = "rust1", since = "1.0.0")] + pub fn send_to(&self, buf: &[u8], addr: A) + -> io::Result { match try!(addr.to_socket_addrs()).next() { Some(addr) => self.0.send_to(buf, &addr), None => Err(Error::new(ErrorKind::InvalidInput, @@ -73,15 +80,24 @@ impl UdpSocket { } /// Returns the socket address that this socket was created from. + #[unstable(feature = "net")] + #[deprecated(since = "1.0.0", reason = "renamed to local_addr")] pub fn socket_addr(&self) -> io::Result { self.0.socket_addr() } + /// Returns the socket address that this socket was created from. + #[stable(feature = "rust1", since = "1.0.0")] + pub fn local_addr(&self) -> io::Result { + self.0.socket_addr() + } + /// Create a new independently owned handle to the underlying socket. /// /// The returned `UdpSocket` is a reference to the same socket that this /// object references. Both handles will read and write the same port, and /// options set on one socket will be propagated to the other. + #[stable(feature = "rust1", since = "1.0.0")] pub fn try_clone(&self) -> io::Result { self.0.duplicate().map(UdpSocket) } @@ -99,12 +115,12 @@ impl UdpSocket { } /// Joins a multicast IP address (becomes a member of it) - pub fn join_multicast(&self, multi: &IpAddr) -> io::Result<()> { + pub fn join_multicast(&self, multi: &SocketAddr) -> io::Result<()> { self.0.join_multicast(multi) } /// Leaves a multicast IP address (drops membership from it) - pub fn leave_multicast(&self, multi: &IpAddr) -> io::Result<()> { + pub fn leave_multicast(&self, multi: &SocketAddr) -> io::Result<()> { self.0.leave_multicast(multi) } @@ -151,7 +167,7 @@ mod tests { #[cfg_attr(any(windows, target_os = "android"), ignore)] #[test] fn bind_error() { - let addr = SocketAddr::new(IpAddr::new_v4(0, 0, 0, 0), 1); + let addr = SocketAddrV4::new(Ipv4Addr::new(0, 0, 0, 0), 1); match UdpSocket::bind(&addr) { Ok(..) => panic!(), Err(e) => assert_eq!(e.kind(), ErrorKind::PermissionDenied), diff --git a/src/libstd/sys/common/net2.rs b/src/libstd/sys/common/net2.rs index af5b49a42392b..25aeab1b4ff74 100644 --- a/src/libstd/sys/common/net2.rs +++ b/src/libstd/sys/common/net2.rs @@ -14,7 +14,7 @@ use ffi::CString; use io::{self, Error, ErrorKind}; use libc::{self, c_int, c_char, c_void, socklen_t}; use mem; -use net::{IpAddr, SocketAddr, Shutdown}; +use net::{SocketAddr, Shutdown}; use sys::c; use sys::net::{cvt, cvt_r, cvt_gai, Socket, init, wrlen_t}; use sys_common::{AsInner, FromInner, IntoInner}; @@ -63,15 +63,15 @@ fn sockaddr_to_addr(storage: &libc::sockaddr_storage, match storage.ss_family as libc::c_int { libc::AF_INET => { assert!(len as usize >= mem::size_of::()); - Ok(FromInner::from_inner(unsafe { + Ok(SocketAddr::V4(FromInner::from_inner(unsafe { *(storage as *const _ as *const libc::sockaddr_in) - })) + }))) } libc::AF_INET6 => { assert!(len as usize >= mem::size_of::()); - Ok(FromInner::from_inner(unsafe { + Ok(SocketAddr::V6(FromInner::from_inner(unsafe { *(storage as *const _ as *const libc::sockaddr_in6) - })) + }))) } _ => { Err(Error::new(ErrorKind::InvalidInput, "invalid argument", None)) @@ -334,39 +334,39 @@ impl UdpSocket { libc::IP_MULTICAST_LOOP, on as c_int) } - pub fn join_multicast(&self, multi: &IpAddr) -> io::Result<()> { + pub fn join_multicast(&self, multi: &SocketAddr) -> io::Result<()> { match *multi { - IpAddr::V4(..) => { + SocketAddr::V4(..) => { self.set_membership(multi, libc::IP_ADD_MEMBERSHIP) } - IpAddr::V6(..) => { + SocketAddr::V6(..) => { self.set_membership(multi, libc::IPV6_ADD_MEMBERSHIP) } } } - pub fn leave_multicast(&self, multi: &IpAddr) -> io::Result<()> { + pub fn leave_multicast(&self, multi: &SocketAddr) -> io::Result<()> { match *multi { - IpAddr::V4(..) => { + SocketAddr::V4(..) => { self.set_membership(multi, libc::IP_DROP_MEMBERSHIP) } - IpAddr::V6(..) => { + SocketAddr::V6(..) => { self.set_membership(multi, libc::IPV6_DROP_MEMBERSHIP) } } } - fn set_membership(&self, addr: &IpAddr, opt: c_int) -> io::Result<()> { + fn set_membership(&self, addr: &SocketAddr, opt: c_int) -> io::Result<()> { match *addr { - IpAddr::V4(ref addr) => { + SocketAddr::V4(ref addr) => { let mreq = libc::ip_mreq { - imr_multiaddr: *addr.as_inner(), + imr_multiaddr: *addr.ip().as_inner(), // interface == INADDR_ANY imr_interface: libc::in_addr { s_addr: 0x0 }, }; setsockopt(&self.inner, libc::IPPROTO_IP, opt, mreq) } - IpAddr::V6(ref addr) => { + SocketAddr::V6(ref addr) => { let mreq = libc::ip6_mreq { - ipv6mr_multiaddr: *addr.as_inner(), + ipv6mr_multiaddr: *addr.ip().as_inner(), ipv6mr_interface: 0, }; setsockopt(&self.inner, libc::IPPROTO_IPV6, opt, mreq) diff --git a/src/libstd/sys/unix/net.rs b/src/libstd/sys/unix/net.rs index 83b6a14b78d95..b22fa33e5624a 100644 --- a/src/libstd/sys/unix/net.rs +++ b/src/libstd/sys/unix/net.rs @@ -15,7 +15,7 @@ use io; use libc::{self, c_int, size_t}; use str; use sys::c; -use net::{SocketAddr, IpAddr}; +use net::SocketAddr; use sys::fd::FileDesc; use sys_common::AsInner; @@ -40,9 +40,9 @@ pub fn cvt_gai(err: c_int) -> io::Result<()> { impl Socket { pub fn new(addr: &SocketAddr, ty: c_int) -> io::Result { - let fam = match addr.ip() { - IpAddr::V4(..) => libc::AF_INET, - IpAddr::V6(..) => libc::AF_INET6, + let fam = match *addr { + SocketAddr::V4(..) => libc::AF_INET, + SocketAddr::V6(..) => libc::AF_INET6, }; unsafe { let fd = try!(cvt(libc::socket(fam, ty, 0))); diff --git a/src/libstd/sys/windows/net.rs b/src/libstd/sys/windows/net.rs index 6caa4df5dfe62..e092faf4935db 100644 --- a/src/libstd/sys/windows/net.rs +++ b/src/libstd/sys/windows/net.rs @@ -14,7 +14,7 @@ use io; use libc::consts::os::extra::INVALID_SOCKET; use libc::{self, c_int, c_void}; use mem; -use net::{SocketAddr, IpAddr}; +use net::SocketAddr; use num::{SignedInt, Int}; use rt; use sync::{Once, ONCE_INIT}; @@ -73,9 +73,9 @@ pub fn cvt_r(mut f: F) -> io::Result where F: FnMut() -> T { impl Socket { pub fn new(addr: &SocketAddr, ty: c_int) -> io::Result { - let fam = match addr.ip() { - IpAddr::V4(..) => libc::AF_INET, - IpAddr::V6(..) => libc::AF_INET6, + let fam = match *addr { + SocketAddr::V4(..) => libc::AF_INET, + SocketAddr::V6(..) => libc::AF_INET6, }; match unsafe { libc::socket(fam, ty, 0) } { INVALID_SOCKET => Err(last_error()), diff --git a/src/test/run-pass/issue-22577.rs b/src/test/run-pass/issue-22577.rs index 1ecdd39ca7af5..f668cae66c603 100644 --- a/src/test/run-pass/issue-22577.rs +++ b/src/test/run-pass/issue-22577.rs @@ -25,5 +25,8 @@ fn main() { assert_both::(); assert_both::(); assert_both::(); - assert_both::(); + assert_both::(); + assert_both::(); + assert_both::(); + assert_both::(); }