Auto merge of #23352 - alexcrichton:stabilize-net, r=aturon
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:
commit
a2572885ab
@ -20,7 +20,6 @@
|
||||
#![feature(std_misc)]
|
||||
#![feature(test)]
|
||||
#![feature(core)]
|
||||
#![feature(net)]
|
||||
#![feature(path_ext)]
|
||||
|
||||
#![deny(warnings)]
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -13,7 +13,7 @@
|
||||
//! > **NOTE**: This module is very much a work in progress and is under active
|
||||
//! > development.
|
||||
|
||||
#![unstable(feature = "net")]
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
|
||||
use prelude::v1::*;
|
||||
|
||||
@ -21,8 +21,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;
|
||||
|
||||
@ -36,23 +36,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;
|
||||
@ -69,8 +73,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() }
|
||||
@ -93,6 +99,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)
|
||||
}
|
||||
|
@ -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)),
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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>> {
|
||||
|
@ -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
|
||||
|
@ -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),
|
||||
|
@ -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)
|
||||
|
@ -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)));
|
||||
|
@ -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()),
|
||||
|
@ -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>();
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user