#![cfg(feature = "server")]
use std::
{
thread,
process,
time::Duration,
sync::{ Arc, Mutex },
net::
{
TcpListener,
UdpSocket,
Shutdown,
},
};
use log::LevelFilter;
use simple_logger::SimpleLogger;
use why2_chat::
{
misc,
config,
options,
crypto::kex,
network::
{
server,
voice::server as voice_server,
},
};
fn quit() {
log::info!("Exiting...");
server::disconnect_all(); }
fn main()
{
SimpleLogger::new()
.with_level(LevelFilter::Info)
.with_module_level("ureq", LevelFilter::Warn) .with_module_level("rustls", LevelFilter::Warn) .init()
.unwrap();
misc::check_version(); config::init_config(); kex::generate_server_keys();
if config::read_config("enable_voice_chat")
{
options::enable_voice_chat();
}
options::set_server_username(&config::read_config::<String>("server_username"));
let address = format!("{}:{}", config::read_config::<String>("server_ip"), config::read_config::<u16>("server_port"));
let listener = match TcpListener::bind(&address)
{
Ok(l) => l,
Err(_) =>
{
log::error!("Binding on {address} failed!");
process::exit(1);
}
};
let udp_socket = if options::voice_chat_enabled() {
Some(UdpSocket::bind(&address).expect("Binding UDP failed"))
} else { None };
log::info!("Listening on {address}");
thread::spawn(move ||
{
let mut n = 0;
loop
{
thread::sleep(Duration::from_secs(5));
server::disconnect_inactive();
n = (n + 1) % 6;
if n == 0
{
server::send_keepalive();
}
}
});
ctrlc::set_handler(move ||
{
quit();
process::exit(0);
}).expect("Setting Ctrl+C handler failed");
if options::voice_chat_enabled()
{
thread::spawn(move || voice_server::listen_client_voice(udp_socket.unwrap()));
}
for stream in listener.incoming()
{
match stream
{
Ok(mut stream) =>
{
let peer_addr = match stream.peer_addr()
{
Ok(p) => p,
Err(_) => continue
};
let auth_clients = server::CONNECTIONS.iter().filter(|c| c.is_authenticated()).count();
let unauth_clients = server::CONNECTIONS.len() - auth_clients;
let ip_clients = server::CONNECTIONS.iter().filter(|c| c.peer_addr().ip() == peer_addr.ip()).count();
if auth_clients >= config::read_config::<usize>("max_clients") ||
unauth_clients >= config::read_config::<usize>("max_unauth_clients") ||
ip_clients >= config::read_config::<usize>("max_ip_clients")
{
log::error!("Connection rejected (limit): {peer_addr}");
stream.shutdown(Shutdown::Both).ok();
continue;
}
match stream.set_nodelay(true)
{
Ok(_) => {},
Err(_) => continue
}
let write_stream = Arc::new(Mutex::new(stream.try_clone().expect("Failed cloning stream")));
thread::spawn(move || server::listen_client(&mut (&mut stream, write_stream)));
},
Err(e) =>
{
log::error!("Connection failed: {}", e);
}
}
}
}