about summary refs log tree commit diff
path: root/src/libstd/net/addr.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/libstd/net/addr.rs')
-rw-r--r--src/libstd/net/addr.rs395
1 files changed, 260 insertions, 135 deletions
diff --git a/src/libstd/net/addr.rs b/src/libstd/net/addr.rs
index 101aae3eb24..702f81db8e2 100644
--- a/src/libstd/net/addr.rs
+++ b/src/libstd/net/addr.rs
@@ -15,150 +15,220 @@ use hash;
 use io;
 use libc::{self, socklen_t, sa_family_t};
 use mem;
-use net::{IpAddr, lookup_host, ntoh, hton};
+use net::{lookup_host, ntoh, hton, Ipv4Addr, Ipv6Addr};
 use option;
 use sys_common::{FromInner, AsInner, IntoInner};
 use vec;
 
-/// Representation of a socket address for networking applications
+/// Representation of a socket address for networking applications.
 ///
-/// A socket address consists of at least an (ip, port) pair and may also
-/// contain other information depending on the protocol.
-#[derive(Copy, Clone, PartialEq, Eq, Hash)]
-pub struct SocketAddr {
-    repr: Repr,
+/// A socket address can either represent the IPv4 or IPv6 protocol and is
+/// paired with at least a port number as well. Each protocol may have more
+/// specific information about the address available to it as well.
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
+#[stable(feature = "rust1", since = "1.0.0")]
+pub enum SocketAddr {
+    /// An IPv4 socket address which is a (ip, port) combination.
+    #[stable(feature = "rust1", since = "1.0.0")]
+    V4(SocketAddrV4),
+    /// An IPv6 socket address
+    #[stable(feature = "rust1", since = "1.0.0")]
+    V6(SocketAddrV6),
 }
 
+/// An IPv4 socket address which is a (ip, port) combination.
 #[derive(Copy)]
-enum Repr {
-    V4(libc::sockaddr_in),
-    V6(libc::sockaddr_in6),
-}
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct SocketAddrV4 { inner: libc::sockaddr_in }
+
+/// An IPv6 socket address
+#[derive(Copy)]
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct SocketAddrV6 { inner: libc::sockaddr_in6 }
 
 impl SocketAddr {
+    /// Gets the port number associated with this socket address
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn port(&self) -> u16 {
+        match *self {
+            SocketAddr::V4(ref a) => a.port(),
+            SocketAddr::V6(ref a) => a.port(),
+        }
+    }
+}
+
+impl SocketAddrV4 {
     /// Creates a new socket address from the (ip, port) pair.
-    pub fn new(ip: IpAddr, port: u16) -> SocketAddr {
-        let repr = match ip {
-            IpAddr::V4(ref ip) => {
-                Repr::V4(libc::sockaddr_in {
-                    sin_family: libc::AF_INET as sa_family_t,
-                    sin_port: hton(port),
-                    sin_addr: *ip.as_inner(),
-                    .. unsafe { mem::zeroed() }
-                })
-            }
-            IpAddr::V6(ref ip) => {
-                Repr::V6(libc::sockaddr_in6 {
-                    sin6_family: libc::AF_INET6 as sa_family_t,
-                    sin6_port: hton(port),
-                    sin6_addr: *ip.as_inner(),
-                    .. unsafe { mem::zeroed() }
-                })
-            }
-        };
-        SocketAddr { repr: repr }
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn new(ip: Ipv4Addr, port: u16) -> SocketAddrV4 {
+        SocketAddrV4 {
+            inner: libc::sockaddr_in {
+                sin_family: libc::AF_INET as sa_family_t,
+                sin_port: hton(port),
+                sin_addr: *ip.as_inner(),
+                .. unsafe { mem::zeroed() }
+            },
+        }
     }
 
     /// Gets the IP address associated with this socket address.
-    pub fn ip(&self) -> IpAddr {
-        match self.repr {
-            Repr::V4(ref sa) => IpAddr::V4(FromInner::from_inner(sa.sin_addr)),
-            Repr::V6(ref sa) => IpAddr::V6(FromInner::from_inner(sa.sin6_addr)),
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn ip(&self) -> &Ipv4Addr {
+        unsafe {
+            &*(&self.inner.sin_addr as *const libc::in_addr as *const Ipv4Addr)
         }
     }
 
     /// Gets the port number associated with this socket address
-    pub fn port(&self) -> u16 {
-        match self.repr {
-            Repr::V4(ref sa) => ntoh(sa.sin_port),
-            Repr::V6(ref sa) => ntoh(sa.sin6_port),
-        }
-    }
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn port(&self) -> u16 { ntoh(self.inner.sin_port) }
+}
 
-    fn set_port(&mut self, port: u16) {
-        match self.repr {
-            Repr::V4(ref mut sa) => sa.sin_port = hton(port),
-            Repr::V6(ref mut sa) => sa.sin6_port = hton(port),
+impl SocketAddrV6 {
+    /// Creates a new socket address from the ip/port/flowinfo/scope_id
+    /// components.
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn new(ip: Ipv6Addr, port: u16, flowinfo: u32, scope_id: u32)
+               -> SocketAddrV6 {
+        SocketAddrV6 {
+            inner: libc::sockaddr_in6 {
+                sin6_family: libc::AF_INET6 as sa_family_t,
+                sin6_port: hton(port),
+                sin6_addr: *ip.as_inner(),
+                sin6_flowinfo: hton(flowinfo),
+                sin6_scope_id: hton(scope_id),
+                .. unsafe { mem::zeroed() }
+            },
         }
     }
-}
 
-#[stable(feature = "rust1", since = "1.0.0")]
-impl fmt::Display for SocketAddr {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        match self.repr {
-            Repr::V4(_) => write!(f, "{}:{}", self.ip(), self.port()),
-            Repr::V6(_) => write!(f, "[{}]:{}", self.ip(), self.port()),
+    /// Gets the IP address associated with this socket address.
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn ip(&self) -> &Ipv6Addr {
+        unsafe {
+            &*(&self.inner.sin6_addr as *const libc::in6_addr as *const Ipv6Addr)
         }
     }
+
+    /// Gets the port number associated with this socket address
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn port(&self) -> u16 { ntoh(self.inner.sin6_port) }
+
+    /// Gets scope ID associated with this address, corresponding to the
+    /// `sin6_flowinfo` field in C.
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn flowinfo(&self) -> u32 { ntoh(self.inner.sin6_flowinfo) }
+
+    /// Gets scope ID associated with this address, corresponding to the
+    /// `sin6_scope_id` field in C.
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn scope_id(&self) -> u32 { ntoh(self.inner.sin6_scope_id) }
 }
 
-impl FromInner<libc::sockaddr_in> for SocketAddr {
-    fn from_inner(addr: libc::sockaddr_in) -> SocketAddr {
-        SocketAddr { repr: Repr::V4(addr) }
+impl FromInner<libc::sockaddr_in> for SocketAddrV4 {
+    fn from_inner(addr: libc::sockaddr_in) -> SocketAddrV4 {
+        SocketAddrV4 { inner: addr }
     }
 }
 
-impl FromInner<libc::sockaddr_in6> for SocketAddr {
-    fn from_inner(addr: libc::sockaddr_in6) -> SocketAddr {
-        SocketAddr { repr: Repr::V6(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.repr {
-            Repr::V4(ref a) => {
+        match *self {
+            SocketAddr::V4(ref a) => {
                 (a as *const _ as *const _, mem::size_of_val(a) as socklen_t)
             }
-            Repr::V6(ref a) => {
+            SocketAddr::V6(ref a) => {
                 (a as *const _ as *const _, mem::size_of_val(a) as socklen_t)
             }
         }
     }
 }
 
-impl fmt::Debug for SocketAddr {
+#[stable(feature = "rust1", since = "1.0.0")]
+impl fmt::Display for SocketAddr {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        match *self {
+            SocketAddr::V4(ref a) => a.fmt(f),
+            SocketAddr::V6(ref a) => a.fmt(f),
+        }
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl fmt::Display for SocketAddrV4 {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "{}:{}", self.ip(), self.port())
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl fmt::Debug for SocketAddrV4 {
     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
         fmt::Display::fmt(self, fmt)
     }
 }
 
-impl Clone for Repr {
-    fn clone(&self) -> Repr { *self }
+#[stable(feature = "rust1", since = "1.0.0")]
+impl fmt::Display for SocketAddrV6 {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "[{}]:{}", self.ip(), self.port())
+    }
 }
 
-impl PartialEq for Repr {
-    fn eq(&self, other: &Repr) -> bool {
-        match (*self, *other) {
-            (Repr::V4(ref a), Repr::V4(ref b)) => {
-                a.sin_port == b.sin_port &&
-                    a.sin_addr.s_addr == b.sin_addr.s_addr
-            }
-            (Repr::V6(ref a), Repr::V6(ref b)) => {
-                a.sin6_port == b.sin6_port &&
-                    a.sin6_addr.s6_addr == b.sin6_addr.s6_addr &&
-                    a.sin6_flowinfo == b.sin6_flowinfo &&
-                    a.sin6_scope_id == b.sin6_scope_id
-            }
-            _ => false,
-        }
+#[stable(feature = "rust1", since = "1.0.0")]
+impl fmt::Debug for SocketAddrV6 {
+    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+        fmt::Display::fmt(self, fmt)
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl Clone for SocketAddrV4 {
+    fn clone(&self) -> SocketAddrV4 { *self }
+}
+#[stable(feature = "rust1", since = "1.0.0")]
+impl Clone for SocketAddrV6 {
+    fn clone(&self) -> SocketAddrV6 { *self }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl PartialEq for SocketAddrV4 {
+    fn eq(&self, other: &SocketAddrV4) -> bool {
+        self.inner.sin_port == other.inner.sin_port &&
+            self.inner.sin_addr.s_addr == other.inner.sin_addr.s_addr
     }
 }
-impl Eq for Repr {}
+#[stable(feature = "rust1", since = "1.0.0")]
+impl PartialEq for SocketAddrV6 {
+    fn eq(&self, other: &SocketAddrV6) -> bool {
+        self.inner.sin6_port == other.inner.sin6_port &&
+            self.inner.sin6_addr.s6_addr == other.inner.sin6_addr.s6_addr &&
+            self.inner.sin6_flowinfo == other.inner.sin6_flowinfo &&
+            self.inner.sin6_scope_id == other.inner.sin6_scope_id
+    }
+}
+#[stable(feature = "rust1", since = "1.0.0")]
+impl Eq for SocketAddrV4 {}
+#[stable(feature = "rust1", since = "1.0.0")]
+impl Eq for SocketAddrV6 {}
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl hash::Hash for Repr {
+impl hash::Hash for SocketAddrV4 {
     fn hash<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;
+        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;
-        Ok(Some(SocketAddr::new(ip, port)).into_iter())
+        SocketAddrV6::new(ip, port, 0, 0).to_socket_addrs()
     }
 }
 
 fn resolve_socket_addr(s: &str, p: u16) -> io::Result<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));
     }