forked from spacebar/rust-nex
Merge branch 'v0' of ssh://ssh.spbr.net:51122/spacebar/rust-nex into v0
This commit is contained in:
commit
25bdbb42eb
30 changed files with 764 additions and 279 deletions
|
|
@ -15,14 +15,14 @@ COPY --from=planner /app/recipe.json recipe.json
|
|||
ARG EDITION
|
||||
ARG DATABASE_URL
|
||||
|
||||
RUN --mount=type=cache,target=/usr/local/cargo/registry \
|
||||
--mount=type=cache,target=/app/target \
|
||||
RUN --mount=type=cache,id=${EDITION}-registry,target=/usr/local/cargo/registry \
|
||||
--mount=type=cache,id=${EDITION}-target,target=/app/target \
|
||||
cargo chef cook --release --recipe-path recipe.json --target x86_64-unknown-linux-musl && \
|
||||
cargo chef cook --tests --target x86_64-unknown-linux-musl --recipe-path recipe.json
|
||||
|
||||
COPY . .
|
||||
RUN --mount=type=cache,target=/usr/local/cargo/registry \
|
||||
--mount=type=cache,target=/app/target \
|
||||
RUN --mount=type=cache,id=${EDITION}-registry,target=/usr/local/cargo/registry \
|
||||
--mount=type=cache,id=${EDITION}-target,target=/app/target \
|
||||
RNEX_STATIC=1 ./test-edition.sh && RNEX_STATIC=1 ./build-edition.sh && \
|
||||
mkdir -p /app/dist && \
|
||||
cp /app/target/x86_64-unknown-linux-musl/release/edge_node_holder_server /app/dist/ && \
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@ use rnex_core::{
|
|||
};
|
||||
use std::{
|
||||
env::{self, VarError},
|
||||
error,
|
||||
net::{AddrParseError, Ipv4Addr, SocketAddr, SocketAddrV4},
|
||||
ops::Deref,
|
||||
panic,
|
||||
|
|
|
|||
|
|
@ -3,9 +3,12 @@ use std::io::Write;
|
|||
use hmac::Mac;
|
||||
use md5::{Digest, Md5};
|
||||
use rc4::{KeyInit, Rc4, StreamCipher};
|
||||
use rnex_core::prudp::{
|
||||
encryption::{DEFAULT_KEY, EncryptionPair},
|
||||
types_flags::{TypesFlags, types::DATA},
|
||||
use rnex_core::{
|
||||
PID,
|
||||
prudp::{
|
||||
encryption::{DEFAULT_KEY, EncryptionPair},
|
||||
types_flags::{TypesFlags, types::DATA},
|
||||
},
|
||||
};
|
||||
use typenum::U5;
|
||||
|
||||
|
|
@ -29,7 +32,7 @@ impl CryptoInstance for InsecureInstance {
|
|||
fn encrypt_outgoing(&mut self, data: &mut [u8]) {
|
||||
self.pair.send.apply_keystream(data);
|
||||
}
|
||||
fn get_user_id(&self) -> u32 {
|
||||
fn get_user_id(&self) -> PID {
|
||||
0
|
||||
}
|
||||
fn generate_signature(&self, types_flags: TypesFlags, data: &[u8]) -> [u8; 4] {
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ use hmac::Mac;
|
|||
use md5::{Digest, Md5};
|
||||
use rc4::{KeyInit, Rc4, StreamCipher};
|
||||
use rnex_core::{
|
||||
PID,
|
||||
executables::common::SECURE_SERVER_ACCOUNT,
|
||||
nex::account::Account,
|
||||
prudp::{
|
||||
|
|
@ -22,7 +23,7 @@ use crate::crypto::{
|
|||
|
||||
pub struct SecureInstance {
|
||||
pair: EncryptionPair<Rc4<U16>>,
|
||||
uid: u32,
|
||||
uid: PID,
|
||||
self_signat: [u8; 4],
|
||||
#[allow(dead_code)]
|
||||
remote_signat: [u8; 4],
|
||||
|
|
@ -35,7 +36,7 @@ impl CryptoInstance for SecureInstance {
|
|||
fn encrypt_outgoing(&mut self, data: &mut [u8]) {
|
||||
self.pair.send.apply_keystream(data);
|
||||
}
|
||||
fn get_user_id(&self) -> u32 {
|
||||
fn get_user_id(&self) -> PID {
|
||||
self.uid
|
||||
}
|
||||
fn generate_signature(&self, types_flags: TypesFlags, data: &[u8]) -> [u8; 4] {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use cfg_if::cfg_if;
|
||||
use rnex_core::prudp::types_flags::TypesFlags;
|
||||
use rnex_core::{PID, prudp::types_flags::TypesFlags};
|
||||
|
||||
mod common_crypto;
|
||||
|
||||
|
|
@ -7,7 +7,7 @@ pub trait CryptoInstance: Send + 'static {
|
|||
fn decrypt_incoming(&mut self, data: &mut [u8]);
|
||||
fn encrypt_outgoing(&mut self, data: &mut [u8]);
|
||||
fn generate_signature(&self, types_flags: TypesFlags, data: &[u8]) -> [u8; 4];
|
||||
fn get_user_id(&self) -> u32;
|
||||
fn get_user_id(&self) -> PID;
|
||||
}
|
||||
|
||||
pub trait Crypto: Send + Sync + 'static {
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ use crate::prudp::socket::{CryptoHandler, CryptoHandlerConnectionInstance};
|
|||
use hmac::digest::consts::U32;
|
||||
use rc4::cipher::StreamCipherCoreWrapper;
|
||||
use rc4::{KeyInit, Rc4, Rc4Core, StreamCipher};
|
||||
use rnex_core::PID;
|
||||
use rnex_core::nex::account::Account;
|
||||
use rnex_core::prudp::encryption::EncryptionPair;
|
||||
use rnex_core::prudp::ticket::read_secure_connection_data;
|
||||
|
|
@ -49,7 +50,7 @@ pub struct SecureInstance {
|
|||
self_signature: [u8; 16],
|
||||
#[allow(dead_code)]
|
||||
remote_signature: [u8; 16],
|
||||
pid: u32,
|
||||
pid: PID,
|
||||
}
|
||||
|
||||
impl CryptoHandler for Secure {
|
||||
|
|
@ -108,7 +109,7 @@ impl CryptoHandlerConnectionInstance for SecureInstance {
|
|||
}
|
||||
}
|
||||
|
||||
fn get_user_id(&self) -> u32 {
|
||||
fn get_user_id(&self) -> i32 {
|
||||
self.pid
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ use async_trait::async_trait;
|
|||
use log::error;
|
||||
use log::{info, warn};
|
||||
use rc4::StreamCipher;
|
||||
use rnex_core::PID;
|
||||
use rnex_core::prudp::socket_addr::PRUDPSockAddr;
|
||||
use rnex_core::prudp::types_flags::TypesFlags;
|
||||
use rnex_core::prudp::types_flags::flags::{ACK, HAS_SIZE, MULTI_ACK, NEED_ACK, RELIABLE};
|
||||
|
|
@ -31,7 +32,7 @@ use tokio::time::{Instant, sleep};
|
|||
/// PRUDP Socket for accepting connections to then send and recieve data from those clients
|
||||
|
||||
pub struct CommonConnection {
|
||||
pub user_id: u32,
|
||||
pub user_id: PID,
|
||||
pub socket_addr: PRUDPSockAddr,
|
||||
pub server_port: VirtualPort,
|
||||
session_id: u8,
|
||||
|
|
@ -851,7 +852,7 @@ pub trait CryptoHandlerConnectionInstance: Send + Sync + 'static {
|
|||
fn decrypt_incoming(&mut self, substream: u8, data: &mut [u8]);
|
||||
fn encrypt_outgoing(&mut self, substream: u8, data: &mut [u8]);
|
||||
|
||||
fn get_user_id(&self) -> u32;
|
||||
fn get_user_id(&self) -> i32;
|
||||
fn sign_connect(&self, packet: &mut PRUDPV1Packet);
|
||||
fn sign_packet(&self, packet: &mut PRUDPV1Packet);
|
||||
fn verify_packet(&self, packet: &PRUDPV1Packet) -> bool;
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ impl CryptoHandlerConnectionInstance for UnsecureInstance {
|
|||
}
|
||||
}
|
||||
|
||||
fn get_user_id(&self) -> u32 {
|
||||
fn get_user_id(&self) -> i32 {
|
||||
0
|
||||
}
|
||||
|
||||
|
|
|
|||
13
rnex-core/build.rs
Normal file
13
rnex-core/build.rs
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
use std::{env, process::Command};
|
||||
fn main() {
|
||||
let output = Command::new("git")
|
||||
.args(&["rev-parse", "HEAD"])
|
||||
.output()
|
||||
.unwrap();
|
||||
let git_hash = String::from_utf8(output.stdout).unwrap();
|
||||
println!("cargo:rustc-env=GIT_HASH={}", git_hash);
|
||||
println!(
|
||||
"cargo:rustc-env=FEATURESET={}",
|
||||
env::var("CARGO_CFG_FEATURE").unwrap()
|
||||
);
|
||||
}
|
||||
|
|
@ -5,23 +5,24 @@ use rnex_core::common::setup;
|
|||
async fn main() {
|
||||
setup();
|
||||
|
||||
#[cfg(feature = "database-support")]
|
||||
{
|
||||
use rnex_core::executables::common::DB_POOL;
|
||||
use sqlx::PgPool;
|
||||
let database_url = std::env::var("RNEX_DATASTORE_DATABASE_URL")
|
||||
.expect("RNEX_DATASTORE_DATABASE_URL must be set");
|
||||
|
||||
let pool = PgPool::connect(&database_url)
|
||||
.await
|
||||
.expect("Failed to create pool");
|
||||
|
||||
DB_POOL.set(pool).expect("failed to set global DB_POOL");
|
||||
}
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(feature = "friends")]{
|
||||
use rnex_core::executables::friends_backend::start_friends_backend;
|
||||
start_friends_backend().await;
|
||||
} else if #[cfg(feature = "datastore")] {
|
||||
use rnex_core::executables::common::DB_POOL;
|
||||
use sqlx::PgPool;
|
||||
let database_url = std::env::var("RNEX_DATASTORE_DATABASE_URL")
|
||||
.expect("RNEX_DATASTORE_DATABASE_URL must be set");
|
||||
|
||||
let pool = PgPool::connect(&database_url)
|
||||
.await
|
||||
.expect("Failed to create pool");
|
||||
|
||||
DB_POOL.set(pool).expect("failed to set global DB_POOL");
|
||||
use rnex_core::executables::regular_backend;
|
||||
regular_backend::start_regular_backend().await
|
||||
} else {
|
||||
use rnex_core::executables::regular_backend;
|
||||
regular_backend::start_regular_backend().await
|
||||
|
|
|
|||
|
|
@ -1,23 +1,18 @@
|
|||
use crate::reggie::UnitPacketRead;
|
||||
use cfg_if::cfg_if;
|
||||
use log::error;
|
||||
use once_cell::sync::Lazy;
|
||||
use rnex_core::nex::account::Account;
|
||||
use rnex_core::rmc::protocols::{RmcCallable, RmcConnection, new_rmc_gateway_connection};
|
||||
use rnex_core::rmc::structures::RmcSerialize;
|
||||
use rnex_core::rnex_proxy_common::ConnectionInitData;
|
||||
use std::env;
|
||||
use std::error::Error;
|
||||
use std::fmt::Display;
|
||||
use std::io::{Cursor, Read, Write};
|
||||
use std::net::{Ipv4Addr, SocketAddrV4, TcpStream};
|
||||
use std::sync::Arc;
|
||||
use tokio::net::TcpListener;
|
||||
cfg_if! {
|
||||
if #[cfg(feature = "datastore")] {
|
||||
use sqlx::postgres::PgPool;
|
||||
}
|
||||
}
|
||||
use crate::reggie::UnitPacketRead;
|
||||
use cfg_if::cfg_if;
|
||||
use log::error;
|
||||
use std::error::Error;
|
||||
|
||||
const IP_REQ_SERVICE_URLS: &[(&str, &str, &str)] = &[
|
||||
("ipinfo.io:80", "ipinfo.io", "/ip"),
|
||||
|
|
@ -30,11 +25,12 @@ const IP_REQ_SERVICE_URLS: &[(&str, &str, &str)] = &[
|
|||
];
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(feature = "datastore")] {
|
||||
if #[cfg(feature = "database-support")] {
|
||||
use std::sync::{LazyLock, OnceLock};
|
||||
pub static RNEX_DATASTORE_DATABASE_URL: LazyLock<String> = LazyLock::new(|| {
|
||||
std::env::var("RNEX_DATASTORE_DATABASE_URL")
|
||||
.expect("RNEX_DATASTORE_DATABASE_URL must be set")
|
||||
use sqlx::postgres::PgPool;
|
||||
pub static RNEX_DATABASE_URL: LazyLock<String> = LazyLock::new(|| {
|
||||
std::env::var("RNEX_DATABASE_URL")
|
||||
.expect("RNEX_DATABASE_URL must be set")
|
||||
});
|
||||
|
||||
pub static DB_POOL: OnceLock<PgPool> = OnceLock::new();
|
||||
|
|
@ -42,6 +38,10 @@ cfg_if! {
|
|||
pub fn get_db() -> &'static PgPool {
|
||||
DB_POOL.get().expect("db_pool not initialized")
|
||||
}
|
||||
}
|
||||
}
|
||||
cfg_if! {
|
||||
if #[cfg(feature = "datastore")]{
|
||||
pub static RNEX_DATASTORE_S3_ENDPOINT: LazyLock<String> = LazyLock::new(|| {
|
||||
std::env::var("RNEX_DATASTORE_S3_ENDPOINT")
|
||||
.expect("RNEX_DATASTORE_S3_ENDPOINT must be set")
|
||||
|
|
|
|||
|
|
@ -166,7 +166,7 @@ impl Client {
|
|||
.find(|v| v.0 == "pid")
|
||||
.ok_or(SomethingHappened)?
|
||||
.1
|
||||
.as_u32()
|
||||
.as_i32()
|
||||
else {
|
||||
return Err(SomethingHappened);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -5,9 +5,9 @@
|
|||
//#![warn(missing_docs)]
|
||||
|
||||
#[cfg(feature = "big_pid")]
|
||||
pub type PID = u64;
|
||||
pub type PID = i64;
|
||||
#[cfg(not(feature = "big_pid"))]
|
||||
pub type PID = u32;
|
||||
pub type PID = i32;
|
||||
|
||||
extern crate self as rnex_core;
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,9 @@ use macros::rmc_struct;
|
|||
use rnex_core::rmc::protocols::account_management::{
|
||||
AccountManagement, RawAccountManagement, RawAccountManagementInfo, RemoteAccountManagement,
|
||||
};
|
||||
use rnex_core::rmc::protocols::friends::{Friends, RawFriends, RawFriendsInfo, RemoteFriends};
|
||||
use rnex_core::rmc::protocols::friends_wiiu::{
|
||||
FriendsWiiU, RawFriendsWiiU, RawFriendsWiiUInfo, RemoteFriendsWiiU,
|
||||
};
|
||||
use rnex_core::rmc::protocols::nintendo_notification::{
|
||||
NintendoNotification, RawNintendoNotification, RawNintendoNotificationInfo,
|
||||
RemoteNintendoNotification,
|
||||
|
|
@ -22,19 +24,20 @@ use rnex_core::{
|
|||
nex::common::get_station_urls,
|
||||
prudp::{socket_addr::PRUDPSockAddr, station_url::StationUrl},
|
||||
rmc::{
|
||||
protocols::friends::{
|
||||
protocols::friends_wiiu::{
|
||||
BlacklistedPrincipal, Comment, FriendInfo, FriendRequest, NNAInfo, NintendoPresenceV2,
|
||||
PersistentNotification, PrincipalPreference,
|
||||
PersistentNotification, PrincipalPreference, PrincipalRequestBlockSetting,
|
||||
},
|
||||
response::ErrorCode,
|
||||
structures::{any::Any, qresult::QResult},
|
||||
},
|
||||
};
|
||||
use sqlx::query;
|
||||
use std::sync::atomic::Ordering::Relaxed;
|
||||
use tokio::spawn;
|
||||
use tokio::sync::RwLock;
|
||||
|
||||
use rnex_core::rmc::protocols::friends::{GameKey, MiiV2, PrincipalBasicInfo};
|
||||
use rnex_core::rmc::protocols::friends_wiiu::{GameKey, MiiV2, PrincipalBasicInfo};
|
||||
|
||||
use rnex_core::PID;
|
||||
|
||||
|
|
@ -44,10 +47,12 @@ use rnex_core::rmc::structures::RmcSerialize;
|
|||
|
||||
use rnex_core::rmc::structures::data::Data;
|
||||
|
||||
use crate::executables::common::get_db;
|
||||
|
||||
define_rmc_proto!(
|
||||
proto FriendsUser{
|
||||
Secure,
|
||||
Friends
|
||||
FriendsWiiU
|
||||
}
|
||||
);
|
||||
define_rmc_proto!(
|
||||
|
|
@ -95,29 +100,12 @@ impl FriendsManager {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn friend_info_from_user(data: &UserData) -> FriendInfo {
|
||||
FriendInfo {
|
||||
data: Data {},
|
||||
nna_info: data.info.clone(),
|
||||
presence: data.presence.clone(),
|
||||
comment: Comment {
|
||||
data: Data {},
|
||||
unk: 0,
|
||||
message: "haii =w=".to_string(),
|
||||
last_changed: KerberosDateTime::now(),
|
||||
},
|
||||
became_friends: KerberosDateTime::now(),
|
||||
last_online: KerberosDateTime::now(),
|
||||
unk: 0,
|
||||
}
|
||||
}
|
||||
|
||||
impl Friends for FriendsUser {
|
||||
impl FriendsWiiU for FriendsUser {
|
||||
async fn update_and_get_all_information(
|
||||
&self,
|
||||
info: NNAInfo,
|
||||
presence: NintendoPresenceV2,
|
||||
_date_time: KerberosDateTime,
|
||||
date_time: KerberosDateTime,
|
||||
) -> Result<
|
||||
(
|
||||
PrincipalPreference,
|
||||
|
|
@ -132,213 +120,105 @@ impl Friends for FriendsUser {
|
|||
),
|
||||
ErrorCode,
|
||||
> {
|
||||
println!("updating own data");
|
||||
let mut data = self.data.write().await;
|
||||
*data = Some(UserData { info, presence });
|
||||
let self_fr_info = friend_info_from_user(data.as_ref().unwrap());
|
||||
let Ok(any_self_fr_info) = Any::new(&self_fr_info) else {
|
||||
return Err(ErrorCode::RendezVous_ControlScriptFailure);
|
||||
};
|
||||
let Ok(any_self_presence) = Any::new(&self_fr_info.presence) else {
|
||||
return Err(ErrorCode::RendezVous_ControlScriptFailure);
|
||||
};
|
||||
drop(data);
|
||||
// let query = query!("select ", self.pid).fetch_all(get_db()).await;
|
||||
Err(ErrorCode::Core_NotImplemented)
|
||||
}
|
||||
|
||||
let mut fr_list = vec![FriendInfo {
|
||||
data: Data{},
|
||||
became_friends: KerberosDateTime::now(),
|
||||
comment: Comment {
|
||||
data: Data{},
|
||||
last_changed: KerberosDateTime::now(),
|
||||
message: "I'm just a dummy account :3".to_string(),
|
||||
unk: 0,
|
||||
},
|
||||
last_online: KerberosDateTime::now(),
|
||||
nna_info: NNAInfo {
|
||||
data: Data{},
|
||||
principal_basic_info: PrincipalBasicInfo {
|
||||
data: Data{},
|
||||
pid: 101,
|
||||
nnid: "dummy:3".to_string(),
|
||||
mii: MiiV2{
|
||||
data: Data{},
|
||||
date_time: KerberosDateTime::now(),
|
||||
name: "TheDummy".to_string(),
|
||||
mii_data: hex::decode("030000402bd7c32986a771f2dc6b35e31da15e37ff7c0000391e6f006f006d0069000000000000000000000000004040001065033568641e2013661a611821640f0000290052485000000000000000000000000000000000000000000000e838").unwrap(),
|
||||
unk: 0,
|
||||
unk2: 0,
|
||||
},
|
||||
unk: 0
|
||||
},
|
||||
unk: 0,
|
||||
unk2: 0
|
||||
},
|
||||
presence: NintendoPresenceV2{
|
||||
data: Data{},
|
||||
changed_flags: 0,
|
||||
message: "".to_string(),
|
||||
app_data: vec![],
|
||||
game_key: GameKey{
|
||||
data: Data{},
|
||||
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
|
||||
}];
|
||||
async fn add_friend(&self, friend: PID) -> Result<(FriendRequest, FriendInfo), ErrorCode> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
println!("acquiring user and current friends locks");
|
||||
let users = self.fm.users.read().await;
|
||||
if users.iter().filter(|u| u.upgrade().is_some()).count() >= 100 {
|
||||
return Err(ErrorCode::RendezVous_ConnectionFailure);
|
||||
}
|
||||
println!("started summing users");
|
||||
for u in users.deref().iter().filter_map(|u| u.upgrade()) {
|
||||
let data = u.data.read().await;
|
||||
let Some(inner_data) = data.as_ref() else {
|
||||
continue;
|
||||
};
|
||||
fr_list.push(friend_info_from_user(&inner_data));
|
||||
drop(data);
|
||||
async fn add_friend_by_name(
|
||||
&self,
|
||||
name: String,
|
||||
) -> Result<(FriendRequest, FriendInfo), ErrorCode> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
let mut curr_friends = self.current_friends.write().await;
|
||||
curr_friends.push(u.pid);
|
||||
drop(curr_friends);
|
||||
async fn remove_friend(&self, friend: PID) -> Result<(), ErrorCode> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
let mut fr = u.current_friends.write().await;
|
||||
if !fr.contains(&self.pid) {
|
||||
fr.push(self.pid);
|
||||
drop(fr);
|
||||
let data = any_self_fr_info.clone();
|
||||
let u = u.clone();
|
||||
let sender = self.pid;
|
||||
spawn(async move {
|
||||
u.remote
|
||||
.process_nintendo_notification_event_1(NintendoNotificationEvent {
|
||||
event_type: 30,
|
||||
sender,
|
||||
data,
|
||||
})
|
||||
.await;
|
||||
});
|
||||
} else {
|
||||
let data = any_self_presence.clone();
|
||||
let u = u.clone();
|
||||
let sender = self.pid;
|
||||
spawn(async move {
|
||||
u.remote
|
||||
.process_nintendo_notification_event_2(NintendoNotificationEvent {
|
||||
event_type: 24,
|
||||
sender,
|
||||
data,
|
||||
})
|
||||
.await;
|
||||
});
|
||||
drop(fr);
|
||||
}
|
||||
}
|
||||
println!("finished summing users");
|
||||
drop(users);
|
||||
async fn add_friend_request(
|
||||
&self,
|
||||
friend: PID,
|
||||
unk1: u8,
|
||||
message: String,
|
||||
unk2: u8,
|
||||
unk3: String,
|
||||
game_key: GameKey,
|
||||
unk4: KerberosDateTime,
|
||||
) -> Result<(FriendRequest, FriendInfo), ErrorCode> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
println!("adding self to users");
|
||||
let mut users = self.fm.users.write().await;
|
||||
users.push(self.this.clone());
|
||||
drop(users);
|
||||
async fn cancel_friend_request(&self, id: u64) -> Result<(), ErrorCode> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
println!("done...");
|
||||
Ok((
|
||||
PrincipalPreference {
|
||||
data: Data {},
|
||||
block_friend_request: false,
|
||||
show_online: false,
|
||||
show_playing_title: false,
|
||||
},
|
||||
Comment {
|
||||
data: Data {},
|
||||
last_changed: KerberosDateTime::now(),
|
||||
message: "".to_string(),
|
||||
unk: 0,
|
||||
},
|
||||
fr_list,
|
||||
vec![],
|
||||
vec![],
|
||||
vec![],
|
||||
false,
|
||||
vec![],
|
||||
false,
|
||||
))
|
||||
async fn accept_friend_request(&self, id: u64) -> Result<FriendInfo, ErrorCode> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
async fn delete_friend_request(&self, id: u64) -> Result<(), ErrorCode> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
async fn deny_friend_request(&self, id: u64) -> Result<BlacklistedPrincipal, ErrorCode> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
async fn mark_friend_requests_as_received(&self, ids: Vec<u64>) -> Result<(), ErrorCode> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
async fn add_blacklist(
|
||||
&self,
|
||||
principal: BlacklistedPrincipal,
|
||||
) -> Result<BlacklistedPrincipal, ErrorCode> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
async fn remove_blacklist(&self, id: PID) -> Result<(), ErrorCode> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
async fn update_presence(&self, presence: NintendoPresenceV2) -> Result<(), ErrorCode> {
|
||||
info!("user updated presence: {:?}", presence);
|
||||
let mut data = self.data.write().await;
|
||||
let Some(inner_data) = data.as_mut() else {
|
||||
log::error!("unable to get presence data");
|
||||
return Err(ErrorCode::RendezVous_PermissionDenied);
|
||||
};
|
||||
inner_data.presence = presence;
|
||||
let Ok(any_self_fr_info) = Any::new(&inner_data.presence) else {
|
||||
log::error!("unable to create presence any data holder");
|
||||
return Err(ErrorCode::RendezVous_ControlScriptFailure);
|
||||
};
|
||||
drop(data);
|
||||
todo!()
|
||||
}
|
||||
|
||||
let users = self.fm.users.read().await;
|
||||
for u in users.deref().iter().filter_map(|u| u.upgrade()) {
|
||||
info!("sending presence update");
|
||||
u.remote
|
||||
.process_nintendo_notification_event_2(NintendoNotificationEvent {
|
||||
event_type: 24,
|
||||
sender: self.pid,
|
||||
data: any_self_fr_info.clone(),
|
||||
})
|
||||
.await;
|
||||
}
|
||||
drop(users);
|
||||
async fn update_mii(&self, presence: MiiV2) -> Result<KerberosDateTime, ErrorCode> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
Ok(())
|
||||
async fn update_comment(&self, presence: Comment) -> Result<KerberosDateTime, ErrorCode> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
async fn update_preference(&self, preference: PrincipalPreference) -> Result<(), ErrorCode> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
async fn get_basic_info(&self, pids: Vec<PID>) -> Result<Vec<PrincipalBasicInfo>, ErrorCode> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
async fn delete_persistent_notification(
|
||||
&self,
|
||||
_notifs: Vec<PersistentNotification>,
|
||||
notifs: Vec<PersistentNotification>,
|
||||
) -> Result<(), ErrorCode> {
|
||||
Ok(())
|
||||
todo!()
|
||||
}
|
||||
|
||||
async fn check_setting_status(&self) -> Result<u8, ErrorCode> {
|
||||
Ok(0xFF)
|
||||
todo!()
|
||||
}
|
||||
|
||||
async fn update_preference(&self, preference: PrincipalPreference) -> Result<(),ErrorCode> {
|
||||
info!("user updated preference: {:?}", preference);
|
||||
let any_presence: Any = Any::new(&preference).expect("out of memory");
|
||||
|
||||
let users = self.fm.users.read().await;
|
||||
for u in users.deref().iter().filter_map(|u| u.upgrade()) {
|
||||
info!("sending preference update");
|
||||
u.remote
|
||||
.process_nintendo_notification_event_2(NintendoNotificationEvent {
|
||||
event_type: 23,
|
||||
sender: self.pid,
|
||||
data: any_presence.clone(),
|
||||
})
|
||||
.await;
|
||||
}
|
||||
drop(users);
|
||||
|
||||
Ok(())
|
||||
async fn get_request_block_settings(
|
||||
&self,
|
||||
unk: Vec<u32>,
|
||||
) -> Result<Vec<PrincipalRequestBlockSetting>, ErrorCode> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
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,
|
||||
|
|
@ -11,9 +10,8 @@ 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;
|
||||
use rnex_core::rmc::structures::matchmake::{
|
||||
Gathering, MatchmakeParam, MatchmakeSession, MatchmakeSessionSearchCriteria,
|
||||
Gathering, MatchmakeSession, MatchmakeSessionSearchCriteria,
|
||||
};
|
||||
use rnex_core::rmc::structures::variant::Variant;
|
||||
use std::collections::HashMap;
|
||||
use std::str::FromStr;
|
||||
use std::sync::atomic::AtomicU32;
|
||||
|
|
@ -28,7 +26,7 @@ pub struct MatchmakeManager {
|
|||
pub sessions: RwLock<HashMap<u32, Arc<Mutex<ExtendedMatchmakeSession>>>>,
|
||||
pub rv_cid_counter: AtomicU32,
|
||||
pub users: RwLock<HashMap<u32, Weak<User>>>,
|
||||
pub users_by_pid: RwLock<HashMap<u32, Weak<User>>>,
|
||||
pub users_by_pid: RwLock<HashMap<PID, Weak<User>>>,
|
||||
}
|
||||
|
||||
impl MatchmakeManager {
|
||||
|
|
@ -162,6 +160,13 @@ impl ExtendedMatchmakeSession {
|
|||
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(feature = "v3-5-0")]{
|
||||
use rnex_core::{
|
||||
rmc::structures::{
|
||||
variant::Variant,
|
||||
matchmake::MatchmakeParam
|
||||
},
|
||||
kerberos::KerberosDateTime
|
||||
};
|
||||
let mm_session = MatchmakeSession {
|
||||
gathering: Gathering {
|
||||
self_gid: gid,
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ use std::env;
|
|||
use std::str::FromStr;
|
||||
|
||||
use cfg_if::cfg_if;
|
||||
use log::{error, info, warn};
|
||||
use log::{error, info};
|
||||
use macros::rmc_struct;
|
||||
use rnex_core::prudp::socket_addr::PRUDPSockAddr;
|
||||
use rnex_core::rmc::protocols::notifications::{NotificationEvent, RemoteNotification};
|
||||
|
|
@ -456,7 +456,7 @@ impl MatchmakeExtension for User {
|
|||
.users_by_pid
|
||||
.read()
|
||||
.await
|
||||
.get(&recpipent)
|
||||
.get(&bytemuck::cast(recpipent))
|
||||
.and_then(|v| v.upgrade())
|
||||
else {
|
||||
return Err(ErrorCode::Core_InvalidArgument);
|
||||
|
|
@ -468,8 +468,8 @@ impl MatchmakeExtension for User {
|
|||
.process_notification_event(NotificationEvent {
|
||||
pid_source: self.pid,
|
||||
notif_type: REQUEST_JOIN_GATHERING * 1000,
|
||||
param_1,
|
||||
param_2,
|
||||
param_1: bytemuck::cast(param_1),
|
||||
param_2: bytemuck::cast(param_2),
|
||||
#[cfg(feature = "third-notif-param")]
|
||||
param_3: 0,
|
||||
str_param,
|
||||
|
|
@ -481,8 +481,8 @@ impl MatchmakeExtension for User {
|
|||
.process_notification_event(NotificationEvent {
|
||||
pid_source: self.pid,
|
||||
notif_type: END_GATHERING * 1000,
|
||||
param_1,
|
||||
param_2,
|
||||
param_1: bytemuck::cast(param_1),
|
||||
param_2: bytemuck::cast(param_2),
|
||||
#[cfg(feature = "third-notif-param")]
|
||||
param_3: 0,
|
||||
str_param,
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ use rnex_core::{
|
|||
rmc::{response::ErrorCode, structures::any::Any},
|
||||
};
|
||||
|
||||
use crate::{kerberos::KerberosDateTime, rmc::protocols::friends::NNAInfo};
|
||||
use crate::{kerberos::KerberosDateTime, rmc::protocols::friends_wiiu::NNAInfo};
|
||||
|
||||
#[derive(RmcSerialize, Debug, Clone)]
|
||||
#[rmc_struct(0)]
|
||||
|
|
|
|||
250
rnex-core/src/rmc/protocols/friends_3ds.rs
Normal file
250
rnex-core/src/rmc/protocols/friends_3ds.rs
Normal file
|
|
@ -0,0 +1,250 @@
|
|||
use macros::{RmcSerialize, method_id, rmc_proto};
|
||||
|
||||
use rnex_core::rmc::{response::ErrorCode, structures::data::Data};
|
||||
|
||||
use crate::{PID, kerberos::KerberosDateTime};
|
||||
|
||||
#[derive(RmcSerialize)]
|
||||
#[rmc_struct(0)]
|
||||
pub struct MyProfile {
|
||||
#[extends]
|
||||
pub data: Data,
|
||||
pub region: u8,
|
||||
pub country: u8,
|
||||
pub area: u8,
|
||||
pub language: u8,
|
||||
pub platform: u8,
|
||||
pub local_friend_code_seed: u64,
|
||||
pub mac_address: String,
|
||||
pub serial_number: String,
|
||||
}
|
||||
|
||||
#[derive(RmcSerialize)]
|
||||
#[rmc_struct(0)]
|
||||
pub struct Mii {
|
||||
#[extends]
|
||||
pub data: Data,
|
||||
pub unk1: String,
|
||||
pub unk2: bool,
|
||||
pub unk3: u8,
|
||||
pub mii_data: Vec<u8>,
|
||||
}
|
||||
|
||||
#[derive(RmcSerialize)]
|
||||
#[rmc_struct(0)]
|
||||
pub struct MiiList {
|
||||
#[extends]
|
||||
pub data: Data,
|
||||
pub unk1: String,
|
||||
pub unk2: bool,
|
||||
pub unk3: u8,
|
||||
pub mii_data: Vec<Vec<u8>>,
|
||||
}
|
||||
|
||||
#[derive(RmcSerialize)]
|
||||
#[rmc_struct(0)]
|
||||
pub struct GameKey {
|
||||
#[extends]
|
||||
pub data: Data,
|
||||
pub title_id: u64,
|
||||
pub version: u16,
|
||||
}
|
||||
|
||||
#[derive(RmcSerialize)]
|
||||
#[rmc_struct(0)]
|
||||
pub struct PlayedGame {
|
||||
#[extends]
|
||||
pub data: Data,
|
||||
pub game_key: GameKey,
|
||||
pub date_time: KerberosDateTime,
|
||||
}
|
||||
|
||||
#[derive(RmcSerialize)]
|
||||
#[rmc_struct(0)]
|
||||
pub struct FriendInfo {
|
||||
pub unk1: u32,
|
||||
pub unk2: KerberosDateTime,
|
||||
}
|
||||
|
||||
#[derive(RmcSerialize)]
|
||||
#[rmc_struct(0)]
|
||||
pub struct FriendMii {
|
||||
#[extends]
|
||||
pub data: Data,
|
||||
pub pid: PID,
|
||||
pub mii: Mii,
|
||||
pub modified_at: KerberosDateTime,
|
||||
}
|
||||
|
||||
#[derive(RmcSerialize)]
|
||||
#[rmc_struct(0)]
|
||||
pub struct FriendMiiList {
|
||||
#[extends]
|
||||
pub data: Data,
|
||||
pub unk1: u32,
|
||||
pub mii_list: MiiList,
|
||||
pub unk2: KerberosDateTime,
|
||||
}
|
||||
|
||||
#[derive(RmcSerialize)]
|
||||
#[rmc_struct(0)]
|
||||
pub struct FriendRelationship {
|
||||
#[extends]
|
||||
pub data: Data,
|
||||
pub unk1: u32,
|
||||
pub unk2: u64,
|
||||
pub unk3: u8,
|
||||
}
|
||||
|
||||
#[derive(RmcSerialize)]
|
||||
#[rmc_struct(0)]
|
||||
pub struct NintendoPresence {
|
||||
#[extends]
|
||||
pub data: Data,
|
||||
pub changed_bit_flag: u32,
|
||||
pub game_key: GameKey,
|
||||
pub game_mode_desctiption: String,
|
||||
pub join_availibility_flag: u32,
|
||||
pub mm_system_type: u8,
|
||||
pub join_game_id: u32,
|
||||
pub join_game_mode: u32,
|
||||
pub owner_pid: PID,
|
||||
pub join_group_id: u32,
|
||||
pub application_arg: Vec<u8>,
|
||||
}
|
||||
#[derive(RmcSerialize)]
|
||||
#[rmc_struct(0)]
|
||||
pub struct FriendPresence {
|
||||
#[extends]
|
||||
pub data: Data,
|
||||
pub unk: u32,
|
||||
pub presence: NintendoPresence,
|
||||
}
|
||||
#[derive(RmcSerialize)]
|
||||
#[rmc_struct(0)]
|
||||
pub struct FriendComment {
|
||||
#[extends]
|
||||
pub data: Data,
|
||||
pub pid: PID,
|
||||
pub comment: String,
|
||||
pub modified_at: KerberosDateTime,
|
||||
}
|
||||
#[derive(RmcSerialize)]
|
||||
#[rmc_struct(0)]
|
||||
pub struct FriendPicture {
|
||||
#[extends]
|
||||
pub data: Data,
|
||||
pub unk1: u32,
|
||||
pub pic_data: Vec<u32>,
|
||||
pub date_time: KerberosDateTime,
|
||||
}
|
||||
|
||||
#[derive(RmcSerialize)]
|
||||
#[rmc_struct(0)]
|
||||
pub struct FriendPersistentInfo {
|
||||
#[extends]
|
||||
pub data: Data,
|
||||
pub pid: PID,
|
||||
pub region: u8,
|
||||
pub country: u8,
|
||||
pub area: u8,
|
||||
pub language: u8,
|
||||
pub platform: u8,
|
||||
pub game_key: GameKey,
|
||||
pub message: String,
|
||||
pub msg_updated_at: KerberosDateTime,
|
||||
pub friended_at: KerberosDateTime,
|
||||
pub last_online: KerberosDateTime,
|
||||
}
|
||||
|
||||
#[rmc_proto(101)]
|
||||
pub trait Friends3DS {
|
||||
#[method_id(1)]
|
||||
async fn update_profile(&self, profile: MyProfile) -> Result<(), ErrorCode>;
|
||||
#[method_id(2)]
|
||||
async fn update_mii(&self, profile: Mii) -> Result<(), ErrorCode>;
|
||||
#[method_id(3)]
|
||||
async fn update_mii_list(&self, profile: MiiList) -> Result<(), ErrorCode>;
|
||||
#[method_id(4)]
|
||||
async fn update_played_games(&self, profile: Vec<PlayedGame>) -> Result<(), ErrorCode>;
|
||||
#[method_id(5)]
|
||||
async fn update_preference(
|
||||
&self,
|
||||
show_online_status: bool,
|
||||
show_current_title: bool,
|
||||
block_friend_requests: bool,
|
||||
) -> Result<(), ErrorCode>;
|
||||
|
||||
#[method_id(6)]
|
||||
async fn get_friend_mii(&self, friends: Vec<FriendInfo>) -> Result<Vec<FriendMii>, ErrorCode>;
|
||||
#[method_id(7)]
|
||||
async fn get_friend_mii_list(
|
||||
&self,
|
||||
friends: Vec<FriendInfo>,
|
||||
) -> Result<Vec<FriendMiiList>, ErrorCode>;
|
||||
#[method_id(8)]
|
||||
async fn is_active_game(&self, unk: Vec<u32>, game_key: GameKey)
|
||||
-> Result<Vec<u32>, ErrorCode>;
|
||||
#[method_id(9)]
|
||||
async fn get_principal_id_by_local_friend_code(
|
||||
&self,
|
||||
unk1: u64,
|
||||
unk2: Vec<u64>,
|
||||
) -> Result<Vec<FriendRelationship>, ErrorCode>;
|
||||
#[method_id(10)]
|
||||
async fn get_friend_relationships(
|
||||
&self,
|
||||
unk2: Vec<u32>,
|
||||
) -> Result<Vec<FriendRelationship>, ErrorCode>;
|
||||
#[method_id(11)]
|
||||
async fn add_friend_by_pid(&self, unk: u64, pid: PID) -> Result<FriendRelationship, ErrorCode>;
|
||||
#[method_id(12)]
|
||||
async fn add_friend_by_lst_pid(
|
||||
&self,
|
||||
unk: u64,
|
||||
pid: Vec<PID>,
|
||||
) -> Result<Vec<FriendRelationship>, ErrorCode>;
|
||||
#[method_id(13)]
|
||||
async fn remove_friend_by_local_code(&self, local_code: u64) -> Result<(), ErrorCode>;
|
||||
#[method_id(14)]
|
||||
async fn remove_friend_by_pid(&self, pid: PID) -> Result<(), ErrorCode>;
|
||||
#[method_id(15)]
|
||||
async fn get_all_friends(&self) -> Result<Vec<FriendRelationship>, ErrorCode>;
|
||||
#[method_id(16)]
|
||||
async fn update_blacklist(&self) -> Result<(), ErrorCode>;
|
||||
#[method_id(17)]
|
||||
async fn sync_friend(
|
||||
&self,
|
||||
unk1: u64,
|
||||
unk2: Vec<u32>,
|
||||
unk3: Vec<u64>,
|
||||
) -> Result<Vec<FriendRelationship>, ErrorCode>;
|
||||
#[method_id(18)]
|
||||
async fn update_presence(
|
||||
&self,
|
||||
nintendo_presence: NintendoPresence,
|
||||
unk: bool,
|
||||
) -> Result<(), ErrorCode>;
|
||||
#[method_id(19)]
|
||||
async fn update_favorite_game_key(&self, game_key: GameKey) -> Result<(), ErrorCode>;
|
||||
#[method_id(20)]
|
||||
async fn update_comment(&self, comment: String) -> Result<(), ErrorCode>;
|
||||
#[method_id(21)]
|
||||
async fn update_picture(&self, unk: u32, picture: Vec<u8>) -> Result<(), ErrorCode>;
|
||||
#[method_id(22)]
|
||||
async fn get_friend_presence(&self, unk: Vec<u32>) -> Result<Vec<FriendPresence>, ErrorCode>;
|
||||
#[method_id(23)]
|
||||
async fn get_friend_comment(
|
||||
&self,
|
||||
unk: Vec<FriendInfo>,
|
||||
) -> Result<Vec<FriendComment>, ErrorCode>;
|
||||
#[method_id(24)]
|
||||
async fn get_friend_picture(&self, unk: Vec<u32>) -> Result<Vec<FriendPicture>, ErrorCode>;
|
||||
#[method_id(25)]
|
||||
async fn get_friend_persistent_info(
|
||||
&self,
|
||||
unk: Vec<u32>,
|
||||
) -> Result<Vec<FriendPersistentInfo>, ErrorCode>;
|
||||
#[method_id(26)]
|
||||
async fn send_invitation(&self, unk: Vec<u32>) -> Result<(), ErrorCode>;
|
||||
}
|
||||
|
|
@ -4,6 +4,8 @@ use rnex_core::{kerberos::KerberosDateTime, rmc::response::ErrorCode};
|
|||
|
||||
use rnex_core::rmc::structures::data::Data;
|
||||
|
||||
use rnex_core::PID;
|
||||
|
||||
#[derive(RmcSerialize, Debug, Clone)]
|
||||
#[rmc_struct(0)]
|
||||
pub struct MiiV2 {
|
||||
|
|
@ -21,7 +23,7 @@ pub struct MiiV2 {
|
|||
pub struct PrincipalBasicInfo {
|
||||
#[extends]
|
||||
pub data: Data,
|
||||
pub pid: u32,
|
||||
pub pid: PID,
|
||||
pub nnid: String,
|
||||
pub mii: MiiV2,
|
||||
pub unk: u8,
|
||||
|
|
@ -147,8 +149,17 @@ pub struct PersistentNotification {
|
|||
pub unk5: String,
|
||||
}
|
||||
|
||||
#[derive(RmcSerialize)]
|
||||
#[rmc_struct(0)]
|
||||
pub struct PrincipalRequestBlockSetting {
|
||||
#[extends]
|
||||
pub data: Data,
|
||||
pub pid: PID,
|
||||
pub blocked: bool,
|
||||
}
|
||||
|
||||
#[rmc_proto(102)]
|
||||
pub trait Friends {
|
||||
pub trait FriendsWiiU {
|
||||
#[method_id(1)]
|
||||
async fn update_and_get_all_information(
|
||||
&self,
|
||||
|
|
@ -169,10 +180,53 @@ pub trait Friends {
|
|||
),
|
||||
ErrorCode,
|
||||
>;
|
||||
#[method_id(2)]
|
||||
async fn add_friend(&self, friend: PID) -> Result<(FriendRequest, FriendInfo), ErrorCode>;
|
||||
#[method_id(3)]
|
||||
async fn add_friend_by_name(
|
||||
&self,
|
||||
name: String,
|
||||
) -> Result<(FriendRequest, FriendInfo), ErrorCode>;
|
||||
#[method_id(4)]
|
||||
async fn remove_friend(&self, friend: PID) -> Result<(), ErrorCode>;
|
||||
#[method_id(5)]
|
||||
async fn add_friend_request(
|
||||
&self,
|
||||
friend: PID,
|
||||
unk1: u8,
|
||||
message: String,
|
||||
unk2: u8,
|
||||
unk3: String,
|
||||
game_key: GameKey,
|
||||
unk4: KerberosDateTime,
|
||||
) -> Result<(FriendRequest, FriendInfo), ErrorCode>;
|
||||
#[method_id(6)]
|
||||
async fn cancel_friend_request(&self, id: u64) -> Result<(), ErrorCode>;
|
||||
#[method_id(7)]
|
||||
async fn accept_friend_request(&self, id: u64) -> Result<FriendInfo, ErrorCode>;
|
||||
#[method_id(8)]
|
||||
async fn delete_friend_request(&self, id: u64) -> Result<(), ErrorCode>;
|
||||
#[method_id(9)]
|
||||
async fn deny_friend_request(&self, id: u64) -> Result<BlacklistedPrincipal, ErrorCode>;
|
||||
#[method_id(10)]
|
||||
async fn mark_friend_requests_as_received(&self, ids: Vec<u64>) -> Result<(), ErrorCode>;
|
||||
#[method_id(11)]
|
||||
async fn add_blacklist(
|
||||
&self,
|
||||
principal: BlacklistedPrincipal,
|
||||
) -> Result<BlacklistedPrincipal, ErrorCode>;
|
||||
#[method_id(12)]
|
||||
async fn remove_blacklist(&self, id: PID) -> Result<(), ErrorCode>;
|
||||
#[method_id(13)]
|
||||
async fn update_presence(&self, presence: NintendoPresenceV2) -> Result<(), ErrorCode>;
|
||||
#[method_id(14)]
|
||||
async fn update_mii(&self, presence: MiiV2) -> Result<KerberosDateTime, ErrorCode>;
|
||||
#[method_id(15)]
|
||||
async fn update_comment(&self, presence: Comment) -> Result<KerberosDateTime, ErrorCode>;
|
||||
#[method_id(16)]
|
||||
async fn update_preference(&self, preference: PrincipalPreference) -> Result<(), ErrorCode>;
|
||||
#[method_id(17)]
|
||||
async fn get_basic_info(&self, pids: Vec<PID>) -> Result<Vec<PrincipalBasicInfo>, ErrorCode>;
|
||||
#[method_id(18)]
|
||||
async fn delete_persistent_notification(
|
||||
&self,
|
||||
|
|
@ -180,4 +234,9 @@ pub trait Friends {
|
|||
) -> Result<(), ErrorCode>;
|
||||
#[method_id(19)]
|
||||
async fn check_setting_status(&self) -> Result<u8, ErrorCode>;
|
||||
#[method_id(20)]
|
||||
async fn get_request_block_settings(
|
||||
&self,
|
||||
unk: Vec<u32>,
|
||||
) -> Result<Vec<PrincipalRequestBlockSetting>, ErrorCode>;
|
||||
}
|
||||
|
|
@ -3,7 +3,8 @@
|
|||
pub mod account_management;
|
||||
pub mod auth;
|
||||
pub mod datastore;
|
||||
pub mod friends;
|
||||
pub mod friends_3ds;
|
||||
pub mod friends_wiiu;
|
||||
pub mod matchmake;
|
||||
pub mod matchmake_ext;
|
||||
pub mod matchmake_extension;
|
||||
|
|
|
|||
|
|
@ -1,10 +1,12 @@
|
|||
use macros::{RmcSerialize, method_id, rmc_proto};
|
||||
|
||||
use rnex_core::kerberos::KerberosDateTime;
|
||||
use rnex_core::rmc::structures::qbuffer::QBuffer;
|
||||
use rnex_core::rmc::structures::resultsrange::ResultsRange;
|
||||
use rnex_core::rmc::response::ErrorCode;
|
||||
use rnex_core::rmc::structures::qbuffer::QBuffer;
|
||||
use rnex_core::rmc::structures::ranking::UploadCompetitionData;
|
||||
use rnex_core::rmc::structures::resultsrange::ResultsRange;
|
||||
|
||||
use crate::PID;
|
||||
|
||||
#[derive(RmcSerialize, Debug, Default, Clone)]
|
||||
#[rmc_struct(1)]
|
||||
|
|
@ -28,7 +30,7 @@ pub struct CompetitionRankingScoreInfo {
|
|||
#[rmc_struct(0)]
|
||||
pub struct CompetitionRankingScoreData {
|
||||
pub unk: u32,
|
||||
pub pid: u32,
|
||||
pub pid: PID,
|
||||
pub score: u32,
|
||||
pub modified: KerberosDateTime,
|
||||
pub unk2: u8,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
use cfg_if::cfg_if;
|
||||
use macros::RmcSerialize;
|
||||
use rnex_core::kerberos::KerberosDateTime;
|
||||
use rnex_core::rmc::structures::variant::Variant;
|
||||
|
||||
use rnex_core::PID;
|
||||
|
|
@ -32,6 +31,7 @@ pub struct MatchmakeParam {
|
|||
|
||||
cfg_if! {
|
||||
if #[cfg(feature = "v3-5-0")]{
|
||||
use rnex_core::kerberos::KerberosDateTime;
|
||||
#[derive(RmcSerialize, Debug, Clone, Default, PartialEq)]
|
||||
#[rmc_struct(3)]
|
||||
pub struct MatchmakeSession {
|
||||
|
|
|
|||
88
rnex-core/src/server_api/gatherings.rs
Normal file
88
rnex-core/src/server_api/gatherings.rs
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
use std::{
|
||||
hash::{DefaultHasher, Hash, Hasher},
|
||||
sync::Arc,
|
||||
};
|
||||
|
||||
use rnex_server_api::gatherings::{
|
||||
Gatherings, gathering_info_service_server::GatheringInfoService,
|
||||
};
|
||||
use tonic::{Request, Response, Status, async_trait};
|
||||
|
||||
use crate::{
|
||||
nex::matchmake::{ExtendedMatchmakeSession, MatchmakeManager},
|
||||
rmc::structures::matchmake::{self, MatchmakeSession},
|
||||
server_api,
|
||||
};
|
||||
|
||||
impl Into<rnex_server_api::gatherings::Gathering> for &ExtendedMatchmakeSession {
|
||||
fn into(self) -> rnex_server_api::gatherings::Gathering {
|
||||
let players = self.get_active_players().map(|p| *p.pid as u64).collect();
|
||||
let ExtendedMatchmakeSession {
|
||||
session:
|
||||
MatchmakeSession {
|
||||
gathering:
|
||||
matchmake::Gathering {
|
||||
state,
|
||||
flags,
|
||||
host_pid,
|
||||
description,
|
||||
maximum_participants,
|
||||
minimum_participants,
|
||||
owner_pid,
|
||||
participant_policy,
|
||||
policy_argument,
|
||||
self_gid,
|
||||
},
|
||||
application_buffer,
|
||||
attributes,
|
||||
gamemode,
|
||||
matchmake_system_type,
|
||||
open_participation,
|
||||
participation_count,
|
||||
session_key,
|
||||
},
|
||||
connected_players,
|
||||
} = self;
|
||||
rnex_server_api::gatherings::Gathering {
|
||||
players,
|
||||
description: description.clone(),
|
||||
flags: *flags,
|
||||
host_pid: *host_pid as _,
|
||||
maximum_participants: *maximum_participants as _,
|
||||
minimum_participants: *minimum_participants as _,
|
||||
owner_pid: *owner_pid as _,
|
||||
participant_policy: *participant_policy,
|
||||
policy_argument: *policy_argument,
|
||||
self_gid: *self_gid,
|
||||
state: *state,
|
||||
application_buffer: application_buffer.clone(),
|
||||
attributes: attributes.clone(),
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct GatheringsApi(Arc<MatchmakeManager>);
|
||||
|
||||
#[async_trait]
|
||||
impl GatheringInfoService for GatheringsApi {
|
||||
async fn get_gatherings(
|
||||
&self,
|
||||
request: Request<()>,
|
||||
) -> std::result::Result<Response<Gatherings>, Status> {
|
||||
Ok(Response::new(Gatherings {
|
||||
gatherings: self
|
||||
.0
|
||||
.sessions
|
||||
.read()
|
||||
.await
|
||||
.keys()
|
||||
.map(|gid| {
|
||||
let mut hasher = DefaultHasher::new();
|
||||
gid.hash(&mut hasher);
|
||||
hasher.finish()
|
||||
})
|
||||
.collect(),
|
||||
}))
|
||||
}
|
||||
}
|
||||
36
rnex-core/src/server_api/meta.rs
Normal file
36
rnex-core/src/server_api/meta.rs
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
use rnex_server_api::meta::{
|
||||
ApiFeature, ApiFeatures, BuildInfo, server_meta_service_server::ServerMetaService,
|
||||
};
|
||||
use tonic::{Request, Response, Status, async_trait, transport::Server};
|
||||
|
||||
pub struct ServerMeta;
|
||||
|
||||
#[async_trait]
|
||||
impl ServerMetaService for ServerMeta {
|
||||
async fn get_build_info(&self, request: Request<()>) -> Result<Response<BuildInfo>, Status> {
|
||||
Ok(Response::new(BuildInfo {
|
||||
version: env!("CARGO_PKG_VERSION").to_owned(),
|
||||
edition: env!("EDITION").to_owned(),
|
||||
build_hash: env!("GIT_HASH").to_owned(),
|
||||
feature_set: env!("FEATURESET").to_owned(),
|
||||
}))
|
||||
}
|
||||
async fn get_api_features(
|
||||
&self,
|
||||
request: Request<()>,
|
||||
) -> Result<Response<ApiFeatures>, Status> {
|
||||
let mut api_features = vec![ApiFeature {
|
||||
name: "meta".to_owned(),
|
||||
needs_admin: false,
|
||||
version: 0,
|
||||
}];
|
||||
|
||||
#[cfg(not(feature = "friends"))]
|
||||
api_features.push(ApiFeature {
|
||||
name: "gatherings".to_owned(),
|
||||
version: 0,
|
||||
needs_admin: true,
|
||||
});
|
||||
Ok(Response::new(ApiFeatures { api_features }))
|
||||
}
|
||||
}
|
||||
22
rnex-core/src/server_api/mod.rs
Normal file
22
rnex-core/src/server_api/mod.rs
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
use std::{net::SocketAddr, str::FromStr};
|
||||
|
||||
use rnex_server_api::meta::server_meta_service_server::ServerMetaServiceServer;
|
||||
use tonic::transport::Server;
|
||||
|
||||
#[cfg(not(feature = "friends"))]
|
||||
use crate::nex::matchmake::MatchmakeManager;
|
||||
use crate::server_api::meta::ServerMeta;
|
||||
#[cfg(not(feature = "friends"))]
|
||||
use std::sync::Arc;
|
||||
#[cfg(not(feature = "friends"))]
|
||||
mod gatherings;
|
||||
|
||||
mod meta;
|
||||
|
||||
pub async fn launch_server_api(#[cfg(not(feature = "friends"))] mmm: Arc<MatchmakeManager>) {
|
||||
let mut server = Server::builder().add_service(ServerMetaServiceServer::new(ServerMeta));
|
||||
|
||||
server
|
||||
.serve(SocketAddr::from_str("0.0.0.0:80").expect("unable to make sockaddr from ip"))
|
||||
.await;
|
||||
}
|
||||
54
rnex-server-api-grpc/gatherings.proto
Normal file
54
rnex-server-api-grpc/gatherings.proto
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
syntax = "proto3";
|
||||
// NOTE: NEVER give out gids to the general public, people can and will be
|
||||
// able to join random mkatches which they arent supposed to join via them
|
||||
//
|
||||
// As an alternative use a unique hash of the Gid
|
||||
|
||||
import "google/protobuf/empty.proto";
|
||||
|
||||
package gatherings;
|
||||
|
||||
message MatchmakeParam{
|
||||
|
||||
}
|
||||
|
||||
message KerberosDateTime{
|
||||
uint32 raw = 1;
|
||||
}
|
||||
|
||||
message Gathering{
|
||||
repeated uint64 players = 1;
|
||||
uint32 self_gid = 2;
|
||||
uint64 owner_pid = 3;
|
||||
uint64 host_pid = 4;
|
||||
uint32 minimum_participants = 5;
|
||||
uint32 maximum_participants = 6;
|
||||
uint32 participant_policy = 7;
|
||||
uint32 policy_argument = 8;
|
||||
uint32 flags = 9;
|
||||
uint32 state = 10;
|
||||
string description = 11;
|
||||
uint32 gamemode = 12;
|
||||
repeated uint32 attributes = 13;
|
||||
bool open_participation = 14;
|
||||
uint32 matchmake_system_type = 15;
|
||||
bytes application_buffer = 16;
|
||||
uint32 participation_count = 17;
|
||||
bytes session_key = 18;
|
||||
optional uint32 progress_score = 19;
|
||||
optional uint32 option0 = 20;
|
||||
optional MatchmakeParam matchmake_param = 21;
|
||||
optional KerberosDateTime datetime = 22;
|
||||
optional string user_password = 23;
|
||||
optional uint32 refer_gid = 24;
|
||||
optional bool user_password_enabled = 25;
|
||||
optional bool system_password_enabled = 26;
|
||||
}
|
||||
|
||||
message Gatherings{
|
||||
repeated Gathering gatherings = 1;
|
||||
}
|
||||
|
||||
service GatheringInfoService{
|
||||
rpc GetGatherings(google.protobuf.Empty) returns (Gatherings);
|
||||
}
|
||||
27
rnex-server-api-grpc/meta.proto
Normal file
27
rnex-server-api-grpc/meta.proto
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
syntax = "proto3";
|
||||
|
||||
package meta;
|
||||
|
||||
import "google/protobuf/empty.proto";
|
||||
|
||||
message BuildInfo {
|
||||
string version = 1;
|
||||
string edition = 2;
|
||||
string feature_set = 3;
|
||||
string build_hash = 4;
|
||||
}
|
||||
|
||||
message ApiFeature {
|
||||
string name = 1;
|
||||
int32 version = 2;
|
||||
bool needs_admin = 3;
|
||||
}
|
||||
|
||||
message ApiFeatures {
|
||||
repeated ApiFeature api_features = 1;
|
||||
}
|
||||
|
||||
service ServerMetaService {
|
||||
rpc GetBuildInfo(google.protobuf.Empty) returns (BuildInfo);
|
||||
rpc GetApiFeatures(google.protobuf.Empty) returns (ApiFeatures);
|
||||
}
|
||||
12
rnex-server-api/Cargo.toml
Normal file
12
rnex-server-api/Cargo.toml
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
[package]
|
||||
name = "rnex-server-api"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
prost = "0.14.3"
|
||||
tonic-prost = "*"
|
||||
tonic = "0.14.6"
|
||||
|
||||
[build-dependencies]
|
||||
tonic-prost-build = "0.14.6"
|
||||
24
rnex-server-api/build.rs
Normal file
24
rnex-server-api/build.rs
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
use std::{env, fs};
|
||||
|
||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
println!("cargo:rerun-if-changed=build.rs");
|
||||
println!("cargo:rerun-if-changed=../rnex-server-api-grpc/");
|
||||
|
||||
let protos: Vec<String> = fs::read_dir("../rnex-server-api-grpc/")?
|
||||
.filter(|e| {
|
||||
e.as_ref().is_ok_and(|e| {
|
||||
e.file_name()
|
||||
.to_str()
|
||||
.is_some_and(|n| n.ends_with(".proto"))
|
||||
})
|
||||
})
|
||||
.filter_map(|e| {
|
||||
e.ok()
|
||||
.map(|v| v.path().to_str().map(|v| v.to_owned()))
|
||||
.flatten()
|
||||
})
|
||||
.collect();
|
||||
tonic_prost_build::configure()
|
||||
.compile_protos(&protos[..], &["../rnex-server-api-grpc/".to_owned()])?;
|
||||
Ok(())
|
||||
}
|
||||
6
rnex-server-api/src/lib.rs
Normal file
6
rnex-server-api/src/lib.rs
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
pub mod meta {
|
||||
tonic::include_proto!("meta");
|
||||
}
|
||||
pub mod gatherings {
|
||||
tonic::include_proto!("gatherings");
|
||||
}
|
||||
Loading…
Reference in a new issue