lots of changes

This commit is contained in:
Maple 2026-02-01 20:59:23 +01:00
commit 3b6de6968d
24 changed files with 879 additions and 258 deletions

View file

@ -1,6 +1,7 @@
use crate::grpc::account;
use crate::reggie::{RemoteEdgeNodeHolder, RemoteEdgeNodeManagement};
use crate::{define_rmc_proto, kerberos};
use cfg_if::cfg_if;
use log::{info, warn};
use macros::rmc_struct;
use rnex_core::kerberos::{KerberosDateTime, Ticket, derive_key};
@ -11,6 +12,7 @@ use rnex_core::rmc::response::ErrorCode;
use rnex_core::rmc::response::ErrorCode::Core_Unknown;
use rnex_core::rmc::structures::any::Any;
use rnex_core::rmc::structures::connection_data::ConnectionData;
use rnex_core::rmc::structures::connection_data::ConnectionDataOld;
use rnex_core::rmc::structures::qresult::QResult;
use std::hash::{DefaultHasher, Hasher};
use std::net::SocketAddrV4;
@ -49,7 +51,13 @@ pub fn generate_ticket(
encrypted_session_ticket
}
async fn get_login_data_by_pid(pid: u32) -> Option<(u32, [u8; 16])> {
async fn get_login_data_by_pid(pid: u32) -> Option<(u32, Box<[u8]>)> {
if pid == GUEST_ACCOUNT.pid {
let source_login_data = GUEST_ACCOUNT.get_login_data();
return Some((source_login_data.0, source_login_data.1.into()));
}
let Ok(mut client) = account::Client::new().await else {
return None;
};
@ -58,7 +66,7 @@ async fn get_login_data_by_pid(pid: u32) -> Option<(u32, [u8; 16])> {
return None;
};
Some((pid, passwd))
Some((pid, passwd.into()))
}
fn station_url_from_sock_addr(sock_addr: SocketAddrV4) -> String {
@ -118,6 +126,42 @@ impl Auth for AuthHandler {
async fn login(
&self,
name: String,
) -> Result<(QResult, u32, Vec<u8>, ConnectionDataOld, String), ErrorCode> {
let (pid, ticket) = self.generate_ticket_from_name(&name).await?;
let result = QResult::success(Core_Unknown);
let mut hasher = DefaultHasher::new();
hasher.write(name.as_bytes());
let Ok(addr) = self.control_server.get_url(hasher.finish()).await else {
warn!("no secure proxies");
return Err(ErrorCode::Core_Exception);
};
let connection_data = ConnectionDataOld {
station_url: station_url_from_sock_addr(addr),
special_station_url: "".to_string(),
special_protocols: Vec::new(),
};
let ret = (
result,
pid,
ticket.into(),
connection_data,
self.build_name.to_string(),
);
info!("data: {:?}", ret);
Ok(ret)
}
async fn login_ex(
&self,
name: String,
_extra_data: Any,
) -> Result<(QResult, u32, Vec<u8>, ConnectionData, String), ErrorCode> {
let (pid, ticket) = self.generate_ticket_from_name(&name).await?;
@ -152,14 +196,6 @@ impl Auth for AuthHandler {
Ok(ret)
}
async fn login_ex(
&self,
name: String,
_extra_data: Any,
) -> Result<(QResult, u32, Vec<u8>, ConnectionData, String), ErrorCode> {
self.login(name).await
}
async fn request_ticket(
&self,
source_pid: u32,

View file

@ -0,0 +1,93 @@
use rnex_core::prudp::station_url::StationUrl;
use rnex_core::prudp::station_url::UrlOptions::{
Address, NatFiltering, NatMapping, NatType, Port, PrincipalID, RVConnectionID,
};
use rnex_core::prudp::station_url::nat_types::PUBLIC;
use rnex_core::rmc::response::ErrorCode::Core_Exception;
use rnex_core::prudp::socket_addr::PRUDPSockAddr;
use rnex_core::rmc::response::ErrorCode;
pub async fn get_station_urls(
station_urls: &[StationUrl],
addr: PRUDPSockAddr,
pid: u32,
cid: u32,
) -> Result<Vec<StationUrl>, ErrorCode> {
let mut public_station: Option<StationUrl> = None;
let mut private_station: Option<StationUrl> = None;
for station in station_urls {
let is_public = station.options.iter().any(|v| {
if let NatType(v) = v {
if *v & PUBLIC != 0 {
return true;
}
}
false
});
let Some(nat_filtering) = station.options.iter().find_map(|v| match v {
NatFiltering(v) => Some(v),
_ => None,
}) else {
return Err(Core_Exception);
};
let Some(nat_mapping) = station.options.iter().find_map(|v| match v {
NatMapping(v) => Some(v),
_ => None,
}) else {
return Err(Core_Exception);
};
if !is_public || (*nat_filtering == 0 && *nat_mapping == 0) {
private_station = Some(station.clone());
}
if is_public {
public_station = Some(station.clone());
}
}
let Some(mut private_station) = private_station else {
return Err(Core_Exception);
};
let mut public_station = if let Some(public_station) = public_station {
public_station
} else {
let mut public_station = private_station.clone();
public_station.options.retain(|v| match v {
Address(_) | Port(_) | NatFiltering(_) | NatMapping(_) | NatType(_) => false,
_ => true,
});
public_station
.options
.push(Address(*addr.regular_socket_addr.ip()));
public_station
.options
.push(Port(addr.regular_socket_addr.port()));
public_station.options.push(NatFiltering(0));
public_station.options.push(NatMapping(0));
public_station.options.push(NatType(3));
public_station
};
let both = [&mut public_station, &mut private_station];
for station in both {
station.options.retain(|v| match v {
PrincipalID(_) | RVConnectionID(_) => false,
_ => true,
});
station.options.push(PrincipalID(pid));
station.options.push(RVConnectionID(cid));
}
Ok(vec![public_station])
}

View file

@ -0,0 +1,160 @@
use std::sync::{Arc, atomic::AtomicU32};
use std::time::Duration;
use log::info;
use macros::rmc_struct;
use rnex_core::rmc::protocols::friends::{Friends, RawFriends, RawFriendsInfo, RemoteFriends};
use rnex_core::rmc::protocols::secure::{RawSecure, RawSecureInfo, RemoteSecure, Secure};
use rnex_core::{
define_rmc_proto,
kerberos::KerberosDateTime,
nex::common::get_station_urls,
prudp::{socket_addr::PRUDPSockAddr, station_url::StationUrl},
rmc::{
protocols::friends::{
BlacklistedPrincipal, Comment, FriendInfo, FriendRequest, NNAInfo, NintendoPresenceV2,
PersistentNotification, PrincipalPreference,
},
response::ErrorCode,
structures::{any::Any, qresult::QResult},
},
};
use std::sync::atomic::Ordering::Relaxed;
use tokio::time::sleep;
use rnex_core::rmc::protocols::friends::{GameKey, MiiV2, PrincipalBasicInfo};
define_rmc_proto!(
proto FriendsUser{
Secure,
Friends
}
);
#[rmc_struct(FriendsUser)]
pub struct FriendsUser {
pub fm: Arc<FriendsManager>,
pub addr: PRUDPSockAddr,
pub pid: u32,
}
pub struct FriendsManager {
pub cid_counter: AtomicU32,
}
impl FriendsManager {
pub fn next_cid(&self) -> u32 {
self.cid_counter.fetch_add(1, Relaxed)
}
}
impl Friends for FriendsUser {
async fn update_and_get_all_information(
&self,
info: NNAInfo,
presence: NintendoPresenceV2,
date_time: KerberosDateTime,
) -> Result<
(
PrincipalPreference,
Comment,
Vec<FriendInfo>,
Vec<FriendRequest>,
Vec<FriendRequest>,
Vec<BlacklistedPrincipal>,
bool,
Vec<PersistentNotification>,
bool,
),
ErrorCode,
> {
Ok((
PrincipalPreference {
block_friend_request: false,
show_online: false,
show_playing_title: false,
},
Comment {
last_changed: KerberosDateTime::now(),
message: "".to_string(),
unk: 0,
},
vec![FriendInfo {
became_friends: KerberosDateTime::now(),
comment: Comment {
last_changed: KerberosDateTime::now(),
message: "I'm just a dummy account :3".to_string(),
unk: 0,
},
last_online: KerberosDateTime::now(),
nna_info: NNAInfo {
principal_basic_info: PrincipalBasicInfo {
pid: 101,
nnid: "dummyaccount".to_string(),
mii: MiiV2{
date_time: KerberosDateTime::now(),
name: "Dummy Account".to_string(),
mii_data: hex::decode("030000402bd7c32986a771f2dc6b35e31da15e37ff7c0000391e6f006f006d0069000000000000000000000000004040001065033568641e2013661a611821640f0000290052485000000000000000000000000000000000000000000000e838").unwrap(),
unk: 0,
unk2: 0,
},
unk: 0
},
unk: 0,
unk2: 0
},
presence: NintendoPresenceV2{
changed_flags: 0,
message: "".to_string(),
app_data: vec![],
game_key: GameKey{
tid: 0x00050002101ce400,
version: 0x0
},
game_server_id: 0,
is_online: true,
gid: 0,
pid: 101,
unk: 0,
unk2: 0,
unk3: 0,
unk4: 0,
unk5: 0,
unk6: 0,
unk7: 0
},
unk: 0
}],
vec![],
vec![],
vec![],
false,
vec![],
false,
))
}
}
impl Secure for FriendsUser {
async fn register(
&self,
station_urls: Vec<StationUrl>,
) -> Result<(QResult, u32, StationUrl), ErrorCode> {
let cid = self.fm.next_cid();
Ok((
QResult::success(ErrorCode::Core_Unknown),
cid,
get_station_urls(&station_urls, self.addr, self.pid, cid).await?[0].clone(),
))
}
async fn register_ex(
&self,
station_urls: Vec<StationUrl>,
data: Any,
) -> Result<(QResult, u32, StationUrl), ErrorCode> {
info!("register");
self.register(station_urls).await
}
async fn replace_url(&self, target: StationUrl, dest: StationUrl) -> Result<(), ErrorCode> {
Err(ErrorCode::Core_NotImplemented)
}
}

View file

@ -1,5 +1,7 @@
pub mod account;
pub mod auth_handler;
pub mod user;
pub mod common;
pub mod friends_handler;
pub mod matchmake;
pub mod remote_console;
pub mod matchmake;
pub mod user;

View file

@ -1,4 +1,5 @@
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::{
@ -21,6 +22,7 @@ use rnex_core::rmc::protocols::matchmake_extension::{
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;
use rnex_core::rmc::structures::any::Any;
use rnex_core::rmc::structures::matchmake::{
AutoMatchmakeParam, CreateMatchmakeSessionParam, JoinMatchmakeSessionParam, MatchmakeSession,
};
@ -71,97 +73,27 @@ impl Secure for User {
users.insert(cid, self.this.clone());
drop(users);
let mut public_station: Option<StationUrl> = None;
let mut private_station: Option<StationUrl> = None;
let stations = get_station_urls(&station_urls, self.ip, self.pid, cid).await?;
for station in station_urls {
let is_public = station.options.iter().any(|v| {
if let NatType(v) = v {
if *v & PUBLIC != 0 {
return true;
}
}
false
});
let Some(nat_filtering) = station.options.iter().find_map(|v| match v {
NatFiltering(v) => Some(v),
_ => None,
}) else {
return Err(Core_Exception);
};
let Some(nat_mapping) = station.options.iter().find_map(|v| match v {
NatMapping(v) => Some(v),
_ => None,
}) else {
return Err(Core_Exception);
};
if !is_public || (*nat_filtering == 0 && *nat_mapping == 0) {
private_station = Some(station.clone());
}
if is_public {
public_station = Some(station);
}
}
let Some(mut private_station) = private_station else {
return Err(Core_Exception);
};
let mut public_station = if let Some(public_station) = public_station {
public_station
} else {
let mut public_station = private_station.clone();
public_station.options.retain(|v| match v {
Address(_) | Port(_) | NatFiltering(_) | NatMapping(_) | NatType(_) => false,
_ => true,
});
public_station
.options
.push(Address(*self.ip.regular_socket_addr.ip()));
public_station
.options
.push(Port(self.ip.regular_socket_addr.port()));
public_station.options.push(NatFiltering(0));
public_station.options.push(NatMapping(0));
public_station.options.push(NatType(3));
public_station
};
let both = [&mut public_station, &mut private_station];
for station in both {
station.options.retain(|v| match v {
PrincipalID(_) | RVConnectionID(_) => false,
_ => true,
});
station.options.push(PrincipalID(self.pid));
station.options.push(RVConnectionID(cid));
}
let first = stations.first().unwrap().clone();
let mut lock = self.station_url.write().await;
*lock = vec![
public_station.clone(),
// private_station.clone()
];
*lock = stations;
drop(lock);
let result = QResult::success(ErrorCode::Core_Unknown);
let out = public_station.to_string();
Ok((result, cid, first))
}
println!("out: {}", out);
Ok((result, cid, public_station))
async fn register_ex(
&self,
station_urls: Vec<StationUrl>,
_data: Any,
) -> Result<(QResult, u32, StationUrl), ErrorCode> {
self.register(station_urls).await
}
async fn replace_url(&self, target_url: StationUrl, dest: StationUrl) -> Result<(), ErrorCode> {