119 lines
3.1 KiB
Rust
119 lines
3.1 KiB
Rust
use mimalloc::MiMalloc;
|
|
|
|
#[global_allocator]
|
|
static GLOBAL: MiMalloc = MiMalloc;
|
|
|
|
mod cli;
|
|
mod quic;
|
|
mod req;
|
|
|
|
use std::{convert::Into, net::SocketAddr, time::Duration};
|
|
|
|
use chrono::{DateTime, Local};
|
|
use clap::Parser as _;
|
|
use cli::Cli;
|
|
use gethostname::gethostname;
|
|
use lanspread_compat::eti;
|
|
use lanspread_db::db::{Game, GameDB};
|
|
use lanspread_mdns::{
|
|
DaemonEvent,
|
|
LANSPREAD_INSTANCE_NAME,
|
|
LANSPREAD_SERVICE_TYPE,
|
|
MdnsAdvertiser,
|
|
};
|
|
use tracing_subscriber::EnvFilter;
|
|
use uuid::Uuid;
|
|
|
|
fn spawn_mdns_task(server_addr: SocketAddr) -> eyre::Result<()> {
|
|
let combined_str = if 1 == 2 {
|
|
let peer_id = Uuid::now_v7().simple().to_string();
|
|
|
|
let uidddd = Uuid::now_v7();
|
|
|
|
// TODO
|
|
let uidddd = uidddd
|
|
.get_timestamp()
|
|
.expect("failed to get timestamp from UUID")
|
|
.to_unix();
|
|
|
|
let local_datetime: DateTime<Local> =
|
|
DateTime::from_timestamp(i64::try_from(uidddd.0).unwrap_or(0), uidddd.1)
|
|
.expect("Failed to create DateTime from uuid unix timestamp")
|
|
.into();
|
|
|
|
dbg!(local_datetime);
|
|
|
|
let hostname = gethostname();
|
|
let mut hostname = hostname.to_str().unwrap_or("");
|
|
|
|
if hostname.len() + peer_id.len() > 63 {
|
|
hostname = &hostname[..63 - peer_id.len()];
|
|
}
|
|
format!("{hostname}-{peer_id}")
|
|
} else {
|
|
String::from(LANSPREAD_INSTANCE_NAME)
|
|
};
|
|
|
|
let mdns = MdnsAdvertiser::new(LANSPREAD_SERVICE_TYPE, &combined_str, server_addr)?;
|
|
|
|
tokio::spawn(async move {
|
|
while let Ok(event) = mdns.monitor.recv() {
|
|
tracing::trace!("mDNS: {:?}", &event);
|
|
if let DaemonEvent::Error(e) = event {
|
|
tracing::error!("mDNS: {e}");
|
|
tokio::time::sleep(Duration::from_secs(1)).await;
|
|
}
|
|
}
|
|
});
|
|
|
|
Ok(())
|
|
}
|
|
|
|
async fn prepare_game_db(cli: &Cli) -> eyre::Result<GameDB> {
|
|
// build games from ETI database
|
|
let mut games: Vec<Game> = eti::get_games(&cli.db)
|
|
.await?
|
|
.into_iter()
|
|
.map(Into::into)
|
|
.collect();
|
|
|
|
// filter out games that the server does not have in game_dir
|
|
games.retain(|game| cli.game_dir.join(&game.id).is_dir());
|
|
|
|
let mut game_db = GameDB::from(games);
|
|
|
|
game_db.add_thumbnails(&cli.thumbs_dir);
|
|
|
|
game_db.all_games().iter().for_each(|game| {
|
|
tracing::debug!("Found game: {game}");
|
|
});
|
|
tracing::info!("Prepared game database with {} games", game_db.games.len());
|
|
|
|
Ok(game_db)
|
|
}
|
|
|
|
#[tokio::main]
|
|
async fn main() -> eyre::Result<()> {
|
|
tracing_subscriber::fmt()
|
|
.with_env_filter(EnvFilter::from_default_env())
|
|
.init();
|
|
|
|
let cli = Cli::parse();
|
|
|
|
assert!(
|
|
cli.game_dir.exists(),
|
|
"Games folder does not exist: {}",
|
|
cli.game_dir.to_str().expect("Invalid path")
|
|
);
|
|
|
|
let server_addr = SocketAddr::from((cli.ip, cli.port));
|
|
|
|
// spawn mDNS listener task
|
|
spawn_mdns_task(server_addr)?;
|
|
|
|
let game_db = prepare_game_db(&cli).await?;
|
|
|
|
tracing::info!("Server listening on {server_addr}");
|
|
crate::quic::run_server(server_addr, game_db, cli.game_dir).await
|
|
}
|