mirror of
https://github.com/oxen-io/session-open-group-server.git
synced 2023-12-13 20:30:35 +01:00
This is obnoxious because it is *impossible* to get rid of the room without it getting recreated at every restart. Note: this breaks file server mode, but that's okay, the DB refactor completely breaks it anyway, and current version will work fine for the global file server.
171 lines
6.2 KiB
Rust
171 lines
6.2 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);
|
|
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_main_database_if_needed();
|
|
// Create required folders
|
|
fs::create_dir_all("./rooms").unwrap();
|
|
fs::create_dir_all("./files").unwrap();
|
|
// Perform migration
|
|
storage::perform_migration();
|
|
// Set up pruning jobs
|
|
let prune_pending_tokens_future = storage::prune_pending_tokens_periodically();
|
|
let prune_tokens_future = storage::prune_tokens_periodically();
|
|
let prune_files_future = storage::prune_files_periodically();
|
|
// 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!(
|
|
prune_pending_tokens_future,
|
|
prune_tokens_future,
|
|
prune_files_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!(
|
|
prune_pending_tokens_future,
|
|
prune_tokens_future,
|
|
prune_files_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("id", &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 {
|
|
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
|
|
);
|
|
}
|