101 lines
2.8 KiB
Rust
101 lines
2.8 KiB
Rust
mod config;
|
|
mod jwt;
|
|
mod message;
|
|
mod router;
|
|
mod stores;
|
|
|
|
use clap::Parser;
|
|
use configparser::ini::Ini;
|
|
use tokio::{
|
|
io::{AsyncReadExt, AsyncWriteExt},
|
|
net::{TcpListener, TcpStream},
|
|
time::{timeout, Duration},
|
|
};
|
|
|
|
use crate::router::ROUTER;
|
|
use config::Config;
|
|
|
|
#[derive(Parser)]
|
|
#[clap(author, version, about, long_about = None)]
|
|
struct Cli {
|
|
/// config filepath (.ini)
|
|
config: String,
|
|
}
|
|
|
|
#[tokio::main]
|
|
async fn main() {
|
|
simple_logger::init_with_level(log::Level::Info).unwrap();
|
|
let args = Cli::parse();
|
|
|
|
let mut config = Ini::new();
|
|
match config.load(args.config) {
|
|
Ok(c) => c,
|
|
Err(e) => {
|
|
log::error!("error while loading the config file details={}", e);
|
|
std::process::exit(1);
|
|
}
|
|
};
|
|
|
|
let server_url = config.get("server", "url").unwrap_or("".to_string());
|
|
let listener = {
|
|
match TcpListener::bind(&server_url).await {
|
|
Ok(t) => {
|
|
log::info!("server is listening on '{}'", server_url);
|
|
t
|
|
}
|
|
Err(e) => {
|
|
log::error!("while initializing tcp listener details={}", e);
|
|
std::process::exit(1);
|
|
}
|
|
}
|
|
};
|
|
|
|
let router_config: Config = {
|
|
match Config::try_from(config) {
|
|
Ok(c) => c,
|
|
Err(e) => {
|
|
log::error!("unable to load the configuration details={}", e);
|
|
std::process::exit(1);
|
|
}
|
|
}
|
|
};
|
|
|
|
loop {
|
|
let (stream, addr) = listener.accept().await.unwrap();
|
|
let conf = router_config.clone();
|
|
tokio::spawn(handle_connection(stream, addr.to_string(), conf.clone()));
|
|
}
|
|
}
|
|
|
|
/// handle_connection parses the incoming request and builds an HTTP response
|
|
async fn handle_connection(mut stream: TcpStream, addr: String, config: Config) {
|
|
log::info!("client connected: {}", addr);
|
|
|
|
let mut message = vec![];
|
|
let mut buffer: [u8; 1024] = [0; 1024];
|
|
|
|
let duration = Duration::from_millis(5);
|
|
|
|
// loop until the message is read
|
|
// the stream can be fragmented so, using a timeout (5ms should be far enough) for the future for completion
|
|
// after the timeout, the message is "considered" as entirely read
|
|
loop {
|
|
match timeout(duration, stream.read(&mut buffer)).await {
|
|
Ok(v) => {
|
|
let n = v.unwrap();
|
|
message.extend_from_slice(&buffer[0..n]);
|
|
}
|
|
Err(_e) => break,
|
|
}
|
|
}
|
|
|
|
let request_string = std::str::from_utf8(&message).unwrap();
|
|
let response = ROUTER.route(request_string, config).await;
|
|
let response_str: String = response.into();
|
|
|
|
stream.write(response_str.as_bytes()).await.unwrap();
|
|
stream.flush().await.unwrap();
|
|
|
|
log::info!("connection closed: {}", addr);
|
|
}
|