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 = 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 { // build games from ETI database let mut games: Vec = 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 }