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-23 03:19:56 +00:00
|
|
|
use log::{debug, 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;
|
2021-03-23 03:19:56 +00:00
|
|
|
debug!("Sending ping!");
|
2021-03-18 01:45:16 +00:00
|
|
|
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,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|