1
Fork 0

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]
This commit is contained in:
Alex Crichton 2015-03-13 14:22:33 -07:00
parent 3e4be02b80
commit f798674b86
12 changed files with 417 additions and 238 deletions

View file

@ -20,7 +20,6 @@
#![feature(std_misc)] #![feature(std_misc)]
#![feature(test)] #![feature(test)]
#![feature(core)] #![feature(core)]
#![feature(net)]
#![feature(path_ext)] #![feature(path_ext)]
#![deny(warnings)] #![deny(warnings)]

View file

@ -15,70 +15,137 @@ use hash;
use io; use io;
use libc::{self, socklen_t, sa_family_t}; use libc::{self, socklen_t, sa_family_t};
use mem; use mem;
use net::{IpAddr, lookup_host, ntoh, hton}; use net::{lookup_host, ntoh, hton, Ipv4Addr, Ipv6Addr};
use option; use option;
use sys_common::{FromInner, AsInner, IntoInner}; use sys_common::{FromInner, AsInner, IntoInner};
use vec; 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 /// A socket address can either represent the IPv4 or IPv6 protocol and is
/// contain other information depending on the protocol. /// paired with at least a port number as well. Each protocol may have more
#[derive(Copy, Clone, PartialEq, Eq, Hash)] /// specific information about the address available to it as well.
pub struct SocketAddr { #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
repr: Repr, #[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)] #[derive(Copy)]
enum Repr { #[stable(feature = "rust1", since = "1.0.0")]
V4(libc::sockaddr_in), pub struct SocketAddrV4 { inner: libc::sockaddr_in }
V6(libc::sockaddr_in6),
} /// An IPv6 socket address
#[derive(Copy)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct SocketAddrV6 { inner: libc::sockaddr_in6 }
impl SocketAddr { 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. /// Creates a new socket address from the (ip, port) pair.
pub fn new(ip: IpAddr, port: u16) -> SocketAddr { #[stable(feature = "rust1", since = "1.0.0")]
let repr = match ip { pub fn new(ip: Ipv4Addr, port: u16) -> SocketAddrV4 {
IpAddr::V4(ref ip) => { SocketAddrV4 {
Repr::V4(libc::sockaddr_in { inner: libc::sockaddr_in {
sin_family: libc::AF_INET as sa_family_t, sin_family: libc::AF_INET as sa_family_t,
sin_port: hton(port), sin_port: hton(port),
sin_addr: *ip.as_inner(), sin_addr: *ip.as_inner(),
.. unsafe { mem::zeroed() } .. 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 }
} }
/// Gets the IP address associated with this socket address. /// Gets the IP address associated with this socket address.
pub fn ip(&self) -> IpAddr { #[stable(feature = "rust1", since = "1.0.0")]
match self.repr { pub fn ip(&self) -> &Ipv4Addr {
Repr::V4(ref sa) => IpAddr::V4(FromInner::from_inner(sa.sin_addr)), unsafe {
Repr::V6(ref sa) => IpAddr::V6(FromInner::from_inner(sa.sin6_addr)), &*(&self.inner.sin_addr as *const libc::in_addr as *const Ipv4Addr)
} }
} }
/// Gets the port number associated with this socket address /// Gets the port number associated with this socket address
pub fn port(&self) -> u16 { #[stable(feature = "rust1", since = "1.0.0")]
match self.repr { pub fn port(&self) -> u16 { ntoh(self.inner.sin_port) }
Repr::V4(ref sa) => ntoh(sa.sin_port), }
Repr::V6(ref sa) => ntoh(sa.sin6_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() }
},
} }
} }
fn set_port(&mut self, port: u16) { /// Gets the IP address associated with this socket address.
match self.repr { #[stable(feature = "rust1", since = "1.0.0")]
Repr::V4(ref mut sa) => sa.sin_port = hton(port), pub fn ip(&self) -> &Ipv6Addr {
Repr::V6(ref mut sa) => sa.sin6_port = hton(port), 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<libc::sockaddr_in> for SocketAddrV4 {
fn from_inner(addr: libc::sockaddr_in) -> SocketAddrV4 {
SocketAddrV4 { inner: addr }
}
}
impl FromInner<libc::sockaddr_in6> 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 {
SocketAddr::V4(ref a) => {
(a as *const _ as *const _, mem::size_of_val(a) as socklen_t)
}
SocketAddr::V6(ref a) => {
(a as *const _ as *const _, mem::size_of_val(a) as socklen_t)
}
} }
} }
} }
@ -86,79 +153,82 @@ impl SocketAddr {
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
impl fmt::Display for SocketAddr { impl fmt::Display for SocketAddr {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self.repr { match *self {
Repr::V4(_) => write!(f, "{}:{}", self.ip(), self.port()), SocketAddr::V4(ref a) => a.fmt(f),
Repr::V6(_) => write!(f, "[{}]:{}", self.ip(), self.port()), SocketAddr::V6(ref a) => a.fmt(f),
} }
} }
} }
impl FromInner<libc::sockaddr_in> for SocketAddr { #[stable(feature = "rust1", since = "1.0.0")]
fn from_inner(addr: libc::sockaddr_in) -> SocketAddr { impl fmt::Display for SocketAddrV4 {
SocketAddr { repr: Repr::V4(addr) } fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}:{}", self.ip(), self.port())
} }
} }
impl FromInner<libc::sockaddr_in6> for SocketAddr { #[stable(feature = "rust1", since = "1.0.0")]
fn from_inner(addr: libc::sockaddr_in6) -> SocketAddr { impl fmt::Debug for SocketAddrV4 {
SocketAddr { repr: Repr::V6(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) => {
(a as *const _ as *const _, mem::size_of_val(a) as socklen_t)
}
Repr::V6(ref a) => {
(a as *const _ as *const _, mem::size_of_val(a) as socklen_t)
}
}
}
}
impl fmt::Debug for SocketAddr {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
fmt::Display::fmt(self, fmt) fmt::Display::fmt(self, fmt)
} }
} }
impl Clone for Repr { #[stable(feature = "rust1", since = "1.0.0")]
fn clone(&self) -> Repr { *self } 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,
}
} }
} }
impl Eq for Repr {}
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
impl hash::Hash for Repr { 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
}
}
#[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 SocketAddrV4 {
fn hash<H: hash::Hasher>(&self, s: &mut H) { fn hash<H: hash::Hasher>(&self, s: &mut H) {
match *self { (self.inner.sin_port, self.inner.sin_addr.s_addr).hash(s)
Repr::V4(ref a) => { }
(a.sin_family, a.sin_port, a.sin_addr.s_addr).hash(s) }
} #[stable(feature = "rust1", since = "1.0.0")]
Repr::V6(ref a) => { impl hash::Hash for SocketAddrV6 {
(a.sin6_family, a.sin6_port, &a.sin6_addr.s6_addr, fn hash<H: hash::Hasher>(&self, s: &mut H) {
a.sin6_flowinfo, a.sin6_scope_id).hash(s) (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 /// This trait is used for generic address resolution when constructing network
/// objects. By default it is implemented for the following types: /// 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 /// * `(&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. /// name.
/// ///
/// * `&str` - the string should be either a string representation of a /// * `&str` - the string should be either a string representation of a
@ -192,18 +263,18 @@ impl hash::Hash for Repr {
/// Some examples: /// Some examples:
/// ///
/// ```no_run /// ```no_run
/// use std::net::{IpAddr, SocketAddr, TcpStream, UdpSocket, TcpListener}; /// use std::net::{SocketAddrV4, TcpStream, UdpSocket, TcpListener, Ipv4Addr};
/// ///
/// fn main() { /// fn main() {
/// let ip = IpAddr::new_v4(127, 0, 0, 1); /// let ip = Ipv4Addr::new(127, 0, 0, 1);
/// let port = 12345; /// let port = 12345;
/// ///
/// // The following lines are equivalent modulo possible "localhost" name /// // The following lines are equivalent modulo possible "localhost" name
/// // resolution differences /// // resolution differences
/// let tcp_s = TcpStream::connect(&SocketAddr::new(ip, port)); /// let tcp_s = TcpStream::connect(SocketAddrV4::new(ip, port));
/// let tcp_s = TcpStream::connect(&(ip, port)); /// let tcp_s = TcpStream::connect((ip, port));
/// let tcp_s = TcpStream::connect(&("127.0.0.1", port)); /// let tcp_s = TcpStream::connect(("127.0.0.1", port));
/// let tcp_s = TcpStream::connect(&("localhost", port)); /// let tcp_s = TcpStream::connect(("localhost", port));
/// let tcp_s = TcpStream::connect("127.0.0.1:12345"); /// let tcp_s = TcpStream::connect("127.0.0.1:12345");
/// let tcp_s = TcpStream::connect("localhost:12345"); /// let tcp_s = TcpStream::connect("localhost:12345");
/// ///
@ -211,13 +282,15 @@ impl hash::Hash for Repr {
/// // behave similarly /// // behave similarly
/// let tcp_l = TcpListener::bind("localhost:12345"); /// let tcp_l = TcpListener::bind("localhost:12345");
/// ///
/// let mut udp_s = UdpSocket::bind(&("127.0.0.1", port)).unwrap(); /// let mut udp_s = UdpSocket::bind(("127.0.0.1", port)).unwrap();
/// udp_s.send_to(&[7], &(ip, 23451)); /// udp_s.send_to(&[7], (ip, 23451));
/// } /// }
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub trait ToSocketAddrs { pub trait ToSocketAddrs {
/// Returned iterator over socket addresses which this type may correspond /// Returned iterator over socket addresses which this type may correspond
/// to. /// to.
#[stable(feature = "rust1", since = "1.0.0")]
type Iter: Iterator<Item=SocketAddr>; type Iter: Iterator<Item=SocketAddr>;
/// Converts this object to an iterator of resolved `SocketAddr`s. /// Converts this object to an iterator of resolved `SocketAddr`s.
@ -231,9 +304,11 @@ pub trait ToSocketAddrs {
/// # Errors /// # Errors
/// ///
/// Any errors encountered during resolution will be returned as an `Err`. /// 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<Self::Iter>; fn to_socket_addrs(&self) -> io::Result<Self::Iter>;
} }
#[stable(feature = "rust1", since = "1.0.0")]
impl ToSocketAddrs for SocketAddr { impl ToSocketAddrs for SocketAddr {
type Iter = option::IntoIter<SocketAddr>; type Iter = option::IntoIter<SocketAddr>;
fn to_socket_addrs(&self) -> io::Result<option::IntoIter<SocketAddr>> { fn to_socket_addrs(&self) -> io::Result<option::IntoIter<SocketAddr>> {
@ -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<SocketAddr>;
fn to_socket_addrs(&self) -> io::Result<option::IntoIter<SocketAddr>> {
SocketAddr::V4(*self).to_socket_addrs()
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl ToSocketAddrs for SocketAddrV6 {
type Iter = option::IntoIter<SocketAddr>;
fn to_socket_addrs(&self) -> io::Result<option::IntoIter<SocketAddr>> {
SocketAddr::V6(*self).to_socket_addrs()
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl ToSocketAddrs for (Ipv4Addr, u16) {
type Iter = option::IntoIter<SocketAddr>; type Iter = option::IntoIter<SocketAddr>;
fn to_socket_addrs(&self) -> io::Result<option::IntoIter<SocketAddr>> { fn to_socket_addrs(&self) -> io::Result<option::IntoIter<SocketAddr>> {
let (ip, port) = *self; let (ip, port) = *self;
Ok(Some(SocketAddr::new(ip, port)).into_iter()) SocketAddrV4::new(ip, port).to_socket_addrs()
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl ToSocketAddrs for (Ipv6Addr, u16) {
type Iter = option::IntoIter<SocketAddr>;
fn to_socket_addrs(&self) -> io::Result<option::IntoIter<SocketAddr>> {
let (ip, port) = *self;
SocketAddrV6::new(ip, port, 0, 0).to_socket_addrs()
} }
} }
fn resolve_socket_addr(s: &str, p: u16) -> io::Result<vec::IntoIter<SocketAddr>> { fn resolve_socket_addr(s: &str, p: u16) -> io::Result<vec::IntoIter<SocketAddr>> {
let ips = try!(lookup_host(s)); let ips = try!(lookup_host(s));
let v: Vec<_> = try!(ips.map(|a| { 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()); }).collect());
Ok(v.into_iter()) Ok(v.into_iter())
} }
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a> ToSocketAddrs for (&'a str, u16) { impl<'a> ToSocketAddrs for (&'a str, u16) {
type Iter = vec::IntoIter<SocketAddr>; type Iter = vec::IntoIter<SocketAddr>;
fn to_socket_addrs(&self) -> io::Result<vec::IntoIter<SocketAddr>> { fn to_socket_addrs(&self) -> io::Result<vec::IntoIter<SocketAddr>> {
let (host, port) = *self; let (host, port) = *self;
// try to parse the host as a regular IpAddr first // try to parse the host as a regular IP address first
match host.parse().ok() { if let Ok(addr) = host.parse::<Ipv4Addr>() {
Some(addr) => return Ok(vec![SocketAddr::new(addr, port)].into_iter()), let addr = SocketAddrV4::new(addr, port);
None => {} return Ok(vec![SocketAddr::V4(addr)].into_iter())
}
if let Ok(addr) = host.parse::<Ipv6Addr>() {
let addr = SocketAddrV6::new(addr, port, 0, 0);
return Ok(vec![SocketAddr::V6(addr)].into_iter())
} }
resolve_socket_addr(host, port) resolve_socket_addr(host, port)
@ -273,6 +389,7 @@ impl<'a> ToSocketAddrs for (&'a str, u16) {
} }
// accepts strings like 'localhost:12345' // accepts strings like 'localhost:12345'
#[stable(feature = "rust1", since = "1.0.0")]
impl ToSocketAddrs for str { impl ToSocketAddrs for str {
type Iter = vec::IntoIter<SocketAddr>; type Iter = vec::IntoIter<SocketAddr>;
fn to_socket_addrs(&self) -> io::Result<vec::IntoIter<SocketAddr>> { fn to_socket_addrs(&self) -> io::Result<vec::IntoIter<SocketAddr>> {
@ -322,16 +439,16 @@ mod tests {
assert_eq!(Ok(Ipv4Addr::new(0, 0, 0, 0)), "0.0.0.0".parse()); assert_eq!(Ok(Ipv4Addr::new(0, 0, 0, 0)), "0.0.0.0".parse());
// out of range // out of range
let none: Option<IpAddr> = "256.0.0.1".parse().ok(); let none: Option<Ipv4Addr> = "256.0.0.1".parse().ok();
assert_eq!(None, none); assert_eq!(None, none);
// too short // too short
let none: Option<IpAddr> = "255.0.0".parse().ok(); let none: Option<Ipv4Addr> = "255.0.0".parse().ok();
assert_eq!(None, none); assert_eq!(None, none);
// too long // too long
let none: Option<IpAddr> = "255.0.0.1.2".parse().ok(); let none: Option<Ipv4Addr> = "255.0.0.1.2".parse().ok();
assert_eq!(None, none); assert_eq!(None, none);
// no number between dots // no number between dots
let none: Option<IpAddr> = "255.0..1".parse().ok(); let none: Option<Ipv4Addr> = "255.0..1".parse().ok();
assert_eq!(None, none); assert_eq!(None, none);
} }
@ -347,19 +464,19 @@ mod tests {
"2a02:6b8::11:11".parse()); "2a02:6b8::11:11".parse());
// too long group // too long group
let none: Option<IpAddr> = "::00000".parse().ok(); let none: Option<Ipv6Addr> = "::00000".parse().ok();
assert_eq!(None, none); assert_eq!(None, none);
// too short // too short
let none: Option<IpAddr> = "1:2:3:4:5:6:7".parse().ok(); let none: Option<Ipv6Addr> = "1:2:3:4:5:6:7".parse().ok();
assert_eq!(None, none); assert_eq!(None, none);
// too long // too long
let none: Option<IpAddr> = "1:2:3:4:5:6:7:8:9".parse().ok(); let none: Option<Ipv6Addr> = "1:2:3:4:5:6:7:8:9".parse().ok();
assert_eq!(None, none); assert_eq!(None, none);
// triple colon // triple colon
let none: Option<IpAddr> = "1:2:::6:7:8".parse().ok(); let none: Option<Ipv6Addr> = "1:2:::6:7:8".parse().ok();
assert_eq!(None, none); assert_eq!(None, none);
// two double colons // two double colons
let none: Option<IpAddr> = "1:2::6::8".parse().ok(); let none: Option<Ipv6Addr> = "1:2::6::8".parse().ok();
assert_eq!(None, none); assert_eq!(None, none);
} }
@ -375,24 +492,24 @@ mod tests {
"2001:db8:122:c000:2:2100:192.0.2.33".parse()); "2001:db8:122:c000:2:2100:192.0.2.33".parse());
// colon after v4 // colon after v4
let none: Option<IpAddr> = "::127.0.0.1:".parse().ok(); let none: Option<Ipv4Addr> = "::127.0.0.1:".parse().ok();
assert_eq!(None, none); assert_eq!(None, none);
// not enough groups // not enough groups
let none: Option<IpAddr> = "1.2.3.4.5:127.0.0.1".parse().ok(); let none: Option<Ipv6Addr> = "1.2.3.4.5:127.0.0.1".parse().ok();
assert_eq!(None, none); assert_eq!(None, none);
// too many groups // too many groups
let none: Option<IpAddr> = "1.2.3.4.5:6:7:127.0.0.1".parse().ok(); let none: Option<Ipv6Addr> = "1.2.3.4.5:6:7:127.0.0.1".parse().ok();
assert_eq!(None, none); assert_eq!(None, none);
} }
#[test] #[test]
fn test_from_str_socket_addr() { fn test_from_str_socket_addr() {
assert_eq!(Ok(SocketAddr::new(IpAddr::new_v4(77, 88, 21, 11), 80)), assert_eq!(Ok(sa4(Ipv4Addr::new(77, 88, 21, 11), 80)),
"77.88.21.11:80".parse()); "77.88.21.11:80".parse());
assert_eq!(Ok(SocketAddr::new(IpAddr::new_v6(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1), 53)), assert_eq!(Ok(sa6(Ipv6Addr::new(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1), 53)),
"[2a02:6b8:0:1::1]:53".parse()); "[2a02:6b8:0:1::1]:53".parse());
assert_eq!(Ok(SocketAddr::new(IpAddr::new_v6(0, 0, 0, 0, 0, 0, 0x7F00, 1), 22)), assert_eq!(Ok(sa6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0x7F00, 1), 22)),
"[::127.0.0.1]:22".parse()); "[::127.0.0.1]:22".parse());
// without port // without port
let none: Option<SocketAddr> = "127.0.0.1".parse().ok(); let none: Option<SocketAddr> = "127.0.0.1".parse().ok();
@ -555,39 +672,47 @@ mod tests {
#[test] #[test]
fn to_socket_addr_socketaddr() { 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)); 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] #[test]
fn to_socket_addr_ipaddr_u16() { 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 p = 12345;
let e = SocketAddr::new(a, p); let e = SocketAddr::V4(SocketAddrV4::new(a, p));
assert_eq!(Ok(vec![e]), tsa((a, p))); assert_eq!(Ok(vec![e]), tsa((a, p)));
} }
#[test] #[test]
fn to_socket_addr_str_u16() { 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))); 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))); 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)); assert!(tsa(("localhost", 23924)).unwrap().contains(&a));
} }
#[test] #[test]
fn to_socket_addr_str() { 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")); 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")); 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)); assert!(tsa("localhost:23924").unwrap().contains(&a));
} }

