1#![doc = include_str!("../README.md")]
2#![deny(
3 rustdoc::broken_intra_doc_links,
4 rustdoc::private_intra_doc_links,
5 rustdoc::missing_crate_level_docs,
6 rustdoc::invalid_codeblock_attributes,
7 rustdoc::invalid_rust_codeblocks,
8 rustdoc::bare_urls,
9 rustdoc::invalid_html_tags
10)]
11#![warn(
12 trivial_casts,
13 trivial_numeric_casts,
14 unused_lifetimes,
15 unused_import_braces,
16 clippy::dbg_macro
17)]
18
19use core::time::Duration;
20use std::net::ToSocketAddrs;
21use std::sync::Arc;
22
23use args::StresserArgs;
24use clap::Parser;
25use stresser::{make_session, SessionParams};
26use tokio::sync::Semaphore;
27
28mod args;
29pub mod stresser;
30
31#[tokio::main]
32async fn main() {
33 let args = StresserArgs::parse();
34
35 let target_addr = args.target_host.to_socket_addrs().unwrap().next().unwrap();
36
37 let mut session_index: usize = 0;
38
39 let sema = Arc::new(Semaphore::new(args.sessions_count));
40
41 while let Ok(perm) = sema.clone().acquire_owned().await {
42 let session_name = format!("{}{}", args.name_prefix, session_index);
43
44 tokio::spawn(async move {
45 let params = SessionParams {
46 socket_addr: target_addr,
47 session_name: session_name.as_str(),
48 read_buffer_size: args.read_buffer_size,
49 };
50
51 if let Err(err) = make_session(¶ms).await {
52 eprintln!("Session {session_name} interrupted with error: {err}")
53 };
54
55 drop(perm);
56 });
57
58 session_index += 1;
59
60 tokio::time::sleep(Duration::from_millis(args.spawn_cooldown)).await;
61 }
62}