Use unstable options
This commit is contained in:
parent
316e69851e
commit
6da2cba78a
4 changed files with 110 additions and 26 deletions
|
@ -1,6 +1,9 @@
|
||||||
use std::num::{NonZeroU16, NonZeroU64};
|
use std::{fmt::Display, path::PathBuf};
|
||||||
use std::path::PathBuf;
|
use std::{fmt::Formatter, sync::atomic::AtomicBool};
|
||||||
use std::sync::atomic::AtomicBool;
|
use std::{
|
||||||
|
num::{NonZeroU16, NonZeroU64},
|
||||||
|
str::FromStr,
|
||||||
|
};
|
||||||
|
|
||||||
use clap::{crate_authors, crate_description, crate_version, Clap};
|
use clap::{crate_authors, crate_description, crate_version, Clap};
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
@ -43,7 +46,6 @@ pub struct CliArgs {
|
||||||
short,
|
short,
|
||||||
long,
|
long,
|
||||||
conflicts_with("memory-quota"),
|
conflicts_with("memory-quota"),
|
||||||
conflicts_with("use-lfu"),
|
|
||||||
env = "LOW_MEMORY_MODE",
|
env = "LOW_MEMORY_MODE",
|
||||||
takes_value = false
|
takes_value = false
|
||||||
)]
|
)]
|
||||||
|
@ -57,16 +59,46 @@ pub struct CliArgs {
|
||||||
/// respectively.
|
/// respectively.
|
||||||
#[clap(short, long, parse(from_occurrences), conflicts_with = "verbose")]
|
#[clap(short, long, parse(from_occurrences), conflicts_with = "verbose")]
|
||||||
pub quiet: usize,
|
pub quiet: usize,
|
||||||
/// Overrides the upstream URL to fetch images from. Don't use this unless
|
#[clap(short = 'Z', long)]
|
||||||
/// you know what you're dealing with.
|
pub unstable_options: Vec<UnstableOptions>,
|
||||||
#[clap(long)]
|
#[clap(long)]
|
||||||
pub override_upstream: Option<Url>,
|
pub override_upstream: Option<Url>,
|
||||||
/// Disables token validation. Don't use this unless you know the
|
}
|
||||||
/// ramifications of this command.
|
|
||||||
#[clap(long)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||||
pub disable_token_validation: bool,
|
pub enum UnstableOptions {
|
||||||
|
/// Overrides the upstream URL to fetch images from. Don't use this unless
|
||||||
|
/// you know what you're dealing with.
|
||||||
|
OverrideUpstream,
|
||||||
|
|
||||||
/// Use an LFU implementation for the in-memory cache instead of the default
|
/// Use an LFU implementation for the in-memory cache instead of the default
|
||||||
/// LRU implementation.
|
/// LRU implementation.
|
||||||
#[clap(short = 'F', long)]
|
UseLfu,
|
||||||
pub use_lfu: bool,
|
|
||||||
|
/// Disables token validation. Don't use this unless you know the
|
||||||
|
/// ramifications of this command.
|
||||||
|
DisableTokenValidation,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromStr for UnstableOptions {
|
||||||
|
type Err = &'static str;
|
||||||
|
|
||||||
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
|
match s {
|
||||||
|
"override-upstream" => Ok(Self::OverrideUpstream),
|
||||||
|
"use-lfu" => Ok(Self::UseLfu),
|
||||||
|
"disable-token-validation" => Ok(Self::DisableTokenValidation),
|
||||||
|
_ => Err("Unknown unstable option"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for UnstableOptions {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
|
Self::OverrideUpstream => write!(f, "override-upstream"),
|
||||||
|
Self::UseLfu => write!(f, "use-lfu"),
|
||||||
|
Self::DisableTokenValidation => write!(f, "disable-token-validation"),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
61
src/main.rs
61
src/main.rs
|
@ -2,13 +2,16 @@
|
||||||
// We're end users, so these is ok
|
// We're end users, so these is ok
|
||||||
#![allow(clippy::module_name_repetitions)]
|
#![allow(clippy::module_name_repetitions)]
|
||||||
|
|
||||||
use std::env::{self, VarError};
|
|
||||||
use std::hint::unreachable_unchecked;
|
|
||||||
use std::num::ParseIntError;
|
use std::num::ParseIntError;
|
||||||
use std::process;
|
use std::process;
|
||||||
use std::sync::atomic::{AtomicBool, Ordering};
|
use std::sync::atomic::{AtomicBool, Ordering};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
use std::{
|
||||||
|
env::{self, VarError},
|
||||||
|
fmt::Display,
|
||||||
|
};
|
||||||
|
use std::{error::Error, hint::unreachable_unchecked};
|
||||||
|
|
||||||
use actix_web::rt::{spawn, time, System};
|
use actix_web::rt::{spawn, time, System};
|
||||||
use actix_web::web::{self, Data};
|
use actix_web::web::{self, Data};
|
||||||
|
@ -24,8 +27,11 @@ use state::{RwLockServerState, ServerState};
|
||||||
use stop::send_stop;
|
use stop::send_stop;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
use crate::cache::{MemoryLfuCache, MemoryLruCache};
|
|
||||||
use crate::state::DynamicServerCert;
|
use crate::state::DynamicServerCert;
|
||||||
|
use crate::{
|
||||||
|
cache::{MemoryLfuCache, MemoryLruCache},
|
||||||
|
config::UnstableOptions,
|
||||||
|
};
|
||||||
|
|
||||||
mod cache;
|
mod cache;
|
||||||
mod config;
|
mod config;
|
||||||
|
@ -50,7 +56,7 @@ enum ServerError {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[actix_web::main]
|
#[actix_web::main]
|
||||||
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
async fn main() -> Result<(), Box<dyn Error>> {
|
||||||
// It's ok to fail early here, it would imply we have a invalid config.
|
// It's ok to fail early here, it would imply we have a invalid config.
|
||||||
dotenv::dotenv().ok();
|
dotenv::dotenv().ok();
|
||||||
let cli_args = CliArgs::parse();
|
let cli_args = CliArgs::parse();
|
||||||
|
@ -60,7 +66,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let disk_quota = cli_args.disk_quota;
|
let disk_quota = cli_args.disk_quota;
|
||||||
let cache_path = cli_args.cache_path.clone();
|
let cache_path = cli_args.cache_path.clone();
|
||||||
let low_mem_mode = cli_args.low_memory;
|
let low_mem_mode = cli_args.low_memory;
|
||||||
let use_lfu = cli_args.use_lfu;
|
let use_lfu = cli_args.unstable_options.contains(&UnstableOptions::UseLfu);
|
||||||
|
|
||||||
let log_level = match (cli_args.quiet, cli_args.verbose) {
|
let log_level = match (cli_args.quiet, cli_args.verbose) {
|
||||||
(n, _) if n > 2 => LevelFilter::Off,
|
(n, _) if n > 2 => LevelFilter::Off,
|
||||||
|
@ -74,7 +80,10 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
|
||||||
SimpleLogger::new().with_level(log_level).init()?;
|
SimpleLogger::new().with_level(log_level).init()?;
|
||||||
|
|
||||||
print_preamble_and_warnings();
|
if let Err(e) = print_preamble_and_warnings(&cli_args) {
|
||||||
|
error!("{}", e);
|
||||||
|
return Err(e);
|
||||||
|
}
|
||||||
|
|
||||||
let client_secret = if let Ok(v) = env::var("CLIENT_SECRET") {
|
let client_secret = if let Ok(v) = env::var("CLIENT_SECRET") {
|
||||||
v
|
v
|
||||||
|
@ -163,7 +172,28 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_preamble_and_warnings() {
|
#[derive(Debug)]
|
||||||
|
enum InvalidCombination {
|
||||||
|
MissingUnstableOption(&'static str, UnstableOptions),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for InvalidCombination {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
|
InvalidCombination::MissingUnstableOption(opt, arg) => {
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"The option '{}' requires the unstable option '-Z {}'",
|
||||||
|
opt, arg
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Error for InvalidCombination {}
|
||||||
|
|
||||||
|
fn print_preamble_and_warnings(args: &CliArgs) -> Result<(), Box<dyn Error>> {
|
||||||
println!(concat!(
|
println!(concat!(
|
||||||
env!("CARGO_PKG_NAME"),
|
env!("CARGO_PKG_NAME"),
|
||||||
" ",
|
" ",
|
||||||
|
@ -186,4 +216,21 @@ fn print_preamble_and_warnings() {
|
||||||
env!("CARGO_PKG_NAME"),
|
env!("CARGO_PKG_NAME"),
|
||||||
". If not, see <https://www.gnu.org/licenses/>.\n"
|
". If not, see <https://www.gnu.org/licenses/>.\n"
|
||||||
));
|
));
|
||||||
|
|
||||||
|
if !args.unstable_options.is_empty() {
|
||||||
|
warn!("Unstable options are enabled. These options should not be used in production!");
|
||||||
|
}
|
||||||
|
|
||||||
|
if args.override_upstream.is_some()
|
||||||
|
&& !args
|
||||||
|
.unstable_options
|
||||||
|
.contains(&UnstableOptions::OverrideUpstream)
|
||||||
|
{
|
||||||
|
Err(Box::new(InvalidCombination::MissingUnstableOption(
|
||||||
|
"override-upstream",
|
||||||
|
UnstableOptions::OverrideUpstream,
|
||||||
|
)))
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,12 +11,12 @@ use serde::{Deserialize, Serialize};
|
||||||
use sodiumoxide::crypto::box_::PrecomputedKey;
|
use sodiumoxide::crypto::box_::PrecomputedKey;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
use crate::client_api_version;
|
|
||||||
use crate::config::{CliArgs, VALIDATE_TOKENS};
|
use crate::config::{CliArgs, VALIDATE_TOKENS};
|
||||||
use crate::state::{
|
use crate::state::{
|
||||||
RwLockServerState, PREVIOUSLY_COMPROMISED, PREVIOUSLY_PAUSED, TLS_CERTS,
|
RwLockServerState, PREVIOUSLY_COMPROMISED, PREVIOUSLY_PAUSED, TLS_CERTS,
|
||||||
TLS_PREVIOUSLY_CREATED, TLS_SIGNING_KEY,
|
TLS_PREVIOUSLY_CREATED, TLS_SIGNING_KEY,
|
||||||
};
|
};
|
||||||
|
use crate::{client_api_version, config::UnstableOptions};
|
||||||
|
|
||||||
pub const CONTROL_CENTER_PING_URL: &str = "https://api.mangadex.network/ping";
|
pub const CONTROL_CENTER_PING_URL: &str = "https://api.mangadex.network/ping";
|
||||||
|
|
||||||
|
@ -170,7 +170,9 @@ pub async fn update_server_state(secret: &str, cli: &CliArgs, data: &mut Arc<RwL
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !cli.disable_token_validation
|
if !cli
|
||||||
|
.unstable_options
|
||||||
|
.contains(&UnstableOptions::DisableTokenValidation)
|
||||||
&& VALIDATE_TOKENS.load(Ordering::Acquire) != resp.force_tokens
|
&& VALIDATE_TOKENS.load(Ordering::Acquire) != resp.force_tokens
|
||||||
{
|
{
|
||||||
if resp.force_tokens {
|
if resp.force_tokens {
|
||||||
|
|
13
src/state.rs
13
src/state.rs
|
@ -1,6 +1,6 @@
|
||||||
use std::sync::atomic::{AtomicBool, Ordering};
|
use std::sync::atomic::{AtomicBool, Ordering};
|
||||||
|
|
||||||
use crate::config::{CliArgs, SEND_SERVER_VERSION, VALIDATE_TOKENS};
|
use crate::config::{CliArgs, UnstableOptions, SEND_SERVER_VERSION, VALIDATE_TOKENS};
|
||||||
use crate::ping::{Request, Response, CONTROL_CENTER_PING_URL};
|
use crate::ping::{Request, Response, CONTROL_CENTER_PING_URL};
|
||||||
use arc_swap::ArcSwap;
|
use arc_swap::ArcSwap;
|
||||||
use log::{error, info, warn};
|
use log::{error, info, warn};
|
||||||
|
@ -90,7 +90,10 @@ impl ServerState {
|
||||||
|
|
||||||
info!("This client's URL has been set to {}", resp.url);
|
info!("This client's URL has been set to {}", resp.url);
|
||||||
|
|
||||||
if config.disable_token_validation {
|
if config
|
||||||
|
.unstable_options
|
||||||
|
.contains(&UnstableOptions::DisableTokenValidation)
|
||||||
|
{
|
||||||
warn!("Token validation is explicitly disabled!");
|
warn!("Token validation is explicitly disabled!");
|
||||||
} else {
|
} else {
|
||||||
if resp.force_tokens {
|
if resp.force_tokens {
|
||||||
|
@ -116,17 +119,17 @@ impl ServerState {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
warn!("Got malformed response: {}", e);
|
error!("Got malformed response: {}. Is MangaDex@Home down?", e);
|
||||||
Err(ServerInitError::MalformedResponse(e))
|
Err(ServerInitError::MalformedResponse(e))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Err(e) => match e {
|
Err(e) => match e {
|
||||||
e if e.is_timeout() => {
|
e if e.is_timeout() => {
|
||||||
error!("Response timed out to control server. Is MangaDex down?");
|
error!("Response timed out to control server. Is MangaDex@Home down?");
|
||||||
Err(ServerInitError::Timeout(e))
|
Err(ServerInitError::Timeout(e))
|
||||||
}
|
}
|
||||||
e => {
|
e => {
|
||||||
warn!("Failed to send request: {}", e);
|
error!("Failed to send request: {}", e);
|
||||||
Err(ServerInitError::SendFailure(e))
|
Err(ServerInitError::SendFailure(e))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in a new issue