diff --git a/src/kerberos/mod.rs b/src/kerberos/mod.rs index 8fb46fa..5fafd9e 100644 --- a/src/kerberos/mod.rs +++ b/src/kerberos/mod.rs @@ -25,7 +25,7 @@ pub fn derive_key(pid: u32, password: [u8; 16]) -> [u8; 16]{ key } -#[derive(Pod, Zeroable, Copy, Clone, Debug, Eq, PartialEq)] +#[derive(Pod, Zeroable, Copy, Clone, Debug, Eq, PartialEq, Default)] #[repr(transparent)] pub struct KerberosDateTime(pub u64); diff --git a/src/protocols/matchmake_common/mod.rs b/src/protocols/matchmake_common/mod.rs index 79f7c97..ab904f7 100644 --- a/src/protocols/matchmake_common/mod.rs +++ b/src/protocols/matchmake_common/mod.rs @@ -1,11 +1,15 @@ use std::collections::{BTreeMap}; use std::sync::Arc; use log::error; -use tokio::sync::Mutex; +use rand::random; +use tokio::sync::{Mutex, RwLock}; +use crate::kerberos::KerberosDateTime; use crate::protocols::notification::Notification; -use crate::prudp::socket::{ConnectionData, SocketData}; -use crate::rmc::structures::matchmake::MatchmakeSession; +use crate::prudp::socket::{ActiveConnectionData, ConnectionData, SocketData}; +use crate::rmc::structures::matchmake::{Gathering, MatchmakeParam, MatchmakeSession}; +use crate::rmc::structures::variant::Variant; +#[derive(Default, Debug)] pub struct ExtendedMatchmakeSession{ pub session: MatchmakeSession, pub connected_players: Vec>>, @@ -16,22 +20,75 @@ pub struct MatchmakeData{ } impl ExtendedMatchmakeSession{ + pub async fn from_matchmake_session(session: MatchmakeSession, host: &Mutex) -> Self{ + let host = host.lock().await; + + let ConnectionData{ + active_connection_data, + .. + } = &*host; + + let Some(active_connection_data) = active_connection_data else{ + return Default::default(); + }; + + let ActiveConnectionData{ + active_secure_connection_data, + .. + } = active_connection_data; + + let Some(active_secure_connection_data) = active_secure_connection_data else{ + return Default::default(); + }; + + + let mm_session = MatchmakeSession{ + gathering: Gathering{ + self_gid: random(), + owner_pid: active_secure_connection_data.pid, + host_pid: active_secure_connection_data.pid, + ..session.gathering.clone() + }, + datetime: KerberosDateTime::now(), + session_key: (0..32).map(|_| random()).collect(), + matchmake_param: MatchmakeParam{ + params: vec![ + ("@SR".to_owned(), Variant::Bool(true)), + ("@GIR".to_owned(), Variant::SInt64(3)) + ] + }, + ..session + }; + + Self{ + session: mm_session, + connected_players: Default::default() + } + } + pub async fn add_player(&mut self, socket: &SocketData, conn: Arc>, join_msg: String) { - let Some(pid) = conn.lock().await.active_connection_data.as_ref() + let locked = conn.lock().await; + + let Some(joining_pid) = locked.active_connection_data.as_ref() .map(|c| c.active_secure_connection_data.as_ref() - .map(|c| c.pid - ) + .map(|c| c.pid) ).flatten() else { error!("tried to add player without secure connection"); return }; + drop(locked); + self.connected_players.push(conn); + self.session.participation_count = self.connected_players.len() as u32; - for conn in &self.connected_players{ - let Some(other_pid) = conn.lock().await.active_connection_data.as_ref() + for other_connection in &self.connected_players{ + let mut conn = other_connection.lock().await; + + + let Some(other_pid) = conn.active_connection_data.as_ref() .map(|c| c.active_secure_connection_data.as_ref() .map(|c| c.pid @@ -41,22 +98,38 @@ impl ExtendedMatchmakeSession{ return }; - let mut conn = conn.lock().await; + /*if other_pid == self.session.gathering.owner_pid && + joining_pid == self.session.gathering.owner_pid{ + continue; + }*/ conn.send_notification(socket, Notification{ - pid_source: pid, + pid_source: joining_pid, notif_type: 3001, param_1: self.session.gathering.self_gid, param_2: other_pid, str_param: join_msg.clone(), + param_3: self.session.participation_count }).await; - - } } } +pub async fn add_matchmake_session(mm_data: Arc>,session: ExtendedMatchmakeSession) -> Arc> { + let gid = session.session.gathering.self_gid; + + let mut mm_data = mm_data.write().await; + + let session = Arc::new(Mutex::new(session)); + + mm_data.matchmake_sessions.insert(gid, session.clone()); + + session +} impl MatchmakeData { + + + pub async fn try_find_session_with_criteria(&self, ) -> Option>>{ None } diff --git a/src/protocols/matchmake_extension/method_auto_matchmake_with_param_postpone.rs b/src/protocols/matchmake_extension/method_auto_matchmake_with_param_postpone.rs index 2d53080..c822dc0 100644 --- a/src/protocols/matchmake_extension/method_auto_matchmake_with_param_postpone.rs +++ b/src/protocols/matchmake_extension/method_auto_matchmake_with_param_postpone.rs @@ -1,12 +1,16 @@ use std::io::Cursor; use std::sync::Arc; +use std::time::Duration; +use chrono::SecondsFormat::Millis; +use log::info; use rand::random; use tokio::sync::{Mutex, RwLock}; +use tokio::time::sleep; use crate::protocols::matchmake_common::{ExtendedMatchmakeSession, MatchmakeData}; use crate::prudp::socket::{ConnectionData, SocketData}; use crate::rmc::message::RMCMessage; use crate::rmc::response::{ErrorCode, RMCResponseResult}; -use crate::rmc::structures::matchmake::{AutoMatchmakeParam}; +use crate::rmc::structures::matchmake::{AutoMatchmakeParam, MatchmakeSession}; use crate::rmc::structures::RmcSerialize; @@ -18,7 +22,7 @@ pub async fn auto_matchmake_with_param_postpone( mm_data: Arc>, auto_matchmake_param: AutoMatchmakeParam ) -> RMCResponseResult{ - println!("auto_matchmake_with_param_postpone: {:?}", auto_matchmake_param); + //println!("auto_matchmake_with_param_postpone: {:?}", auto_matchmake_param); let locked_conn = conn.lock().await; let Some(secure_conn) = locked_conn.active_connection_data.as_ref().map(|a| a.active_secure_connection_data.as_ref()).flatten() else { @@ -38,35 +42,41 @@ pub async fn auto_matchmake_with_param_postpone( // up anything else unnescesarily drop(mm_data_read); - let gid = random(); - - let mut matchmake_session = auto_matchmake_param.matchmake_session.clone(); - matchmake_session.gathering.self_gid = gid; - matchmake_session.gathering.host_pid = pid; - matchmake_session.gathering.owner_pid = pid; - + let session = + ExtendedMatchmakeSession::from_matchmake_session(auto_matchmake_param.matchmake_session, &conn).await; + let gid = session.session.gathering.self_gid; let mut mm_data = mm_data.write().await; - let session = Arc::new(Mutex::new(ExtendedMatchmakeSession{ - session: matchmake_session.clone(), - connected_players: Vec::new() - })); + let session = Arc::new(Mutex::new(session)); mm_data.matchmake_sessions.insert(gid, session.clone()); session }; - let mut session = session.lock().await; + let mut locked_session = session.lock().await; //todo: refactor so that this works - session.add_player(socket, conn.clone(), auto_matchmake_param.join_message).await; + { + let session = session.clone(); + let socket = socket.clone(); + let connection = conn.clone(); + let join_msg = auto_matchmake_param.join_message.clone(); + tokio::spawn(async move{ + sleep(Duration::from_millis(500)).await; + println!("adding player"); + let mut session = session.lock().await; + session.add_player(&socket, connection, join_msg).await; + }); + } + + info!("new session: {:?}", locked_session); let mut response = Vec::new(); - session.session.serialize(&mut response).expect("unable to serialize matchmake session"); + locked_session.session.serialize(&mut response).expect("unable to serialize matchmake session"); rmcmessage.success_with_data(response) } diff --git a/src/protocols/matchmake_extension/method_create_matchmake_session_with_param.rs b/src/protocols/matchmake_extension/method_create_matchmake_session_with_param.rs new file mode 100644 index 0000000..fd31c55 --- /dev/null +++ b/src/protocols/matchmake_extension/method_create_matchmake_session_with_param.rs @@ -0,0 +1,62 @@ +use std::io::Cursor; +use std::sync::Arc; +use tokio::sync::{Mutex, RwLock}; +use crate::protocols::matchmake_common::{add_matchmake_session, ExtendedMatchmakeSession, MatchmakeData}; +use crate::protocols::matchmake_extension::method_auto_matchmake_with_param_postpone::auto_matchmake_with_param_postpone; +use crate::prudp::socket::{ConnectionData, SocketData}; +use crate::rmc::message::RMCMessage; +use crate::rmc::response::{ErrorCode, RMCResponseResult}; +use crate::rmc::structures::matchmake::{AutoMatchmakeParam, CreateMatchmakeSessionParam}; +use crate::rmc::structures::RmcSerialize; + +pub async fn create_matchmake_session_with_param( + rmcmessage: &RMCMessage, + conn: &Arc>, + socket: &Arc, + mm_data: Arc>, + create_matchmake_session: CreateMatchmakeSessionParam +) -> RMCResponseResult { + let locked_conn = conn.lock().await; + let Some(secure_conn) = + locked_conn.active_connection_data.as_ref().map(|a| a.active_secure_connection_data.as_ref()).flatten() else { + return rmcmessage.error_result_with_code(ErrorCode::Core_Exception); + }; + + println!("{:?}", create_matchmake_session); + + let pid = secure_conn.pid; + + let mut session = + ExtendedMatchmakeSession::from_matchmake_session(create_matchmake_session.matchmake_session, &conn).await; + + session.session.participation_count = create_matchmake_session.participation_count as u32; + + let session = add_matchmake_session(mm_data, session).await; + + let mut session = session.lock().await; + + session.add_player(&socket, conn.clone(), create_matchmake_session.join_message).await; + + let mut response = Vec::new(); + + session.session.serialize(&mut response).expect("unable to serialize session"); + + rmcmessage.success_with_data(response) +} + +pub async fn create_matchmake_session_with_param_raw_params( + rmcmessage: &RMCMessage, + socket: &Arc, + connection_data: &Arc>, + data: Arc> +) -> RMCResponseResult{ + let mut reader = Cursor::new(&rmcmessage.rest_of_data); + + let Ok(matchmake_param) = CreateMatchmakeSessionParam::deserialize(&mut reader) else { + return rmcmessage.error_result_with_code(ErrorCode::Core_InvalidArgument); + }; + + + + create_matchmake_session_with_param(rmcmessage, connection_data, socket, data, matchmake_param).await +} \ No newline at end of file diff --git a/src/protocols/matchmake_extension/mod.rs b/src/protocols/matchmake_extension/mod.rs index 509f3bb..ddca083 100644 --- a/src/protocols/matchmake_extension/mod.rs +++ b/src/protocols/matchmake_extension/mod.rs @@ -1,5 +1,6 @@ mod method_get_playing_session; mod method_auto_matchmake_with_param_postpone; +mod method_create_matchmake_session_with_param; use std::sync::Arc; use tokio::sync::{RwLock}; @@ -7,10 +8,12 @@ use crate::define_protocol; use crate::protocols::matchmake_common::MatchmakeData; use method_get_playing_session::get_playing_session_raw_params; use method_auto_matchmake_with_param_postpone::auto_matchmake_with_param_postpone_raw_params; +use crate::protocols::matchmake_extension::method_create_matchmake_session_with_param::create_matchmake_session_with_param_raw_params; define_protocol!{ 109(matchmake_data: Arc>) => { 16 => get_playing_session_raw_params, + 38 => create_matchmake_session_with_param_raw_params, 40 => auto_matchmake_with_param_postpone_raw_params } } \ No newline at end of file diff --git a/src/protocols/notification/mod.rs b/src/protocols/notification/mod.rs index 7c96090..daa33ee 100644 --- a/src/protocols/notification/mod.rs +++ b/src/protocols/notification/mod.rs @@ -15,17 +15,19 @@ pub struct Notification{ pub param_1: u32, pub param_2: u32, pub str_param: String, + pub param_3: u32, } impl ConnectionData{ pub async fn send_notification(&mut self, socket: &SocketData, notif: Notification){ + println!("sending notification"); let mut data = Vec::new(); notif.serialize(&mut data).expect("unable to write"); let message = RMCMessage{ - protocol_id: 0xE, + protocol_id: 14, method_id: 1, call_id: random(), rest_of_data: data @@ -43,6 +45,8 @@ impl ConnectionData{ packet_signature: [0;16] }; + + self.finish_and_send_packet_to(socket, prudp_packet).await; } } \ No newline at end of file diff --git a/src/prudp/socket.rs b/src/prudp/socket.rs index ecf0108..c7b93ee 100644 --- a/src/prudp/socket.rs +++ b/src/prudp/socket.rs @@ -1,4 +1,6 @@ +use log::info; use std::collections::{HashMap, VecDeque}; +use std::fmt::{Debug, Formatter}; use std::future::Future; use std::ops::Deref; use std::pin::Pin; @@ -29,6 +31,7 @@ pub struct Socket { type OnConnectHandlerFn = Box Pin, Vec, Option)>> + Send>> + Send + Sync>; type OnDataHandlerFn = Box, Arc>) -> Pin + Send>> + Send + Sync>; +#[derive(Debug)] pub struct ActiveSecureConnectionData { pub(crate) pid: u32, pub(crate) session_key: [u8; 32], @@ -49,6 +52,13 @@ pub struct EncryptionPair{ pub recv: Box } +impl Debug for EncryptionPair{ + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "Stubbed") + } +} + +#[derive(Debug)] pub struct ActiveConnectionData { pub reliable_client_counter: u16, pub reliable_server_counter: u16, @@ -60,6 +70,7 @@ pub struct ActiveConnectionData { } +#[derive(Debug)] pub struct ConnectionData { pub sock_addr: PRUDPSockAddr, pub id: u64, @@ -174,8 +185,8 @@ impl SocketData { // dont keep holding the connections list unnescesarily drop(connections); + let mutual_exclusion_packet_handeling_mtx = conn.1.lock().await; let mut connection = conn.0.lock().await; - //let _mutual_exclusion_packet_handeling_mtx = conn.1.lock().await; if (packet.header.types_and_flags.get_flags() & ACK) != 0 { //todo: handle acknowledgements and resending packets propperly @@ -387,6 +398,8 @@ impl SocketData { .. } = &mut *connection; + info!("got ping"); + if (packet.header.types_and_flags.get_flags() & NEED_ACK) != 0 { let Some(active_connection) = active_connection_data.as_mut() else { error!("got data packet on non active connection!"); @@ -438,6 +451,8 @@ impl SocketData { } _ => error!("unimplemented packet type: {}", packet.header.types_and_flags.get_types()) } + + drop(mutual_exclusion_packet_handeling_mtx) } } @@ -459,6 +474,10 @@ impl ConnectionData{ encryption.apply_keystream(&mut packet.payload); } + packet.header.session_id = self.active_connection_data.as_ref().map(|v| v.server_session_id).unwrap_or_default(); + + + packet.header.source_port = socket.virtual_port; packet.header.destination_port = self.sock_addr.virtual_port; diff --git a/src/rmc/structures/matchmake.rs b/src/rmc/structures/matchmake.rs index 72cb6a0..f11b432 100644 --- a/src/rmc/structures/matchmake.rs +++ b/src/rmc/structures/matchmake.rs @@ -3,7 +3,7 @@ use crate::kerberos::KerberosDateTime; use crate::rmc::structures::variant::Variant; // rmc structure -#[derive(RmcSerialize, Debug, Clone)] +#[derive(RmcSerialize, Debug, Clone, Default)] #[rmc_struct(0)] pub struct Gathering { pub self_gid: u32, @@ -19,7 +19,7 @@ pub struct Gathering { } // rmc structure -#[derive(RmcSerialize, Debug, Clone)] +#[derive(RmcSerialize, Debug, Clone, Default)] #[rmc_struct(0)] pub struct MatchmakeParam { pub params: Vec<(String, Variant)>, @@ -27,7 +27,7 @@ pub struct MatchmakeParam { // rmc structure -#[derive(RmcSerialize, Debug, Clone)] +#[derive(RmcSerialize, Debug, Clone, Default)] #[rmc_struct(3)] pub struct MatchmakeSession { //inherits from @@ -81,4 +81,16 @@ pub struct AutoMatchmakeParam { pub participation_count: u16, pub search_criteria: Vec, pub target_gids: Vec, -} \ No newline at end of file +} + +#[derive(RmcSerialize, Debug, Clone)] +#[rmc_struct(0)] +pub struct CreateMatchmakeSessionParam { + pub matchmake_session: MatchmakeSession, + pub additional_participants: Vec, + pub gid_for_participation_check: u32, + pub create_matchmake_session_option: u32, + pub join_message: String, + pub participation_count: u16, + +} diff --git a/src/rmc/structures/variant.rs b/src/rmc/structures/variant.rs index 7472b03..ebd25b8 100644 --- a/src/rmc/structures/variant.rs +++ b/src/rmc/structures/variant.rs @@ -3,8 +3,9 @@ use crate::kerberos::KerberosDateTime; use crate::rmc::structures; use crate::rmc::structures::RmcSerialize; -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Default)] pub enum Variant{ + #[default] None, SInt64(i64), Double(f64),