2013-10-22 17:13:18 -05:00
|
|
|
// 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.
|
|
|
|
|
2014-05-05 20:56:44 -05:00
|
|
|
use libc::{size_t, ssize_t, c_int, c_void, c_uint};
|
|
|
|
use libc;
|
2014-01-17 21:33:29 -06:00
|
|
|
use std::mem;
|
2013-12-12 19:47:48 -06:00
|
|
|
use std::ptr;
|
2013-11-05 02:27:41 -06:00
|
|
|
use std::rt::rtio;
|
2014-06-04 02:00:59 -05:00
|
|
|
use std::rt::rtio::IoError;
|
2013-12-12 19:47:48 -06:00
|
|
|
use std::rt::task::BlockedTask;
|
2013-10-22 17:13:18 -05:00
|
|
|
|
2013-12-12 19:47:48 -06:00
|
|
|
use homing::{HomingIO, HomeHandle};
|
2014-01-22 21:32:16 -06:00
|
|
|
use rc::Refcount;
|
2013-11-05 13:29:45 -06:00
|
|
|
use stream::StreamWatcher;
|
|
|
|
use super::{Loop, Request, UvError, Buf, status_to_io_result,
|
2013-11-07 17:13:06 -06:00
|
|
|
uv_error_to_io_error, UvHandle, slice_to_uv_buf,
|
2013-12-12 19:47:48 -06:00
|
|
|
wait_until_woken_after, wakeup};
|
2014-04-27 17:45:16 -05:00
|
|
|
use timeout::{AccessTimeout, AcceptTimeout, ConnectCtx};
|
2013-12-12 19:47:48 -06:00
|
|
|
use uvio::UvIoFactory;
|
2013-11-05 13:29:45 -06:00
|
|
|
use uvll;
|
2013-10-22 17:13:18 -05:00
|
|
|
|
2013-11-05 02:27:41 -06:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
/// Generic functions related to dealing with sockaddr things
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2013-10-22 17:13:18 -05:00
|
|
|
|
2014-04-14 05:04:14 -05:00
|
|
|
pub fn htons(u: u16) -> u16 { mem::to_be16(u) }
|
|
|
|
pub fn ntohs(u: u16) -> u16 { mem::from_be16(u) }
|
2013-10-22 17:13:18 -05:00
|
|
|
|
2014-01-17 21:33:29 -06:00
|
|
|
pub fn sockaddr_to_addr(storage: &libc::sockaddr_storage,
|
2014-06-04 02:00:59 -05:00
|
|
|
len: uint) -> rtio::SocketAddr {
|
2014-01-17 21:33:29 -06:00
|
|
|
match storage.ss_family as c_int {
|
|
|
|
libc::AF_INET => {
|
|
|
|
assert!(len as uint >= mem::size_of::<libc::sockaddr_in>());
|
|
|
|
let storage: &libc::sockaddr_in = unsafe {
|
core: Remove the cast module
This commit revisits the `cast` module in libcore and libstd, and scrutinizes
all functions inside of it. The result was to remove the `cast` module entirely,
folding all functionality into the `mem` module. Specifically, this is the fate
of each function in the `cast` module.
* transmute - This function was moved to `mem`, but it is now marked as
#[unstable]. This is due to planned changes to the `transmute`
function and how it can be invoked (see the #[unstable] comment).
For more information, see RFC 5 and #12898
* transmute_copy - This function was moved to `mem`, with clarification that is
is not an error to invoke it with T/U that are different
sizes, but rather that it is strongly discouraged. This
function is now #[stable]
* forget - This function was moved to `mem` and marked #[stable]
* bump_box_refcount - This function was removed due to the deprecation of
managed boxes as well as its questionable utility.
* transmute_mut - This function was previously deprecated, and removed as part
of this commit.
* transmute_mut_unsafe - This function doesn't serve much of a purpose when it
can be achieved with an `as` in safe code, so it was
removed.
* transmute_lifetime - This function was removed because it is likely a strong
indication that code is incorrect in the first place.
* transmute_mut_lifetime - This function was removed for the same reasons as
`transmute_lifetime`
* copy_lifetime - This function was moved to `mem`, but it is marked
`#[unstable]` now due to the likelihood of being removed in
the future if it is found to not be very useful.
* copy_mut_lifetime - This function was also moved to `mem`, but had the same
treatment as `copy_lifetime`.
* copy_lifetime_vec - This function was removed because it is not used today,
and its existence is not necessary with DST
(copy_lifetime will suffice).
In summary, the cast module was stripped down to these functions, and then the
functions were moved to the `mem` module.
transmute - #[unstable]
transmute_copy - #[stable]
forget - #[stable]
copy_lifetime - #[unstable]
copy_mut_lifetime - #[unstable]
[breaking-change]
2014-05-09 12:34:51 -05:00
|
|
|
mem::transmute(storage)
|
2013-11-25 23:59:08 -06:00
|
|
|
};
|
2014-05-27 04:00:50 -05:00
|
|
|
let ip = mem::to_be32(storage.sin_addr.s_addr as u32);
|
|
|
|
let a = (ip >> 24) as u8;
|
|
|
|
let b = (ip >> 16) as u8;
|
|
|
|
let c = (ip >> 8) as u8;
|
|
|
|
let d = (ip >> 0) as u8;
|
2014-06-04 02:00:59 -05:00
|
|
|
rtio::SocketAddr {
|
|
|
|
ip: rtio::Ipv4Addr(a, b, c, d),
|
2014-01-17 21:33:29 -06:00
|
|
|
port: ntohs(storage.sin_port),
|
2013-10-22 17:13:18 -05:00
|
|
|
}
|
2014-01-17 21:33:29 -06:00
|
|
|
}
|
|
|
|
libc::AF_INET6 => {
|
|
|
|
assert!(len as uint >= mem::size_of::<libc::sockaddr_in6>());
|
|
|
|
let storage: &libc::sockaddr_in6 = unsafe {
|
core: Remove the cast module
This commit revisits the `cast` module in libcore and libstd, and scrutinizes
all functions inside of it. The result was to remove the `cast` module entirely,
folding all functionality into the `mem` module. Specifically, this is the fate
of each function in the `cast` module.
* transmute - This function was moved to `mem`, but it is now marked as
#[unstable]. This is due to planned changes to the `transmute`
function and how it can be invoked (see the #[unstable] comment).
For more information, see RFC 5 and #12898
* transmute_copy - This function was moved to `mem`, with clarification that is
is not an error to invoke it with T/U that are different
sizes, but rather that it is strongly discouraged. This
function is now #[stable]
* forget - This function was moved to `mem` and marked #[stable]
* bump_box_refcount - This function was removed due to the deprecation of
managed boxes as well as its questionable utility.
* transmute_mut - This function was previously deprecated, and removed as part
of this commit.
* transmute_mut_unsafe - This function doesn't serve much of a purpose when it
can be achieved with an `as` in safe code, so it was
removed.
* transmute_lifetime - This function was removed because it is likely a strong
indication that code is incorrect in the first place.
* transmute_mut_lifetime - This function was removed for the same reasons as
`transmute_lifetime`
* copy_lifetime - This function was moved to `mem`, but it is marked
`#[unstable]` now due to the likelihood of being removed in
the future if it is found to not be very useful.
* copy_mut_lifetime - This function was also moved to `mem`, but had the same
treatment as `copy_lifetime`.
* copy_lifetime_vec - This function was removed because it is not used today,
and its existence is not necessary with DST
(copy_lifetime will suffice).
In summary, the cast module was stripped down to these functions, and then the
functions were moved to the `mem` module.
transmute - #[unstable]
transmute_copy - #[stable]
forget - #[stable]
copy_lifetime - #[unstable]
copy_mut_lifetime - #[unstable]
[breaking-change]
2014-05-09 12:34:51 -05:00
|
|
|
mem::transmute(storage)
|
2013-11-07 17:26:47 -06:00
|
|
|
};
|
2014-01-17 21:33:29 -06:00
|
|
|
let a = ntohs(storage.sin6_addr.s6_addr[0]);
|
|
|
|
let b = ntohs(storage.sin6_addr.s6_addr[1]);
|
|
|
|
let c = ntohs(storage.sin6_addr.s6_addr[2]);
|
|
|
|
let d = ntohs(storage.sin6_addr.s6_addr[3]);
|
|
|
|
let e = ntohs(storage.sin6_addr.s6_addr[4]);
|
|
|
|
let f = ntohs(storage.sin6_addr.s6_addr[5]);
|
|
|
|
let g = ntohs(storage.sin6_addr.s6_addr[6]);
|
|
|
|
let h = ntohs(storage.sin6_addr.s6_addr[7]);
|
2014-06-04 02:00:59 -05:00
|
|
|
rtio::SocketAddr {
|
|
|
|
ip: rtio::Ipv6Addr(a, b, c, d, e, f, g, h),
|
2014-01-17 21:33:29 -06:00
|
|
|
port: ntohs(storage.sin6_port),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
n => {
|
|
|
|
fail!("unknown family {}", n);
|
|
|
|
}
|
2013-11-07 17:26:47 -06:00
|
|
|
}
|
2013-10-22 17:13:18 -05:00
|
|
|
}
|
|
|
|
|
2014-06-04 02:00:59 -05:00
|
|
|
fn addr_to_sockaddr(addr: rtio::SocketAddr) -> (libc::sockaddr_storage, uint) {
|
2014-01-17 21:33:29 -06:00
|
|
|
unsafe {
|
2014-05-17 02:56:00 -05:00
|
|
|
let mut storage: libc::sockaddr_storage = mem::zeroed();
|
2014-01-17 21:33:29 -06:00
|
|
|
let len = match addr.ip {
|
2014-06-04 02:00:59 -05:00
|
|
|
rtio::Ipv4Addr(a, b, c, d) => {
|
2014-05-27 04:00:50 -05:00
|
|
|
let ip = (a as u32 << 24) |
|
|
|
|
(b as u32 << 16) |
|
|
|
|
(c as u32 << 8) |
|
|
|
|
(d as u32 << 0);
|
2014-01-17 21:33:29 -06:00
|
|
|
let storage: &mut libc::sockaddr_in =
|
core: Remove the cast module
This commit revisits the `cast` module in libcore and libstd, and scrutinizes
all functions inside of it. The result was to remove the `cast` module entirely,
folding all functionality into the `mem` module. Specifically, this is the fate
of each function in the `cast` module.
* transmute - This function was moved to `mem`, but it is now marked as
#[unstable]. This is due to planned changes to the `transmute`
function and how it can be invoked (see the #[unstable] comment).
For more information, see RFC 5 and #12898
* transmute_copy - This function was moved to `mem`, with clarification that is
is not an error to invoke it with T/U that are different
sizes, but rather that it is strongly discouraged. This
function is now #[stable]
* forget - This function was moved to `mem` and marked #[stable]
* bump_box_refcount - This function was removed due to the deprecation of
managed boxes as well as its questionable utility.
* transmute_mut - This function was previously deprecated, and removed as part
of this commit.
* transmute_mut_unsafe - This function doesn't serve much of a purpose when it
can be achieved with an `as` in safe code, so it was
removed.
* transmute_lifetime - This function was removed because it is likely a strong
indication that code is incorrect in the first place.
* transmute_mut_lifetime - This function was removed for the same reasons as
`transmute_lifetime`
* copy_lifetime - This function was moved to `mem`, but it is marked
`#[unstable]` now due to the likelihood of being removed in
the future if it is found to not be very useful.
* copy_mut_lifetime - This function was also moved to `mem`, but had the same
treatment as `copy_lifetime`.
* copy_lifetime_vec - This function was removed because it is not used today,
and its existence is not necessary with DST
(copy_lifetime will suffice).
In summary, the cast module was stripped down to these functions, and then the
functions were moved to the `mem` module.
transmute - #[unstable]
transmute_copy - #[stable]
forget - #[stable]
copy_lifetime - #[unstable]
copy_mut_lifetime - #[unstable]
[breaking-change]
2014-05-09 12:34:51 -05:00
|
|
|
mem::transmute(&mut storage);
|
2014-01-17 21:33:29 -06:00
|
|
|
(*storage).sin_family = libc::AF_INET as libc::sa_family_t;
|
|
|
|
(*storage).sin_port = htons(addr.port);
|
|
|
|
(*storage).sin_addr = libc::in_addr {
|
2014-05-27 04:00:50 -05:00
|
|
|
s_addr: mem::from_be32(ip)
|
2014-01-17 21:33:29 -06:00
|
|
|
};
|
|
|
|
mem::size_of::<libc::sockaddr_in>()
|
|
|
|
}
|
2014-06-04 02:00:59 -05:00
|
|
|
rtio::Ipv6Addr(a, b, c, d, e, f, g, h) => {
|
2014-01-17 21:33:29 -06:00
|
|
|
let storage: &mut libc::sockaddr_in6 =
|
core: Remove the cast module
This commit revisits the `cast` module in libcore and libstd, and scrutinizes
all functions inside of it. The result was to remove the `cast` module entirely,
folding all functionality into the `mem` module. Specifically, this is the fate
of each function in the `cast` module.
* transmute - This function was moved to `mem`, but it is now marked as
#[unstable]. This is due to planned changes to the `transmute`
function and how it can be invoked (see the #[unstable] comment).
For more information, see RFC 5 and #12898
* transmute_copy - This function was moved to `mem`, with clarification that is
is not an error to invoke it with T/U that are different
sizes, but rather that it is strongly discouraged. This
function is now #[stable]
* forget - This function was moved to `mem` and marked #[stable]
* bump_box_refcount - This function was removed due to the deprecation of
managed boxes as well as its questionable utility.
* transmute_mut - This function was previously deprecated, and removed as part
of this commit.
* transmute_mut_unsafe - This function doesn't serve much of a purpose when it
can be achieved with an `as` in safe code, so it was
removed.
* transmute_lifetime - This function was removed because it is likely a strong
indication that code is incorrect in the first place.
* transmute_mut_lifetime - This function was removed for the same reasons as
`transmute_lifetime`
* copy_lifetime - This function was moved to `mem`, but it is marked
`#[unstable]` now due to the likelihood of being removed in
the future if it is found to not be very useful.
* copy_mut_lifetime - This function was also moved to `mem`, but had the same
treatment as `copy_lifetime`.
* copy_lifetime_vec - This function was removed because it is not used today,
and its existence is not necessary with DST
(copy_lifetime will suffice).
In summary, the cast module was stripped down to these functions, and then the
functions were moved to the `mem` module.
transmute - #[unstable]
transmute_copy - #[stable]
forget - #[stable]
copy_lifetime - #[unstable]
copy_mut_lifetime - #[unstable]
[breaking-change]
2014-05-09 12:34:51 -05:00
|
|
|
mem::transmute(&mut storage);
|
2014-01-17 21:33:29 -06:00
|
|
|
storage.sin6_family = libc::AF_INET6 as libc::sa_family_t;
|
|
|
|
storage.sin6_port = htons(addr.port);
|
|
|
|
storage.sin6_addr = libc::in6_addr {
|
|
|
|
s6_addr: [
|
|
|
|
htons(a),
|
|
|
|
htons(b),
|
|
|
|
htons(c),
|
|
|
|
htons(d),
|
|
|
|
htons(e),
|
|
|
|
htons(f),
|
|
|
|
htons(g),
|
|
|
|
htons(h),
|
|
|
|
]
|
|
|
|
};
|
|
|
|
mem::size_of::<libc::sockaddr_in6>()
|
|
|
|
}
|
|
|
|
};
|
|
|
|
return (storage, len);
|
|
|
|
}
|
2013-10-22 17:13:18 -05:00
|
|
|
}
|
|
|
|
|
2013-11-05 02:27:41 -06:00
|
|
|
enum SocketNameKind {
|
|
|
|
TcpPeer,
|
|
|
|
Tcp,
|
|
|
|
Udp
|
|
|
|
}
|
2013-10-22 17:13:18 -05:00
|
|
|
|
2014-01-17 21:33:29 -06:00
|
|
|
fn socket_name(sk: SocketNameKind,
|
2014-06-04 02:00:59 -05:00
|
|
|
handle: *c_void) -> Result<rtio::SocketAddr, IoError> {
|
2014-01-17 21:33:29 -06:00
|
|
|
let getsockname = match sk {
|
|
|
|
TcpPeer => uvll::uv_tcp_getpeername,
|
|
|
|
Tcp => uvll::uv_tcp_getsockname,
|
|
|
|
Udp => uvll::uv_udp_getsockname,
|
|
|
|
};
|
2013-10-22 17:13:18 -05:00
|
|
|
|
2014-01-17 21:33:29 -06:00
|
|
|
// Allocate a sockaddr_storage since we don't know if it's ipv4 or ipv6
|
2014-05-17 02:56:00 -05:00
|
|
|
let mut sockaddr: libc::sockaddr_storage = unsafe { mem::zeroed() };
|
2014-01-17 21:33:29 -06:00
|
|
|
let mut namelen = mem::size_of::<libc::sockaddr_storage>() as c_int;
|
2013-10-22 17:13:18 -05:00
|
|
|
|
2014-01-17 21:33:29 -06:00
|
|
|
let sockaddr_p = &mut sockaddr as *mut libc::sockaddr_storage;
|
|
|
|
match unsafe {
|
|
|
|
getsockname(handle, sockaddr_p as *mut libc::sockaddr, &mut namelen)
|
|
|
|
} {
|
|
|
|
0 => Ok(sockaddr_to_addr(&sockaddr, namelen as uint)),
|
|
|
|
n => Err(uv_error_to_io_error(UvError(n)))
|
2013-10-22 17:13:18 -05:00
|
|
|
}
|
2013-11-05 02:27:41 -06:00
|
|
|
}
|
2014-04-22 20:38:59 -05:00
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
/// TCP implementation
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
pub struct TcpWatcher {
|
|
|
|
handle: *uvll::uv_tcp_t,
|
|
|
|
stream: StreamWatcher,
|
|
|
|
home: HomeHandle,
|
|
|
|
refcount: Refcount,
|
|
|
|
|
|
|
|
// libuv can't support concurrent reads and concurrent writes of the same
|
|
|
|
// stream object, so we use these access guards in order to arbitrate among
|
|
|
|
// multiple concurrent reads and writes. Note that libuv *can* read and
|
|
|
|
// write simultaneously, it just can't read and read simultaneously.
|
2014-04-27 17:45:16 -05:00
|
|
|
read_access: AccessTimeout,
|
|
|
|
write_access: AccessTimeout,
|
2014-04-22 20:38:59 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
pub struct TcpListener {
|
|
|
|
home: HomeHandle,
|
|
|
|
handle: *uvll::uv_pipe_t,
|
2014-06-14 13:03:34 -05:00
|
|
|
outgoing: Sender<Result<Box<rtio::RtioTcpStream + Send>, IoError>>,
|
|
|
|
incoming: Receiver<Result<Box<rtio::RtioTcpStream + Send>, IoError>>,
|
2014-04-22 20:38:59 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
pub struct TcpAcceptor {
|
2014-05-05 20:56:44 -05:00
|
|
|
listener: Box<TcpListener>,
|
2014-04-22 20:38:59 -05:00
|
|
|
timeout: AcceptTimeout,
|
|
|
|
}
|
|
|
|
|
|
|
|
// TCP watchers (clients/streams)
|
|
|
|
|
|
|
|
impl TcpWatcher {
|
|
|
|
pub fn new(io: &mut UvIoFactory) -> TcpWatcher {
|
|
|
|
let handle = io.make_handle();
|
|
|
|
TcpWatcher::new_home(&io.loop_, handle)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn new_home(loop_: &Loop, home: HomeHandle) -> TcpWatcher {
|
|
|
|
let handle = unsafe { uvll::malloc_handle(uvll::UV_TCP) };
|
|
|
|
assert_eq!(unsafe {
|
|
|
|
uvll::uv_tcp_init(loop_.handle, handle)
|
|
|
|
}, 0);
|
|
|
|
TcpWatcher {
|
|
|
|
home: home,
|
|
|
|
handle: handle,
|
|
|
|
stream: StreamWatcher::new(handle),
|
|
|
|
refcount: Refcount::new(),
|
2014-04-27 17:45:16 -05:00
|
|
|
read_access: AccessTimeout::new(),
|
|
|
|
write_access: AccessTimeout::new(),
|
2014-04-22 20:38:59 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn connect(io: &mut UvIoFactory,
|
2014-06-04 02:00:59 -05:00
|
|
|
address: rtio::SocketAddr,
|
2014-04-22 20:38:59 -05:00
|
|
|
timeout: Option<u64>) -> Result<TcpWatcher, UvError> {
|
|
|
|
let tcp = TcpWatcher::new(io);
|
|
|
|
let cx = ConnectCtx { status: -1, task: None, timer: None };
|
|
|
|
let (addr, _len) = addr_to_sockaddr(address);
|
|
|
|
let addr_p = &addr as *_ as *libc::sockaddr;
|
|
|
|
cx.connect(tcp, timeout, io, |req, tcp, cb| {
|
|
|
|
unsafe { uvll::uv_tcp_connect(req.handle, tcp.handle, addr_p, cb) }
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-11-05 02:27:41 -06:00
|
|
|
impl HomingIO for TcpWatcher {
|
2013-12-12 19:47:48 -06:00
|
|
|
fn home<'r>(&'r mut self) -> &'r mut HomeHandle { &mut self.home }
|
2013-11-05 02:27:41 -06:00
|
|
|
}
|
2013-10-22 17:13:18 -05:00
|
|
|
|
2013-11-05 02:27:41 -06:00
|
|
|
impl rtio::RtioSocket for TcpWatcher {
|
2014-06-04 02:00:59 -05:00
|
|
|
fn socket_name(&mut self) -> Result<rtio::SocketAddr, IoError> {
|
2013-11-06 01:29:11 -06:00
|
|
|
let _m = self.fire_homing_missile();
|
2013-11-05 02:27:41 -06:00
|
|
|
socket_name(Tcp, self.handle)
|
2013-10-22 17:13:18 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-11-05 02:27:41 -06:00
|
|
|
impl rtio::RtioTcpStream for TcpWatcher {
|
|
|
|
fn read(&mut self, buf: &mut [u8]) -> Result<uint, IoError> {
|
2014-01-22 21:32:16 -06:00
|
|
|
let m = self.fire_homing_missile();
|
2014-04-27 17:45:16 -05:00
|
|
|
let guard = try!(self.read_access.grant(m));
|
2014-04-24 20:48:21 -05:00
|
|
|
|
|
|
|
// see comments in close_read about this check
|
2014-04-27 17:45:16 -05:00
|
|
|
if guard.access.is_closed() {
|
2014-06-04 02:00:59 -05:00
|
|
|
return Err(uv_error_to_io_error(UvError(uvll::EOF)))
|
2014-04-24 20:48:21 -05:00
|
|
|
}
|
|
|
|
|
2013-11-05 02:27:41 -06:00
|
|
|
self.stream.read(buf).map_err(uv_error_to_io_error)
|
2013-10-22 17:13:18 -05:00
|
|
|
}
|
2013-11-05 02:27:41 -06:00
|
|
|
|
|
|
|
fn write(&mut self, buf: &[u8]) -> Result<(), IoError> {
|
2014-01-22 21:32:16 -06:00
|
|
|
let m = self.fire_homing_missile();
|
2014-04-27 17:45:16 -05:00
|
|
|
let guard = try!(self.write_access.grant(m));
|
|
|
|
self.stream.write(buf, guard.can_timeout).map_err(uv_error_to_io_error)
|
2013-10-22 17:13:18 -05:00
|
|
|
}
|
|
|
|
|
2014-06-04 02:00:59 -05:00
|
|
|
fn peer_name(&mut self) -> Result<rtio::SocketAddr, IoError> {
|
2013-11-06 01:29:11 -06:00
|
|
|
let _m = self.fire_homing_missile();
|
2013-11-05 02:27:41 -06:00
|
|
|
socket_name(TcpPeer, self.handle)
|
|
|
|
}
|
2013-10-22 17:13:18 -05:00
|
|
|
|
2013-11-05 02:27:41 -06:00
|
|
|
fn control_congestion(&mut self) -> Result<(), IoError> {
|
2013-11-06 01:29:11 -06:00
|
|
|
let _m = self.fire_homing_missile();
|
2013-11-05 02:27:41 -06:00
|
|
|
status_to_io_result(unsafe {
|
|
|
|
uvll::uv_tcp_nodelay(self.handle, 0 as c_int)
|
|
|
|
})
|
2013-10-22 17:13:18 -05:00
|
|
|
}
|
|
|
|
|
2013-11-05 02:27:41 -06:00
|
|
|
fn nodelay(&mut self) -> Result<(), IoError> {
|
2013-11-06 01:29:11 -06:00
|
|
|
let _m = self.fire_homing_missile();
|
2013-11-05 02:27:41 -06:00
|
|
|
status_to_io_result(unsafe {
|
|
|
|
uvll::uv_tcp_nodelay(self.handle, 1 as c_int)
|
|
|
|
})
|
2013-10-22 17:13:18 -05:00
|
|
|
}
|
|
|
|
|
2013-11-05 02:27:41 -06:00
|
|
|
fn keepalive(&mut self, delay_in_seconds: uint) -> Result<(), IoError> {
|
2013-11-06 01:29:11 -06:00
|
|
|
let _m = self.fire_homing_missile();
|
2013-11-05 02:27:41 -06:00
|
|
|
status_to_io_result(unsafe {
|
|
|
|
uvll::uv_tcp_keepalive(self.handle, 1 as c_int,
|
|
|
|
delay_in_seconds as c_uint)
|
|
|
|
})
|
|
|
|
}
|
2013-10-22 17:13:18 -05:00
|
|
|
|
2013-11-05 02:27:41 -06:00
|
|
|
fn letdie(&mut self) -> Result<(), IoError> {
|
2013-11-06 01:29:11 -06:00
|
|
|
let _m = self.fire_homing_missile();
|
2013-11-05 02:27:41 -06:00
|
|
|
status_to_io_result(unsafe {
|
|
|
|
uvll::uv_tcp_keepalive(self.handle, 0 as c_int, 0 as c_uint)
|
|
|
|
})
|
|
|
|
}
|
2014-01-22 21:32:16 -06:00
|
|
|
|
2014-06-14 13:03:34 -05:00
|
|
|
fn clone(&self) -> Box<rtio::RtioTcpStream + Send> {
|
2014-04-25 03:08:02 -05:00
|
|
|
box TcpWatcher {
|
2014-01-22 21:32:16 -06:00
|
|
|
handle: self.handle,
|
|
|
|
stream: StreamWatcher::new(self.handle),
|
|
|
|
home: self.home.clone(),
|
|
|
|
refcount: self.refcount.clone(),
|
|
|
|
read_access: self.read_access.clone(),
|
2014-04-27 17:45:16 -05:00
|
|
|
write_access: self.write_access.clone(),
|
2014-06-14 13:03:34 -05:00
|
|
|
} as Box<rtio::RtioTcpStream + Send>
|
2014-01-22 21:32:16 -06:00
|
|
|
}
|
2014-03-12 19:04:34 -05:00
|
|
|
|
2014-04-24 20:48:21 -05:00
|
|
|
fn close_read(&mut self) -> Result<(), IoError> {
|
|
|
|
// see comments in PipeWatcher::close_read
|
2014-04-27 17:45:16 -05:00
|
|
|
let task = {
|
|
|
|
let m = self.fire_homing_missile();
|
|
|
|
self.read_access.access.close(&m);
|
|
|
|
self.stream.cancel_read(uvll::EOF as libc::ssize_t)
|
|
|
|
};
|
|
|
|
let _ = task.map(|t| t.reawaken());
|
2014-04-24 20:48:21 -05:00
|
|
|
Ok(())
|
|
|
|
}
|
2014-03-12 19:04:34 -05:00
|
|
|
|
2014-04-24 20:48:21 -05:00
|
|
|
fn close_write(&mut self) -> Result<(), IoError> {
|
|
|
|
let _m = self.fire_homing_missile();
|
|
|
|
shutdown(self.handle, &self.uv_loop())
|
2014-03-12 19:04:34 -05:00
|
|
|
}
|
2014-04-27 17:45:16 -05:00
|
|
|
|
|
|
|
fn set_timeout(&mut self, timeout: Option<u64>) {
|
|
|
|
self.set_read_timeout(timeout);
|
|
|
|
self.set_write_timeout(timeout);
|
|
|
|
}
|
|
|
|
|
|
|
|
fn set_read_timeout(&mut self, ms: Option<u64>) {
|
|
|
|
let _m = self.fire_homing_missile();
|
|
|
|
let loop_ = self.uv_loop();
|
|
|
|
self.read_access.set_timeout(ms, &self.home, &loop_, cancel_read,
|
|
|
|
&self.stream as *_ as uint);
|
|
|
|
|
|
|
|
fn cancel_read(stream: uint) -> Option<BlockedTask> {
|
core: Remove the cast module
This commit revisits the `cast` module in libcore and libstd, and scrutinizes
all functions inside of it. The result was to remove the `cast` module entirely,
folding all functionality into the `mem` module. Specifically, this is the fate
of each function in the `cast` module.
* transmute - This function was moved to `mem`, but it is now marked as
#[unstable]. This is due to planned changes to the `transmute`
function and how it can be invoked (see the #[unstable] comment).
For more information, see RFC 5 and #12898
* transmute_copy - This function was moved to `mem`, with clarification that is
is not an error to invoke it with T/U that are different
sizes, but rather that it is strongly discouraged. This
function is now #[stable]
* forget - This function was moved to `mem` and marked #[stable]
* bump_box_refcount - This function was removed due to the deprecation of
managed boxes as well as its questionable utility.
* transmute_mut - This function was previously deprecated, and removed as part
of this commit.
* transmute_mut_unsafe - This function doesn't serve much of a purpose when it
can be achieved with an `as` in safe code, so it was
removed.
* transmute_lifetime - This function was removed because it is likely a strong
indication that code is incorrect in the first place.
* transmute_mut_lifetime - This function was removed for the same reasons as
`transmute_lifetime`
* copy_lifetime - This function was moved to `mem`, but it is marked
`#[unstable]` now due to the likelihood of being removed in
the future if it is found to not be very useful.
* copy_mut_lifetime - This function was also moved to `mem`, but had the same
treatment as `copy_lifetime`.
* copy_lifetime_vec - This function was removed because it is not used today,
and its existence is not necessary with DST
(copy_lifetime will suffice).
In summary, the cast module was stripped down to these functions, and then the
functions were moved to the `mem` module.
transmute - #[unstable]
transmute_copy - #[stable]
forget - #[stable]
copy_lifetime - #[unstable]
copy_mut_lifetime - #[unstable]
[breaking-change]
2014-05-09 12:34:51 -05:00
|
|
|
let stream: &mut StreamWatcher = unsafe { mem::transmute(stream) };
|
2014-04-27 17:45:16 -05:00
|
|
|
stream.cancel_read(uvll::ECANCELED as ssize_t)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn set_write_timeout(&mut self, ms: Option<u64>) {
|
|
|
|
let _m = self.fire_homing_missile();
|
|
|
|
let loop_ = self.uv_loop();
|
|
|
|
self.write_access.set_timeout(ms, &self.home, &loop_, cancel_write,
|
|
|
|
&self.stream as *_ as uint);
|
|
|
|
|
|
|
|
fn cancel_write(stream: uint) -> Option<BlockedTask> {
|
core: Remove the cast module
This commit revisits the `cast` module in libcore and libstd, and scrutinizes
all functions inside of it. The result was to remove the `cast` module entirely,
folding all functionality into the `mem` module. Specifically, this is the fate
of each function in the `cast` module.
* transmute - This function was moved to `mem`, but it is now marked as
#[unstable]. This is due to planned changes to the `transmute`
function and how it can be invoked (see the #[unstable] comment).
For more information, see RFC 5 and #12898
* transmute_copy - This function was moved to `mem`, with clarification that is
is not an error to invoke it with T/U that are different
sizes, but rather that it is strongly discouraged. This
function is now #[stable]
* forget - This function was moved to `mem` and marked #[stable]
* bump_box_refcount - This function was removed due to the deprecation of
managed boxes as well as its questionable utility.
* transmute_mut - This function was previously deprecated, and removed as part
of this commit.
* transmute_mut_unsafe - This function doesn't serve much of a purpose when it
can be achieved with an `as` in safe code, so it was
removed.
* transmute_lifetime - This function was removed because it is likely a strong
indication that code is incorrect in the first place.
* transmute_mut_lifetime - This function was removed for the same reasons as
`transmute_lifetime`
* copy_lifetime - This function was moved to `mem`, but it is marked
`#[unstable]` now due to the likelihood of being removed in
the future if it is found to not be very useful.
* copy_mut_lifetime - This function was also moved to `mem`, but had the same
treatment as `copy_lifetime`.
* copy_lifetime_vec - This function was removed because it is not used today,
and its existence is not necessary with DST
(copy_lifetime will suffice).
In summary, the cast module was stripped down to these functions, and then the
functions were moved to the `mem` module.
transmute - #[unstable]
transmute_copy - #[stable]
forget - #[stable]
copy_lifetime - #[unstable]
copy_mut_lifetime - #[unstable]
[breaking-change]
2014-05-09 12:34:51 -05:00
|
|
|
let stream: &mut StreamWatcher = unsafe { mem::transmute(stream) };
|
2014-04-27 17:45:16 -05:00
|
|
|
stream.cancel_write()
|
|
|
|
}
|
|
|
|
}
|
2013-11-05 02:27:41 -06:00
|
|
|
}
|
2013-10-22 17:13:18 -05:00
|
|
|
|
2013-11-07 17:13:06 -06:00
|
|
|
impl UvHandle<uvll::uv_tcp_t> for TcpWatcher {
|
|
|
|
fn uv_handle(&self) -> *uvll::uv_tcp_t { self.stream.handle }
|
|
|
|
}
|
|
|
|
|
2013-11-05 02:27:41 -06:00
|
|
|
impl Drop for TcpWatcher {
|
|
|
|
fn drop(&mut self) {
|
2013-11-06 01:29:11 -06:00
|
|
|
let _m = self.fire_homing_missile();
|
2014-01-22 21:32:16 -06:00
|
|
|
if self.refcount.decrement() {
|
|
|
|
self.close();
|
|
|
|
}
|
2013-11-05 02:27:41 -06:00
|
|
|
}
|
|
|
|
}
|
2013-10-22 17:13:18 -05:00
|
|
|
|
2013-11-05 02:27:41 -06:00
|
|
|
// TCP listeners (unbound servers)
|
|
|
|
|
|
|
|
impl TcpListener {
|
2014-06-04 02:00:59 -05:00
|
|
|
pub fn bind(io: &mut UvIoFactory, address: rtio::SocketAddr)
|
2014-05-05 20:56:44 -05:00
|
|
|
-> Result<Box<TcpListener>, UvError> {
|
2013-11-21 18:55:40 -06:00
|
|
|
let handle = unsafe { uvll::malloc_handle(uvll::UV_TCP) };
|
|
|
|
assert_eq!(unsafe {
|
2013-12-12 19:47:48 -06:00
|
|
|
uvll::uv_tcp_init(io.uv_loop(), handle)
|
2013-11-21 18:55:40 -06:00
|
|
|
}, 0);
|
2014-03-09 16:58:32 -05:00
|
|
|
let (tx, rx) = channel();
|
2014-04-25 03:08:02 -05:00
|
|
|
let l = box TcpListener {
|
2013-12-12 19:47:48 -06:00
|
|
|
home: io.make_handle(),
|
2013-11-21 18:55:40 -06:00
|
|
|
handle: handle,
|
2014-03-09 16:58:32 -05:00
|
|
|
outgoing: tx,
|
|
|
|
incoming: rx,
|
2013-11-21 18:55:40 -06:00
|
|
|
};
|
2014-01-17 21:33:29 -06:00
|
|
|
let (addr, _len) = addr_to_sockaddr(address);
|
|
|
|
let res = unsafe {
|
|
|
|
let addr_p = &addr as *libc::sockaddr_storage;
|
|
|
|
uvll::uv_tcp_bind(l.handle, addr_p as *libc::sockaddr)
|
|
|
|
};
|
2013-11-21 18:55:40 -06:00
|
|
|
return match res {
|
|
|
|
0 => Ok(l.install()),
|
|
|
|
n => Err(UvError(n))
|
|
|
|
};
|
2013-10-22 17:13:18 -05:00
|
|
|
}
|
2013-11-05 02:27:41 -06:00
|
|
|
}
|
2013-10-22 17:13:18 -05:00
|
|
|
|
2013-11-05 02:27:41 -06:00
|
|
|
impl HomingIO for TcpListener {
|
2013-12-12 19:47:48 -06:00
|
|
|
fn home<'r>(&'r mut self) -> &'r mut HomeHandle { &mut self.home }
|
2013-11-05 02:27:41 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
impl UvHandle<uvll::uv_tcp_t> for TcpListener {
|
|
|
|
fn uv_handle(&self) -> *uvll::uv_tcp_t { self.handle }
|
|
|
|
}
|
|
|
|
|
|
|
|
impl rtio::RtioSocket for TcpListener {
|
2014-06-04 02:00:59 -05:00
|
|
|
fn socket_name(&mut self) -> Result<rtio::SocketAddr, IoError> {
|
2013-11-06 01:29:11 -06:00
|
|
|
let _m = self.fire_homing_missile();
|
2013-11-05 02:27:41 -06:00
|
|
|
socket_name(Tcp, self.handle)
|
2013-10-22 17:13:18 -05:00
|
|
|
}
|
2013-11-05 02:27:41 -06:00
|
|
|
}
|
2013-10-22 17:13:18 -05:00
|
|
|
|
2013-11-05 02:27:41 -06:00
|
|
|
impl rtio::RtioTcpListener for TcpListener {
|
2014-06-14 13:03:34 -05:00
|
|
|
fn listen(~self) -> Result<Box<rtio::RtioTcpAcceptor + Send>, IoError> {
|
2013-11-05 02:27:41 -06:00
|
|
|
// create the acceptor object from ourselves
|
2014-04-25 03:08:02 -05:00
|
|
|
let mut acceptor = box TcpAcceptor {
|
2014-04-21 22:30:07 -05:00
|
|
|
listener: self,
|
2014-04-22 20:38:59 -05:00
|
|
|
timeout: AcceptTimeout::new(),
|
2014-04-21 22:30:07 -05:00
|
|
|
};
|
2013-11-05 02:27:41 -06:00
|
|
|
|
2013-11-06 01:29:11 -06:00
|
|
|
let _m = acceptor.fire_homing_missile();
|
2014-01-26 02:43:42 -06:00
|
|
|
// FIXME: the 128 backlog should be configurable
|
2013-11-05 02:27:41 -06:00
|
|
|
match unsafe { uvll::uv_listen(acceptor.listener.handle, 128, listen_cb) } {
|
2014-06-14 13:03:34 -05:00
|
|
|
0 => Ok(acceptor as Box<rtio::RtioTcpAcceptor + Send>),
|
2013-11-05 02:27:41 -06:00
|
|
|
n => Err(uv_error_to_io_error(UvError(n))),
|
2013-10-22 17:13:18 -05:00
|
|
|
}
|
2013-11-05 02:27:41 -06:00
|
|
|
}
|
|
|
|
}
|
2013-10-22 17:13:18 -05:00
|
|
|
|
2013-11-05 02:27:41 -06:00
|
|
|
extern fn listen_cb(server: *uvll::uv_stream_t, status: c_int) {
|
2013-11-07 17:13:06 -06:00
|
|
|
assert!(status != uvll::ECANCELED);
|
2013-12-12 19:47:48 -06:00
|
|
|
let tcp: &mut TcpListener = unsafe { UvHandle::from_uv_handle(&server) };
|
2013-11-05 02:27:41 -06:00
|
|
|
let msg = match status {
|
|
|
|
0 => {
|
2013-11-05 13:29:45 -06:00
|
|
|
let loop_ = Loop::wrap(unsafe {
|
2013-11-05 02:27:41 -06:00
|
|
|
uvll::get_loop_for_uv_handle(server)
|
|
|
|
});
|
2013-12-12 19:47:48 -06:00
|
|
|
let client = TcpWatcher::new_home(&loop_, tcp.home().clone());
|
2013-11-05 02:27:41 -06:00
|
|
|
assert_eq!(unsafe { uvll::uv_accept(server, client.handle) }, 0);
|
2014-06-14 13:03:34 -05:00
|
|
|
Ok(box client as Box<rtio::RtioTcpStream + Send>)
|
2013-10-22 17:13:18 -05:00
|
|
|
}
|
2013-11-05 02:27:41 -06:00
|
|
|
n => Err(uv_error_to_io_error(UvError(n)))
|
|
|
|
};
|
|
|
|
tcp.outgoing.send(msg);
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Drop for TcpListener {
|
|
|
|
fn drop(&mut self) {
|
2013-11-07 17:13:06 -06:00
|
|
|
let _m = self.fire_homing_missile();
|
|
|
|
self.close();
|
2013-10-22 17:13:18 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-11-05 02:27:41 -06:00
|
|
|
// TCP acceptors (bound servers)
|
|
|
|
|
|
|
|
impl HomingIO for TcpAcceptor {
|
2013-12-12 19:47:48 -06:00
|
|
|
fn home<'r>(&'r mut self) -> &'r mut HomeHandle { self.listener.home() }
|
2013-11-05 02:27:41 -06:00
|
|
|
}
|
2013-10-22 17:13:18 -05:00
|
|
|
|
2013-11-05 02:27:41 -06:00
|
|
|
impl rtio::RtioSocket for TcpAcceptor {
|
2014-06-04 02:00:59 -05:00
|
|
|
fn socket_name(&mut self) -> Result<rtio::SocketAddr, IoError> {
|
2013-11-06 01:29:11 -06:00
|
|
|
let _m = self.fire_homing_missile();
|
2013-11-05 02:27:41 -06:00
|
|
|
socket_name(Tcp, self.listener.handle)
|
|
|
|
}
|
|
|
|
}
|
2013-10-22 17:13:18 -05:00
|
|
|
|
2013-11-05 02:27:41 -06:00
|
|
|
impl rtio::RtioTcpAcceptor for TcpAcceptor {
|
2014-06-14 13:03:34 -05:00
|
|
|
fn accept(&mut self) -> Result<Box<rtio::RtioTcpStream + Send>, IoError> {
|
2014-04-22 20:38:59 -05:00
|
|
|
self.timeout.accept(&self.listener.incoming)
|
2013-10-22 17:13:18 -05:00
|
|
|
}
|
|
|
|
|
2013-11-05 02:27:41 -06:00
|
|
|
fn accept_simultaneously(&mut self) -> Result<(), IoError> {
|
2013-11-06 01:29:11 -06:00
|
|
|
let _m = self.fire_homing_missile();
|
2013-11-05 02:27:41 -06:00
|
|
|
status_to_io_result(unsafe {
|
|
|
|
uvll::uv_tcp_simultaneous_accepts(self.listener.handle, 1)
|
|
|
|
})
|
2013-10-22 17:13:18 -05:00
|
|
|
}
|
|
|
|
|
2013-11-05 02:27:41 -06:00
|
|
|
fn dont_accept_simultaneously(&mut self) -> Result<(), IoError> {
|
2013-11-06 01:29:11 -06:00
|
|
|
let _m = self.fire_homing_missile();
|
2013-11-05 02:27:41 -06:00
|
|
|
status_to_io_result(unsafe {
|
|
|
|
uvll::uv_tcp_simultaneous_accepts(self.listener.handle, 0)
|
|
|
|
})
|
2013-10-22 17:13:18 -05:00
|
|
|
}
|
2014-04-21 22:30:07 -05:00
|
|
|
|
|
|
|
fn set_timeout(&mut self, ms: Option<u64>) {
|
2014-04-27 17:45:16 -05:00
|
|
|
let _m = self.fire_homing_missile();
|
2014-04-22 20:38:59 -05:00
|
|
|
match ms {
|
|
|
|
None => self.timeout.clear(),
|
|
|
|
Some(ms) => self.timeout.set_timeout(ms, &mut *self.listener),
|
2014-04-21 22:30:07 -05:00
|
|
|
}
|
|
|
|
}
|
2013-10-22 17:13:18 -05:00
|
|
|
}
|
|
|
|
|
2013-11-05 02:27:41 -06:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
/// UDP implementation
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
pub struct UdpWatcher {
|
|
|
|
handle: *uvll::uv_udp_t,
|
2013-12-12 19:47:48 -06:00
|
|
|
home: HomeHandle,
|
2014-01-22 21:32:16 -06:00
|
|
|
|
|
|
|
// See above for what these fields are
|
2014-03-28 12:27:14 -05:00
|
|
|
refcount: Refcount,
|
2014-04-27 17:45:16 -05:00
|
|
|
read_access: AccessTimeout,
|
|
|
|
write_access: AccessTimeout,
|
|
|
|
|
|
|
|
blocked_sender: Option<BlockedTask>,
|
|
|
|
}
|
|
|
|
|
|
|
|
struct UdpRecvCtx {
|
|
|
|
task: Option<BlockedTask>,
|
|
|
|
buf: Option<Buf>,
|
2014-06-04 02:00:59 -05:00
|
|
|
result: Option<(ssize_t, Option<rtio::SocketAddr>)>,
|
2014-04-27 17:45:16 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
struct UdpSendCtx {
|
|
|
|
result: c_int,
|
|
|
|
data: Option<Vec<u8>>,
|
|
|
|
udp: *mut UdpWatcher,
|
2013-11-05 02:27:41 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
impl UdpWatcher {
|
2014-06-04 02:00:59 -05:00
|
|
|
pub fn bind(io: &mut UvIoFactory, address: rtio::SocketAddr)
|
2013-11-20 17:46:49 -06:00
|
|
|
-> Result<UdpWatcher, UvError> {
|
2013-11-21 18:55:40 -06:00
|
|
|
let udp = UdpWatcher {
|
|
|
|
handle: unsafe { uvll::malloc_handle(uvll::UV_UDP) },
|
2013-12-12 19:47:48 -06:00
|
|
|
home: io.make_handle(),
|
2014-01-22 21:32:16 -06:00
|
|
|
refcount: Refcount::new(),
|
2014-04-27 17:45:16 -05:00
|
|
|
read_access: AccessTimeout::new(),
|
|
|
|
write_access: AccessTimeout::new(),
|
|
|
|
blocked_sender: None,
|
2013-11-21 18:55:40 -06:00
|
|
|
};
|
|
|
|
assert_eq!(unsafe {
|
2013-12-12 19:47:48 -06:00
|
|
|
uvll::uv_udp_init(io.uv_loop(), udp.handle)
|
2013-11-21 18:55:40 -06:00
|
|
|
}, 0);
|
2014-01-17 21:33:29 -06:00
|
|
|
let (addr, _len) = addr_to_sockaddr(address);
|
|
|
|
let result = unsafe {
|
|
|
|
let addr_p = &addr as *libc::sockaddr_storage;
|
|
|
|
uvll::uv_udp_bind(udp.handle, addr_p as *libc::sockaddr, 0u32)
|
|
|
|
};
|
2013-11-21 18:55:40 -06:00
|
|
|
return match result {
|
|
|
|
0 => Ok(udp),
|
|
|
|
n => Err(UvError(n)),
|
|
|
|
};
|
2013-10-22 17:13:18 -05:00
|
|
|
}
|
2013-11-05 02:27:41 -06:00
|
|
|
}
|
|
|
|
|
2013-11-07 17:13:06 -06:00
|
|
|
impl UvHandle<uvll::uv_udp_t> for UdpWatcher {
|
|
|
|
fn uv_handle(&self) -> *uvll::uv_udp_t { self.handle }
|
|
|
|
}
|
|
|
|
|
2013-11-05 02:27:41 -06:00
|
|
|
impl HomingIO for UdpWatcher {
|
2013-12-12 19:47:48 -06:00
|
|
|
fn home<'r>(&'r mut self) -> &'r mut HomeHandle { &mut self.home }
|
2013-11-05 02:27:41 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
impl rtio::RtioSocket for UdpWatcher {
|
2014-06-04 02:00:59 -05:00
|
|
|
fn socket_name(&mut self) -> Result<rtio::SocketAddr, IoError> {
|
2013-11-06 01:29:11 -06:00
|
|
|
let _m = self.fire_homing_missile();
|
2013-11-05 02:27:41 -06:00
|
|
|
socket_name(Udp, self.handle)
|
2013-10-22 17:13:18 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-11-05 02:27:41 -06:00
|
|
|
impl rtio::RtioUdpSocket for UdpWatcher {
|
|
|
|
fn recvfrom(&mut self, buf: &mut [u8])
|
2014-06-04 02:00:59 -05:00
|
|
|
-> Result<(uint, rtio::SocketAddr), IoError>
|
2013-11-05 02:27:41 -06:00
|
|
|
{
|
2014-02-10 21:59:35 -06:00
|
|
|
let loop_ = self.uv_loop();
|
2014-01-22 21:32:16 -06:00
|
|
|
let m = self.fire_homing_missile();
|
2014-04-27 17:45:16 -05:00
|
|
|
let _guard = try!(self.read_access.grant(m));
|
2013-11-05 02:27:41 -06:00
|
|
|
|
2014-04-24 20:48:21 -05:00
|
|
|
return match unsafe {
|
2013-11-05 02:27:41 -06:00
|
|
|
uvll::uv_udp_recv_start(self.handle, alloc_cb, recv_cb)
|
|
|
|
} {
|
|
|
|
0 => {
|
2014-04-27 17:45:16 -05:00
|
|
|
let mut cx = UdpRecvCtx {
|
2013-11-05 02:27:41 -06:00
|
|
|
task: None,
|
|
|
|
buf: Some(slice_to_uv_buf(buf)),
|
|
|
|
result: None,
|
|
|
|
};
|
2014-02-09 06:37:44 -06:00
|
|
|
let handle = self.handle;
|
2014-02-10 21:59:35 -06:00
|
|
|
wait_until_woken_after(&mut cx.task, &loop_, || {
|
2014-02-09 06:37:44 -06:00
|
|
|
unsafe { uvll::set_data_for_uv_handle(handle, &cx) }
|
2013-11-20 17:46:49 -06:00
|
|
|
});
|
2013-11-05 02:27:41 -06:00
|
|
|
match cx.result.take_unwrap() {
|
|
|
|
(n, _) if n < 0 =>
|
|
|
|
Err(uv_error_to_io_error(UvError(n as c_int))),
|
2013-11-07 17:26:47 -06:00
|
|
|
(n, addr) => Ok((n as uint, addr.unwrap()))
|
2013-11-05 02:27:41 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
n => Err(uv_error_to_io_error(UvError(n)))
|
|
|
|
};
|
|
|
|
|
|
|
|
extern fn alloc_cb(handle: *uvll::uv_udp_t,
|
2013-11-07 17:26:47 -06:00
|
|
|
_suggested_size: size_t,
|
|
|
|
buf: *mut Buf) {
|
|
|
|
unsafe {
|
2014-04-27 17:45:16 -05:00
|
|
|
let cx = uvll::get_data_for_uv_handle(handle);
|
|
|
|
let cx = &mut *(cx as *mut UdpRecvCtx);
|
2013-11-07 17:26:47 -06:00
|
|
|
*buf = cx.buf.take().expect("recv alloc_cb called more than once")
|
|
|
|
}
|
2013-11-05 02:27:41 -06:00
|
|
|
}
|
2013-10-22 17:13:18 -05:00
|
|
|
|
2013-11-07 17:26:47 -06:00
|
|
|
extern fn recv_cb(handle: *uvll::uv_udp_t, nread: ssize_t, buf: *Buf,
|
2014-01-17 21:33:29 -06:00
|
|
|
addr: *libc::sockaddr, _flags: c_uint) {
|
2013-11-07 17:13:06 -06:00
|
|
|
assert!(nread != uvll::ECANCELED as ssize_t);
|
2014-04-24 20:48:21 -05:00
|
|
|
let cx = unsafe {
|
2014-04-27 17:45:16 -05:00
|
|
|
&mut *(uvll::get_data_for_uv_handle(handle) as *mut UdpRecvCtx)
|
2013-11-07 17:13:06 -06:00
|
|
|
};
|
2013-10-22 17:13:18 -05:00
|
|
|
|
2013-11-05 02:27:41 -06:00
|
|
|
// When there's no data to read the recv callback can be a no-op.
|
|
|
|
// This can happen if read returns EAGAIN/EWOULDBLOCK. By ignoring
|
|
|
|
// this we just drop back to kqueue and wait for the next callback.
|
2013-11-07 17:13:06 -06:00
|
|
|
if nread == 0 {
|
2013-11-07 17:26:47 -06:00
|
|
|
cx.buf = Some(unsafe { *buf });
|
2013-11-07 17:13:06 -06:00
|
|
|
return
|
|
|
|
}
|
2013-11-05 02:27:41 -06:00
|
|
|
|
2014-04-24 20:48:21 -05:00
|
|
|
unsafe { assert_eq!(uvll::uv_udp_recv_stop(handle), 0) }
|
2013-11-07 17:26:47 -06:00
|
|
|
let addr = if addr == ptr::null() {
|
|
|
|
None
|
|
|
|
} else {
|
2014-01-17 21:33:29 -06:00
|
|
|
let len = mem::size_of::<libc::sockaddr_storage>();
|
core: Remove the cast module
This commit revisits the `cast` module in libcore and libstd, and scrutinizes
all functions inside of it. The result was to remove the `cast` module entirely,
folding all functionality into the `mem` module. Specifically, this is the fate
of each function in the `cast` module.
* transmute - This function was moved to `mem`, but it is now marked as
#[unstable]. This is due to planned changes to the `transmute`
function and how it can be invoked (see the #[unstable] comment).
For more information, see RFC 5 and #12898
* transmute_copy - This function was moved to `mem`, with clarification that is
is not an error to invoke it with T/U that are different
sizes, but rather that it is strongly discouraged. This
function is now #[stable]
* forget - This function was moved to `mem` and marked #[stable]
* bump_box_refcount - This function was removed due to the deprecation of
managed boxes as well as its questionable utility.
* transmute_mut - This function was previously deprecated, and removed as part
of this commit.
* transmute_mut_unsafe - This function doesn't serve much of a purpose when it
can be achieved with an `as` in safe code, so it was
removed.
* transmute_lifetime - This function was removed because it is likely a strong
indication that code is incorrect in the first place.
* transmute_mut_lifetime - This function was removed for the same reasons as
`transmute_lifetime`
* copy_lifetime - This function was moved to `mem`, but it is marked
`#[unstable]` now due to the likelihood of being removed in
the future if it is found to not be very useful.
* copy_mut_lifetime - This function was also moved to `mem`, but had the same
treatment as `copy_lifetime`.
* copy_lifetime_vec - This function was removed because it is not used today,
and its existence is not necessary with DST
(copy_lifetime will suffice).
In summary, the cast module was stripped down to these functions, and then the
functions were moved to the `mem` module.
transmute - #[unstable]
transmute_copy - #[stable]
forget - #[stable]
copy_lifetime - #[unstable]
copy_mut_lifetime - #[unstable]
[breaking-change]
2014-05-09 12:34:51 -05:00
|
|
|
Some(sockaddr_to_addr(unsafe { mem::transmute(addr) }, len))
|
2013-11-07 17:26:47 -06:00
|
|
|
};
|
2013-11-05 02:27:41 -06:00
|
|
|
cx.result = Some((nread, addr));
|
2013-12-12 19:47:48 -06:00
|
|
|
wakeup(&mut cx.task);
|
2013-11-05 02:27:41 -06:00
|
|
|
}
|
2013-10-22 17:13:18 -05:00
|
|
|
}
|
|
|
|
|
2014-06-04 02:00:59 -05:00
|
|
|
fn sendto(&mut self, buf: &[u8], dst: rtio::SocketAddr) -> Result<(), IoError> {
|
2014-01-22 21:32:16 -06:00
|
|
|
let m = self.fire_homing_missile();
|
2014-02-10 21:59:35 -06:00
|
|
|
let loop_ = self.uv_loop();
|
2014-04-27 17:45:16 -05:00
|
|
|
let guard = try!(self.write_access.grant(m));
|
2013-11-05 02:27:41 -06:00
|
|
|
|
2013-11-07 17:13:06 -06:00
|
|
|
let mut req = Request::new(uvll::UV_UDP_SEND);
|
2014-01-17 21:33:29 -06:00
|
|
|
let (addr, _len) = addr_to_sockaddr(dst);
|
2014-04-27 17:45:16 -05:00
|
|
|
let addr_p = &addr as *_ as *libc::sockaddr;
|
|
|
|
|
|
|
|
// see comments in StreamWatcher::write for why we may allocate a buffer
|
|
|
|
// here.
|
|
|
|
let data = if guard.can_timeout {Some(Vec::from_slice(buf))} else {None};
|
|
|
|
let uv_buf = if guard.can_timeout {
|
|
|
|
slice_to_uv_buf(data.get_ref().as_slice())
|
|
|
|
} else {
|
|
|
|
slice_to_uv_buf(buf)
|
2014-01-17 21:33:29 -06:00
|
|
|
};
|
2013-11-05 02:27:41 -06:00
|
|
|
|
2014-04-27 17:45:16 -05:00
|
|
|
return match unsafe {
|
|
|
|
uvll::uv_udp_send(req.handle, self.handle, [uv_buf], addr_p, send_cb)
|
|
|
|
} {
|
2013-11-05 02:27:41 -06:00
|
|
|
0 => {
|
2013-11-07 17:13:06 -06:00
|
|
|
req.defuse(); // uv callback now owns this request
|
2014-04-27 17:45:16 -05:00
|
|
|
let mut cx = UdpSendCtx {
|
|
|
|
result: uvll::ECANCELED, data: data, udp: self as *mut _
|
|
|
|
};
|
|
|
|
wait_until_woken_after(&mut self.blocked_sender, &loop_, || {
|
2013-11-07 17:13:06 -06:00
|
|
|
req.set_data(&cx);
|
2013-11-20 17:46:49 -06:00
|
|
|
});
|
2014-04-27 17:45:16 -05:00
|
|
|
|
|
|
|
if cx.result != uvll::ECANCELED {
|
|
|
|
return match cx.result {
|
|
|
|
0 => Ok(()),
|
|
|
|
n => Err(uv_error_to_io_error(UvError(n)))
|
|
|
|
}
|
2013-11-05 02:27:41 -06:00
|
|
|
}
|
2014-05-08 01:39:56 -05:00
|
|
|
let new_cx = box UdpSendCtx {
|
2014-04-27 17:45:16 -05:00
|
|
|
result: 0,
|
|
|
|
udp: 0 as *mut UdpWatcher,
|
|
|
|
data: cx.data.take(),
|
|
|
|
};
|
|
|
|
unsafe {
|
|
|
|
req.set_data(&*new_cx);
|
core: Remove the cast module
This commit revisits the `cast` module in libcore and libstd, and scrutinizes
all functions inside of it. The result was to remove the `cast` module entirely,
folding all functionality into the `mem` module. Specifically, this is the fate
of each function in the `cast` module.
* transmute - This function was moved to `mem`, but it is now marked as
#[unstable]. This is due to planned changes to the `transmute`
function and how it can be invoked (see the #[unstable] comment).
For more information, see RFC 5 and #12898
* transmute_copy - This function was moved to `mem`, with clarification that is
is not an error to invoke it with T/U that are different
sizes, but rather that it is strongly discouraged. This
function is now #[stable]
* forget - This function was moved to `mem` and marked #[stable]
* bump_box_refcount - This function was removed due to the deprecation of
managed boxes as well as its questionable utility.
* transmute_mut - This function was previously deprecated, and removed as part
of this commit.
* transmute_mut_unsafe - This function doesn't serve much of a purpose when it
can be achieved with an `as` in safe code, so it was
removed.
* transmute_lifetime - This function was removed because it is likely a strong
indication that code is incorrect in the first place.
* transmute_mut_lifetime - This function was removed for the same reasons as
`transmute_lifetime`
* copy_lifetime - This function was moved to `mem`, but it is marked
`#[unstable]` now due to the likelihood of being removed in
the future if it is found to not be very useful.
* copy_mut_lifetime - This function was also moved to `mem`, but had the same
treatment as `copy_lifetime`.
* copy_lifetime_vec - This function was removed because it is not used today,
and its existence is not necessary with DST
(copy_lifetime will suffice).
In summary, the cast module was stripped down to these functions, and then the
functions were moved to the `mem` module.
transmute - #[unstable]
transmute_copy - #[stable]
forget - #[stable]
copy_lifetime - #[unstable]
copy_mut_lifetime - #[unstable]
[breaking-change]
2014-05-09 12:34:51 -05:00
|
|
|
mem::forget(new_cx);
|
2014-04-27 17:45:16 -05:00
|
|
|
}
|
|
|
|
Err(uv_error_to_io_error(UvError(cx.result)))
|
2013-11-05 02:27:41 -06:00
|
|
|
}
|
|
|
|
n => Err(uv_error_to_io_error(UvError(n)))
|
|
|
|
};
|
|
|
|
|
2014-04-27 17:45:16 -05:00
|
|
|
// This function is the same as stream::write_cb, but adapted for udp
|
|
|
|
// instead of streams.
|
2013-11-05 02:27:41 -06:00
|
|
|
extern fn send_cb(req: *uvll::uv_udp_send_t, status: c_int) {
|
|
|
|
let req = Request::wrap(req);
|
2014-04-27 17:45:16 -05:00
|
|
|
let cx: &mut UdpSendCtx = unsafe { req.get_data() };
|
2013-11-05 02:27:41 -06:00
|
|
|
cx.result = status;
|
2014-04-27 17:45:16 -05:00
|
|
|
|
|
|
|
if cx.udp as uint != 0 {
|
|
|
|
let udp: &mut UdpWatcher = unsafe { &mut *cx.udp };
|
|
|
|
wakeup(&mut udp.blocked_sender);
|
|
|
|
} else {
|
core: Remove the cast module
This commit revisits the `cast` module in libcore and libstd, and scrutinizes
all functions inside of it. The result was to remove the `cast` module entirely,
folding all functionality into the `mem` module. Specifically, this is the fate
of each function in the `cast` module.
* transmute - This function was moved to `mem`, but it is now marked as
#[unstable]. This is due to planned changes to the `transmute`
function and how it can be invoked (see the #[unstable] comment).
For more information, see RFC 5 and #12898
* transmute_copy - This function was moved to `mem`, with clarification that is
is not an error to invoke it with T/U that are different
sizes, but rather that it is strongly discouraged. This
function is now #[stable]
* forget - This function was moved to `mem` and marked #[stable]
* bump_box_refcount - This function was removed due to the deprecation of
managed boxes as well as its questionable utility.
* transmute_mut - This function was previously deprecated, and removed as part
of this commit.
* transmute_mut_unsafe - This function doesn't serve much of a purpose when it
can be achieved with an `as` in safe code, so it was
removed.
* transmute_lifetime - This function was removed because it is likely a strong
indication that code is incorrect in the first place.
* transmute_mut_lifetime - This function was removed for the same reasons as
`transmute_lifetime`
* copy_lifetime - This function was moved to `mem`, but it is marked
`#[unstable]` now due to the likelihood of being removed in
the future if it is found to not be very useful.
* copy_mut_lifetime - This function was also moved to `mem`, but had the same
treatment as `copy_lifetime`.
* copy_lifetime_vec - This function was removed because it is not used today,
and its existence is not necessary with DST
(copy_lifetime will suffice).
In summary, the cast module was stripped down to these functions, and then the
functions were moved to the `mem` module.
transmute - #[unstable]
transmute_copy - #[stable]
forget - #[stable]
copy_lifetime - #[unstable]
copy_mut_lifetime - #[unstable]
[breaking-change]
2014-05-09 12:34:51 -05:00
|
|
|
let _cx: Box<UdpSendCtx> = unsafe { mem::transmute(cx) };
|
2014-04-27 17:45:16 -05:00
|
|
|
}
|
2013-10-22 17:13:18 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-06-04 02:00:59 -05:00
|
|
|
fn join_multicast(&mut self, multi: rtio::IpAddr) -> Result<(), IoError> {
|
2013-11-06 01:29:11 -06:00
|
|
|
let _m = self.fire_homing_missile();
|
2013-11-05 02:27:41 -06:00
|
|
|
status_to_io_result(unsafe {
|
2013-11-20 17:46:49 -06:00
|
|
|
multi.to_str().with_c_str(|m_addr| {
|
2013-11-05 02:27:41 -06:00
|
|
|
uvll::uv_udp_set_membership(self.handle,
|
|
|
|
m_addr, ptr::null(),
|
|
|
|
uvll::UV_JOIN_GROUP)
|
2013-11-20 17:46:49 -06:00
|
|
|
})
|
2013-11-05 02:27:41 -06:00
|
|
|
})
|
2013-10-22 17:13:18 -05:00
|
|
|
}
|
|
|
|
|
2014-06-04 02:00:59 -05:00
|
|
|
fn leave_multicast(&mut self, multi: rtio::IpAddr) -> Result<(), IoError> {
|
2013-11-06 01:29:11 -06:00
|
|
|
let _m = self.fire_homing_missile();
|
2013-11-05 02:27:41 -06:00
|
|
|
status_to_io_result(unsafe {
|
2013-11-20 17:46:49 -06:00
|
|
|
multi.to_str().with_c_str(|m_addr| {
|
2013-11-05 02:27:41 -06:00
|
|
|
uvll::uv_udp_set_membership(self.handle,
|
|
|
|
m_addr, ptr::null(),
|
|
|
|
uvll::UV_LEAVE_GROUP)
|
2013-11-20 17:46:49 -06:00
|
|
|
})
|
2013-11-05 02:27:41 -06:00
|
|
|
})
|
2013-10-22 17:13:18 -05:00
|
|
|
}
|
2013-11-05 02:27:41 -06:00
|
|
|
|
|
|
|
fn loop_multicast_locally(&mut self) -> Result<(), IoError> {
|
2013-11-06 01:29:11 -06:00
|
|
|
let _m = self.fire_homing_missile();
|
2013-11-05 02:27:41 -06:00
|
|
|
status_to_io_result(unsafe {
|
|
|
|
uvll::uv_udp_set_multicast_loop(self.handle,
|
|
|
|
1 as c_int)
|
|
|
|
})
|
2013-10-22 17:13:18 -05:00
|
|
|
}
|
|
|
|
|
2013-11-05 02:27:41 -06:00
|
|
|
fn dont_loop_multicast_locally(&mut self) -> Result<(), IoError> {
|
2013-11-06 01:29:11 -06:00
|
|
|
let _m = self.fire_homing_missile();
|
2013-11-05 02:27:41 -06:00
|
|
|
status_to_io_result(unsafe {
|
|
|
|
uvll::uv_udp_set_multicast_loop(self.handle,
|
|
|
|
0 as c_int)
|
|
|
|
})
|
|
|
|
}
|
2013-10-22 17:13:18 -05:00
|
|
|
|
2013-11-05 02:27:41 -06:00
|
|
|
fn multicast_time_to_live(&mut self, ttl: int) -> Result<(), IoError> {
|
2013-11-06 01:29:11 -06:00
|
|
|
let _m = self.fire_homing_missile();
|
2013-11-05 02:27:41 -06:00
|
|
|
status_to_io_result(unsafe {
|
|
|
|
uvll::uv_udp_set_multicast_ttl(self.handle,
|
|
|
|
ttl as c_int)
|
|
|
|
})
|
2013-10-22 17:13:18 -05:00
|
|
|
}
|
|
|
|
|
2013-11-05 02:27:41 -06:00
|
|
|
fn time_to_live(&mut self, ttl: int) -> Result<(), IoError> {
|
2013-11-06 01:29:11 -06:00
|
|
|
let _m = self.fire_homing_missile();
|
2013-11-05 02:27:41 -06:00
|
|
|
status_to_io_result(unsafe {
|
|
|
|
uvll::uv_udp_set_ttl(self.handle, ttl as c_int)
|
|
|
|
})
|
2013-10-22 17:13:18 -05:00
|
|
|
}
|
|
|
|
|
2013-11-05 02:27:41 -06:00
|
|
|
fn hear_broadcasts(&mut self) -> Result<(), IoError> {
|
2013-11-06 01:29:11 -06:00
|
|
|
let _m = self.fire_homing_missile();
|
2013-11-05 02:27:41 -06:00
|
|
|
status_to_io_result(unsafe {
|
|
|
|
uvll::uv_udp_set_broadcast(self.handle,
|
|
|
|
1 as c_int)
|
|
|
|
})
|
2013-10-22 17:13:18 -05:00
|
|
|
}
|
|
|
|
|
2013-11-05 02:27:41 -06:00
|
|
|
fn ignore_broadcasts(&mut self) -> Result<(), IoError> {
|
2013-11-06 01:29:11 -06:00
|
|
|
let _m = self.fire_homing_missile();
|
2013-11-05 02:27:41 -06:00
|
|
|
status_to_io_result(unsafe {
|
|
|
|
uvll::uv_udp_set_broadcast(self.handle,
|
|
|
|
0 as c_int)
|
|
|
|
})
|
2013-10-22 17:13:18 -05:00
|
|
|
}
|
2014-01-22 21:32:16 -06:00
|
|
|
|
2014-06-14 13:03:34 -05:00
|
|
|
fn clone(&self) -> Box<rtio::RtioUdpSocket + Send> {
|
2014-04-25 03:08:02 -05:00
|
|
|
box UdpWatcher {
|
2014-01-22 21:32:16 -06:00
|
|
|
handle: self.handle,
|
|
|
|
home: self.home.clone(),
|
|
|
|
refcount: self.refcount.clone(),
|
|
|
|
write_access: self.write_access.clone(),
|
|
|
|
read_access: self.read_access.clone(),
|
2014-04-27 17:45:16 -05:00
|
|
|
blocked_sender: None,
|
2014-06-14 13:03:34 -05:00
|
|
|
} as Box<rtio::RtioUdpSocket + Send>
|
2014-01-22 21:32:16 -06:00
|
|
|
}
|
2014-04-27 17:45:16 -05:00
|
|
|
|
|
|
|
fn set_timeout(&mut self, timeout: Option<u64>) {
|
|
|
|
self.set_read_timeout(timeout);
|
|
|
|
self.set_write_timeout(timeout);
|
|
|
|
}
|
|
|
|
|
|
|
|
fn set_read_timeout(&mut self, ms: Option<u64>) {
|
|
|
|
let _m = self.fire_homing_missile();
|
|
|
|
let loop_ = self.uv_loop();
|
|
|
|
self.read_access.set_timeout(ms, &self.home, &loop_, cancel_read,
|
|
|
|
self.handle as uint);
|
|
|
|
|
|
|
|
fn cancel_read(stream: uint) -> Option<BlockedTask> {
|
|
|
|
// This method is quite similar to StreamWatcher::cancel_read, see
|
|
|
|
// there for more information
|
|
|
|
let handle = stream as *uvll::uv_udp_t;
|
|
|
|
assert_eq!(unsafe { uvll::uv_udp_recv_stop(handle) }, 0);
|
|
|
|
let data = unsafe {
|
|
|
|
let data = uvll::get_data_for_uv_handle(handle);
|
|
|
|
if data.is_null() { return None }
|
|
|
|
uvll::set_data_for_uv_handle(handle, 0 as *int);
|
|
|
|
&mut *(data as *mut UdpRecvCtx)
|
|
|
|
};
|
|
|
|
data.result = Some((uvll::ECANCELED as ssize_t, None));
|
|
|
|
data.task.take()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn set_write_timeout(&mut self, ms: Option<u64>) {
|
|
|
|
let _m = self.fire_homing_missile();
|
|
|
|
let loop_ = self.uv_loop();
|
|
|
|
self.write_access.set_timeout(ms, &self.home, &loop_, cancel_write,
|
|
|
|
self as *mut _ as uint);
|
|
|
|
|
|
|
|
fn cancel_write(stream: uint) -> Option<BlockedTask> {
|
core: Remove the cast module
This commit revisits the `cast` module in libcore and libstd, and scrutinizes
all functions inside of it. The result was to remove the `cast` module entirely,
folding all functionality into the `mem` module. Specifically, this is the fate
of each function in the `cast` module.
* transmute - This function was moved to `mem`, but it is now marked as
#[unstable]. This is due to planned changes to the `transmute`
function and how it can be invoked (see the #[unstable] comment).
For more information, see RFC 5 and #12898
* transmute_copy - This function was moved to `mem`, with clarification that is
is not an error to invoke it with T/U that are different
sizes, but rather that it is strongly discouraged. This
function is now #[stable]
* forget - This function was moved to `mem` and marked #[stable]
* bump_box_refcount - This function was removed due to the deprecation of
managed boxes as well as its questionable utility.
* transmute_mut - This function was previously deprecated, and removed as part
of this commit.
* transmute_mut_unsafe - This function doesn't serve much of a purpose when it
can be achieved with an `as` in safe code, so it was
removed.
* transmute_lifetime - This function was removed because it is likely a strong
indication that code is incorrect in the first place.
* transmute_mut_lifetime - This function was removed for the same reasons as
`transmute_lifetime`
* copy_lifetime - This function was moved to `mem`, but it is marked
`#[unstable]` now due to the likelihood of being removed in
the future if it is found to not be very useful.
* copy_mut_lifetime - This function was also moved to `mem`, but had the same
treatment as `copy_lifetime`.
* copy_lifetime_vec - This function was removed because it is not used today,
and its existence is not necessary with DST
(copy_lifetime will suffice).
In summary, the cast module was stripped down to these functions, and then the
functions were moved to the `mem` module.
transmute - #[unstable]
transmute_copy - #[stable]
forget - #[stable]
copy_lifetime - #[unstable]
copy_mut_lifetime - #[unstable]
[breaking-change]
2014-05-09 12:34:51 -05:00
|
|
|
let stream: &mut UdpWatcher = unsafe { mem::transmute(stream) };
|
2014-04-27 17:45:16 -05:00
|
|
|
stream.blocked_sender.take()
|
|
|
|
}
|
|
|
|
}
|
2013-11-05 02:27:41 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Drop for UdpWatcher {
|
|
|
|
fn drop(&mut self) {
|
|
|
|
// Send ourselves home to close this handle (blocking while doing so).
|
2013-11-07 17:13:06 -06:00
|
|
|
let _m = self.fire_homing_missile();
|
2014-01-22 21:32:16 -06:00
|
|
|
if self.refcount.decrement() {
|
|
|
|
self.close();
|
|
|
|
}
|
2013-10-22 17:13:18 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-04-24 20:48:21 -05:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Shutdown helper
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
pub fn shutdown(handle: *uvll::uv_stream_t, loop_: &Loop) -> Result<(), IoError> {
|
|
|
|
struct Ctx {
|
|
|
|
slot: Option<BlockedTask>,
|
|
|
|
status: c_int,
|
|
|
|
}
|
|
|
|
let mut req = Request::new(uvll::UV_SHUTDOWN);
|
|
|
|
|
|
|
|
return match unsafe { uvll::uv_shutdown(req.handle, handle, shutdown_cb) } {
|
|
|
|
0 => {
|
|
|
|
req.defuse(); // uv callback now owns this request
|
|
|
|
let mut cx = Ctx { slot: None, status: 0 };
|
|
|
|
|
|
|
|
wait_until_woken_after(&mut cx.slot, loop_, || {
|
|
|
|
req.set_data(&cx);
|
|
|
|
});
|
|
|
|
|
|
|
|
status_to_io_result(cx.status)
|
|
|
|
}
|
|
|
|
n => Err(uv_error_to_io_error(UvError(n)))
|
|
|
|
};
|
|
|
|
|
|
|
|
extern fn shutdown_cb(req: *uvll::uv_shutdown_t, status: libc::c_int) {
|
|
|
|
let req = Request::wrap(req);
|
|
|
|
assert!(status != uvll::ECANCELED);
|
|
|
|
let cx: &mut Ctx = unsafe { req.get_data() };
|
|
|
|
cx.status = status;
|
|
|
|
wakeup(&mut cx.slot);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-10-22 17:13:18 -05:00
|
|
|
#[cfg(test)]
|
|
|
|
mod test {
|
2013-11-06 13:03:11 -06:00
|
|
|
use std::rt::rtio::{RtioTcpStream, RtioTcpListener, RtioTcpAcceptor,
|
|
|
|
RtioUdpSocket};
|
|
|
|
|
2013-12-13 13:30:59 -06:00
|
|
|
use super::{UdpWatcher, TcpWatcher, TcpListener};
|
2013-11-07 17:13:06 -06:00
|
|
|
use super::super::local_loop;
|
2013-10-22 17:13:18 -05:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn connect_close_ip4() {
|
2014-06-04 02:00:59 -05:00
|
|
|
match TcpWatcher::connect(local_loop(), ::next_test_ip4(), None) {
|
2013-11-28 14:22:53 -06:00
|
|
|
Ok(..) => fail!(),
|
2014-05-25 05:17:19 -05:00
|
|
|
Err(e) => assert_eq!(e.name(), "ECONNREFUSED".to_string()),
|
2013-10-22 17:13:18 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn connect_close_ip6() {
|
2014-06-04 02:00:59 -05:00
|
|
|
match TcpWatcher::connect(local_loop(), ::next_test_ip6(), None) {
|
2013-11-28 14:22:53 -06:00
|
|
|
Ok(..) => fail!(),
|
2014-05-25 05:17:19 -05:00
|
|
|
Err(e) => assert_eq!(e.name(), "ECONNREFUSED".to_string()),
|
2013-10-22 17:13:18 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn udp_bind_close_ip4() {
|
2014-06-04 02:00:59 -05:00
|
|
|
match UdpWatcher::bind(local_loop(), ::next_test_ip4()) {
|
2013-11-28 14:22:53 -06:00
|
|
|
Ok(..) => {}
|
|
|
|
Err(..) => fail!()
|
2013-10-22 17:13:18 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn udp_bind_close_ip6() {
|
2014-06-04 02:00:59 -05:00
|
|
|
match UdpWatcher::bind(local_loop(), ::next_test_ip6()) {
|
2013-11-28 14:22:53 -06:00
|
|
|
Ok(..) => {}
|
|
|
|
Err(..) => fail!()
|
2013-10-22 17:13:18 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn listen_ip4() {
|
2014-03-09 16:58:32 -05:00
|
|
|
let (tx, rx) = channel();
|
2014-06-04 02:00:59 -05:00
|
|
|
let addr = ::next_test_ip4();
|
2013-10-22 17:13:18 -05:00
|
|
|
|
2014-01-26 21:57:42 -06:00
|
|
|
spawn(proc() {
|
2013-11-07 17:13:06 -06:00
|
|
|
let w = match TcpListener::bind(local_loop(), addr) {
|
2013-11-06 13:03:11 -06:00
|
|
|
Ok(w) => w, Err(e) => fail!("{:?}", e)
|
2013-10-22 17:13:18 -05:00
|
|
|
};
|
2013-11-07 17:13:06 -06:00
|
|
|
let mut w = match w.listen() {
|
|
|
|
Ok(w) => w, Err(e) => fail!("{:?}", e),
|
|
|
|
};
|
2014-03-09 16:58:32 -05:00
|
|
|
tx.send(());
|
2013-11-07 17:13:06 -06:00
|
|
|
match w.accept() {
|
|
|
|
Ok(mut stream) => {
|
|
|
|
let mut buf = [0u8, ..10];
|
|
|
|
match stream.read(buf) {
|
|
|
|
Ok(10) => {} e => fail!("{:?}", e),
|
|
|
|
}
|
|
|
|
for i in range(0, 10u8) {
|
2014-04-01 22:39:26 -05:00
|
|
|
assert_eq!(buf[i as uint], i + 1);
|
2013-11-07 17:13:06 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
Err(e) => fail!("{:?}", e)
|
2013-11-06 13:03:11 -06:00
|
|
|
}
|
2014-01-26 21:57:42 -06:00
|
|
|
});
|
2013-11-07 17:13:06 -06:00
|
|
|
|
2014-03-09 16:58:32 -05:00
|
|
|
rx.recv();
|
2014-04-18 15:23:56 -05:00
|
|
|
let mut w = match TcpWatcher::connect(local_loop(), addr, None) {
|
2013-11-07 17:13:06 -06:00
|
|
|
Ok(w) => w, Err(e) => fail!("{:?}", e)
|
|
|
|
};
|
|
|
|
match w.write([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) {
|
|
|
|
Ok(()) => {}, Err(e) => fail!("{:?}", e)
|
|
|
|
}
|
2013-10-22 17:13:18 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn listen_ip6() {
|
2014-03-09 16:58:32 -05:00
|
|
|
let (tx, rx) = channel();
|
2014-06-04 02:00:59 -05:00
|
|
|
let addr = ::next_test_ip6();
|
2013-11-06 13:03:11 -06:00
|
|
|
|
2014-01-26 21:57:42 -06:00
|
|
|
spawn(proc() {
|
2013-11-07 17:13:06 -06:00
|
|
|
let w = match TcpListener::bind(local_loop(), addr) {
|
2013-11-06 13:03:11 -06:00
|
|
|
Ok(w) => w, Err(e) => fail!("{:?}", e)
|
2013-10-22 17:13:18 -05:00
|
|
|
};
|
2013-11-07 17:13:06 -06:00
|
|
|
let mut w = match w.listen() {
|
|
|
|
Ok(w) => w, Err(e) => fail!("{:?}", e),
|
|
|
|
};
|
2014-03-09 16:58:32 -05:00
|
|
|
tx.send(());
|
2013-11-07 17:13:06 -06:00
|
|
|
match w.accept() {
|
|
|
|
Ok(mut stream) => {
|
|
|
|
let mut buf = [0u8, ..10];
|
|
|
|
match stream.read(buf) {
|
|
|
|
Ok(10) => {} e => fail!("{:?}", e),
|
|
|
|
}
|
|
|
|
for i in range(0, 10u8) {
|
2014-04-01 22:39:26 -05:00
|
|
|
assert_eq!(buf[i as uint], i + 1);
|
2013-11-07 17:13:06 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
Err(e) => fail!("{:?}", e)
|
2013-11-06 13:03:11 -06:00
|
|
|
}
|
2014-01-26 21:57:42 -06:00
|
|
|
});
|
2013-11-07 17:13:06 -06:00
|
|
|
|
2014-03-09 16:58:32 -05:00
|
|
|
rx.recv();
|
2014-04-18 15:23:56 -05:00
|
|
|
let mut w = match TcpWatcher::connect(local_loop(), addr, None) {
|
2013-11-07 17:13:06 -06:00
|
|
|
Ok(w) => w, Err(e) => fail!("{:?}", e)
|
|
|
|
};
|
|
|
|
match w.write([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) {
|
|
|
|
Ok(()) => {}, Err(e) => fail!("{:?}", e)
|
|
|
|
}
|
2013-11-06 13:03:11 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn udp_recv_ip4() {
|
2014-03-09 16:58:32 -05:00
|
|
|
let (tx, rx) = channel();
|
2014-06-04 02:00:59 -05:00
|
|
|
let client = ::next_test_ip4();
|
|
|
|
let server = ::next_test_ip4();
|
2013-11-07 17:13:06 -06:00
|
|
|
|
2014-01-26 21:57:42 -06:00
|
|
|
spawn(proc() {
|
2013-11-07 17:13:06 -06:00
|
|
|
match UdpWatcher::bind(local_loop(), server) {
|
|
|
|
Ok(mut w) => {
|
2014-03-09 16:58:32 -05:00
|
|
|
tx.send(());
|
2013-11-07 17:13:06 -06:00
|
|
|
let mut buf = [0u8, ..10];
|
|
|
|
match w.recvfrom(buf) {
|
2014-06-04 02:00:59 -05:00
|
|
|
Ok((10, addr)) => assert!(addr == client),
|
2013-11-07 17:13:06 -06:00
|
|
|
e => fail!("{:?}", e),
|
|
|
|
}
|
|
|
|
for i in range(0, 10u8) {
|
2014-04-01 22:39:26 -05:00
|
|
|
assert_eq!(buf[i as uint], i + 1);
|
2013-10-22 17:13:18 -05:00
|
|
|
}
|
|
|
|
}
|
2013-11-07 17:13:06 -06:00
|
|
|
Err(e) => fail!("{:?}", e)
|
2013-11-06 13:03:11 -06:00
|
|
|
}
|
2014-01-26 21:57:42 -06:00
|
|
|
});
|
2013-11-06 13:03:11 -06:00
|
|
|
|
2014-03-09 16:58:32 -05:00
|
|
|
rx.recv();
|
2013-11-07 17:13:06 -06:00
|
|
|
let mut w = match UdpWatcher::bind(local_loop(), client) {
|
|
|
|
Ok(w) => w, Err(e) => fail!("{:?}", e)
|
|
|
|
};
|
|
|
|
match w.sendto([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], server) {
|
|
|
|
Ok(()) => {}, Err(e) => fail!("{:?}", e)
|
2013-11-06 13:03:11 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn udp_recv_ip6() {
|
2014-03-09 16:58:32 -05:00
|
|
|
let (tx, rx) = channel();
|
2014-06-04 02:00:59 -05:00
|
|
|
let client = ::next_test_ip6();
|
|
|
|
let server = ::next_test_ip6();
|
2013-11-07 17:13:06 -06:00
|
|
|
|
2014-01-26 21:57:42 -06:00
|
|
|
spawn(proc() {
|
2013-11-07 17:13:06 -06:00
|
|
|
match UdpWatcher::bind(local_loop(), server) {
|
|
|
|
Ok(mut w) => {
|
2014-03-09 16:58:32 -05:00
|
|
|
tx.send(());
|
2013-11-07 17:13:06 -06:00
|
|
|
let mut buf = [0u8, ..10];
|
|
|
|
match w.recvfrom(buf) {
|
2014-06-04 02:00:59 -05:00
|
|
|
Ok((10, addr)) => assert!(addr == client),
|
2013-11-07 17:13:06 -06:00
|
|
|
e => fail!("{:?}", e),
|
|
|
|
}
|
|
|
|
for i in range(0, 10u8) {
|
2014-04-01 22:39:26 -05:00
|
|
|
assert_eq!(buf[i as uint], i + 1);
|
2013-11-06 13:03:11 -06:00
|
|
|
}
|
|
|
|
}
|
2013-11-07 17:13:06 -06:00
|
|
|
Err(e) => fail!("{:?}", e)
|
2013-11-06 13:03:11 -06:00
|
|
|
}
|
2014-01-26 21:57:42 -06:00
|
|
|
});
|
2013-10-22 17:13:18 -05:00
|
|
|
|
2014-03-09 16:58:32 -05:00
|
|
|
rx.recv();
|
2013-11-07 17:13:06 -06:00
|
|
|
let mut w = match UdpWatcher::bind(local_loop(), client) {
|
|
|
|
Ok(w) => w, Err(e) => fail!("{:?}", e)
|
|
|
|
};
|
|
|
|
match w.sendto([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], server) {
|
|
|
|
Ok(()) => {}, Err(e) => fail!("{:?}", e)
|
2013-10-22 17:13:18 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
2013-11-06 13:03:11 -06:00
|
|
|
fn test_read_read_read() {
|
2014-06-04 02:00:59 -05:00
|
|
|
let addr = ::next_test_ip4();
|
2013-11-07 17:13:06 -06:00
|
|
|
static MAX: uint = 5000;
|
2014-03-09 16:58:32 -05:00
|
|
|
let (tx, rx) = channel();
|
2013-11-07 17:13:06 -06:00
|
|
|
|
2014-01-26 21:57:42 -06:00
|
|
|
spawn(proc() {
|
2013-11-07 17:13:06 -06:00
|
|
|
let listener = TcpListener::bind(local_loop(), addr).unwrap();
|
2014-06-04 02:00:59 -05:00
|
|
|
let mut acceptor = listener.listen().ok().unwrap();
|
2014-03-09 16:58:32 -05:00
|
|
|
tx.send(());
|
2014-06-04 02:00:59 -05:00
|
|
|
let mut stream = acceptor.accept().ok().unwrap();
|
2013-11-07 17:13:06 -06:00
|
|
|
let buf = [1, .. 2048];
|
|
|
|
let mut total_bytes_written = 0;
|
|
|
|
while total_bytes_written < MAX {
|
|
|
|
assert!(stream.write(buf).is_ok());
|
|
|
|
uvdebug!("wrote bytes");
|
|
|
|
total_bytes_written += buf.len();
|
2013-11-06 13:03:11 -06:00
|
|
|
}
|
2014-01-26 21:57:42 -06:00
|
|
|
});
|
2013-11-06 13:03:11 -06:00
|
|
|
|
2014-03-09 16:58:32 -05:00
|
|
|
rx.recv();
|
2014-04-18 15:23:56 -05:00
|
|
|
let mut stream = TcpWatcher::connect(local_loop(), addr, None).unwrap();
|
2013-12-13 13:30:59 -06:00
|
|
|
let mut buf = [0, .. 2048];
|
|
|
|
let mut total_bytes_read = 0;
|
|
|
|
while total_bytes_read < MAX {
|
2014-06-04 02:00:59 -05:00
|
|
|
let nread = stream.read(buf).ok().unwrap();
|
2013-12-13 13:30:59 -06:00
|
|
|
total_bytes_read += nread;
|
|
|
|
for i in range(0u, nread) {
|
|
|
|
assert_eq!(buf[i], 1);
|
2013-11-06 13:03:11 -06:00
|
|
|
}
|
|
|
|
}
|
2013-12-13 13:30:59 -06:00
|
|
|
uvdebug!("read {} bytes total", total_bytes_read);
|
2013-11-06 13:03:11 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
2013-11-09 13:02:16 -06:00
|
|
|
#[ignore(cfg(windows))] // FIXME(#10102) server never sees second packet
|
2013-11-06 13:03:11 -06:00
|
|
|
fn test_udp_twice() {
|
2014-06-04 02:00:59 -05:00
|
|
|
let server_addr = ::next_test_ip4();
|
|
|
|
let client_addr = ::next_test_ip4();
|
2014-03-09 16:58:32 -05:00
|
|
|
let (tx, rx) = channel();
|
2013-10-22 17:13:18 -05:00
|
|
|
|
2014-01-26 21:57:42 -06:00
|
|
|
spawn(proc() {
|
2013-11-07 17:13:06 -06:00
|
|
|
let mut client = UdpWatcher::bind(local_loop(), client_addr).unwrap();
|
2014-03-09 16:58:32 -05:00
|
|
|
rx.recv();
|
2013-11-07 17:13:06 -06:00
|
|
|
assert!(client.sendto([1], server_addr).is_ok());
|
|
|
|
assert!(client.sendto([2], server_addr).is_ok());
|
2014-01-26 21:57:42 -06:00
|
|
|
});
|
2013-11-07 17:13:06 -06:00
|
|
|
|
|
|
|
let mut server = UdpWatcher::bind(local_loop(), server_addr).unwrap();
|
2014-03-09 16:58:32 -05:00
|
|
|
tx.send(());
|
2013-11-07 17:13:06 -06:00
|
|
|
let mut buf1 = [0];
|
|
|
|
let mut buf2 = [0];
|
2014-06-04 02:00:59 -05:00
|
|
|
let (nread1, src1) = server.recvfrom(buf1).ok().unwrap();
|
|
|
|
let (nread2, src2) = server.recvfrom(buf2).ok().unwrap();
|
2013-11-07 17:13:06 -06:00
|
|
|
assert_eq!(nread1, 1);
|
|
|
|
assert_eq!(nread2, 1);
|
2014-06-04 02:00:59 -05:00
|
|
|
assert!(src1 == client_addr);
|
|
|
|
assert!(src2 == client_addr);
|
2013-11-07 17:13:06 -06:00
|
|
|
assert_eq!(buf1[0], 1);
|
|
|
|
assert_eq!(buf2[0], 2);
|
2013-11-06 13:03:11 -06:00
|
|
|
}
|
2013-10-22 17:13:18 -05:00
|
|
|
|
2013-11-06 13:03:11 -06:00
|
|
|
#[test]
|
|
|
|
fn test_udp_many_read() {
|
2014-06-04 02:00:59 -05:00
|
|
|
let server_out_addr = ::next_test_ip4();
|
|
|
|
let server_in_addr = ::next_test_ip4();
|
|
|
|
let client_out_addr = ::next_test_ip4();
|
|
|
|
let client_in_addr = ::next_test_ip4();
|
2013-11-07 17:13:06 -06:00
|
|
|
static MAX: uint = 500_000;
|
|
|
|
|
2014-03-09 16:58:32 -05:00
|
|
|
let (tx1, rx1) = channel::<()>();
|
|
|
|
let (tx2, rx2) = channel::<()>();
|
2013-11-07 17:13:06 -06:00
|
|
|
|
2014-01-26 21:57:42 -06:00
|
|
|
spawn(proc() {
|
2013-11-07 17:13:06 -06:00
|
|
|
let l = local_loop();
|
|
|
|
let mut server_out = UdpWatcher::bind(l, server_out_addr).unwrap();
|
|
|
|
let mut server_in = UdpWatcher::bind(l, server_in_addr).unwrap();
|
2014-03-09 16:58:32 -05:00
|
|
|
let (tx, rx) = (tx2, rx1);
|
|
|
|
tx.send(());
|
|
|
|
rx.recv();
|
2013-11-07 17:13:06 -06:00
|
|
|
let msg = [1, .. 2048];
|
|
|
|
let mut total_bytes_sent = 0;
|
|
|
|
let mut buf = [1];
|
|
|
|
while buf[0] == 1 {
|
|
|
|
// send more data
|
|
|
|
assert!(server_out.sendto(msg, client_in_addr).is_ok());
|
|
|
|
total_bytes_sent += msg.len();
|
|
|
|
// check if the client has received enough
|
|
|
|
let res = server_in.recvfrom(buf);
|
|
|
|
assert!(res.is_ok());
|
2014-06-04 02:00:59 -05:00
|
|
|
let (nread, src) = res.ok().unwrap();
|
2013-11-07 17:13:06 -06:00
|
|
|
assert_eq!(nread, 1);
|
2014-06-04 02:00:59 -05:00
|
|
|
assert!(src == client_out_addr);
|
2013-11-06 13:03:11 -06:00
|
|
|
}
|
2013-11-07 17:13:06 -06:00
|
|
|
assert!(total_bytes_sent >= MAX);
|
2014-01-26 21:57:42 -06:00
|
|
|
});
|
2013-10-22 17:13:18 -05:00
|
|
|
|
2013-12-13 13:30:59 -06:00
|
|
|
let l = local_loop();
|
|
|
|
let mut client_out = UdpWatcher::bind(l, client_out_addr).unwrap();
|
|
|
|
let mut client_in = UdpWatcher::bind(l, client_in_addr).unwrap();
|
2014-03-09 16:58:32 -05:00
|
|
|
let (tx, rx) = (tx1, rx2);
|
|
|
|
rx.recv();
|
|
|
|
tx.send(());
|
2013-12-13 13:30:59 -06:00
|
|
|
let mut total_bytes_recv = 0;
|
|
|
|
let mut buf = [0, .. 2048];
|
|
|
|
while total_bytes_recv < MAX {
|
|
|
|
// ask for more
|
|
|
|
assert!(client_out.sendto([1], server_in_addr).is_ok());
|
|
|
|
// wait for data
|
|
|
|
let res = client_in.recvfrom(buf);
|
|
|
|
assert!(res.is_ok());
|
2014-06-04 02:00:59 -05:00
|
|
|
let (nread, src) = res.ok().unwrap();
|
|
|
|
assert!(src == server_out_addr);
|
2013-12-13 13:30:59 -06:00
|
|
|
total_bytes_recv += nread;
|
|
|
|
for i in range(0u, nread) {
|
|
|
|
assert_eq!(buf[i], 1);
|
2013-11-06 13:03:11 -06:00
|
|
|
}
|
|
|
|
}
|
2013-12-13 13:30:59 -06:00
|
|
|
// tell the server we're done
|
|
|
|
assert!(client_out.sendto([0], server_in_addr).is_ok());
|
2013-11-06 13:03:11 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_read_and_block() {
|
2014-06-04 02:00:59 -05:00
|
|
|
let addr = ::next_test_ip4();
|
2014-03-09 16:58:32 -05:00
|
|
|
let (tx, rx) = channel::<Receiver<()>>();
|
2013-11-07 17:13:06 -06:00
|
|
|
|
2014-01-26 21:57:42 -06:00
|
|
|
spawn(proc() {
|
2014-03-09 16:58:32 -05:00
|
|
|
let rx = rx.recv();
|
2014-04-18 15:23:56 -05:00
|
|
|
let mut stream = TcpWatcher::connect(local_loop(), addr, None).unwrap();
|
2014-06-04 02:00:59 -05:00
|
|
|
stream.write([0, 1, 2, 3, 4, 5, 6, 7]).ok().unwrap();
|
|
|
|
stream.write([0, 1, 2, 3, 4, 5, 6, 7]).ok().unwrap();
|
2014-03-09 16:58:32 -05:00
|
|
|
rx.recv();
|
2014-06-04 02:00:59 -05:00
|
|
|
stream.write([0, 1, 2, 3, 4, 5, 6, 7]).ok().unwrap();
|
|
|
|
stream.write([0, 1, 2, 3, 4, 5, 6, 7]).ok().unwrap();
|
2014-03-09 16:58:32 -05:00
|
|
|
rx.recv();
|
2014-01-26 21:57:42 -06:00
|
|
|
});
|
2013-12-13 13:30:59 -06:00
|
|
|
|
|
|
|
let listener = TcpListener::bind(local_loop(), addr).unwrap();
|
2014-06-04 02:00:59 -05:00
|
|
|
let mut acceptor = listener.listen().ok().unwrap();
|
2014-03-09 16:58:32 -05:00
|
|
|
let (tx2, rx2) = channel();
|
|
|
|
tx.send(rx2);
|
2014-06-04 02:00:59 -05:00
|
|
|
let mut stream = acceptor.accept().ok().unwrap();
|
2013-12-13 13:30:59 -06:00
|
|
|
let mut buf = [0, .. 2048];
|
|
|
|
|
|
|
|
let expected = 32;
|
|
|
|
let mut current = 0;
|
|
|
|
let mut reads = 0;
|
|
|
|
|
|
|
|
while current < expected {
|
2014-06-04 02:00:59 -05:00
|
|
|
let nread = stream.read(buf).ok().unwrap();
|
2013-12-13 13:30:59 -06:00
|
|
|
for i in range(0u, nread) {
|
|
|
|
let val = buf[i] as uint;
|
|
|
|
assert_eq!(val, current % 8);
|
|
|
|
current += 1;
|
|
|
|
}
|
|
|
|
reads += 1;
|
|
|
|
|
std: Make std::comm return types consistent
There are currently a number of return values from the std::comm methods, not
all of which are necessarily completely expressive:
Sender::try_send(t: T) -> bool
This method currently doesn't transmit back the data `t` if the send fails
due to the other end having disconnected. Additionally, this shares the name
of the synchronous try_send method, but it differs in semantics in that it
only has one failure case, not two (the buffer can never be full).
SyncSender::try_send(t: T) -> TrySendResult<T>
This method accurately conveys all possible information, but it uses a
custom type to the std::comm module with no convenience methods on it.
Additionally, if you want to inspect the result you're forced to import
something from `std::comm`.
SyncSender::send_opt(t: T) -> Option<T>
This method uses Some(T) as an "error value" and None as a "success value",
but almost all other uses of Option<T> have Some/None the other way
Receiver::try_recv(t: T) -> TryRecvResult<T>
Similarly to the synchronous try_send, this custom return type is lacking in
terms of usability (no convenience methods).
With this number of drawbacks in mind, I believed it was time to re-work the
return types of these methods. The new API for the comm module is:
Sender::send(t: T) -> ()
Sender::send_opt(t: T) -> Result<(), T>
SyncSender::send(t: T) -> ()
SyncSender::send_opt(t: T) -> Result<(), T>
SyncSender::try_send(t: T) -> Result<(), TrySendError<T>>
Receiver::recv() -> T
Receiver::recv_opt() -> Result<T, ()>
Receiver::try_recv() -> Result<T, TryRecvError>
The notable changes made are:
* Sender::try_send => Sender::send_opt. This renaming brings the semantics in
line with the SyncSender::send_opt method. An asychronous send only has one
failure case, unlike the synchronous try_send method which has two failure
cases (full/disconnected).
* Sender::send_opt returns the data back to the caller if the send is guaranteed
to fail. This method previously returned `bool`, but then it was unable to
retrieve the data if the data was guaranteed to fail to send. There is still a
race such that when `Ok(())` is returned the data could still fail to be
received, but that's inherent to an asynchronous channel.
* Result is now the basis of all return values. This not only adds lots of
convenience methods to all return values for free, but it also means that you
can inspect the return values with no extra imports (Ok/Err are in the
prelude). Additionally, it's now self documenting when something failed or not
because the return value has "Err" in the name.
Things I'm a little uneasy about:
* The methods send_opt and recv_opt are not returning options, but rather
results. I felt more strongly that Option was the wrong return type than the
_opt prefix was wrong, and I coudn't think of a much better name for these
methods. One possible way to think about them is to read the _opt suffix as
"optionally".
* Result<T, ()> is often better expressed as Option<T>. This is only applicable
to the recv_opt() method, but I thought it would be more consistent for
everything to return Result rather than one method returning an Option.
Despite my two reasons to feel uneasy, I feel much better about the consistency
in return values at this point, and I think the only real open question is if
there's a better suffix for {send,recv}_opt.
Closes #11527
2014-04-10 12:53:49 -05:00
|
|
|
let _ = tx2.send_opt(());
|
2013-12-13 13:30:59 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
// Make sure we had multiple reads
|
|
|
|
assert!(reads > 1);
|
2013-11-06 13:03:11 -06:00
|
|
|
}
|
2013-10-22 17:13:18 -05:00
|
|
|
|
2013-11-06 13:03:11 -06:00
|
|
|
#[test]
|
|
|
|
fn test_simple_tcp_server_and_client_on_diff_threads() {
|
2014-06-04 02:00:59 -05:00
|
|
|
let addr = ::next_test_ip4();
|
2013-11-06 13:03:11 -06:00
|
|
|
|
2014-01-26 21:57:42 -06:00
|
|
|
spawn(proc() {
|
2013-11-07 17:13:06 -06:00
|
|
|
let listener = TcpListener::bind(local_loop(), addr).unwrap();
|
2014-06-04 02:00:59 -05:00
|
|
|
let mut acceptor = listener.listen().ok().unwrap();
|
|
|
|
let mut stream = acceptor.accept().ok().unwrap();
|
2013-11-07 17:13:06 -06:00
|
|
|
let mut buf = [0, .. 2048];
|
2014-06-04 02:00:59 -05:00
|
|
|
let nread = stream.read(buf).ok().unwrap();
|
2013-11-07 17:13:06 -06:00
|
|
|
assert_eq!(nread, 8);
|
|
|
|
for i in range(0u, nread) {
|
|
|
|
assert_eq!(buf[i], i as u8);
|
2013-10-22 17:13:18 -05:00
|
|
|
}
|
2014-01-26 21:57:42 -06:00
|
|
|
});
|
2013-10-22 17:13:18 -05:00
|
|
|
|
2014-04-18 15:23:56 -05:00
|
|
|
let mut stream = TcpWatcher::connect(local_loop(), addr, None);
|
2013-12-13 13:30:59 -06:00
|
|
|
while stream.is_err() {
|
2014-04-18 15:23:56 -05:00
|
|
|
stream = TcpWatcher::connect(local_loop(), addr, None);
|
2013-10-22 17:13:18 -05:00
|
|
|
}
|
2014-06-04 02:00:59 -05:00
|
|
|
stream.unwrap().write([0, 1, 2, 3, 4, 5, 6, 7]).ok().unwrap();
|
2013-10-22 17:13:18 -05:00
|
|
|
}
|
2013-11-06 13:03:11 -06:00
|
|
|
|
2013-11-07 22:13:25 -06:00
|
|
|
#[should_fail] #[test]
|
|
|
|
fn tcp_listener_fail_cleanup() {
|
2014-06-04 02:00:59 -05:00
|
|
|
let addr = ::next_test_ip4();
|
2013-11-07 22:13:25 -06:00
|
|
|
let w = TcpListener::bind(local_loop(), addr).unwrap();
|
2014-06-04 02:00:59 -05:00
|
|
|
let _w = w.listen().ok().unwrap();
|
2013-11-07 22:13:25 -06:00
|
|
|
fail!();
|
|
|
|
}
|
|
|
|
|
|
|
|
#[should_fail] #[test]
|
|
|
|
fn tcp_stream_fail_cleanup() {
|
2014-03-09 16:58:32 -05:00
|
|
|
let (tx, rx) = channel();
|
2014-06-04 02:00:59 -05:00
|
|
|
let addr = ::next_test_ip4();
|
2013-11-07 22:13:25 -06:00
|
|
|
|
2014-01-26 21:57:42 -06:00
|
|
|
spawn(proc() {
|
2013-11-07 22:13:25 -06:00
|
|
|
let w = TcpListener::bind(local_loop(), addr).unwrap();
|
2014-06-04 02:00:59 -05:00
|
|
|
let mut w = w.listen().ok().unwrap();
|
2014-03-09 16:58:32 -05:00
|
|
|
tx.send(());
|
2014-06-04 02:00:59 -05:00
|
|
|
drop(w.accept().ok().unwrap());
|
2014-01-26 21:57:42 -06:00
|
|
|
});
|
2014-03-09 16:58:32 -05:00
|
|
|
rx.recv();
|
2014-04-18 15:23:56 -05:00
|
|
|
let _w = TcpWatcher::connect(local_loop(), addr, None).unwrap();
|
2013-11-07 22:13:25 -06:00
|
|
|
fail!();
|
|
|
|
}
|
|
|
|
|
|
|
|
#[should_fail] #[test]
|
|
|
|
fn udp_listener_fail_cleanup() {
|
2014-06-04 02:00:59 -05:00
|
|
|
let addr = ::next_test_ip4();
|
2013-11-07 22:13:25 -06:00
|
|
|
let _w = UdpWatcher::bind(local_loop(), addr).unwrap();
|
|
|
|
fail!();
|
|
|
|
}
|
|
|
|
|
|
|
|
#[should_fail] #[test]
|
|
|
|
fn udp_fail_other_task() {
|
2014-06-04 02:00:59 -05:00
|
|
|
let addr = ::next_test_ip4();
|
2014-03-09 16:58:32 -05:00
|
|
|
let (tx, rx) = channel();
|
2013-11-07 22:13:25 -06:00
|
|
|
|
|
|
|
// force the handle to be created on a different scheduler, failure in
|
|
|
|
// the original task will force a homing operation back to this
|
|
|
|
// scheduler.
|
2014-01-26 21:57:42 -06:00
|
|
|
spawn(proc() {
|
2013-11-07 22:13:25 -06:00
|
|
|
let w = UdpWatcher::bind(local_loop(), addr).unwrap();
|
2014-03-09 16:58:32 -05:00
|
|
|
tx.send(w);
|
2014-01-26 21:57:42 -06:00
|
|
|
});
|
2013-11-07 22:13:25 -06:00
|
|
|
|
2014-03-09 16:58:32 -05:00
|
|
|
let _w = rx.recv();
|
2013-11-07 22:13:25 -06:00
|
|
|
fail!();
|
|
|
|
}
|
2013-10-22 17:13:18 -05:00
|
|
|
}
|