diff --git a/rnex-core/Cargo.toml b/rnex-core/Cargo.toml index 56991b1..6617a92 100644 --- a/rnex-core/Cargo.toml +++ b/rnex-core/Cargo.toml @@ -44,7 +44,8 @@ guest_login = [] friends = ["guest_login", "database-support"] big_pid = [] v3-3-2 = [] -v3-8-15 = ["rmc_struct_header", "v3-3-2"] +v3-5-0 = ["v3-3-2"] +v3-8-15 = ["rmc_struct_header", "v3-5-0"] v4-3-11 = ["v3-8-15"] nx = ["big_pid"] datastore = ["database-support", "v3-8-15", "dep:aws-sdk-s3", "dep:aws-config"] diff --git a/rnex-core/src/main.rs b/rnex-core/src/main.rs deleted file mode 100644 index eda5915..0000000 --- a/rnex-core/src/main.rs +++ /dev/null @@ -1,127 +0,0 @@ -#![allow(dead_code)] -#![allow(async_fn_in_trait)] -//#![warn(missing_docs)] - -//! # Splatoon RNEX server -//! -//! This server still includes the code for rnex itself as this is the first rnex server and thus -//! also the first and only current usage of rnex, expect this and rnex to be split into seperate -//! repos soon. - -extern crate self as rust_nex; - -use once_cell::sync::Lazy; -use std::hint::black_box; - -mod prudp; -pub mod rmc; -//mod protocols; - -mod grpc; -mod kerberos; -mod nex; -mod result; -mod versions; -pub mod reggie; -pub mod util; -pub mod common; - -pub mod config{ - pub const FEATURE_HAS_STRUCT_HEADER: bool = cfg!(feature = "rmc_struct_header"); -} - -use std::io::Cursor; -use std::ops::Deref; -use rnex_core::kerberos::KerberosDateTime; -use rnex_core::rmc::structures::matchmake::{AutoMatchmakeParam, Gathering, MatchmakeParam, MatchmakeSession, MatchmakeSessionSearchCriteria}; -use rnex_core::rmc::structures::RmcSerialize; -use rnex_core::rmc::structures::variant::Variant; - -static DUMMY: Lazy = Lazy::new(|| AutoMatchmakeParam{ - additional_participants: vec![1,2,3,4], - auto_matchmake_option: 10, - gid_for_participation_check: 9, - join_message: "hi".to_string(), - participation_count: 32, - target_gids: vec![45,2,51,1,1,1,1], - search_criteria: vec![MatchmakeSessionSearchCriteria{ - attribs: vec!["hi".to_string(), "ig".to_string(), "gotta put data here".to_string()], - exclude_locked: true, - exclude_non_host_pid: false, - exclude_system_password_set: true, - exclude_user_password_set: false, - game_mode: "some gamemode".to_string(), - matchmake_param: MatchmakeParam{ - params: vec![ - ("SR".to_string(), Variant::Bool(true)), - ("SR2".to_string(), Variant::Double(1.0)), - ("SR3".to_string(), Variant::SInt64(42)), - ("SR4".to_string(), Variant::String("test".to_string())) - ] - }, - matchmake_system_type: "some type".to_string(), - maximum_participants: "???".to_string(), - minimum_participants: "-99".to_string(), - refer_gid: 123, - selection_method: 9999999, - vacant_only: true, - vacant_participants: 1000 - }], - matchmake_session: MatchmakeSession{ - refer_gid: 10, - matchmake_system_type: 139, - matchmake_param: MatchmakeParam{ - params: vec![ - ("QSR".to_string(), Variant::Bool(false)), - ("SRQ2".to_string(), Variant::Double(1.1)), - ("SQR3".to_string(), Variant::SInt64(422)), - ("SDR4".to_string(), Variant::String("tetst".to_string())) - ] - }, - participation_count: 99, - application_buffer: vec![1,2,3,4,5,6,7,8,9], - attributes: vec![10,20,99,100000], - datetime: KerberosDateTime::now(), - gamemode: 111, - open_participation: false, - option0: 100, - progress_score: 1, - system_password_enabled: false, - user_password: "aaa".to_string(), - session_key: vec![91,123,5,2,1,2,4,124,4], - user_password_enabled: false, - gathering: Gathering{ - minimum_participants: 1, - maximum_participants: 12, - description: "aaargh".to_string(), - flags: 100, - host_pid: 999999919, - owner_pid: 138830, - participant_policy: 1, - policy_argument: 99837, - self_gid: 129, - state: 1389488 - } - } -}); - -static DUMMY_SER: Lazy> = Lazy::new(|| serialize_to_vec(DUMMY.deref())); - -fn serialize_to_vec(r: &impl RmcSerialize) -> Vec{ - let vec = r.to_data(); - - vec.unwrap() -} - -fn read_struct(r: &[u8]) -> T{ - T::deserialize(&mut Cursor::new(r)).unwrap() -} - -fn main(){ - for _ in 0..10000000 { - let v = serialize_to_vec(black_box(DUMMY.deref())); - let u = read_struct::(black_box(DUMMY_SER.deref().as_slice())); - black_box(v); - black_box(u); - } -} \ No newline at end of file diff --git a/rnex-core/src/nex/matchmake.rs b/rnex-core/src/nex/matchmake.rs index 0a18f74..8ab6105 100644 --- a/rnex-core/src/nex/matchmake.rs +++ b/rnex-core/src/nex/matchmake.rs @@ -1,12 +1,12 @@ -use crate::nex::user::User; -use crate::rmc::protocols::notifications::{NotificationEvent, RemoteNotification}; use log::info; use rand::random; use rnex_core::PID; use rnex_core::kerberos::KerberosDateTime; +use rnex_core::nex::user::User; use rnex_core::rmc::protocols::notifications::notification_types::{ HOST_CHANGED, OWNERSHIP_CHANGED, }; +use rnex_core::rmc::protocols::notifications::{NotificationEvent, RemoteNotification}; use rnex_core::rmc::response::ErrorCode; use rnex_core::rmc::response::ErrorCode::{Core_InvalidArgument, RendezVous_SessionVoid}; use rnex_core::rmc::structures::matchmake::gathering_flags::PERSISTENT_GATHERING; @@ -155,28 +155,47 @@ impl ExtendedMatchmakeSession { return Default::default(); }; - let mm_session = MatchmakeSession { - gathering: Gathering { - self_gid: gid, - owner_pid: host.pid, - host_pid: host.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)), - ], - }, - system_password_enabled: false, - ..session - }; + cfg_if::cfg_if! { + if #[cfg(feature = "v3-5-0")]{ + let mm_session = MatchmakeSession { + gathering: Gathering { + self_gid: gid, + owner_pid: host.pid, + host_pid: host.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)), + ], + }, + system_password_enabled: false, + ..session + }; - Self { - session: mm_session, - connected_players: Default::default(), + return Self { + session: mm_session, + connected_players: Default::default(), + } + } else { + let mm_session = MatchmakeSession { + gathering: Gathering { + self_gid: gid, + owner_pid: host.pid, + host_pid: host.pid, + ..session.gathering.clone() + }, + session_key: (0..32).map(|_| random()).collect(), + ..session + }; + return Self { + session: mm_session, + connected_players: Default::default(), + } + } } } @@ -212,6 +231,7 @@ impl ExtendedMatchmakeSession { param_1: self.session.gathering.self_gid as PID, param_2: other_pid, str_param: "".into(), + #[cfg(feature = "v3-5-0")] param_3: 0, }) .await; @@ -244,6 +264,7 @@ impl ExtendedMatchmakeSession { param_1: self.session.gathering.self_gid as PID, param_2: *pid, str_param: join_msg.clone(), + #[cfg(feature = "v3-5-0")] param_3: self.connected_players.len() as _, }) .await; @@ -266,6 +287,7 @@ impl ExtendedMatchmakeSession { param_1: self.session.gathering.self_gid as PID, param_2: new_conn_pid, str_param: join_msg.clone(), + #[cfg(feature = "v3-5-0")] param_3: self.connected_players.len() as _, }) .await; @@ -318,15 +340,19 @@ impl ExtendedMatchmakeSession { } } - if search_criteria.exclude_system_password_set { - if self.session.system_password_enabled { - return Ok(false); - } - } + cfg_if::cfg_if! { + if #[cfg(feature = "v3-5-0")]{ + if search_criteria.exclude_system_password_set { + if self.session.system_password_enabled { + return Ok(false); + } + } - if search_criteria.exclude_user_password_set { - if self.session.user_password_enabled { - return Ok(false); + if search_criteria.exclude_user_password_set { + if self.session.user_password_enabled { + return Ok(false); + } + } } } diff --git a/rnex-core/src/nex/user.rs b/rnex-core/src/nex/user.rs index e8a50fa..71ffe34 100644 --- a/rnex-core/src/nex/user.rs +++ b/rnex-core/src/nex/user.rs @@ -1,26 +1,29 @@ -use crate::define_rmc_proto; -use crate::nex::common::get_station_urls; -use crate::nex::matchmake::{ExtendedMatchmakeSession, MatchmakeManager}; -use crate::nex::remote_console::RemoteConsole; -use crate::rmc::protocols::matchmake::{ - Matchmake, RawMatchmake, RawMatchmakeInfo, RemoteMatchmake, -}; -use crate::rmc::protocols::nat_traversal::{ - NatTraversal, RawNatTraversal, RawNatTraversalInfo, RemoteNatTraversal, - RemoteNatTraversalConsole, -}; use rnex_core::PID; +use rnex_core::define_rmc_proto; use rnex_core::kerberos::KerberosDateTime; +use rnex_core::nex::common::get_station_urls; +use rnex_core::nex::matchmake::{ExtendedMatchmakeSession, MatchmakeManager}; +use rnex_core::nex::remote_console::RemoteConsole; use rnex_core::prudp::station_url::StationUrl; use rnex_core::prudp::station_url::UrlOptions::{ Address, NatFiltering, NatMapping, Port, RVConnectionID, }; +use rnex_core::rmc::protocols::matchmake::{ + Matchmake, RawMatchmake, RawMatchmakeInfo, RemoteMatchmake, +}; use rnex_core::rmc::protocols::matchmake_ext::{ MatchmakeExt, RawMatchmakeExt, RawMatchmakeExtInfo, RemoteMatchmakeExt, }; use rnex_core::rmc::protocols::matchmake_extension::{ MatchmakeExtension, RawMatchmakeExtension, RawMatchmakeExtensionInfo, RemoteMatchmakeExtension, }; +use rnex_core::rmc::protocols::nat_traversal::{ + NatTraversal, RawNatTraversal, RawNatTraversalInfo, RemoteNatTraversal, + RemoteNatTraversalConsole, +}; +use rnex_core::rmc::protocols::notifications::notification_types::{ + END_GATHERING, REQUEST_JOIN_GATHERING, +}; use rnex_core::rmc::protocols::ranking::{Ranking, RawRanking, RawRankingInfo, RemoteRanking}; use rnex_core::rmc::protocols::secure::{RawSecure, RawSecureInfo, RemoteSecure, Secure}; use rnex_core::rmc::response::ErrorCode; @@ -32,11 +35,13 @@ use serde::{Deserialize, Serialize}; use std::env; use std::str::FromStr; -use crate::rmc::protocols::notifications::{NotificationEvent, RemoteNotification}; use cfg_if::cfg_if; use log::{error, info}; use macros::rmc_struct; use rnex_core::prudp::socket_addr::PRUDPSockAddr; +use rnex_core::rmc::protocols::notifications::{ + self, Notification, NotificationEvent, RemoteNotification, +}; use rnex_core::rmc::protocols::ranking::{ CompetitionRankingGetParam, CompetitionRankingScoreData, CompetitionRankingScoreInfo, }; @@ -248,6 +253,8 @@ impl MatchmakeExtension for User { .await?; let mut session = session.lock().await; + + #[cfg(feature = "v3-5-0")] if join_session_param.user_password != session.session.user_password { return Err(ErrorCode::RendezVous_InvalidPassword); } @@ -396,6 +403,101 @@ impl MatchmakeExtension for User { Ok(()) } + + async fn create_matchmake_session( + &self, + gathering: Any, + message: String, + ) -> Result<(u32, Vec), ErrorCode> { + let Some(Ok(session)): Option> = gathering.try_get() else { + return Err(ErrorCode::Core_InvalidArgument); + }; + + let session = self + .create_matchmake_session_with_param(CreateMatchmakeSessionParam { + matchmake_session: session, + additional_participants: vec![], + gid_for_participation_check: 0, + create_matchmake_session_option: 0, + join_message: message, + participation_count: 1, + }) + .await?; + + Ok((session.gathering.self_gid, session.session_key)) + } + + async fn get_friend_notification_data( + &self, + ty: i32, + ) -> Result, ErrorCode> { + Ok(vec![]) + } + async fn update_notification_data( + &self, + ty: u32, + param_1: u32, + param_2: u32, + str_param: String, + ) -> Result<(), ErrorCode> { + let recpipent = param_2; + let Some(user) = self + .matchmake_manager + .users + .read() + .await + .get(&recpipent) + .and_then(|v| v.upgrade()) + else { + return Err(ErrorCode::Core_InvalidArgument); + }; + match ty { + REQUEST_JOIN_GATHERING => { + user.remote + .process_notification_event(NotificationEvent { + pid_source: self.pid, + notif_type: REQUEST_JOIN_GATHERING * 1000, + param_1, + param_2, + #[cfg(feature = "v3-5-0")] + param_3: 0, + str_param, + }) + .await; + } + END_GATHERING => { + user.remote + .process_notification_event(NotificationEvent { + pid_source: self.pid, + notif_type: END_GATHERING * 1000, + param_1, + param_2, + #[cfg(feature = "v3-5-0")] + param_3: 0, + str_param, + }) + .await; + } + _ => { + return Err(ErrorCode::Core_InvalidArgument); + } + } + Ok(()) + } + + async fn join_matchmake_session_ex( + &self, + gid: u32, + message: String, + dont_care_block_list: bool, + participation_count: u16, + ) -> Result, ErrorCode> { + let sess = self.matchmake_manager.get_session(gid).await?; + let mut sess = sess.lock().await; + sess.add_players(&[self.this.clone()], message).await; + + Ok(sess.session.session_key.clone()) + } } impl Matchmake for User { @@ -448,6 +550,7 @@ impl Matchmake for User { pid_source: self.pid, param_1: gid as PID, param_2: self.pid, + #[cfg(feature = "v3-5-0")] param_3: 0, str_param: "".to_string(), }) @@ -469,6 +572,7 @@ impl Matchmake for User { pid_source: self.pid, param_1: gid as PID, param_2: self.pid, + #[cfg(feature = "v3-5-0")] param_3: 0, str_param: "".to_string(), }) @@ -504,6 +608,7 @@ impl Matchmake for User { pid_source: self.pid, param_1: gid as PID, param_2: *candidate as PID, + #[cfg(feature = "v3-5-0")] param_3: 0, str_param: "".to_string(), }) diff --git a/rnex-core/src/rmc/protocols/matchmake_extension.rs b/rnex-core/src/rmc/protocols/matchmake_extension.rs index fff5252..7591a48 100644 --- a/rnex-core/src/rmc/protocols/matchmake_extension.rs +++ b/rnex-core/src/rmc/protocols/matchmake_extension.rs @@ -1,17 +1,57 @@ use macros::{method_id, rmc_proto}; use rnex_core::rmc::response::ErrorCode; -use rnex_core::rmc::structures::matchmake::{AutoMatchmakeParam, CreateMatchmakeSessionParam, JoinMatchmakeSessionParam, MatchmakeSession}; +use rnex_core::rmc::structures::matchmake::{ + AutoMatchmakeParam, CreateMatchmakeSessionParam, JoinMatchmakeSessionParam, MatchmakeSession, +}; + +use crate::rmc::protocols::notifications::NotificationEvent; +use crate::rmc::structures::any::Any; #[rmc_proto(109)] -pub trait MatchmakeExtension{ +pub trait MatchmakeExtension { #[method_id(1)] async fn close_participation(&self, gid: u32) -> Result<(), ErrorCode>; #[method_id(2)] async fn open_participation(&self, gid: u32) -> Result<(), ErrorCode>; + #[method_id(6)] + async fn create_matchmake_session( + &self, + gathering: Any, + message: String, + ) -> Result<(u32, Vec), ErrorCode>; + + #[method_id(9)] + async fn update_notification_data( + &self, + ty: u32, + param1: u32, + param2: u32, + str_param: String, + ) -> Result<(), ErrorCode>; + + #[method_id(10)] + async fn get_friend_notification_data( + &self, + ty: i32, + ) -> Result, ErrorCode>; + + #[method_id(30)] + async fn join_matchmake_session_ex( + &self, + gid: u32, + message: String, + dont_care_block_list: bool, + participation_count: u16, + ) -> Result, ErrorCode>; #[method_id(8)] - async fn modify_current_game_attribute(&self, gid: u32, attrib_index: u32, attrib_val: u32) -> Result<(), ErrorCode>; + async fn modify_current_game_attribute( + &self, + gid: u32, + attrib_index: u32, + attrib_val: u32, + ) -> Result<(), ErrorCode>; #[method_id(16)] async fn get_playing_session(&self, pids: Vec) -> Result, ErrorCode>; @@ -19,14 +59,26 @@ pub trait MatchmakeExtension{ #[method_id(34)] async fn update_progress_score(&self, gid: u32, progress: u8) -> Result<(), ErrorCode>; #[method_id(38)] - async fn create_matchmake_session_with_param(&self, session: CreateMatchmakeSessionParam) -> Result; + async fn create_matchmake_session_with_param( + &self, + session: CreateMatchmakeSessionParam, + ) -> Result; #[method_id(39)] - async fn join_matchmake_session_with_param(&self, session: JoinMatchmakeSessionParam) -> Result; + async fn join_matchmake_session_with_param( + &self, + session: JoinMatchmakeSessionParam, + ) -> Result; #[method_id(40)] - async fn auto_matchmake_with_param_postpone(&self, session: AutoMatchmakeParam) -> Result; + async fn auto_matchmake_with_param_postpone( + &self, + session: AutoMatchmakeParam, + ) -> Result; #[method_id(41)] - async fn find_matchmake_session_by_gathering_id_detail(&self, gid: u32) -> Result; -} \ No newline at end of file + async fn find_matchmake_session_by_gathering_id_detail( + &self, + gid: u32, + ) -> Result; +} diff --git a/rnex-core/src/rmc/protocols/notifications.rs b/rnex-core/src/rmc/protocols/notifications.rs index afbebd8..a0aa508 100644 --- a/rnex-core/src/rmc/protocols/notifications.rs +++ b/rnex-core/src/rmc/protocols/notifications.rs @@ -5,8 +5,12 @@ use rnex_core::PID; pub mod notification_types { pub const OWNERSHIP_CHANGED: u32 = 4000; pub const HOST_CHANGED: u32 = 110000; + pub const REQUEST_JOIN_GATHERING: u32 = 101; + pub const END_GATHERING: u32 = 102; } +cfg_if::cfg_if! { + if #[cfg(feature = "v3-5-0")]{ #[derive(RmcSerialize, Debug, Default, Clone)] #[rmc_struct(0)] pub struct NotificationEvent { @@ -17,6 +21,18 @@ pub struct NotificationEvent { pub str_param: String, pub param_3: PID, } + } else { + #[derive(RmcSerialize, Debug, Default, Clone)] + #[rmc_struct(0)] + pub struct NotificationEvent { + pub pid_source: PID, + pub notif_type: u32, + pub param_1: PID, + pub param_2: PID, + pub str_param: String, + } + } +} #[rmc_proto(14, NoReturn)] pub trait Notification { diff --git a/rnex-core/src/rmc/structures/matchmake.rs b/rnex-core/src/rmc/structures/matchmake.rs index a1518d1..ffe4d7f 100644 --- a/rnex-core/src/rmc/structures/matchmake.rs +++ b/rnex-core/src/rmc/structures/matchmake.rs @@ -1,3 +1,4 @@ +use cfg_if::cfg_if; use macros::RmcSerialize; use rnex_core::kerberos::KerberosDateTime; use rnex_core::rmc::structures::variant::Variant; @@ -27,29 +28,49 @@ pub struct MatchmakeParam { pub params: Vec<(String, Variant)>, } -// rmc structure -#[derive(RmcSerialize, Debug, Clone, Default)] -#[rmc_struct(3)] -pub struct MatchmakeSession { - //inherits from - #[extends] - pub gathering: Gathering, +cfg_if! { + if #[cfg(feature = "v3-5-0")]{ + #[derive(RmcSerialize, Debug, Clone, Default)] + #[rmc_struct(3)] + pub struct MatchmakeSession { + //inherits from + #[extends] + pub gathering: Gathering, - pub gamemode: u32, - pub attributes: Vec, - pub open_participation: bool, - pub matchmake_system_type: u32, - pub application_buffer: Vec, - pub participation_count: u32, - pub progress_score: u8, - pub session_key: Vec, - pub option0: u32, - pub matchmake_param: MatchmakeParam, - pub datetime: KerberosDateTime, - pub user_password: String, - pub refer_gid: u32, - pub user_password_enabled: bool, - pub system_password_enabled: bool, + pub gamemode: u32, + pub attributes: Vec, + pub open_participation: bool, + pub matchmake_system_type: u32, + pub application_buffer: Vec, + pub participation_count: u32, + pub progress_score: u8, + pub session_key: Vec, + pub option0: u32, + pub matchmake_param: MatchmakeParam, + pub datetime: KerberosDateTime, + pub user_password: String, + pub refer_gid: u32, + pub user_password_enabled: bool, + pub system_password_enabled: bool, + } + } else { + #[derive(RmcSerialize, Debug, Clone, Default)] + #[rmc_struct(0)] + pub struct MatchmakeSession { + //inherits from + #[extends] + pub gathering: Gathering, + + pub gamemode: u32, + pub attributes: Vec, + pub open_participation: bool, + pub matchmake_system_type: u32, + pub application_buffer: Vec, + pub participation_count: u32, + pub progress_score: u8, + pub session_key: Vec, + } + } } #[derive(RmcSerialize, Debug, Clone)]