diff options
-rw-r--r-- | src/sys/socket/sockopt.rs | 91 |
1 files changed, 90 insertions, 1 deletions
diff --git a/src/sys/socket/sockopt.rs b/src/sys/socket/sockopt.rs index f440a00c..424d7557 100644 --- a/src/sys/socket/sockopt.rs +++ b/src/sys/socket/sockopt.rs @@ -6,6 +6,28 @@ use libc::{self, c_int, uint8_t, c_void, socklen_t}; use std::mem; use std::os::unix::io::RawFd; +/// Helper for implementing `SetSockOpt` for a given socket option. See +/// [`::sys::socket::SetSockOpt`](sys/socket/trait.SetSockOpt.html). +/// +/// This macro aims to help implementing `SetSockOpt` for different socket options that accept +/// different kinds of data to be used with `setsockopt`. +/// +/// Instead of using this macro directly consider using `sockopt_impl!`, especially if the option +/// you are implementing represents a simple type. +/// +/// # Arguments +/// +/// * `$name:ident`: name of the type you want to implement `SetSockOpt` for. +/// * `$level:path` : socket layer, or a `protocol level`: could be *raw sockets* +/// (`lic::SOL_SOCKET`), *ip protocol* (libc::IPPROTO_IP), *tcp protocol* (`libc::IPPROTO_TCP`), +/// and more. Please refer to your system manual for more options. Will be passed as the second +/// argument (`level`) to the `setsockopt` call. +/// * `$flag:path`: a flag name to set. Some examples: `libc::SO_REUSEADDR`, `libc::TCP_NODELAY`, +/// `libc::IP_ADD_MEMBERSHIP` and others. Will be passed as the third argument (`option_name`) +/// to the `setsockopt` call. +/// * Type of the value that you are going to set. +/// * Type that implements the `Set` trait for the type from the previous item (like `SetBool` for +/// `bool`, `SetUsize` for `usize`, etc.). macro_rules! setsockopt_impl { ($name:ident, $level:path, $flag:path, $ty:ty, $setter:ty) => { impl SetSockOpt for $name { @@ -25,6 +47,28 @@ macro_rules! setsockopt_impl { } } +/// Helper for implementing `GetSockOpt` for a given socket option. See +/// [`::sys::socket::GetSockOpt`](sys/socket/trait.GetSockOpt.html). +/// +/// This macro aims to help implementing `GetSockOpt` for different socket options that accept +/// different kinds of data to be use with `getsockopt`. +/// +/// Instead of using this macro directly consider using `sockopt_impl!`, especially if the option +/// you are implementing represents a simple type. +/// +/// # Arguments +/// +/// * Name of the type you want to implement `GetSockOpt` for. +/// * Socket layer, or a `protocol level`: could be *raw sockets* (`lic::SOL_SOCKET`), *ip +/// protocol* (libc::IPPROTO_IP), *tcp protocol* (`libc::IPPROTO_TCP`), and more. Please refer +/// to your system manual for more options. Will be passed as the second argument (`level`) to +/// the `getsockopt` call. +/// * A flag to set. Some examples: `libc::SO_REUSEADDR`, `libc::TCP_NODELAY`, +/// `libc::SO_ORIGINAL_DST` and others. Will be passed as the third argument (`option_name`) to +/// the `getsockopt` call. +/// * Type of the value that you are going to get. +/// * Type that implements the `Get` trait for the type from the previous item (`GetBool` for +/// `bool`, `GetUsize` for `usize`, etc.). macro_rules! getsockopt_impl { ($name:ident, $level:path, $flag:path, $ty:ty, $getter:ty) => { impl GetSockOpt for $name { @@ -46,7 +90,31 @@ macro_rules! getsockopt_impl { } } -// Helper to generate the sockopt accessors +/// Helper to generate the sockopt accessors. See +/// [`::sys::socket::GetSockOpt`](sys/socket/trait.GetSockOpt.html) and +/// [`::sys::socket::SetSockOpt`](sys/socket/trait.SetSockOpt.html). +/// +/// This macro aims to help implementing `GetSockOpt` and `SetSockOpt` for different socket options +/// that accept different kinds of data to be use with `getsockopt` and `setsockopt` respectively. +/// +/// Basically this macro wraps up the [`getsockopt_impl!`](macro.getsockopt_impl.html) and +/// [`setsockopt_impl!`](macro.setsockopt_impl.html) macros. +/// +/// # Arguments +/// +/// * `GetOnly`, `SetOnly` or `Both`: whether you want to implement only getter, only setter or +/// both of them. +/// * `$name:ident`: name of type `GetSockOpt`/`SetSockOpt` will be implemented for. +/// * `$level:path` : socket layer, or a `protocol level`: could be *raw sockets* +/// (`lic::SOL_SOCKET`), *ip protocol* (libc::IPPROTO_IP), *tcp protocol* (`libc::IPPROTO_TCP`), +/// and more. Please refer to your system manual for more options. Will be passed as the second +/// argument (`level`) to the `getsockopt`/`setsockopt` call. +/// * `$flag:path`: a flag name to set. Some examples: `libc::SO_REUSEADDR`, `libc::TCP_NODELAY`, +/// `libc::IP_ADD_MEMBERSHIP` and others. Will be passed as the third argument (`option_name`) +/// to the `setsockopt`/`getsockopt` call. +/// * `$ty:ty`: type of the value that will be get/set. +/// * `$getter:ty`: `Get` implementation; optional; only for `GetOnly` and `Both`. +/// * `$setter:ty`: `Set` implementation; optional; only for `SetOnly` and `Both`. macro_rules! sockopt_impl { (GetOnly, $name:ident, $level:path, $flag:path, bool) => { sockopt_impl!(GetOnly, $name, $level, $flag, bool, GetBool); @@ -192,19 +260,33 @@ sockopt_impl!(Both, BindAny, libc::IPPROTO_IP, libc::IP_BINDANY, bool); * */ +/// Helper trait that describes what is expected from a `GetSockOpt` getter. unsafe trait Get<T> { + /// Returns an empty value. unsafe fn blank() -> Self; + /// Returns a pointer to the stored value. This pointer will be passed to the system's + /// `getsockopt` call (`man 3p getsockopt`, argument `option_value`). fn ffi_ptr(&mut self) -> *mut c_void; + /// Returns length of the stored value. This pointer will be passed to the system's + /// `getsockopt` call (`man 3p getsockopt`, argument `option_len`). fn ffi_len(&mut self) -> *mut socklen_t; + /// Returns the stored value. unsafe fn unwrap(self) -> T; } +/// Helper trait that describes what is expected from a `SetSockOpt` setter. unsafe trait Set<'a, T> { + /// Initialize the setter with a given value. fn new(val: &'a T) -> Self; + /// Returns a pointer to the stored value. This pointer will be passed to the system's + /// `setsockopt` call (`man 3p setsockopt`, argument `option_value`). fn ffi_ptr(&self) -> *const c_void; + /// Returns length of the stored value. This pointer will be passed to the system's + /// `setsockopt` call (`man 3p setsockopt`, argument `option_len`). fn ffi_len(&self) -> socklen_t; } +/// Getter for an arbitrary `struct`. struct GetStruct<T> { len: socklen_t, val: T, @@ -232,6 +314,7 @@ unsafe impl<T> Get<T> for GetStruct<T> { } } +/// Setter for an arbitrary `struct`. struct SetStruct<'a, T: 'static> { ptr: &'a T, } @@ -250,6 +333,7 @@ unsafe impl<'a, T> Set<'a, T> for SetStruct<'a, T> { } } +/// Getter for a boolean value. struct GetBool { len: socklen_t, val: c_int, @@ -277,6 +361,7 @@ unsafe impl Get<bool> for GetBool { } } +/// Setter for a boolean value. struct SetBool { val: c_int, } @@ -295,6 +380,7 @@ unsafe impl<'a> Set<'a, bool> for SetBool { } } +/// Getter for an `u8` value. struct GetU8 { len: socklen_t, val: uint8_t, @@ -322,6 +408,7 @@ unsafe impl Get<u8> for GetU8 { } } +/// Setter for an `u8` value. struct SetU8 { val: uint8_t, } @@ -340,6 +427,7 @@ unsafe impl<'a> Set<'a, u8> for SetU8 { } } +/// Getter for an `usize` value. struct GetUsize { len: socklen_t, val: c_int, @@ -367,6 +455,7 @@ unsafe impl Get<usize> for GetUsize { } } +/// Setter for an `usize` value. struct SetUsize { val: c_int, } |