2023-02-07 15:21:00 +00:00
|
|
|
use std::net::SocketAddr;
|
|
|
|
|
2023-02-09 19:01:21 +00:00
|
|
|
use prometheus::{IntCounter, IntGauge, Registry as MetricsRegistry};
|
2023-02-09 18:19:03 +00:00
|
|
|
use serde::Deserialize;
|
2023-02-09 19:01:21 +00:00
|
|
|
use tokio::io::{AsyncBufReadExt, BufReader, BufWriter};
|
2023-02-07 15:21:00 +00:00
|
|
|
use tokio::net::{TcpListener, TcpStream};
|
|
|
|
use tokio::sync::oneshot::channel;
|
|
|
|
|
2023-02-09 19:01:21 +00:00
|
|
|
use crate::core::player::PlayerRegistry;
|
2023-02-07 15:21:00 +00:00
|
|
|
use crate::prelude::*;
|
|
|
|
use crate::protos::irc::*;
|
|
|
|
use crate::util::Terminator;
|
|
|
|
|
2023-02-09 18:19:03 +00:00
|
|
|
#[derive(Deserialize, Debug)]
|
2023-02-07 15:21:00 +00:00
|
|
|
pub struct ServerConfig {
|
|
|
|
pub listen_on: SocketAddr,
|
|
|
|
}
|
|
|
|
|
|
|
|
async fn handle_socket(
|
|
|
|
mut stream: TcpStream,
|
|
|
|
socket_addr: SocketAddr,
|
|
|
|
mut players: PlayerRegistry,
|
2023-02-09 19:01:21 +00:00
|
|
|
current_connections: IntGauge,
|
2023-02-07 15:21:00 +00:00
|
|
|
) {
|
|
|
|
let (reader, writer) = stream.split();
|
|
|
|
let mut reader = BufReader::new(reader);
|
|
|
|
let mut writer = BufWriter::new(writer);
|
|
|
|
|
|
|
|
let mut buffer = vec![];
|
|
|
|
|
|
|
|
// let (player_id, mut player_handle) = players.create_player().await;
|
|
|
|
// let mut sub = player_handle.subscribe().await;
|
|
|
|
|
|
|
|
loop {
|
|
|
|
select! {
|
|
|
|
biased;
|
|
|
|
res = reader.read_until(b'\n', &mut buffer) => {
|
|
|
|
match res {
|
|
|
|
Ok(len) => if len == 0 {
|
|
|
|
log::info!("Terminating socket");
|
|
|
|
break;
|
|
|
|
},
|
|
|
|
Err(err) => log::warn!("Failed to read from socket: {err}"),
|
|
|
|
}
|
|
|
|
let parsed = parse_client_message(&buffer[..]);
|
|
|
|
match parsed {
|
|
|
|
Ok((rest, msg)) => {
|
|
|
|
log::info!("Incoming IRC message: {msg:?}");
|
|
|
|
},
|
|
|
|
Err(err) => {
|
|
|
|
log::warn!("Failed to parse IRC message: {err}");
|
|
|
|
},
|
|
|
|
}
|
|
|
|
buffer.clear();
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
2023-02-09 19:01:21 +00:00
|
|
|
current_connections.dec();
|
2023-02-07 15:21:00 +00:00
|
|
|
}
|
|
|
|
|
2023-02-09 19:01:21 +00:00
|
|
|
pub async fn launch(
|
|
|
|
config: &ServerConfig,
|
|
|
|
players: PlayerRegistry,
|
|
|
|
metrics: MetricsRegistry,
|
|
|
|
) -> Result<Terminator> {
|
2023-02-07 15:21:00 +00:00
|
|
|
log::info!("Starting IRC projection");
|
|
|
|
let (signal, mut rx) = channel();
|
2023-02-09 19:01:21 +00:00
|
|
|
let current_connections =
|
|
|
|
IntGauge::new("irc_current_connections", "Open and alive TCP connections")?;
|
|
|
|
let total_connections = IntCounter::new(
|
|
|
|
"irc_total_connections",
|
|
|
|
"Total number of opened connections",
|
|
|
|
)?;
|
|
|
|
metrics.register(Box::new(current_connections.clone()))?;
|
|
|
|
metrics.register(Box::new(total_connections.clone()))?;
|
|
|
|
|
2023-02-07 15:21:00 +00:00
|
|
|
let listener = TcpListener::bind(config.listen_on).await?;
|
|
|
|
log::debug!("Listener started");
|
|
|
|
|
|
|
|
let handle = tokio::task::spawn(async move {
|
|
|
|
loop {
|
|
|
|
select! {
|
|
|
|
biased;
|
|
|
|
_ = &mut rx => break,
|
|
|
|
new_conn = listener.accept() => {
|
|
|
|
match new_conn {
|
|
|
|
Ok((stream, socket_addr)) => {
|
2023-02-09 19:01:21 +00:00
|
|
|
total_connections.inc();
|
|
|
|
current_connections.inc();
|
2023-02-07 15:21:00 +00:00
|
|
|
log::debug!("Incoming connection from {socket_addr}");
|
2023-02-09 19:01:21 +00:00
|
|
|
let handle = tokio::task::spawn(handle_socket(stream, socket_addr, players.clone(), current_connections.clone()));
|
2023-02-07 15:21:00 +00:00
|
|
|
},
|
|
|
|
Err(err) => log::warn!("Failed to accept new connection: {err}"),
|
|
|
|
}
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
log::info!("Stopping IRC projection");
|
|
|
|
Ok(())
|
|
|
|
});
|
|
|
|
|
|
|
|
let terminator = Terminator::from_raw(signal, handle);
|
|
|
|
Ok(terminator)
|
|
|
|
}
|