Finish implementing io::net::addrinfo
This fills in the `hints` structure and exposes libuv's full functionality for doing dns lookups.
This commit is contained in:
parent
bac9681858
commit
1db783bdcf
127
src/libstd/rt/io/net/addrinfo.rs
Normal file
127
src/libstd/rt/io/net/addrinfo.rs
Normal file
@ -0,0 +1,127 @@
|
||||
// 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.
|
||||
|
||||
/*!
|
||||
|
||||
Synchronous DNS Resolution
|
||||
|
||||
Contains the functionality to perform DNS resolution in a style related to
|
||||
getaddrinfo()
|
||||
|
||||
*/
|
||||
|
||||
use option::{Option, Some, None};
|
||||
use result::{Ok, Err};
|
||||
use rt::io::io_error;
|
||||
use rt::io::net::ip::{SocketAddr, IpAddr};
|
||||
use rt::rtio::{IoFactory, IoFactoryObject};
|
||||
use rt::local::Local;
|
||||
|
||||
/// Hints to the types of sockets that are desired when looking up hosts
|
||||
pub enum SocketType {
|
||||
Stream, Datagram, Raw
|
||||
}
|
||||
|
||||
/// Flags which can be or'd into the `flags` field of a `Hint`. These are used
|
||||
/// to manipulate how a query is performed.
|
||||
///
|
||||
/// The meaning of each of these flags can be found with `man -s 3 getaddrinfo`
|
||||
pub enum Flag {
|
||||
AddrConfig,
|
||||
All,
|
||||
CanonName,
|
||||
NumericHost,
|
||||
NumericServ,
|
||||
Passive,
|
||||
V4Mapped,
|
||||
}
|
||||
|
||||
/// A transport protocol associated with either a hint or a return value of
|
||||
/// `lookup`
|
||||
pub enum Protocol {
|
||||
TCP, UDP
|
||||
}
|
||||
|
||||
/// This structure is used to provide hints when fetching addresses for a
|
||||
/// remote host to control how the lookup is performed.
|
||||
///
|
||||
/// For details on these fields, see their corresponding definitions via
|
||||
/// `man -s 3 getaddrinfo`
|
||||
pub struct Hint {
|
||||
family: uint,
|
||||
socktype: Option<SocketType>,
|
||||
protocol: Option<Protocol>,
|
||||
flags: uint,
|
||||
}
|
||||
|
||||
pub struct Info {
|
||||
address: SocketAddr,
|
||||
family: uint,
|
||||
socktype: Option<SocketType>,
|
||||
protocol: Option<Protocol>,
|
||||
flags: uint,
|
||||
}
|
||||
|
||||
/// Easy name resolution. Given a hostname, returns the list of IP addresses for
|
||||
/// that hostname.
|
||||
///
|
||||
/// # Failure
|
||||
///
|
||||
/// On failure, this will raise on the `io_error` condition.
|
||||
pub fn get_host_addresses(host: &str) -> Option<~[IpAddr]> {
|
||||
lookup(Some(host), None, None).map(|a| a.map(|i| i.address.ip))
|
||||
}
|
||||
|
||||
/// Full-fleged resolution. This function will perform a synchronous call to
|
||||
/// getaddrinfo, controlled by the parameters
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * hostname - an optional hostname to lookup against
|
||||
/// * servname - an optional service name, listed in the system services
|
||||
/// * hint - see the hint structure, and "man -s 3 getaddrinfo", for how this
|
||||
/// controls lookup
|
||||
///
|
||||
/// # Failure
|
||||
///
|
||||
/// On failure, this will raise on the `io_error` condition.
|
||||
pub fn lookup(hostname: Option<&str>, servname: Option<&str>,
|
||||
hint: Option<Hint>) -> Option<~[Info]> {
|
||||
let ipaddrs = unsafe {
|
||||
let io: *mut IoFactoryObject = Local::unsafe_borrow();
|
||||
(*io).get_host_addresses(hostname, servname, hint)
|
||||
};
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
@ -8,55 +8,11 @@
|
||||
// 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 use self::addrinfo::get_host_addresses;
|
||||
|
||||
pub mod addrinfo;
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -13,6 +13,7 @@ use option::*;
|
||||
use result::*;
|
||||
use libc::c_int;
|
||||
|
||||
use ai = rt::io::net::addrinfo;
|
||||
use rt::io::IoError;
|
||||
use super::io::process::ProcessConfig;
|
||||
use super::io::net::ip::{IpAddr, SocketAddr};
|
||||
@ -80,7 +81,8 @@ pub trait IoFactory {
|
||||
fn fs_open<P: PathLike>(&mut self, path: &P, fm: FileMode, fa: FileAccess)
|
||||
-> Result<~RtioFileStream, IoError>;
|
||||
fn fs_unlink<P: PathLike>(&mut self, path: &P) -> Result<(), IoError>;
|
||||
fn get_host_addresses(&mut self, host: &str) -> Result<~[IpAddr], IoError>;
|
||||
fn get_host_addresses(&mut self, host: Option<&str>, servname: Option<&str>,
|
||||
hint: Option<ai::Hint>) -> Result<~[ai::Info], IoError>;
|
||||
fn fs_stat<P: PathLike>(&mut self, path: &P) -> Result<FileStat, IoError>;
|
||||
fn fs_mkdir<P: PathLike>(&mut self, path: &P) -> Result<(), IoError>;
|
||||
fn fs_rmdir<P: PathLike>(&mut self, path: &P) -> Result<(), IoError>;
|
||||
|
@ -18,9 +18,10 @@ use rt::uv::uvll;
|
||||
use rt::uv::uvll::UV_GETADDRINFO;
|
||||
use rt::uv::{Loop, UvError, NativeHandle};
|
||||
use rt::uv::status_to_maybe_uv_error;
|
||||
use rt::uv::net::UvAddrInfo;
|
||||
use rt::uv::net;
|
||||
use ai = rt::io::net::addrinfo;
|
||||
|
||||
type GetAddrInfoCallback = ~fn(GetAddrInfoRequest, &UvAddrInfo, Option<UvError>);
|
||||
type GetAddrInfoCallback = ~fn(GetAddrInfoRequest, &net::UvAddrInfo, Option<UvError>);
|
||||
|
||||
pub struct GetAddrInfoRequest(*uvll::uv_getaddrinfo_t);
|
||||
|
||||
@ -38,7 +39,7 @@ impl GetAddrInfoRequest {
|
||||
}
|
||||
|
||||
pub fn getaddrinfo(&mut self, loop_: &Loop, node: Option<&str>,
|
||||
service: Option<&str>, hints: Option<UvAddrInfo>,
|
||||
service: Option<&str>, hints: Option<ai::Hint>,
|
||||
cb: GetAddrInfoCallback) {
|
||||
|
||||
assert!(node.is_some() || service.is_some());
|
||||
@ -72,8 +73,37 @@ impl GetAddrInfoRequest {
|
||||
cb(req, addrinfo, err)
|
||||
};
|
||||
|
||||
// XXX: Implement hints
|
||||
assert!(hints.is_none());
|
||||
let hint = hints.map(|hint| unsafe {
|
||||
let mut flags = 0;
|
||||
do each_ai_flag |cval, aival| {
|
||||
if hint.flags & (aival as uint) != 0 {
|
||||
flags |= cval as i32;
|
||||
}
|
||||
}
|
||||
let socktype = match hint.socktype {
|
||||
Some(ai::Stream) => uvll::rust_SOCK_STREAM(),
|
||||
Some(ai::Datagram) => uvll::rust_SOCK_DGRAM(),
|
||||
Some(ai::Raw) => uvll::rust_SOCK_RAW(),
|
||||
None => 0,
|
||||
};
|
||||
let protocol = match hint.protocol {
|
||||
Some(ai::UDP) => uvll::rust_IPPROTO_UDP(),
|
||||
Some(ai::TCP) => uvll::rust_IPPROTO_TCP(),
|
||||
_ => 0,
|
||||
};
|
||||
|
||||
uvll::addrinfo {
|
||||
ai_flags: flags,
|
||||
ai_family: hint.family as c_int,
|
||||
ai_socktype: socktype,
|
||||
ai_protocol: protocol,
|
||||
ai_addrlen: 0,
|
||||
ai_canonname: null(),
|
||||
ai_addr: null(),
|
||||
ai_next: null(),
|
||||
}
|
||||
});
|
||||
let hint_ptr = hint.as_ref().map_default(null(), |x| x as *uvll::addrinfo);
|
||||
|
||||
self.get_req_data().getaddrinfo_cb = Some(wrapper_cb);
|
||||
|
||||
@ -83,7 +113,7 @@ impl GetAddrInfoRequest {
|
||||
getaddrinfo_cb,
|
||||
c_node_ptr,
|
||||
c_service_ptr,
|
||||
null()));
|
||||
hint_ptr));
|
||||
}
|
||||
|
||||
extern "C" fn getaddrinfo_cb(req: *uvll::uv_getaddrinfo_t,
|
||||
@ -91,7 +121,7 @@ impl GetAddrInfoRequest {
|
||||
res: *uvll::addrinfo) {
|
||||
let mut req: GetAddrInfoRequest = NativeHandle::from_native_handle(req);
|
||||
let err = status_to_maybe_uv_error(status);
|
||||
let addrinfo = UvAddrInfo(res);
|
||||
let addrinfo = net::UvAddrInfo(res);
|
||||
let data = req.get_req_data();
|
||||
(*data.getaddrinfo_cb.get_ref())(req, &addrinfo, err);
|
||||
unsafe {
|
||||
@ -137,6 +167,66 @@ impl GetAddrInfoRequest {
|
||||
}
|
||||
}
|
||||
|
||||
fn each_ai_flag(f: &fn(c_int, ai::Flag)) {
|
||||
unsafe {
|
||||
f(uvll::rust_AI_ADDRCONFIG(), ai::AddrConfig);
|
||||
f(uvll::rust_AI_ALL(), ai::All);
|
||||
f(uvll::rust_AI_CANONNAME(), ai::CanonName);
|
||||
f(uvll::rust_AI_NUMERICHOST(), ai::NumericHost);
|
||||
f(uvll::rust_AI_NUMERICSERV(), ai::NumericServ);
|
||||
f(uvll::rust_AI_PASSIVE(), ai::Passive);
|
||||
f(uvll::rust_AI_V4MAPPED(), ai::V4Mapped);
|
||||
}
|
||||
}
|
||||
|
||||
// Traverse the addrinfo linked list, producing a vector of Rust socket addresses
|
||||
pub fn accum_addrinfo(addr: &net::UvAddrInfo) -> ~[ai::Info] {
|
||||
unsafe {
|
||||
let &net::UvAddrInfo(addr) = addr;
|
||||
let mut addr = addr;
|
||||
|
||||
let mut addrs = ~[];
|
||||
loop {
|
||||
let uvaddr = net::sockaddr_to_UvSocketAddr((*addr).ai_addr);
|
||||
let rustaddr = net::uv_socket_addr_to_socket_addr(uvaddr);
|
||||
|
||||
let mut flags = 0;
|
||||
do each_ai_flag |cval, aival| {
|
||||
if (*addr).ai_flags & cval != 0 {
|
||||
flags |= aival as uint;
|
||||
}
|
||||
}
|
||||
|
||||
let protocol = match (*addr).ai_protocol {
|
||||
p if p == uvll::rust_IPPROTO_UDP() => Some(ai::UDP),
|
||||
p if p == uvll::rust_IPPROTO_TCP() => Some(ai::TCP),
|
||||
_ => None,
|
||||
};
|
||||
let socktype = match (*addr).ai_socktype {
|
||||
p if p == uvll::rust_SOCK_STREAM() => Some(ai::Stream),
|
||||
p if p == uvll::rust_SOCK_DGRAM() => Some(ai::Datagram),
|
||||
p if p == uvll::rust_SOCK_RAW() => Some(ai::Raw),
|
||||
_ => None,
|
||||
};
|
||||
|
||||
addrs.push(ai::Info {
|
||||
address: rustaddr,
|
||||
family: (*addr).ai_family as uint,
|
||||
socktype: socktype,
|
||||
protocol: protocol,
|
||||
flags: flags,
|
||||
});
|
||||
if (*addr).ai_next.is_not_null() {
|
||||
addr = (*addr).ai_next;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return addrs;
|
||||
}
|
||||
}
|
||||
|
||||
impl NativeHandle<*uvll::uv_getaddrinfo_t> for GetAddrInfoRequest {
|
||||
fn from_native_handle(handle: *uvll::uv_getaddrinfo_t) -> GetAddrInfoRequest {
|
||||
GetAddrInfoRequest(handle)
|
||||
@ -150,7 +240,6 @@ impl NativeHandle<*uvll::uv_getaddrinfo_t> for GetAddrInfoRequest {
|
||||
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::*;
|
||||
|
||||
@ -159,14 +248,14 @@ mod 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 sockaddrs = accum_addrinfo(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;
|
||||
found_local = found_local || addr.address == *local_addr;
|
||||
}
|
||||
assert!(found_local);
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ pub enum UvSocketAddr {
|
||||
UvIpv6SocketAddr(*sockaddr_in6),
|
||||
}
|
||||
|
||||
fn sockaddr_to_UvSocketAddr(addr: *uvll::sockaddr) -> UvSocketAddr {
|
||||
pub fn sockaddr_to_UvSocketAddr(addr: *uvll::sockaddr) -> UvSocketAddr {
|
||||
unsafe {
|
||||
assert!((is_ip4_addr(addr) || is_ip6_addr(addr)));
|
||||
assert!(!(is_ip4_addr(addr) && is_ip6_addr(addr)));
|
||||
@ -96,28 +96,6 @@ pub fn uv_socket_addr_to_socket_addr(addr: UvSocketAddr) -> SocketAddr {
|
||||
uv_socket_addr_as_socket_addr(addr, util::id)
|
||||
}
|
||||
|
||||
// Traverse the addrinfo linked list, producing a vector of Rust socket addresses
|
||||
pub fn accum_sockaddrs(addr: &UvAddrInfo) -> ~[SocketAddr] {
|
||||
unsafe {
|
||||
let &UvAddrInfo(addr) = addr;
|
||||
let mut addr = addr;
|
||||
|
||||
let mut addrs = ~[];
|
||||
loop {
|
||||
let uvaddr = sockaddr_to_UvSocketAddr((*addr).ai_addr);
|
||||
let rustaddr = uv_socket_addr_to_socket_addr(uvaddr);
|
||||
addrs.push(rustaddr);
|
||||
if (*addr).ai_next.is_not_null() {
|
||||
addr = (*addr).ai_next;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return addrs;
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[test]
|
||||
fn test_ip4_conversion() {
|
||||
@ -232,13 +210,13 @@ impl StreamWatcher {
|
||||
data.connect_cb = Some(cb);
|
||||
}
|
||||
|
||||
unsafe {
|
||||
return unsafe {
|
||||
static BACKLOG: c_int = 128; // XXX should be configurable
|
||||
match uvll::listen(self.native_handle(), BACKLOG, connection_cb) {
|
||||
0 => Ok(()),
|
||||
n => Err(UvError(n))
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
extern fn connection_cb(handle: *uvll::uv_stream_t, status: c_int) {
|
||||
rtdebug!("connection_cb");
|
||||
@ -466,12 +444,12 @@ impl NativeHandle<*uvll::uv_udp_t> for UdpWatcher {
|
||||
}
|
||||
|
||||
// uv_connect_t is a subclass of uv_req_t
|
||||
struct ConnectRequest(*uvll::uv_connect_t);
|
||||
pub struct ConnectRequest(*uvll::uv_connect_t);
|
||||
impl Request for ConnectRequest { }
|
||||
|
||||
impl ConnectRequest {
|
||||
|
||||
fn new() -> ConnectRequest {
|
||||
pub fn new() -> ConnectRequest {
|
||||
let connect_handle = unsafe { malloc_req(UV_CONNECT) };
|
||||
assert!(connect_handle.is_not_null());
|
||||
ConnectRequest(connect_handle as *uvll::uv_connect_t)
|
||||
|
@ -32,8 +32,8 @@ use rt::tube::Tube;
|
||||
use rt::task::SchedHome;
|
||||
use rt::uv::*;
|
||||
use rt::uv::idle::IdleWatcher;
|
||||
use rt::uv::net::{UvIpv4SocketAddr, UvIpv6SocketAddr, accum_sockaddrs};
|
||||
use rt::uv::addrinfo::GetAddrInfoRequest;
|
||||
use rt::uv::net::{UvIpv4SocketAddr, UvIpv6SocketAddr};
|
||||
use rt::uv::addrinfo::{GetAddrInfoRequest, accum_addrinfo};
|
||||
use unstable::sync::Exclusive;
|
||||
use path::{GenericPath, Path};
|
||||
use super::super::io::support::PathLike;
|
||||
@ -43,6 +43,7 @@ use rt::io::{FileMode, FileAccess, OpenOrCreate, Open, Create,
|
||||
CreateOrTruncate, Append, Truncate, Read, Write, ReadWrite,
|
||||
FileStat};
|
||||
use task;
|
||||
use ai = rt::io::net::addrinfo;
|
||||
|
||||
#[cfg(test)] use container::Container;
|
||||
#[cfg(test)] use unstable::run_in_bare_thread;
|
||||
@ -658,12 +659,16 @@ impl IoFactory for UvIoFactory {
|
||||
return result_cell.take();
|
||||
}
|
||||
|
||||
fn get_host_addresses(&mut self, host: &str) -> Result<~[IpAddr], IoError> {
|
||||
fn get_host_addresses(&mut self, host: Option<&str>, servname: Option<&str>,
|
||||
hint: Option<ai::Hint>) -> Result<~[ai::Info], IoError> {
|
||||
let result_cell = Cell::new_empty();
|
||||
let result_cell_ptr: *Cell<Result<~[IpAddr], IoError>> = &result_cell;
|
||||
let host_ptr: *&str = &host;
|
||||
let result_cell_ptr: *Cell<Result<~[ai::Info], IoError>> = &result_cell;
|
||||
let host_ptr: *Option<&str> = &host;
|
||||
let servname_ptr: *Option<&str> = &servname;
|
||||
let hint_ptr: *Option<ai::Hint> = &hint;
|
||||
let addrinfo_req = GetAddrInfoRequest::new();
|
||||
let addrinfo_req_cell = Cell::new(addrinfo_req);
|
||||
|
||||
do task::unkillable { // FIXME(#8674)
|
||||
let scheduler: ~Scheduler = Local::take();
|
||||
do scheduler.deschedule_running_task_and_then |_, task| {
|
||||
@ -671,10 +676,10 @@ impl IoFactory for UvIoFactory {
|
||||
let mut addrinfo_req = addrinfo_req_cell.take();
|
||||
unsafe {
|
||||
do addrinfo_req.getaddrinfo(self.uv_loop(),
|
||||
Some(*host_ptr),
|
||||
None, None) |_, addrinfo, err| {
|
||||
*host_ptr, *servname_ptr,
|
||||
*hint_ptr) |_, addrinfo, err| {
|
||||
let res = match err {
|
||||
None => Ok(accum_sockaddrs(addrinfo).map(|addr| addr.ip.clone())),
|
||||
None => Ok(accum_addrinfo(addrinfo)),
|
||||
Some(err) => Err(uv_error_to_io_error(err))
|
||||
};
|
||||
(*result_cell_ptr).put_back(res);
|
||||
|
@ -637,3 +637,16 @@ extern "C" int
|
||||
rust_uv_pipe_init(uv_loop_t *loop, uv_pipe_t* p, int ipc) {
|
||||
return uv_pipe_init(loop, p, ipc);
|
||||
}
|
||||
|
||||
extern "C" int rust_SOCK_STREAM() { return SOCK_STREAM; }
|
||||
extern "C" int rust_SOCK_DGRAM() { return SOCK_DGRAM; }
|
||||
extern "C" int rust_SOCK_RAW() { return SOCK_RAW; }
|
||||
extern "C" int rust_IPPROTO_UDP() { return IPPROTO_UDP; }
|
||||
extern "C" int rust_IPPROTO_TCP() { return IPPROTO_TCP; }
|
||||
extern "C" int rust_AI_ADDRCONFIG() { return AI_ADDRCONFIG; }
|
||||
extern "C" int rust_AI_ALL() { return AI_ALL; }
|
||||
extern "C" int rust_AI_CANONNAME() { return AI_CANONNAME; }
|
||||
extern "C" int rust_AI_NUMERICHOST() { return AI_NUMERICHOST; }
|
||||
extern "C" int rust_AI_NUMERICSERV() { return AI_NUMERICSERV; }
|
||||
extern "C" int rust_AI_PASSIVE() { return AI_PASSIVE; }
|
||||
extern "C" int rust_AI_V4MAPPED() { return AI_V4MAPPED; }
|
||||
|
Loading…
x
Reference in New Issue
Block a user