feat(matchmake): a bunch of things

This commit is contained in:
DJMrTV 2025-02-12 18:46:29 +01:00
commit 7d24a71f09
13 changed files with 220 additions and 30 deletions

View file

@ -66,7 +66,7 @@ impl KerberosDateTime{
#[inline]
pub fn get_month(&self) -> u8{
((self.0 >> 22) & 0b111111) as u8
((self.0 >> 22) & 0b1111) as u8
}
#[inline]
@ -154,3 +154,17 @@ impl Ticket{
data.into_boxed_slice()
}
}
#[cfg(test)]
mod test{
use chrono::{Datelike, Utc};
use crate::kerberos::KerberosDateTime;
#[test]
fn kerberos_time_convert_test(){
let time = KerberosDateTime(135904948834);
println!("{}", time.to_regular_time().to_rfc2822());
}
}

View file

@ -64,11 +64,9 @@ static OWN_IP_PRIVATE: Lazy<Ipv4Addr> = Lazy::new(||{
.expect("no public ip specified")
});
static OWN_IP_PUBLIC: Lazy<Ipv4Addr> = Lazy::new(||{
static OWN_IP_PUBLIC: Lazy<String> = Lazy::new(||{
env::var("SERVER_IP_PUBLIC")
.ok()
.and_then(|s| s.parse().ok())
.unwrap_or(*OWN_IP_PRIVATE)
.unwrap_or(OWN_IP_PRIVATE.to_string())
});
static SECURE_STATION_URL: Lazy<String> = Lazy::new(||
@ -194,7 +192,8 @@ async fn start_secure_server() -> SecureServer{
Box::new(block_if_maintenance),
Box::new(protocols::secure::bound_protocol()),
Box::new(protocols::matchmake::bound_protocol(matchmake_data.clone())),
Box::new(protocols::matchmake_extension::bound_protocol(matchmake_data))
Box::new(protocols::matchmake_extension::bound_protocol(matchmake_data)),
Box::new(protocols::nat_traversal::bound_protocol())
]));
let socket =

View file

@ -57,6 +57,7 @@ impl ExtendedMatchmakeSession{
("@GIR".to_owned(), Variant::SInt64(3))
]
},
system_password_enabled: false,
..session
};

View file

