diff --git a/src/libstd/net/addr.rs b/src/libstd/net/addr.rs index e8187dc2c4027..dafca974bec0e 100644 --- a/src/libstd/net/addr.rs +++ b/src/libstd/net/addr.rs @@ -15,7 +15,7 @@ use hash; use io; use libc::{self, socklen_t, sa_family_t}; use mem; -use net::{lookup_host, ntoh, hton, Ipv4Addr, Ipv6Addr}; +use net::{lookup_host, ntoh, hton, IpAddr, Ipv4Addr, Ipv6Addr}; use option; use sys_common::{FromInner, AsInner, IntoInner}; use vec; @@ -47,6 +47,15 @@ pub struct SocketAddrV4 { inner: libc::sockaddr_in } pub struct SocketAddrV6 { inner: libc::sockaddr_in6 } impl SocketAddr { + /// Gets the IP address associated with this socket address. + #[unstable(feature = "ip_addr", reason = "recent addition")] + pub fn ip(&self) -> IpAddr { + match *self { + SocketAddr::V4(ref a) => IpAddr::V4(*a.ip()), + SocketAddr::V6(ref a) => IpAddr::V6(*a.ip()), + } + } + /// Gets the port number associated with this socket address #[stable(feature = "rust1", since = "1.0.0")] pub fn port(&self) -> u16 { @@ -333,6 +342,18 @@ impl ToSocketAddrs for SocketAddrV6 { } } +#[stable(feature = "rust1", since = "1.0.0")] +impl ToSocketAddrs for (IpAddr, u16) { + type Iter = option::IntoIter<SocketAddr>; + fn to_socket_addrs(&self) -> io::Result<option::IntoIter<SocketAddr>> { + let (ip, port) = *self; + match ip { + IpAddr::V4(ref a) => (*a, port).to_socket_addrs(), + IpAddr::V6(ref a) => (*a, port).to_socket_addrs(), + } + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl ToSocketAddrs for (Ipv4Addr, u16) { type Iter = option::IntoIter<SocketAddr>; diff --git a/src/libstd/net/ip.rs b/src/libstd/net/ip.rs index d737ad17ff8ec..c8b1928747705 100644 --- a/src/libstd/net/ip.rs +++ b/src/libstd/net/ip.rs @@ -21,6 +21,16 @@ use libc; use sys_common::{AsInner, FromInner}; use net::{hton, ntoh}; +/// An IP address, either a IPv4 or IPv6 address. +#[unstable(feature = "ip_addr", reason = "recent addition")] +#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash, PartialOrd, Ord)] +pub enum IpAddr { + /// Representation of an IPv4 address. + V4(Ipv4Addr), + /// Representation of an IPv6 address. + V6(Ipv6Addr), +} + /// Representation of an IPv4 address. #[derive(Copy)] #[stable(feature = "rust1", since = "1.0.0")] @@ -139,6 +149,16 @@ impl Ipv4Addr { } +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Display for IpAddr { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + match *self { + IpAddr::V4(ref a) => a.fmt(fmt), + IpAddr::V6(ref a) => a.fmt(fmt), + } + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl fmt::Display for Ipv4Addr { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { diff --git a/src/libstd/net/mod.rs b/src/libstd/net/mod.rs index 48b3247f2127a..7f51b1cba3fe7 100644 --- a/src/libstd/net/mod.rs +++ b/src/libstd/net/mod.rs @@ -21,7 +21,7 @@ use io::{self, Error, ErrorKind}; use num::Int; use sys_common::net2 as net_imp; -pub use self::ip::{Ipv4Addr, Ipv6Addr, Ipv6MulticastScope}; +pub use self::ip::{IpAddr, Ipv4Addr, Ipv6Addr, Ipv6MulticastScope}; pub use self::addr::{SocketAddr, SocketAddrV4, SocketAddrV6, ToSocketAddrs}; pub use self::tcp::{TcpStream, TcpListener}; pub use self::udp::UdpSocket; @@ -74,10 +74,14 @@ fn each_addr<A: ToSocketAddrs, F, T>(addr: A, mut f: F) -> io::Result<T> } /// An iterator over `SocketAddr` values returned from a host lookup operation. -#[stable(feature = "rust1", since = "1.0.0")] +#[unstable(feature = "lookup_host", reason = "unsure about the returned \ + iterator and returning socket \ + addresses")] pub struct LookupHost(net_imp::LookupHost); -#[stable(feature = "rust1", since = "1.0.0")] +#[unstable(feature = "lookup_host", reason = "unsure about the returned \ + iterator and returning socket \ + addresses")] impl Iterator for LookupHost { type Item = io::Result<SocketAddr>; fn next(&mut self) -> Option<io::Result<SocketAddr>> { self.0.next() } @@ -91,7 +95,7 @@ impl Iterator for LookupHost { /// # Examples /// /// ```no_run -/// # #![feature(net)] +/// # #![feature(lookup_host)] /// use std::net; /// /// # fn foo() -> std::io::Result<()> { @@ -101,7 +105,9 @@ impl Iterator for LookupHost { /// # Ok(()) /// # } /// ``` -#[stable(feature = "rust1", since = "1.0.0")] +#[unstable(feature = "lookup_host", reason = "unsure about the returned \ + iterator and returning socket \ + addresses")] pub fn lookup_host(host: &str) -> io::Result<LookupHost> { net_imp::lookup_host(host).map(LookupHost) } diff --git a/src/libstd/net/udp.rs b/src/libstd/net/udp.rs index e593bbe8e489b..811511149628e 100644 --- a/src/libstd/net/udp.rs +++ b/src/libstd/net/udp.rs @@ -14,7 +14,7 @@ use prelude::v1::*; use io::{self, Error, ErrorKind}; -use net::{ToSocketAddrs, SocketAddr}; +use net::{ToSocketAddrs, SocketAddr, IpAddr}; use sys_common::net2 as net_imp; use sys_common::AsInner; @@ -116,12 +116,12 @@ impl UdpSocket { } /// Joins a multicast IP address (becomes a member of it) - pub fn join_multicast(&self, multi: &SocketAddr) -> io::Result<()> { + pub fn join_multicast(&self, multi: &IpAddr) -> io::Result<()> { self.0.join_multicast(multi) } /// Leaves a multicast IP address (drops membership from it) - pub fn leave_multicast(&self, multi: &SocketAddr) -> io::Result<()> { + pub fn leave_multicast(&self, multi: &IpAddr) -> io::Result<()> { self.0.leave_multicast(multi) } diff --git a/src/libstd/sys/common/net2.rs b/src/libstd/sys/common/net2.rs index 25aeab1b4ff74..e213a86644fe1 100644 --- a/src/libstd/sys/common/net2.rs +++ b/src/libstd/sys/common/net2.rs @@ -14,7 +14,7 @@ use ffi::CString; use io::{self, Error, ErrorKind}; use libc::{self, c_int, c_char, c_void, socklen_t}; use mem; -use net::{SocketAddr, Shutdown}; +use net::{SocketAddr, Shutdown, IpAddr}; use sys::c; use sys::net::{cvt, cvt_r, cvt_gai, Socket, init, wrlen_t}; use sys_common::{AsInner, FromInner, IntoInner}; @@ -334,39 +334,39 @@ impl UdpSocket { libc::IP_MULTICAST_LOOP, on as c_int) } - pub fn join_multicast(&self, multi: &SocketAddr) -> io::Result<()> { + pub fn join_multicast(&self, multi: &IpAddr) -> io::Result<()> { match *multi { - SocketAddr::V4(..) => { + IpAddr::V4(..) => { self.set_membership(multi, libc::IP_ADD_MEMBERSHIP) } - SocketAddr::V6(..) => { + IpAddr::V6(..) => { self.set_membership(multi, libc::IPV6_ADD_MEMBERSHIP) } } } - pub fn leave_multicast(&self, multi: &SocketAddr) -> io::Result<()> { + pub fn leave_multicast(&self, multi: &IpAddr) -> io::Result<()> { match *multi { - SocketAddr::V4(..) => { + IpAddr::V4(..) => { self.set_membership(multi, libc::IP_DROP_MEMBERSHIP) } - SocketAddr::V6(..) => { + IpAddr::V6(..) => { self.set_membership(multi, libc::IPV6_DROP_MEMBERSHIP) } } } - fn set_membership(&self, addr: &SocketAddr, opt: c_int) -> io::Result<()> { + fn set_membership(&self, addr: &IpAddr, opt: c_int) -> io::Result<()> { match *addr { - SocketAddr::V4(ref addr) => { + IpAddr::V4(ref addr) => { let mreq = libc::ip_mreq { - imr_multiaddr: *addr.ip().as_inner(), + imr_multiaddr: *addr.as_inner(), // interface == INADDR_ANY imr_interface: libc::in_addr { s_addr: 0x0 }, }; setsockopt(&self.inner, libc::IPPROTO_IP, opt, mreq) } - SocketAddr::V6(ref addr) => { + IpAddr::V6(ref addr) => { let mreq = libc::ip6_mreq { - ipv6mr_multiaddr: *addr.ip().as_inner(), + ipv6mr_multiaddr: *addr.as_inner(), ipv6mr_interface: 0, }; setsockopt(&self.inner, libc::IPPROTO_IPV6, opt, mreq)