use crate::auth_client::AuthClient; use crate::connection_service::ConnectionService; use crate::packet::{send_packet, Packet, PacketPayload}; use crate::packet_type::PacketType; use crate::packets::cli_channel_list_req::CliChannelListReq; use crate::packets::cli_join_server_token_req::CliJoinServerTokenReq; use crate::packets::cli_login_token_req::CliLoginTokenReq; use crate::packets::cli_srv_select_req::CliSrvSelectReq; use crate::packets::srv_accept_reply::SrvAcceptReply; use crate::packets::srv_channel_list_reply::{ChannelInfo, SrvChannelListReply}; use crate::packets::srv_join_server_reply::SrvJoinServerReply; use crate::packets::srv_login_reply::{ServerInfo, SrvLoginReply}; use crate::packets::srv_logout_reply::SrvLogoutReply; use crate::packets::srv_srv_select_reply::SrvSrvSelectReply; use crate::packets::*; use std::collections::HashMap; use std::env; use std::error::Error; use std::net::SocketAddr; use std::sync::Arc; use tokio::io::AsyncWriteExt; use tokio::net::TcpStream; use tokio::sync::Mutex; use tonic::{Code, Status}; use tracing::{debug, error, info, warn}; use utils::null_string::NullTerminatedString; use utils::service_discovery; use utils::service_discovery::{get_kube_service_endpoints_by_dns, get_service_info}; pub(crate) async fn handle_alive_req( stream: &mut TcpStream, packet: Packet, auth_client: Arc>, connection_service: Arc, connection_id: String, ) -> Result<(), Box> { if let Some(mut state) = connection_service.get_connection(&connection_id) { let session_id = state.session_id.clone().unwrap(); debug!("Attempting to refresh session {}", session_id); let mut auth_client = auth_client.lock().await; let session = auth_client.refresh_session(&session_id).await?; if (!session.valid) { warn!("Invalid session ID: {}", session_id); return Err("Session not valid".into()); } Ok(()) } else { Err("Unable to find connection state".into()) } } pub(crate) async fn handle_accept_req( stream: &mut TcpStream, packet: Packet, ) -> Result<(), Box> { let data = SrvAcceptReply { result: srv_accept_reply::Result::Accepted, rand_value: 0, }; let response_packet = Packet::new(PacketType::PakssAcceptReply, &data)?; send_packet(stream, &response_packet).await?; Ok(()) } pub(crate) async fn handle_join_server_req( stream: &mut TcpStream, packet: Packet, auth_client: Arc>, connection_service: Arc, connection_id: String, ) -> Result<(), Box> { let request = CliJoinServerTokenReq::decode(packet.payload.as_slice()); debug!("{:?}", request); if let Some(mut state) = connection_service.get_connection(&connection_id) { let session_id = state.session_id.clone().unwrap(); let mut auth_client = auth_client.lock().await; let session = auth_client.validate_session(&session_id).await?; if (!session.valid) { warn!("Invalid session ID: {}", session_id); let data = SrvJoinServerReply { result: srv_join_server_reply::Result::Failed, id: 0, pay_flag: 0, }; let response_packet = Packet::new(PacketType::PakscJoinServerReply, &data)?; send_packet(stream, &response_packet).await?; return Err("Session not valid".into()); } let data = SrvJoinServerReply { result: srv_join_server_reply::Result::Ok, id: 1, pay_flag: 0, }; let response_packet = Packet::new(PacketType::PakscJoinServerReply, &data)?; send_packet(stream, &response_packet).await?; Ok(()) } else { Err("Unable to find connection state".into()) } } pub(crate) async fn handle_logout_req( stream: &mut TcpStream, packet: Packet, auth_client: Arc>, connection_service: Arc, connection_id: String, ) -> Result<(), Box> { if let Some(mut state) = connection_service.get_connection(&connection_id) { let session_id = state.session_id.clone().unwrap(); let mut auth_client = auth_client.lock().await; auth_client.logout(&session_id).await?; let data = SrvLogoutReply { wait_time: 1 }; let response_packet = Packet::new(PacketType::PakwcLogoutReply, &data)?; send_packet(stream, &response_packet).await?; stream.shutdown().await?; Ok(()) } else { Err("Unable to find connection state".into()) } } pub(crate) async fn handle_login_req( stream: &mut TcpStream, packet: Packet, auth_client: Arc>, connection_service: Arc, connection_id: String, addr: SocketAddr, ) -> Result<(), Box> { debug!( "decoding packet payload of size {}", packet.payload.as_slice().len() ); let data = CliLoginTokenReq::decode(packet.payload.as_slice())?; debug!("{:?}", data); let mut auth_client = auth_client.lock().await; match auth_client.validate_session(&data.token.0).await { Ok(response) => { if response.valid == false { info!("Login failed: Invalid credentials"); let data = SrvLoginReply { result: srv_login_reply::Result::UnknownAccount, right: 0, type_: 0, servers_info: Vec::new(), }; let response_packet = Packet::new(PacketType::PaklcLoginReply, &data)?; send_packet(stream, &response_packet).await?; } else { debug!("Successfully logged in"); if let Some(mut state) = connection_service.get_connection_mut(&connection_id) { state.user_id = Some(response.user_id.parse().unwrap()); state.session_id = Some(response.session_id.parse().unwrap()); } let mut id = 0; let mut server_info: Vec = Vec::new(); match get_service_info("default", "character-service").await { Ok(service_info) => { if let Some(annotations) = service_info.annotations { let mut server_name = "".to_string(); let mut is_test = false; for (key, value) in annotations { match key.as_str() { "name" => { server_name = value; } "tags" => { } _ => {} } } if is_test { server_name = format!("@{}", server_name); } else { server_name = format!(" {}", server_name); } server_info.push(ServerInfo { test: u8::from(is_test), name: NullTerminatedString::new(&server_name), id, }); let data = SrvLoginReply { result: srv_login_reply::Result::Ok, right: 0, type_: 0, servers_info: server_info, }; let response_packet = Packet::new(PacketType::PaklcLoginReply, &data)?; send_packet(stream, &response_packet).await?; } } Err(err) => { let data = SrvLoginReply { result: srv_login_reply::Result::Failed, right: 0, type_: 0, servers_info: Vec::new(), }; let response_packet = Packet::new(PacketType::PaklcLoginReply, &data)?; send_packet(stream, &response_packet).await?; return Ok(()); } } } } Err(status) => { if let Some(tonic_status) = status.downcast_ref::() { match tonic_status.code() { Code::Unauthenticated => { info!("Login failed: Invalid credentials"); let data = SrvLoginReply { result: srv_login_reply::Result::UnknownAccount, right: 0, type_: 0, servers_info: Vec::new(), }; let response_packet = Packet::new(PacketType::PaklcLoginReply, &data)?; send_packet(stream, &response_packet).await?; } Code::Unavailable => { warn!("Login failed: Service is unavailable"); let data = SrvLoginReply { result: srv_login_reply::Result::Failed, right: 0, type_: 0, servers_info: Vec::new(), }; let response_packet = Packet::new(PacketType::PaklcLoginReply, &data)?; send_packet(stream, &response_packet).await?; } _ => { error!("Unexpected error: {}", tonic_status.message()); let data = SrvLoginReply { result: srv_login_reply::Result::Failed, right: 0, type_: 0, servers_info: Vec::new(), }; let response_packet = Packet::new(PacketType::PaklcLoginReply, &data)?; send_packet(stream, &response_packet).await?; } } } } } Ok(()) } pub(crate) async fn handle_server_select_req( stream: &mut TcpStream, packet: Packet, connection_service: Arc, connection_id: String, ) -> Result<(), Box> { let request = CliSrvSelectReq::decode(packet.payload.as_slice())?; debug!("{:?}", request); if let Some(mut state) = connection_service.get_connection_mut(&connection_id) { state .additional_data .insert("server".to_string(), request.server_id.to_string()); state .additional_data .insert("channel".to_string(), request.channel_id.to_string()); } let data = SrvSrvSelectReply { result: srv_srv_select_reply::Result::Ok, session_id: 0, // Client should already have this value crypt_val: 0, // This is only for the old encryption ip: NullTerminatedString::new(""), // If this is empty, the client should stay connected (requires client change) port: 0, // See comment about ip above }; let response_packet = Packet::new(PacketType::PaklcSrvSelectReply, &data)?; send_packet(stream, &response_packet).await?; Ok(()) } pub(crate) async fn handle_channel_list_req( stream: &mut TcpStream, packet: Packet, ) -> Result<(), Box> { let request = CliChannelListReq::decode(packet.payload.as_slice()); debug!("{:?}", request); let mut id = 1; let mut channel_info: Vec = Vec::new(); match get_service_info("default", "world-service").await { Ok(service_info) => { if let Some(annotations) = service_info.annotations { let mut server_name = "".to_string(); for (key, value) in annotations { match key.as_str() { "name" => { server_name = value; } "tags" => {} _ => {} } } channel_info.push(ChannelInfo { id: id, low_age: 0, high_age: 0, capacity: 0, name: NullTerminatedString::new(&server_name), }); id = id + 1; let data = SrvChannelListReply { id: request?.server_id, channels: channel_info, }; let response_packet = Packet::new(PacketType::PaklcChannelListReply, &data)?; send_packet(stream, &response_packet).await?; } } Err(err) => { let data = SrvChannelListReply { id: request?.server_id, channels: Vec::new(), }; let response_packet = Packet::new(PacketType::PaklcChannelListReply, &data)?; send_packet(stream, &response_packet).await?; return Ok(()); } } Ok(()) }