diff options
author | Fensteer <fensteer@protonmail.com> | 2018-11-16 16:06:12 +0100 |
---|---|---|
committer | nobody <nomaill@domain.org> | 2018-12-06 16:29:29 +0100 |
commit | b75d31d2f5b84a3ac5c0d59809dba918dd9c53d8 (patch) | |
tree | 02b018b6e5e266b4c2baa439bd02f56f8b989df9 /src | |
parent | f2780946875817c41b8de1dadb1904652b697e60 (diff) | |
download | nix-b75d31d2f5b84a3ac5c0d59809dba918dd9c53d8.zip |
Add support of TCP_CONGESTION for setsockopt
Diffstat (limited to 'src')
-rw-r--r-- | src/sys/socket/sockopt.rs | 61 |
1 files changed, 61 insertions, 0 deletions
diff --git a/src/sys/socket/sockopt.rs b/src/sys/socket/sockopt.rs index 494de4f5..17119384 100644 --- a/src/sys/socket/sockopt.rs +++ b/src/sys/socket/sockopt.rs @@ -5,6 +5,14 @@ use sys::time::TimeVal; use libc::{self, c_int, uint8_t, c_void, socklen_t}; use std::mem; use std::os::unix::io::RawFd; +use std::ffi::{OsStr, OsString}; +#[cfg(target_family = "unix")] +use std::os::unix::ffi::OsStrExt; + +// Constants +// TCP_CA_NAME_MAX isn't defined in user space include files +#[cfg(any(target_os = "freebsd", target_os = "linux"))] +const TCP_CA_NAME_MAX: usize = 16; /// Helper for implementing `SetSockOpt` for a given socket option. See /// [`::sys::socket::SetSockOpt`](sys/socket/trait.SetSockOpt.html). @@ -152,6 +160,10 @@ macro_rules! sockopt_impl { sockopt_impl!(Both, $name, $level, $flag, usize, GetUsize, SetUsize); }; + (Both, $name:ident, $level:path, $flag:path, OsString<$array:ty>) => { + sockopt_impl!(Both, $name, $level, $flag, OsString, GetOsString<$array>, SetOsString); + }; + /* * Matchers with generic getter types must be placed at the end, so * they'll only match _after_ specialized matchers fail @@ -257,6 +269,8 @@ sockopt_impl!(Both, BindAny, libc::IPPROTO_IP, libc::IP_BINDANY, bool); sockopt_impl!(Both, Mark, libc::SOL_SOCKET, libc::SO_MARK, u32); #[cfg(any(target_os = "android", target_os = "linux"))] sockopt_impl!(Both, PassCred, libc::SOL_SOCKET, libc::SO_PASSCRED, bool); +#[cfg(any(target_os = "freebsd", target_os = "linux"))] +sockopt_impl!(Both, TcpCongestion, libc::IPPROTO_TCP, libc::TCP_CONGESTION, OsString<[u8; TCP_CA_NAME_MAX]>); /* * @@ -478,6 +492,53 @@ unsafe impl<'a> Set<'a, usize> for SetUsize { } } +/// Getter for a `OsString` value. +struct GetOsString<T: AsMut<[u8]>> { + len: socklen_t, + val: T, +} + +unsafe impl<T: AsMut<[u8]>> Get<OsString> for GetOsString<T> { + unsafe fn blank() -> Self { + GetOsString { + len: mem::size_of::<T>() as socklen_t, + val: mem::zeroed(), + } + } + + fn ffi_ptr(&mut self) -> *mut c_void { + &mut self.val as *mut T as *mut c_void + } + + fn ffi_len(&mut self) -> *mut socklen_t { + &mut self.len + } + + unsafe fn unwrap(mut self) -> OsString { + OsStr::from_bytes(self.val.as_mut()).to_owned() + } +} + +/// Setter for a `OsString` value. +struct SetOsString<'a> { + val: &'a OsStr, +} + +unsafe impl<'a> Set<'a, OsString> for SetOsString<'a> { + fn new(val: &'a OsString) -> SetOsString { + SetOsString { val: val.as_os_str() } + } + + fn ffi_ptr(&self) -> *const c_void { + self.val.as_bytes().as_ptr() as *const c_void + } + + fn ffi_len(&self) -> socklen_t { + self.val.len() as socklen_t + } +} + + #[cfg(test)] mod test { #[cfg(any(target_os = "android", target_os = "linux"))] |