e_libscanner/utils/
traceroute.rs1use std::{
2 fmt,
3 net::IpAddr,
4 sync::{
5 mpsc::{self, Receiver, Sender},
6 Arc, Mutex,
7 },
8 thread,
9 time::Duration,
10};
11use e_utils::traceroute::Traceroute;
12
13#[derive(Clone, Debug)]
15pub struct TracertQueryResult {
16 #[doc(hidden)]
17 pub id: u8,
18 pub rtt: Duration,
20 pub addr: Vec<Vec<String>>,
22}
23impl fmt::Display for TracertQueryResult {
24 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
25 write!(
26 f,
27 "[id[{}] rtt[{}] addr[{:?}]]",
28 self.id,
29 self.rtt.as_millis(),
30 self.addr
31 )
32 }
33}
34
35#[derive(Debug)]
68pub struct Tracert {
69 iface_ip: Option<IpAddr>,
70 target: Vec<String>,
71 sender: Arc<Mutex<Sender<TracertQueryResult>>>,
72 receiver: Arc<Mutex<Receiver<TracertQueryResult>>>,
73}
74impl Tracert {
75 pub fn new(target: Vec<String>, iface_ip: Option<IpAddr>) -> Self {
77 let (tx, rx) = mpsc::channel();
78 Tracert {
79 iface_ip,
80 target,
81 sender: Arc::new(Mutex::new(tx)),
82 receiver: Arc::new(Mutex::new(rx)),
83 }
84 }
85 pub fn len(&self) -> usize {
87 self.target.len()
88 }
89 pub fn get_progress_receiver(&self) -> Arc<Mutex<Receiver<TracertQueryResult>>> {
91 self.receiver.clone()
92 }
93 pub fn scan(&self, pstop: Option<Arc<Mutex<bool>>>) -> Vec<TracertQueryResult> {
95 let mut handles = vec![];
96 let mut results = vec![];
97 let stop = if let Some(p) = pstop {
98 p
99 } else {
100 Arc::new(Mutex::new(false))
101 };
102 for t in self.target.clone() {
103 let sender_cp = Arc::clone(&self.sender);
104 let iface_ip_cp = self.iface_ip.clone();
105 let stop_cp = Arc::clone(&stop);
106 handles.push(thread::spawn(move || {
107 let tracert = Traceroute::new(t.clone(), iface_ip_cp).unwrap();
108 let mut tracert_results = vec![];
109 let mut state = false;
110 for hop in tracert {
111 if state {
112 break;
113 } else {
114 let mut result = TracertQueryResult {
115 id: hop.ttl,
116 rtt: Duration::default(),
117 addr: vec![],
118 };
119 for query_result in hop.query_result {
120 if query_result.rtt.as_millis() > result.rtt.as_micros() {
121 result.rtt = query_result.rtt;
122 }
123 result.addr.push(query_result.addr);
124 if *stop_cp.lock().unwrap() {
125 state = true;
126 break;
127 }
128 }
129 sender_cp.lock().unwrap().send(result.clone()).unwrap();
130 tracert_results.push(result);
131 }
132 }
133 tracert_results
134 }));
135 }
136 for handle in handles {
137 results.append(&mut handle.join().unwrap());
138 }
139 results
140 }
141}