feat(matchmake): add create_matchmake_session_with_param and change some/add other stuff

This commit is contained in:
DJMrTV 2025-02-08 11:54:49 +01:00
commit c6b83b3ad9
9 changed files with 220 additions and 36 deletions

View file

@ -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);

View file

@ -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<Arc<Mutex<ConnectionData>>>,
@ -16,22 +20,75 @@ pub struct MatchmakeData{
}
impl ExtendedMatchmakeSession{
pub async fn from_matchmake_session(session: MatchmakeSession, host: &Mutex<ConnectionData>) -> 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<Mutex<ConnectionData>>, 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<RwLock<MatchmakeData>>,session: ExtendedMatchmakeSession) -> Arc<Mutex<ExtendedMatchmakeSession>> {
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<Arc<Mutex<ExtendedMatchmakeSession>>>{
None
}

View file

@ -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<RwLock<MatchmakeData>>,
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)
}

View file

@ -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<Mutex<ConnectionData>>,
socket: &Arc<SocketData>,
mm_data: Arc<RwLock<MatchmakeData>>,
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<SocketData>,
connection_data: &Arc<Mutex<ConnectionData>>,
data: Arc<RwLock<MatchmakeData>>
) -> 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
}

View file

@ -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<RwLock<MatchmakeData>>) => {
16 => get_playing_session_raw_params,
38 => create_matchmake_session_with_param_raw_params,
40 => auto_matchmake_with_param_postpone_raw_params
}
}

View file

@ -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;
}
}

View file

@ -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<dyn Fn(PRUDPPacket, u8) -> Pin<Box<dyn Future<Output=Option<(Vec<u8>, Vec<EncryptionPair>, Option<ActiveSecureConnectionData>)>> + Send>> + Send + Sync>;
type OnDataHandlerFn = Box<dyn Fn(PRUDPPacket, Arc<SocketData>, Arc<Mutex<ConnectionData>>) -> Pin<Box<dyn Future<Output=()> + 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<dyn StreamCipher + Send>
}
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;

View file

@ -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<MatchmakeSessionSearchCriteria>,
pub target_gids: Vec<u32>,
}
}
#[derive(RmcSerialize, Debug, Clone)]
#[rmc_struct(0)]
pub struct CreateMatchmakeSessionParam {
pub matchmake_session: MatchmakeSession,
pub additional_participants: Vec<u32>,
pub gid_for_participation_check: u32,
pub create_matchmake_session_option: u32,
pub join_message: String,
pub participation_count: u16,
}

View file

@ -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),