#![allow(bad_style, dead_code)]
use std::io;
use std::mem;
use std::net::{TcpStream, TcpListener, UdpSocket, Ipv4Addr, Ipv6Addr};
use std::net::ToSocketAddrs;
use {TcpBuilder, UdpBuilder, FromInner};
use sys;
use sys::c;
use socket;
cfg_if! {
if #[cfg(any(target_os = "dragonfly",
target_os = "freebsd",
target_os = "ios",
target_os = "macos",
target_os = "netbsd",
target_os = "openbsd",
target_os = "solaris",
target_env = "uclibc"))] {
use libc::IPV6_JOIN_GROUP as IPV6_ADD_MEMBERSHIP;
use libc::IPV6_LEAVE_GROUP as IPV6_DROP_MEMBERSHIP;
} else {
}
}
use std::time::Duration;
#[cfg(any(unix, target_os = "redox"))] use libc::*;
#[cfg(any(unix, target_os = "redox"))] use std::os::unix::prelude::*;
#[cfg(target_os = "redox")] pub type Socket = usize;
#[cfg(unix)] pub type Socket = c_int;
#[cfg(windows)] pub type Socket = SOCKET;
#[cfg(windows)] use std::os::windows::prelude::*;
#[cfg(windows)] use sys::c::*;
#[cfg(windows)] const SIO_KEEPALIVE_VALS: DWORD = 0x98000004;
#[cfg(windows)]
#[repr(C)]
struct tcp_keepalive {
onoff: c_ulong,
keepalivetime: c_ulong,
keepaliveinterval: c_ulong,
}
#[cfg(target_os = "redox")] fn v(opt: c_int) -> c_int { opt }
#[cfg(unix)] fn v(opt: c_int) -> c_int { opt }
#[cfg(windows)] fn v(opt: IPPROTO) -> c_int { opt as c_int }
pub fn set_opt<T: Copy>(sock: Socket, opt: c_int, val: c_int,
payload: T) -> io::Result<()> {
unsafe {
let payload = &payload as *const T as *const c_void;
#[cfg(target_os = "redox")]
let sock = sock as c_int;
try!(::cvt(setsockopt(sock, opt, val, payload as *const _,
mem::size_of::<T>() as socklen_t)));
Ok(())
}
}
pub fn get_opt<T: Copy>(sock: Socket, opt: c_int, val: c_int) -> io::Result<T> {
unsafe {
let mut slot: T = mem::zeroed();
let mut len = mem::size_of::<T>() as socklen_t;
#[cfg(target_os = "redox")]
let sock = sock as c_int;
try!(::cvt(getsockopt(sock, opt, val,
&mut slot as *mut _ as *mut _,
&mut len)));
assert_eq!(len as usize, mem::size_of::<T>());
Ok(slot)
}
}
pub trait TcpStreamExt {
fn set_nodelay(&self, nodelay: bool) -> io::Result<()>;
fn nodelay(&self) -> io::Result<bool>;
fn set_recv_buffer_size(&self, size: usize) -> io::Result<()>;
fn recv_buffer_size(&self) -> io::Result<usize>;
fn set_send_buffer_size(&self, size: usize) -> io::Result<()>;
fn send_buffer_size(&self) -> io::Result<usize>;
fn set_keepalive_ms(&self, keepalive: Option<u32>) -> io::Result<()>;
fn keepalive_ms(&self) -> io::Result<Option<u32>>;
fn set_keepalive(&self, keepalive: Option<Duration>) -> io::Result<()>;
fn keepalive(&self) -> io::Result<Option<Duration>>;
fn set_read_timeout_ms(&self, val: Option<u32>) -> io::Result<()>;
fn set_read_timeout(&self, val: Option<Duration>) -> io::Result<()>;
fn read_timeout_ms(&self) -> io::Result<Option<u32>>;
fn read_timeout(&self) -> io::Result<Option<Duration>>;
fn set_write_timeout_ms(&self, val: Option<u32>) -> io::Result<()>;
fn set_write_timeout(&self, val: Option<Duration>) -> io::Result<()>;
fn write_timeout_ms(&self) -> io::Result<Option<u32>>;
fn write_timeout(&self) -> io::Result<Option<Duration>>;
fn set_ttl(&self, ttl: u32) -> io::Result<()>;
fn ttl(&self) -> io::Result<u32>;
fn set_only_v6(&self, only_v6: bool) -> io::Result<()>;
fn only_v6(&self) -> io::Result<bool>;
fn connect<T: ToSocketAddrs>(&self, addr: T) -> io::Result<()>;
fn take_error(&self) -> io::Result<Option<io::Error>>;
fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()>;
fn set_linger(&self, dur: Option<Duration>) -> io::Result<()>;
fn linger(&self) -> io::Result<Option<Duration>>;
}
pub trait TcpListenerExt {
fn set_ttl(&self, ttl: u32) -> io::Result<()>;
fn ttl(&self) -> io::Result<u32>;
fn set_only_v6(&self, only_v6: bool) -> io::Result<()>;
fn only_v6(&self) -> io::Result<bool>;
fn take_error(&self) -> io::Result<Option<io::Error>>;
fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()>;
fn set_linger(&self, dur: Option<Duration>) -> io::Result<()>;
fn linger(&self) -> io::Result<Option<Duration>>;
}
pub trait UdpSocketExt {
fn set_recv_buffer_size(&self, size: usize) -> io::Result<()>;
fn recv_buffer_size(&self) -> io::Result<usize>;
fn set_send_buffer_size(&self, size: usize) -> io::Result<()>;
fn send_buffer_size(&self) -> io::Result<usize>;
fn set_broadcast(&self, broadcast: bool) -> io::Result<()>;
fn broadcast(&self) -> io::Result<bool>;
fn set_multicast_loop_v4(&self, multicast_loop_v4: bool) -> io::Result<()>;
fn multicast_loop_v4(&self) -> io::Result<bool>;
fn set_multicast_ttl_v4(&self, multicast_ttl_v4: u32) -> io::Result<()>;
fn multicast_ttl_v4(&self) -> io::Result<u32>;
fn set_multicast_hops_v6(&self, hops: u32) -> io::Result<()>;
fn multicast_hops_v6(&self) -> io::Result<u32>;
fn set_multicast_loop_v6(&self, multicast_loop_v6: bool) -> io::Result<()>;
fn multicast_loop_v6(&self) -> io::Result<bool>;
fn set_multicast_if_v4(&self, interface: &Ipv4Addr) -> io::Result<()>;
fn multicast_if_v4(&self) -> io::Result<Ipv4Addr>;
fn set_multicast_if_v6(&self, interface: u32) -> io::Result<()>;
fn multicast_if_v6(&self) -> io::Result<u32>;
fn set_ttl(&self, ttl: u32) -> io::Result<()>;
fn ttl(&self) -> io::Result<u32>;
fn set_unicast_hops_v6(&self, ttl: u32) -> io::Result<()>;
fn unicast_hops_v6(&self) -> io::Result<u32>;
fn set_only_v6(&self, only_v6: bool) -> io::Result<()>;
fn only_v6(&self) -> io::Result<bool>;
fn join_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr)
-> io::Result<()>;
fn join_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32)
-> io::Result<()>;
fn leave_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr)
-> io::Result<()>;
fn leave_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32)
-> io::Result<()>;
fn set_read_timeout_ms(&self, val: Option<u32>) -> io::Result<()>;
fn set_read_timeout(&self, val: Option<Duration>) -> io::Result<()>;
fn read_timeout_ms(&self) -> io::Result<Option<u32>>;
fn read_timeout(&self) -> io::Result<Option<Duration>>;
fn set_write_timeout_ms(&self, val: Option<u32>) -> io::Result<()>;
fn set_write_timeout(&self, val: Option<Duration>) -> io::Result<()>;
fn write_timeout_ms(&self) -> io::Result<Option<u32>>;
fn write_timeout(&self) -> io::Result<Option<Duration>>;
fn take_error(&self) -> io::Result<Option<io::Error>>;
fn connect<A: ToSocketAddrs>(&self, addr: A) -> io::Result<()>;
fn send(&self, buf: &[u8]) -> io::Result<usize>;
fn recv(&self, buf: &mut [u8]) -> io::Result<usize>;
fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()>;
}
#[doc(hidden)]
pub trait AsSock {
fn as_sock(&self) -> Socket;
}
#[cfg(target_os = "redox")]
impl<T: AsRawFd> AsSock for T {
fn as_sock(&self) -> Socket { self.as_raw_fd() }
}
#[cfg(unix)]
impl<T: AsRawFd> AsSock for T {
fn as_sock(&self) -> Socket { self.as_raw_fd() }
}
#[cfg(windows)]
impl<T: AsRawSocket> AsSock for T {
fn as_sock(&self) -> Socket { self.as_raw_socket() as Socket }
}
cfg_if! {
if #[cfg(any(target_os = "macos", target_os = "ios"))] {
use libc::TCP_KEEPALIVE as KEEPALIVE_OPTION;
} else if #[cfg(any(target_os = "openbsd", target_os = "netbsd"))] {
use libc::SO_KEEPALIVE as KEEPALIVE_OPTION;
} else if #[cfg(unix)] {
use libc::TCP_KEEPIDLE as KEEPALIVE_OPTION;
} else if #[cfg(target_os = "redox")] {
use libc::TCP_KEEPIDLE as KEEPALIVE_OPTION;
} else {
}
}
impl TcpStreamExt for TcpStream {
fn set_recv_buffer_size(&self, size: usize) -> io::Result<()> {
set_opt(self.as_sock(), SOL_SOCKET, SO_RCVBUF, size as c_int)
}
fn recv_buffer_size(&self) -> io::Result<usize> {
get_opt(self.as_sock(), SOL_SOCKET, SO_RCVBUF).map(int2usize)
}
fn set_send_buffer_size(&self, size: usize) -> io::Result<()> {
set_opt(self.as_sock(), SOL_SOCKET, SO_SNDBUF, size as c_int)
}
fn send_buffer_size(&self) -> io::Result<usize> {
get_opt(self.as_sock(), SOL_SOCKET, SO_SNDBUF).map(int2usize)
}
fn set_nodelay(&self, nodelay: bool) -> io::Result<()> {
set_opt(self.as_sock(), v(IPPROTO_TCP), TCP_NODELAY,
nodelay as c_int)
}
fn nodelay(&self) -> io::Result<bool> {
get_opt(self.as_sock(), v(IPPROTO_TCP), TCP_NODELAY)
.map(int2bool)
}
fn set_keepalive(&self, keepalive: Option<Duration>) -> io::Result<()> {
self.set_keepalive_ms(keepalive.map(dur2ms))
}
fn keepalive(&self) -> io::Result<Option<Duration>> {
self.keepalive_ms().map(|o| o.map(ms2dur))
}
#[cfg(target_os = "redox")]
fn set_keepalive_ms(&self, keepalive: Option<u32>) -> io::Result<()> {
try!(set_opt(self.as_sock(), SOL_SOCKET, SO_KEEPALIVE,
keepalive.is_some() as c_int));
if let Some(dur) = keepalive {
try!(set_opt(self.as_sock(), v(IPPROTO_TCP), KEEPALIVE_OPTION,
(dur / 1000) as c_int));
}
Ok(())
}
#[cfg(target_os = "redox")]
fn keepalive_ms(&self) -> io::Result<Option<u32>> {
let keepalive = try!(get_opt::<c_int>(self.as_sock(), SOL_SOCKET,
SO_KEEPALIVE));
if keepalive == 0 {
return Ok(None)
}
let secs = try!(get_opt::<c_int>(self.as_sock(), v(IPPROTO_TCP),
KEEPALIVE_OPTION));
Ok(Some((secs as u32) * 1000))
}
#[cfg(unix)]
fn set_keepalive_ms(&self, keepalive: Option<u32>) -> io::Result<()> {
try!(set_opt(self.as_sock(), SOL_SOCKET, SO_KEEPALIVE,
keepalive.is_some() as c_int));
if let Some(dur) = keepalive {
try!(set_opt(self.as_sock(), v(IPPROTO_TCP), KEEPALIVE_OPTION,
(dur / 1000) as c_int));
}
Ok(())
}
#[cfg(unix)]
fn keepalive_ms(&self) -> io::Result<Option<u32>> {
let keepalive = try!(get_opt::<c_int>(self.as_sock(), SOL_SOCKET,
SO_KEEPALIVE));
if keepalive == 0 {
return Ok(None)
}
let secs = try!(get_opt::<c_int>(self.as_sock(), v(IPPROTO_TCP),
KEEPALIVE_OPTION));
Ok(Some((secs as u32) * 1000))
}
#[cfg(windows)]
fn set_keepalive_ms(&self, keepalive: Option<u32>) -> io::Result<()> {
let ms = keepalive.unwrap_or(INFINITE);
let ka = tcp_keepalive {
onoff: keepalive.is_some() as c_ulong,
keepalivetime: ms as c_ulong,
keepaliveinterval: ms as c_ulong,
};
unsafe {
::cvt_win(WSAIoctl(self.as_sock(),
SIO_KEEPALIVE_VALS,
&ka as *const _ as *mut _,
mem::size_of_val(&ka) as DWORD,
0 as *mut _,
0,
0 as *mut _,
0 as *mut _,
None)).map(|_| ())
}
}
#[cfg(windows)]
fn keepalive_ms(&self) -> io::Result<Option<u32>> {
let mut ka = tcp_keepalive {
onoff: 0,
keepalivetime: 0,
keepaliveinterval: 0,
};
unsafe {
try!(::cvt_win(WSAIoctl(self.as_sock(),
SIO_KEEPALIVE_VALS,
0 as *mut _,
0,
&mut ka as *mut _ as *mut _,
mem::size_of_val(&ka) as DWORD,
0 as *mut _,
0 as *mut _,
None)));
}
Ok({
if ka.onoff == 0 {
None
} else {
timeout2ms(ka.keepaliveinterval as DWORD)
}
})
}
fn set_read_timeout_ms(&self, dur: Option<u32>) -> io::Result<()> {
set_opt(self.as_sock(), SOL_SOCKET, SO_RCVTIMEO,
ms2timeout(dur))
}
fn read_timeout_ms(&self) -> io::Result<Option<u32>> {
get_opt(self.as_sock(), SOL_SOCKET, SO_RCVTIMEO)
.map(timeout2ms)
}
fn set_write_timeout_ms(&self, dur: Option<u32>) -> io::Result<()> {
set_opt(self.as_sock(), SOL_SOCKET, SO_SNDTIMEO,
ms2timeout(dur))
}
fn write_timeout_ms(&self) -> io::Result<Option<u32>> {
get_opt(self.as_sock(), SOL_SOCKET, SO_SNDTIMEO)
.map(timeout2ms)
}
fn set_read_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
self.set_read_timeout_ms(dur.map(dur2ms))
}
fn read_timeout(&self) -> io::Result<Option<Duration>> {
self.read_timeout_ms().map(|o| o.map(ms2dur))
}
fn set_write_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
self.set_write_timeout_ms(dur.map(dur2ms))
}
fn write_timeout(&self) -> io::Result<Option<Duration>> {
self.write_timeout_ms().map(|o| o.map(ms2dur))
}
fn set_ttl(&self, ttl: u32) -> io::Result<()> {
set_opt(self.as_sock(), IPPROTO_IP, IP_TTL, ttl as c_int)
}
fn ttl(&self) -> io::Result<u32> {
get_opt::<c_int>(self.as_sock(), IPPROTO_IP, IP_TTL)
.map(|b| b as u32)
}
fn set_only_v6(&self, only_v6: bool) -> io::Result<()> {
set_opt(self.as_sock(), v(IPPROTO_IPV6), IPV6_V6ONLY, only_v6 as c_int)
}
fn only_v6(&self) -> io::Result<bool> {
get_opt(self.as_sock(), v(IPPROTO_IPV6), IPV6_V6ONLY).map(int2bool)
}
fn connect<T: ToSocketAddrs>(&self, addr: T) -> io::Result<()> {
do_connect(self.as_sock(), addr)
}
fn take_error(&self) -> io::Result<Option<io::Error>> {
get_opt(self.as_sock(), SOL_SOCKET, SO_ERROR).map(int2err)
}
fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
set_nonblocking(self.as_sock(), nonblocking)
}
fn set_linger(&self, dur: Option<Duration>) -> io::Result<()> {
set_opt(self.as_sock(), SOL_SOCKET, SO_LINGER, dur2linger(dur))
}
fn linger(&self) -> io::Result<Option<Duration>> {
get_opt(self.as_sock(), SOL_SOCKET, SO_LINGER).map(linger2dur)
}
}
#[cfg(any(target_os = "redox", unix))]
fn ms2timeout(dur: Option<u32>) -> timeval {
match dur {
Some(d) => timeval {
tv_sec: (d / 1000) as time_t,
tv_usec: (d % 1000) as suseconds_t,
},
None => timeval { tv_sec: 0, tv_usec: 0 },
}
}
#[cfg(any(target_os = "redox", unix))]
fn timeout2ms(dur: timeval) -> Option<u32> {
if dur.tv_sec == 0 && dur.tv_usec == 0 {
None
} else {
Some(dur.tv_sec as u32 * 1000 + dur.tv_usec as u32 / 1000)
}
}
#[cfg(windows)]
fn ms2timeout(dur: Option<u32>) -> DWORD {
dur.unwrap_or(0)
}
#[cfg(windows)]
fn timeout2ms(dur: DWORD) -> Option<u32> {
if dur == 0 {
None
} else {
Some(dur)
}
}
fn linger2dur(linger_opt: linger) -> Option<Duration> {
if linger_opt.l_onoff == 0 {
None
}
else {
Some(Duration::from_secs(linger_opt.l_linger as u64))
}
}
#[cfg(windows)]
fn dur2linger(dur: Option<Duration>) -> linger {
match dur {
Some(d) => {
linger {
l_onoff: 1,
l_linger: d.as_secs() as u16,
}
},
None => linger { l_onoff: 0, l_linger: 0 },
}
}
#[cfg(any(target_os = "redox", unix))]
fn dur2linger(dur: Option<Duration>) -> linger {
match dur {
Some(d) => {
linger {
l_onoff: 1,
l_linger: d.as_secs() as c_int,
}
},
None => linger { l_onoff: 0, l_linger: 0 },
}
}
fn ms2dur(ms: u32) -> Duration {
Duration::new((ms as u64) / 1000, (ms as u32) % 1000 * 1_000_000)
}
fn dur2ms(dur: Duration) -> u32 {
(dur.as_secs() as u32 * 1000) + (dur.subsec_nanos() / 1_000_000)
}
pub fn int2bool(n: c_int) -> bool {
if n == 0 {false} else {true}
}
pub fn int2usize(n: c_int) -> usize {
n as usize
}
pub fn int2err(n: c_int) -> Option<io::Error> {
if n == 0 {
None
} else {
Some(io::Error::from_raw_os_error(n as i32))
}
}
impl UdpSocketExt for UdpSocket {
fn set_recv_buffer_size(&self, size: usize) -> io::Result<()> {
set_opt(self.as_sock(), SOL_SOCKET, SO_RCVBUF, size as c_int)
}
fn recv_buffer_size(&self) -> io::Result<usize> {
get_opt(self.as_sock(), SOL_SOCKET, SO_RCVBUF).map(int2usize)
}
fn set_send_buffer_size(&self, size: usize) -> io::Result<()> {
set_opt(self.as_sock(), SOL_SOCKET, SO_SNDBUF, size as c_int)
}
fn send_buffer_size(&self) -> io::Result<usize> {
get_opt(self.as_sock(), SOL_SOCKET, SO_SNDBUF).map(int2usize)
}
fn set_broadcast(&self, broadcast: bool) -> io::Result<()> {
set_opt(self.as_sock(), SOL_SOCKET, SO_BROADCAST,
broadcast as c_int)
}
fn broadcast(&self) -> io::Result<bool> {
get_opt(self.as_sock(), SOL_SOCKET, SO_BROADCAST)
.map(int2bool)
}
fn set_multicast_loop_v4(&self, multicast_loop_v4: bool) -> io::Result<()> {
set_opt(self.as_sock(), IPPROTO_IP, IP_MULTICAST_LOOP,
multicast_loop_v4 as c_int)
}
fn multicast_loop_v4(&self) -> io::Result<bool> {
get_opt(self.as_sock(), IPPROTO_IP, IP_MULTICAST_LOOP)
.map(int2bool)
}
fn set_multicast_ttl_v4(&self, multicast_ttl_v4: u32) -> io::Result<()> {
set_opt(self.as_sock(), IPPROTO_IP, IP_MULTICAST_TTL,
multicast_ttl_v4 as c_int)
}
fn multicast_ttl_v4(&self) -> io::Result<u32> {
get_opt::<c_int>(self.as_sock(), IPPROTO_IP, IP_MULTICAST_TTL)
.map(|b| b as u32)
}
fn set_multicast_hops_v6(&self, _hops: u32) -> io::Result<()> {
#[cfg(target_os = "redox")]
return Err(io::Error::new(io::ErrorKind::Other, "Not implemented yet"));
#[cfg(not(target_os = "redox"))]
set_opt(self.as_sock(), v(IPPROTO_IPV6), IPV6_MULTICAST_HOPS,
_hops as c_int)
}
fn multicast_hops_v6(&self) -> io::Result<u32> {
#[cfg(target_os = "redox")]
return Err(io::Error::new(io::ErrorKind::Other, "Not implemented yet"));
#[cfg(not(target_os = "redox"))]
get_opt::<c_int>(self.as_sock(), v(IPPROTO_IPV6), IPV6_MULTICAST_HOPS)
.map(|b| b as u32)
}
fn set_multicast_loop_v6(&self, multicast_loop_v6: bool) -> io::Result<()> {
set_opt(self.as_sock(), v(IPPROTO_IPV6), IPV6_MULTICAST_LOOP,
multicast_loop_v6 as c_int)
}
fn multicast_loop_v6(&self) -> io::Result<bool> {
get_opt(self.as_sock(), v(IPPROTO_IPV6), IPV6_MULTICAST_LOOP)
.map(int2bool)
}
fn set_multicast_if_v4(&self, _interface: &Ipv4Addr) -> io::Result<()> {
#[cfg(target_os = "redox")]
return Err(io::Error::new(io::ErrorKind::Other, "Not implemented yet"));
#[cfg(not(target_os = "redox"))]
set_opt(self.as_sock(), IPPROTO_IP, IP_MULTICAST_IF, ip2in_addr(_interface))
}
fn multicast_if_v4(&self) -> io::Result<Ipv4Addr> {
#[cfg(target_os = "redox")]
return Err(io::Error::new(io::ErrorKind::Other, "Not implemented yet"));
#[cfg(not(target_os = "redox"))]
get_opt(self.as_sock(), IPPROTO_IP, IP_MULTICAST_IF).map(in_addr2ip)
}
fn set_multicast_if_v6(&self, _interface: u32) -> io::Result<()> {
#[cfg(target_os = "redox")]
return Err(io::Error::new(io::ErrorKind::Other, "Not implemented yet"));
#[cfg(not(target_os = "redox"))]
set_opt(self.as_sock(), v(IPPROTO_IPV6), IPV6_MULTICAST_IF, to_ipv6mr_interface(_interface))
}
fn multicast_if_v6(&self) -> io::Result<u32> {
#[cfg(target_os = "redox")]
return Err(io::Error::new(io::ErrorKind::Other, "Not implemented yet"));
#[cfg(not(target_os = "redox"))]
get_opt::<c_int>(self.as_sock(), v(IPPROTO_IPV6), IPV6_MULTICAST_IF).map(|b| b as u32)
}
fn set_ttl(&self, ttl: u32) -> io::Result<()> {
set_opt(self.as_sock(), IPPROTO_IP, IP_TTL, ttl as c_int)
}
fn ttl(&self) -> io::Result<u32> {
get_opt::<c_int>(self.as_sock(), IPPROTO_IP, IP_TTL)
.map(|b| b as u32)
}
fn set_unicast_hops_v6(&self, _ttl: u32) -> io::Result<()> {
#[cfg(target_os = "redox")]
return Err(io::Error::new(io::ErrorKind::Other, "Not implemented yet"));
#[cfg(not(target_os = "redox"))]
set_opt(self.as_sock(), v(IPPROTO_IPV6), IPV6_UNICAST_HOPS, _ttl as c_int)
}
fn unicast_hops_v6(&self) -> io::Result<u32> {
#[cfg(target_os = "redox")]
return Err(io::Error::new(io::ErrorKind::Other, "Not implemented yet"));
#[cfg(not(target_os = "redox"))]
get_opt::<c_int>(self.as_sock(), IPPROTO_IP, IPV6_UNICAST_HOPS)
.map(|b| b as u32)
}
fn set_only_v6(&self, only_v6: bool) -> io::Result<()> {
set_opt(self.as_sock(), v(IPPROTO_IPV6), IPV6_V6ONLY, only_v6 as c_int)
}
fn only_v6(&self) -> io::Result<bool> {
get_opt(self.as_sock(), v(IPPROTO_IPV6), IPV6_V6ONLY).map(int2bool)
}
fn join_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr)
-> io::Result<()> {
let mreq = ip_mreq {
imr_multiaddr: ip2in_addr(multiaddr),
imr_interface: ip2in_addr(interface),
};
set_opt(self.as_sock(), IPPROTO_IP, IP_ADD_MEMBERSHIP, mreq)
}
fn join_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32)
-> io::Result<()> {
let mreq = ipv6_mreq {
ipv6mr_multiaddr: ip2in6_addr(multiaddr),
ipv6mr_interface: to_ipv6mr_interface(interface),
};
set_opt(self.as_sock(), v(IPPROTO_IPV6), IPV6_ADD_MEMBERSHIP,
mreq)
}
fn leave_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr)
-> io::Result<()> {
let mreq = ip_mreq {
imr_multiaddr: ip2in_addr(multiaddr),
imr_interface: ip2in_addr(interface),
};
set_opt(self.as_sock(), IPPROTO_IP, IP_DROP_MEMBERSHIP, mreq)
}
fn leave_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32)
-> io::Result<()> {
let mreq = ipv6_mreq {
ipv6mr_multiaddr: ip2in6_addr(multiaddr),
ipv6mr_interface: to_ipv6mr_interface(interface),
};
set_opt(self.as_sock(), v(IPPROTO_IPV6), IPV6_DROP_MEMBERSHIP,
mreq)
}
fn set_read_timeout_ms(&self, dur: Option<u32>) -> io::Result<()> {
set_opt(self.as_sock(), SOL_SOCKET, SO_RCVTIMEO,
ms2timeout(dur))
}
fn read_timeout_ms(&self) -> io::Result<Option<u32>> {
get_opt(self.as_sock(), SOL_SOCKET, SO_RCVTIMEO)
.map(timeout2ms)
}
fn set_write_timeout_ms(&self, dur: Option<u32>) -> io::Result<()> {
set_opt(self.as_sock(), SOL_SOCKET, SO_SNDTIMEO,
ms2timeout(dur))
}
fn write_timeout_ms(&self) -> io::Result<Option<u32>> {
get_opt(self.as_sock(), SOL_SOCKET, SO_SNDTIMEO)
.map(timeout2ms)
}
fn set_read_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
self.set_read_timeout_ms(dur.map(dur2ms))
}
fn read_timeout(&self) -> io::Result<Option<Duration>> {
self.read_timeout_ms().map(|o| o.map(ms2dur))
}
fn set_write_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
self.set_write_timeout_ms(dur.map(dur2ms))
}
fn write_timeout(&self) -> io::Result<Option<Duration>> {
self.write_timeout_ms().map(|o| o.map(ms2dur))
}
fn take_error(&self) -> io::Result<Option<io::Error>> {
get_opt(self.as_sock(), SOL_SOCKET, SO_ERROR).map(int2err)
}
fn connect<A: ToSocketAddrs>(&self, addr: A) -> io::Result<()> {
do_connect(self.as_sock(), addr)
}
#[cfg(target_os = "redox")]
fn send(&self, buf: &[u8]) -> io::Result<usize> {
unsafe {
::cvt(write(self.as_sock() as c_int, buf.as_ptr() as *const _, buf.len())).map(|n| n as usize)
}
}
#[cfg(unix)]
fn send(&self, buf: &[u8]) -> io::Result<usize> {
unsafe {
::cvt(send(self.as_sock() as c_int, buf.as_ptr() as *const _, buf.len(), 0)).map(|n| n as usize)
}
}
#[cfg(windows)]
fn send(&self, buf: &[u8]) -> io::Result<usize> {
let len = ::std::cmp::min(buf.len(), c_int::max_value() as usize);
let buf = &buf[..len];
unsafe {
::cvt(send(self.as_sock(), buf.as_ptr() as *const _, len as c_int, 0))
.map(|n| n as usize)
}
}
#[cfg(target_os = "redox")]
fn recv(&self, buf: &mut [u8]) -> io::Result<usize> {
unsafe {
::cvt(read(self.as_sock() as c_int, buf.as_mut_ptr() as *mut _, buf.len()))
.map(|n| n as usize)
}
}
#[cfg(unix)]
fn recv(&self, buf: &mut [u8]) -> io::Result<usize> {
unsafe {
::cvt(recv(self.as_sock(), buf.as_mut_ptr() as *mut _, buf.len(), 0))
.map(|n| n as usize)
}
}
#[cfg(windows)]
fn recv(&self, buf: &mut [u8]) -> io::Result<usize> {
let len = ::std::cmp::min(buf.len(), c_int::max_value() as usize);
let buf = &mut buf[..len];
unsafe {
::cvt(recv(self.as_sock(), buf.as_mut_ptr() as *mut _, buf.len() as c_int, 0))
.map(|n| n as usize)
}
}
fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
set_nonblocking(self.as_sock(), nonblocking)
}
}
fn do_connect<A: ToSocketAddrs>(sock: Socket, addr: A) -> io::Result<()> {
let err = io::Error::new(io::ErrorKind::Other,
"no socket addresses resolved");
let addrs = try!(addr.to_socket_addrs());
let sys = sys::Socket::from_inner(sock);
let sock = socket::Socket::from_inner(sys);
let ret = addrs.fold(Err(err), |prev, addr| {
prev.or_else(|_| sock.connect(&addr))
});
mem::forget(sock);
return ret
}
#[cfg(target_os = "redox")]
fn set_nonblocking(sock: Socket, nonblocking: bool) -> io::Result<()> {
let mut flags = ::cvt(unsafe {
fcntl(sock as c_int, F_GETFL)
})?;
if nonblocking {
flags |= O_NONBLOCK;
} else {
flags &= !O_NONBLOCK;
}
::cvt(unsafe {
fcntl(sock as c_int, F_SETFL, flags)
}).and(Ok(()))
}
#[cfg(unix)]
fn set_nonblocking(sock: Socket, nonblocking: bool) -> io::Result<()> {
let mut nonblocking = nonblocking as c_ulong;
::cvt(unsafe {
ioctl(sock, FIONBIO, &mut nonblocking)
}).map(|_| ())
}
#[cfg(windows)]
fn set_nonblocking(sock: Socket, nonblocking: bool) -> io::Result<()> {
let mut nonblocking = nonblocking as c_ulong;
::cvt(unsafe {
ioctlsocket(sock, FIONBIO as c_int, &mut nonblocking)
}).map(|_| ())
}
#[cfg(target_os = "redox")]
fn ip2in_addr(ip: &Ipv4Addr) -> in_addr {
let oct = ip.octets();
in_addr {
s_addr: ::hton(((oct[0] as u32) << 24) |
((oct[1] as u32) << 16) |
((oct[2] as u32) << 8) |
((oct[3] as u32) << 0)),
}
}
#[cfg(unix)]
fn ip2in_addr(ip: &Ipv4Addr) -> in_addr {
let oct = ip.octets();
in_addr {
s_addr: ::hton(((oct[0] as u32) << 24) |
((oct[1] as u32) << 16) |
((oct[2] as u32) << 8) |
((oct[3] as u32) << 0)),
}
}
#[cfg(windows)]
fn ip2in_addr(ip: &Ipv4Addr) -> in_addr {
let oct = ip.octets();
unsafe {
let mut S_un: in_addr_S_un = mem::zeroed();
*S_un.S_addr_mut() = ::hton(((oct[0] as u32) << 24) |
((oct[1] as u32) << 16) |
((oct[2] as u32) << 8) |
((oct[3] as u32) << 0));
in_addr {
S_un: S_un,
}
}
}
fn in_addr2ip(ip: &in_addr) -> Ipv4Addr {
let h_addr = c::in_addr_to_u32(ip);
let a: u8 = (h_addr >> 24) as u8;
let b: u8 = (h_addr >> 16) as u8;
let c: u8 = (h_addr >> 8) as u8;
let d: u8 = (h_addr >> 0) as u8;
Ipv4Addr::new(a,b,c,d)
}
#[cfg(target_os = "android")]
fn to_ipv6mr_interface(value: u32) -> c_int {
value as c_int
}
#[cfg(not(target_os = "android"))]
fn to_ipv6mr_interface(value: u32) -> c_uint {
value as c_uint
}
fn ip2in6_addr(ip: &Ipv6Addr) -> in6_addr {
let mut ret: in6_addr = unsafe { mem::zeroed() };
let seg = ip.segments();
let bytes = [
(seg[0] >> 8) as u8,
(seg[0] >> 0) as u8,
(seg[1] >> 8) as u8,
(seg[1] >> 0) as u8,
(seg[2] >> 8) as u8,
(seg[2] >> 0) as u8,
(seg[3] >> 8) as u8,
(seg[3] >> 0) as u8,
(seg[4] >> 8) as u8,
(seg[4] >> 0) as u8,
(seg[5] >> 8) as u8,
(seg[5] >> 0) as u8,
(seg[6] >> 8) as u8,
(seg[6] >> 0) as u8,
(seg[7] >> 8) as u8,
(seg[7] >> 0) as u8,
];
#[cfg(windows)] unsafe { *ret.u.Byte_mut() = bytes; }
#[cfg(not(windows))] { ret.s6_addr = bytes; }
return ret
}
impl TcpListenerExt for TcpListener {
fn set_ttl(&self, ttl: u32) -> io::Result<()> {
set_opt(self.as_sock(), IPPROTO_IP, IP_TTL, ttl as c_int)
}
fn ttl(&self) -> io::Result<u32> {
get_opt::<c_int>(self.as_sock(), IPPROTO_IP, IP_TTL)
.map(|b| b as u32)
}
fn set_only_v6(&self, only_v6: bool) -> io::Result<()> {
set_opt(self.as_sock(), v(IPPROTO_IPV6), IPV6_V6ONLY, only_v6 as c_int)
}
fn only_v6(&self) -> io::Result<bool> {
get_opt(self.as_sock(), v(IPPROTO_IPV6), IPV6_V6ONLY).map(int2bool)
}
fn take_error(&self) -> io::Result<Option<io::Error>> {
get_opt(self.as_sock(), SOL_SOCKET, SO_ERROR).map(int2err)
}
fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
set_nonblocking(self.as_sock(), nonblocking)
}
fn set_linger(&self, dur: Option<Duration>) -> io::Result<()> {
set_opt(self.as_sock(), SOL_SOCKET, SO_LINGER, dur2linger(dur))
}
fn linger(&self) -> io::Result<Option<Duration>> {
get_opt(self.as_sock(), SOL_SOCKET, SO_LINGER).map(linger2dur)
}
}
impl TcpBuilder {
pub fn ttl(&self, ttl: u32) -> io::Result<&Self> {
set_opt(self.as_sock(), IPPROTO_IP, IP_TTL, ttl as c_int)
.map(|()| self)
}
pub fn only_v6(&self, only_v6: bool) -> io::Result<&Self> {
set_opt(self.as_sock(), v(IPPROTO_IPV6), IPV6_V6ONLY, only_v6 as c_int)
.map(|()| self)
}
pub fn reuse_address(&self, reuse: bool) -> io::Result<&Self> {
set_opt(self.as_sock(), SOL_SOCKET, SO_REUSEADDR,
reuse as c_int).map(|()| self)
}
pub fn get_reuse_address(&self) -> io::Result<bool> {
get_opt(self.as_sock(), SOL_SOCKET, SO_REUSEADDR).map(int2bool)
}
pub fn take_error(&self) -> io::Result<Option<io::Error>> {
get_opt(self.as_sock(), SOL_SOCKET, SO_ERROR).map(int2err)
}
fn set_linger(&self, dur: Option<Duration>) -> io::Result<()> {
set_opt(self.as_sock(), SOL_SOCKET, SO_LINGER, dur2linger(dur))
}
fn linger(&self) -> io::Result<Option<Duration>> {
get_opt(self.as_sock(), SOL_SOCKET, SO_LINGER).map(linger2dur)
}
}
impl UdpBuilder {
pub fn ttl(&self, ttl: u32) -> io::Result<&Self> {
set_opt(self.as_sock(), IPPROTO_IP, IP_TTL, ttl as c_int)
.map(|()| self)
}
pub fn only_v6(&self, only_v6: bool) -> io::Result<&Self> {
set_opt(self.as_sock(), v(IPPROTO_IPV6), IPV6_V6ONLY, only_v6 as c_int)
.map(|()| self)
}
pub fn reuse_address(&self, reuse: bool) -> io::Result<&Self> {
set_opt(self.as_sock(), SOL_SOCKET, SO_REUSEADDR,
reuse as c_int).map(|()| self)
}
pub fn get_reuse_address(&self) -> io::Result<bool> {
get_opt(self.as_sock(), SOL_SOCKET, SO_REUSEADDR).map(int2bool)
}
pub fn take_error(&self) -> io::Result<Option<io::Error>> {
get_opt(self.as_sock(), SOL_SOCKET, SO_ERROR).map(int2err)
}
}