[code] restructured into different crates
This commit is contained in:
16
crates/lanspread-server/Cargo.toml
Normal file
16
crates/lanspread-server/Cargo.toml
Normal 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 }
|
116
crates/lanspread-server/src/main.rs
Normal file
116
crates/lanspread-server/src/main.rs
Normal 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();
|
||||
}
|
Reference in New Issue
Block a user