@ -1,5 +1,6 @@
use std::io::Cursor;
use std::sync::Arc;
use log::info;
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;
@ -16,15 +17,6 @@ pub async fn create_matchmake_session_with_param(
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;
@ -37,8 +29,11 @@ pub async fn create_matchmake_session_with_param(
session.add_player(&socket, conn.clone(), create_matchmake_session.join_message).await;
println!("{:?}", session);
let mut response = Vec::new();
session.session.serialize(&mut response).expect("unable to serialize session");
rmcmessage.success_with_data(response)

View file

@ -18,6 +18,7 @@ pub mod matchmake_extension;
pub mod matchmake_common;
pub mod matchmake;
mod notification;
pub mod nat_traversal;
static IS_MAINTENANCE: Lazy<bool> = Lazy::new(|| {
env::var("IS_MAINTENANCE")

View file

@ -0,0 +1,27 @@
use std::io::Cursor;
use std::sync::Arc;
use tokio::sync::{Mutex, RwLock};
use crate::protocols::matchmake_common::MatchmakeData;
use crate::prudp::socket::{ConnectionData, SocketData};
use crate::rmc::message::RMCMessage;
use crate::rmc::response::{ErrorCode, RMCResponseResult};
use crate::rmc::structures::matchmake::CreateMatchmakeSessionParam;
pub async fn report_nat_properties(
rmcmessage: &RMCMessage,
socket: &Arc<SocketData>,
connection_data: &Arc<Mutex<ConnectionData>>,
) -> RMCResponseResult{
rmcmessage.success_with_data(Vec::new())
}
pub async fn report_nat_properties_raw_params(
rmcmessage: &RMCMessage,
socket: &Arc<SocketData>,
connection_data: &Arc<Mutex<ConnectionData>>,
_: ()
) -> RMCResponseResult{
let mut reader = Cursor::new(&rmcmessage.rest_of_data);
report_nat_properties(rmcmessage, socket, connection_data).await
}

View file

@ -0,0 +1,10 @@
mod method_report_nat_properties;
use crate::define_protocol;
use crate::protocols::nat_traversal::method_report_nat_properties::report_nat_properties_raw_params;
define_protocol!{
3() => {
5 => report_nat_properties_raw_params
}
}

View file

@ -1,13 +1,13 @@
use macros::RmcSerialize;
use rand::random;
use crate::prudp::packet::{PRUDPHeader, PRUDPPacket, TypesFlags};
use crate::prudp::packet::{PRUDPHeader, PRUDPPacket, PacketOption, TypesFlags};
use crate::prudp::packet::flags::{NEED_ACK, RELIABLE};
use crate::prudp::packet::types::DATA;
use crate::prudp::socket::{ConnectionData, SocketData};
use crate::rmc::message::RMCMessage;
use crate::rmc::structures::RmcSerialize;
#[derive(RmcSerialize)]
#[derive(Debug, Eq, PartialEq, RmcSerialize)]
#[rmc_struct(0)]
pub struct Notification{
pub pid_source: u32,
@ -18,6 +18,7 @@ pub struct Notification{
pub param_3: u32,
}
impl ConnectionData{
pub async fn send_notification(&mut self, socket: &SocketData, notif: Notification){
println!("sending notification");
@ -33,20 +34,143 @@ impl ConnectionData{
rest_of_data: data
};
let prudp_packet = PRUDPPacket{
let mut prudp_packet = PRUDPPacket{
header: PRUDPHeader{
types_and_flags: TypesFlags::default().types(DATA).flags(NEED_ACK | RELIABLE),
source_port: socket.get_virual_port(),
destination_port: self.sock_addr.virtual_port,
..Default::default()
},
options: Vec::new(),
options: vec![
PacketOption::FragmentId(0),
],
payload: message.to_data(),
packet_signature: [0;16]
};
self.finish_and_send_packet_to(socket, prudp_packet).await;
}
}
#[cfg(test)]
mod test{
use std::io::Cursor;
use rand::random;
use crate::protocols::notification::Notification;
use crate::prudp::packet::{PRUDPHeader, PRUDPPacket, PacketOption, TypesFlags};
use crate::prudp::packet::flags::{NEED_ACK, RELIABLE};
use crate::prudp::packet::types::DATA;
use crate::rmc::message::RMCMessage;
use crate::rmc::structures::RmcSerialize;
#[test]
fn test(){
let data = hex::decode("ead001032900a1af62000000000000000000000000000000000000000000020100250000000e57238a6601000000001700000051b39957b90b00003661636851b3995701000001000000").unwrap();
let packet = PRUDPPacket::new(&mut Cursor::new(data)).expect("invalid packet");
println!("{:?}", packet);
let rmc = RMCMessage::new(&mut Cursor::new(packet.payload)).expect("invalid rmc message");
println!("{:?}", rmc);
let notif = Notification::deserialize(&mut Cursor::new(rmc.rest_of_data)).expect("invalid notification");
println!("{:?}", notif);
}
#[test]
fn test2(){
let data = hex::decode("250000000e57b6801001000000001700000051b39957b90b0000248a5a9851b3995701000001000000").unwrap();
//let packet = PRUDPPacket::new(&mut Cursor::new(data)).expect("invalid packet");
//println!("{:?}", packet);
let rmc = RMCMessage::new(&mut Cursor::new(data)).expect("invalid rmc message");
println!("{:?}", rmc);
let notif = Notification::deserialize(&mut Cursor::new(rmc.rest_of_data)).expect("invalid notification");
println!("{:?}", notif);
}
#[test]
fn test3(){
let data = hex::decode("ead001032900a1af620084000300020100250000008e0100000001000000001700000051b39957b90b00000100000051b399570100000100000000000000000000000000000000000000").unwrap();
let packet = PRUDPPacket::new(&mut Cursor::new(data)).expect("invalid packet");
println!("{:?}", packet);
let rmc = RMCMessage::new(&mut Cursor::new(packet.payload)).expect("invalid rmc message");
println!("{:?}", rmc);
let notif = Notification::deserialize(&mut Cursor::new(rmc.rest_of_data)).expect("invalid notification");
println!("{:?}", notif);
}
#[test]
fn test_rmc_serialization(){
let notif = Notification{
pid_source: random(),
notif_type: random(),
param_1: random(),
param_2: random(),
str_param: "".to_string(),
param_3: random(),
};
let mut notif_data = Vec::new();
notif.serialize(&mut notif_data).unwrap();
let message = RMCMessage{
protocol_id: 14,
method_id: 1,
call_id: random(),
rest_of_data: notif_data
};
let mut prudp_packet = PRUDPPacket{
header: PRUDPHeader{
..Default::default()
},
options: vec![
PacketOption::FragmentId(0),
],
payload: message.to_data(),
packet_signature: [0;16]
};
prudp_packet.set_sizes();
let mut packet_data: Vec<u8> = Vec::new();
prudp_packet.write_to(&mut packet_data).expect("what");
let packet_deserialized = PRUDPPacket::new(&mut Cursor::new(packet_data)).unwrap();
assert_eq!(prudp_packet, packet_deserialized);
let message_deserialized = RMCMessage::new(&mut Cursor::new(packet_deserialized.payload)).unwrap();
assert_eq!(message, message_deserialized);
let notification_deserialized = Notification::deserialize(&mut Cursor::new(message_deserialized.rest_of_data)).unwrap();
assert_eq!(notification_deserialized, notif);
}
}

View file

@ -29,7 +29,9 @@ impl RMCProtocolServer{
for proto in &self.0 {
if let Some(response) = proto(&rmc, &socket, &connection).await {
if matches!(response.response_result, RMCResponseResult::Error {..}){
error!("an rmc error occurred")
}
let mut locked = connection.lock().await;
send_response(&packet, &socket, &mut locked, response).await;
drop(locked);

View file

@ -40,7 +40,7 @@ pub enum Error {
pub type Result<T> = std::result::Result<T, Error>;
#[repr(transparent)]
#[derive(Copy, Clone, Pod, Zeroable, SwapEndian, Default)]
#[derive(Copy, Clone, Pod, Zeroable, SwapEndian, Default, Eq, PartialEq)]
pub struct TypesFlags(u16);
impl TypesFlags {
@ -141,7 +141,7 @@ impl Debug for VirtualPort {
}
#[repr(C)]
#[derive(Debug, Copy, Clone, Pod, Zeroable, SwapEndian)]
#[derive(Debug, Copy, Clone, Pod, Zeroable, SwapEndian, Eq, PartialEq)]
pub struct PRUDPHeader {
pub magic: [u8; 2],
pub version: u8,
@ -173,7 +173,7 @@ impl Default for PRUDPHeader{
}
#[derive(Debug, Clone)]
#[derive(Debug, Clone, Eq, PartialEq)]
pub enum PacketOption{
SupportedFunctions(u32),
ConnectionSignature([u8; 16]),
@ -236,7 +236,7 @@ impl PacketOption{
}
}
#[derive(Debug, Clone)]
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct PRUDPPacket {
pub header: PRUDPHeader,
pub packet_signature: [u8; 16],
@ -290,9 +290,12 @@ impl PRUDPPacket {
let packet_signature: [u8; 16] = reader.read_struct(IS_BIG_ENDIAN)?;
//let packet_signature: [u8; 16] = [0; 16];
assert_eq!(reader.stream_position().ok(), Some(14 + 16));
let mut packet_specific_buffer = vec![0u8; header.packet_specific_size as usize];
reader.read_exact(&mut packet_specific_buffer)?;
@ -474,6 +477,8 @@ impl PRUDPPacket {
#[cfg(test)]
mod test {
use crate::prudp::packet::flags::{NEED_ACK, RELIABLE};
use crate::prudp::packet::types::DATA;
use super::{OptionId, PacketOption, PRUDPHeader, TypesFlags, VirtualPort};
#[test]
fn size_test() {
@ -523,4 +528,13 @@ mod test {
let header_data: [u8; 8] = bytes.try_into().unwrap();
}
#[test]
fn test_types_flags(){
let types = TypesFlags::default().types(DATA).flags(NEED_ACK | RELIABLE);
assert_ne!((types.0 >> 4) & NEED_ACK, 0);
assert_ne!((types.0 >> 4) & RELIABLE, 0);
assert_ne!((types.0 & 0xFF) as u8 & DATA, 0);
}
}

View file

@ -195,7 +195,7 @@ impl SocketData {
}
if (packet.header.types_and_flags.get_flags() & MULTI_ACK) != 0 {
println!("got ack");
println!("got multi ack");
return;
}
@ -458,6 +458,8 @@ impl SocketData {
impl ConnectionData{
pub async fn finish_and_send_packet_to(&mut self, socket: &SocketData, mut packet: PRUDPPacket){
if (packet.header.types_and_flags.get_flags() & RELIABLE) != 0{
let Some(active_connection) = self.active_connection_data.as_mut() else {
error!("tried to send a secure packet to an inactive connection");
@ -491,7 +493,6 @@ impl ConnectionData{
packet.calculate_and_assign_signature(socket.access_key, potential_session_key, Some(self.server_signature));
let mut vec = Vec::new();
packet.write_to(&mut vec).expect("somehow failed to convert backet to bytes");

View file

@ -5,7 +5,7 @@ use log::error;
use crate::endianness::{IS_BIG_ENDIAN, ReadExtensions};
use crate::rmc::response::{ErrorCode, RMCResponseResult};
#[derive(Debug, Clone)]
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct RMCMessage{
pub protocol_id: u16,
pub call_id: u32,
@ -60,13 +60,15 @@ impl RMCMessage{
output.write_all(bytes_of(&size)).expect("unable to write size");
let proto_id = self.protocol_id as u8;
let proto_id = self.protocol_id as u8 | 0x80;
output.write_all(bytes_of(&proto_id)).expect("unable to write size");
output.write_all(bytes_of(&self.call_id)).expect("unable to write size");
output.write_all(bytes_of(&self.method_id)).expect("unable to write size");
output.write_all(&self.rest_of_data).expect("unable to write data");
output
}

View file

@ -93,7 +93,7 @@ pub async fn send_response(original_packet: &PRUDPPacket, socket: &SocketData, c
packet.header.types_and_flags.set_types(DATA);
packet.header.types_and_flags.set_flag((original_packet.header.types_and_flags.get_flags() & RELIABLE) | NEED_ACK);
packet.header.session_id = active_connection.server_session_id;
//packet.header.session_id = active_connection.server_session_id;
packet.header.substream_id = 0;
packet.options.push(FragmentId(0));