use std::ffi::CStr;
use std::time::{Duration, UNIX_EPOCH, SystemTime};
use crate::addr::ScamperAddr;
use crate::list::{ScamperList, ScamperCycle};
use crate::ffi::scamper_udpprobe::{self, ScamperUdpprobeT, ScamperUdpprobeProbeT,
ScamperUdpprobeReplyT,
SCAMPER_UDPPROBE_STOP_NONE, SCAMPER_UDPPROBE_STOP_DONE,
SCAMPER_UDPPROBE_STOP_HALTED, SCAMPER_UDPPROBE_STOP_ERROR};
fn timeval_to_duration(tv: *const libc::timeval) -> Option<Duration> {
if tv.is_null() { return None; }
let tv = unsafe { &*tv };
Some(Duration::new(tv.tv_sec as u64, tv.tv_usec as u32 * 1000))
}
fn timeval_to_systemtime(tv: *const libc::timeval) -> Option<SystemTime> {
timeval_to_duration(tv).map(|d| UNIX_EPOCH + d)
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum UdpprobeStopReason {
None, Done, Halted, Error, Unknown(u8),
}
impl From<u8> for UdpprobeStopReason {
fn from(v: u8) -> Self {
match v {
SCAMPER_UDPPROBE_STOP_NONE => Self::None,
SCAMPER_UDPPROBE_STOP_DONE => Self::Done,
SCAMPER_UDPPROBE_STOP_HALTED => Self::Halted,
SCAMPER_UDPPROBE_STOP_ERROR => Self::Error,
other => Self::Unknown(other),
}
}
}
pub struct ScamperUdpprobeReply { inner: *mut ScamperUdpprobeReplyT }
impl ScamperUdpprobeReply {
pub(crate) unsafe fn from_ptr(ptr: *mut ScamperUdpprobeReplyT) -> Option<Self> {
if ptr.is_null() { return None; }
let ptr = unsafe { scamper_udpprobe::scamper_udpprobe_reply_use(ptr) };
Some(ScamperUdpprobeReply { inner: ptr })
}
pub fn data(&self) -> &[u8] {
let len = unsafe { scamper_udpprobe::scamper_udpprobe_reply_len_get(self.inner) } as usize;
let ptr = unsafe { scamper_udpprobe::scamper_udpprobe_reply_data_get(self.inner) };
if ptr.is_null() || len == 0 { &[] } else { unsafe { std::slice::from_raw_parts(ptr, len) } }
}
pub fn len(&self) -> u16 { unsafe { scamper_udpprobe::scamper_udpprobe_reply_len_get(self.inner) } }
pub fn rx(&self) -> Option<SystemTime> {
timeval_to_systemtime(unsafe { scamper_udpprobe::scamper_udpprobe_reply_rx_get(self.inner) })
}
pub fn ifname(&self) -> Option<&str> {
let p = unsafe { scamper_udpprobe::scamper_udpprobe_reply_ifname_get(self.inner) };
if p.is_null() { None } else { Some(unsafe { CStr::from_ptr(p) }.to_str().unwrap_or("")) }
}
}
impl Drop for ScamperUdpprobeReply {
fn drop(&mut self) { unsafe { scamper_udpprobe::scamper_udpprobe_reply_free(self.inner) }; }
}
unsafe impl Send for ScamperUdpprobeReply {}
unsafe impl Sync for ScamperUdpprobeReply {}
pub struct ScamperUdpprobeProbe { inner: *mut ScamperUdpprobeProbeT }
impl ScamperUdpprobeProbe {
pub(crate) unsafe fn from_ptr(ptr: *mut ScamperUdpprobeProbeT) -> Option<Self> {
if ptr.is_null() { return None; }
let ptr = unsafe { scamper_udpprobe::scamper_udpprobe_probe_use(ptr) };
Some(ScamperUdpprobeProbe { inner: ptr })
}
pub fn tx(&self) -> Option<SystemTime> {
timeval_to_systemtime(unsafe { scamper_udpprobe::scamper_udpprobe_probe_tx_get(self.inner) })
}
pub fn sport(&self) -> u16 { unsafe { scamper_udpprobe::scamper_udpprobe_probe_sport_get(self.inner) } }
pub fn replyc(&self) -> u8 { unsafe { scamper_udpprobe::scamper_udpprobe_probe_replyc_get(self.inner) } }
pub fn reply(&self, i: u8) -> Option<ScamperUdpprobeReply> {
let ptr = unsafe { scamper_udpprobe::scamper_udpprobe_probe_reply_get(self.inner, i) };
unsafe { ScamperUdpprobeReply::from_ptr(ptr) }
}
}
impl Drop for ScamperUdpprobeProbe {
fn drop(&mut self) { unsafe { scamper_udpprobe::scamper_udpprobe_probe_free(self.inner) }; }
}
unsafe impl Send for ScamperUdpprobeProbe {}
unsafe impl Sync for ScamperUdpprobeProbe {}
pub struct ScamperUdpprobe { pub(crate) inner: *mut ScamperUdpprobeT }
impl ScamperUdpprobe {
pub(crate) unsafe fn from_ptr(ptr: *mut ScamperUdpprobeT) -> Option<Self> {
if ptr.is_null() { return None; }
Some(ScamperUdpprobe { inner: ptr })
}
pub fn src(&self) -> Option<ScamperAddr> {
unsafe { ScamperAddr::from_ptr(scamper_udpprobe::scamper_udpprobe_src_get(self.inner)) }
}
pub fn dst(&self) -> Option<ScamperAddr> {
unsafe { ScamperAddr::from_ptr(scamper_udpprobe::scamper_udpprobe_dst_get(self.inner)) }
}
pub fn userid(&self) -> u32 { unsafe { scamper_udpprobe::scamper_udpprobe_userid_get(self.inner) } }
pub fn sport(&self) -> u16 { unsafe { scamper_udpprobe::scamper_udpprobe_sport_get(self.inner) } }
pub fn dport(&self) -> u16 { unsafe { scamper_udpprobe::scamper_udpprobe_dport_get(self.inner) } }
pub fn start(&self) -> Option<SystemTime> {
timeval_to_systemtime(unsafe { scamper_udpprobe::scamper_udpprobe_start_get(self.inner) })
}
pub fn stop_reason(&self) -> UdpprobeStopReason {
UdpprobeStopReason::from(unsafe { scamper_udpprobe::scamper_udpprobe_stop_reason_get(self.inner) })
}
pub fn errmsg(&self) -> Option<&str> {
let p = unsafe { scamper_udpprobe::scamper_udpprobe_errmsg_get(self.inner) };
if p.is_null() { None } else { Some(unsafe { CStr::from_ptr(p) }.to_str().unwrap_or("")) }
}
pub fn data(&self) -> &[u8] {
let len = unsafe { scamper_udpprobe::scamper_udpprobe_len_get(self.inner) } as usize;
let ptr = unsafe { scamper_udpprobe::scamper_udpprobe_data_get(self.inner) };
if ptr.is_null() || len == 0 { &[] } else { unsafe { std::slice::from_raw_parts(ptr, len) } }
}
pub fn probe_count(&self) -> u8 { unsafe { scamper_udpprobe::scamper_udpprobe_probe_count_get(self.inner) } }
pub fn probe_sent(&self) -> u8 { unsafe { scamper_udpprobe::scamper_udpprobe_probe_sent_get(self.inner) } }
pub fn probe(&self, i: u8) -> Option<ScamperUdpprobeProbe> {
let ptr = unsafe { scamper_udpprobe::scamper_udpprobe_probe_get(self.inner, i) };
unsafe { ScamperUdpprobeProbe::from_ptr(ptr) }
}
pub fn wait_timeout(&self) -> Option<Duration> {
timeval_to_duration(unsafe { scamper_udpprobe::scamper_udpprobe_wait_timeout_get(self.inner) })
}
pub fn wait_probe(&self) -> Option<Duration> {
timeval_to_duration(unsafe { scamper_udpprobe::scamper_udpprobe_wait_probe_get(self.inner) })
}
pub fn list(&self) -> Option<ScamperList> {
unsafe { ScamperList::from_ptr(scamper_udpprobe::scamper_udpprobe_list_get(self.inner)) }
}
pub fn cycle(&self) -> Option<ScamperCycle> {
unsafe { ScamperCycle::from_ptr(scamper_udpprobe::scamper_udpprobe_cycle_get(self.inner)) }
}
pub fn to_json(&self) -> Option<String> {
let mut len = 0usize;
let ptr = unsafe { scamper_udpprobe::scamper_udpprobe_tojson(self.inner, &mut len) };
if ptr.is_null() { return None; }
let s = unsafe { CStr::from_ptr(ptr) }.to_string_lossy().into_owned();
unsafe { libc::free(ptr as *mut libc::c_void) };
Some(s)
}
}
impl Drop for ScamperUdpprobe {
fn drop(&mut self) { unsafe { scamper_udpprobe::scamper_udpprobe_free(self.inner) }; }
}
unsafe impl Send for ScamperUdpprobe {}
unsafe impl Sync for ScamperUdpprobe {}