//! Contains the necessary ingredients to start a graf karto world server. use crate::net::server::ConnectionManager; use crate::net::Cargo; use crate::world::World; use std::io; use std::net::{Ipv4Addr, Ipv6Addr, SocketAddr}; use std::thread::{self, JoinHandle}; /// The default port the dedicated graf karto server runs on. pub const DEFAULT_PORT: u16 = 44309; fn localhost(port: u16, ipv4: bool) -> SocketAddr { if ipv4 { SocketAddr::new(Ipv4Addr::LOCALHOST.into(), port) } else { SocketAddr::new(Ipv6Addr::LOCALHOST.into(), port) } } /// Starts a thread for the server and tries to bind to the specified port. If the /// port cannot be bound to it fails returning an error, otherwise the join handle /// for the server thread is returned. pub fn start_with_port(port: u16, ipv4: bool) -> Result, io::Error> { let addr = localhost(port, ipv4); let conn_man = ConnectionManager::start(addr)?; Ok(start(conn_man)) } /// Starts a thread on any free system port. Returns an error in case that's not /// possible. pub fn start_any_port(ipv4: bool) -> Result<(JoinHandle<()>, u16), io::Error> { let addr = localhost(0, ipv4); let conn_man = ConnectionManager::start(addr)?; let port = conn_man.port(); Ok((start(conn_man), port)) } fn start(conn_man: ConnectionManager) -> JoinHandle<()> { info!("Server started on port {}", conn_man.port()); let mut world = World::new(); thread::spawn(move || loop { if let Some((user, cargo)) = conn_man.next_packet() { match cargo { Cargo::AddRoom(room) => { let room_id = world.push_room(room.clone()); conn_man.broadcast(Cargo::SetRoom((room_id, room))); } other => error!("Unknown packet received from `{}`: {:?}", user, other), } } }) }