use crate::error::{Error,
                   Result};
pub use crate::os::system::{uname,
                            Uname};
use std::net::{IpAddr,
               UdpSocket};

static GOOGLE_DNS: &str = "8.8.8.8:53";

pub fn ip() -> Result<IpAddr> {
    let socket = UdpSocket::bind("0.0.0.0:0").map_err(Error::IpLookupFailed)?;
    socket.connect(GOOGLE_DNS).map_err(Error::IpLookupFailed)?;
    let addr = socket.local_addr().map_err(Error::IpLookupFailed)?;
    Ok(addr.ip())
}

use crate::error::{Error,
                   Result};
pub use crate::os::system::{uname,
                            Uname};
use std::{io,
          net::{IpAddr,
                Ipv4Addr,
                ToSocketAddrs,
                UdpSocket}};

const UNSPECIFIED_SOCKET_ADDR: (Ipv4Addr, u16) = (Ipv4Addr::UNSPECIFIED, 0);
const GOOGLE_DNS: &str = "8.8.8.8:53";

pub fn ip() -> Result<IpAddr> { ip_impl(GOOGLE_DNS).map_err(Error::IpLookupFailed) }

fn ip_impl(connect_addr: impl ToSocketAddrs) -> io::Result<IpAddr> {
    let socket = UdpSocket::bind(UNSPECIFIED_SOCKET_ADDR)?;
    socket.connect(connect_addr)?;
    let addr = socket.local_addr()?;
    Ok(addr.ip())
}

#[cfg(test)]
mod test {
    use super::{ip,
                ip_impl};

    #[test]
    fn ip_lookup() {
        assert!(ip_impl("an invalid socket addr").is_err());
        assert!(ip().is_ok());
    }
}

Make ip lookup more testable
Make ip lookup more testable

Signed-off-by: David McNeil <e57c3c663692ef9cceb57f3c25154b8f67832195@gmail.com>
