From 979faf097691dc35bb12b91dcde0d804a3d32b79 Mon Sep 17 00:00:00 2001 From: Carl Lerche Date: Mon, 23 Feb 2015 15:23:06 -0800 Subject: Improve ergonomics of getsockopt / setsockopt --- src/sys/socket/mod.rs | 71 ++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 50 insertions(+), 21 deletions(-) (limited to 'src/sys/socket/mod.rs') diff --git a/src/sys/socket/mod.rs b/src/sys/socket/mod.rs index 7e8afbfd..046df007 100644 --- a/src/sys/socket/mod.rs +++ b/src/sys/socket/mod.rs @@ -10,6 +10,7 @@ use std::os::unix::prelude::*; mod addr; mod consts; mod ffi; +pub mod sockopt; /* * @@ -264,34 +265,62 @@ pub struct linger { pub l_linger: c_int } -pub fn getsockopt(fd: Fd, level: SockLevel, opt: SockOpt, val: &mut T) -> NixResult { - let mut len = mem::size_of::() as socklen_t; +/* + * + * ===== Socket Options ===== + * + */ - let res = unsafe { - ffi::getsockopt( - fd, level, opt, - mem::transmute(val), - &mut len as *mut socklen_t) - }; +/// Represents a socket option that can be accessed or set +pub trait SockOpt : Copy + fmt::Debug { + /// Type of `getsockopt` return value + type Get; - if res < 0 { - return Err(NixError::Sys(Errno::last())); - } + /// Type of value used to set the socket option. Used as the argument to + /// `setsockopt`. + type Set; - Ok(len as usize) + #[doc(hidden)] + fn get(&self, fd: Fd, level: c_int) -> NixResult; + + #[doc(hidden)] + fn set(&self, fd: Fd, level: c_int, val: Self::Set) -> NixResult<()>; } -pub fn setsockopt(fd: Fd, level: SockLevel, opt: SockOpt, val: &T) -> NixResult<()> { - let len = mem::size_of::() as socklen_t; +pub enum SockLevel { + Socket, + Tcp, + Ip, + Ipv6, + Udp +} - let res = unsafe { - ffi::setsockopt( - fd, level, opt, - mem::transmute(val), - len) - }; +impl SockLevel { + fn as_cint(&self) -> c_int { + use self::SockLevel::*; - from_ffi(res) + match *self { + Socket => consts::SOL_SOCKET, + Tcp => consts::IPPROTO_TCP, + Ip => consts::IPPROTO_IP, + Ipv6 => consts::IPPROTO_IPV6, + Udp => consts::IPPROTO_UDP, + } + } +} + +/// Get the current value for the requested socket option +/// +/// [Further reading](http://man7.org/linux/man-pages/man2/setsockopt.2.html) +pub fn getsockopt(fd: Fd, level: SockLevel, opt: O) -> NixResult { + opt.get(fd, level.as_cint()) +} + +/// Sets the value for the requested socket option +/// +/// [Further reading](http://man7.org/linux/man-pages/man2/setsockopt.2.html) +pub fn setsockopt(fd: Fd, level: SockLevel, opt: O, val: O::Set) -> NixResult<()> { + opt.set(fd, level.as_cint(), val) } fn getpeername_sockaddr(sockfd: Fd, addr: &T) -> NixResult { -- cgit v1.2.3