Skip to content

Commit

Permalink
libnative: Implement get_host_addresses.
Browse files Browse the repository at this point in the history
  • Loading branch information
luqmana committed Jan 23, 2014
1 parent fce7922 commit 5aa31c4
Show file tree
Hide file tree
Showing 6 changed files with 162 additions and 59 deletions.
100 changes: 100 additions & 0 deletions src/libnative/io/addrinfo.rs
@@ -0,0 +1,100 @@
// 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);
}
19 changes: 10 additions & 9 deletions src/libnative/io/mod.rs
Expand Up @@ -23,28 +23,29 @@

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;
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::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;

type IoResult<T> = Result<T, IoError>;

Expand Down Expand Up @@ -186,9 +187,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
Expand Down
4 changes: 2 additions & 2 deletions src/libnative/io/net.rs
Expand Up @@ -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>());
Expand Down
9 changes: 5 additions & 4 deletions src/librustuv/addrinfo.rs
Expand Up @@ -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;
Expand All @@ -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 {
Expand Down Expand Up @@ -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,
Expand All @@ -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 {
Expand All @@ -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() };
Expand Down
41 changes: 1 addition & 40 deletions src/librustuv/uvll.rs
Expand Up @@ -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;

Expand Down Expand Up @@ -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;
Expand Down
48 changes: 44 additions & 4 deletions src/libstd/libc.rs
Expand Up @@ -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;
Expand Down Expand Up @@ -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
}
}
}

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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
}
}
}

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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
}
}
}

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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
}
}
}

Expand Down

0 comments on commit 5aa31c4

Please sign in to comment.