[code] restructured into different crates

This commit is contained in:
2024-11-08 10:05:24 +01:00
parent 70e3aaea17
commit 04a39790b8
11 changed files with 202 additions and 301 deletions

View File

@ -0,0 +1,16 @@
[package]
name = "lanspread-server"
version = "0.1.0"
edition = "2021"
[dependencies]
# local
lanspread-db = { path = "../lanspread-db" }
# external
bytes = { workspace = true }
eyre = { workspace = true }
itertools = { workspace = true }
s2n-quic = { workspace = true }
serde_json = { workspace = true }
semver = { workspace = true }
tokio = { workspace = true }

View File

@ -0,0 +1,116 @@
use std::{net::SocketAddr, path::PathBuf, sync::Arc};
use bytes::Bytes;
use itertools::Itertools as _;
use lanspread_db::GameDB;
use s2n_quic::Server as QuicServer;
use tokio::sync::Mutex;
static KEY_PEM: &str = include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/../../key.pem"));
static CERT_PEM: &str = include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/../../cert.pem"));
const SERVER_ADDR: &str = "0.0.0.0";
const SERVER_PORT: u16 = 13337;
pub(crate) struct Server {
pub(crate) db: Arc<Mutex<GameDB>>,
db_path: PathBuf,
}
impl Server {
pub(crate) fn new<S: Into<PathBuf>>(db_path: S) -> Self {
let db_path = db_path.into();
let db = Arc::new(Mutex::new(GameDB::load_from_file(&db_path).unwrap()));
Server { db, db_path }
}
pub(crate) async fn run(&mut self, addr: SocketAddr) -> eyre::Result<()> {
let mut server = QuicServer::builder()
.with_tls((CERT_PEM, KEY_PEM))?
.with_io(addr)?
.start()?;
let db = self.db.clone();
while let Some(mut connection) = server.accept().await {
// spawn a new task for the connection
let db = db.clone();
tokio::spawn(async move {
eprintln!("Connection accepted from {:?}", connection.remote_addr());
while let Ok(Some(mut stream)) = connection.accept_bidirectional_stream().await {
// spawn a new task for the stream
let db = db.clone();
tokio::spawn(async move {
eprintln!("Stream opened from {:?}", stream.connection().remote_addr());
// echo any data back to the stream
while let Ok(Some(data)) = stream.receive().await {
eprintln!("got data from client: {data:?}");
if data.as_ref() == b"get_games" {
let games_vec: Vec<_> =
db.lock().await.games.values().cloned().collect();
let json = serde_json::to_string(&games_vec).unwrap();
stream.send(Bytes::from(json)).await.unwrap();
}
}
});
}
});
}
Ok(())
}
}
fn generate_test_db<P: Into<PathBuf>>(db_path: P) {
let db_path = db_path.into();
let mut db = GameDB::new();
db.add_game(
"Call of Duty 3",
"A shooter game in war.",
"call_of_duty.tar.zst",
64,
semver::Version::new(1, 0, 0),
);
db.add_game(
"Counter-Strike Source",
"Valve's iconic shooter.",
"cstrike.tar.zst",
32,
semver::Version::new(1, 0, 0),
);
db.add_game(
"Factorio",
"Best game of all time, seriously.",
"factorio.tar.zst",
128,
semver::Version::new(1, 0, 0),
);
db.update_game(1, Some("Call of Duty 4"), None, None);
db.save_to_file(&db_path).unwrap();
}
const GAME_DB_PATH: &str = "/home/pfs/shm/game.db";
#[tokio::main]
async fn main() {
generate_test_db(GAME_DB_PATH);
let mut server = Server::new(GAME_DB_PATH);
server
.db
.lock()
.await
.list_games()
.iter()
.sorted()
.for_each(|game| println!("{game:?}"));
server
.run(format!("{SERVER_ADDR}:{SERVER_PORT}").parse().unwrap())
.await
.unwrap();
}