From 5d6ba17f0308d3b8c96cd89f4c0663bae0f2b9f7 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sat, 27 Feb 2016 15:02:48 -0800 Subject: Add UDP functionality from net2 --- src/libstd/sys/common/net.rs | 138 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 135 insertions(+), 3 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/common/net.rs b/src/libstd/sys/common/net.rs index 0ac4056de8e..31d3be45372 100644 --- a/src/libstd/sys/common/net.rs +++ b/src/libstd/sys/common/net.rs @@ -17,7 +17,7 @@ use io::{self, Error, ErrorKind}; use libc::{c_int, c_char, c_void}; use mem; #[allow(deprecated)] -use net::{SocketAddr, Shutdown, IpAddr}; +use net::{SocketAddr, Shutdown, IpAddr, Ipv4Addr, Ipv6Addr}; use ptr; use str::from_utf8; use sys::net::{cvt, cvt_r, cvt_gai, Socket, init, wrlen_t}; @@ -40,8 +40,7 @@ pub fn setsockopt(sock: &Socket, opt: c_int, val: c_int, } pub fn getsockopt(sock: &Socket, opt: c_int, - val: c_int) -> io::Result { - unsafe { + val: c_int) -> io::Result { unsafe { let mut slot: T = mem::zeroed(); let mut len = mem::size_of::() as c::socklen_t; try!(cvt(c::getsockopt(*sock.as_inner(), opt, val, @@ -84,6 +83,16 @@ fn sockaddr_to_addr(storage: &c::sockaddr_storage, } } +#[cfg(target_os = "android")] +fn to_ipv6mr_interface(value: u32) -> c::c_int { + value as c::c_int +} + +#[cfg(not(target_os = "android"))] +fn to_ipv6mr_interface(value: u32) -> c::c_uint { + value as c::c_uint +} + //////////////////////////////////////////////////////////////////////////////// // get_host_addresses //////////////////////////////////////////////////////////////////////////////// @@ -480,6 +489,129 @@ impl UdpSocket { pub fn write_timeout(&self) -> io::Result> { self.inner.timeout(c::SO_SNDTIMEO) } + + pub fn set_broadcast(&self, broadcast: bool) -> io::Result<()> { + setsockopt(&self.inner, c::SOL_SOCKET, c::SO_BROADCAST, broadcast as c_int) + } + + pub fn broadcast(&self) -> io::Result { + let raw: c_int = try!(getsockopt(&self.inner, c::SOL_SOCKET, c::SO_BROADCAST)); + Ok(raw != 0) + } + + pub fn set_multicast_loop_v4(&self, multicast_loop_v4: bool) -> io::Result<()> { + setsockopt(&self.inner, c::IPPROTO_IP, c::IP_MULTICAST_LOOP, multicast_loop_v4 as c_int) + } + + pub fn multicast_loop_v4(&self) -> io::Result { + let raw: c_int = try!(getsockopt(&self.inner, c::IPPROTO_IP, c::IP_MULTICAST_LOOP)); + Ok(raw != 0) + } + + pub fn set_multicast_ttl_v4(&self, multicast_ttl_v4: u32) -> io::Result<()> { + setsockopt(&self.inner, c::IPPROTO_IP, c::IP_MULTICAST_TTL, multicast_ttl_v4 as c_int) + } + + pub fn multicast_ttl_v4(&self) -> io::Result { + let raw: c_int = try!(getsockopt(&self.inner, c::IPPROTO_IP, c::IP_MULTICAST_TTL)); + Ok(raw as u32) + } + + pub fn set_multicast_loop_v6(&self, multicast_loop_v6: bool) -> io::Result<()> { + setsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_MULTICAST_LOOP, multicast_loop_v6 as c_int) + } + + pub fn multicast_loop_v6(&self) -> io::Result { + let raw: c_int = try!(getsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_MULTICAST_LOOP)); + Ok(raw != 0) + } + + pub fn join_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) + -> io::Result<()> { + let mreq = c::ip_mreq { + imr_multiaddr: *multiaddr.as_inner(), + imr_interface: *interface.as_inner(), + }; + setsockopt(&self.inner, c::IPPROTO_IP, c::IP_ADD_MEMBERSHIP, mreq) + } + + pub fn join_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) + -> io::Result<()> { + let mreq = c::ipv6_mreq { + ipv6mr_multiaddr: *multiaddr.as_inner(), + ipv6mr_interface: to_ipv6mr_interface(interface), + }; + setsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_ADD_MEMBERSHIP, mreq) + } + + pub fn leave_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) + -> io::Result<()> { + let mreq = c::ip_mreq { + imr_multiaddr: *multiaddr.as_inner(), + imr_interface: *interface.as_inner(), + }; + setsockopt(&self.inner, c::IPPROTO_IP, c::IP_DROP_MEMBERSHIP, mreq) + } + + pub fn leave_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) + -> io::Result<()> { + let mreq = c::ipv6_mreq { + ipv6mr_multiaddr: *multiaddr.as_inner(), + ipv6mr_interface: to_ipv6mr_interface(interface), + }; + setsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_DROP_MEMBERSHIP, mreq) + } + + pub fn set_ttl(&self, ttl: u32) -> io::Result<()> { + setsockopt(&self.inner, c::IPPROTO_IP, c::IP_TTL, ttl as c_int) + } + + pub fn ttl(&self) -> io::Result { + let raw: c_int = try!(getsockopt(&self.inner, c::IPPROTO_IP, c::IP_TTL)); + Ok(raw as u32) + } + + pub fn set_only_v6(&self, only_v6: bool) -> io::Result<()> { + setsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_V6ONLY, only_v6 as c_int) + } + + pub fn only_v6(&self) -> io::Result { + let raw: c_int = try!(getsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_V6ONLY)); + Ok(raw != 0) + } + + pub fn take_error(&self) -> io::Result> { + let raw: c_int = try!(getsockopt(&self.inner, c::SOL_SOCKET, c::SO_ERROR)); + if raw == 0 { + Ok(None) + } else { + Ok(Some(io::Error::from_raw_os_error(raw as i32))) + } + } + + pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { + self.inner.set_nonblocking(nonblocking) + } + + pub fn recv(&self, buf: &mut [u8]) -> io::Result { + self.inner.read(buf) + } + + pub fn send(&self, buf: &[u8]) -> io::Result { + let len = cmp::min(buf.len(), ::max_value() as usize) as wrlen_t; + let ret = try!(cvt(unsafe { + c::send(*self.inner.as_inner(), + buf.as_ptr() as *const c_void, + len, + 0) + })); + Ok(ret as usize) + } + + pub fn connect(&self, addr: &SocketAddr) -> io::Result<()> { + let (addrp, len) = addr.into_inner(); + cvt_r(|| unsafe { c::connect(*self.inner.as_inner(), addrp, len) }).map(|_| ()) + } } impl FromInner for UdpSocket { -- cgit 1.4.1-3-g733a5