139 lines
4.3 KiB
Rust
139 lines
4.3 KiB
Rust
use std::net::{SocketAddr, TcpListener, UdpSocket};
|
|
use std::sync::Arc;
|
|
use std::sync::Mutex;
|
|
use std::thread;
|
|
|
|
use ansi_term::Color;
|
|
use openssl::ssl::{SslAcceptor, SslFiletype, SslMethod};
|
|
use rusty_pool;
|
|
use std::fmt::Formatter;
|
|
use std::time::Duration;
|
|
|
|
mod database;
|
|
mod error;
|
|
mod http;
|
|
mod udp;
|
|
mod usimp;
|
|
mod websocket;
|
|
|
|
enum SocketType {
|
|
Http,
|
|
Https,
|
|
Udp,
|
|
}
|
|
|
|
impl std::fmt::Display for SocketType {
|
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
|
write!(f, "{}", match self {
|
|
SocketType::Http => "http+ws",
|
|
SocketType::Https => "https+wss",
|
|
SocketType::Udp => "udp",
|
|
})
|
|
}
|
|
}
|
|
|
|
struct SocketConfig {
|
|
address: SocketAddr,
|
|
socket_type: SocketType,
|
|
}
|
|
|
|
fn main() {
|
|
println!("Locutus server");
|
|
|
|
let socket_configs: Vec<SocketConfig> = vec![
|
|
SocketConfig {
|
|
address: "[::]:8080".parse().unwrap(),
|
|
socket_type: SocketType::Http,
|
|
},
|
|
SocketConfig {
|
|
address: "[::]:8443".parse().unwrap(),
|
|
socket_type: SocketType::Https,
|
|
},
|
|
SocketConfig {
|
|
address: "[::]:3126".parse().unwrap(),
|
|
socket_type: SocketType::Udp,
|
|
},
|
|
];
|
|
|
|
// Note: rust's stdout is line buffered!
|
|
eprint!("Initializing database connection pool...");
|
|
if let Err(error) = database::init() {
|
|
eprintln!("\n{}", Color::Red.bold().paint(error.to_string()));
|
|
std::process::exit(1);
|
|
}
|
|
eprintln!(" {}", Color::Green.paint("success"));
|
|
|
|
let thread_pool = rusty_pool::Builder::new()
|
|
.core_size(4)
|
|
.max_size(1024)
|
|
.keep_alive(Duration::from_secs(60 * 60))
|
|
.build();
|
|
let thread_pool_mutex = Arc::new(Mutex::new(thread_pool));
|
|
|
|
let mut threads = Vec::new();
|
|
|
|
for socket_config in socket_configs {
|
|
let thread_pool_mutex = thread_pool_mutex.clone();
|
|
|
|
eprintln!(
|
|
"Creating listening thread for {} ({})",
|
|
ansi_term::Style::new().bold().paint(socket_config.address.to_string()),
|
|
socket_config.socket_type
|
|
);
|
|
|
|
threads.push(match socket_config.socket_type {
|
|
SocketType::Http => thread::spawn(move || {
|
|
let mut tcp_socket = TcpListener::bind(socket_config.address).unwrap();
|
|
|
|
for stream in tcp_socket.incoming() {
|
|
thread_pool_mutex.lock().unwrap().execute(|| {
|
|
let stream = stream.unwrap();
|
|
http::connection_handler(http::Stream::Tcp(stream));
|
|
});
|
|
}
|
|
}),
|
|
SocketType::Https => thread::spawn(move || {
|
|
let mut ssl_socket = TcpListener::bind(socket_config.address).unwrap();
|
|
|
|
let mut acceptor = SslAcceptor::mozilla_intermediate(SslMethod::tls()).unwrap();
|
|
acceptor
|
|
.set_certificate_chain_file("/home/lorenz/Certificates/chakotay.pem")
|
|
.unwrap();
|
|
acceptor
|
|
.set_private_key_file("/home/lorenz/Certificates/priv/chakotay.key",SslFiletype::PEM)
|
|
.unwrap();
|
|
acceptor.check_private_key().unwrap();
|
|
let acceptor = Arc::new(acceptor.build());
|
|
|
|
for stream in ssl_socket.incoming() {
|
|
let acceptor = acceptor.clone();
|
|
thread_pool_mutex.lock().unwrap().execute(move || {
|
|
let stream = stream.unwrap();
|
|
let stream = acceptor.accept(stream).unwrap();
|
|
http::connection_handler(http::Stream::Ssl(stream));
|
|
});
|
|
}
|
|
}),
|
|
SocketType::Udp => thread::spawn(move || {
|
|
let mut udp_socket = UdpSocket::bind(socket_config.address).unwrap();
|
|
let mut buf = [0; 65_536];
|
|
|
|
loop {
|
|
let (size, addr) = udp_socket.recv_from(&mut buf).unwrap();
|
|
let req = udp::Request::new(&udp_socket, addr, size, &buf);
|
|
thread_pool_mutex
|
|
.lock()
|
|
.unwrap()
|
|
.execute(|| udp::handler(req));
|
|
}
|
|
}),
|
|
});
|
|
}
|
|
|
|
println!("{}", Color::Green.paint("Ready"));
|
|
|
|
for thread in threads {
|
|
thread.join().unwrap();
|
|
}
|
|
}
|