Skip to content

Commit

Permalink
Use in-process server
Browse files Browse the repository at this point in the history
  • Loading branch information
Ralith committed Aug 11, 2024
1 parent 5dc0d2b commit a3abc58
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 78 deletions.
1 change: 0 additions & 1 deletion client/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
120 changes: 58 additions & 62 deletions client/src/main.rs
Original file line number Diff line number Diff line change
@@ -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},
Expand All @@ -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::<SocketAddr>().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();
Expand All @@ -89,6 +82,7 @@ struct App {
dirs: directories::ProjectDirs,
metrics: Arc<metrics::Recorder>,
window: Option<graphics::Window>,
net: Option<server::Handle>,
}

impl ApplicationHandler for App {
Expand All @@ -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(
Expand Down
33 changes: 20 additions & 13 deletions server/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ pub struct Server {
sim: Sim,
clients: DenseSlotMap<ClientId, Client>,
save: Save,
endpoint: quinn::Endpoint,
endpoint: Option<quinn::Endpoint>,

new_clients_send: mpsc::UnboundedSender<(quinn::Connection, proto::ClientHello)>,
new_clients_recv: mpsc::UnboundedReceiver<(quinn::Connection, proto::ClientHello)>,
Expand All @@ -43,18 +43,23 @@ pub struct Server {
}

impl Server {
pub fn new(net: NetParams, mut cfg: SimConfig, save: Save) -> Result<Self> {
pub fn new(net: Option<NetParams>, mut cfg: SimConfig, save: Save) -> Result<Self> {
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);
Expand Down Expand Up @@ -143,7 +148,9 @@ impl Server {

fn handle_incoming(&self) -> mpsc::Receiver<quinn::Connection> {
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");
Expand Down
4 changes: 2 additions & 2 deletions server/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
)?;
Expand Down

0 comments on commit a3abc58

Please sign in to comment.