From 06b389b28fc829025a582cf5a96c0c04a95ffa68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Mekina?= Date: Wed, 30 Apr 2025 23:39:21 +0200 Subject: [PATCH] wip: add base for server --- theseus-server/src/main.rs | 60 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 58 insertions(+), 2 deletions(-) diff --git a/theseus-server/src/main.rs b/theseus-server/src/main.rs index 23ceea5..55d9701 100644 --- a/theseus-server/src/main.rs +++ b/theseus-server/src/main.rs @@ -1,16 +1,41 @@ +use std::sync::{atomic::AtomicU32, Arc}; use http_body_util::{combinators::BoxBody, BodyExt, Full}; -use hyper::{body::{Bytes, Incoming}, Error, Request, Response}; +use hyper::{ + body::{Bytes, Incoming}, server::conn::http1, service::service_fn, Error, Request, Response +}; +use hyper_util::rt::TokioIo; +use tokio::net::TcpListener; mod args; +mod config; async fn router( _: Request, + _: Arc, ) -> Result>, Error> { Ok(Response::new(Full::new("test".into()).map_err(|n| match n {}).boxed())) } +fn load_config(path: &str) -> Result { + let Ok(file_contents) = std::fs::read_to_string(path) else { + return Err("could not read the config file"); + }; + toml::from_str(&file_contents).map_err(|_| "invalid config file structure or fields") +} + +struct SharedState { + counter: AtomicU32, +} + +impl Default for SharedState { + fn default() -> Self { + Self { counter: 0.into() } + } +} + #[tokio::main] async fn main() { + // load config let args = match args::Args::try_from(&mut std::env::args()) { Ok(v) => v, Err(e) => { @@ -18,5 +43,36 @@ async fn main() { return; } }; - println!("{}", args.config_path()); + let config = match load_config(args.config_path()) { + Ok(v) => v, + Err(e) => { + eprintln!("{}", e); + return; + } + }; + + // shared state + let state = Arc::new(SharedState::default()); + + // server + let Ok(listener) = TcpListener::bind(config.server.bind_to).await else { + eprintln!("unable to bind to: {:?}", config.server.bind_to); + return; + }; + + loop { + let Ok((stream, _)) = listener.accept().await else { + eprintln!("unable to accept new connections"); + return; + }; + let io = TokioIo::new(stream); + let state_clone = state.clone(); + tokio::task::spawn(async move { + if let Err(_) = http1::Builder::new().serve_connection(io, service_fn(move |req| { + router(req, state_clone.clone()) + })).await { + println!("closed connection"); + } + }); + } }