View file

@ -8,6 +8,10 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // 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 prelude::v1::*;
use cmp::Ordering; use cmp::Ordering;
@ -19,12 +23,14 @@ use net::{hton, ntoh};
/// Representation of an IPv4 address. /// Representation of an IPv4 address.
#[derive(Copy)] #[derive(Copy)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Ipv4Addr { pub struct Ipv4Addr {
inner: libc::in_addr, inner: libc::in_addr,
} }
/// Representation of an IPv6 address. /// Representation of an IPv6 address.
#[derive(Copy)] #[derive(Copy)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Ipv6Addr { pub struct Ipv6Addr {
inner: libc::in6_addr, inner: libc::in6_addr,
} }
@ -41,46 +47,11 @@ pub enum Ipv6MulticastScope {
Global 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 { impl Ipv4Addr {
/// Create a new IPv4 address from four eight-bit octets. /// Create a new IPv4 address from four eight-bit octets.
/// ///
/// The result will represent the IP address a.b.c.d /// 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 { pub fn new(a: u8, b: u8, c: u8, d: u8) -> Ipv4Addr {
Ipv4Addr { Ipv4Addr {
inner: libc::in_addr { inner: libc::in_addr {
@ -93,6 +64,7 @@ impl Ipv4Addr {
} }
/// Returns the four eight-bit integers that make up this address /// Returns the four eight-bit integers that make up this address
#[stable(feature = "rust1", since = "1.0.0")]
pub fn octets(&self) -> [u8; 4] { pub fn octets(&self) -> [u8; 4] {
let bits = ntoh(self.inner.s_addr); let bits = ntoh(self.inner.s_addr);
[(bits >> 24) as u8, (bits >> 16) as u8, (bits >> 8) as u8, bits as u8] [(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 /// Convert this address to an IPv4-compatible IPv6 address
/// ///
/// a.b.c.d becomes ::a.b.c.d /// a.b.c.d becomes ::a.b.c.d
#[stable(feature = "rust1", since = "1.0.0")]
pub fn to_ipv6_compatible(&self) -> Ipv6Addr { pub fn to_ipv6_compatible(&self) -> Ipv6Addr {
Ipv6Addr::new(0, 0, 0, 0, 0, 0, Ipv6Addr::new(0, 0, 0, 0, 0, 0,
((self.octets()[0] as u16) << 8) | self.octets()[1] as u16, ((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 /// Convert this address to an IPv4-mapped IPv6 address
/// ///
/// a.b.c.d becomes ::ffff:a.b.c.d /// a.b.c.d becomes ::ffff:a.b.c.d
#[stable(feature = "rust1", since = "1.0.0")]
pub fn to_ipv6_mapped(&self) -> Ipv6Addr { pub fn to_ipv6_mapped(&self) -> Ipv6Addr {
Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff,
((self.octets()[0] as u16) << 8) | self.octets()[1] as u16, ((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 { impl fmt::Display for Ipv4Addr {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
let octets = self.octets(); 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 { impl fmt::Debug for Ipv4Addr {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
fmt::Display::fmt(self, fmt) fmt::Display::fmt(self, fmt)
} }
} }
#[stable(feature = "rust1", since = "1.0.0")]
impl Clone for Ipv4Addr { impl Clone for Ipv4Addr {
fn clone(&self) -> Ipv4Addr { *self } fn clone(&self) -> Ipv4Addr { *self }
} }
#[stable(feature = "rust1", since = "1.0.0")]
impl PartialEq for Ipv4Addr { impl PartialEq for Ipv4Addr {
fn eq(&self, other: &Ipv4Addr) -> bool { fn eq(&self, other: &Ipv4Addr) -> bool {
self.inner.s_addr == other.inner.s_addr self.inner.s_addr == other.inner.s_addr
} }
} }
#[stable(feature = "rust1", since = "1.0.0")]
impl Eq for Ipv4Addr {} impl Eq for Ipv4Addr {}
#[stable(feature = "rust1", since = "1.0.0")] #[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 { impl PartialOrd for Ipv4Addr {
fn partial_cmp(&self, other: &Ipv4Addr) -> Option<Ordering> { fn partial_cmp(&self, other: &Ipv4Addr) -> Option<Ordering> {
Some(self.cmp(other)) Some(self.cmp(other))
} }
} }
#[stable(feature = "rust1", since = "1.0.0")]
impl Ord for Ipv4Addr { impl Ord for Ipv4Addr {
fn cmp(&self, other: &Ipv4Addr) -> Ordering { fn cmp(&self, other: &Ipv4Addr) -> Ordering {
self.inner.s_addr.cmp(&other.inner.s_addr) 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. /// Create a new IPv6 address from eight 16-bit segments.
/// ///
/// The result will represent the IP address a:b:c:d:e:f /// 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, pub fn new(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16,
h: u16) -> Ipv6Addr { h: u16) -> Ipv6Addr {
Ipv6Addr { Ipv6Addr {
@ -232,6 +215,7 @@ impl Ipv6Addr {
} }
/// Return the eight 16-bit segments that make up this address /// Return the eight 16-bit segments that make up this address
#[stable(feature = "rust1", since = "1.0.0")]
pub fn segments(&self) -> [u16; 8] { pub fn segments(&self) -> [u16; 8] {
[ntoh(self.inner.s6_addr[0]), [ntoh(self.inner.s6_addr[0]),
ntoh(self.inner.s6_addr[1]), ntoh(self.inner.s6_addr[1]),
@ -324,6 +308,7 @@ impl Ipv6Addr {
/// neither IPv4-compatible or IPv4-mapped. /// neither IPv4-compatible or IPv4-mapped.
/// ///
/// ::a.b.c.d and ::ffff:a.b.c.d become a.b.c.d /// ::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<Ipv4Addr> { pub fn to_ipv4(&self) -> Option<Ipv4Addr> {
match self.segments() { match self.segments() {
[0, 0, 0, 0, 0, f, g, h] if f == 0 || f == 0xffff => { [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 { impl fmt::Display for Ipv6Addr {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
match self.segments() { match self.segments() {
@ -405,21 +391,26 @@ impl fmt::Display for Ipv6Addr {
} }
} }
#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::Debug for Ipv6Addr { impl fmt::Debug for Ipv6Addr {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
fmt::Display::fmt(self, fmt) fmt::Display::fmt(self, fmt)
} }
} }
#[stable(feature = "rust1", since = "1.0.0")]
impl Clone for Ipv6Addr { impl Clone for Ipv6Addr {
fn clone(&self) -> Ipv6Addr { *self } fn clone(&self) -> Ipv6Addr { *self }
} }
#[stable(feature = "rust1", since = "1.0.0")]
impl PartialEq for Ipv6Addr { impl PartialEq for Ipv6Addr {
fn eq(&self, other: &Ipv6Addr) -> bool { fn eq(&self, other: &Ipv6Addr) -> bool {
self.inner.s6_addr == other.inner.s6_addr self.inner.s6_addr == other.inner.s6_addr
} }
} }
#[stable(feature = "rust1", since = "1.0.0")]
impl Eq for Ipv6Addr {} impl Eq for Ipv6Addr {}
#[stable(feature = "rust1", since = "1.0.0")] #[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 { impl PartialOrd for Ipv6Addr {
fn partial_cmp(&self, other: &Ipv6Addr) -> Option<Ordering> { fn partial_cmp(&self, other: &Ipv6Addr) -> Option<Ordering> {
Some(self.cmp(other)) Some(self.cmp(other))
} }
} }
#[stable(feature = "rust1", since = "1.0.0")]
impl Ord for Ipv6Addr { impl Ord for Ipv6Addr {
fn cmp(&self, other: &Ipv6Addr) -> Ordering { fn cmp(&self, other: &Ipv6Addr) -> Ordering {
self.inner.s6_addr.cmp(&other.inner.s6_addr) self.inner.s6_addr.cmp(&other.inner.s6_addr)

View file

@ -14,7 +14,7 @@
//! > development. At this time it is still recommended to use the `old_io` //! > development. At this time it is still recommended to use the `old_io`
//! > module while the details of this module shake out. //! > module while the details of this module shake out.
#![unstable(feature = "net")] #![stable(feature = "rust1", since = "1.0.0")]
use prelude::v1::*; use prelude::v1::*;
@ -22,8 +22,8 @@ use io::{self, Error, ErrorKind};
use num::Int; use num::Int;
use sys_common::net2 as net_imp; use sys_common::net2 as net_imp;
pub use self::ip::{IpAddr, Ipv4Addr, Ipv6Addr, Ipv6MulticastScope}; pub use self::ip::{Ipv4Addr, Ipv6Addr, Ipv6MulticastScope};
pub use self::addr::{SocketAddr, ToSocketAddrs}; pub use self::addr::{SocketAddr, SocketAddrV4, SocketAddrV6, ToSocketAddrs};
pub use self::tcp::{TcpStream, TcpListener}; pub use self::tcp::{TcpStream, TcpListener};
pub use self::udp::UdpSocket; pub use self::udp::UdpSocket;
@ -37,23 +37,27 @@ mod parser;
/// Possible values which can be passed to the `shutdown` method of `TcpStream` /// Possible values which can be passed to the `shutdown` method of `TcpStream`
/// and `UdpSocket`. /// and `UdpSocket`.
#[derive(Copy, Clone, PartialEq)] #[derive(Copy, Clone, PartialEq)]
#[stable(feature = "rust1", since = "1.0.0")]
pub enum Shutdown { pub enum Shutdown {
/// Indicates that the reading portion of this stream/socket should be shut /// Indicates that the reading portion of this stream/socket should be shut
/// down. All currently blocked and future reads will return `Ok(0)`. /// down. All currently blocked and future reads will return `Ok(0)`.
#[stable(feature = "rust1", since = "1.0.0")]
Read, Read,
/// Indicates that the writing portion of this stream/socket should be shut /// Indicates that the writing portion of this stream/socket should be shut
/// down. All currently blocked and future writes will return an error. /// down. All currently blocked and future writes will return an error.
#[stable(feature = "rust1", since = "1.0.0")]
Write, Write,
/// Shut down both the reading and writing portions of this stream. /// Shut down both the reading and writing portions of this stream.
/// ///
/// See `Shutdown::Read` and `Shutdown::Write` for more information. /// See `Shutdown::Read` and `Shutdown::Write` for more information.
Both #[stable(feature = "rust1", since = "1.0.0")]
Both,
} }
fn hton<I: Int>(i: I) -> I { i.to_be() } fn hton<I: Int>(i: I) -> I { i.to_be() }
fn ntoh<I: Int>(i: I) -> I { Int::from_be(i) } fn ntoh<I: Int>(i: I) -> I { Int::from_be(i) }
fn each_addr<A: ToSocketAddrs + ?Sized, F, T>(addr: &A, mut f: F) -> io::Result<T> fn each_addr<A: ToSocketAddrs, F, T>(addr: A, mut f: F) -> io::Result<T>
where F: FnMut(&SocketAddr) -> io::Result<T> where F: FnMut(&SocketAddr) -> io::Result<T>
{ {
let mut last_err = None; let mut last_err = None;
@ -70,8 +74,10 @@ fn each_addr<A: ToSocketAddrs + ?Sized, F, T>(addr: &A, mut f: F) -> io::Result<
} }
/// An iterator over `SocketAddr` values returned from a host lookup operation. /// An iterator over `SocketAddr` values returned from a host lookup operation.
#[stable(feature = "rust1", since = "1.0.0")]
pub struct LookupHost(net_imp::LookupHost); pub struct LookupHost(net_imp::LookupHost);
#[stable(feature = "rust1", since = "1.0.0")]
impl Iterator for LookupHost { impl Iterator for LookupHost {
type Item = io::Result<SocketAddr>; type Item = io::Result<SocketAddr>;
fn next(&mut self) -> Option<io::Result<SocketAddr>> { self.0.next() } fn next(&mut self) -> Option<io::Result<SocketAddr>> { self.0.next() }
@ -94,6 +100,7 @@ impl Iterator for LookupHost {
/// # Ok(()) /// # Ok(())
/// # } /// # }
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn lookup_host(host: &str) -> io::Result<LookupHost> { pub fn lookup_host(host: &str) -> io::Result<LookupHost> {
net_imp::lookup_host(host).map(LookupHost) net_imp::lookup_host(host).map(LookupHost)
} }

View file

@ -16,7 +16,7 @@
use prelude::v1::*; use prelude::v1::*;
use str::FromStr; use str::FromStr;
use net::{Ipv4Addr, Ipv6Addr, IpAddr, SocketAddr}; use net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6};
struct Parser<'a> { struct Parser<'a> {
// parsing as ASCII, so can use byte array // parsing as ASCII, so can use byte array
@ -24,6 +24,11 @@ struct Parser<'a> {
pos: usize, pos: usize,
} }
enum IpAddr {
V4(Ipv4Addr),
V6(Ipv6Addr),
}
impl<'a> Parser<'a> { impl<'a> Parser<'a> {
fn new(s: &'a str) -> Parser<'a> { fn new(s: &'a str) -> Parser<'a> {
Parser { 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); let port = |p: &mut Parser| p.read_number(10, 5, 0x10000).map(|n| n as u16);
// host, colon, port // host, colon, port
self.read_seq_3::<IpAddr, char, u16, _, _, _>(ip_addr, colon, port) self.read_seq_3(ip_addr, colon, port).map(|t| {
.map(|t| match t { (ip, _, port) => SocketAddr::new(ip, port) }) 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)),
impl FromStr for IpAddr { }
type Err = ParseError; })
fn from_str(s: &str) -> Result<IpAddr, ParseError> {
match Parser::new(s).read_till_eof(|p| p.read_ip_addr()) {
Some(s) => Ok(s),
None => Err(ParseError),
}
} }
} }

View file

@ -8,6 +8,9 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
#![unstable(feature = "tcp", reason = "remaining functions have not been \
scrutinized enough to be stabilized")]
use prelude::v1::*; use prelude::v1::*;
use io::prelude::*; use io::prelude::*;
@ -35,6 +38,7 @@ use sys_common::AsInner;
/// let _ = stream.read(&mut [0; 128]); // ignore here too /// let _ = stream.read(&mut [0; 128]); // ignore here too
/// } // the stream is closed here /// } // the stream is closed here
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub struct TcpStream(net_imp::TcpStream); pub struct TcpStream(net_imp::TcpStream);
/// A structure representing a socket server. /// A structure representing a socket server.
@ -67,12 +71,14 @@ pub struct TcpStream(net_imp::TcpStream);
/// // close the socket server /// // close the socket server
/// drop(listener); /// drop(listener);
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub struct TcpListener(net_imp::TcpListener); pub struct TcpListener(net_imp::TcpListener);
/// An infinite iterator over the connections from a `TcpListener`. /// An infinite iterator over the connections from a `TcpListener`.
/// ///
/// This iterator will infinitely yield `Some` of the accepted connections. It /// This iterator will infinitely yield `Some` of the accepted connections. It
/// is equivalent to calling `accept` in a loop. /// is equivalent to calling `accept` in a loop.
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Incoming<'a> { listener: &'a TcpListener } pub struct Incoming<'a> { listener: &'a TcpListener }
impl TcpStream { impl TcpStream {
@ -81,25 +87,36 @@ impl TcpStream {
/// `addr` is an address of the remote host. Anything which implements /// `addr` is an address of the remote host. Anything which implements
/// `ToSocketAddrs` trait can be supplied for the address; see this trait /// `ToSocketAddrs` trait can be supplied for the address; see this trait
/// documentation for concrete examples. /// documentation for concrete examples.
pub fn connect<A: ToSocketAddrs + ?Sized>(addr: &A) -> io::Result<TcpStream> { #[stable(feature = "rust1", since = "1.0.0")]
pub fn connect<A: ToSocketAddrs>(addr: A) -> io::Result<TcpStream> {
super::each_addr(addr, net_imp::TcpStream::connect).map(TcpStream) super::each_addr(addr, net_imp::TcpStream::connect).map(TcpStream)
} }
/// Returns the socket address of the remote peer of this TCP connection. /// 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<SocketAddr> { pub fn peer_addr(&self) -> io::Result<SocketAddr> {
self.0.peer_addr() self.0.peer_addr()
} }
/// Returns the socket address of the local half of this TCP connection. /// 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<SocketAddr> { pub fn socket_addr(&self) -> io::Result<SocketAddr> {
self.0.socket_addr() 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<SocketAddr> {
self.0.socket_addr()
}
/// Shut down the read, write, or both halves of this connection. /// Shut down the read, write, or both halves of this connection.
/// ///
/// This function will cause all pending and future I/O on the specified /// This function will cause all pending and future I/O on the specified
/// portions to return immediately with an appropriate value (see the /// portions to return immediately with an appropriate value (see the
/// documentation of `Shutdown`). /// documentation of `Shutdown`).
#[stable(feature = "rust1", since = "1.0.0")]
pub fn shutdown(&self, how: Shutdown) -> io::Result<()> { pub fn shutdown(&self, how: Shutdown) -> io::Result<()> {
self.0.shutdown(how) self.0.shutdown(how)
} }
@ -110,6 +127,7 @@ impl TcpStream {
/// object references. Both handles will read and write the same stream of /// 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 /// data, and options set on one stream will be propagated to the other
/// stream. /// stream.
#[stable(feature = "rust1", since = "1.0.0")]
pub fn try_clone(&self) -> io::Result<TcpStream> { pub fn try_clone(&self) -> io::Result<TcpStream> {
self.0.duplicate().map(TcpStream) self.0.duplicate().map(TcpStream)
} }
@ -129,16 +147,20 @@ impl TcpStream {
} }
} }
#[stable(feature = "rust1", since = "1.0.0")]
impl Read for TcpStream { impl Read for TcpStream {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { self.0.read(buf) } fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { self.0.read(buf) }
} }
#[stable(feature = "rust1", since = "1.0.0")]
impl Write for TcpStream { impl Write for TcpStream {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> { self.0.write(buf) } fn write(&mut self, buf: &[u8]) -> io::Result<usize> { self.0.write(buf) }
fn flush(&mut self) -> io::Result<()> { Ok(()) } fn flush(&mut self) -> io::Result<()> { Ok(()) }
} }
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a> Read for &'a TcpStream { impl<'a> Read for &'a TcpStream {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { self.0.read(buf) } fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { self.0.read(buf) }
} }
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a> Write for &'a TcpStream { impl<'a> Write for &'a TcpStream {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> { self.0.write(buf) } fn write(&mut self, buf: &[u8]) -> io::Result<usize> { self.0.write(buf) }
fn flush(&mut self) -> io::Result<()> { Ok(()) } fn flush(&mut self) -> io::Result<()> { Ok(()) }
@ -160,11 +182,20 @@ impl TcpListener {
/// ///
/// The address type can be any implementer of `ToSocketAddrs` trait. See /// The address type can be any implementer of `ToSocketAddrs` trait. See
/// its documentation for concrete examples. /// its documentation for concrete examples.
pub fn bind<A: ToSocketAddrs + ?Sized>(addr: &A) -> io::Result<TcpListener> { #[stable(feature = "rust1", since = "1.0.0")]
pub fn bind<A: ToSocketAddrs>(addr: A) -> io::Result<TcpListener> {
super::each_addr(addr, net_imp::TcpListener::bind).map(TcpListener) super::each_addr(addr, net_imp::TcpListener::bind).map(TcpListener)
} }
/// Returns the local socket address of this listener. /// Returns the local socket address of this listener.
#[stable(feature = "rust1", since = "1.0.0")]
pub fn local_addr(&self) -> io::Result<SocketAddr> {
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<SocketAddr> { pub fn socket_addr(&self) -> io::Result<SocketAddr> {
self.0.socket_addr() self.0.socket_addr()
} }
@ -174,6 +205,7 @@ impl TcpListener {
/// The returned `TcpListener` is a reference to the same socket that this /// The returned `TcpListener` is a reference to the same socket that this
/// object references. Both handles can be used to accept incoming /// object references. Both handles can be used to accept incoming
/// connections and options set on one listener will affect the other. /// 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<TcpListener> { pub fn try_clone(&self) -> io::Result<TcpListener> {
self.0.duplicate().map(TcpListener) self.0.duplicate().map(TcpListener)
} }
@ -183,6 +215,7 @@ impl TcpListener {
/// This function will block the calling thread until a new TCP connection /// This function will block the calling thread until a new TCP connection
/// is established. When established, the corresponding `TcpStream` and the /// is established. When established, the corresponding `TcpStream` and the
/// remote peer's address will be returned. /// remote peer's address will be returned.
#[stable(feature = "rust1", since = "1.0.0")]
pub fn accept(&self) -> io::Result<(TcpStream, SocketAddr)> { pub fn accept(&self) -> io::Result<(TcpStream, SocketAddr)> {
self.0.accept().map(|(a, b)| (TcpStream(a), b)) 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 returned iterator will never returned `None` and will also not yield
/// the peer's `SocketAddr` structure. /// the peer's `SocketAddr` structure.
#[stable(feature = "rust1", since = "1.0.0")]
pub fn incoming(&self) -> Incoming { pub fn incoming(&self) -> Incoming {
Incoming { listener: self } Incoming { listener: self }
} }
} }
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a> Iterator for Incoming<'a> { impl<'a> Iterator for Incoming<'a> {
type Item = io::Result<TcpStream>; type Item = io::Result<TcpStream>;
fn next(&mut self) -> Option<io::Result<TcpStream>> { fn next(&mut self) -> Option<io::Result<TcpStream>> {

View file

@ -11,19 +11,20 @@
use prelude::v1::*; use prelude::v1::*;
use env; use env;
use net::{SocketAddr, IpAddr}; use net::{SocketAddr, SocketAddrV4, SocketAddrV6, Ipv4Addr, Ipv6Addr};
use sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering}; use sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
static PORT: AtomicUsize = ATOMIC_USIZE_INIT; static PORT: AtomicUsize = ATOMIC_USIZE_INIT;
pub fn next_test_ip4() -> SocketAddr { pub fn next_test_ip4() -> SocketAddr {
SocketAddr::new(IpAddr::new_v4(127, 0, 0, 1), let port = PORT.fetch_add(1, Ordering::SeqCst) as u16 + base_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 { pub fn next_test_ip6() -> SocketAddr {
SocketAddr::new(IpAddr::new_v6(0, 0, 0, 0, 0, 0, 0, 1), let port = PORT.fetch_add(1, Ordering::SeqCst) as u16 + base_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 // The bots run multiple builds at the same time, and these builds

View file

@ -8,10 +8,13 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
#![unstable(feature = "udp", reason = "remaining functions have not been \
scrutinized enough to be stabilized")]
use prelude::v1::*; use prelude::v1::*;
use io::{self, Error, ErrorKind}; use io::{self, Error, ErrorKind};
use net::{ToSocketAddrs, SocketAddr, IpAddr}; use net::{ToSocketAddrs, SocketAddr};
use sys_common::net2 as net_imp; use sys_common::net2 as net_imp;
use sys_common::AsInner; use sys_common::AsInner;
@ -41,6 +44,7 @@ use sys_common::AsInner;
/// # Ok(()) /// # Ok(())
/// # } /// # }
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub struct UdpSocket(net_imp::UdpSocket); pub struct UdpSocket(net_imp::UdpSocket);
impl UdpSocket { impl UdpSocket {
@ -48,12 +52,14 @@ impl UdpSocket {
/// ///
/// Address type can be any implementor of `ToSocketAddr` trait. See its /// Address type can be any implementor of `ToSocketAddr` trait. See its
/// documentation for concrete examples. /// documentation for concrete examples.
pub fn bind<A: ToSocketAddrs + ?Sized>(addr: &A) -> io::Result<UdpSocket> { #[stable(feature = "rust1", since = "1.0.0")]
pub fn bind<A: ToSocketAddrs>(addr: A) -> io::Result<UdpSocket> {
super::each_addr(addr, net_imp::UdpSocket::bind).map(UdpSocket) super::each_addr(addr, net_imp::UdpSocket::bind).map(UdpSocket)
} }
/// Receives data from the socket. On success, returns the number of bytes /// Receives data from the socket. On success, returns the number of bytes
/// read and the address from whence the data came. /// 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)> { pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
self.0.recv_from(buf) self.0.recv_from(buf)
} }
@ -63,8 +69,9 @@ impl UdpSocket {
/// ///
/// Address type can be any implementor of `ToSocketAddrs` trait. See its /// Address type can be any implementor of `ToSocketAddrs` trait. See its
/// documentation for concrete examples. /// documentation for concrete examples.
pub fn send_to<A: ToSocketAddrs + ?Sized>(&self, buf: &[u8], addr: &A) #[stable(feature = "rust1", since = "1.0.0")]
-> io::Result<usize> { pub fn send_to<A: ToSocketAddrs>(&self, buf: &[u8], addr: A)
-> io::Result<usize> {
match try!(addr.to_socket_addrs()).next() { match try!(addr.to_socket_addrs()).next() {
Some(addr) => self.0.send_to(buf, &addr), Some(addr) => self.0.send_to(buf, &addr),
None => Err(Error::new(ErrorKind::InvalidInput, None => Err(Error::new(ErrorKind::InvalidInput,
@ -73,15 +80,24 @@ impl UdpSocket {
} }
/// Returns the socket address that this socket was created from. /// 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<SocketAddr> { pub fn socket_addr(&self) -> io::Result<SocketAddr> {
self.0.socket_addr() 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<SocketAddr> {
self.0.socket_addr()
}
/// Create a new independently owned handle to the underlying socket. /// Create a new independently owned handle to the underlying socket.
/// ///
/// The returned `UdpSocket` is a reference to the same socket that this /// The returned `UdpSocket` is a reference to the same socket that this
/// object references. Both handles will read and write the same port, and /// object references. Both handles will read and write the same port, and
/// options set on one socket will be propagated to the other. /// 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<UdpSocket> { pub fn try_clone(&self) -> io::Result<UdpSocket> {
self.0.duplicate().map(UdpSocket) self.0.duplicate().map(UdpSocket)
} }
@ -99,12 +115,12 @@ impl UdpSocket {
} }
/// Joins a multicast IP address (becomes a member of it) /// 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) self.0.join_multicast(multi)
} }
/// Leaves a multicast IP address (drops membership from it) /// 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) self.0.leave_multicast(multi)
} }
@ -151,7 +167,7 @@ mod tests {
#[cfg_attr(any(windows, target_os = "android"), ignore)] #[cfg_attr(any(windows, target_os = "android"), ignore)]
#[test] #[test]
fn bind_error() { 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) { match UdpSocket::bind(&addr) {
Ok(..) => panic!(), Ok(..) => panic!(),
Err(e) => assert_eq!(e.kind(), ErrorKind::PermissionDenied), Err(e) => assert_eq!(e.kind(), ErrorKind::PermissionDenied),

View file

@ -14,7 +14,7 @@ use ffi::CString;
use io::{self, Error, ErrorKind}; use io::{self, Error, ErrorKind};
use libc::{self, c_int, c_char, c_void, socklen_t}; use libc::{self, c_int, c_char, c_void, socklen_t};
use mem; use mem;
use net::{IpAddr, SocketAddr, Shutdown}; use net::{SocketAddr, Shutdown};
use sys::c; use sys::c;
use sys::net::{cvt, cvt_r, cvt_gai, Socket, init, wrlen_t}; use sys::net::{cvt, cvt_r, cvt_gai, Socket, init, wrlen_t};
use sys_common::{AsInner, FromInner, IntoInner}; 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 { match storage.ss_family as libc::c_int {
libc::AF_INET => { libc::AF_INET => {
assert!(len as usize >= mem::size_of::<libc::sockaddr_in>()); assert!(len as usize >= mem::size_of::<libc::sockaddr_in>());
Ok(FromInner::from_inner(unsafe { Ok(SocketAddr::V4(FromInner::from_inner(unsafe {
*(storage as *const _ as *const libc::sockaddr_in) *(storage as *const _ as *const libc::sockaddr_in)
})) })))
} }
libc::AF_INET6 => { libc::AF_INET6 => {
assert!(len as usize >= mem::size_of::<libc::sockaddr_in6>()); assert!(len as usize >= mem::size_of::<libc::sockaddr_in6>());
Ok(FromInner::from_inner(unsafe { Ok(SocketAddr::V6(FromInner::from_inner(unsafe {
*(storage as *const _ as *const libc::sockaddr_in6) *(storage as *const _ as *const libc::sockaddr_in6)
})) })))
} }
_ => { _ => {
Err(Error::new(ErrorKind::InvalidInput, "invalid argument", None)) Err(Error::new(ErrorKind::InvalidInput, "invalid argument", None))
@ -334,39 +334,39 @@ impl UdpSocket {
libc::IP_MULTICAST_LOOP, on as c_int) 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 { match *multi {
IpAddr::V4(..) => { SocketAddr::V4(..) => {
self.set_membership(multi, libc::IP_ADD_MEMBERSHIP) self.set_membership(multi, libc::IP_ADD_MEMBERSHIP)
} }
IpAddr::V6(..) => { SocketAddr::V6(..) => {
self.set_membership(multi, libc::IPV6_ADD_MEMBERSHIP) 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 { match *multi {
IpAddr::V4(..) => { SocketAddr::V4(..) => {
self.set_membership(multi, libc::IP_DROP_MEMBERSHIP) self.set_membership(multi, libc::IP_DROP_MEMBERSHIP)
} }
IpAddr::V6(..) => { SocketAddr::V6(..) => {
self.set_membership(multi, libc::IPV6_DROP_MEMBERSHIP) 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 { match *addr {
IpAddr::V4(ref addr) => { SocketAddr::V4(ref addr) => {
let mreq = libc::ip_mreq { let mreq = libc::ip_mreq {
imr_multiaddr: *addr.as_inner(), imr_multiaddr: *addr.ip().as_inner(),
// interface == INADDR_ANY // interface == INADDR_ANY
imr_interface: libc::in_addr { s_addr: 0x0 }, imr_interface: libc::in_addr { s_addr: 0x0 },
}; };
setsockopt(&self.inner, libc::IPPROTO_IP, opt, mreq) setsockopt(&self.inner, libc::IPPROTO_IP, opt, mreq)
} }
IpAddr::V6(ref addr) => { SocketAddr::V6(ref addr) => {
let mreq = libc::ip6_mreq { let mreq = libc::ip6_mreq {
ipv6mr_multiaddr: *addr.as_inner(), ipv6mr_multiaddr: *addr.ip().as_inner(),
ipv6mr_interface: 0, ipv6mr_interface: 0,
}; };
setsockopt(&self.inner, libc::IPPROTO_IPV6, opt, mreq) setsockopt(&self.inner, libc::IPPROTO_IPV6, opt, mreq)

View file

@ -15,7 +15,7 @@ use io;
use libc::{self, c_int, size_t}; use libc::{self, c_int, size_t};
use str; use str;
use sys::c; use sys::c;
use net::{SocketAddr, IpAddr}; use net::SocketAddr;
use sys::fd::FileDesc; use sys::fd::FileDesc;
use sys_common::AsInner; use sys_common::AsInner;
@ -40,9 +40,9 @@ pub fn cvt_gai(err: c_int) -> io::Result<()> {
impl Socket { impl Socket {
pub fn new(addr: &SocketAddr, ty: c_int) -> io::Result<Socket> { pub fn new(addr: &SocketAddr, ty: c_int) -> io::Result<Socket> {
let fam = match addr.ip() { let fam = match *addr {
IpAddr::V4(..) => libc::AF_INET, SocketAddr::V4(..) => libc::AF_INET,
IpAddr::V6(..) => libc::AF_INET6, SocketAddr::V6(..) => libc::AF_INET6,
}; };
unsafe { unsafe {
let fd = try!(cvt(libc::socket(fam, ty, 0))); let fd = try!(cvt(libc::socket(fam, ty, 0)));

View file

@ -14,7 +14,7 @@ use io;
use libc::consts::os::extra::INVALID_SOCKET; use libc::consts::os::extra::INVALID_SOCKET;
use libc::{self, c_int, c_void}; use libc::{self, c_int, c_void};
use mem; use mem;
use net::{SocketAddr, IpAddr}; use net::SocketAddr;
use num::{SignedInt, Int}; use num::{SignedInt, Int};
use rt; use rt;
use sync::{Once, ONCE_INIT}; use sync::{Once, ONCE_INIT};
@ -73,9 +73,9 @@ pub fn cvt_r<T: SignedInt, F>(mut f: F) -> io::Result<T> where F: FnMut() -> T {
impl Socket { impl Socket {
pub fn new(addr: &SocketAddr, ty: c_int) -> io::Result<Socket> { pub fn new(addr: &SocketAddr, ty: c_int) -> io::Result<Socket> {
let fam = match addr.ip() { let fam = match *addr {
IpAddr::V4(..) => libc::AF_INET, SocketAddr::V4(..) => libc::AF_INET,
IpAddr::V6(..) => libc::AF_INET6, SocketAddr::V6(..) => libc::AF_INET6,
}; };
match unsafe { libc::socket(fam, ty, 0) } { match unsafe { libc::socket(fam, ty, 0) } {
INVALID_SOCKET => Err(last_error()), INVALID_SOCKET => Err(last_error()),

View file

@ -25,5 +25,8 @@ fn main() {
assert_both::<net::TcpListener>(); assert_both::<net::TcpListener>();
assert_both::<net::UdpSocket>(); assert_both::<net::UdpSocket>();
assert_both::<net::SocketAddr>(); assert_both::<net::SocketAddr>();
assert_both::<net::IpAddr>(); assert_both::<net::SocketAddrV4>();
assert_both::<net::SocketAddrV6>();
assert_both::<net::Ipv4Addr>();
assert_both::<net::Ipv6Addr>();
} }