88 lines
2.2 KiB
Rust
88 lines
2.2 KiB
Rust
mod db;
|
|
mod handle;
|
|
mod net;
|
|
|
|
use crate::{
|
|
db::{Db, ServerPerms},
|
|
handle::{ClientHandler, ClientState},
|
|
};
|
|
use clap::Parser;
|
|
use net::{ClientSender, ConAccepter, listen};
|
|
use openworm::{
|
|
net::{AccountToken, ClientMsgInst, RecvHandler, install_crypto_provider},
|
|
rsc::DataDir,
|
|
};
|
|
use rand::distr::{Alphanumeric, SampleString};
|
|
use std::{
|
|
collections::HashMap,
|
|
sync::{
|
|
Arc,
|
|
atomic::{AtomicU64, Ordering},
|
|
},
|
|
};
|
|
use tokio::{signal::ctrl_c, sync::RwLock};
|
|
|
|
#[derive(Parser, Debug)]
|
|
#[command(version, about, long_about = None)]
|
|
struct Args {
|
|
/// port to listen on
|
|
#[arg(short, long)]
|
|
port: u16,
|
|
}
|
|
|
|
fn main() {
|
|
let args = Args::parse();
|
|
install_crypto_provider();
|
|
run_server(args.port);
|
|
}
|
|
|
|
#[tokio::main]
|
|
pub async fn run_server(port: u16) {
|
|
let dir = DataDir::new(Some("server"));
|
|
let db = Db::open(dir.path.join("db"));
|
|
let handler = ServerListener {
|
|
senders: Default::default(),
|
|
count: 0.into(),
|
|
db: db.clone(),
|
|
};
|
|
if db.users.is_empty() {
|
|
let token = account_token(&db, ServerPerms::ALL);
|
|
println!("no users found, token for admin: {token}");
|
|
}
|
|
let (endpoint, handle) = listen(port, &dir.path, handler);
|
|
let _ = ctrl_c().await;
|
|
println!("stopping server");
|
|
println!("closing connections...");
|
|
endpoint.close(0u32.into(), &[]);
|
|
let _ = handle.await;
|
|
endpoint.wait_idle().await;
|
|
}
|
|
|
|
pub fn account_token(db: &Db, perms: ServerPerms) -> AccountToken {
|
|
let token = Alphanumeric.sample_string(&mut rand::rng(), 16);
|
|
db.account_tokens.insert(&token, &perms);
|
|
token
|
|
}
|
|
|
|
type ClientId = u64;
|
|
|
|
struct ServerListener {
|
|
db: Db,
|
|
senders: Arc<RwLock<HashMap<ClientId, ClientSender>>>,
|
|
count: AtomicU64,
|
|
}
|
|
|
|
impl ConAccepter for ServerListener {
|
|
async fn accept(&self, send: ClientSender) -> impl RecvHandler<ClientMsgInst> {
|
|
let id = self.count.fetch_add(1, Ordering::Release);
|
|
self.senders.write().await.insert(id, send.clone());
|
|
ClientHandler {
|
|
db: self.db.clone(),
|
|
senders: self.senders.clone(),
|
|
state: Arc::new(RwLock::new(ClientState::Login)),
|
|
send,
|
|
id,
|
|
}
|
|
}
|
|
}
|