@Chris-Morgan ran into this, turns out if we have a clean llvm in the old location we won't rebuild/reconfigure even though we should.
branch = master
[submodule "src/libuv"]
path = src/libuv
- url = https://github.com/brson/libuv.git
+ url = https://github.com/alexcrichton/libuv.git
branch = master
+[submodule "src/gyp"]
+ path = src/gyp
+ url = https://git.chromium.org/external/gyp.git
$(Q)rm -f $(RUSTLLVM_LIB_OBJS) $(RUSTLLVM_OBJS_OBJS) $(RUSTLLVM_DEF)
$(Q)rm -Rf $(DOCS)
$(Q)rm -Rf $(GENERATED)
- $(Q)rm -f tmp/*
+ $(Q)rm -Rf tmp/*
$(Q)rm -Rf rust-stage0-*.tar.bz2 $(PKG_NAME)-*.tar.gz dist
$(Q)rm -Rf $(foreach ext, \
html aux cp fn ky log pdf pg toc tp vr cps, \
PKG_EXE = $(PKG_DIR)-install.exe
endif
-PKG_GITMODULES := $(S)src/libuv $(S)src/llvm
+PKG_GITMODULES := $(S)src/libuv $(S)src/llvm $(S)src/gyp
PKG_FILES := \
$(S)COPYRIGHT \
$$(S)src/libuv/*/*/*/*)
endif
+LIBUV_MAKEFILE_$(1)_$(2) := $$(CFG_BUILD_DIR)$$(RT_BUILD_DIR_$(1)_$(2))/libuv/Makefile
+LIBUV_NO_LOAD = run-benchmarks.target.mk run-tests.target.mk \
+ uv_dtrace_header.target.mk uv_dtrace_provider.target.mk
+
+export PYTHONPATH := $(PYTHONPATH):$$(S)src/gyp/pylib
+
+$$(LIBUV_MAKEFILE_$(1)_$(2)):
+ (cd $(S)src/libuv/ && \
+ ./gyp_uv -f make -Dtarget_arch=$$(LIBUV_ARCH_$(1)) -D ninja \
+ -Goutput_dir=$$(@D) --generator-output $$(@D))
+
# XXX: Shouldn't need platform-specific conditions here
ifdef CFG_WINDOWSY_$(1)
$$(LIBUV_LIB_$(1)_$(2)): $$(LIBUV_DEPS)
- $$(Q)$$(MAKE) -C $$(S)src/libuv/ \
- builddir_name="$$(CFG_BUILD_DIR)/$$(RT_BUILD_DIR_$(1)_$(2))/libuv" \
- OS=mingw \
+ $$(Q)$$(MAKE) -C $$(S)src/libuv -f Makefile.mingw \
+ CFLAGS="$$(CFG_GCCISH_CFLAGS) $$(LIBUV_FLAGS_$$(HOST_$(1))) $$(SNAP_DEFINES)" \
+ AR="$$(AR_$(1))" \
V=$$(VERBOSE)
+ $$(Q)cp $$(S)src/libuv/libuv.a $$@
else ifeq ($(OSTYPE_$(1)), linux-androideabi)
-$$(LIBUV_LIB_$(1)_$(2)): $$(LIBUV_DEPS)
- $$(Q)$$(MAKE) -C $$(S)src/libuv/ \
+$$(LIBUV_LIB_$(1)_$(2)): $$(LIBUV_DEPS) $$(LIBUV_MAKEFILE_$(1)_$(2))
+ $$(Q)$$(MAKE) -C $$(@D) \
CFLAGS="$$(CFG_GCCISH_CFLAGS) $$(LIBUV_FLAGS_$$(HOST_$(1))) $$(SNAP_DEFINES)" \
LDFLAGS="$$(CFG_GCCISH_LINK_FLAGS) $$(LIBUV_FLAGS_$$(HOST_$(1)))" \
CC="$$(CC_$(1))" \
LINK="$$(CXX_$(1))" \
AR="$$(AR_$(1))" \
PLATFORM=android \
- BUILDTYPE=Release \
- builddir_name="$$(CFG_BUILD_DIR)/$$(RT_BUILD_DIR_$(1)_$(2))/libuv" \
host=android OS=linux \
+ builddir="." \
+ BUILDTYPE=Release \
+ NO_LOAD="$$(LIBUV_NO_LOAD)" \
V=$$(VERBOSE)
else
-$$(LIBUV_LIB_$(1)_$(2)): $$(LIBUV_DEPS)
- $$(Q)$$(MAKE) -C $$(S)src/libuv/ \
+$$(LIBUV_LIB_$(1)_$(2)): $$(LIBUV_DEPS) $$(LIBUV_MAKEFILE_$(1)_$(2))
+ $$(Q)$$(MAKE) -C $$(@D) \
CFLAGS="$$(CFG_GCCISH_CFLAGS) $$(LIBUV_FLAGS_$$(HOST_$(1))) $$(SNAP_DEFINES)" \
LDFLAGS="$$(CFG_GCCISH_LINK_FLAGS) $$(LIBUV_FLAGS_$$(HOST_$(1)))" \
CC="$$(CC_$(1))" \
CXX="$$(CXX_$(1))" \
AR="$$(AR_$(1))" \
- builddir_name="$$(CFG_BUILD_DIR)/$$(RT_BUILD_DIR_$(1)_$(2))/libuv" \
+ builddir="." \
+ BUILDTYPE=Release \
+ NO_LOAD="$$(LIBUV_NO_LOAD)" \
V=$$(VERBOSE)
endif
# llvm, but using it straight out of the build directory)
ifdef CFG_WINDOWSY_$(1)
LLVM_EXTRA_INCDIRS_$(1)= -iquote $(S)src/llvm/include \
- -iquote llvm/$(1)/include
+ -iquote $$(CFG_LLVM_BUILD_DIR_$(1))/include
endif
RUSTLLVM_OBJS_CS_$(1) := $$(addprefix rustllvm/, RustWrapper.cpp PassWrapper.cpp)
--- /dev/null
+Subproject commit f407f09c94e00d2d570e8e42114e3f6848b2deb2
#[cfg(test)]
mod test {
use std::{io, os, unstable};
+ use std::unstable::finally::Finally;
use super::*;
+ use tempfile;
#[test]
fn test_relative_pattern() {
+ fn change_then_remove(p: &Path, f: &fn()) {
+ do (|| {
+ unstable::change_dir_locked(p, || f());
+ }).finally {
+ os::remove_dir_recursive(p);
+ }
+ }
+
fn mk_file(path: &str, directory: bool) {
if directory {
os::make_dir(&Path(path), 0xFFFF);
glob(pattern).collect()
}
- mk_file("tmp", true);
- mk_file("tmp/glob-tests", true);
+ let root = tempfile::mkdtemp(&os::tmpdir(), "glob-tests");
+ let root = root.expect("Should have created a temp directory");
- do unstable::change_dir_locked(&Path("tmp/glob-tests")) {
+ do change_then_remove(&root) {
mk_file("aaa", true);
mk_file("aaa/apple", true);
pub mod file;
/// Synchronous, non-blocking network I/O.
-pub mod net {
- pub mod tcp;
- pub mod udp;
- pub mod ip;
- #[cfg(unix)]
- pub mod unix;
-}
+pub mod net;
/// Readers and Writers for memory buffers and strings.
pub mod mem;
--- /dev/null
+// 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.
+
+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 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);
+ }
+}
do run_in_newsched_task {
let mut called = false;
do io_error::cond.trap(|e| {
- assert!(e.kind == ConnectionRefused);
+ assert_eq!(e.kind, ConnectionRefused);
called = true;
}).inside {
let addr = SocketAddr { ip: Ipv4Addr(0, 0, 0, 0), port: 1 };
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>;
}
pub trait RtioTcpListener : RtioSocket {
--- /dev/null
+// 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.
+
+use cast::transmute;
+use cell::Cell;
+use c_str::ToCStr;
+use libc::{c_int, c_void};
+use option::{Option, Some, None};
+use ptr::null;
+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;
+
+type GetAddrInfoCallback = ~fn(GetAddrInfoRequest, &UvAddrInfo, Option<UvError>);
+
+pub struct GetAddrInfoRequest(*uvll::uv_getaddrinfo_t);
+
+pub struct RequestData {
+ getaddrinfo_cb: Option<GetAddrInfoCallback>,
+}
+
+impl GetAddrInfoRequest {
+ pub fn new() -> GetAddrInfoRequest {
+ let req = unsafe { uvll::malloc_req(UV_GETADDRINFO) };
+ assert!(req.is_not_null());
+ let mut req: GetAddrInfoRequest = NativeHandle::from_native_handle(req);
+ req.install_req_data();
+ return req;
+ }
+
+ pub fn getaddrinfo(&mut self, loop_: &Loop, node: Option<&str>,
+ service: Option<&str>, hints: Option<UvAddrInfo>,
+ cb: GetAddrInfoCallback) {
+
+ assert!(node.is_some() || service.is_some());
+
+ let (c_node, c_node_ptr) = match node {
+ Some(n) => {
+ let c_node = n.to_c_str();
+ let c_node_ptr = c_node.with_ref(|r| r);
+ (Some(c_node), c_node_ptr)
+ }
+ None => (None, null())
+ };
+
+ let (c_service, c_service_ptr) = match service {
+ Some(s) => {
+ let c_service = s.to_c_str();
+ let c_service_ptr = c_service.with_ref(|r| r);
+ (Some(c_service), c_service_ptr)
+ }
+ None => (None, null())
+ };
+
+ let cb = Cell::new(cb);
+ let wrapper_cb: GetAddrInfoCallback = |req, addrinfo, err| {
+ // Capture some heap values that need to stay alive for the
+ // getaddrinfo call
+ let _ = &c_node;
+ let _ = &c_service;
+
+ let cb = cb.take();
+ cb(req, addrinfo, err)
+ };
+
+ // XXX: Implement hints
+ assert!(hints.is_none());
+
+ self.get_req_data().getaddrinfo_cb = Some(wrapper_cb);
+
+ unsafe {
+ assert!(0 == uvll::getaddrinfo(loop_.native_handle(),
+ self.native_handle(),
+ getaddrinfo_cb,
+ c_node_ptr,
+ c_service_ptr,
+ null()));
+ }
+
+ extern "C" fn getaddrinfo_cb(req: *uvll::uv_getaddrinfo_t,
+ status: c_int,
+ 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 data = req.get_req_data();
+ (*data.getaddrinfo_cb.get_ref())(req, &addrinfo, err);
+ unsafe {
+ uvll::freeaddrinfo(res);
+ }
+ }
+ }
+
+ fn get_loop(&self) -> Loop {
+ unsafe {
+ Loop {
+ handle: uvll::get_loop_from_fs_req(self.native_handle())
+ }
+ }
+ }
+
+ fn install_req_data(&mut self) {
+ let req = self.native_handle() as *uvll::uv_getaddrinfo_t;
+ let data = ~RequestData {
+ getaddrinfo_cb: None
+ };
+ unsafe {
+ let data = transmute::<~RequestData, *c_void>(data);
+ uvll::set_data_for_req(req, data);
+ }
+ }
+
+ fn get_req_data<'r>(&'r mut self) -> &'r mut RequestData {
+ unsafe {
+ let data = uvll::get_data_for_req(self.native_handle());
+ let data = transmute::<&*c_void, &mut ~RequestData>(&data);
+ return &mut **data;
+ }
+ }
+
+ fn delete(self) {
+ unsafe {
+ let data = uvll::get_data_for_req(self.native_handle());
+ let _data = transmute::<*c_void, ~RequestData>(data);
+ uvll::set_data_for_req(self.native_handle(), null::<()>());
+ uvll::free_req(self.native_handle());
+ }
+ }
+}
+
+impl NativeHandle<*uvll::uv_getaddrinfo_t> for GetAddrInfoRequest {
+ fn from_native_handle(handle: *uvll::uv_getaddrinfo_t) -> GetAddrInfoRequest {
+ GetAddrInfoRequest(handle)
+ }
+ fn native_handle(&self) -> *uvll::uv_getaddrinfo_t {
+ match self { &GetAddrInfoRequest(ptr) => ptr }
+ }
+}
+
+#[cfg(test)]
+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::*;
+
+ #[test]
+ fn getaddrinfo_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 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;
+ }
+ assert!(found_local);
+ }
+ loop_.run();
+ loop_.close();
+ req.delete();
+ }
+}
extern fn async_cb(handle: *uvll::uv_async_t, status: c_int) {
let mut watcher: AsyncWatcher = NativeHandle::from_native_handle(handle);
- let status = status_to_maybe_uv_error(watcher, status);
+ let status = status_to_maybe_uv_error(status);
let data = watcher.get_watcher_data();
let cb = data.async_cb.get_ref();
(*cb)(watcher, status);
use ptr::null;
use libc::c_void;
use rt::uv::{Request, NativeHandle, Loop, FsCallback, Buf,
- status_to_maybe_uv_error_with_loop, UvError};
+ status_to_maybe_uv_error, UvError};
use rt::uv::uvll;
use rt::uv::uvll::*;
use super::super::io::support::PathLike;
pub fn open_sync<P: PathLike>(loop_: &Loop, path: &P, flags: int, mode: int)
-> Result<int, UvError> {
let result = FsRequest::open_common(loop_, path, flags, mode, None);
- sync_cleanup(loop_, result)
+ sync_cleanup(result)
}
fn unlink_common<P: PathLike>(loop_: &Loop, path: &P, cb: Option<FsCallback>) -> int {
}
pub fn unlink<P: PathLike>(loop_: &Loop, path: &P, cb: FsCallback) {
let result = FsRequest::unlink_common(loop_, path, Some(cb));
- sync_cleanup(loop_, result);
+ sync_cleanup(result);
}
pub fn unlink_sync<P: PathLike>(loop_: &Loop, path: &P) -> Result<int, UvError> {
let result = FsRequest::unlink_common(loop_, path, None);
- sync_cleanup(loop_, result)
+ sync_cleanup(result)
}
pub fn install_req_data(&self, cb: Option<FsCallback>) {
match self { &FsRequest(ptr) => ptr }
}
}
- fn sync_cleanup(loop_: &Loop, result: int)
- -> Result<int, UvError> {
- match status_to_maybe_uv_error_with_loop(loop_.native_handle(), result as i32) {
- Some(err) => Err(err),
- None => Ok(result)
- }
+
+fn sync_cleanup(result: int)
+ -> Result<int, UvError> {
+ match status_to_maybe_uv_error(result as i32) {
+ Some(err) => Err(err),
+ None => Ok(result)
}
+}
pub struct FileDescriptor(c_int);
+
impl FileDescriptor {
fn new(fd: c_int) -> FileDescriptor {
FileDescriptor(fd)
pub fn write_sync(&mut self, loop_: &Loop, buf: Buf, offset: i64)
-> Result<int, UvError> {
let result = self.write_common(loop_, buf, offset, None);
- sync_cleanup(loop_, result)
+ sync_cleanup(result)
}
fn read_common(&mut self, loop_: &Loop, buf: Buf,
pub fn read_sync(&mut self, loop_: &Loop, buf: Buf, offset: i64)
-> Result<int, UvError> {
let result = self.read_common(loop_, buf, offset, None);
- sync_cleanup(loop_, result)
+ sync_cleanup(result)
}
fn close_common(self, loop_: &Loop, cb: Option<FsCallback>) -> int {
}
pub fn close_sync(self, loop_: &Loop) -> Result<int, UvError> {
let result = self.close_common(loop_, None);
- sync_cleanup(loop_, result)
+ sync_cleanup(result)
}
}
extern fn compl_cb(req: *uv_fs_t) {
let mut req: FsRequest = NativeHandle::from_native_handle(req);
- let loop_ = req.get_loop();
// pull the user cb out of the req data
let cb = {
let data = req.get_req_data();
// in uv_fs_open calls, the result will be the fd in the
// case of success, otherwise it's -1 indicating an error
let result = req.get_result();
- let status = status_to_maybe_uv_error_with_loop(
- loop_.native_handle(), result);
+ let status = status_to_maybe_uv_error(result);
// we have a req and status, call the user cb..
// only giving the user a ref to the FsRequest, as we
// have to clean it up, afterwards (and they aren't really
let mut idle_watcher: IdleWatcher = NativeHandle::from_native_handle(handle);
let data = idle_watcher.get_watcher_data();
let cb: &IdleCallback = data.idle_cb.get_ref();
- let status = status_to_maybe_uv_error(idle_watcher, status);
+ let status = status_to_maybe_uv_error(status);
(*cb)(idle_watcher, status);
}
}
let mut idle_watcher: IdleWatcher = NativeHandle::from_native_handle(handle);
let data = idle_watcher.get_watcher_data();
let cb: &IdleCallback = data.idle_cb.get_ref();
- let status = status_to_maybe_uv_error(idle_watcher, status);
+ let status = status_to_maybe_uv_error(status);
(*cb)(idle_watcher, status);
}
}
pub mod idle;
pub mod timer;
pub mod async;
+pub mod addrinfo;
/// XXX: Loop(*handle) is buggy with destructors. Normal structs
/// with dtors may not be destructured, but tuple structs can,
pub type UdpSendCallback = ~fn(UdpWatcher, Option<UvError>);
-/// Callbacks used by StreamWatchers, set as custom data on the foreign handle
+/// Callbacks used by StreamWatchers, set as custom data on the foreign handle.
+/// XXX: Would be better not to have all watchers allocate room for all callback types.
struct WatcherData {
read_cb: Option<ReadCallback>,
write_cb: Option<ConnectionCallback>,
// XXX: Need to define the error constants like EOF so they can be
// compared to the UvError type
-pub struct UvError(uvll::uv_err_t);
+pub struct UvError(c_int);
impl UvError {
pub fn name(&self) -> ~str {
unsafe {
- let inner = match self { &UvError(ref a) => a };
+ let inner = match self { &UvError(a) => a };
let name_str = uvll::err_name(inner);
assert!(name_str.is_not_null());
from_c_str(name_str)
pub fn desc(&self) -> ~str {
unsafe {
- let inner = match self { &UvError(ref a) => a };
+ let inner = match self { &UvError(a) => a };
let desc_str = uvll::strerror(inner);
assert!(desc_str.is_not_null());
from_c_str(desc_str)
}
pub fn is_eof(&self) -> bool {
- self.code == uvll::EOF
+ **self == uvll::EOF
}
}
#[test]
fn error_smoke_test() {
- let err = uvll::uv_err_t { code: 1, sys_errno_: 1 };
- let err: UvError = UvError(err);
+ let err: UvError = UvError(uvll::EOF);
assert_eq!(err.to_str(), ~"EOF: end of file");
}
-pub fn last_uv_error<H, W: Watcher + NativeHandle<*H>>(watcher: &W) -> UvError {
- unsafe {
- let loop_ = watcher.event_loop();
- UvError(uvll::last_error(loop_.native_handle()))
- }
-}
-
pub fn uv_error_to_io_error(uverr: UvError) -> IoError {
unsafe {
// Importing error constants
use rt::io::*;
// uv error descriptions are static
- let c_desc = uvll::strerror(&*uverr);
+ let c_desc = uvll::strerror(*uverr);
let desc = str::raw::c_str_to_static_slice(c_desc);
- let kind = match uverr.code {
+ let kind = match *uverr {
UNKNOWN => OtherIoError,
OK => OtherIoError,
EOF => EndOfFile,
ECONNREFUSED => ConnectionRefused,
ECONNRESET => ConnectionReset,
EPIPE => BrokenPipe,
- _ => {
- rtdebug!("uverr.code %u", uverr.code as uint);
+ err => {
+ rtdebug!("uverr.code %d", err as int);
// XXX: Need to map remaining uv error types
OtherIoError
}
}
/// Given a uv handle, convert a callback status to a UvError
-pub fn status_to_maybe_uv_error_with_loop(
- loop_: *uvll::uv_loop_t,
- status: c_int) -> Option<UvError> {
- if status != -1 {
+pub fn status_to_maybe_uv_error(status: c_int) -> Option<UvError>
+{
+ if status >= 0 {
None
} else {
- unsafe {
- rtdebug!("loop: %x", loop_ as uint);
- let err = uvll::last_error(loop_);
- Some(UvError(err))
- }
- }
-}
-/// Given a uv handle, convert a callback status to a UvError
-pub fn status_to_maybe_uv_error<T, U: Watcher + NativeHandle<*T>>(handle: U,
- status: c_int) -> Option<UvError> {
- if status != -1 {
- None
- } else {
- unsafe {
- rtdebug!("handle: %x", handle.native_handle() as uint);
- let loop_ = uvll::get_loop_for_uv_handle(handle.native_handle());
- status_to_maybe_uv_error_with_loop(loop_, status)
- }
+ Some(UvError(status))
}
}
use rt::uv::{Loop, Watcher, Request, UvError, Buf, NativeHandle, NullCallback,
status_to_maybe_uv_error};
use rt::io::net::ip::{SocketAddr, Ipv4Addr, Ipv6Addr};
-use rt::uv::last_uv_error;
use vec;
use str;
use from_str::{FromStr};
+pub struct UvAddrInfo(*uvll::addrinfo);
+
pub enum UvSocketAddr {
UvIpv4SocketAddr(*sockaddr_in),
UvIpv6SocketAddr(*sockaddr_in6),
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() {
rtdebug!("buf len: %d", buf.len as int);
let mut stream_watcher: StreamWatcher = NativeHandle::from_native_handle(stream);
let cb = stream_watcher.get_watcher_data().read_cb.get_ref();
- let status = status_to_maybe_uv_error(stream_watcher, nread as c_int);
+ let status = status_to_maybe_uv_error(nread as c_int);
(*cb)(stream_watcher, nread as int, buf, status);
}
}
let mut stream_watcher = write_request.stream();
write_request.delete();
let cb = stream_watcher.get_watcher_data().write_cb.take_unwrap();
- let status = status_to_maybe_uv_error(stream_watcher, status);
+ let status = status_to_maybe_uv_error(status);
cb(stream_watcher, status);
}
}
};
match result {
0 => Ok(()),
- _ => Err(last_uv_error(self)),
+ _ => Err(UvError(result)),
}
}
}
let mut stream_watcher = connect_request.stream();
connect_request.delete();
let cb = stream_watcher.get_watcher_data().connect_cb.take_unwrap();
- let status = status_to_maybe_uv_error(stream_watcher, status);
+ let status = status_to_maybe_uv_error(status);
cb(stream_watcher, status);
}
}
rtdebug!("connection_cb");
let mut stream_watcher: StreamWatcher = NativeHandle::from_native_handle(handle);
let cb = stream_watcher.get_watcher_data().connect_cb.get_ref();
- let status = status_to_maybe_uv_error(stream_watcher, status);
+ let status = status_to_maybe_uv_error(status);
(*cb)(stream_watcher, status);
}
}
};
match result {
0 => Ok(()),
- _ => Err(last_uv_error(self)),
+ _ => Err(UvError(result)),
}
}
}
rtdebug!("buf len: %d", buf.len as int);
let mut udp_watcher: UdpWatcher = NativeHandle::from_native_handle(handle);
let cb = udp_watcher.get_watcher_data().udp_recv_cb.get_ref();
- let status = status_to_maybe_uv_error(udp_watcher, nread as c_int);
+ let status = status_to_maybe_uv_error(nread as c_int);
let addr = uv_socket_addr_to_socket_addr(sockaddr_to_UvSocketAddr(addr));
(*cb)(udp_watcher, nread as int, buf, addr, flags as uint, status);
}
let mut udp_watcher = send_request.handle();
send_request.delete();
let cb = udp_watcher.get_watcher_data().udp_send_cb.take_unwrap();
- let status = status_to_maybe_uv_error(udp_watcher, status);
+ let status = status_to_maybe_uv_error(status);
cb(udp_watcher, status);
}
}
let mut watcher: TimerWatcher = NativeHandle::from_native_handle(handle);
let data = watcher.get_watcher_data();
let cb = data.timer_cb.get_ref();
- let status = status_to_maybe_uv_error(watcher, status);
+ let status = status_to_maybe_uv_error(status);
(*cb)(watcher, status);
}
}
use rt::task::SchedHome;
use rt::uv::*;
use rt::uv::idle::IdleWatcher;
-use rt::uv::net::{UvIpv4SocketAddr, UvIpv6SocketAddr};
+use rt::uv::net::{UvIpv4SocketAddr, UvIpv6SocketAddr, accum_sockaddrs};
+use rt::uv::addrinfo::GetAddrInfoRequest;
use unstable::sync::Exclusive;
use super::super::io::support::PathLike;
use libc::{lseek, off_t, O_CREAT, O_APPEND, O_TRUNC, O_RDWR, O_RDONLY, O_WRONLY,
};
if r != 0 {
- let status = status_to_maybe_uv_error(handle, r);
+ let status = status_to_maybe_uv_error(r);
return Err(uv_error_to_io_error(status.unwrap()));
}
assert!(!result_cell.is_empty());
return result_cell.take();
}
+
+ fn get_host_addresses(&mut self, host: &str) -> Result<~[IpAddr], IoError> {
+ let result_cell = Cell::new_empty();
+ let result_cell_ptr: *Cell<Result<~[IpAddr], IoError>> = &result_cell;
+ let host_ptr: *&str = &host;
+ 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| {
+ let task_cell = Cell::new(task);
+ let mut addrinfo_req = addrinfo_req_cell.take();
+ unsafe {
+ do addrinfo_req.getaddrinfo(self.uv_loop(),
+ Some(*host_ptr),
+ None, None) |_, addrinfo, err| {
+ let res = match err {
+ None => Ok(accum_sockaddrs(addrinfo).map(|addr| addr.ip.clone())),
+ Some(err) => Err(uv_error_to_io_error(err))
+ };
+ (*result_cell_ptr).put_back(res);
+ let scheduler: ~Scheduler = Local::take();
+ scheduler.resume_blocked_task_immediately(task_cell.take());
+ }
+ }
+ }
+ }
+ addrinfo_req.delete();
+ assert!(!result_cell.is_empty());
+ return result_cell.take();
+ }
}
pub struct UvTcpListener {
uvll::tcp_simultaneous_accepts(self_.listener.watcher.native_handle(), 1 as c_int)
};
- match status_to_maybe_uv_error(self_.listener.watcher, r) {
+ match status_to_maybe_uv_error(r) {
Some(err) => Err(uv_error_to_io_error(err)),
None => Ok(())
}
uvll::tcp_simultaneous_accepts(self_.listener.watcher.native_handle(), 0 as c_int)
};
- match status_to_maybe_uv_error(self_.listener.watcher, r) {
+ match status_to_maybe_uv_error(r) {
Some(err) => Err(uv_error_to_io_error(err)),
None => Ok(())
}
do self.home_for_io |self_| {
let r = unsafe { uvll::tcp_nodelay(self_.watcher.native_handle(), 0 as c_int) };
- match status_to_maybe_uv_error(self_.watcher, r) {
+ match status_to_maybe_uv_error(r) {
Some(err) => Err(uv_error_to_io_error(err)),
None => Ok(())
}
do self.home_for_io |self_| {
let r = unsafe { uvll::tcp_nodelay(self_.watcher.native_handle(), 1 as c_int) };
- match status_to_maybe_uv_error(self_.watcher, r) {
+ match status_to_maybe_uv_error(r) {
Some(err) => Err(uv_error_to_io_error(err)),
None => Ok(())
}
delay_in_seconds as c_uint)
};
- match status_to_maybe_uv_error(self_.watcher, r) {
+ match status_to_maybe_uv_error(r) {
Some(err) => Err(uv_error_to_io_error(err)),
None => Ok(())
}
uvll::tcp_keepalive(self_.watcher.native_handle(), 0 as c_int, 0 as c_uint)
};
- match status_to_maybe_uv_error(self_.watcher, r) {
+ match status_to_maybe_uv_error(r) {
Some(err) => Err(uv_error_to_io_error(err)),
None => Ok(())
}
}
};
- match status_to_maybe_uv_error(self_.watcher, r) {
+ match status_to_maybe_uv_error(r) {
Some(err) => Err(uv_error_to_io_error(err)),
None => Ok(())
}
}
};
- match status_to_maybe_uv_error(self_.watcher, r) {
+ match status_to_maybe_uv_error(r) {
Some(err) => Err(uv_error_to_io_error(err)),
None => Ok(())
}
uvll::udp_set_multicast_loop(self_.watcher.native_handle(), 1 as c_int)
};
- match status_to_maybe_uv_error(self_.watcher, r) {
+ match status_to_maybe_uv_error(r) {
Some(err) => Err(uv_error_to_io_error(err)),
None => Ok(())
}
uvll::udp_set_multicast_loop(self_.watcher.native_handle(), 0 as c_int)
};
- match status_to_maybe_uv_error(self_.watcher, r) {
+ match status_to_maybe_uv_error(r) {
Some(err) => Err(uv_error_to_io_error(err)),
None => Ok(())
}
uvll::udp_set_multicast_ttl(self_.watcher.native_handle(), ttl as c_int)
};
- match status_to_maybe_uv_error(self_.watcher, r) {
+ match status_to_maybe_uv_error(r) {
Some(err) => Err(uv_error_to_io_error(err)),
None => Ok(())
}
uvll::udp_set_ttl(self_.watcher.native_handle(), ttl as c_int)
};
- match status_to_maybe_uv_error(self_.watcher, r) {
+ match status_to_maybe_uv_error(r) {
Some(err) => Err(uv_error_to_io_error(err)),
None => Ok(())
}
uvll::udp_set_broadcast(self_.watcher.native_handle(), 1 as c_int)
};
- match status_to_maybe_uv_error(self_.watcher, r) {
+ match status_to_maybe_uv_error(r) {
Some(err) => Err(uv_error_to_io_error(err)),
None => Ok(())
}
uvll::udp_set_broadcast(self_.watcher.native_handle(), 0 as c_int)
};
- match status_to_maybe_uv_error(self_.watcher, r) {
+ match status_to_maybe_uv_error(r) {
Some(err) => Err(uv_error_to_io_error(err)),
None => Ok(())
}
use libc;
use prelude::*;
use ptr;
-use str;
use vec;
-pub static UNKNOWN: c_int = -1;
+pub use self::errors::*;
+
pub static OK: c_int = 0;
-pub static EOF: c_int = 1;
-pub static EADDRINFO: c_int = 2;
-pub static EACCES: c_int = 3;
-pub static ECONNREFUSED: c_int = 12;
-pub static ECONNRESET: c_int = 13;
-pub static EPIPE: c_int = 36;
+pub static EOF: c_int = -4095;
+pub static UNKNOWN: c_int = -4094;
+
+// uv-errno.h redefines error codes for windows, but not for unix...
+
+#[cfg(windows)]
+pub mod errors {
+ use libc::c_int;
-pub struct uv_err_t {
- code: c_int,
- sys_errno_: c_int
+ pub static EACCES: c_int = -4093;
+ pub static ECONNREFUSED: c_int = -4079;
+ pub static ECONNRESET: c_int = -4078;
+ pub static EPIPE: c_int = -4048;
+}
+#[cfg(not(windows))]
+pub mod errors {
+ use libc;
+ use libc::c_int;
+
+ pub static EACCES: c_int = -libc::EACCES;
+ pub static ECONNREFUSED: c_int = -libc::ECONNREFUSED;
+ pub static ECONNRESET: c_int = -libc::ECONNRESET;
+ pub static EPIPE: c_int = -libc::EPIPE;
}
pub struct uv_buf_t {
pub type uv_stream_t = c_void;
pub type uv_fs_t = c_void;
pub type uv_udp_send_t = c_void;
+pub type uv_getaddrinfo_t = c_void;
#[cfg(stage0)]
pub type uv_idle_cb = *u8;
pub type uv_timer_cb = *u8;
#[cfg(stage0)]
pub type uv_write_cb = *u8;
+#[cfg(stage0)]
+pub type uv_getaddrinfo_cb = *u8;
#[cfg(not(stage0))]
pub type uv_idle_cb = extern "C" fn(handle: *uv_idle_t,
#[cfg(not(stage0))]
pub type uv_write_cb = extern "C" fn(handle: *uv_write_t,
status: c_int);
+#[cfg(not(stage0))]
+pub type uv_getaddrinfo_cb = extern "C" fn(req: *uv_getaddrinfo_t,
+ status: c_int,
+ res: *addrinfo);
pub type sockaddr = c_void;
pub type sockaddr_in = c_void;
pub type sockaddr_in6 = c_void;
pub type sockaddr_storage = c_void;
+#[cfg(unix)]
+pub type socklen_t = c_int;
+
+// 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: 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: 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
+}
+
#[deriving(Eq)]
pub enum uv_handle_type {
UV_UNKNOWN_HANDLE,
return rust_uv_read_stop(stream as *c_void);
}
-pub unsafe fn last_error(loop_handle: *c_void) -> uv_err_t {
+pub unsafe fn strerror(err: c_int) -> *c_char {
#[fixed_stack_segment]; #[inline(never)];
-
- return rust_uv_last_error(loop_handle);
-}
-
-pub unsafe fn strerror(err: *uv_err_t) -> *c_char {
- #[fixed_stack_segment]; #[inline(never)];
-
return rust_uv_strerror(err);
}
-pub unsafe fn err_name(err: *uv_err_t) -> *c_char {
+pub unsafe fn err_name(err: c_int) -> *c_char {
#[fixed_stack_segment]; #[inline(never)];
-
return rust_uv_err_name(err);
}
rust_uv_get_loop_from_fs_req(req)
}
+pub unsafe fn get_loop_from_getaddrinfo_req(req: *uv_getaddrinfo_t) -> *uv_loop_t {
+ #[fixed_stack_segment]; #[inline(never)];
+
+ rust_uv_get_loop_from_getaddrinfo_req(req)
+}
pub unsafe fn get_loop_for_uv_handle<T>(handle: *T) -> *c_void {
#[fixed_stack_segment]; #[inline(never)];
return rust_uv_get_len_from_buf(buf);
}
-pub unsafe fn get_last_err_info(uv_loop: *c_void) -> ~str {
- let err = last_error(uv_loop);
- let err_ptr = ptr::to_unsafe_ptr(&err);
- let err_name = str::raw::from_c_str(err_name(err_ptr));
- let err_msg = str::raw::from_c_str(strerror(err_ptr));
- return fmt!("LIBUV ERROR: name: %s msg: %s",
- err_name, err_msg);
+pub unsafe fn getaddrinfo(loop_: *uv_loop_t, req: *uv_getaddrinfo_t,
+ getaddrinfo_cb: uv_getaddrinfo_cb,
+ node: *c_char, service: *c_char,
+ hints: *addrinfo) -> c_int {
+ #[fixed_stack_segment]; #[inline(never)];
+ return rust_uv_getaddrinfo(loop_, req, getaddrinfo_cb, node, service, hints);
}
-
-pub unsafe fn get_last_err_data(uv_loop: *c_void) -> uv_err_data {
- let err = last_error(uv_loop);
- let err_ptr = ptr::to_unsafe_ptr(&err);
- let err_name = str::raw::from_c_str(err_name(err_ptr));
- let err_msg = str::raw::from_c_str(strerror(err_ptr));
- uv_err_data { err_name: err_name, err_msg: err_msg }
+pub unsafe fn freeaddrinfo(ai: *addrinfo) {
+ #[fixed_stack_segment]; #[inline(never)];
+ rust_uv_freeaddrinfo(ai);
}
pub struct uv_err_data {
cb: uv_async_cb) -> c_int;
fn rust_uv_tcp_init(loop_handle: *c_void, handle_ptr: *uv_tcp_t) -> c_int;
fn rust_uv_buf_init(out_buf: *uv_buf_t, base: *u8, len: size_t);
- fn rust_uv_last_error(loop_handle: *c_void) -> uv_err_t;
- fn rust_uv_strerror(err: *uv_err_t) -> *c_char;
- fn rust_uv_err_name(err: *uv_err_t) -> *c_char;
+ fn rust_uv_strerror(err: c_int) -> *c_char;
+ fn rust_uv_err_name(err: c_int) -> *c_char;
fn rust_uv_ip4_addrp(ip: *u8, port: c_int) -> *sockaddr_in;
fn rust_uv_ip6_addrp(ip: *u8, port: c_int) -> *sockaddr_in6;
fn rust_uv_free_ip4_addr(addr: *sockaddr_in);
fn rust_uv_fs_req_cleanup(req: *uv_fs_t);
fn rust_uv_get_result_from_fs_req(req: *uv_fs_t) -> c_int;
fn rust_uv_get_loop_from_fs_req(req: *uv_fs_t) -> *uv_loop_t;
+ fn rust_uv_get_loop_from_getaddrinfo_req(req: *uv_fs_t) -> *uv_loop_t;
fn rust_uv_get_stream_handle_from_connect_req(connect_req: *uv_connect_t) -> *uv_stream_t;
fn rust_uv_get_stream_handle_from_write_req(write_req: *uv_write_t) -> *uv_stream_t;
fn rust_uv_set_data_for_req(req: *c_void, data: *c_void);
fn rust_uv_get_base_from_buf(buf: uv_buf_t) -> *u8;
fn rust_uv_get_len_from_buf(buf: uv_buf_t) -> size_t;
+ fn rust_uv_getaddrinfo(loop_: *uv_loop_t, req: *uv_getaddrinfo_t,
+ getaddrinfo_cb: uv_getaddrinfo_cb,
+ node: *c_char, service: *c_char,
+ hints: *addrinfo) -> c_int;
+ fn rust_uv_freeaddrinfo(ai: *addrinfo);
}
fn shrink_to_fit(&mut self);
fn push(&mut self, t: T);
- unsafe fn push_fast(&mut self, t: T);
-
fn push_all_move(&mut self, rhs: ~[T]);
fn pop(&mut self) -> T;
fn pop_opt(&mut self) -> Option<T>;
self.reserve_at_least(new_len);
}
- self.push_fast(t);
+ push_fast(self, t);
} else {
let repr: **Vec<()> = cast::transmute(&mut *self);
let fill = (**repr).fill;
self.reserve_at_least(new_len);
}
- self.push_fast(t);
+ push_fast(self, t);
}
}
- }
- // This doesn't bother to make sure we have space.
- #[inline] // really pretty please
- unsafe fn push_fast(&mut self, t: T) {
- if contains_managed::<T>() {
- let repr: **mut Box<Vec<u8>> = cast::transmute(self);
- let fill = (**repr).data.fill;
- (**repr).data.fill += sys::nonzero_size_of::<T>();
- let p = to_unsafe_ptr(&((**repr).data.data));
- let p = ptr::offset(p, fill as int) as *mut T;
- intrinsics::move_val_init(&mut(*p), t);
- } else {
- let repr: **mut Vec<u8> = cast::transmute(self);
- let fill = (**repr).fill;
- (**repr).fill += sys::nonzero_size_of::<T>();
- let p = to_unsafe_ptr(&((**repr).data));
- let p = ptr::offset(p, fill as int) as *mut T;
- intrinsics::move_val_init(&mut(*p), t);
+ // This doesn't bother to make sure we have space.
+ #[inline] // really pretty please
+ unsafe fn push_fast<T>(this: &mut ~[T], t: T) {
+ if contains_managed::<T>() {
+ let repr: **mut Box<Vec<u8>> = cast::transmute(this);
+ let fill = (**repr).data.fill;
+ (**repr).data.fill += sys::nonzero_size_of::<T>();
+ let p = to_unsafe_ptr(&((**repr).data.data));
+ let p = ptr::offset(p, fill as int) as *mut T;
+ intrinsics::move_val_init(&mut(*p), t);
+ } else {
+ let repr: **mut Vec<u8> = cast::transmute(this);
+ let fill = (**repr).fill;
+ (**repr).fill += sys::nonzero_size_of::<T>();
+ let p = to_unsafe_ptr(&((**repr).data));
+ let p = ptr::offset(p, fill as int) as *mut T;
+ intrinsics::move_val_init(&mut(*p), t);
+ }
}
+
}
/// Takes ownership of the vector `rhs`, moving all elements into
-Subproject commit dfae9c3e958dc086d9c0ab068cd76d196c95a433
+Subproject commit d88cf5652a1afb23939da0bae86c70ec521b9921
return buf.len;
}
-extern "C" uv_err_t
-rust_uv_last_error(uv_loop_t* loop) {
- return uv_last_error(loop);
-}
-
extern "C" const char*
-rust_uv_strerror(uv_err_t* err_ptr) {
- uv_err_t err = *err_ptr;
+rust_uv_strerror(int err) {
return uv_strerror(err);
}
extern "C" const char*
-rust_uv_err_name(uv_err_t* err_ptr) {
- uv_err_t err = *err_ptr;
+rust_uv_err_name(int err) {
return uv_err_name(err);
}
rust_uv_get_loop_from_fs_req(uv_fs_t* req) {
return req->loop;
}
+
+extern "C" uv_loop_t*
+rust_uv_get_loop_from_getaddrinfo_req(uv_getaddrinfo_t* req) {
+ return req->loop;
+}
rust_uv_timer_stop
rust_uv_tcp_init
rust_uv_buf_init
-rust_uv_last_error
rust_uv_strerror
rust_uv_err_name
rust_uv_ip4_addr
rust_drop_change_dir_lock
rust_get_test_int
rust_get_task
+rust_uv_get_loop_from_getaddrinfo_req