Prettier resultsé
All checks were successful
Rust-build / build (push) Successful in 2m19s

This commit is contained in:
Justine Pelletreau
2023-07-22 18:56:21 +02:00
parent 53c405b7a6
commit dd430b1b2c
6 changed files with 82 additions and 40 deletions

View File

@ -47,4 +47,3 @@ jobs:
- name: Build - name: Build
run: cargo build --release run: cargo build --release

View File

@ -4,7 +4,6 @@ Portnut is a port stressing / scanning multithreaded utility. It can handle raw
# TODO # TODO
* Make a distributed version that allows stressing from multiple computers at the same time * Make a distributed version that allows stressing from multiple computers at the same time
* When TCP stress testing, show results for each port.
* Return more stats (low 1%, high 1%) * Return more stats (low 1%, high 1%)
* Automated releases * Automated releases

View File

@ -5,12 +5,6 @@ use std::sync::mpsc;
use crate::results::*; use crate::results::*;
fn print_results(res: Vec<StressResult>) {
let myres = ListOfResults { results: res };
myres.show_ratio();
println!("\tMean answer time : {:?}", myres.get_mean_time());
}
pub fn http_stress(url: String, interval: Duration, sleep: Duration, threads: u32) -> std::io::Result<()> { pub fn http_stress(url: String, interval: Duration, sleep: Duration, threads: u32) -> std::io::Result<()> {
let mut handles = vec![]; let mut handles = vec![];
@ -18,7 +12,7 @@ pub fn http_stress(url: String, interval: Duration, sleep: Duration, threads: u3
println!("Threads starting their {:?} run...", interval); println!("Threads starting their {:?} run...", interval);
for i in 0..=threads { for _i in 0..=threads {
let add = url.clone(); let add = url.clone();
let end_time = Instant::now() + interval; let end_time = Instant::now() + interval;
let wait = sleep.clone(); let wait = sleep.clone();
@ -35,12 +29,12 @@ pub fn http_stress(url: String, interval: Duration, sleep: Duration, threads: u3
let time = Instant::now() - b4; let time = Instant::now() - b4;
match resp { match resp {
Ok(_) => { Ok(_) => {
let myres = StressResult { time: time, thread: i, ok: true }; let myres = StressResult { time: time, ok: true, rtype: ResType::Http };
let _ = tx2.send(myres); let _ = tx2.send(myres);
//println!("Got an answer for {} in {:?} in thread {}", add, time, i); //println!("Got an answer for {} in {:?} in thread {}", add, time, i);
}, },
Err(_) => { Err(_) => {
let myres = StressResult { time: time, thread: i, ok: false }; let myres = StressResult { time: time, ok: false, rtype: ResType::Http };
let _ = tx2.send(myres); let _ = tx2.send(myres);
//println!("No answer for {} after {:?} in thread {}", add, time, i); //println!("No answer for {} after {:?} in thread {}", add, time, i);
}, },
@ -63,7 +57,8 @@ pub fn http_stress(url: String, interval: Duration, sleep: Duration, threads: u3
for r in rx.try_iter() { for r in rx.try_iter() {
res.push(r); res.push(r);
} }
print_results(res); let lres = ListOfResults { results: res, restype: ResType::Http };
lres.show_info();
Ok(()) Ok(())
} }

View File

@ -37,14 +37,17 @@ fn main() -> std::io::Result<()> {
match args.mode.as_str() { match args.mode.as_str() {
"tcpstress" => { "tcpstress" => {
println!("===== TCP STRESS TEST =====");
tcp_stress(payload, address, timeout, duration, ports, threads)?; tcp_stress(payload, address, timeout, duration, ports, threads)?;
return Ok(()); return Ok(());
} }
"tcpscan" => { "tcpscan" => {
println!("===== TCP SCAN =====");
tcp_scan(address, timeout, sleep, ports)?; tcp_scan(address, timeout, sleep, ports)?;
return Ok(()); return Ok(());
} }
"httpstress" => { "httpstress" => {
println!("===== HTTP STRESS TEST =====");
http_stress(address, duration, sleep, threads)?; http_stress(address, duration, sleep, threads)?;
return Ok(()); return Ok(());
} }

View File

@ -1,34 +1,32 @@
use std::time::Duration; use std::time::Duration;
///Is implemented for Stress test results.
pub trait IsAResult {
///A way to return the ratio of hits to nohits (eg: "45% of our requests were answered" or
///smth)
fn show_ratio(&self);
///Return the mean hit time as a Duration
fn get_mean_time(&self) -> Duration;
}
#[derive(Debug)] #[derive(Debug, Clone)]
pub struct StressResult { pub struct StressResult {
///How long did it take ///How long did it take
pub time: Duration, pub time: Duration,
///What thread are we from
pub thread: u32,
///Did we get an answer ///Did we get an answer
pub ok: bool, pub ok: bool,
pub rtype: ResType,
} }
#[derive(Debug, Clone)]
pub enum ResType {
Tcp(u32),
Http,
}
#[derive(Debug, Clone)]
pub struct ListOfResults { pub struct ListOfResults {
pub results: Vec<StressResult>, pub results: Vec<StressResult>,
pub restype: ResType,
} }
impl ListOfResults {
impl IsAResult for ListOfResults { fn compute_ratio(&self) {
fn show_ratio(&self) {
let mut ok: u64 = 0; let mut ok: u64 = 0;
let mut nok: u64 = 0; let mut nok: u64 = 0;
for r in &self.results { for r in self.results.clone() {
if r.ok == true { if r.ok == true {
*&mut ok += 1; *&mut ok += 1;
} else { } else {
@ -39,10 +37,60 @@ impl IsAResult for ListOfResults {
println!("TOTAL {}\n\tOK {}\n\tNOK {}", compute, ok, nok); println!("TOTAL {}\n\tOK {}\n\tNOK {}", compute, ok, nok);
if compute < 1 { compute = 1; } if compute < 1 { compute = 1; }
compute = ok * 100 / compute; compute = ok * 100 / compute;
println!("\tGot {}% of OK", compute ); println!("Got {}% of OK\n", compute );
} }
fn get_mean_time(&self) -> Duration { ///Get the different TCP ports from the results
fn get_ports(&self) -> Vec<u32> {
let mut ports = vec![];
for r in &self.results {
match r.rtype {
ResType::Tcp(p) => {
if !ports.contains(&p) {
ports.push(p);
}
},
ResType::Http => (),
}
}
ports
}
///Show info, by port if we are in TCP mode
pub fn show_info(&self) {
println!("\n===== RESULTS =====");
match &self.restype {
ResType::Tcp(_) => {
let ports = self.get_ports();
for port in ports {
let mut results = Vec::new();
for res in &self.results {
match res.rtype {
ResType::Tcp(v) => {
if v == port { *&mut results.push(res.clone()); }
},
_ => (),
}
}
let list = ListOfResults { results: results, restype: ResType::Tcp(1) };
println!("=====> PORT {}", port);
list.show_mean_time();
list.compute_ratio();
}
},
ResType::Http => {
self.show_mean_time();
self.compute_ratio();
},
}
}
fn show_mean_time(&self) {
let mut total: u128 = 0; let mut total: u128 = 0;
let mut acc: u128 = 0; let mut acc: u128 = 0;
@ -54,13 +102,10 @@ impl IsAResult for ListOfResults {
} }
if total == 0 { total += 1 }; if total == 0 { total += 1 };
let restime = acc / total; let restime = acc / total;
Duration::from_millis(restime.try_into().unwrap()) println!("Average response time : {:?}", Duration::from_millis(restime.try_into().unwrap()));
} }
} }
pub fn print_results(res: Vec<StressResult>) {
let myres = ListOfResults { results: res };
myres.show_ratio();
println!("\tMean answer time : {:?}", myres.get_mean_time());
}

View File

@ -50,7 +50,6 @@ pub fn tcp_stress(payload: String, address: String, timeout: Duration, interval:
let (tx, rx) = mpsc::channel(); let (tx, rx) = mpsc::channel();
for port in ports { for port in ports {
tcp_scan(address.clone(), timeout, Duration::from_millis(100), vec![port])?;
let mut threads_left = threads; let mut threads_left = threads;
let tx2 = tx.clone(); let tx2 = tx.clone();
@ -87,7 +86,7 @@ pub fn tcp_stress(payload: String, address: String, timeout: Duration, interval:
} }
let time = Instant::now() - b4; let time = Instant::now() - b4;
let myres = StressResult { time: time, thread: port.clone(), ok: true }; let myres = StressResult { time: time, ok: true, rtype: ResType::Tcp(port.clone()) };
let _ = tx3.send(myres); let _ = tx3.send(myres);
//Sleeping //Sleeping
@ -96,7 +95,7 @@ pub fn tcp_stress(payload: String, address: String, timeout: Duration, interval:
}, },
Err(_) => { Err(_) => {
let time = Instant::now() - b4; let time = Instant::now() - b4;
let myres = StressResult { time: time, thread: port.clone(), ok: false }; let myres = StressResult { time: time, ok: false, rtype: ResType::Tcp(port.clone()) };
let _ = tx3.send(myres); let _ = tx3.send(myres);
} }
} }
@ -107,7 +106,7 @@ pub fn tcp_stress(payload: String, address: String, timeout: Duration, interval:
} }
} }
drop(tx); drop(tx);
println!("\nStressing {} using {} concurrent threads per port for {:?} \n", address, threads, interval); println!("Stressing {} using {} concurrent threads per port for {:?} \n", address, threads, interval);
for handle in handles { for handle in handles {
let _ = handle.join(); let _ = handle.join();
@ -117,7 +116,9 @@ pub fn tcp_stress(payload: String, address: String, timeout: Duration, interval:
for r in rx.try_iter() { for r in rx.try_iter() {
res.push(r); res.push(r);
} }
print_results(res); let listofres = ListOfResults { results: res, restype: ResType::Tcp(1) };
listofres.show_info();
Ok(()) Ok(())
} }