|
|
@ -5,10 +5,9 @@ use clap::Parser;
|
|
|
|
use std::io::Write;
|
|
|
|
use std::io::Write;
|
|
|
|
use std::io::{self, BufRead};
|
|
|
|
use std::io::{self, BufRead};
|
|
|
|
use chrono::{DateTime, Utc};
|
|
|
|
use chrono::{DateTime, Utc};
|
|
|
|
//use std::borrow::{Borrow, BorrowMut};
|
|
|
|
|
|
|
|
//use retain_mut::RetainMut;
|
|
|
|
|
|
|
|
use std::collections::BTreeMap;
|
|
|
|
use std::collections::BTreeMap;
|
|
|
|
|
|
|
|
use serde::{Serialize, Deserialize};
|
|
|
|
|
|
|
|
use std::fs::File;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// Represent one single chat user and their network stuff
|
|
|
|
/// Represent one single chat user and their network stuff
|
|
|
@ -30,13 +29,14 @@ impl ChatUser {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
struct ChatServer {
|
|
|
|
struct ChatServer {
|
|
|
|
|
|
|
|
config: ConfigArgs,
|
|
|
|
user_map: BTreeMap<u64, ChatUser>,
|
|
|
|
user_map: BTreeMap<u64, ChatUser>,
|
|
|
|
user_id_counter: u64,
|
|
|
|
user_id_counter: u64,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
impl ChatServer {
|
|
|
|
impl ChatServer {
|
|
|
|
pub fn new() -> Self {
|
|
|
|
pub fn new(config: ConfigArgs) -> Self {
|
|
|
|
Self{user_map: BTreeMap::new(), user_id_counter: 1}
|
|
|
|
Self{config, user_map: BTreeMap::new(), user_id_counter: 1}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub fn get_user_count(&self) -> usize {
|
|
|
|
pub fn get_user_count(&self) -> usize {
|
|
|
@ -156,22 +156,46 @@ fn run_thread(stream: TcpStream, server: Arc<Mutex<ChatServer>>) {
|
|
|
|
#[derive(Parser, Debug)]
|
|
|
|
#[derive(Parser, Debug)]
|
|
|
|
#[clap(about, version, author)]
|
|
|
|
#[clap(about, version, author)]
|
|
|
|
struct Args {
|
|
|
|
struct Args {
|
|
|
|
|
|
|
|
/// Path to config file
|
|
|
|
|
|
|
|
#[clap(short, long, default_value = "config.yaml")]
|
|
|
|
|
|
|
|
config: String,
|
|
|
|
|
|
|
|
|
|
|
|
/// IP address to bind to
|
|
|
|
/// IP address to bind to
|
|
|
|
#[clap(long, default_value = "0.0.0.0")]
|
|
|
|
#[clap(long)]
|
|
|
|
host: String,
|
|
|
|
host: Option<String>,
|
|
|
|
|
|
|
|
|
|
|
|
/// Port to run the server on
|
|
|
|
/// Port to run the server on
|
|
|
|
#[clap(short, long, default_value_t = 1337)]
|
|
|
|
#[clap(short, long)]
|
|
|
|
port: i16,
|
|
|
|
port: Option<u16>,
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Debug, Serialize, Deserialize)]
|
|
|
|
|
|
|
|
struct ConfigArgs {
|
|
|
|
|
|
|
|
host: String,
|
|
|
|
|
|
|
|
port: u16,
|
|
|
|
|
|
|
|
greeting_msg: String,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn main() -> std::io::Result<()> {
|
|
|
|
fn main() -> std::io::Result<()> {
|
|
|
|
|
|
|
|
// argument parsing
|
|
|
|
let args = Args::parse();
|
|
|
|
let args = Args::parse();
|
|
|
|
let binding_host = format!("{}:{}", args.host, args.port);
|
|
|
|
|
|
|
|
|
|
|
|
// read config file
|
|
|
|
|
|
|
|
let config_reader = File::open(args.config).expect("Could not open config file");
|
|
|
|
|
|
|
|
let mut config: ConfigArgs = serde_yaml::from_reader(&config_reader).expect("Could not parse config file");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if let Some(host) = args.host {
|
|
|
|
|
|
|
|
config.host = host;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if let Some(port) = args.port {
|
|
|
|
|
|
|
|
config.port = port;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
let binding_host = format!("{}:{}", config.host, config.port);
|
|
|
|
println!("Binding to {}", binding_host);
|
|
|
|
println!("Binding to {}", binding_host);
|
|
|
|
|
|
|
|
|
|
|
|
let listener = TcpListener::bind(binding_host)?;
|
|
|
|
let listener = TcpListener::bind(binding_host)?;
|
|
|
|
let server = Arc::new(Mutex::new(ChatServer::new()));
|
|
|
|
let server = Arc::new(Mutex::new(ChatServer::new(config)));
|
|
|
|
|
|
|
|
|
|
|
|
// accept connections and process them serially
|
|
|
|
// accept connections and process them serially
|
|
|
|
for stream in listener.incoming() {
|
|
|
|
for stream in listener.incoming() {
|
|
|
|