diff options
author | metamuffin <metamuffin@disroot.org> | 2025-01-04 22:52:42 +0100 |
---|---|---|
committer | metamuffin <metamuffin@disroot.org> | 2025-01-04 22:52:42 +0100 |
commit | 2707f03617478e2a5e521961c46c9c6511d5088d (patch) | |
tree | a3516660f36614b006ea44eecf92bb4ff709fa3b /server/src | |
parent | 2c1d8fdfd65ceb9361114f0105c23ff6a94bac2e (diff) | |
download | weareserver-2707f03617478e2a5e521961c46c9c6511d5088d.tar weareserver-2707f03617478e2a5e521961c46c9c6511d5088d.tar.bz2 weareserver-2707f03617478e2a5e521961c46c9c6511d5088d.tar.zst |
a
Diffstat (limited to 'server/src')
-rw-r--r-- | server/src/main.rs | 129 |
1 files changed, 127 insertions, 2 deletions
diff --git a/server/src/main.rs b/server/src/main.rs index e7a11a9..02ea03f 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -1,3 +1,128 @@ -fn main() { - println!("Hello, world!"); +use anyhow::Result; +use clap::Parser; +use log::{debug, info}; +use std::{ + collections::HashMap, + io::{BufReader, BufWriter}, + net::{IpAddr, TcpListener, TcpStream}, + sync::{ + Arc, Mutex, + mpsc::{Receiver, Sender, channel}, + }, + thread::spawn, +}; +use weareshared::{packets::Packet, store::ResourceStore, tree::SceneTree}; + +#[derive(Parser, Debug)] +struct Args { + #[arg(short, long, default_value = "::0")] + bind_addr: IpAddr, + #[arg(short, long, default_value = "28555")] + port: u16, +} + +struct State { + tx: HashMap<usize, Sender<Packet>>, + store: ResourceStore, + tree: SceneTree, +} + +fn main() -> Result<()> { + env_logger::init_from_env("LOG"); + let args = Args::parse(); + + let listener = TcpListener::bind((args.bind_addr, args.port))?; + info!("bound to {}", listener.local_addr()?); + let state = Arc::new(Mutex::new(State::new()?)); + for conn in 0.. { + let (sock, addr) = listener.accept()?; + info!("{addr} connected"); + let (tx, rx) = channel(); + state.lock().unwrap().tx.insert(conn, tx); + let state2 = state.clone(); + let sock2 = sock.try_clone().unwrap(); + spawn(move || { + let _ = handle_conn_read(conn, sock, state2.clone()); + info!("{addr} disconnected"); + state2.lock().unwrap().tx.remove(&conn); + }); + spawn(move || { + let _ = handle_conn_write(conn, sock2, rx); + }); + } + Ok(()) +} + +fn handle_conn_read(conn: usize, sock: TcpStream, state: Arc<Mutex<State>>) -> Result<()> { + let mut sock = BufReader::new(sock); + loop { + let packet = Packet::deserialize(&mut sock)?; + debug!("{conn} <- {packet:?}"); + state.lock().unwrap().handle_packet(conn, packet)?; + } +} +fn handle_conn_write(conn: usize, sock: TcpStream, rx: Receiver<Packet>) -> Result<()> { + let mut sock = BufWriter::new(sock); + for packet in rx { + debug!("{conn} -> {packet:?}"); + packet.serialize(&mut sock)?; + } + Ok(()) +} +impl State { + pub fn new() -> Result<Self> { + Ok(Self { + tx: HashMap::new(), + store: ResourceStore::new( + &xdg::BaseDirectories::with_prefix("weareserver")?.place_cache_file("resources")?, + )?, + tree: SceneTree::default(), + }) + } + pub fn broadcast(&self, packet: Packet) -> Result<()> { + for tx in self.tx.values() { + tx.send(packet.clone())?; + } + Ok(()) + } + pub fn send(&self, conn: usize, packet: Packet) -> Result<()> { + if let Some(tx) = self.tx.get(&conn) { + tx.send(packet)?; + } + Ok(()) + } + pub fn handle_packet(&mut self, conn: usize, packet: Packet) -> Result<()> { + self.tree.update(&packet); + match packet { + Packet::RequestResource(resource) => { + if let Some(r) = self.store.get(resource)? { + self.send(conn, Packet::RespondResource(resource, r))?; + } else { + self.broadcast(Packet::RequestResource(resource))?; + } + } + Packet::RespondResource(resource, vec) => { + self.broadcast(Packet::RespondResource(resource, vec))?; + } + Packet::Add(object, resource) => { + self.broadcast(Packet::Add(object, resource))?; + } + Packet::Remove(object) => { + self.broadcast(Packet::Remove(object))?; + } + Packet::Position(object, pos, rot) => { + self.broadcast(Packet::Position(object, pos, rot))?; + } + Packet::Pose(object, vec) => { + self.broadcast(Packet::Pose(object, vec))?; + } + Packet::Parent(parent, child) => { + self.broadcast(Packet::Parent(parent, child))?; + } + Packet::Sound(object, vec) => { + self.broadcast(Packet::Sound(object, vec))?; + } + } + Ok(()) + } } |