std::rt: Add get_host_addresses function

This is a very simplistic method for host name resolution. It converts
a host name to a vector of IP addresses. Should be enough to get started.
This commit is contained in:
Brian Anderson 2013-09-05 14:16:17 -07:00
parent c218694cec
commit 0948f54e65
4 changed files with 78 additions and 10 deletions

View File

@ -269,13 +269,7 @@ pub use self::extensions::WriterByteConversions;
pub mod file;
/// Synchronous, non-blocking network I/O.
pub mod net {
pub mod tcp;
pub mod udp;
pub mod ip;
#[cfg(unix)]
pub mod unix;
}
pub mod net;
/// Readers and Writers for memory buffers and strings.
pub mod mem;

View File

@ -8,14 +8,55 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use option::{Option, Some, None};
use result::{Ok, Err};
use rt::io::io_error;
use rt::io::net::ip::IpAddr;
use rt::rtio::{IoFactory, IoFactoryObject};
use rt::local::Local;
fn get_host_addresses(host: &str) -> Option<~[IpAddr]> {
pub mod tcp;
pub mod udp;
pub mod ip;
#[cfg(unix)]
pub mod unix;
/// Simplistic name resolution
pub fn get_host_addresses(host: &str) -> Option<~[IpAddr]> {
/*!
* Get the IP addresses for a given host name.
*
* Raises io_error on failure.
*/
fail!()
let ipaddrs = unsafe {
let io: *mut IoFactoryObject = Local::unsafe_borrow();
(*io).get_host_addresses(host)
};
match ipaddrs {
Ok(i) => Some(i),
Err(ioerr) => {
io_error::cond.raise(ioerr);
None
}
}
}
#[cfg(test)]
mod test {
use option::Some;
use rt::io::net::ip::Ipv4Addr;
use super::*;
#[test]
fn dns_smoke_test() {
let ipaddrs = get_host_addresses("localhost").unwrap();
let mut found_local = false;
let local_addr = &Ipv4Addr(127, 0, 0, 1);
for addr in ipaddrs.iter() {
found_local = found_local || addr == local_addr;
}
assert!(found_local);
}
}

View File

@ -73,6 +73,7 @@ pub trait IoFactory {
fn fs_open<P: PathLike>(&mut self, path: &P, fm: FileMode, fa: FileAccess)
-> Result<~RtioFileStream, IoError>;
fn fs_unlink<P: PathLike>(&mut self, path: &P) -> Result<(), IoError>;
fn get_host_addresses(&mut self, host: &str) -> Result<~[IpAddr], IoError>;
}
pub trait RtioTcpListener : RtioSocket {

View File

@ -29,7 +29,8 @@ use rt::tube::Tube;
use rt::task::SchedHome;
use rt::uv::*;
use rt::uv::idle::IdleWatcher;
use rt::uv::net::{UvIpv4SocketAddr, UvIpv6SocketAddr};
use rt::uv::net::{UvIpv4SocketAddr, UvIpv6SocketAddr, accum_sockaddrs};
use rt::uv::addrinfo::GetAddrInfoRequest;
use unstable::sync::Exclusive;
use super::super::io::support::PathLike;
use libc::{lseek, off_t, O_CREAT, O_APPEND, O_TRUNC, O_RDWR, O_RDONLY, O_WRONLY,
@ -596,6 +597,37 @@ impl IoFactory for UvIoFactory {
assert!(!result_cell.is_empty());
return result_cell.take();
}
fn get_host_addresses(&mut self, host: &str) -> Result<~[IpAddr], IoError> {
let result_cell = Cell::new_empty();
let result_cell_ptr: *Cell<Result<~[IpAddr], IoError>> = &result_cell;
let host_ptr: *&str = &host;
let addrinfo_req = GetAddrInfoRequest::new();
let addrinfo_req_cell = Cell::new(addrinfo_req);
do task::unkillable { // FIXME(#8674)
let scheduler: ~Scheduler = Local::take();
do scheduler.deschedule_running_task_and_then |_, task| {
let task_cell = Cell::new(task);
let mut addrinfo_req = addrinfo_req_cell.take();
unsafe {
do addrinfo_req.getaddrinfo(self.uv_loop(),
Some(*host_ptr),
None, None) |_, addrinfo, err| {
let res = match err {
None => Ok(accum_sockaddrs(addrinfo).map(|addr| addr.ip.clone())),
Some(err) => Err(uv_error_to_io_error(err))
};
(*result_cell_ptr).put_back(res);
let scheduler: ~Scheduler = Local::take();
scheduler.resume_blocked_task_immediately(task_cell.take());
}
}
}
}
addrinfo_req.delete();
assert!(!result_cell.is_empty());
return result_cell.take();
}
}
pub struct UvTcpListener {