mirror of
https://github.com/oxen-io/session-open-group-server.git
synced 2023-12-13 20:30:35 +01:00
162 lines
5.9 KiB
Rust
162 lines
5.9 KiB
Rust
#![allow(clippy::needless_return, clippy::upper_case_acronyms)]
|
|
|
|
use parking_lot::RwLock;
|
|
use std::fs;
|
|
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
|
|
use std::{
|
|
collections::HashMap,
|
|
sync::atomic::{AtomicBool, AtomicU16, Ordering},
|
|
};
|
|
|
|
use futures::join;
|
|
use log::info;
|
|
use structopt::StructOpt;
|
|
use warp::Filter;
|
|
|
|
mod crypto;
|
|
mod errors;
|
|
mod handlers;
|
|
mod logging;
|
|
mod models;
|
|
mod onion_requests;
|
|
mod options;
|
|
mod routes;
|
|
mod rpc;
|
|
mod storage;
|
|
|
|
#[cfg(test)]
|
|
mod tests;
|
|
|
|
const LOCALHOST_PORT: u16 = 3030;
|
|
|
|
lazy_static::lazy_static! {
|
|
|
|
pub static ref USES_TLS: AtomicBool = AtomicBool::new(false);
|
|
pub static ref PORT: AtomicU16 = AtomicU16::new(0);
|
|
pub static ref HEX_PUBLIC_KEY: RwLock<String> = RwLock::new("".to_string());
|
|
}
|
|
|
|
#[tokio::main]
|
|
async fn main() {
|
|
// Parse arguments
|
|
let opt = options::Opt::from_args();
|
|
if opt.add_room.is_some()
|
|
|| opt.delete_room.is_some()
|
|
|| opt.add_moderator.is_some()
|
|
|| opt.delete_moderator.is_some()
|
|
|| opt.print_url
|
|
{
|
|
// Run in command mode
|
|
execute_commands(opt).await;
|
|
} else {
|
|
// Store the port and TLS mode
|
|
PORT.store(opt.port, Ordering::SeqCst);
|
|
USES_TLS.store(opt.tls, Ordering::SeqCst);
|
|
// Run in server mode
|
|
logging::init(opt.log_file, opt.log_level);
|
|
let addr = SocketAddr::new(IpAddr::V4(opt.host), opt.port);
|
|
let localhost = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), LOCALHOST_PORT);
|
|
*crypto::PRIVATE_KEY_PATH.lock().unwrap() = opt.x25519_private_key;
|
|
*crypto::PUBLIC_KEY_PATH.lock().unwrap() = opt.x25519_public_key;
|
|
// Print the server URL
|
|
let hex_public_key = hex::encode(crypto::PUBLIC_KEY.as_bytes());
|
|
*HEX_PUBLIC_KEY.write() = hex_public_key;
|
|
info!("Users can join rooms on this open group server using the following URL format:");
|
|
info!("{}", get_url());
|
|
// Create the main database
|
|
storage::create_database_if_needed();
|
|
// Create required folders
|
|
fs::create_dir_all("./files").unwrap();
|
|
// Set up pruning jobs
|
|
let db_maintenance_future = storage::db_maintenance_job();
|
|
// Serve routes
|
|
let public_routes = routes::root().or(routes::fallback()).or(routes::lsrpc());
|
|
let private_routes = routes::create_room()
|
|
.or(routes::delete_room())
|
|
.or(routes::add_moderator())
|
|
.or(routes::delete_moderator())
|
|
.or(routes::get_room_stats())
|
|
.or(routes::get_url());
|
|
if opt.tls {
|
|
info!("Running on {} with TLS.", addr);
|
|
let serve_public_routes_future = warp::serve(public_routes)
|
|
.tls()
|
|
.cert_path(opt.tls_certificate)
|
|
.key_path(opt.tls_private_key)
|
|
.run(addr);
|
|
let serve_private_routes_future = warp::serve(private_routes).run(localhost);
|
|
// Keep futures alive
|
|
join!(
|
|
db_maintenance_future,
|
|
serve_public_routes_future,
|
|
serve_private_routes_future
|
|
);
|
|
} else {
|
|
info!("Running on {}.", addr);
|
|
let serve_public_routes_future = warp::serve(public_routes).run(addr);
|
|
let serve_private_routes_future = warp::serve(private_routes).run(localhost);
|
|
// Keep futures alive
|
|
join!(
|
|
db_maintenance_future,
|
|
serve_public_routes_future,
|
|
serve_private_routes_future
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
async fn execute_commands(opt: options::Opt) {
|
|
let client = reqwest::Client::new();
|
|
let localhost = format!("http://127.0.0.1:{}", LOCALHOST_PORT);
|
|
// Add a room
|
|
if let Some(args) = opt.add_room {
|
|
let mut params = HashMap::new();
|
|
params.insert("token", &args[0]);
|
|
params.insert("name", &args[1]);
|
|
client.post(format!("{}/rooms", localhost)).json(¶ms).send().await.unwrap();
|
|
println!("Added room with ID: {}", &args[0]);
|
|
}
|
|
// Delete a room
|
|
if let Some(args) = opt.delete_room {
|
|
client.delete(format!("{}/rooms/{}", localhost, args)).send().await.unwrap();
|
|
println!("Deleted room with ID: {}", &args);
|
|
}
|
|
// Add a moderator
|
|
if let Some(args) = opt.add_moderator {
|
|
// FIXME: need to add an ability to add an admin instead of moderator (by setting the "admin" param to true)
|
|
let mut params = HashMap::new();
|
|
params.insert("public_key", &args[0]);
|
|
params.insert("room_id", &args[1]);
|
|
client.post(format!("{}/moderators", localhost)).json(¶ms).send().await.unwrap();
|
|
println!("Added moderator: {} to room with ID: {}", &args[0], &args[1]);
|
|
}
|
|
// Delete a moderator
|
|
if let Some(args) = opt.delete_moderator {
|
|
let mut params = HashMap::new();
|
|
params.insert("public_key", &args[0]);
|
|
params.insert("room_id", &args[1]);
|
|
client.post(format!("{}/delete_moderator", localhost)).json(¶ms).send().await.unwrap();
|
|
println!("Deleted moderator: {} from room with ID: {}", &args[0], &args[1]);
|
|
}
|
|
// Print URL
|
|
if opt.print_url {
|
|
let response =
|
|
client.get(format!("{}/url", localhost)).send().await.unwrap().text().await.unwrap();
|
|
println!("Users can join rooms on this open group server using the following URL format:");
|
|
println!("{}", response);
|
|
}
|
|
}
|
|
|
|
fn get_url() -> String {
|
|
let uses_tls: bool = USES_TLS.load(Ordering::SeqCst);
|
|
let port: u16 = PORT.load(Ordering::SeqCst);
|
|
let hex_public_key: &str = &*HEX_PUBLIC_KEY.read();
|
|
let protocol = if uses_tls { "https" } else { "http" };
|
|
let is_port_implicit = (port == 80 && !uses_tls) || (port == 443 && uses_tls);
|
|
return format!(
|
|
"{}://[host_name_or_ip]{}/[room_id]?public_key={}",
|
|
protocol,
|
|
if is_port_implicit { "".to_string() } else { format!(":{}", port) },
|
|
hex_public_key
|
|
);
|
|
}
|