1
Fork 0

auto merge of #11186 : alexcrichton/rust/native-udp, r=brson

I personally do not have huge amounts of experience in this area, so there's likely a thing or two wrong around the edges. I tried to just copy what libuv is doing as closely as possible with a few tweaks in a few places, but all of the `std::io::net::udp` tests are now run in both native and green settings so the published functionality is all being tested.
This commit is contained in:
bors 2013-12-31 16:21:55 -08:00
commit 09a561ac9c
4 changed files with 379 additions and 113 deletions

View file

@ -166,8 +166,8 @@ impl rtio::IoFactory for IoFactory {
fn tcp_bind(&mut self, addr: SocketAddr) -> IoResult<~RtioTcpListener> { fn tcp_bind(&mut self, addr: SocketAddr) -> IoResult<~RtioTcpListener> {
net::TcpListener::bind(addr).map(|s| ~s as ~RtioTcpListener) net::TcpListener::bind(addr).map(|s| ~s as ~RtioTcpListener)
} }
fn udp_bind(&mut self, _addr: SocketAddr) -> IoResult<~RtioUdpSocket> { fn udp_bind(&mut self, addr: SocketAddr) -> IoResult<~RtioUdpSocket> {
Err(unimpl()) net::UdpSocket::bind(addr).map(|u| ~u as ~RtioUdpSocket)
} }
fn unix_bind(&mut self, _path: &CString) -> IoResult<~RtioUnixListener> { fn unix_bind(&mut self, _path: &CString) -> IoResult<~RtioUnixListener> {
Err(unimpl()) Err(unimpl())

View file

@ -19,13 +19,13 @@ use std::unstable::intrinsics;
use super::IoResult; use super::IoResult;
use super::file::keep_going; use super::file::keep_going;
////////////////////////////////////////////////////////////////////////////////
// sockaddr and misc bindings
////////////////////////////////////////////////////////////////////////////////
#[cfg(windows)] pub type sock_t = libc::SOCKET; #[cfg(windows)] pub type sock_t = libc::SOCKET;
#[cfg(unix)] pub type sock_t = super::file::fd_t; #[cfg(unix)] pub type sock_t = super::file::fd_t;
pub struct TcpStream {
priv fd: sock_t,
}
#[cfg(target_endian = "big")] pub fn htons(x: u16) -> u16 { x } #[cfg(target_endian = "big")] pub fn htons(x: u16) -> u16 { x }
#[cfg(target_endian = "big")] pub fn ntohs(x: u16) -> u16 { x } #[cfg(target_endian = "big")] pub fn ntohs(x: u16) -> u16 { x }
#[cfg(target_endian = "little")] #[cfg(target_endian = "little")]
@ -37,32 +37,54 @@ pub fn ntohs(u: u16) -> u16 {
unsafe { intrinsics::bswap16(u as i16) as u16 } unsafe { intrinsics::bswap16(u as i16) as u16 }
} }
enum InAddr {
InAddr(libc::in_addr),
In6Addr(libc::in6_addr),
}
fn ip_to_inaddr(ip: ip::IpAddr) -> InAddr {
match ip {
ip::Ipv4Addr(a, b, c, d) => {
InAddr(libc::in_addr {
s_addr: (d as u32 << 24) |
(c as u32 << 16) |
(b as u32 << 8) |
(a as u32 << 0)
})
}
ip::Ipv6Addr(a, b, c, d, e, f, g, h) => {
In6Addr(libc::in6_addr {
s6_addr: [
htons(a),
htons(b),
htons(c),
htons(d),
htons(e),
htons(f),
htons(g),
htons(h),
]
})
}
}
}
fn addr_to_sockaddr(addr: ip::SocketAddr) -> (libc::sockaddr_storage, uint) { fn addr_to_sockaddr(addr: ip::SocketAddr) -> (libc::sockaddr_storage, uint) {
unsafe { unsafe {
let storage: libc::sockaddr_storage = intrinsics::init(); let storage: libc::sockaddr_storage = intrinsics::init();
let len = match addr.ip { let len = match ip_to_inaddr(addr.ip) {
ip::Ipv4Addr(a, b, c, d) => { InAddr(inaddr) => {
let storage: *mut libc::sockaddr_in = cast::transmute(&storage); let storage: *mut libc::sockaddr_in = cast::transmute(&storage);
(*storage).sin_family = libc::AF_INET as libc::sa_family_t; (*storage).sin_family = libc::AF_INET as libc::sa_family_t;
(*storage).sin_port = htons(addr.port); (*storage).sin_port = htons(addr.port);
(*storage).sin_addr.s_addr = (d as u32 << 24) | (*storage).sin_addr = inaddr;
(c as u32 << 16) |
(b as u32 << 8) |
(a as u32 << 0);
mem::size_of::<libc::sockaddr_in>() mem::size_of::<libc::sockaddr_in>()
} }
ip::Ipv6Addr(a, b, c, d, e, f, g, h) => { In6Addr(inaddr) => {
let storage: *mut libc::sockaddr_in6 = cast::transmute(&storage); let storage: *mut libc::sockaddr_in6 = cast::transmute(&storage);
(*storage).sin6_family = libc::AF_INET6 as libc::sa_family_t; (*storage).sin6_family = libc::AF_INET6 as libc::sa_family_t;
(*storage).sin6_port = htons(addr.port); (*storage).sin6_port = htons(addr.port);
(*storage).sin6_addr.s6_addr[0] = htons(a); (*storage).sin6_addr = inaddr;
(*storage).sin6_addr.s6_addr[1] = htons(b);
(*storage).sin6_addr.s6_addr[2] = htons(c);
(*storage).sin6_addr.s6_addr[3] = htons(d);
(*storage).sin6_addr.s6_addr[4] = htons(e);
(*storage).sin6_addr.s6_addr[5] = htons(f);
(*storage).sin6_addr.s6_addr[6] = htons(g);
(*storage).sin6_addr.s6_addr[7] = htons(h);
mem::size_of::<libc::sockaddr_in6>() mem::size_of::<libc::sockaddr_in6>()
} }
}; };
@ -70,19 +92,33 @@ fn addr_to_sockaddr(addr: ip::SocketAddr) -> (libc::sockaddr_storage, uint) {
} }
} }
fn socket(addr: ip::SocketAddr) -> IoResult<sock_t> { fn socket(addr: ip::SocketAddr, ty: libc::c_int) -> IoResult<sock_t> {
unsafe { unsafe {
let fam = match addr.ip { let fam = match addr.ip {
ip::Ipv4Addr(..) => libc::AF_INET, ip::Ipv4Addr(..) => libc::AF_INET,
ip::Ipv6Addr(..) => libc::AF_INET6, ip::Ipv6Addr(..) => libc::AF_INET6,
}; };
match libc::socket(fam, libc::SOCK_STREAM, 0) { match libc::socket(fam, ty, 0) {
-1 => Err(super::last_error()), -1 => Err(super::last_error()),
fd => Ok(fd), fd => Ok(fd),
} }
} }
} }
fn setsockopt<T>(fd: sock_t, opt: libc::c_int, val: libc::c_int,
payload: T) -> IoResult<()> {
unsafe {
let payload = &payload as *T as *libc::c_void;
let ret = libc::setsockopt(fd, opt, val,
payload,
mem::size_of::<T>() as libc::socklen_t);
super::mkerr_libc(ret)
}
}
#[cfg(windows)] unsafe fn close(sock: sock_t) { libc::closesocket(sock); }
#[cfg(unix)] unsafe fn close(sock: sock_t) { libc::close(sock); }
fn sockname(fd: sock_t, fn sockname(fd: sock_t,
f: extern "system" unsafe fn(sock_t, *mut libc::sockaddr, f: extern "system" unsafe fn(sock_t, *mut libc::sockaddr,
*mut libc::socklen_t) -> libc::c_int) *mut libc::socklen_t) -> libc::c_int)
@ -99,11 +135,16 @@ fn sockname(fd: sock_t,
return Err(super::last_error()) return Err(super::last_error())
} }
} }
return sockaddr_to_addr(&storage, len as uint);
}
fn sockaddr_to_addr(storage: &libc::sockaddr_storage,
len: uint) -> IoResult<ip::SocketAddr> {
match storage.ss_family as libc::c_int { match storage.ss_family as libc::c_int {
libc::AF_INET => { libc::AF_INET => {
assert!(len as uint >= mem::size_of::<libc::sockaddr_in>()); assert!(len as uint >= mem::size_of::<libc::sockaddr_in>());
let storage: &mut libc::sockaddr_in = unsafe { let storage: &libc::sockaddr_in = unsafe {
cast::transmute(&mut storage) cast::transmute(storage)
}; };
let addr = storage.sin_addr.s_addr as u32; let addr = storage.sin_addr.s_addr as u32;
let a = (addr >> 0) as u8; let a = (addr >> 0) as u8;
@ -117,8 +158,8 @@ fn sockname(fd: sock_t,
} }
libc::AF_INET6 => { libc::AF_INET6 => {
assert!(len as uint >= mem::size_of::<libc::sockaddr_in6>()); assert!(len as uint >= mem::size_of::<libc::sockaddr_in6>());
let storage: &mut libc::sockaddr_in6 = unsafe { let storage: &libc::sockaddr_in6 = unsafe {
cast::transmute(&mut storage) cast::transmute(storage)
}; };
let a = ntohs(storage.sin6_addr.s6_addr[0]); let a = ntohs(storage.sin6_addr.s6_addr[0]);
let b = ntohs(storage.sin6_addr.s6_addr[1]); let b = ntohs(storage.sin6_addr.s6_addr[1]);
@ -180,10 +221,18 @@ pub fn init() {
} }
} }
////////////////////////////////////////////////////////////////////////////////
// TCP streams
////////////////////////////////////////////////////////////////////////////////
pub struct TcpStream {
priv fd: sock_t,
}
impl TcpStream { impl TcpStream {
pub fn connect(addr: ip::SocketAddr) -> IoResult<TcpStream> { pub fn connect(addr: ip::SocketAddr) -> IoResult<TcpStream> {
unsafe { unsafe {
socket(addr).and_then(|fd| { socket(addr, libc::SOCK_STREAM).and_then(|fd| {
let (addr, len) = addr_to_sockaddr(addr); let (addr, len) = addr_to_sockaddr(addr);
let addrp = &addr as *libc::sockaddr_storage; let addrp = &addr as *libc::sockaddr_storage;
let ret = TcpStream { fd: fd }; let ret = TcpStream { fd: fd };
@ -199,63 +248,31 @@ impl TcpStream {
pub fn fd(&self) -> sock_t { self.fd } pub fn fd(&self) -> sock_t { self.fd }
fn set_nodelay(&mut self, nodelay: bool) -> IoResult<()> { fn set_nodelay(&mut self, nodelay: bool) -> IoResult<()> {
unsafe { setsockopt(self.fd, libc::IPPROTO_TCP, libc::TCP_NODELAY,
let on = nodelay as libc::c_int; nodelay as libc::c_int)
let on = &on as *libc::c_int;
super::mkerr_libc(libc::setsockopt(self.fd,
libc::IPPROTO_TCP,
libc::TCP_NODELAY,
on as *libc::c_void,
mem::size_of::<libc::c_void>()
as libc::socklen_t))
}
} }
fn set_keepalive(&mut self, seconds: Option<uint>) -> IoResult<()> { fn set_keepalive(&mut self, seconds: Option<uint>) -> IoResult<()> {
unsafe { let ret = setsockopt(self.fd, libc::SOL_SOCKET, libc::SO_KEEPALIVE,
let on = seconds.is_some() as libc::c_int; seconds.is_some() as libc::c_int);
let on = &on as *libc::c_int; match seconds {
let ret = libc::setsockopt(self.fd, Some(n) => ret.and_then(|()| self.set_tcp_keepalive(n)),
libc::SOL_SOCKET, None => ret,
libc::SO_KEEPALIVE,
on as *libc::c_void,
mem::size_of::<libc::c_void>()
as libc::socklen_t);
if ret != 0 { return Err(super::last_error()) }
match seconds {
Some(n) => self.set_tcp_keepalive(n),
None => Ok(())
}
} }
} }
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
unsafe fn set_tcp_keepalive(&mut self, seconds: uint) -> IoResult<()> { fn set_tcp_keepalive(&mut self, seconds: uint) -> IoResult<()> {
let delay = seconds as libc::c_uint; setsockopt(self.fd, libc::IPPROTO_TCP, libc::TCP_KEEPALIVE,
let delay = &delay as *libc::c_uint; seconds as libc::c_int)
let ret = libc::setsockopt(self.fd,
libc::IPPROTO_TCP,
libc::TCP_KEEPALIVE,
delay as *libc::c_void,
mem::size_of::<libc::c_uint>()
as libc::socklen_t);
super::mkerr_libc(ret)
} }
#[cfg(target_os = "freebsd")] #[cfg(target_os = "freebsd")]
unsafe fn set_tcp_keepalive(&mut self, seconds: uint) -> IoResult<()> { fn set_tcp_keepalive(&mut self, seconds: uint) -> IoResult<()> {
let delay = seconds as libc::c_uint; setsockopt(self.fd, libc::IPPROTO_TCP, libc::TCP_KEEPIDLE,
let delay = &delay as *libc::c_uint; seconds as libc::c_int)
let ret = libc::setsockopt(self.fd,
libc::IPPROTO_TCP,
libc::TCP_KEEPIDLE,
delay as *libc::c_void,
mem::size_of::<libc::c_uint>()
as libc::socklen_t);
super::mkerr_libc(ret)
} }
#[cfg(not(target_os = "macos"), not(target_os = "freebsd"))] #[cfg(not(target_os = "macos"), not(target_os = "freebsd"))]
unsafe fn set_tcp_keepalive(&mut self, _seconds: uint) -> IoResult<()> { fn set_tcp_keepalive(&mut self, _seconds: uint) -> IoResult<()> {
Ok(()) Ok(())
} }
} }
@ -320,17 +337,13 @@ impl rtio::RtioSocket for TcpStream {
} }
impl Drop for TcpStream { impl Drop for TcpStream {
#[cfg(unix)] fn drop(&mut self) { unsafe { close(self.fd); } }
fn drop(&mut self) {
unsafe { libc::close(self.fd); }
}
#[cfg(windows)]
fn drop(&mut self) {
unsafe { libc::closesocket(self.fd); }
}
} }
////////////////////////////////////////////////////////////////////////////////
// TCP listeners
////////////////////////////////////////////////////////////////////////////////
pub struct TcpListener { pub struct TcpListener {
priv fd: sock_t, priv fd: sock_t,
} }
@ -338,7 +351,7 @@ pub struct TcpListener {
impl TcpListener { impl TcpListener {
pub fn bind(addr: ip::SocketAddr) -> IoResult<TcpListener> { pub fn bind(addr: ip::SocketAddr) -> IoResult<TcpListener> {
unsafe { unsafe {
socket(addr).and_then(|fd| { socket(addr, libc::SOCK_STREAM).and_then(|fd| {
let (addr, len) = addr_to_sockaddr(addr); let (addr, len) = addr_to_sockaddr(addr);
let addrp = &addr as *libc::sockaddr_storage; let addrp = &addr as *libc::sockaddr_storage;
let ret = TcpListener { fd: fd }; let ret = TcpListener { fd: fd };
@ -356,7 +369,7 @@ impl TcpListener {
pub fn native_listen(self, backlog: int) -> IoResult<TcpAcceptor> { pub fn native_listen(self, backlog: int) -> IoResult<TcpAcceptor> {
match unsafe { libc::listen(self.fd, backlog as libc::c_int) } { match unsafe { libc::listen(self.fd, backlog as libc::c_int) } {
-1 => Err(super::last_error()), -1 => Err(super::last_error()),
_ => Ok(TcpAcceptor { fd: self.fd }) _ => Ok(TcpAcceptor { listener: self })
} }
} }
} }
@ -373,12 +386,16 @@ impl rtio::RtioSocket for TcpListener {
} }
} }
impl Drop for TcpListener {
fn drop(&mut self) { unsafe { close(self.fd); } }
}
pub struct TcpAcceptor { pub struct TcpAcceptor {
priv fd: sock_t, priv listener: TcpListener,
} }
impl TcpAcceptor { impl TcpAcceptor {
pub fn fd(&self) -> sock_t { self.fd } pub fn fd(&self) -> sock_t { self.listener.fd }
pub fn native_accept(&mut self) -> IoResult<TcpStream> { pub fn native_accept(&mut self) -> IoResult<TcpStream> {
unsafe { unsafe {
@ -386,7 +403,7 @@ impl TcpAcceptor {
let storagep = &mut storage as *mut libc::sockaddr_storage; let storagep = &mut storage as *mut libc::sockaddr_storage;
let size = mem::size_of::<libc::sockaddr_storage>(); let size = mem::size_of::<libc::sockaddr_storage>();
let mut size = size as libc::socklen_t; let mut size = size as libc::socklen_t;
match libc::accept(self.fd, match libc::accept(self.fd(),
storagep as *mut libc::sockaddr, storagep as *mut libc::sockaddr,
&mut size as *mut libc::socklen_t) { &mut size as *mut libc::socklen_t) {
-1 => Err(super::last_error()), -1 => Err(super::last_error()),
@ -398,7 +415,7 @@ impl TcpAcceptor {
impl rtio::RtioSocket for TcpAcceptor { impl rtio::RtioSocket for TcpAcceptor {
fn socket_name(&mut self) -> IoResult<ip::SocketAddr> { fn socket_name(&mut self) -> IoResult<ip::SocketAddr> {
sockname(self.fd, libc::getsockname) sockname(self.fd(), libc::getsockname)
} }
} }
@ -410,3 +427,161 @@ impl rtio::RtioTcpAcceptor for TcpAcceptor {
fn accept_simultaneously(&mut self) -> IoResult<()> { Ok(()) } fn accept_simultaneously(&mut self) -> IoResult<()> { Ok(()) }
fn dont_accept_simultaneously(&mut self) -> IoResult<()> { Ok(()) } fn dont_accept_simultaneously(&mut self) -> IoResult<()> { Ok(()) }
} }
////////////////////////////////////////////////////////////////////////////////
// UDP
////////////////////////////////////////////////////////////////////////////////
pub struct UdpSocket {
priv fd: sock_t,
}
impl UdpSocket {
pub fn bind(addr: ip::SocketAddr) -> IoResult<UdpSocket> {
unsafe {
socket(addr, libc::SOCK_DGRAM).and_then(|fd| {
let (addr, len) = addr_to_sockaddr(addr);
let addrp = &addr as *libc::sockaddr_storage;
let ret = UdpSocket { fd: fd };
match libc::bind(fd, addrp as *libc::sockaddr,
len as libc::socklen_t) {
-1 => Err(super::last_error()),
_ => Ok(ret),
}
})
}
}
pub fn fd(&self) -> sock_t { self.fd }
pub fn set_broadcast(&mut self, on: bool) -> IoResult<()> {
setsockopt(self.fd, libc::SOL_SOCKET, libc::SO_BROADCAST,
on as libc::c_int)
}
pub fn set_multicast_loop(&mut self, on: bool) -> IoResult<()> {
setsockopt(self.fd, libc::IPPROTO_IP, libc::IP_MULTICAST_LOOP,
on as libc::c_int)
}
pub fn set_membership(&mut self, addr: ip::IpAddr,
opt: libc::c_int) -> IoResult<()> {
match ip_to_inaddr(addr) {
InAddr(addr) => {
let mreq = libc::ip_mreq {
imr_multiaddr: addr,
// interface == INADDR_ANY
imr_interface: libc::in_addr { s_addr: 0x0 },
};
setsockopt(self.fd, libc::IPPROTO_IP, opt, mreq)
}
In6Addr(addr) => {
let mreq = libc::ip6_mreq {
ipv6mr_multiaddr: addr,
ipv6mr_interface: 0,
};
setsockopt(self.fd, libc::IPPROTO_IPV6, opt, mreq)
}
}
}
}
impl rtio::RtioSocket for UdpSocket {
fn socket_name(&mut self) -> IoResult<ip::SocketAddr> {
sockname(self.fd(), libc::getsockname)
}
}
#[cfg(windows)] type msglen_t = libc::c_int;
#[cfg(unix)] type msglen_t = libc::size_t;
impl rtio::RtioUdpSocket for UdpSocket {
fn recvfrom(&mut self, buf: &mut [u8]) -> IoResult<(uint, ip::SocketAddr)> {
unsafe {
let mut storage: libc::sockaddr_storage = intrinsics::init();
let storagep = &mut storage as *mut libc::sockaddr_storage;
let mut addrlen: libc::socklen_t =
mem::size_of::<libc::sockaddr_storage>() as libc::socklen_t;
let ret = libc::recvfrom(self.fd,
buf.as_ptr() as *mut libc::c_void,
buf.len() as msglen_t,
0,
storagep as *mut libc::sockaddr,
&mut addrlen);
if ret < 0 { return Err(super::last_error()) }
sockaddr_to_addr(&storage, addrlen as uint).and_then(|addr| {
Ok((ret as uint, addr))
})
}
}
fn sendto(&mut self, buf: &[u8], dst: ip::SocketAddr) -> IoResult<()> {
let (dst, len) = addr_to_sockaddr(dst);
let dstp = &dst as *libc::sockaddr_storage;
unsafe {
let ret = libc::sendto(self.fd,
buf.as_ptr() as *libc::c_void,
buf.len() as msglen_t,
0,
dstp as *libc::sockaddr,
len as libc::socklen_t);
match ret {
-1 => Err(super::last_error()),
n if n as uint != buf.len() => {
Err(io::IoError {
kind: io::OtherIoError,
desc: "couldn't send entire packet at once",
detail: None,
})
}
_ => Ok(())
}
}
}
fn join_multicast(&mut self, multi: ip::IpAddr) -> IoResult<()> {
match multi {
ip::Ipv4Addr(..) => {
self.set_membership(multi, libc::IP_ADD_MEMBERSHIP)
}
ip::Ipv6Addr(..) => {
self.set_membership(multi, libc::IPV6_ADD_MEMBERSHIP)
}
}
}
fn leave_multicast(&mut self, multi: ip::IpAddr) -> IoResult<()> {
match multi {
ip::Ipv4Addr(..) => {
self.set_membership(multi, libc::IP_DROP_MEMBERSHIP)
}
ip::Ipv6Addr(..) => {
self.set_membership(multi, libc::IPV6_DROP_MEMBERSHIP)
}
}
}
fn loop_multicast_locally(&mut self) -> IoResult<()> {
self.set_multicast_loop(true)
}
fn dont_loop_multicast_locally(&mut self) -> IoResult<()> {
self.set_multicast_loop(false)
}
fn multicast_time_to_live(&mut self, ttl: int) -> IoResult<()> {
setsockopt(self.fd, libc::IPPROTO_IP, libc::IP_MULTICAST_TTL,
ttl as libc::c_int)
}
fn time_to_live(&mut self, ttl: int) -> IoResult<()> {
setsockopt(self.fd, libc::IPPROTO_IP, libc::IP_TTL, ttl as libc::c_int)
}
fn hear_broadcasts(&mut self) -> IoResult<()> {
self.set_broadcast(true)
}
fn ignore_broadcasts(&mut self) -> IoResult<()> {
self.set_broadcast(false)
}
}
impl Drop for UdpSocket {
fn drop(&mut self) { unsafe { close(self.fd) } }
}

View file

@ -104,11 +104,10 @@ mod test {
use io::test::*; use io::test::*;
use prelude::*; use prelude::*;
#[test] #[ignore] iotest!(fn bind_error() {
fn bind_error() {
let mut called = false; let mut called = false;
io_error::cond.trap(|e| { io_error::cond.trap(|e| {
assert!(e.kind == PermissionDenied); assert_eq!(e.kind, PermissionDenied);
called = true; called = true;
}).inside(|| { }).inside(|| {
let addr = SocketAddr { ip: Ipv4Addr(0, 0, 0, 0), port: 1 }; let addr = SocketAddr { ip: Ipv4Addr(0, 0, 0, 0), port: 1 };
@ -116,13 +115,13 @@ mod test {
assert!(socket.is_none()); assert!(socket.is_none());
}); });
assert!(called); assert!(called);
} } #[ignore(cfg(windows))])
#[test] iotest!(fn socket_smoke_test_ip4() {
fn socket_smoke_test_ip4() {
let server_ip = next_test_ip4(); let server_ip = next_test_ip4();
let client_ip = next_test_ip4(); let client_ip = next_test_ip4();
let (port, chan) = Chan::new(); let (port, chan) = Chan::new();
let (port2, chan2) = Chan::new();
do spawn { do spawn {
match UdpSocket::bind(client_ip) { match UdpSocket::bind(client_ip) {
@ -132,6 +131,7 @@ mod test {
} }
None => fail!() None => fail!()
} }
chan2.send(());
} }
match UdpSocket::bind(server_ip) { match UdpSocket::bind(server_ip) {
@ -149,10 +149,10 @@ mod test {
} }
None => fail!() None => fail!()
} }
} port2.recv();
})
#[test] iotest!(fn socket_smoke_test_ip6() {
fn socket_smoke_test_ip6() {
let server_ip = next_test_ip6(); let server_ip = next_test_ip6();
let client_ip = next_test_ip6(); let client_ip = next_test_ip6();
let (port, chan) = Chan::<()>::new(); let (port, chan) = Chan::<()>::new();
@ -182,13 +182,13 @@ mod test {
} }
None => fail!() None => fail!()
} }
} })
#[test] iotest!(fn stream_smoke_test_ip4() {
fn stream_smoke_test_ip4() {
let server_ip = next_test_ip4(); let server_ip = next_test_ip4();
let client_ip = next_test_ip4(); let client_ip = next_test_ip4();
let (port, chan) = Chan::new(); let (port, chan) = Chan::new();
let (port2, chan2) = Chan::new();
do spawn { do spawn {
match UdpSocket::bind(client_ip) { match UdpSocket::bind(client_ip) {
@ -200,6 +200,7 @@ mod test {
} }
None => fail!() None => fail!()
} }
chan2.send(());
} }
match UdpSocket::bind(server_ip) { match UdpSocket::bind(server_ip) {
@ -218,13 +219,14 @@ mod test {
} }
None => fail!() None => fail!()
} }
} port2.recv();
})
#[test] iotest!(fn stream_smoke_test_ip6() {
fn stream_smoke_test_ip6() {
let server_ip = next_test_ip6(); let server_ip = next_test_ip6();
let client_ip = next_test_ip6(); let client_ip = next_test_ip6();
let (port, chan) = Chan::new(); let (port, chan) = Chan::new();
let (port2, chan2) = Chan::new();
do spawn { do spawn {
match UdpSocket::bind(client_ip) { match UdpSocket::bind(client_ip) {
@ -236,6 +238,7 @@ mod test {
} }
None => fail!() None => fail!()
} }
chan2.send(());
} }
match UdpSocket::bind(server_ip) { match UdpSocket::bind(server_ip) {
@ -254,9 +257,10 @@ mod test {
} }
None => fail!() None => fail!()
} }
} port2.recv();
})
fn socket_name(addr: SocketAddr) { pub fn socket_name(addr: SocketAddr) {
let server = UdpSocket::bind(addr); let server = UdpSocket::bind(addr);
assert!(server.is_some()); assert!(server.is_some());
@ -269,13 +273,11 @@ mod test {
assert_eq!(addr, so_name.unwrap()); assert_eq!(addr, so_name.unwrap());
} }
#[test] iotest!(fn socket_name_ip4() {
fn socket_name_ip4() {
socket_name(next_test_ip4()); socket_name(next_test_ip4());
} })
#[test] iotest!(fn socket_name_ip6() {
fn socket_name_ip6() {
socket_name(next_test_ip6()); socket_name(next_test_ip6());
} })
} }

View file

@ -256,6 +256,8 @@ pub mod types {
pub enum timezone {} pub enum timezone {}
} }
pub mod bsd44 { pub mod bsd44 {
use libc::types::os::arch::c95::c_uint;
pub type socklen_t = u32; pub type socklen_t = u32;
pub type sa_family_t = u16; pub type sa_family_t = u16;
pub type in_port_t = u16; pub type in_port_t = u16;
@ -288,6 +290,14 @@ pub mod types {
pub struct in6_addr { pub struct in6_addr {
s6_addr: [u16, ..8] s6_addr: [u16, ..8]
} }
pub struct ip_mreq {
imr_multiaddr: in_addr,
imr_interface: in_addr,
}
pub struct ip6_mreq {
ipv6mr_multiaddr: in6_addr,
ipv6mr_interface: c_uint,
}
} }
} }
@ -603,6 +613,8 @@ pub mod types {
pub enum timezone {} pub enum timezone {}
} }
pub mod bsd44 { pub mod bsd44 {
use libc::types::os::arch::c95::c_uint;
pub type socklen_t = u32; pub type socklen_t = u32;
pub type sa_family_t = u8; pub type sa_family_t = u8;
pub type in_port_t = u16; pub type in_port_t = u16;
@ -640,6 +652,14 @@ pub mod types {
pub struct in6_addr { pub struct in6_addr {
s6_addr: [u16, ..8] s6_addr: [u16, ..8]
} }
pub struct ip_mreq {
imr_multiaddr: in_addr,
imr_interface: in_addr,
}
pub struct ip6_mreq {
ipv6mr_multiaddr: in6_addr,
ipv6mr_interface: c_uint,
}
} }
} }
@ -815,6 +835,14 @@ pub mod types {
pub struct in6_addr { pub struct in6_addr {
s6_addr: [u16, ..8] s6_addr: [u16, ..8]
} }
pub struct ip_mreq {
imr_multiaddr: in_addr,
imr_interface: in_addr,
}
pub struct ip6_mreq {
ipv6mr_multiaddr: in6_addr,
ipv6mr_interface: c_uint,
}
} }
} }
@ -1082,7 +1110,7 @@ pub mod types {
} }
pub mod bsd44 { pub mod bsd44 {
use libc::types::os::arch::c95::c_int; use libc::types::os::arch::c95::{c_int, c_uint};
pub type socklen_t = c_int; pub type socklen_t = c_int;
pub type sa_family_t = u8; pub type sa_family_t = u8;
@ -1121,6 +1149,14 @@ pub mod types {
pub struct in6_addr { pub struct in6_addr {
s6_addr: [u16, ..8] s6_addr: [u16, ..8]
} }
pub struct ip_mreq {
imr_multiaddr: in_addr,
imr_interface: in_addr,
}
pub struct ip6_mreq {
ipv6mr_multiaddr: in6_addr,
ipv6mr_interface: c_uint,
}
} }
} }
@ -1445,10 +1481,20 @@ pub mod consts {
pub static SOCK_STREAM: c_int = 1; pub static SOCK_STREAM: c_int = 1;
pub static SOCK_DGRAM: c_int = 2; pub static SOCK_DGRAM: c_int = 2;
pub static IPPROTO_TCP: c_int = 6; pub static IPPROTO_TCP: c_int = 6;
pub static IPPROTO_IP: c_int = 0;
pub static IPPROTO_IPV6: c_int = 41;
pub static IP_MULTICAST_TTL: c_int = 3;
pub static IP_MULTICAST_LOOP: c_int = 4;
pub static IP_ADD_MEMBERSHIP: c_int = 5;
pub static IP_DROP_MEMBERSHIP: c_int = 6;
pub static IPV6_ADD_MEMBERSHIP: c_int = 5;
pub static IPV6_DROP_MEMBERSHIP: c_int = 6;
pub static IP_TTL: c_int = 4;
pub static TCP_NODELAY: c_int = 0x0001; pub static TCP_NODELAY: c_int = 0x0001;
pub static SOL_SOCKET: c_int = 0xffff; pub static SOL_SOCKET: c_int = 0xffff;
pub static SO_KEEPALIVE: c_int = 8; pub static SO_KEEPALIVE: c_int = 8;
pub static SO_BROADCAST: c_int = 32;
} }
pub mod extra { pub mod extra {
use libc::types::os::arch::c95::c_int; use libc::types::os::arch::c95::c_int;
@ -2154,10 +2200,20 @@ pub mod consts {
pub static SOCK_STREAM: c_int = 1; pub static SOCK_STREAM: c_int = 1;
pub static SOCK_DGRAM: c_int = 2; pub static SOCK_DGRAM: c_int = 2;
pub static IPPROTO_TCP: c_int = 6; pub static IPPROTO_TCP: c_int = 6;
pub static IPPROTO_IP: c_int = 0;
pub static IPPROTO_IPV6: c_int = 41;
pub static IP_MULTICAST_TTL: c_int = 33;
pub static IP_MULTICAST_LOOP: c_int = 34;
pub static IP_TTL: c_int = 2;
pub static IP_ADD_MEMBERSHIP: c_int = 35;
pub static IP_DROP_MEMBERSHIP: c_int = 36;
pub static IPV6_ADD_MEMBERSHIP: c_int = 20;
pub static IPV6_DROP_MEMBERSHIP: c_int = 21;
pub static TCP_NODELAY: c_int = 1; pub static TCP_NODELAY: c_int = 1;
pub static SOL_SOCKET: c_int = 1; pub static SOL_SOCKET: c_int = 1;
pub static SO_KEEPALIVE: c_int = 9; pub static SO_KEEPALIVE: c_int = 9;
pub static SO_BROADCAST: c_int = 6;
} }
#[cfg(target_arch = "x86")] #[cfg(target_arch = "x86")]
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
@ -2584,11 +2640,21 @@ pub mod consts {
pub static SOCK_STREAM: c_int = 1; pub static SOCK_STREAM: c_int = 1;
pub static SOCK_DGRAM: c_int = 2; pub static SOCK_DGRAM: c_int = 2;
pub static IPPROTO_TCP: c_int = 6; pub static IPPROTO_TCP: c_int = 6;
pub static IPPROTO_IP: c_int = 0;
pub static IPPROTO_IPV6: c_int = 41;
pub static IP_MULTICAST_TTL: c_int = 10;
pub static IP_MULTICAST_LOOP: c_int = 11;
pub static IP_TTL: c_int = 4;
pub static IP_ADD_MEMBERSHIP: c_int = 12;
pub static IP_DROP_MEMBERSHIP: c_int = 13;
pub static IPV6_ADD_MEMBERSHIP: c_int = 12;
pub static IPV6_DROP_MEMBERSHIP: c_int = 13;
pub static TCP_NODELAY: c_int = 1; pub static TCP_NODELAY: c_int = 1;
pub static TCP_KEEPIDLE: c_int = 256; pub static TCP_KEEPIDLE: c_int = 256;
pub static SOL_SOCKET: c_int = 0xffff; pub static SOL_SOCKET: c_int = 0xffff;
pub static SO_KEEPALIVE: c_int = 0x0008; pub static SO_KEEPALIVE: c_int = 0x0008;
pub static SO_BROADCAST: c_int = 0x0020;
} }
pub mod extra { pub mod extra {
use libc::types::os::arch::c95::c_int; use libc::types::os::arch::c95::c_int;
@ -2949,11 +3015,21 @@ pub mod consts {
pub static SOCK_STREAM: c_int = 1; pub static SOCK_STREAM: c_int = 1;
pub static SOCK_DGRAM: c_int = 2; pub static SOCK_DGRAM: c_int = 2;
pub static IPPROTO_TCP: c_int = 6; pub static IPPROTO_TCP: c_int = 6;
pub static IPPROTO_IP: c_int = 0;
pub static IPPROTO_IPV6: c_int = 41;
pub static IP_MULTICAST_TTL: c_int = 10;
pub static IP_MULTICAST_LOOP: c_int = 11;
pub static IP_TTL: c_int = 4;
pub static IP_ADD_MEMBERSHIP: c_int = 12;
pub static IP_DROP_MEMBERSHIP: c_int = 13;
pub static IPV6_ADD_MEMBERSHIP: c_int = 12;
pub static IPV6_DROP_MEMBERSHIP: c_int = 13;
pub static TCP_NODELAY: c_int = 0x01; pub static TCP_NODELAY: c_int = 0x01;
pub static TCP_KEEPALIVE: c_int = 0x10; pub static TCP_KEEPALIVE: c_int = 0x10;
pub static SOL_SOCKET: c_int = 0xffff; pub static SOL_SOCKET: c_int = 0xffff;
pub static SO_KEEPALIVE: c_int = 0x0008; pub static SO_KEEPALIVE: c_int = 0x0008;
pub static SO_BROADCAST: c_int = 0x0020;
} }
pub mod extra { pub mod extra {
use libc::types::os::arch::c95::c_int; use libc::types::os::arch::c95::c_int;
@ -3660,6 +3736,12 @@ pub mod funcs {
flags: c_int) -> ssize_t; flags: c_int) -> ssize_t;
pub fn send(socket: c_int, buf: *mut c_void, len: size_t, pub fn send(socket: c_int, buf: *mut c_void, len: size_t,
flags: c_int) -> ssize_t; flags: c_int) -> ssize_t;
pub fn recvfrom(socket: c_int, buf: *mut c_void, len: size_t,
flags: c_int, addr: *mut sockaddr,
addrlen: *mut socklen_t) -> ssize_t;
pub fn sendto(socket: c_int, buf: *c_void, len: size_t,
flags: c_int, addr: *sockaddr,
addrlen: socklen_t) -> ssize_t;
} }
} }
@ -3668,6 +3750,7 @@ pub mod funcs {
use libc::types::common::c95::{c_void}; use libc::types::common::c95::{c_void};
use libc::types::os::common::bsd44::{socklen_t, sockaddr, SOCKET}; use libc::types::os::common::bsd44::{socklen_t, sockaddr, SOCKET};
use libc::types::os::arch::c95::c_int; use libc::types::os::arch::c95::c_int;
use libc::types::os::arch::posix88::ssize_t;
extern "system" { extern "system" {
pub fn socket(domain: c_int, ty: c_int, protocol: c_int) -> SOCKET; pub fn socket(domain: c_int, ty: c_int, protocol: c_int) -> SOCKET;
@ -3689,6 +3772,12 @@ pub mod funcs {
flags: c_int) -> c_int; flags: c_int) -> c_int;
pub fn send(socket: SOCKET, buf: *mut c_void, len: c_int, pub fn send(socket: SOCKET, buf: *mut c_void, len: c_int,
flags: c_int) -> c_int; flags: c_int) -> c_int;
pub fn recvfrom(socket: SOCKET, buf: *mut c_void, len: c_int,
flags: c_int, addr: *mut sockaddr,
addrlen: *mut c_int) -> ssize_t;
pub fn sendto(socket: SOCKET, buf: *c_void, len: c_int,
flags: c_int, addr: *sockaddr,
addrlen: c_int) -> c_int;
} }
} }