opti: Replace Arc with &'static

This commit is contained in:
Pascal Engélibert 2022-10-29 11:03:37 +02:00
parent 81681303b2
commit 0d7356ec1f
Signed by: tuxmain
GPG key ID: 3504BC6D362F7DCA
6 changed files with 61 additions and 81 deletions

7
Cargo.lock generated
View file

@ -2529,6 +2529,12 @@ dependencies = [
"version_check", "version_check",
] ]
[[package]]
name = "static-rc"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b91d0104a7b28aeda24b30919f83222570111ac0bf1aab23aaffb8f59330e654"
[[package]] [[package]]
name = "stdweb" name = "stdweb"
version = "0.4.20" version = "0.4.20"
@ -3209,6 +3215,7 @@ dependencies = [
"serde", "serde",
"sha2 0.10.6", "sha2 0.10.6",
"sled", "sled",
"static-rc",
"tera", "tera",
"tide", "tide",
"tokio", "tokio",

View file

@ -21,6 +21,7 @@ rpassword = "7.1.0"
serde = { version = "1.0.147", features = ["derive", "rc"] } serde = { version = "1.0.147", features = ["derive", "rc"] }
sha2 = "0.10.6" sha2 = "0.10.6"
sled = "0.34.7" sled = "0.34.7"
static-rc = "0.6.1"
tera = { version = "1.17.1", features = ["builtins", "date-locale"] } tera = { version = "1.17.1", features = ["builtins", "date-locale"] }
tide = { version = "0.16.0", default-features = false, features = ["h1-server", "cookies", "logger"] } tide = { version = "0.16.0", default-features = false, features = ["h1-server", "cookies", "logger"] }
tokio = { version = "1.21.2", features = ["macros", "rt-multi-thread"] } tokio = { version = "1.21.2", features = ["macros", "rt-multi-thread"] }

View file

@ -1,8 +1,8 @@
use crate::{config::Config, db::*}; use crate::{config::Config, db::*};
use std::{sync::Arc, time::Duration}; use std::time::Duration;
pub async fn run_cleaner(config: Arc<Config>, dbs: Dbs) { pub async fn run_cleaner(config: &Config, dbs: Dbs) {
let mut last_db_clean = 0; let mut last_db_clean = 0;
loop { loop {
let time = std::time::SystemTime::now() let time = std::time::SystemTime::now()
@ -11,7 +11,7 @@ pub async fn run_cleaner(config: Arc<Config>, dbs: Dbs) {
.as_secs(); .as_secs();
if time > last_db_clean + 3600 { if time > last_db_clean + 3600 {
clean_antispam(config.clone(), dbs.clone(), time); clean_antispam(config, dbs.clone(), time);
last_db_clean = time; last_db_clean = time;
} }
@ -19,7 +19,7 @@ pub async fn run_cleaner(config: Arc<Config>, dbs: Dbs) {
} }
} }
fn clean_antispam(config: Arc<Config>, dbs: Dbs, time: u64) { fn clean_antispam(config: &Config, dbs: Dbs, time: u64) {
for (addr, (last_mutation, _mutation_count)) in for (addr, (last_mutation, _mutation_count)) in
dbs.client_mutation.iter().filter_map(|o| o.ok()) dbs.client_mutation.iter().filter_map(|o| o.ok())
{ {

View file

@ -13,7 +13,6 @@ use argon2::{
Argon2, Argon2,
}; };
use clap::Parser; use clap::Parser;
use std::sync::Arc;
#[tokio::main] #[tokio::main]
async fn main() { async fn main() {
@ -25,9 +24,12 @@ async fn main() {
} }
cli::MainSubcommand::Start(subopt) => { cli::MainSubcommand::Start(subopt) => {
let (config, dbs, templates) = init_all(opt.opt, subopt); let (config, dbs, templates) = init_all(opt.opt, subopt);
let config = Arc::new(config);
let templates = Arc::new(templates); // These will never be dropped nor mutated
tokio::spawn(cleaner::run_cleaner(config.clone(), dbs.clone())); let templates = Box::leak(Box::new(templates));
let config = Box::leak(Box::new(config));
tokio::spawn(cleaner::run_cleaner(config, dbs.clone()));
server::run_server(config, dbs, templates).await; server::run_server(config, dbs, templates).await;
} }
cli::MainSubcommand::Psw => { cli::MainSubcommand::Psw => {

View file

@ -3,10 +3,7 @@ use crate::config::Config;
use crossbeam_channel::Receiver; use crossbeam_channel::Receiver;
use log::error; use log::error;
use matrix_sdk::ruma; use matrix_sdk::ruma;
use std::{ use std::time::{Duration, SystemTime};
sync::Arc,
time::{Duration, SystemTime},
};
enum OptionSince<T> { enum OptionSince<T> {
Some(T), Some(T),
@ -80,10 +77,10 @@ impl Notifier {
} }
} }
pub async fn run_notifier(config: Arc<Config>, recv: Receiver<()>) { pub async fn run_notifier(config: &Config, recv: Receiver<()>) {
let mut notifier = Notifier::new(&config).await; let mut notifier = Notifier::new(config).await;
for () in recv { for () in recv {
notifier.notify(&config).await; notifier.notify(config).await;
} }
} }

View file

@ -3,65 +3,40 @@ use crate::{config::*, db::*, helpers, queries::*, templates::*};
use argon2::{Argon2, PasswordHash, PasswordVerifier}; use argon2::{Argon2, PasswordHash, PasswordVerifier};
use crossbeam_channel::Sender; use crossbeam_channel::Sender;
use log::{error, warn}; use log::{error, warn};
use std::sync::Arc;
use tera::Context; use tera::Context;
pub async fn run_server(config: Arc<Config>, dbs: Dbs, templates: Arc<Templates>) { pub async fn run_server(config: &'static Config, dbs: Dbs, templates: &'static Templates) {
tide::log::start(); tide::log::start();
let (notify_send, notify_recv) = crossbeam_channel::bounded(10); let (notify_send, notify_recv) = crossbeam_channel::bounded(10);
tokio::spawn(crate::notify::run_notifier(config.clone(), notify_recv)); tokio::spawn(crate::notify::run_notifier(config, notify_recv));
let mut app = tide::new(); let mut app = tide::new();
app.at(&format!("{}t/:topic", config.root_url)).get({ app.at(&format!("{}t/:topic", config.root_url)).get({
let config = config.clone();
let templates = templates.clone();
let dbs = dbs.clone(); let dbs = dbs.clone();
move |req: tide::Request<()>| { move |req: tide::Request<()>| {
serve_comments( serve_comments(req, config, templates, dbs.clone(), Context::new(), 200)
req,
config.clone(),
templates.clone(),
dbs.clone(),
Context::new(),
200,
)
} }
}); });
app.at(&format!("{}t/:topic", config.root_url)).post({ app.at(&format!("{}t/:topic", config.root_url)).post({
let config = config.clone();
let templates = templates.clone();
let dbs = dbs.clone(); let dbs = dbs.clone();
move |req: tide::Request<()>| { move |req: tide::Request<()>| {
handle_post_comments( handle_post_comments(req, config, templates, dbs.clone(), notify_send.clone())
req,
config.clone(),
templates.clone(),
dbs.clone(),
notify_send.clone(),
)
} }
}); });
app.at(&format!("{}admin", config.root_url)).get({ app.at(&format!("{}admin", config.root_url))
let config = config.clone(); .get(move |req: tide::Request<()>| serve_admin_login(req, config, templates));
let templates = templates.clone();
move |req: tide::Request<()>| serve_admin_login(req, config.clone(), templates.clone())
});
app.at(&format!("{}admin", config.root_url)).post({ app.at(&format!("{}admin", config.root_url)).post({
let config = config.clone();
let templates = templates.clone();
let dbs = dbs.clone(); let dbs = dbs.clone();
move |req: tide::Request<()>| { move |req: tide::Request<()>| handle_post_admin(req, config, templates, dbs.clone())
handle_post_admin(req, config.clone(), templates.clone(), dbs.clone())
}
}); });
app.listen(config.listen).await.unwrap(); app.listen(config.listen).await.unwrap();
} }
async fn serve_comments<'a>( async fn serve_comments<'a>(
req: tide::Request<()>, req: tide::Request<()>,
config: Arc<Config>, config: &Config,
templates: Arc<Templates>, templates: &Templates,
dbs: Dbs, dbs: Dbs,
mut context: Context, mut context: Context,
status_code: u16, status_code: u16,
@ -71,7 +46,7 @@ async fn serve_comments<'a>(
}; };
let admin = req.cookie("admin").map_or(false, |psw| { let admin = req.cookie("admin").map_or(false, |psw| {
check_admin_password_hash(&config, &String::from(psw.value())) check_admin_password_hash(config, &String::from(psw.value()))
}); });
let topic_hash = TopicHash::from_topic(topic); let topic_hash = TopicHash::from_topic(topic);
@ -142,8 +117,8 @@ async fn serve_comments<'a>(
async fn serve_admin<'a>( async fn serve_admin<'a>(
_req: tide::Request<()>, _req: tide::Request<()>,
config: Arc<Config>, config: &Config,
templates: Arc<Templates>, templates: &Templates,
dbs: Dbs, dbs: Dbs,
) -> tide::Result<tide::Response> { ) -> tide::Result<tide::Response> {
let mut context = Context::new(); let mut context = Context::new();
@ -187,8 +162,8 @@ async fn serve_admin<'a>(
async fn serve_admin_login( async fn serve_admin_login(
_req: tide::Request<()>, _req: tide::Request<()>,
config: Arc<Config>, config: &Config,
templates: Arc<Templates>, templates: &Templates,
) -> tide::Result<tide::Response> { ) -> tide::Result<tide::Response> {
let mut context = Context::new(); let mut context = Context::new();
context.insert("config", &config); context.insert("config", &config);
@ -201,17 +176,17 @@ async fn serve_admin_login(
async fn handle_post_comments( async fn handle_post_comments(
mut req: tide::Request<()>, mut req: tide::Request<()>,
config: Arc<Config>, config: &Config,
templates: Arc<Templates>, templates: &Templates,
dbs: Dbs, dbs: Dbs,
notify_send: Sender<()>, notify_send: Sender<()>,
) -> tide::Result<tide::Response> { ) -> tide::Result<tide::Response> {
let admin = req.cookie("admin").map_or(false, |psw| { let admin = req.cookie("admin").map_or(false, |psw| {
check_admin_password_hash(&config, &String::from(psw.value())) check_admin_password_hash(config, &String::from(psw.value()))
}); });
let client_addr = if !admin && config.antispam_enable { let client_addr = if !admin && config.antispam_enable {
match helpers::get_client_addr(&config, &req) { match helpers::get_client_addr(config, &req) {
Some(Ok(addr)) => { Some(Ok(addr)) => {
if config.antispam_whitelist.contains(&addr) { if config.antispam_whitelist.contains(&addr) {
None None
@ -241,11 +216,11 @@ async fn handle_post_comments(
return Err(tide::Error::from_str(404, "No topic")) return Err(tide::Error::from_str(404, "No topic"))
}; };
helpers::check_comment(&config, &query.comment, &mut errors); helpers::check_comment(config, &query.comment, &mut errors);
if let Some(client_addr) = &client_addr { if let Some(client_addr) = &client_addr {
if let Some(antispam_timeout) = if let Some(antispam_timeout) =
helpers::antispam_check_client_mutation(client_addr, &dbs, &config).unwrap() helpers::antispam_check_client_mutation(client_addr, &dbs, config).unwrap()
{ {
errors.push(format!( errors.push(format!(
"The edition quota from your IP is reached. You will be unblocked in {}s.", "The edition quota from your IP is reached. You will be unblocked in {}s.",
@ -294,7 +269,7 @@ async fn handle_post_comments(
return Err(tide::Error::from_str(403, "Forbidden")); return Err(tide::Error::from_str(403, "Forbidden"));
} }
helpers::check_comment(&config, &query.comment, &mut errors); helpers::check_comment(config, &query.comment, &mut errors);
let comment_id = if let Ok(comment_id) = CommentId::from_base64(&query.id) { let comment_id = if let Ok(comment_id) = CommentId::from_base64(&query.id) {
comment_id comment_id
@ -310,7 +285,7 @@ async fn handle_post_comments(
if let Some(client_addr) = &client_addr { if let Some(client_addr) = &client_addr {
if let Some(antispam_timeout) = if let Some(antispam_timeout) =
helpers::antispam_check_client_mutation(client_addr, &dbs, &config).unwrap() helpers::antispam_check_client_mutation(client_addr, &dbs, config).unwrap()
{ {
errors.push(format!( errors.push(format!(
"The edition quota from your IP is reached. You will be unblocked in {}s.", "The edition quota from your IP is reached. You will be unblocked in {}s.",
@ -361,12 +336,12 @@ async fn handle_post_comments(
async fn handle_post_admin( async fn handle_post_admin(
mut req: tide::Request<()>, mut req: tide::Request<()>,
config: Arc<Config>, config: &Config,
templates: Arc<Templates>, templates: &Templates,
dbs: Dbs, dbs: Dbs,
) -> tide::Result<tide::Response> { ) -> tide::Result<tide::Response> {
if let Some(psw) = req.cookie("admin") { if let Some(psw) = req.cookie("admin") {
if check_admin_password(&config, &String::from(psw.value())).is_some() { if check_admin_password(config, &String::from(psw.value())).is_some() {
#[allow(clippy::match_single_binding)] #[allow(clippy::match_single_binding)]
match req.body_form::<AdminQuery>().await? { match req.body_form::<AdminQuery>().await? {
_ => serve_admin(req, config, templates, dbs).await, _ => serve_admin(req, config, templates, dbs).await,
@ -375,10 +350,8 @@ async fn handle_post_admin(
serve_admin_login(req, config, templates).await serve_admin_login(req, config, templates).await
} }
} else if let AdminQuery::Login(query) = req.body_form::<AdminQuery>().await? { } else if let AdminQuery::Login(query) = req.body_form::<AdminQuery>().await? {
if let Some(password_hash) = check_admin_password(&config, &query.psw) { if let Some(password_hash) = check_admin_password(config, &query.psw) {
serve_admin(req, config.clone(), templates, dbs) serve_admin(req, config, templates, dbs).await.map(|mut r| {
.await
.map(|mut r| {
let mut cookie = tide::http::Cookie::new("admin", password_hash); let mut cookie = tide::http::Cookie::new("admin", password_hash);
cookie.set_http_only(Some(true)); cookie.set_http_only(Some(true));
cookie.set_path(config.root_url.clone()); cookie.set_path(config.root_url.clone());