Files
osirose-new/packet-service/src/main.rs
raven aa2be43f4e Refactor
Updated handlers by spliting the TcpStream in half to allow reading and writing data at the same time.
This fixes an issue where you are unable to get chat messages until the client sends a packet to the server

Fixed client id's by adding the id manager
Added shout chat handling
2025-06-07 00:36:02 -04:00

140 lines
4.4 KiB
Rust

use crate::auth_client::AuthClient;
use crate::bufferpool::BufferPool;
use crate::character_client::CharacterClient;
use crate::connection_service::ConnectionService;
use crate::metrics::{ACTIVE_CONNECTIONS, PACKETS_RECEIVED};
use crate::packet::Packet;
use crate::router::PacketRouter;
use dotenv::dotenv;
use prometheus::{self, Encoder, TextEncoder};
use prometheus_exporter;
use std::collections::HashMap;
use std::env;
use std::error::Error;
use std::net::ToSocketAddrs;
use std::str::FromStr;
use std::sync::Arc;
use tokio::io::AsyncReadExt;
use tokio::net::{TcpListener, TcpStream};
use tokio::sync::{Mutex, Semaphore};
use tokio::{io, select, signal};
use tracing::Level;
use tracing::{debug, error, info, warn};
use tracing_subscriber::EnvFilter;
use utils::service_discovery::get_kube_service_endpoints_by_dns;
use utils::{health_check, logging};
use warp::Filter;
mod auth_client;
mod bufferpool;
mod character_client;
mod connection_service;
mod connection_state;
mod dataconsts;
mod enums;
mod handlers;
mod metrics;
mod packet;
mod packet_type;
mod packets;
mod router;
mod types;
mod interceptors;
mod id_manager;
pub mod common {
tonic::include_proto!("common");
}
pub mod auth {
tonic::include_proto!("auth");
}
pub mod character_common {
tonic::include_proto!("character_common");
}
pub mod character {
tonic::include_proto!("character");
}
const BUFFER_POOL_SIZE: usize = 1000;
const MAX_CONCURRENT_CONNECTIONS: usize = 100;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
dotenv().ok();
let app_name = env!("CARGO_PKG_NAME");
logging::setup_logging(app_name, &["packet_service", "health_check"]);
// Set the gRPC server address
let addr = env::var("LISTEN_ADDR").unwrap_or_else(|_| "0.0.0.0".to_string());
let port = env::var("SERVICE_PORT").unwrap_or_else(|_| "29000".to_string());
let metrics_port = env::var("PACKET_METRICS_PORT").unwrap_or_else(|_| "4001".to_string());
let auth_url = format!(
"http://{}",
get_kube_service_endpoints_by_dns("auth-service", "tcp", "auth-service")
.await?
.get(0)
.unwrap()
);
let character_url = format!(
"http://{}",
get_kube_service_endpoints_by_dns("character-service", "tcp", "character-service")
.await?
.get(0)
.unwrap()
);
// Start health-check endpoint
health_check::start_health_check(addr.as_str()).await?;
let auth_client = Arc::new(Mutex::new(AuthClient::connect(&auth_url).await?));
let character_client = Arc::new(Mutex::new(CharacterClient::connect(&character_url).await?));
let full_addr = format!("{}:{}", &addr, port);
tokio::spawn(async move {
let semaphore = Arc::new(Semaphore::new(MAX_CONCURRENT_CONNECTIONS));
let listener = TcpListener::bind(full_addr.clone()).await.unwrap();
let buffer_pool = BufferPool::new(BUFFER_POOL_SIZE);
let connection_service = Arc::new(ConnectionService::new());
let packet_router = PacketRouter {
auth_client,
character_client,
connection_service,
};
info!("Packet service listening on {}", full_addr);
loop {
let (mut socket, addr) = listener.accept().await.unwrap();
let packet_router = packet_router.clone();
info!("New connection from {}", addr);
let pool = buffer_pool.clone();
let permit = semaphore.clone().acquire_owned().await.unwrap();
let peer_addr = socket.peer_addr().unwrap();
let (mut reader, writer) = io::split(socket);
let writer = Arc::new(tokio::sync::Mutex::new(writer));
// Spawn a new task for each connection
tokio::spawn(async move {
let _permit = permit;
let connection_id = packet_router.connection_service.add_connection(writer);
if let Err(e) = packet_router
.handle_connection(reader, pool, connection_id.clone(), peer_addr.to_string())
.await
{
error!("Error handling connection: {}", e);
}
packet_router.connection_service.remove_connection(&connection_id);
});
}
});
let binding = format!("{}:{}", &addr, metrics_port);
prometheus_exporter::start(binding.parse().unwrap()).unwrap();
utils::signal_handler::wait_for_signal().await;
Ok(())
}