mirror of
https://github.com/YGGverse/aquatic.git
synced 2026-03-31 17:55:36 +00:00
add crate cli_helpers with option and config parsing; use in aquatic
Putting cli functionality into its own crate will allow using it from aquatic_bench and possibly other programs.
This commit is contained in:
parent
06756f1c74
commit
ac52668a3d
9 changed files with 147 additions and 10 deletions
38
Cargo.lock
generated
38
Cargo.lock
generated
|
|
@ -18,11 +18,18 @@ dependencies = [
|
|||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
version = "1.0.28"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d9a60d744a80c30fcb657dfe2c1b22bcb3e814c1a1e3674f32bf5820b570fbff"
|
||||
|
||||
[[package]]
|
||||
name = "aquatic"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"bittorrent_udp",
|
||||
"cli_helpers",
|
||||
"dashmap",
|
||||
"histogram",
|
||||
"indexmap",
|
||||
|
|
@ -32,6 +39,7 @@ dependencies = [
|
|||
"quickcheck",
|
||||
"quickcheck_macros",
|
||||
"rand",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -142,6 +150,16 @@ version = "0.1.10"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
|
||||
|
||||
[[package]]
|
||||
name = "cli_helpers"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"gumdrop",
|
||||
"serde",
|
||||
"toml",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clicolors-control"
|
||||
version = "1.0.1"
|
||||
|
|
@ -237,6 +255,26 @@ dependencies = [
|
|||
"wasi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gumdrop"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ee50908bc1beeac1f2902e0b4e0cd0d844e716f5ebdc6f0cfc1163fe5e10bcde"
|
||||
dependencies = [
|
||||
"gumdrop_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gumdrop_derive"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "90454ce4de40b7ca6a8968b5ef367bdab48413962588d0d2b1638d60090c35d7"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.1.10"
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
[workspace]
|
||||
|
||||
members = [
|
||||
"bittorrent_udp",
|
||||
"aquatic",
|
||||
"aquatic_bench",
|
||||
"bittorrent_udp",
|
||||
"cli_helpers",
|
||||
]
|
||||
|
||||
[profile.release]
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ name = "aquatic"
|
|||
|
||||
[dependencies]
|
||||
bittorrent_udp = { path = "../bittorrent_udp" }
|
||||
cli_helpers = { path = "../cli_helpers" }
|
||||
dashmap = "3"
|
||||
histogram = "0.6"
|
||||
indexmap = "1"
|
||||
|
|
@ -20,6 +21,7 @@ mimalloc = { version = "0.1", default-features = false }
|
|||
mio = { version = "0.7", features = ["udp", "os-poll", "os-util"] }
|
||||
net2 = "0.2"
|
||||
rand = { version = "0.7", features = ["small_rng"] }
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
|
||||
[dev-dependencies]
|
||||
quickcheck = "0.9"
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
use aquatic;
|
||||
use cli_helpers;
|
||||
|
||||
|
||||
#[global_allocator]
|
||||
|
|
@ -6,5 +7,8 @@ static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc;
|
|||
|
||||
|
||||
fn main(){
|
||||
aquatic::run();
|
||||
cli_helpers::run_with_cli_and_config(
|
||||
"aquatic: udp bittorrent tracker",
|
||||
aquatic::run,
|
||||
)
|
||||
}
|
||||
|
|
@ -1,7 +1,9 @@
|
|||
use std::net::SocketAddr;
|
||||
|
||||
use serde::{Serialize, Deserialize};
|
||||
|
||||
#[derive(Clone)]
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct Config {
|
||||
/// Spawn this number of threads for workers
|
||||
pub num_threads: usize,
|
||||
|
|
@ -11,7 +13,7 @@ pub struct Config {
|
|||
}
|
||||
|
||||
|
||||
#[derive(Clone)]
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct NetworkConfig {
|
||||
/// Bind to this address
|
||||
pub address: SocketAddr,
|
||||
|
|
@ -27,14 +29,14 @@ pub struct NetworkConfig {
|
|||
}
|
||||
|
||||
|
||||
#[derive(Clone)]
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct StatisticsConfig {
|
||||
/// Print statistics this often (seconds). Don't print when set to zero.
|
||||
pub interval: u64,
|
||||
}
|
||||
|
||||
|
||||
#[derive(Clone)]
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct CleaningConfig {
|
||||
/// Clean torrents and connections this often (seconds)
|
||||
pub interval: u64,
|
||||
|
|
|
|||
|
|
@ -10,8 +10,7 @@ use config::Config;
|
|||
use common::State;
|
||||
|
||||
|
||||
pub fn run(){
|
||||
let config = Config::default();
|
||||
pub fn run(config: Config){
|
||||
let state = State::new();
|
||||
|
||||
for i in 0..config.num_threads {
|
||||
|
|
|
|||
11
cli_helpers/Cargo.toml
Normal file
11
cli_helpers/Cargo.toml
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
[package]
|
||||
name = "cli_helpers"
|
||||
version = "0.1.0"
|
||||
authors = ["Joakim Frostegård <joakim.frostegard@gmail.com>"]
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1"
|
||||
gumdrop = "0.7"
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
toml = "0.5"
|
||||
80
cli_helpers/src/lib.rs
Normal file
80
cli_helpers/src/lib.rs
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
use std::fs::File;
|
||||
use std::io::Read;
|
||||
|
||||
use anyhow;
|
||||
use gumdrop::Options;
|
||||
use serde::{Serialize, de::DeserializeOwned};
|
||||
use toml;
|
||||
|
||||
|
||||
#[derive(Debug, Options)]
|
||||
struct AppOptions {
|
||||
#[options(help = "run with config file", short = "c", meta = "PATH")]
|
||||
config_file: Option<String>,
|
||||
#[options(help = "print default config file")]
|
||||
print_config: bool,
|
||||
#[options(help = "print help message")]
|
||||
help: bool,
|
||||
}
|
||||
|
||||
|
||||
fn config_from_toml_file<T>(path: String) -> anyhow::Result<T>
|
||||
where T: DeserializeOwned
|
||||
{
|
||||
let mut file = File::open(path)?;
|
||||
let mut data = String::new();
|
||||
file.read_to_string(&mut data)?;
|
||||
|
||||
toml::from_str(&data).map_err(|e| anyhow::anyhow!("Parse failed: {}", e))
|
||||
}
|
||||
|
||||
fn default_config_as_toml<T>() -> String
|
||||
where T: Default + Serialize
|
||||
{
|
||||
toml::to_string_pretty(&T::default())
|
||||
.expect("Could not serialize default config to toml")
|
||||
}
|
||||
|
||||
|
||||
pub fn run_with_cli_and_config<T, F>(
|
||||
title: &str,
|
||||
// Function that takes config file and runs application
|
||||
f: F,
|
||||
) where T: Default + Serialize + DeserializeOwned, F: Fn(T) {
|
||||
let args: Vec<String> = ::std::env::args().collect();
|
||||
|
||||
match AppOptions::parse_args_default(&args[1..]){
|
||||
Ok(opts) => {
|
||||
if opts.help_requested(){
|
||||
print_help(title, None);
|
||||
} else if opts.print_config {
|
||||
print!("{}", default_config_as_toml::<T>());
|
||||
} else if let Some(config_file) = opts.config_file {
|
||||
match config_from_toml_file(config_file){
|
||||
Ok(config) => f(config),
|
||||
Err(err) => {
|
||||
eprintln!("Error while reading config file: {}", err);
|
||||
|
||||
::std::process::exit(1);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
f(T::default())
|
||||
}
|
||||
},
|
||||
Err(err) => {
|
||||
print_help(title, Some(&format!("{}", err)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fn print_help(title: &str, opt_error: Option<&str>){
|
||||
println!("{}", title);
|
||||
|
||||
if let Some(error) = opt_error {
|
||||
println!("\nError: {}.", error);
|
||||
}
|
||||
|
||||
println!("\n{}", AppOptions::usage());
|
||||
}
|
||||
|
|
@ -2,4 +2,4 @@
|
|||
|
||||
export RUSTFLAGS="-C target-cpu=native"
|
||||
|
||||
cargo run --release --bin aquatic
|
||||
cargo run --release --bin aquatic -- $@
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue