1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
use crate::Result;
#[cfg(target_os = "linux")]
use libc::{c_char, in_addr, sockaddr_in};
use libc::{c_void, fd_set, suseconds_t, time_t, timeval};
use std::time::Duration;
use std::{mem, ptr};
pub mod c_str;
pub trait FromRaw<T> {
unsafe fn from_raw<'a>(raw: *mut c_void) -> &'a mut T {
assert_not_null!(raw);
&mut *(raw as *mut T)
}
}
pub trait CloneRaw<T: FromRaw<T> + Clone> {
unsafe fn clone_raw(raw: *mut c_void) -> Box<T> {
assert_not_null!(raw);
Box::new(T::from_raw(raw).clone())
}
}
pub trait AsRaw {
fn as_raw(&mut self) -> *mut c_void {
self as *mut _ as *mut c_void
}
}
pub unsafe fn read_select(sock_fd: i32, timeout: Duration) -> Result<u32> {
let mut read_flags: fd_set = mem::zeroed();
libc::FD_ZERO(&mut read_flags);
libc::FD_SET(sock_fd, &mut read_flags);
let tv_sec = timeout.as_secs() as time_t;
let tv_usec = timeout.subsec_micros() as suseconds_t;
let mut timeout = timeval { tv_sec, tv_usec };
let result = libc::select(
sock_fd + 1,
&mut read_flags,
ptr::null_mut(),
ptr::null_mut(),
&mut timeout,
);
if result < 0 {
Err("select(): returned error status".into())
} else {
Ok(result as u32)
}
}
pub trait UnwrapOrNull<T> {
fn unwrap_or_null(&self) -> *const T;
}
impl<T> UnwrapOrNull<T> for Option<*const T> {
fn unwrap_or_null(&self) -> *const T {
self.unwrap_or_else(|| ptr::null() as *const T)
}
}
pub trait UnwrapMutOrNull<T> {
fn unwrap_mut_or_null(&mut self) -> *mut T;
}
impl<T> UnwrapMutOrNull<T> for Option<*mut T> {
fn unwrap_mut_or_null(&mut self) -> *mut T {
self.unwrap_or_else(|| ptr::null_mut() as *mut T)
}
}
#[cfg(target_os = "linux")]
pub unsafe fn get_ip(address: *const sockaddr_in) -> String {
assert_not_null!(address);
let raw = inet_ntoa(&(*address).sin_addr as *const in_addr);
String::from(c_str::raw_to_str(raw))
}
#[cfg(target_os = "linux")]
extern "C" {
fn inet_ntoa(addr: *const in_addr) -> *const c_char;
}