--- /dev/null
+// Copyright 2014 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 ai = std::io::net::addrinfo;
+use std::c_str::CString;
+use std::cast;
+use std::io;
+use std::io::IoError;
+use std::libc;
+use std::libc::{c_char, c_int};
+use std::ptr::null;
+use std::str::raw::from_c_str;
+
+use super::net::sockaddr_to_addr;
+
+pub struct GetAddrInfoRequest;
+
+impl GetAddrInfoRequest {
+ pub fn run(host: Option<&str>, servname: Option<&str>,
+ hint: Option<ai::Hint>) -> Result<~[ai::Info], IoError> {
+ assert!(host.is_some() || servname.is_some());
+
+ let c_host = host.map_or(unsafe { CString::new(null(), true) }, |x| x.to_c_str());
+ let c_serv = servname.map_or(unsafe { CString::new(null(), true) }, |x| x.to_c_str());
+
+ let hint = hint.map(|hint| {
+ libc::addrinfo {
+ ai_flags: hint.flags as c_int,
+ ai_family: hint.family as c_int,
+ ai_socktype: 0,
+ ai_protocol: 0,
+ ai_addrlen: 0,
+ ai_canonname: null(),
+ ai_addr: null(),
+ ai_next: null()
+ }
+ });
+
+ let hint_ptr = hint.as_ref().map_or(null(), |x| x as *libc::addrinfo);
+ let res = null();
+
+ // Make the call
+ let s = unsafe {
+ let ch = if c_host.is_null() { null() } else { c_host.with_ref(|x| x) };
+ let cs = if c_serv.is_null() { null() } else { c_serv.with_ref(|x| x) };
+ getaddrinfo(ch, cs, hint_ptr, &res)
+ };
+
+ // Error?
+ if s != 0 {
+ let err_str = unsafe { from_c_str(gai_strerror(s)) };
+
+ return Err(IoError {
+ kind: io::OtherIoError,
+ desc: "unable to resolve host",
+ detail: Some(err_str),
+ });
+ }
+
+ // Collect all the results we found
+ let mut addrs = ~[];
+ let mut rp = res;
+ while rp.is_not_null() {
+ unsafe {
+ let addr = match sockaddr_to_addr(cast::transmute((*rp).ai_addr),
+ (*rp).ai_addrlen as uint) {
+ Ok(a) => a,
+ Err(e) => return Err(e)
+ };
+ addrs.push(ai::Info {
+ address: addr,
+ family: (*rp).ai_family as uint,
+ socktype: None,
+ protocol: None,
+ flags: (*rp).ai_flags as uint
+ });
+
+ rp = (*rp).ai_next;
+ }
+ }
+
+ unsafe { freeaddrinfo(res); }
+
+ Ok(addrs)
+ }
+}
+
+extern {
+ fn getaddrinfo(node: *c_char, service: *c_char,
+ hints: *libc::addrinfo, res: **libc::addrinfo) -> c_int;
+ fn gai_strerror(errcode: c_int) -> *c_char;
+ fn freeaddrinfo(res: *libc::addrinfo);
+}
use std::c_str::CString;
use std::comm::SharedChan;
+use std::io;
+use std::io::IoError;
+use std::io::net::ip::SocketAddr;
+use std::io::process::ProcessConfig;
+use std::io::signal::Signum;
use std::libc::c_int;
use std::libc;
use std::os;
use std::rt::rtio::{RtioTcpStream, RtioTcpListener, RtioUdpSocket,
RtioUnixListener, RtioPipe, RtioFileStream, RtioProcess,
RtioSignal, RtioTTY, CloseBehavior, RtioTimer};
-use std::io;
-use std::io::IoError;
-use std::io::net::ip::SocketAddr;
-use std::io::process::ProcessConfig;
-use std::io::signal::Signum;
use ai = std::io::net::addrinfo;
// Local re-exports
pub use self::process::Process;
// Native I/O implementations
+pub mod addrinfo;
pub mod file;
-pub mod process;
pub mod net;
+pub mod process;
type IoResult<T> = Result<T, IoError>;
fn unix_connect(&mut self, _path: &CString) -> IoResult<~RtioPipe> {
Err(unimpl())
}
- fn get_host_addresses(&mut self, _host: Option<&str>, _servname: Option<&str>,
- _hint: Option<ai::Hint>) -> IoResult<~[ai::Info]> {
- Err(unimpl())
+ fn get_host_addresses(&mut self, host: Option<&str>, servname: Option<&str>,
+ hint: Option<ai::Hint>) -> IoResult<~[ai::Info]> {
+ addrinfo::GetAddrInfoRequest::run(host, servname, hint)
}
// filesystem operations
return sockaddr_to_addr(&storage, len as uint);
}
-fn sockaddr_to_addr(storage: &libc::sockaddr_storage,
- len: uint) -> IoResult<ip::SocketAddr> {
+pub fn sockaddr_to_addr(storage: &libc::sockaddr_storage,
+ len: uint) -> IoResult<ip::SocketAddr> {
match storage.ss_family as libc::c_int {
libc::AF_INET => {
assert!(len as uint >= mem::size_of::<libc::sockaddr_in>());
use ai = std::io::net::addrinfo;
use std::cast;
+use std::libc;
use std::libc::c_int;
use std::ptr::null;
use std::rt::task::BlockedTask;
use uvll;
struct Addrinfo {
- handle: *uvll::addrinfo,
+ handle: *libc::addrinfo,
}
struct Ctx {
let socktype = 0;
let protocol = 0;
- uvll::addrinfo {
+ libc::addrinfo {
ai_flags: flags,
ai_family: hint.family as c_int,
ai_socktype: socktype,
ai_next: null(),
}
});
- let hint_ptr = hint.as_ref().map_or(null(), |x| x as *uvll::addrinfo);
+ let hint_ptr = hint.as_ref().map_or(null(), |x| x as *libc::addrinfo);
let mut req = Request::new(uvll::UV_GETADDRINFO);
return match unsafe {
extern fn getaddrinfo_cb(req: *uvll::uv_getaddrinfo_t,
status: c_int,
- res: *uvll::addrinfo) {
+ res: *libc::addrinfo) {
let req = Request::wrap(req);
assert!(status != uvll::ECANCELED);
let cx: &mut Ctx = unsafe { req.get_data() };
#[allow(non_camel_case_types)]; // C types
use std::libc::{size_t, c_int, c_uint, c_void, c_char, c_double};
-use std::libc::{ssize_t, sockaddr, free};
+use std::libc::{ssize_t, sockaddr, free, addrinfo};
use std::libc;
use std::rt::global_heap::malloc_raw;
signum: c_int);
pub type uv_fs_cb = extern "C" fn(req: *uv_fs_t);
-// XXX: This is a standard C type. Could probably be defined in libc
-#[cfg(target_os = "android")]
-#[cfg(target_os = "linux")]
-pub struct addrinfo {
- ai_flags: c_int,
- ai_family: c_int,
- ai_socktype: c_int,
- ai_protocol: c_int,
- ai_addrlen: libc::socklen_t,
- ai_addr: *sockaddr,
- ai_canonname: *char,
- ai_next: *addrinfo
-}
-
-#[cfg(target_os = "macos")]
-#[cfg(target_os = "freebsd")]
-pub struct addrinfo {
- ai_flags: c_int,
- ai_family: c_int,
- ai_socktype: c_int,
- ai_protocol: c_int,
- ai_addrlen: libc::socklen_t,
- ai_canonname: *char,
- ai_addr: *sockaddr,
- ai_next: *addrinfo
-}
-
-#[cfg(windows)]
-pub struct addrinfo {
- ai_flags: c_int,
- ai_family: c_int,
- ai_socktype: c_int,
- ai_protocol: c_int,
- ai_addrlen: size_t,
- ai_canonname: *char,
- ai_addr: *sockaddr,
- ai_next: *addrinfo
-}
-
#[cfg(unix)] pub type uv_uid_t = libc::types::os::arch::posix88::uid_t;
#[cfg(unix)] pub type uv_gid_t = libc::types::os::arch::posix88::gid_t;
#[cfg(windows)] pub type uv_uid_t = libc::c_uchar;
pub enum timezone {}
}
pub mod bsd44 {
- use libc::types::os::arch::c95::c_uint;
+ use libc::types::os::arch::c95::{c_char, c_int, c_uint};
pub type socklen_t = u32;
pub type sa_family_t = u16;
ipv6mr_multiaddr: in6_addr,
ipv6mr_interface: c_uint,
}
+ pub struct addrinfo {
+ ai_flags: c_int,
+ ai_family: c_int,
+ ai_socktype: c_int,
+ ai_protocol: c_int,
+ ai_addrlen: socklen_t,
+ ai_addr: *sockaddr,
+ ai_canonname: *c_char,
+ ai_next: *addrinfo
+ }
}
}
pub enum timezone {}
}
pub mod bsd44 {
- use libc::types::os::arch::c95::c_uint;
+ use libc::types::os::arch::c95::{c_char, c_int, c_uint};
pub type socklen_t = u32;
pub type sa_family_t = u8;
ipv6mr_multiaddr: in6_addr,
ipv6mr_interface: c_uint,
}
+ pub struct addrinfo {
+ ai_flags: c_int,
+ ai_family: c_int,
+ ai_socktype: c_int,
+ ai_protocol: c_int,
+ ai_addrlen: socklen_t,
+ ai_canonname: *c_char,
+ ai_addr: *sockaddr,
+ ai_next: *addrinfo
+ }
}
}
}
pub mod bsd44 {
- use libc::types::os::arch::c95::{c_int, c_uint};
+ use libc::types::os::arch::c95::{c_char, c_int, c_uint, size_t};
pub type SOCKET = c_uint;
pub type socklen_t = c_int;
ipv6mr_multiaddr: in6_addr,
ipv6mr_interface: c_uint,
}
+ pub struct addrinfo {
+ ai_flags: c_int,
+ ai_family: c_int,
+ ai_socktype: c_int,
+ ai_protocol: c_int,
+ ai_addrlen: size_t,
+ ai_canonname: *c_char,
+ ai_addr: *sockaddr,
+ ai_next: *addrinfo
+ }
}
}
}
pub mod bsd44 {
- use libc::types::os::arch::c95::{c_int, c_uint};
+ use libc::types::os::arch::c95::{c_char, c_int, c_uint};
pub type socklen_t = c_int;
pub type sa_family_t = u8;
ipv6mr_multiaddr: in6_addr,
ipv6mr_interface: c_uint,
}
+ pub struct addrinfo {
+ ai_flags: c_int,
+ ai_family: c_int,
+ ai_socktype: c_int,
+ ai_protocol: c_int,
+ ai_addrlen: socklen_t,
+ ai_canonname: *c_char,
+ ai_addr: *sockaddr,
+ ai_next: *addrinfo
+ }
}
}