From cf67bfa4fa272bb47adecd7c738eb13e3f1e4b84 Mon Sep 17 00:00:00 2001 From: Benjamin Saunders Date: Sun, 28 Jul 2024 20:22:30 -0700 Subject: [PATCH] Use in-process server --- client/Cargo.toml | 1 - client/src/main.rs | 120 ++++++++++++++++++++++----------------------- server/src/lib.rs | 33 ++++++++----- server/src/main.rs | 4 +- 4 files changed, 80 insertions(+), 78 deletions(-) diff --git a/client/Cargo.toml b/client/Cargo.toml index 7903b7a3..0e296a8c 100644 --- a/client/Cargo.toml +++ b/client/Cargo.toml @@ -35,7 +35,6 @@ quinn = { workspace = true } futures-util = "0.3.1" webpki = "0.22.0" hecs = { workspace = true } -rcgen = { version = "0.13.1", default-features = false, features = ["ring"] } memoffset = "0.9" gltf = { version = "1.0.0", default-features = false, features = ["utils"] } metrics = "0.23.0" diff --git a/client/src/main.rs b/client/src/main.rs index 916f8372..91562552 100644 --- a/client/src/main.rs +++ b/client/src/main.rs @@ -1,15 +1,12 @@ -use std::{ - net::{SocketAddr, UdpSocket}, - sync::Arc, -}; +use std::{sync::Arc, thread}; use client::{graphics, metrics, net, Config}; -use quinn::rustls::pki_types::{CertificateDer, PrivatePkcs8KeyDer}; +use common::proto; use save::Save; use ash::khr; use server::Server; -use tracing::{error, error_span, info}; +use tracing::{debug, error, error_span, info, Instrument}; use winit::{ application::ApplicationHandler, event_loop::{ActiveEventLoop, EventLoop}, @@ -21,62 +18,58 @@ fn main() { let metrics = crate::metrics::init(); let dirs = directories::ProjectDirs::from("", "", "hypermine").unwrap(); - let mut config = Config::load(&dirs); - - if config.server.is_none() { - // spawn an in-process server - let socket = - UdpSocket::bind("[::1]:0".parse::().unwrap()).expect("binding socket"); - config.server = Some(socket.local_addr().unwrap()); - - let certified_key = rcgen::generate_simple_self_signed(vec!["localhost".into()]).unwrap(); - let key = certified_key.key_pair.serialize_der(); - let cert = certified_key.cert.der().to_vec(); - let sim_cfg = config.local_simulation.clone(); - - let save = dirs.data_local_dir().join(&config.save); - info!("using save file {}", save.display()); - std::fs::create_dir_all(save.parent().unwrap()).unwrap(); - let save = match Save::open(&save, config.local_simulation.chunk_size) { - Ok(x) => x, - Err(e) => { - error!("couldn't open save: {}", e); - return; - } - }; - - let server = match Server::new( - server::NetParams { - certificate_chain: vec![CertificateDer::from(cert)], - private_key: PrivatePkcs8KeyDer::from(key).into(), - socket, - }, - sim_cfg, - save, - ) { - Ok(server) => server, - Err(e) => { - eprintln!("{e:#}"); - std::process::exit(1); - } - }; - - std::thread::spawn(move || { - #[tokio::main(flavor = "current_thread")] - async fn run_server(server: Server) { - server.run().await; - } - - let span = error_span!("server"); - let _guard = span.enter(); - run_server(server); - }); - } + let config = Arc::new(Config::load(&dirs)); + + let net = match config.server { + None => { + // spawn an in-process server + let sim_cfg = config.local_simulation.clone(); + + let save = dirs.data_local_dir().join(&config.save); + info!("using save file {}", save.display()); + std::fs::create_dir_all(save.parent().unwrap()).unwrap(); + let save = match Save::open(&save, config.local_simulation.chunk_size) { + Ok(x) => x, + Err(e) => { + error!("couldn't open save: {}", e); + return; + } + }; + + let mut server = match Server::new(None, sim_cfg, save) { + Ok(server) => server, + Err(e) => { + eprintln!("{e:#}"); + std::process::exit(1); + } + }; + + let (handle, backend) = server::Handle::loopback(); + let name = (*config.name).into(); + + thread::spawn(move || { + let runtime = tokio::runtime::Builder::new_current_thread() + .enable_time() + .build() + .unwrap(); + let _guard = runtime.enter(); + server + .connect(proto::ClientHello { name }, backend) + .unwrap(); + runtime.block_on(server.run().instrument(error_span!("server"))); + debug!("server thread terminated"); + }); + + handle + } + Some(_) => net::spawn(config.clone()), + }; let mut app = App { - config: Arc::new(config), + config, dirs, metrics, window: None, + net: Some(net), }; let event_loop = EventLoop::new().unwrap(); @@ -89,6 +82,7 @@ struct App { dirs: directories::ProjectDirs, metrics: Arc, window: Option, + net: Option, } impl ApplicationHandler for App { @@ -98,11 +92,13 @@ impl ApplicationHandler for App { // Initialize Vulkan with the extensions needed to render to the window let core = Arc::new(graphics::Core::new(window.required_extensions())); - // Kick off networking - let net = net::spawn(self.config.clone()); - // Finish creating the window, including the Vulkan resources used to render to it - let mut window = graphics::Window::new(window, core.clone(), self.config.clone(), net); + let mut window = graphics::Window::new( + window, + core.clone(), + self.config.clone(), + self.net.take().unwrap(), + ); // Initialize widely-shared graphics resources let gfx = Arc::new( diff --git a/server/src/lib.rs b/server/src/lib.rs index 3e280325..0788d0cf 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -34,7 +34,7 @@ pub struct Server { sim: Sim, clients: DenseSlotMap, save: Save, - endpoint: quinn::Endpoint, + endpoint: Option, new_clients_send: mpsc::UnboundedSender<(quinn::Connection, proto::ClientHello)>, new_clients_recv: mpsc::UnboundedReceiver<(quinn::Connection, proto::ClientHello)>, @@ -43,18 +43,23 @@ pub struct Server { } impl Server { - pub fn new(net: NetParams, mut cfg: SimConfig, save: Save) -> Result { + pub fn new(net: Option, mut cfg: SimConfig, save: Save) -> Result { cfg.chunk_size = save.meta().chunk_size as u8; - let server_config = - quinn::ServerConfig::with_single_cert(net.certificate_chain, net.private_key) - .context("parsing certificate")?; - let endpoint = quinn::Endpoint::new( - quinn::EndpointConfig::default(), - Some(server_config), - net.socket, - quinn::default_runtime().unwrap(), - )?; - info!(address = %endpoint.local_addr().unwrap(), "listening"); + let endpoint = net + .map(|net| { + let server_config = + quinn::ServerConfig::with_single_cert(net.certificate_chain, net.private_key) + .context("parsing certificate")?; + let endpoint = quinn::Endpoint::new( + quinn::EndpointConfig::default(), + Some(server_config), + net.socket, + quinn::default_runtime().unwrap(), + )?; + info!(address = %endpoint.local_addr().unwrap(), "listening"); + Ok::<_, Error>(endpoint) + }) + .transpose()?; let (new_clients_send, new_clients_recv) = mpsc::unbounded_channel(); let (client_events_send, client_events_recv) = mpsc::channel(128); @@ -143,7 +148,9 @@ impl Server { fn handle_incoming(&self) -> mpsc::Receiver { let (incoming_send, incoming_recv) = mpsc::channel(16); - let endpoint = self.endpoint.clone(); + let Some(endpoint) = self.endpoint.clone() else { + return incoming_recv; + }; tokio::spawn(async move { while let Some(conn) = endpoint.accept().await { trace!(address = %conn.remote_address(), "connection incoming"); diff --git a/server/src/main.rs b/server/src/main.rs index d0c76501..bbf1f79a 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -74,11 +74,11 @@ pub async fn run() -> Result<()> { let save = Save::open(&save, sim_cfg.chunk_size)?; let server = server::Server::new( - server::NetParams { + Some(server::NetParams { certificate_chain, private_key, socket: UdpSocket::bind(cfg.listen).context("binding socket")?, - }, + }), sim_cfg, save, )?;