Checkpoint, or something.

This commit is contained in:
2022-11-22 20:13:14 -08:00
parent 277125e1a0
commit 1d182a150f
9 changed files with 467 additions and 97 deletions

35
server/config/cmdline.rs Normal file
View File

@@ -0,0 +1,35 @@
use clap::Parser;
use std::path::PathBuf;
use tracing::metadata::LevelFilter;
#[derive(Parser, Debug)]
#[clap(author, version, about, long_about = None)]
pub struct Arguments {
#[clap(
short,
long,
help = "Use the given config file, rather than $XDG_CONFIG_DIR/socks5.toml"
)]
pub config_file: Option<PathBuf>,
#[clap(
short,
long,
help = "Default logging to the given level. (Defaults to ERROR if not given)"
)]
pub log_level: Option<LevelFilter>,
#[clap(
short,
long,
help = "Start only the named server(s) from the config file. For more than one, use comma-separated values or multiple instances of --start"
)]
pub start: Vec<String>,
#[clap(
short,
long = "validate",
help = "Do not actually start any servers; just validate the config file."
)]
pub validate_only: bool,
}

View File

@@ -0,0 +1,62 @@
use super::ConfigError;
use serde::{Deserialize, Deserializer};
use std::collections::HashMap;
use std::fs;
use std::path::PathBuf;
use tracing::metadata::LevelFilter;
use xdg::BaseDirectories;
#[derive(serde_derive::Deserialize, Default)]
pub struct ConfigFile {
#[serde(deserialize_with = "parse_log_level")]
pub log_level: Option<LevelFilter>,
pub start_servers: Option<String>,
#[serde(flatten)]
pub servers: HashMap<String, ServerDefinition>,
}
#[derive(serde_derive::Deserialize)]
pub struct ServerDefinition {
pub interface: Option<String>,
#[serde(deserialize_with = "parse_log_level")]
pub log_level: Option<LevelFilter>,
pub address: Option<String>,
pub port: Option<u16>,
}
fn parse_log_level<'de, D>(deserializer: D) -> Result<Option<LevelFilter>, D::Error>
where
D: Deserializer<'de>,
{
let possible_string: Option<&str> = Deserialize::deserialize(deserializer)?;
if let Some(s) = possible_string {
Ok(Some(s.parse().map_err(|e| {
serde::de::Error::custom(format!("Couldn't parse log level '{}': {}", s, e))
})?))
} else {
Ok(None)
}
}
impl ConfigFile {
pub fn read(mut config_file_path: Option<PathBuf>) -> Result<ConfigFile, ConfigError> {
if config_file_path.is_none() {
let base_dirs = BaseDirectories::with_prefix("socks5")?;
let proposed_path = base_dirs.get_config_home();
if let Ok(attributes) = fs::metadata(proposed_path.clone()) {
if attributes.is_file() {
config_file_path = Some(proposed_path);
}
}
}
match config_file_path {
None => Ok(ConfigFile::default()),
Some(path) => {
let content = fs::read(path)?;
Ok(toml::from_slice(&content)?)
}
}
}
}