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(test)]
#![feature(core)]
#![feature(net)]
#![feature(path_ext)]
#![deny(warnings)]

View File

@ -15,70 +15,137 @@ 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) }
}
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) {
match self.repr {
Repr::V4(ref mut sa) => sa.sin_port = hton(port),
Repr::V6(ref mut sa) => sa.sin6_port = hton(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<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")]
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()),
match *self {
SocketAddr::V4(ref a) => a.fmt(f),
SocketAddr::V6(ref a) => a.fmt(f),
}
}
}
impl FromInner<libc::sockaddr_in> for SocketAddr {
fn from_inner(addr: libc::sockaddr_in) -> SocketAddr {
SocketAddr { repr: Repr::V4(addr) }
#[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())
}
}
impl FromInner<libc::sockaddr_in6> for SocketAddr {
fn from_inner(addr: libc::sockaddr_in6) -> SocketAddr {
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 {
#[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 }
}
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::Display for SocketAddrV6 {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "[{}]:{}", self.ip(), self.port())
}
}
impl Eq for Repr {}
#[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) {
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<H: hash::Hasher>(&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<Item=SocketAddr>;
/// 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<Self::Iter>;
}
#[stable(feature = "rust1", since = "1.0.0")]
impl ToSocketAddrs for SocketAddr {
type Iter = 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>;
fn to_socket_addrs(&self) -> io::Result<option::IntoIter<SocketAddr>> {
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>> {
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<SocketAddr>;
fn to_socket_addrs(&self) -> io::Result<vec::IntoIter<SocketAddr>> {
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::<Ipv4Addr>() {
let addr = SocketAddrV4::new(addr, port);
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)
@ -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<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());
// 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);
// too short
let none: Option<IpAddr> = "255.0.0".parse().ok();
let none: Option<Ipv4Addr> = "255.0.0".parse().ok();
assert_eq!(None, none);
// 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);
// 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);
}
@ -347,19 +464,19 @@ mod tests {
"2a02:6b8::11:11".parse());
// too long group
let none: Option<IpAddr> = "::00000".parse().ok();
let none: Option<Ipv6Addr> = "::00000".parse().ok();
assert_eq!(None, none);
// 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);
// 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);
// 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);
// 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);
}
@ -375,24 +492,24 @@ mod tests {
"2001:db8:122:c000:2:2100:192.0.2.33".parse());
// 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);
// 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);
// 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);
}
#[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<SocketAddr> = "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));
}

View File

@ -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<Ordering> {
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<Ipv4Addr> {
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<Ordering> {
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)

View File

@ -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: Int>(i: I) -> I { i.to_be() }
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>
{
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.
#[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<SocketAddr>;
fn next(&mut self) -> Option<io::Result<SocketAddr>> { 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<LookupHost> {
net_imp::lookup_host(host).map(LookupHost)
}

View File

@ -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::<IpAddr, char, u16, _, _, _>(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<IpAddr, ParseError> {
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)),
}
})
}
}

View File

@ -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<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)
}
/// 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> {
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<SocketAddr> {
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.
///
/// 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<TcpStream> {
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<usize> { self.0.read(buf) }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl Write for TcpStream {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> { 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<usize> { 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<usize> { 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<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)
}
/// 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> {
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<TcpListener> {
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<TcpStream>;
fn next(&mut self) -> Option<io::Result<TcpStream>> {

View File

@ -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

View File

@ -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<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)
}
/// 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<A: ToSocketAddrs + ?Sized>(&self, buf: &[u8], addr: &A)
-> io::Result<usize> {
#[stable(feature = "rust1", since = "1.0.0")]
pub fn send_to<A: ToSocketAddrs>(&self, buf: &[u8], addr: A)
-> io::Result<usize> {
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<SocketAddr> {
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.
///
/// 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<UdpSocket> {
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),

View File

@ -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::<libc::sockaddr_in>());
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::<libc::sockaddr_in6>());
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)

View File

@ -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<Socket> {
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)));

View File

@ -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<T: SignedInt, F>(mut f: F) -> io::Result<T> where F: FnMut() -> T {
impl Socket {
pub fn new(addr: &SocketAddr, ty: c_int) -> io::Result<Socket> {
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()),

View File

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