-
Notifications
You must be signed in to change notification settings - Fork 13.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
auto merge of #9000 : brson/rust/dns, r=anasazi
This exposes a very simple function for resolving host names. There's a lot more that needs to be done, but this is probably enough for servo to get started connecting to real websites again.
- Loading branch information
Showing
11 changed files
with
388 additions
and
15 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT | ||
// file at the top-level directory of this distribution and at | ||
// http://rust-lang.org/COPYRIGHT. | ||
// | ||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | ||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | ||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | ||
// 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; | ||
|
||
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. | ||
*/ | ||
|
||
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); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,178 @@ | ||
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT | ||
// file at the top-level directory of this distribution and at | ||
// http://rust-lang.org/COPYRIGHT. | ||
// | ||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | ||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | ||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | ||
// option. This file may not be copied, modified, or distributed | ||
// except according to those terms. | ||
|
||
use cast::transmute; | ||
use cell::Cell; | ||
use c_str::ToCStr; | ||
use libc::{c_int, c_void}; | ||
use option::{Option, Some, None}; | ||
use ptr::null; | ||
use rt::uv::uvll; | ||
use rt::uv::uvll::UV_GETADDRINFO; | ||
use rt::uv::{Loop, UvError, NativeHandle}; | ||
use rt::uv::status_to_maybe_uv_error_with_loop; | ||
use rt::uv::net::UvAddrInfo; | ||
|
||
type GetAddrInfoCallback = ~fn(GetAddrInfoRequest, &UvAddrInfo, Option<UvError>); | ||
|
||
pub struct GetAddrInfoRequest(*uvll::uv_getaddrinfo_t); | ||
|
||
pub struct RequestData { | ||
getaddrinfo_cb: Option<GetAddrInfoCallback>, | ||
} | ||
|
||
impl GetAddrInfoRequest { | ||
pub fn new() -> GetAddrInfoRequest { | ||
let req = unsafe { uvll::malloc_req(UV_GETADDRINFO) }; | ||
assert!(req.is_not_null()); | ||
let mut req: GetAddrInfoRequest = NativeHandle::from_native_handle(req); | ||
req.install_req_data(); | ||
return req; | ||
} | ||
|
||
pub fn getaddrinfo(&mut self, loop_: &Loop, node: Option<&str>, | ||
service: Option<&str>, hints: Option<UvAddrInfo>, | ||
cb: GetAddrInfoCallback) { | ||
|
||
assert!(node.is_some() || service.is_some()); | ||
|
||
let (c_node, c_node_ptr) = match node { | ||
Some(n) => { | ||
let c_node = n.to_c_str(); | ||
let c_node_ptr = c_node.with_ref(|r| r); | ||
(Some(c_node), c_node_ptr) | ||
} | ||
None => (None, null()) | ||
}; | ||
|
||
let (c_service, c_service_ptr) = match service { | ||
Some(s) => { | ||
let c_service = s.to_c_str(); | ||
let c_service_ptr = c_service.with_ref(|r| r); | ||
(Some(c_service), c_service_ptr) | ||
} | ||
None => (None, null()) | ||
}; | ||
|
||
let cb = Cell::new(cb); | ||
let wrapper_cb: GetAddrInfoCallback = |req, addrinfo, err| { | ||
// Capture some heap values that need to stay alive for the | ||
// getaddrinfo call | ||
let _ = &c_node; | ||
let _ = &c_service; | ||
|
||
let cb = cb.take(); | ||
cb(req, addrinfo, err) | ||
}; | ||
|
||
// XXX: Implement hints | ||
assert!(hints.is_none()); | ||
|
||
self.get_req_data().getaddrinfo_cb = Some(wrapper_cb); | ||
|
||
unsafe { | ||
assert!(0 == uvll::getaddrinfo(loop_.native_handle(), | ||
self.native_handle(), | ||
getaddrinfo_cb, | ||
c_node_ptr, | ||
c_service_ptr, | ||
null())); | ||
} | ||
|
||
extern "C" fn getaddrinfo_cb(req: *uvll::uv_getaddrinfo_t, | ||
status: c_int, | ||
res: *uvll::addrinfo) { | ||
let mut req: GetAddrInfoRequest = NativeHandle::from_native_handle(req); | ||
let loop_ = req.get_loop(); | ||
let err = status_to_maybe_uv_error_with_loop(loop_.native_handle(), status); | ||
let addrinfo = UvAddrInfo(res); | ||
let data = req.get_req_data(); | ||
(*data.getaddrinfo_cb.get_ref())(req, &addrinfo, err); | ||
unsafe { | ||
uvll::freeaddrinfo(res); | ||
} | ||
} | ||
} | ||
|
||
fn get_loop(&self) -> Loop { | ||
unsafe { | ||
Loop { | ||
handle: uvll::get_loop_from_fs_req(self.native_handle()) | ||
} | ||
} | ||
} | ||
|
||
fn install_req_data(&mut self) { | ||
let req = self.native_handle() as *uvll::uv_getaddrinfo_t; | ||
let data = ~RequestData { | ||
getaddrinfo_cb: None | ||
}; | ||
unsafe { | ||
let data = transmute::<~RequestData, *c_void>(data); | ||
uvll::set_data_for_req(req, data); | ||
} | ||
} | ||
|
||
fn get_req_data<'r>(&'r mut self) -> &'r mut RequestData { | ||
unsafe { | ||
let data = uvll::get_data_for_req(self.native_handle()); | ||
let data = transmute::<&*c_void, &mut ~RequestData>(&data); | ||
return &mut **data; | ||
} | ||
} | ||
|
||
fn delete(self) { | ||
unsafe { | ||
let data = uvll::get_data_for_req(self.native_handle()); | ||
let _data = transmute::<*c_void, ~RequestData>(data); | ||
uvll::set_data_for_req(self.native_handle(), null::<()>()); | ||
uvll::free_req(self.native_handle()); | ||
} | ||
} | ||
} | ||
|
||
impl NativeHandle<*uvll::uv_getaddrinfo_t> for GetAddrInfoRequest { | ||
fn from_native_handle(handle: *uvll::uv_getaddrinfo_t) -> GetAddrInfoRequest { | ||
GetAddrInfoRequest(handle) | ||
} | ||
fn native_handle(&self) -> *uvll::uv_getaddrinfo_t { | ||
match self { &GetAddrInfoRequest(ptr) => ptr } | ||
} | ||
} | ||
|
||
#[cfg(test)] | ||
mod test { | ||
use option::{Some, None}; | ||
use rt::uv::Loop; | ||
use rt::uv::net::accum_sockaddrs; | ||
use rt::io::net::ip::{SocketAddr, Ipv4Addr}; | ||
use super::*; | ||
|
||
#[test] | ||
fn getaddrinfo_test() { | ||
let mut loop_ = Loop::new(); | ||
let mut req = GetAddrInfoRequest::new(); | ||
do req.getaddrinfo(&loop_, Some("localhost"), None, None) |_, addrinfo, _| { | ||
let sockaddrs = accum_sockaddrs(addrinfo); | ||
let mut found_local = false; | ||
let local_addr = &SocketAddr { | ||
ip: Ipv4Addr(127, 0, 0, 1), | ||
port: 0 | ||
}; | ||
for addr in sockaddrs.iter() { | ||
found_local = found_local || addr == local_addr; | ||
} | ||
assert!(found_local); | ||
} | ||
loop_.run(); | ||
loop_.close(); | ||
req.delete(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.