mangadex-home-rs/src/main.rs

135 lines
3.7 KiB
Rust
Raw Normal View History

2021-03-18 01:45:16 +00:00
#![warn(clippy::pedantic, clippy::nursery)]
2021-03-23 00:00:21 +00:00
// We're end users, so these is ok
#![allow(clippy::future_not_send, clippy::module_name_repetitions)]
2021-03-18 01:45:16 +00:00
use std::env::{self, VarError};
2021-03-22 21:47:56 +00:00
use std::path::PathBuf;
use std::sync::atomic::AtomicBool;
use std::sync::Arc;
2021-03-18 01:45:16 +00:00
use std::time::Duration;
2021-03-22 21:47:56 +00:00
use std::{num::ParseIntError, sync::atomic::Ordering};
2021-03-18 01:45:16 +00:00
2021-03-22 21:47:56 +00:00
use actix_web::rt::{spawn, time, System};
2021-03-23 03:04:54 +00:00
use actix_web::web::{self, Data};
2021-03-18 01:45:16 +00:00
use actix_web::{App, HttpServer};
2021-03-22 21:47:56 +00:00
use log::{error, warn, LevelFilter};
2021-03-18 01:45:16 +00:00
use parking_lot::RwLock;
2021-03-22 21:47:56 +00:00
use rustls::{NoClientAuth, ServerConfig};
2021-03-18 01:45:16 +00:00
use simple_logger::SimpleLogger;
2021-03-22 21:47:56 +00:00
use state::{RwLockServerState, ServerState};
use stop::send_stop;
2021-03-18 01:45:16 +00:00
use thiserror::Error;
2021-03-22 21:47:56 +00:00
mod cache;
2021-03-18 01:45:16 +00:00
mod ping;
mod routes;
2021-03-22 21:47:56 +00:00
mod state;
2021-03-18 01:45:16 +00:00
mod stop;
#[macro_export]
macro_rules! client_api_version {
() => {
"30"
};
}
#[derive(Error, Debug)]
enum ServerError {
#[error("There was a failure parsing config")]
Config(#[from] VarError),
#[error("Failed to parse an int")]
ParseInt(#[from] ParseIntError),
}
#[actix_web::main]
async fn main() -> Result<(), std::io::Error> {
2021-03-22 21:47:56 +00:00
// It's ok to fail early here, it would imply we have a invalid config.
2021-03-18 01:45:16 +00:00
dotenv::dotenv().ok();
2021-03-22 21:47:56 +00:00
SimpleLogger::new()
.with_level(LevelFilter::Info)
.init()
.unwrap();
2021-03-18 01:45:16 +00:00
let config = Config::new().unwrap();
let port = config.port;
let server = ServerState::init(&config).await.unwrap();
2021-03-22 21:47:56 +00:00
// Set ctrl+c to send a stop message
let running = Arc::new(AtomicBool::new(true));
let r = running.clone();
let client_secret = config.secret.clone();
ctrlc::set_handler(move || {
let client_secret = client_secret.clone();
System::new().block_on(async move {
send_stop(&client_secret).await;
});
r.store(false, Ordering::SeqCst);
})
.expect("Error setting Ctrl-C handler");
2021-03-18 01:45:16 +00:00
let data_0 = Arc::new(RwLockServerState(RwLock::new(server)));
let data_1 = Arc::clone(&data_0);
let data_2 = Arc::clone(&data_0);
spawn(async move {
let mut interval = time::interval(Duration::from_secs(90));
let mut data = Arc::clone(&data_0);
loop {
interval.tick().await;
ping::update_server_state(&config, &mut data).await;
}
});
let mut tls_config = ServerConfig::new(NoClientAuth::new());
tls_config.cert_resolver = data_2;
HttpServer::new(move || {
App::new()
.service(routes::token_data)
2021-03-22 21:47:56 +00:00
.service(routes::token_data_saver)
.route("{tail:.*}", web::get().to(routes::default))
2021-03-18 01:45:16 +00:00
.app_data(Data::from(Arc::clone(&data_1)))
})
.shutdown_timeout(60)
.bind_rustls(format!("0.0.0.0:{}", port), tls_config)?
.run()
2021-03-22 21:47:56 +00:00
.await?;
// Waiting for us to finish sending stop message
while running.load(Ordering::SeqCst) {
std::thread::sleep(Duration::from_millis(250));
}
Ok(())
2021-03-18 01:45:16 +00:00
}
2021-03-18 02:41:48 +00:00
pub struct Config {
2021-03-18 01:45:16 +00:00
secret: String,
port: u16,
2021-03-22 21:47:56 +00:00
memory_quota: usize,
2021-03-18 01:45:16 +00:00
disk_quota: usize,
2021-03-22 21:47:56 +00:00
disk_path: PathBuf,
2021-03-18 01:45:16 +00:00
network_speed: usize,
}
impl Config {
fn new() -> Result<Self, ServerError> {
let secret = env::var("CLIENT_SECRET")?;
2021-03-22 21:47:56 +00:00
let port = env::var("PORT")?.parse()?;
let disk_quota = env::var("DISK_CACHE_QUOTA_BYTES")?.parse()?;
let memory_quota = env::var("MEM_CACHE_QUOTA_BYTES")?.parse()?;
let network_speed = env::var("MAX_NETWORK_SPEED")?.parse()?;
let disk_path = env::var("DISK_CACHE_PATH")
2021-03-23 00:00:21 +00:00
.unwrap_or_else(|_| "./cache".to_string())
2021-03-22 21:47:56 +00:00
.parse()
.unwrap();
2021-03-18 01:45:16 +00:00
Ok(Self {
secret,
port,
disk_quota,
2021-03-22 21:47:56 +00:00
memory_quota,
disk_path,
2021-03-18 01:45:16 +00:00
network_speed,
})
}
}