feat: refactor prudp code and start working on refactoring rmc

This commit is contained in:
DJMrTV 2025-02-18 22:55:33 +01:00
commit 3ea7c7e671
37 changed files with 2029 additions and 456 deletions

848
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -25,6 +25,9 @@ prost = "0.13.4"
hex = "0.4.3"
macros = { path = "macros" }
rocket = { version = "0.5.1", features = ["json", "serde_json"] }
serde = { version = "1.0.217", features = ["derive"] }
async-trait = "0.1.86"
[build-dependencies]
tonic-build = "0.12.3"

View file

@ -14,25 +14,21 @@ use simplelog::{ColorChoice, CombinedLogger, Config, LevelFilter, TerminalMode,
use tokio::sync::RwLock;
use tokio::task::JoinHandle;
use crate::nex::account::Account;
use crate::protocols::{auth, block_if_maintenance};
use crate::protocols::auth::AuthProtocolConfig;
use crate::protocols::matchmake_common::MatchmakeData;
use crate::protocols::server::RMCProtocolServer;
use crate::prudp::socket::{ActiveSecureConnectionData, EncryptionPair, Socket};
use crate::prudp::socket::{EncryptionPair, Unsecure};
use crate::prudp::packet::{VirtualPort};
use crate::prudp::router::Router;
use crate::prudp::secure::{generate_secure_encryption_pairs, read_secure_connection_data};
use crate::rmc::message::RMCMessage;
use crate::rmc::structures::RmcSerialize;
use crate::prudp::sockaddr::PRUDPSockAddr;
use crate::prudp::station_url::Type::PRUDP;
mod endianness;
mod prudp;
pub mod rmc;
mod protocols;
//mod protocols;
mod nex;
mod grpc;
mod kerberos;
mod web;
static KERBEROS_SERVER_PASSWORD: Lazy<String> = Lazy::new(||{
env::var("AUTH_SERVER_PASSWORD")
@ -97,6 +93,7 @@ async fn main() {
start_servers().await;
}
/*
struct AuthServer{
router: Arc<Router>,
@ -236,74 +233,66 @@ async fn start_secure_server() -> SecureServer{
router,
socket,
}
}
}*/
async fn start_servers(){
let a = tokio::spawn(async{
let (router_auth, _) =
Router::new(SocketAddrV4::new(*OWN_IP_PRIVATE, *AUTH_SERVER_PORT)).await.expect("unable to start router");
let mut socket_auth = router_auth.add_socket(VirtualPort::new(1,10), Unsecure("CD&ML")).await
.expect("unable to add socket");
let mut conn = socket_auth.accept().await.unwrap();
info!("got conn");
if let Some(data) = conn.recv().await{
let str = String::from_utf8(data).unwrap();
println!("{}", str)
}
});
let b = tokio::spawn(async{
let auth_ip = SocketAddrV4::new(*OWN_IP_PRIVATE, *AUTH_SERVER_PORT);
let auth_port = VirtualPort::new(1,10);
let auth_sockaddr = PRUDPSockAddr::new(auth_ip,auth_port);
let (router_secure, _) =
Router::new(SocketAddrV4::new(*OWN_IP_PRIVATE, *SECURE_SERVER_PORT)).await.expect("unable to start router");
let mut socket_secure = router_secure.add_socket(VirtualPort::new(1,10), Unsecure("CD&ML")).await
.expect("unable to add socket");
let conn = socket_secure.connect(auth_sockaddr).await.unwrap();
let conn = conn.duplicate_sender();
conn.send("Yippie".as_bytes().to_owned()).await;
info!("got conn");
});
a.await;
b.await;
/*
#[cfg(feature = "auth")]
let auth_server = start_auth_server().await;
#[cfg(feature = "secure")]
let secure_server = start_secure_server().await;
let web_server = web::start_web().await;
#[cfg(feature = "auth")]
auth_server.join_handle.await.expect("auth server crashed");
#[cfg(feature = "secure")]
secure_server.join_handle.await.expect("auth server crashed");
}
#[cfg(test)]
mod test{
use std::io::Cursor;
use std::num::ParseIntError;
use std::str::from_utf8;
use hmac::digest::consts::U5;
use rc4::{KeyInit, Rc4, StreamCipher};
use crate::prudp::packet::PRUDPPacket;
use crate::rmc;
fn from_hex_stream(val: &str) -> Result<Vec<u8>, ParseIntError> {
let res: Result<Vec<u8>, _> = val.as_bytes()
.chunks_exact(2)
.map(|c| from_utf8(c).expect("unable to convert back to string"))
.map(|s| u8::from_str_radix(s, 16))
.collect();
res
}
#[tokio::test]
async fn simulate_packets(){
let val = from_hex_stream("ead001037d00afa1e200a5000200d9e4a4050368c18c6de4e2fb1cc40f0c020100768744db99f92c5005a061fd2a1df280cd64d5c1a565952c6befa607cbaf34661312b16db0fa6fccfb81e28b5a3a9bed02b49152bbc99cc112b7e29b9e45ec3d4b89df0fe71390883d9a927c264d07ada0de9cd28499e3ccdf3fd079e4a9848d4d783778c42da2af06106a7326634dc5bec5c3438ef18e30109839ffcc").expect("uuuuh");
let mut packet = PRUDPPacket::new(&mut Cursor::new(&val)).expect("invalid packet");
let mut rc4: Rc4<U5> =
Rc4::new_from_slice("CD&ML".as_bytes().into()).expect("invalid key");
rc4.apply_keystream(&mut packet.payload);
println!("packet: {:?}", packet);
let rmc_packet = rmc::message::RMCMessage::new(&mut Cursor::new(&packet.payload)).expect("unable to read message");
let mut a = Cursor::new(&rmc_packet.rest_of_data);
//let pid = rmc::structures::string::read(&mut a).expect("unable to read pid");
}
#[tokio::test]
async fn simulate_packets_response(){
let val = from_hex_stream("ead001032501a1af6200a500010013ffcdbc3a2ebc44efc6e38ea32a72b40201002e8644db19fe2a5005a2637d2a16f3b1fe5633037c1ed61c5aefad8afebdf2ff8600e9350fba1298b570c70f6dd647eac2d3faf0ab74ef761e2ee43dc10e249e5f91aed6813dcc04b3c707d9442b6e353b9b0b654e98f860fe5379c41d3c2a1874b7dd37ebf499e03bd2fd3e9a9203c0959feb760c38f504dcd0c9e99b17fd410657da4efa3e01c8a68ab3042d6d489788d5580778d32249cdf1fba8bf68cf4019d116ea7c580622ea1e3635139d91b44635d5e95b6c35b33898fdc0117fa6fc7162840d07a49f1e7089aa0ea65409a8ddeb2334449ba73a0ff7de462cf4a706a696de0f0521b84ae5a3f8587f3585d202d3cc0fb0451519c1b830b5e3cdd6de52e9add7325cbbf08a7c2f8b875934942b226703a22b4bc8931932dab055049051e4144b02").expect("uuuuh");
let mut packet = PRUDPPacket::new(&mut Cursor::new(&val)).expect("invalid packet");
let mut rc4: Rc4<U5> =
Rc4::new_from_slice("CD&ML".as_bytes().into()).expect("invalid key");
rc4.apply_keystream(&mut packet.payload);
println!("packet: {:?}", packet);
}
web_server.await.expect("webserver crashed");*/
}

View file

@ -3,7 +3,6 @@ use std::sync::Arc;
use log::error;
use tokio::sync::Mutex;
use crate::protocols::auth::AuthProtocolConfig;
use crate::prudp::socket::{ConnectionData, SocketData};
use crate::rmc::message::RMCMessage;
use crate::rmc::response::{ErrorCode, RMCResponseResult};
use crate::rmc::structures::RmcSerialize;

View file

@ -7,7 +7,6 @@ use crate::grpc::account;
use crate::kerberos::KerberosDateTime;
use crate::protocols::auth::AuthProtocolConfig;
use crate::protocols::auth::ticket_generation::generate_ticket;
use crate::prudp::socket::{ConnectionData, SocketData};
use crate::rmc;
use crate::rmc::message::RMCMessage;
use crate::rmc::response::{ErrorCode, RMCResponseResult};

View file

@ -4,7 +4,6 @@ use tokio::sync::Mutex;
use crate::endianness::{IS_BIG_ENDIAN, ReadExtensions};
use crate::protocols::auth::{AuthProtocolConfig, get_login_data_by_pid};
use crate::protocols::auth::ticket_generation::generate_ticket;
use crate::prudp::socket::{ConnectionData, SocketData};
use crate::rmc::message::RMCMessage;
use crate::rmc::response::{ErrorCode, RMCResponseResult};
use crate::rmc::response::ErrorCode::Core_Unknown;

View file

@ -2,7 +2,6 @@ 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::qresult::QResult;

View file

@ -5,7 +5,6 @@ use rand::random;
use tokio::sync::{Mutex, RwLock};
use crate::kerberos::KerberosDateTime;
use crate::protocols::notification::Notification;
use crate::prudp::socket::{ActiveConnectionData, ConnectionData, SocketData};
use crate::rmc::structures::matchmake::{Gathering, MatchmakeParam, MatchmakeSession};
use crate::rmc::structures::variant::Variant;
@ -44,7 +43,7 @@ impl ExtendedMatchmakeSession{
let mm_session = MatchmakeSession{
gathering: Gathering{
self_gid: random(),
self_gid: 1,
owner_pid: active_secure_connection_data.pid,
host_pid: active_secure_connection_data.pid,
..session.gathering.clone()

View file

@ -7,7 +7,6 @@ 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, MatchmakeSession};

View file

@ -1,10 +1,11 @@
use std::io::Cursor;
use std::sync::Arc;
use std::time::Duration;
use log::info;
use tokio::sync::{Mutex, RwLock};
use tokio::time::sleep;
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};
@ -29,13 +30,17 @@ 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");
println!("{}", hex::encode(&response));
rmcmessage.success_with_data(response)
}
@ -51,7 +56,32 @@ pub async fn create_matchmake_session_with_param_raw_params(
return rmcmessage.error_result_with_code(ErrorCode::Core_InvalidArgument);
};
create_matchmake_session_with_param(rmcmessage, connection_data, socket, data, matchmake_param).await
}
#[cfg(test)]
mod test{
use std::io::Cursor;
use crate::prudp::packet::PRUDPPacket;
use crate::rmc::message::RMCMessage;
use crate::rmc::structures::matchmake::MatchmakeSession;
use crate::rmc::structures::RmcSerialize;
#[test]
fn test(){
let data = hex::decode("ead001030000a1af12001800050002010000000000000000000000000000000000").unwrap();
let packet = PRUDPPacket::new(&mut Cursor::new(data)).unwrap();
println!("{:?}", packet);
}
#[test]
fn test_2(){
let data = hex::decode("250000008e0100000001000000001700000051b39957b90b00000100000051b3995701000001000000").unwrap();
let msg = RMCMessage::new(&mut Cursor::new(data)).unwrap();
println!("{:?}", msg)
}
}

View file

@ -3,7 +3,6 @@ use std::sync::Arc;
use log::info;
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::RmcSerialize;

View file

@ -6,7 +6,6 @@ use log::warn;
use once_cell::sync::Lazy;
use tokio::sync::Mutex;
use crate::grpc;
use crate::prudp::socket::{ConnectionData, SocketData};
use crate::rmc::message::RMCMessage;
use crate::rmc::response::{ErrorCode, RMCResponse};
@ -17,7 +16,7 @@ pub mod secure;
pub mod matchmake_extension;
pub mod matchmake_common;
pub mod matchmake;
mod notification;
pub mod notification;
pub mod nat_traversal;
static IS_MAINTENANCE: Lazy<bool> = Lazy::new(|| {

View file

@ -1,8 +1,9 @@
use std::io::Cursor;
use std::sync::Arc;
use std::time::Duration;
use tokio::sync::{Mutex, RwLock};
use tokio::time::sleep;
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;
@ -12,6 +13,7 @@ pub async fn report_nat_properties(
socket: &Arc<SocketData>,
connection_data: &Arc<Mutex<ConnectionData>>,
) -> RMCResponseResult{
sleep(Duration::from_millis(50)).await;
rmcmessage.success_with_data(Vec::new())
}

View file

@ -3,7 +3,6 @@ use rand::random;
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;
@ -30,10 +29,11 @@ impl ConnectionData{
let message = RMCMessage{
protocol_id: 14,
method_id: 1,
call_id: random(),
call_id: 1,
rest_of_data: data
};
println!("notif: {}", hex::encode(message.to_data()));
let mut prudp_packet = PRUDPPacket{
@ -99,23 +99,6 @@ mod test{
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{

View file

@ -2,7 +2,6 @@ use std::io::{Cursor, Write};
use std::sync::Arc;
use bytemuck::bytes_of;
use tokio::sync::Mutex;
use crate::prudp::socket::{ConnectionData, SocketData};
use crate::prudp::station_url::{nat_types, StationUrl};
use crate::prudp::station_url::Type::PRUDPS;
use crate::prudp::station_url::UrlOptions::{Address, NatFiltering, NatMapping, NatType, Port, PrincipalID, RVConnectionID};

View file

@ -3,11 +3,11 @@ use std::sync::Arc;
use log::error;
use tokio::sync::Mutex;
use crate::endianness::{IS_BIG_ENDIAN, ReadExtensions};
use crate::prudp::socket::{ConnectionData, SocketData};
use crate::rmc::message::RMCMessage;
use crate::rmc::response::{RMCResponseResult};
use crate::rmc::response::ErrorCode::Core_InvalidArgument;
use crate::rmc::structures::qbuffer;
use crate::rmc::structures::{qbuffer, RmcSerialize};
use crate::rmc::structures::qbuffer::QBuffer;
pub async fn send_report(rmcmessage: &RMCMessage, report_id: u32, data: Vec<u8>) -> RMCResponseResult{
let result = tokio::fs::write(format!("./reports/{}", report_id), data).await;
@ -17,7 +17,7 @@ pub async fn send_report(rmcmessage: &RMCMessage, report_id: u32, data: Vec<u8>)
Err(e) => error!("{}", e)
}
return rmcmessage.success_with_data(Vec::new());
rmcmessage.success_with_data(Vec::new())
}
pub async fn send_report_raw_params(rmcmessage: &RMCMessage, _: &Arc<SocketData>, _conn_data: &Arc<Mutex<ConnectionData>>, _: ()) -> RMCResponseResult{
@ -27,7 +27,7 @@ pub async fn send_report_raw_params(rmcmessage: &RMCMessage, _: &Arc<SocketData>
return rmcmessage.error_result_with_code(Core_InvalidArgument);
};
let Ok(data) = qbuffer::read(&mut reader) else {
let Ok(QBuffer(data)) = QBuffer::deserialize(&mut reader) else {
return rmcmessage.error_result_with_code(Core_InvalidArgument);
};

View file

@ -5,10 +5,11 @@ use std::sync::Arc;
use log::error;
use tokio::sync::Mutex;
use crate::prudp::packet::PRUDPPacket;
use crate::prudp::socket::{ConnectionData, SocketData};
use crate::rmc::message::RMCMessage;
use crate::rmc::response::{RMCResponse, RMCResponseResult, send_response};
use crate::rmc::response::ErrorCode::Core_NotImplemented;
use crate::web::DirectionalData::Incoming;
use crate::web::WEB_DATA;
type ContainedProtocolList = Box<[Box<dyn for<'a> Fn(&'a RMCMessage, &'a Arc<SocketData>, &'a Arc<Mutex<ConnectionData>>) -> Pin<Box<dyn Future<Output = Option<RMCResponse>> + Send + 'a>> + Send + Sync>]>;
@ -20,6 +21,13 @@ impl RMCProtocolServer{
}
pub async fn process_message(&self, packet: PRUDPPacket, socket: Arc<SocketData>, connection: Arc<Mutex<ConnectionData>>){
let locked = connection.lock().await;
let addr = locked.sock_addr.regular_socket_addr;
drop(locked);
let mut web = WEB_DATA.lock().await;
web.data.push((addr, Incoming(hex::encode(&packet.payload))));
drop(web);
let Ok(rmc) = RMCMessage::new(&mut Cursor::new(&packet.payload)) else {
error!("error reading rmc message");
return;

View file

@ -2,6 +2,6 @@ pub mod packet;
pub mod router;
pub mod socket;
mod auth_module;
mod sockaddr;
pub mod secure;
pub mod sockaddr;
//pub mod secure;
pub mod station_url;

View file

@ -96,10 +96,11 @@ impl Debug for TypesFlags {
}
#[repr(transparent)]
#[derive(PartialEq, Eq, Copy, Clone, Pod, Zeroable, SwapEndian, Hash)]
#[derive(PartialEq, Eq, Ord, PartialOrd, Copy, Clone, Pod, Zeroable, SwapEndian, Hash)]
pub struct VirtualPort(pub(crate) u8);
impl VirtualPort {
#[inline]
pub const fn get_stream_type(self) -> u8 {
(self.0 & 0xF0) >> 4
@ -236,7 +237,7 @@ impl PacketOption{
}
}
#[derive(Debug, Clone, Eq, PartialEq)]
#[derive(Debug, Default, Clone, Eq, PartialEq)]
pub struct PRUDPPacket {
pub header: PRUDPHeader,
pub packet_signature: [u8; 16],
@ -375,6 +376,7 @@ impl PRUDPPacket {
types_and_flags: flags,
sequence_id: self.header.sequence_id,
substream_id: self.header.substream_id,
session_id: self.header.session_id,
..base.header
},
options,

View file

@ -11,7 +11,7 @@ use once_cell::sync::Lazy;
use log::{error, info, trace};
use thiserror::Error;
use tokio::sync::RwLock;
use crate::prudp::socket::SocketData;
use crate::prudp::socket::{new_socket_pair, AnyInternalSocket, CryptoHandler, ExternalSocket};
use crate::prudp::packet::{PRUDPPacket, VirtualPort};
use crate::prudp::router::Error::VirtualPortTaken;
@ -22,10 +22,9 @@ static SERVER_DATAGRAMS: Lazy<u8> = Lazy::new(||{
});
pub struct Router {
endpoints: RwLock<[Option<Arc<SocketData>>; 16]>,
endpoints: RwLock<[Option<Arc<dyn AnyInternalSocket>>; 16]>,
running: AtomicBool,
socket: Arc<UdpSocket>,
//pub auth_module: Arc<dyn AuthModule>
_no_outside_construction: PhantomData<()>
}
#[derive(Debug, Error)]
@ -36,9 +35,6 @@ pub enum Error{
impl Router {
fn process_prudp_packet(&self, _packet: &PRUDPPacket){
}
async fn process_prudp_packets<'a>(self: Arc<Self>, _socket: Arc<UdpSocket>, addr: SocketAddrV4, udp_message: Vec<u8>){
let mut stream = Cursor::new(&udp_message);
@ -69,7 +65,9 @@ impl Router {
trace!("sending packet to endpoint");
endpoint.process_packet(connection, &packet).await;
tokio::spawn(async move {
endpoint.recieve_packet(connection, packet).await
});
}
}
@ -88,6 +86,7 @@ impl Router {
continue;
};
let current_msg = &msg_buffer[0..len];
tokio::spawn(self.clone().process_prudp_packets(socket.clone(), addr, current_msg.to_vec()));
@ -144,18 +143,22 @@ impl Router {
}
// returns Some(()) i
pub(crate) async fn add_socket(&self, socket: Arc<SocketData>) -> Result<(), Error>{
pub(crate) async fn add_socket<E: CryptoHandler>(&self, virtual_port: VirtualPort, encryption: E)
-> Result<ExternalSocket, Error>{
let mut endpoints = self.endpoints.write().await;
let idx = socket.get_virual_port().get_port_number() as usize;
let idx = virtual_port.get_port_number() as usize;
if endpoints[idx].is_none() {
endpoints[idx] = Some(socket);
} else {
// dont create the socket if we dont need to
if !endpoints[idx].is_none(){
return Err(VirtualPortTaken(idx as u8));
}
Ok(())
let (internal, external) = new_socket_pair(virtual_port, encryption, self.socket.clone());
endpoints[idx] = Some(internal);
Ok(external)
}
pub fn get_own_address(&self) -> SocketAddrV4{

View file

@ -73,12 +73,12 @@ pub fn read_secure_connection_data(data: &[u8], act: &Account) -> Option<([u8; 3
type Rc4U32 = StreamCipherCoreWrapper<Rc4Core<U32>>;
pub fn generate_secure_encryption_pairs(mut session_key: [u8; 32], count: u8) -> Vec<EncryptionPair>{
pub fn generate_secure_encryption_pairs(mut session_key: [u8; 32], count: u8) -> Vec<EncryptionPair<Rc4<U32>>>{
let mut vec = Vec::with_capacity(count as usize);
vec.push(EncryptionPair{
send: Box::new(Rc4U32::new_from_slice(&session_key).expect("unable to create rc4")),
recv: Box::new(Rc4U32::new_from_slice(&session_key).expect("unable to create rc4"))
send: Rc4U32::new_from_slice(&session_key).expect("unable to create rc4"),
recv: Rc4U32::new_from_slice(&session_key).expect("unable to create rc4")
});
for _ in 1..=count{
@ -91,8 +91,8 @@ pub fn generate_secure_encryption_pairs(mut session_key: [u8; 32], count: u8) ->
}
vec.push(EncryptionPair{
send: Box::new(Rc4U32::new_from_slice(&session_key).expect("unable to create rc4")),
recv: Box::new(Rc4U32::new_from_slice(&session_key).expect("unable to create rc4"))
send: Rc4U32::new_from_slice(&session_key).expect("unable to create rc4"),
recv: Rc4U32::new_from_slice(&session_key).expect("unable to create rc4")
});
}

View file

@ -5,14 +5,24 @@ use crate::prudp::packet::VirtualPort;
type Md5Hmac = Hmac<md5::Md5>;
#[derive(Eq, PartialEq, Hash, Debug, Copy, Clone)]
#[derive(Eq, PartialEq, Hash, Debug, Copy, Clone, Ord, PartialOrd)]
pub struct PRUDPSockAddr{
pub regular_socket_addr: SocketAddrV4,
pub virtual_port: VirtualPort
}
impl PRUDPSockAddr{
pub fn calculate_connection_signature(&self) -> [u8; 16] {
pub fn new(regular_socket_addr: SocketAddrV4, virtual_port: VirtualPort) -> Self{
Self{
regular_socket_addr,
virtual_port
}
}
pub(super) fn calculate_connection_signature(&self) -> [u8; 16] {
let mut hmac = Md5Hmac::new_from_slice(&[0; 16]).expect("fuck");
let mut data = self.regular_socket_addr.ip().octets().to_vec();

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,7 @@
pub mod message;
pub mod structures;
pub mod response;
pub mod protocols;

17
src/rmc/protocols/mod.rs Normal file
View file

@ -0,0 +1,17 @@
use std::sync::Arc;
use async_trait::async_trait;
use tokio::sync::Mutex;
use crate::prudp::socket::ExternalConnection;
use crate::rmc::structures::connection_data::ConnectionData;
pub trait RmcCallable{
fn rmc_call(protocol_id: u8, method_id: u8, rest: Vec<u8>);
}
struct LocalRmcObjectWrapper<T: RmcCallable>(T);
impl<T: RmcCallable> LocalRmcObjectWrapper<T>{
pub fn new(object: T, conn: ExternalConnection) -> Self{
unimplemented!()
}
}

View file

@ -6,8 +6,10 @@ use crate::prudp::packet::{PRUDPPacket};
use crate::prudp::packet::flags::{NEED_ACK, RELIABLE};
use crate::prudp::packet::PacketOption::FragmentId;
use crate::prudp::packet::types::DATA;
use crate::prudp::socket::{ConnectionData, SocketData};
use crate::prudp::socket::ExternalConnection;
use crate::rmc::structures::qresult::ERROR_MASK;
use crate::web::DirectionalData::{Incoming, Outgoing};
use crate::web::WEB_DATA;
pub enum RMCResponseResult {
Success{
@ -76,33 +78,8 @@ pub fn generate_response(protocol_id: u8, response: RMCResponseResult) -> io::Re
Ok(data_out)
}
pub async fn send_response(original_packet: &PRUDPPacket, socket: &SocketData, connection: &mut ConnectionData, rmcresponse: RMCResponse){
let ConnectionData{
active_connection_data,
..
} = connection;
let Some(active_connection) = active_connection_data else {
return;
};
let mut packet = original_packet.base_response_packet();
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.substream_id = 0;
packet.options.push(FragmentId(0));
packet.payload = rmcresponse.to_data();
//tokio::time::sleep(Duration::from_millis(500)).await;
connection.finish_and_send_packet_to(socket, packet).await;
pub async fn send_response(original_packet: &PRUDPPacket, connection: &mut ExternalConnection, rmcresponse: RMCResponse){
connection.send(rmcresponse.to_data()).await;
}
//taken from kinnays error list directly

View file

@ -30,6 +30,7 @@ pub mod qbuffer;
pub mod primitives;
pub mod matchmake;
pub mod variant;
mod ranking;
pub trait RmcSerialize: Sized{
fn serialize(&self, writer: &mut dyn Write) -> Result<()>;

View file

@ -1,12 +1,30 @@
use std::io::Read;
use std::io::{Read, Write};
use bytemuck::bytes_of;
use crate::endianness::{IS_BIG_ENDIAN, ReadExtensions};
use crate::rmc::structures::Result;
pub fn read(reader: &mut impl Read) -> Result<Vec<u8>>{
let size: u16 = reader.read_struct(IS_BIG_ENDIAN)?;
use crate::rmc::structures::{Result, RmcSerialize};
use crate::rmc::structures::qresult::QResult;
let mut vec = vec![0; size as usize];
reader.read_exact(&mut vec)?;
#[derive(Debug)]
pub struct QBuffer(pub Vec<u8>);
Ok(vec)
impl RmcSerialize for QBuffer{
fn serialize(&self, writer: &mut dyn Write) -> Result<()> {
let len_u16 = self.0.len() as u16;
writer.write(bytes_of(&len_u16))?;
writer.write(&self.0)?;
Ok(())
}
fn deserialize(mut reader: &mut dyn Read) -> Result<Self> {
let size: u16 = reader.read_struct(IS_BIG_ENDIAN)?;
let mut vec = vec![0; size as usize];
reader.read_exact(&mut vec)?;
Ok(Self(vec))
}
}

View file

@ -0,0 +1,69 @@
use bytemuck::{Pod, Zeroable};
use macros::RmcSerialize;
use crate::rmc::structures::qbuffer::QBuffer;
#[derive(RmcSerialize, Debug)]
#[rmc_struct(0)]
struct UploadCompetitionData{
winning_team/*?*/: u32,
splatfest_id/*?*/: u32,
unk_2/*?*/: u32,
unk_3: u32,
team_id_1: u8,
team_id_2: u8,
unk_5: u32,
player_data/*?*/: QBuffer,
}
#[derive(Copy, Clone, Pod, Zeroable)]
#[repr(C)]
struct UserData{
name: [u16; 0x10],
}
#[cfg(test)]
mod test{
use std::io::Cursor;
use bytemuck::from_bytes;
use tokio::io::AsyncReadExt;
use crate::rmc::structures::ranking::{UploadCompetitionData, UserData};
use crate::rmc::structures::RmcSerialize;
#[test]
fn test() {
let data: [u8; 0xBD] = [
0x00, 0xB8, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xFC, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00,
0x00, 0x1F, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0xA0, 0x00, 0x00, 0x49, 0x00,
0x7A, 0x00, 0x7A, 0x00, 0x79, 0x00, 0x53, 0x00, 0x50, 0x00, 0x46, 0x00, 0x4E, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0xF2, 0x00, 0x00, 0x00,
0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x1F, 0x5E, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, 0x90, 0x00, 0x00, 0x00,
0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x0A, 0x00, 0x00, 0x14, 0x87, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
0x02, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x4C, 0x00, 0x00, 0x00,
];
let mut cursor = Cursor::new(data);
let data = UploadCompetitionData::deserialize(&mut cursor).expect("unable to deserialize data");
let user_data: &UserData = from_bytes(&data.player_data.0[..size_of::<UserData>()]);
let pos = user_data.name.iter()
.position(|v| *v == 0x0000)
.unwrap_or(0x10);
let mut name = user_data.name[0..pos].to_vec();
name.iter_mut().for_each(|v| *v = v.swap_bytes());
let name = String::from_utf16(&name).expect("unable to get name");
println!("{:?}", name);
assert!(u8::deserialize(&mut cursor).is_err())
}
}

View file

@ -36,3 +36,4 @@ impl RmcSerialize for &str{
Ok(())
}
}

37
src/web/mod.rs Normal file
View file

@ -0,0 +1,37 @@
use std::net::SocketAddrV4;
use once_cell::sync::Lazy;
use rocket::{get, routes, Rocket};
use rocket::serde::json::Json;
use tokio::task::JoinHandle;
use serde::Serialize;
use tokio::sync::Mutex;
#[get("/")]
async fn server_data() -> Json<WebData> {
Json(WEB_DATA.lock().await.clone())
}
pub async fn start_web() -> JoinHandle<()>{
tokio::spawn(async{
rocket::build()
.mount("/",routes![server_data])
.launch().await
.expect("unable to start webserver");
})
}
#[derive(Serialize, Clone)]
pub enum DirectionalData{
Incoming(String),
Outgoing(String)
}
#[derive(Serialize, Default, Clone)]
pub struct WebData{
pub data: Vec<(SocketAddrV4, DirectionalData)>
}
pub static WEB_DATA: Lazy<Mutex<WebData>> = Lazy::new(|| Mutex::new(
WebData{
data: Vec::new(),
}
));