use std::ffi::CStr;
use std::time::{Duration, UNIX_EPOCH, SystemTime};
use crate::addr::ScamperAddr;
use crate::list::{ScamperList, ScamperCycle};
use crate::ffi::scamper_tbit::{self, ScamperTbitT, ScamperTbitPktT};
fn timeval_to_systemtime(tv: *const libc::timeval) -> Option<SystemTime> {
if tv.is_null() { return None; }
let tv = unsafe { &*tv };
Some(UNIX_EPOCH + Duration::new(tv.tv_sec as u64, tv.tv_usec as u32 * 1000))
}
pub struct ScamperTbitPkt { inner: *mut ScamperTbitPktT }
impl ScamperTbitPkt {
pub(crate) unsafe fn from_ptr(ptr: *mut ScamperTbitPktT) -> Option<Self> {
if ptr.is_null() { return None; }
let ptr = unsafe { scamper_tbit::scamper_tbit_pkt_use(ptr) };
Some(ScamperTbitPkt { inner: ptr })
}
pub fn tv(&self) -> Option<SystemTime> {
timeval_to_systemtime(unsafe { scamper_tbit::scamper_tbit_pkt_tv_get(self.inner) })
}
pub fn dir(&self) -> u8 { unsafe { scamper_tbit::scamper_tbit_pkt_dir_get(self.inner) } }
pub fn len(&self) -> u16 { unsafe { scamper_tbit::scamper_tbit_pkt_len_get(self.inner) } }
pub fn data(&self) -> &[u8] {
let len = self.len() as usize;
let ptr = unsafe { scamper_tbit::scamper_tbit_pkt_data_get(self.inner) };
if ptr.is_null() || len == 0 { &[] } else { unsafe { std::slice::from_raw_parts(ptr, len) } }
}
}
impl Drop for ScamperTbitPkt {
fn drop(&mut self) { unsafe { scamper_tbit::scamper_tbit_pkt_free(self.inner) }; }
}
unsafe impl Send for ScamperTbitPkt {}
unsafe impl Sync for ScamperTbitPkt {}
pub struct ScamperTbit { pub(crate) inner: *mut ScamperTbitT }
impl ScamperTbit {
pub(crate) unsafe fn from_ptr(ptr: *mut ScamperTbitT) -> Option<Self> {
if ptr.is_null() { return None; }
Some(ScamperTbit { inner: ptr })
}
pub fn src(&self) -> Option<ScamperAddr> {
unsafe { ScamperAddr::from_ptr(scamper_tbit::scamper_tbit_src_get(self.inner)) }
}
pub fn dst(&self) -> Option<ScamperAddr> {
unsafe { ScamperAddr::from_ptr(scamper_tbit::scamper_tbit_dst_get(self.inner)) }
}
pub fn userid(&self) -> u32 { unsafe { scamper_tbit::scamper_tbit_userid_get(self.inner) } }
pub fn sport(&self) -> u16 { unsafe { scamper_tbit::scamper_tbit_sport_get(self.inner) } }
pub fn dport(&self) -> u16 { unsafe { scamper_tbit::scamper_tbit_dport_get(self.inner) } }
pub fn start(&self) -> Option<SystemTime> {
timeval_to_systemtime(unsafe { scamper_tbit::scamper_tbit_start_get(self.inner) })
}
pub fn tbit_type(&self) -> u8 { unsafe { scamper_tbit::scamper_tbit_type_get(self.inner) } }
pub fn app_proto(&self) -> u8 { unsafe { scamper_tbit::scamper_tbit_app_proto_get(self.inner) } }
pub fn options(&self) -> u32 { unsafe { scamper_tbit::scamper_tbit_options_get(self.inner) } }
pub fn errmsg(&self) -> Option<&str> {
let p = unsafe { scamper_tbit::scamper_tbit_errmsg_get(self.inner) };
if p.is_null() { None } else { Some(unsafe { CStr::from_ptr(p) }.to_str().unwrap_or("")) }
}
pub fn client_mss(&self) -> u16 { unsafe { scamper_tbit::scamper_tbit_client_mss_get(self.inner) } }
pub fn client_wscale(&self) -> u8 { unsafe { scamper_tbit::scamper_tbit_client_wscale_get(self.inner) } }
pub fn client_ipttl(&self) -> u8 { unsafe { scamper_tbit::scamper_tbit_client_ipttl_get(self.inner) } }
pub fn client_syn_retx(&self) -> u8 { unsafe { scamper_tbit::scamper_tbit_client_syn_retx_get(self.inner) } }
pub fn client_dat_retx(&self) -> u8 { unsafe { scamper_tbit::scamper_tbit_client_dat_retx_get(self.inner) } }
pub fn server_mss(&self) -> u16 { unsafe { scamper_tbit::scamper_tbit_server_mss_get(self.inner) } }
pub fn pktc(&self) -> u32 { unsafe { scamper_tbit::scamper_tbit_pktc_get(self.inner) } }
pub fn pkt(&self, i: u32) -> Option<ScamperTbitPkt> {
let ptr = unsafe { scamper_tbit::scamper_tbit_pkt_get(self.inner, i) };
unsafe { ScamperTbitPkt::from_ptr(ptr) }
}
pub fn list(&self) -> Option<ScamperList> {
unsafe { ScamperList::from_ptr(scamper_tbit::scamper_tbit_list_get(self.inner)) }
}
pub fn cycle(&self) -> Option<ScamperCycle> {
unsafe { ScamperCycle::from_ptr(scamper_tbit::scamper_tbit_cycle_get(self.inner)) }
}
pub fn to_json(&self) -> Option<String> {
let mut len = 0usize;
let ptr = unsafe { scamper_tbit::scamper_tbit_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 ScamperTbit {
fn drop(&mut self) { unsafe { scamper_tbit::scamper_tbit_free(self.inner) }; }
}
unsafe impl Send for ScamperTbit {}
unsafe impl Sync for ScamperTbit {}