auto merge of #11732 : luqmana/rust/native-getaddrinfo, r=alexcrichton
The last bit I needed to be able to use libnative :P
This commit is contained in:
commit
8de3fab82a
src
117
src/libnative/io/addrinfo.rs
Normal file
117
src/libnative/io/addrinfo.rs
Normal file
@ -0,0 +1,117 @@
|
||||
// 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::IoError;
|
||||
use std::libc;
|
||||
use std::libc::{c_char, c_int};
|
||||
use std::ptr::null;
|
||||
|
||||
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 {
|
||||
return Err(get_error(s));
|
||||
}
|
||||
|
||||
// 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 "system" {
|
||||
fn getaddrinfo(node: *c_char, service: *c_char,
|
||||
hints: *libc::addrinfo, res: **libc::addrinfo) -> c_int;
|
||||
fn freeaddrinfo(res: *libc::addrinfo);
|
||||
#[cfg(not(windows))]
|
||||
fn gai_strerror(errcode: c_int) -> *c_char;
|
||||
#[cfg(windows)]
|
||||
fn WSAGetLastError() -> c_int;
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
fn get_error(_: c_int) -> IoError {
|
||||
use super::translate_error;
|
||||
|
||||
unsafe {
|
||||
translate_error(WSAGetLastError() as i32, true)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(windows))]
|
||||
fn get_error(s: c_int) -> IoError {
|
||||
use std::io;
|
||||
use std::str::raw::from_c_str;
|
||||
|
||||
let err_str = unsafe { from_c_str(gai_strerror(s)) };
|
||||
IoError {
|
||||
kind: io::OtherIoError,
|
||||
desc: "unable to resolve host",
|
||||
detail: Some(err_str),
|
||||
}
|
||||
}
|
@ -23,6 +23,11 @@
|
||||
|
||||
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;
|
||||
@ -30,11 +35,6 @@ use std::rt::rtio;
|
||||
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
|
||||
@ -42,9 +42,10 @@ pub use self::file::FileDesc;
|
||||
pub use self::process::Process;
|
||||
|
||||
// Native I/O implementations
|
||||
pub mod addrinfo;
|
||||
pub mod file;
|
||||
pub mod process;
|
||||
pub mod net;
|
||||
pub mod process;
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
#[cfg(target_os = "freebsd")]
|
||||
@ -202,9 +203,9 @@ impl rtio::IoFactory for IoFactory {
|
||||
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
|
||||
|
@ -134,8 +134,8 @@ fn sockname(fd: sock_t,
|
||||
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>());
|
||||
|
@ -10,6 +10,7 @@
|
||||
|
||||
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;
|
||||
@ -19,7 +20,7 @@ use super::{Loop, UvError, Request, wait_until_woken_after, wakeup};
|
||||
use uvll;
|
||||
|
||||
struct Addrinfo {
|
||||
handle: *uvll::addrinfo,
|
||||
handle: *libc::addrinfo,
|
||||
}
|
||||
|
||||
struct Ctx {
|
||||
@ -62,7 +63,7 @@ impl GetAddrInfoRequest {
|
||||
let socktype = 0;
|
||||
let protocol = 0;
|
||||
|
||||
uvll::addrinfo {
|
||||
libc::addrinfo {
|
||||
ai_flags: flags,
|
||||
ai_family: hint.family as c_int,
|
||||
ai_socktype: socktype,
|
||||
@ -73,7 +74,7 @@ impl GetAddrInfoRequest {
|
||||
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 {
|
||||
@ -100,7 +101,7 @@ impl GetAddrInfoRequest {
|
||||
|
||||
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() };
|
||||
@ -182,39 +183,3 @@ pub fn accum_addrinfo(addr: &Addrinfo) -> ~[ai::Info] {
|
||||
return addrs;
|
||||
}
|
||||
}
|
||||
|
||||
// cannot give tcp/ip permission without help of apk
|
||||
#[cfg(test, not(target_os="android"))]
|
||||
mod test {
|
||||
use std::io::net::ip::{SocketAddr, Ipv4Addr};
|
||||
use super::super::local_loop;
|
||||
use super::GetAddrInfoRequest;
|
||||
|
||||
#[test]
|
||||
fn getaddrinfo_test() {
|
||||
let loop_ = &mut local_loop().loop_;
|
||||
match GetAddrInfoRequest::run(loop_, Some("localhost"), None, None) {
|
||||
Ok(infos) => {
|
||||
let mut found_local = false;
|
||||
let local_addr = &SocketAddr {
|
||||
ip: Ipv4Addr(127, 0, 0, 1),
|
||||
port: 0
|
||||
};
|
||||
for addr in infos.iter() {
|
||||
found_local = found_local || addr.address == *local_addr;
|
||||
}
|
||||
assert!(found_local);
|
||||
}
|
||||
Err(e) => fail!("{:?}", e),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn issue_10663() {
|
||||
let loop_ = &mut local_loop().loop_;
|
||||
// Something should happen here, but this certainly shouldn't cause
|
||||
// everything to die. The actual outcome we don't care too much about.
|
||||
GetAddrInfoRequest::run(loop_, Some("irc.n0v4.com"), None,
|
||||
None);
|
||||
}
|
||||
}
|
||||
|
@ -30,7 +30,7 @@
|
||||
#[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;
|
||||
|
||||
@ -249,45 +249,6 @@ pub type uv_signal_cb = extern "C" fn(handle: *uv_signal_t,
|
||||
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;
|
||||
|
@ -98,15 +98,15 @@ fn lookup(hostname: Option<&str>, servname: Option<&str>, hint: Option<Hint>)
|
||||
LocalIo::maybe_raise(|io| io.get_host_addresses(hostname, servname, hint))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
// Ignored on android since we cannot give tcp/ip
|
||||
// permission without help of apk
|
||||
#[cfg(test, not(target_os = "android"))]
|
||||
mod test {
|
||||
use io::net::ip::Ipv4Addr;
|
||||
use prelude::*;
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
#[ignore(cfg(target_os="android"))] // cannot give tcp/ip permission without help of apk
|
||||
fn dns_smoke_test() {
|
||||
iotest!(fn dns_smoke_test() {
|
||||
let ipaddrs = get_host_addresses("localhost").unwrap();
|
||||
let mut found_local = false;
|
||||
let local_addr = &Ipv4Addr(127, 0, 0, 1);
|
||||
@ -114,5 +114,11 @@ mod test {
|
||||
found_local = found_local || addr == local_addr;
|
||||
}
|
||||
assert!(found_local);
|
||||
}
|
||||
})
|
||||
|
||||
iotest!(fn issue_10663() {
|
||||
// Something should happen here, but this certainly shouldn't cause
|
||||
// everything to die. The actual outcome we don't care too much about.
|
||||
get_host_addresses("example.com");
|
||||
} #[ignore])
|
||||
}
|
||||
|
@ -267,7 +267,7 @@ pub mod types {
|
||||
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;
|
||||
@ -309,6 +309,16 @@ pub mod types {
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -624,7 +634,7 @@ pub mod types {
|
||||
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;
|
||||
@ -671,6 +681,16 @@ pub mod types {
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -811,7 +831,7 @@ pub mod types {
|
||||
}
|
||||
|
||||
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;
|
||||
@ -854,6 +874,16 @@ pub mod types {
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1121,7 +1151,7 @@ pub mod types {
|
||||
}
|
||||
|
||||
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;
|
||||
@ -1168,6 +1198,16 @@ pub mod types {
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user