diff options
| author | bors <bors@rust-lang.org> | 2014-01-24 14:51:36 -0800 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2014-01-24 14:51:36 -0800 |
| commit | 8de3fab82a44506be96c51183d488b1019f04cc3 (patch) | |
| tree | b6ee3dc0ee3234acd7146aa5f7d0e6f7e09a5861 /src/libnative | |
| parent | a1d9d9e6d2ca79ac0b157170a76e300acfdcf143 (diff) | |
| parent | adb512802057a89b4339651c90dca81e5dd96751 (diff) | |
| download | rust-8de3fab82a44506be96c51183d488b1019f04cc3.tar.gz rust-8de3fab82a44506be96c51183d488b1019f04cc3.zip | |
auto merge of #11732 : luqmana/rust/native-getaddrinfo, r=alexcrichton
The last bit I needed to be able to use libnative :P
Diffstat (limited to 'src/libnative')
| -rw-r--r-- | src/libnative/io/addrinfo.rs | 117 | ||||
| -rw-r--r-- | src/libnative/io/mod.rs | 19 | ||||
| -rw-r--r-- | src/libnative/io/net.rs | 4 |
3 files changed, 129 insertions, 11 deletions
diff --git a/src/libnative/io/addrinfo.rs b/src/libnative/io/addrinfo.rs new file mode 100644 index 00000000000..5bdeaa17e74 --- /dev/null +++ b/src/libnative/io/addrinfo.rs @@ -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), + } +} diff --git a/src/libnative/io/mod.rs b/src/libnative/io/mod.rs index f3aca7820a5..1ef5987de0a 100644 --- a/src/libnative/io/mod.rs +++ b/src/libnative/io/mod.rs @@ -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 diff --git a/src/libnative/io/net.rs b/src/libnative/io/net.rs index adcd21f0ac4..9be4247b056 100644 --- a/src/libnative/io/net.rs +++ b/src/libnative/io/net.rs @@ -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>()); |
