diff --git a/src/libstd/io/net/mod.rs b/src/libstd/io/net/mod.rs index 68577e192d2..61cefa6f208 100644 --- a/src/libstd/io/net/mod.rs +++ b/src/libstd/io/net/mod.rs @@ -10,11 +10,11 @@ //! Networking I/O -use io::{IoError, InvalidInput}; +use io::{IoError, IoResult, InvalidInput}; use option::None; use result::{Result, Ok, Err}; use rt::rtio; -use self::ip::{Ipv4Addr, Ipv6Addr, IpAddr, ToSocketAddr}; +use self::ip::{Ipv4Addr, Ipv6Addr, IpAddr, SocketAddr, ToSocketAddr}; pub use self::addrinfo::get_host_addresses; @@ -42,7 +42,7 @@ fn from_rtio(ip: rtio::IpAddr) -> IpAddr { } } -fn with_addresses( +fn with_addresses_io( addr: A, action: |&mut rtio::IoFactory, rtio::SocketAddr| -> Result ) -> Result { @@ -63,3 +63,22 @@ fn with_addresses( } Err(err) } + +fn with_addresses(addr: A, action: |SocketAddr| -> IoResult) + -> IoResult { + const DEFAULT_ERROR: IoError = IoError { + kind: InvalidInput, + desc: "no addresses found for hostname", + detail: None + }; + + let addresses = try!(addr.to_socket_addr_all()); + let mut err = DEFAULT_ERROR; + for addr in addresses.into_iter() { + match action(addr) { + Ok(r) => return Ok(r), + Err(e) => err = e + } + } + Err(err) +} diff --git a/src/libstd/io/net/tcp.rs b/src/libstd/io/net/tcp.rs index 5dffc45bcd8..ee5f56469ad 100644 --- a/src/libstd/io/net/tcp.rs +++ b/src/libstd/io/net/tcp.rs @@ -67,7 +67,7 @@ impl TcpStream { /// trait can be supplied for the address; see this trait documentation for /// concrete examples. pub fn connect(addr: A) -> IoResult { - super::with_addresses(addr, |io, addr| io.tcp_connect(addr, None).map(TcpStream::new)) + super::with_addresses_io(addr, |io, addr| io.tcp_connect(addr, None).map(TcpStream::new)) } /// Creates a TCP connection to a remote socket address, timing out after @@ -89,7 +89,7 @@ impl TcpStream { return Err(standard_error(TimedOut)); } - super::with_addresses(addr, |io, addr| + super::with_addresses_io(addr, |io, addr| io.tcp_connect(addr, Some(timeout.num_milliseconds() as u64)).map(TcpStream::new) ) } @@ -324,7 +324,7 @@ impl TcpListener { /// to this listener. The port allocated can be queried via the /// `socket_name` function. pub fn bind(addr: A) -> IoResult { - super::with_addresses(addr, |io, addr| io.tcp_bind(addr).map(|l| TcpListener { obj: l })) + super::with_addresses_io(addr, |io, addr| io.tcp_bind(addr).map(|l| TcpListener { obj: l })) } /// Returns the local socket address of this listener. diff --git a/src/libstd/io/net/udp.rs b/src/libstd/io/net/udp.rs index ad9ed090a5b..62eeba7cbd2 100644 --- a/src/libstd/io/net/udp.rs +++ b/src/libstd/io/net/udp.rs @@ -16,7 +16,7 @@ //! datagram protocol. use clone::Clone; -use io::net::ip::{SocketAddr, IpAddr}; +use io::net::ip::{SocketAddr, IpAddr, ToSocketAddr}; use io::{Reader, Writer, IoResult, IoError}; use kinds::Send; use boxed::Box; @@ -65,18 +65,13 @@ pub struct UdpSocket { impl UdpSocket { /// Creates a UDP socket from the given socket address. - pub fn bind(addr: SocketAddr) -> IoResult { - let SocketAddr { ip, port } = addr; - LocalIo::maybe_raise(|io| { - let addr = rtio::SocketAddr { ip: super::to_rtio(ip), port: port }; - io.udp_bind(addr).map(|s| UdpSocket { obj: s }) - }).map_err(IoError::from_rtio_error) + pub fn bind(addr: A) -> IoResult { + super::with_addresses_io(addr, |io, addr| io.udp_bind(addr).map(|s| UdpSocket { obj: s })) } /// Receives data from the socket. On success, returns the number of bytes /// read and the address from whence the data came. - pub fn recv_from(&mut self, buf: &mut [u8]) - -> IoResult<(uint, SocketAddr)> { + pub fn recv_from(&mut self, buf: &mut [u8]) -> IoResult<(uint, SocketAddr)> { match self.obj.recv_from(buf) { Ok((amt, rtio::SocketAddr { ip, port })) => { Ok((amt, SocketAddr { ip: super::from_rtio(ip), port: port })) @@ -87,11 +82,11 @@ impl UdpSocket { /// Sends data on the socket to the given address. Returns nothing on /// success. - pub fn send_to(&mut self, buf: &[u8], dst: SocketAddr) -> IoResult<()> { - self.obj.send_to(buf, rtio::SocketAddr { - ip: super::to_rtio(dst.ip), - port: dst.port, - }).map_err(IoError::from_rtio_error) + pub fn send_to(&mut self, buf: &[u8], addr: A) -> IoResult<()> { + super::with_addresses(addr, |addr| self.obj.send_to(buf, rtio::SocketAddr { + ip: super::to_rtio(addr.ip), + port: addr.port, + }).map_err(IoError::from_rtio_error)) } /// Creates a `UdpStream`, which allows use of the `Reader` and `Writer`