about summary refs log tree commit diff
path: root/src/libstd/sys
diff options
context:
space:
mode:
Diffstat (limited to 'src/libstd/sys')
-rw-r--r--src/libstd/sys/common/net.rs138
1 files changed, 135 insertions, 3 deletions
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<T>(sock: &Socket, opt: c_int, val: c_int,
 }
 
 pub fn getsockopt<T: Copy>(sock: &Socket, opt: c_int,
-                       val: c_int) -> io::Result<T> {
-    unsafe {
+                       val: c_int) -> io::Result<T> { unsafe {
         let mut slot: T = mem::zeroed();
         let mut len = mem::size_of::<T>() 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<Option<Duration>> {
         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<bool> {
+        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<bool> {
+        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<u32> {
+        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<bool> {
+        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<u32> {
+        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<bool> {
+        let raw: c_int = try!(getsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_V6ONLY));
+        Ok(raw != 0)
+    }
+
+    pub fn take_error(&self) -> io::Result<Option<io::Error>> {
+        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<usize> {
+        self.inner.read(buf)
+    }
+
+    pub fn send(&self, buf: &[u8]) -> io::Result<usize> {
+        let len = cmp::min(buf.len(), <wrlen_t>::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<Socket> for UdpSocket {