fix port binding
This commit is contained in:
parent
dad8ac498c
commit
785341e883
43 changed files with 1543 additions and 431 deletions
|
|
@ -34,6 +34,11 @@ ureq = "3.1.4"
|
|||
rmc_struct_header = []
|
||||
guest_login = []
|
||||
friends = ["guest_login"]
|
||||
big_pid = []
|
||||
v3-8-15 = ["rmc_struct_header"]
|
||||
v4-3-11 = ["v3-8-15"]
|
||||
nx = ["big_pid"]
|
||||
|
||||
|
||||
[[bench]]
|
||||
name = "rmc_serialization"
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ async fn main() {
|
|||
if #[cfg(feature = "friends")]{
|
||||
start_friends_backend().await;
|
||||
} else {
|
||||
use rnex_core::executables::regular_backend;
|
||||
regular_backend::start_regular_backend().await
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,22 +1,65 @@
|
|||
use std::sync::{Arc, atomic::AtomicU32};
|
||||
use std::{
|
||||
io::Cursor,
|
||||
net::SocketAddrV4,
|
||||
sync::{Arc, atomic::AtomicU32},
|
||||
};
|
||||
|
||||
use log::error;
|
||||
use tokio::net::TcpListener;
|
||||
|
||||
use crate::{
|
||||
executables::common::new_simple_backend,
|
||||
nex::friends_handler::{FriendsManager, FriendsUser},
|
||||
executables::common::{OWN_IP_PRIVATE, SERVER_PORT, new_simple_backend},
|
||||
nex::friends_handler::{FriendsGuest, FriendsManager, FriendsUser},
|
||||
reggie::UnitPacketRead,
|
||||
rmc::{
|
||||
protocols::{RmcCallable, new_rmc_gateway_connection},
|
||||
structures::RmcSerialize,
|
||||
},
|
||||
rnex_proxy_common::ConnectionInitData,
|
||||
};
|
||||
|
||||
pub async fn start_friends_backend() {
|
||||
let fm = Arc::new(FriendsManager {
|
||||
cid_counter: AtomicU32::new(1),
|
||||
});
|
||||
let listen = TcpListener::bind(SocketAddrV4::new(*OWN_IP_PRIVATE, *SERVER_PORT))
|
||||
.await
|
||||
.unwrap();
|
||||
while let Ok((mut stream, _addr)) = listen.accept().await {
|
||||
let buffer = match stream.read_buffer().await {
|
||||
Ok(v) => v,
|
||||
Err(e) => {
|
||||
error!(
|
||||
"an error ocurred whilest reading connection data buffer: {:?}",
|
||||
e
|
||||
);
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
||||
new_simple_backend(move |c, r| {
|
||||
let user_connection_data = ConnectionInitData::deserialize(&mut Cursor::new(buffer));
|
||||
|
||||
let c = match user_connection_data {
|
||||
Ok(v) => v,
|
||||
Err(e) => {
|
||||
error!("an error ocurred whilest reading connection data: {:?}", e);
|
||||
continue;
|
||||
}
|
||||
};
|
||||
let fm = fm.clone();
|
||||
Arc::new_cyclic(move |this| FriendsUser {
|
||||
fm,
|
||||
addr: c.prudpsock_addr,
|
||||
pid: c.pid,
|
||||
})
|
||||
})
|
||||
.await;
|
||||
if c.pid != 100 {
|
||||
new_rmc_gateway_connection(stream.into(), move |r| {
|
||||
Arc::new_cyclic(move |this| FriendsUser {
|
||||
fm,
|
||||
addr: c.prudpsock_addr,
|
||||
pid: c.pid,
|
||||
})
|
||||
});
|
||||
} else {
|
||||
Arc::new_cyclic(move |this| FriendsGuest {
|
||||
fm,
|
||||
addr: c.prudpsock_addr,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,29 +1,27 @@
|
|||
use std::{env, result};
|
||||
use crate::grpc::account::Error::SomethingHappened;
|
||||
use json::{JsonValue, object};
|
||||
use once_cell::sync::Lazy;
|
||||
use rnex_core::PID;
|
||||
use std::array::TryFromSliceError;
|
||||
use std::ops::Deref;
|
||||
use json::{object, JsonValue};
|
||||
use once_cell::sync::Lazy;
|
||||
use std::{env, result};
|
||||
use thiserror::Error;
|
||||
use tokio::task::{spawn_blocking, JoinError};
|
||||
use crate::grpc::account::Error::SomethingHappened;
|
||||
static API_KEY: Lazy<String> = Lazy::new(||{
|
||||
let key = env::var("ACCOUNT_GQL_API_KEY")
|
||||
.expect("no graphql ip specified");
|
||||
use tokio::task::{JoinError, spawn_blocking};
|
||||
static API_KEY: Lazy<String> = Lazy::new(|| {
|
||||
let key = env::var("ACCOUNT_GQL_API_KEY").expect("no graphql ip specified");
|
||||
|
||||
key
|
||||
});
|
||||
|
||||
static CLIENT_URI: Lazy<String> = Lazy::new(||{
|
||||
static CLIENT_URI: Lazy<String> = Lazy::new(|| {
|
||||
env::var("ACCOUNT_GQL_URL")
|
||||
.ok()
|
||||
.and_then(|s| s.parse().ok())
|
||||
.expect("no graphql ip specified")
|
||||
});
|
||||
|
||||
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
pub enum Error{
|
||||
pub enum Error {
|
||||
#[error(transparent)]
|
||||
RequestError(#[from] ureq::Error),
|
||||
#[error(transparent)]
|
||||
|
|
@ -35,20 +33,20 @@ pub enum Error{
|
|||
#[error("something happened")]
|
||||
SomethingHappened,
|
||||
#[error("error joining blocking task: {0}")]
|
||||
Join(#[from] JoinError)
|
||||
Join(#[from] JoinError),
|
||||
}
|
||||
|
||||
pub type Result<T> = result::Result<T, Error>;
|
||||
|
||||
pub struct Client;//(reqwest::Client);
|
||||
pub struct Client; //(reqwest::Client);
|
||||
|
||||
impl Client{
|
||||
impl Client {
|
||||
pub async fn new() -> Result<Self> {
|
||||
//Ok(Self(reqwest::ClientBuilder::new().build()?))
|
||||
Ok(Self)
|
||||
}
|
||||
|
||||
async fn do_request(&self, request_data: JsonValue) -> Result<JsonValue>{
|
||||
async fn do_request(&self, request_data: JsonValue) -> Result<JsonValue> {
|
||||
let request = ureq::post(CLIENT_URI.as_str())
|
||||
.header("X-API-Key", API_KEY.deref())
|
||||
.content_type("application/json");
|
||||
|
|
@ -70,28 +68,35 @@ impl Client{
|
|||
*/
|
||||
}
|
||||
|
||||
pub async fn get_nex_password(&mut self , pid: u32) -> Result<[u8; 16]>{
|
||||
let req = self.do_request(object!{
|
||||
"query": r"query($pid: Int!){
|
||||
pub async fn get_nex_password(&mut self, pid: PID) -> Result<[u8; 16]> {
|
||||
let req = self
|
||||
.do_request(object! {
|
||||
"query": r"query($pid: Int!){
|
||||
userByPid(pid: $pid){
|
||||
nexPassword
|
||||
}
|
||||
}",
|
||||
"variables": {
|
||||
"pid": pid
|
||||
}
|
||||
}).await?;
|
||||
"variables": {
|
||||
"pid": pid
|
||||
}
|
||||
})
|
||||
.await?;
|
||||
|
||||
let Some(val) = req.entries()
|
||||
let Some(val) = req
|
||||
.entries()
|
||||
.find(|v| v.0 == "data")
|
||||
.ok_or(SomethingHappened)?.1
|
||||
.ok_or(SomethingHappened)?
|
||||
.1
|
||||
.entries()
|
||||
.find(|v| v.0 == "userByPid")
|
||||
.ok_or(SomethingHappened)?.1
|
||||
.ok_or(SomethingHappened)?
|
||||
.1
|
||||
.entries()
|
||||
.find(|v| v.0 == "nexPassword")
|
||||
.ok_or(SomethingHappened)?.1
|
||||
.as_str() else {
|
||||
.ok_or(SomethingHappened)?
|
||||
.1
|
||||
.as_str()
|
||||
else {
|
||||
return Err(SomethingHappened);
|
||||
};
|
||||
|
||||
|
|
@ -109,8 +114,6 @@ impl Client{
|
|||
}*/
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
|
||||
pub struct Client(AccountClient<InterceptedService<Channel, InterceptorFunc>>);
|
||||
|
|
@ -148,4 +151,4 @@ impl Client{
|
|||
Ok(response)
|
||||
}
|
||||
}
|
||||
*/
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -6,18 +6,21 @@ use hmac::Mac;
|
|||
use md5::{Digest, Md5};
|
||||
use rc4::KeyInit;
|
||||
use rc4::cipher::StreamCipherCoreWrapper;
|
||||
use rc4::consts::U16;
|
||||
use rc4::{Rc4, Rc4Core, StreamCipher};
|
||||
use rnex_core::rmc::structures::RmcSerialize;
|
||||
use std::io::{Read, Write};
|
||||
use typenum::U16;
|
||||
use typenum::Unsigned;
|
||||
|
||||
use rnex_core::rmc::structures::Result;
|
||||
|
||||
use rnex_core::PID;
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(feature = "friends")]{
|
||||
pub type SESSION_KEY_LENGTH_TY = U16;
|
||||
} else {
|
||||
use rc4::consts::U32;
|
||||
pub type SESSION_KEY_LENGTH_TY = U32;
|
||||
}
|
||||
}
|
||||
|
|
@ -25,7 +28,7 @@ pub const SESSION_KEY_LENGTH: usize = SESSION_KEY_LENGTH_TY::USIZE;
|
|||
|
||||
type Md5Hmac = Hmac<md5::Md5>;
|
||||
|
||||
pub fn derive_key(pid: u32, password: &[u8]) -> [u8; 16] {
|
||||
pub fn derive_key(pid: PID, password: &[u8]) -> [u8; 16] {
|
||||
let iteration_count = 65000 + pid % 1024;
|
||||
// we do one iteration out here to ensure the key is always 16 bytes
|
||||
|
||||
|
|
@ -125,12 +128,12 @@ impl RmcSerialize for KerberosDateTime {
|
|||
#[repr(C, packed)]
|
||||
pub struct TicketInternalData {
|
||||
pub issued_time: KerberosDateTime,
|
||||
pub pid: u32,
|
||||
pub pid: PID,
|
||||
pub session_key: [u8; SESSION_KEY_LENGTH],
|
||||
}
|
||||
|
||||
impl TicketInternalData {
|
||||
pub(crate) fn new(pid: u32) -> Self {
|
||||
pub(crate) fn new(pid: PID) -> Self {
|
||||
Self {
|
||||
issued_time: KerberosDateTime::now(),
|
||||
pid,
|
||||
|
|
@ -162,7 +165,7 @@ impl TicketInternalData {
|
|||
#[repr(C, packed)]
|
||||
pub struct Ticket {
|
||||
pub session_key: [u8; SESSION_KEY_LENGTH],
|
||||
pub pid: u32,
|
||||
pub pid: PID,
|
||||
}
|
||||
|
||||
impl Ticket {
|
||||
|
|
|
|||
|
|
@ -4,7 +4,10 @@
|
|||
#![allow(async_fn_in_trait)]
|
||||
//#![warn(missing_docs)]
|
||||
|
||||
|
||||
#[cfg(feature = "big_pid")]
|
||||
pub type PID = u64;
|
||||
#[cfg(not(feature = "big_pid"))]
|
||||
pub type PID = u32;
|
||||
|
||||
extern crate self as rnex_core;
|
||||
|
||||
|
|
@ -12,18 +15,18 @@ pub mod prudp;
|
|||
pub mod rmc;
|
||||
//mod protocols;
|
||||
|
||||
pub mod common;
|
||||
pub mod executables;
|
||||
pub mod grpc;
|
||||
pub mod kerberos;
|
||||
pub mod nex;
|
||||
pub mod result;
|
||||
pub mod versions;
|
||||
pub mod common;
|
||||
pub mod reggie;
|
||||
pub mod result;
|
||||
pub mod rnex_proxy_common;
|
||||
pub mod util;
|
||||
pub mod executables;
|
||||
pub mod versions;
|
||||
pub use macros::*;
|
||||
|
||||
pub mod config{
|
||||
pub mod config {
|
||||
pub const FEATURE_HAS_STRUCT_HEADER: bool = cfg!(feature = "rmc_struct_header");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,16 +1,16 @@
|
|||
use macros::RmcSerialize;
|
||||
|
||||
use rnex_core::PID;
|
||||
|
||||
#[derive(RmcSerialize, Clone)]
|
||||
pub struct Account {
|
||||
pub pid: u32,
|
||||
pub pid: PID,
|
||||
pub username: String,
|
||||
pub kerbros_password: Box<[u8]>,
|
||||
}
|
||||
|
||||
impl Account {
|
||||
pub fn new(pid: u32, username: &str, passwd: &str) -> Self {
|
||||
let passwd_data = passwd.as_bytes();
|
||||
|
||||
pub fn new(pid: PID, username: &str, passwd: &str) -> Self {
|
||||
Self {
|
||||
kerbros_password: passwd.as_bytes().into(),
|
||||
username: username.into(),
|
||||
|
|
@ -18,7 +18,7 @@ impl Account {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn new_raw_password(pid: u32, username: &str, passwd: &[u8]) -> Self {
|
||||
pub fn new_raw_password(pid: PID, username: &str, passwd: &[u8]) -> Self {
|
||||
Self {
|
||||
kerbros_password: passwd.into(),
|
||||
username: username.into(),
|
||||
|
|
@ -26,7 +26,7 @@ impl Account {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn get_login_data(&self) -> (u32, &[u8]) {
|
||||
pub fn get_login_data(&self) -> (PID, &[u8]) {
|
||||
(self.pid, &self.kerbros_password)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ use crate::{define_rmc_proto, kerberos};
|
|||
use cfg_if::cfg_if;
|
||||
use log::{info, warn};
|
||||
use macros::rmc_struct;
|
||||
use rnex_core::PID;
|
||||
use rnex_core::kerberos::{KerberosDateTime, Ticket, derive_key};
|
||||
use rnex_core::nex::account::Account;
|
||||
use rnex_core::rmc::protocols::OnlyRemote;
|
||||
|
|
@ -16,7 +17,7 @@ use rnex_core::rmc::structures::connection_data::ConnectionDataOld;
|
|||
use rnex_core::rmc::structures::qresult::QResult;
|
||||
use std::hash::{DefaultHasher, Hasher};
|
||||
use std::net::SocketAddrV4;
|
||||
use std::sync::{Arc, LazyLock, OnceLock};
|
||||
use std::sync::{Arc, LazyLock};
|
||||
|
||||
define_rmc_proto!(
|
||||
proto AuthClientProtocol{
|
||||
|
|
@ -33,8 +34,8 @@ pub struct AuthHandler {
|
|||
}
|
||||
|
||||
pub fn generate_ticket(
|
||||
source_act_login_data: (u32, &[u8]),
|
||||
dest_act_login_data: (u32, &[u8]),
|
||||
source_act_login_data: (PID, &[u8]),
|
||||
dest_act_login_data: (PID, &[u8]),
|
||||
) -> Box<[u8]> {
|
||||
let source_key = derive_key(source_act_login_data.0, source_act_login_data.1);
|
||||
let dest_key = derive_key(dest_act_login_data.0, dest_act_login_data.1);
|
||||
|
|
@ -50,8 +51,28 @@ pub fn generate_ticket(
|
|||
|
||||
encrypted_session_ticket
|
||||
}
|
||||
pub fn generate_ticket_with_string_user_key(
|
||||
source_act: PID,
|
||||
dest_act_login_data: (PID, &[u8]),
|
||||
) -> (String, Box<[u8]>) {
|
||||
let source_key: [u8; 8] = rand::random();
|
||||
let key_string = hex::encode(source_key);
|
||||
let key_data: [u8; 16] = key_string.as_bytes().try_into().unwrap();
|
||||
let dest_key = derive_key(dest_act_login_data.0, dest_act_login_data.1);
|
||||
|
||||
async fn get_login_data_by_pid(pid: u32) -> Option<(u32, Box<[u8]>)> {
|
||||
let internal_data = kerberos::TicketInternalData::new(source_act);
|
||||
|
||||
let encrypted_inner = internal_data.encrypt(dest_key);
|
||||
let encrypted_session_ticket = Ticket {
|
||||
pid: dest_act_login_data.0,
|
||||
session_key: internal_data.session_key,
|
||||
}
|
||||
.encrypt(key_data, &encrypted_inner);
|
||||
|
||||
(key_string, encrypted_session_ticket)
|
||||
}
|
||||
|
||||
async fn get_login_data_by_pid(pid: PID) -> Option<(PID, Box<[u8]>)> {
|
||||
if pid == GUEST_ACCOUNT.pid {
|
||||
let source_login_data = GUEST_ACCOUNT.get_login_data();
|
||||
|
||||
|
|
@ -84,7 +105,7 @@ impl AuthHandler {
|
|||
pub async fn generate_ticket_from_name(
|
||||
&self,
|
||||
name: &str,
|
||||
) -> Result<(u32, Box<[u8]>), ErrorCode> {
|
||||
) -> Result<(PID, Box<[u8]>), ErrorCode> {
|
||||
#[cfg(feature = "guest_login")]
|
||||
{
|
||||
if name == GUEST_ACCOUNT.username {
|
||||
|
|
@ -120,13 +141,39 @@ impl AuthHandler {
|
|||
generate_ticket(source_login_data, destination_login_data),
|
||||
))
|
||||
}
|
||||
|
||||
pub async fn generate_ticket_from_name_string_user_key(
|
||||
&self,
|
||||
name: &str,
|
||||
) -> Result<(PID, String, Box<[u8]>), ErrorCode> {
|
||||
#[cfg(feature = "guest_login")]
|
||||
{
|
||||
if name == GUEST_ACCOUNT.username {
|
||||
let source_login_data = GUEST_ACCOUNT.get_login_data();
|
||||
let destination_login_data = self.destination_server_acct.get_login_data();
|
||||
|
||||
return Ok((
|
||||
source_login_data.0,
|
||||
generate_ticket(source_login_data, destination_login_data),
|
||||
));
|
||||
}
|
||||
}
|
||||
let Ok(pid) = name.parse() else {
|
||||
warn!("unable to connect to parse pid: {}", name);
|
||||
return Err(ErrorCode::Core_InvalidArgument);
|
||||
};
|
||||
let destination_login_data = self.destination_server_acct.get_login_data();
|
||||
|
||||
let data = generate_ticket_with_string_user_key(pid, destination_login_data);
|
||||
Ok((pid, data.0, data.1))
|
||||
}
|
||||
}
|
||||
|
||||
impl Auth for AuthHandler {
|
||||
async fn login(
|
||||
&self,
|
||||
name: String,
|
||||
) -> Result<(QResult, u32, Vec<u8>, ConnectionDataOld, String), ErrorCode> {
|
||||
) -> Result<(QResult, PID, Vec<u8>, ConnectionDataOld, String), ErrorCode> {
|
||||
let (pid, ticket) = self.generate_ticket_from_name(&name).await?;
|
||||
|
||||
let result = QResult::success(Core_Unknown);
|
||||
|
|
@ -157,103 +204,135 @@ impl Auth for AuthHandler {
|
|||
info!("data: {:?}", ret);
|
||||
Ok(ret)
|
||||
}
|
||||
cfg_if! {
|
||||
|
||||
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?;
|
||||
if #[cfg(feature = "nx")]{
|
||||
async fn login_ex(
|
||||
&self,
|
||||
name: String,
|
||||
_extra_data: Any,
|
||||
) -> Result<(QResult, PID, Vec<u8>, ConnectionData, String, String), ErrorCode> {
|
||||
let (pid, key, ticket) = self.generate_ticket_from_name_string_user_key(&name).await?;
|
||||
|
||||
let result = QResult::success(Core_Unknown);
|
||||
let result = QResult::success(Core_Unknown);
|
||||
|
||||
let mut hasher = DefaultHasher::new();
|
||||
let mut hasher = DefaultHasher::new();
|
||||
|
||||
hasher.write(name.as_bytes());
|
||||
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 Ok(addr) = self.control_server.get_url(hasher.finish()).await else {
|
||||
warn!("no secure proxies");
|
||||
return Err(ErrorCode::Core_Exception);
|
||||
};
|
||||
|
||||
let connection_data = ConnectionData {
|
||||
station_url: station_url_from_sock_addr(addr),
|
||||
special_station_url: "".to_string(),
|
||||
//date_time: KerberosDateTime::new(1,1,1,1,1,1),
|
||||
date_time: KerberosDateTime::now(),
|
||||
special_protocols: Vec::new(),
|
||||
};
|
||||
let connection_data = ConnectionData {
|
||||
station_url: station_url_from_sock_addr(addr),
|
||||
special_station_url: "".to_string(),
|
||||
//date_time: KerberosDateTime::new(1,1,1,1,1,1),
|
||||
date_time: KerberosDateTime::now(),
|
||||
special_protocols: Vec::new(),
|
||||
};
|
||||
|
||||
let ret = (
|
||||
result,
|
||||
pid,
|
||||
ticket.into(),
|
||||
connection_data,
|
||||
self.build_name.to_string(),
|
||||
);
|
||||
let ret = (
|
||||
result,
|
||||
pid,
|
||||
ticket.into(),
|
||||
connection_data,
|
||||
self.build_name.to_string(),
|
||||
key
|
||||
);
|
||||
|
||||
info!("data: {:?}", ret);
|
||||
Ok(ret)
|
||||
}
|
||||
info!("data: {:?}", ret);
|
||||
Ok(ret)
|
||||
}
|
||||
async fn request_ticket(
|
||||
&self,
|
||||
source_pid: PID,
|
||||
destination_pid: PID,
|
||||
) -> Result<(QResult, Vec<u8>, String), ErrorCode> {
|
||||
let Some((pid, _)) = get_login_data_by_pid(source_pid).await else {
|
||||
return Err(ErrorCode::Core_Exception);
|
||||
};
|
||||
|
||||
async fn request_ticket(
|
||||
&self,
|
||||
source_pid: u32,
|
||||
destination_pid: u32,
|
||||
) -> Result<(QResult, Vec<u8>), ErrorCode> {
|
||||
let Some((pid, passwd)) = get_login_data_by_pid(source_pid).await else {
|
||||
return Err(ErrorCode::Core_Exception);
|
||||
};
|
||||
let desgination_login_data = if destination_pid == self.destination_server_acct.pid {
|
||||
self.destination_server_acct.get_login_data()
|
||||
} else {
|
||||
return Err(ErrorCode::RendezVous_InvalidOperation);
|
||||
};
|
||||
|
||||
let desgination_login_data = if destination_pid == self.destination_server_acct.pid {
|
||||
self.destination_server_acct.get_login_data()
|
||||
let result = QResult::success(Core_Unknown);
|
||||
|
||||
let ticket = generate_ticket_with_string_user_key(pid, desgination_login_data);
|
||||
|
||||
Ok((result, ticket.1.into(), ticket.0))
|
||||
}
|
||||
} else {
|
||||
return Err(ErrorCode::RendezVous_InvalidOperation);
|
||||
};
|
||||
async fn login_ex(
|
||||
&self,
|
||||
name: String,
|
||||
_extra_data: Any,
|
||||
) -> Result<(QResult, PID, Vec<u8>, ConnectionData, String), ErrorCode> {
|
||||
let (pid, ticket) = self.generate_ticket_from_name(&name).await?;
|
||||
|
||||
let result = QResult::success(Core_Unknown);
|
||||
let result = QResult::success(Core_Unknown);
|
||||
|
||||
let ticket = generate_ticket((pid, &passwd[..]), desgination_login_data);
|
||||
let mut hasher = DefaultHasher::new();
|
||||
|
||||
Ok((result, ticket.into()))
|
||||
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 = ConnectionData {
|
||||
station_url: station_url_from_sock_addr(addr),
|
||||
special_station_url: "".to_string(),
|
||||
//date_time: KerberosDateTime::new(1,1,1,1,1,1),
|
||||
date_time: KerberosDateTime::now(),
|
||||
special_protocols: Vec::new(),
|
||||
};
|
||||
|
||||
let ret = (
|
||||
result,
|
||||
pid,
|
||||
ticket.into(),
|
||||
connection_data,
|
||||
self.build_name.to_string(),
|
||||
);
|
||||
|
||||
info!("data: {:?}", ret);
|
||||
Ok(ret)
|
||||
}
|
||||
async fn request_ticket(
|
||||
&self,
|
||||
source_pid: PID,
|
||||
destination_pid: PID,
|
||||
) -> Result<(QResult, Vec<u8>), ErrorCode> {
|
||||
let Some((pid, passwd)) = get_login_data_by_pid(source_pid).await else {
|
||||
return Err(ErrorCode::Core_Exception);
|
||||
};
|
||||
|
||||
let desgination_login_data = if destination_pid == self.destination_server_acct.pid {
|
||||
self.destination_server_acct.get_login_data()
|
||||
} else {
|
||||
return Err(ErrorCode::RendezVous_InvalidOperation);
|
||||
};
|
||||
|
||||
let result = QResult::success(Core_Unknown);
|
||||
|
||||
let ticket = generate_ticket((pid, &passwd[..]), desgination_login_data);
|
||||
|
||||
Ok((result, ticket.into()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn get_pid(&self, _username: String) -> Result<u32, ErrorCode> {
|
||||
Err(ErrorCode::Core_Exception)
|
||||
}
|
||||
|
||||
async fn get_name(&self, _pid: u32) -> Result<String, ErrorCode> {
|
||||
async fn get_name(&self, _pid: PID) -> Result<String, ErrorCode> {
|
||||
Err(ErrorCode::Core_Exception)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use rnex_core::rmc::response::RMCResponse;
|
||||
use rnex_core::rmc::structures::RmcSerialize;
|
||||
use rnex_core::rmc::structures::connection_data::ConnectionData;
|
||||
use rnex_core::rmc::structures::qresult::QResult;
|
||||
use std::io::Cursor;
|
||||
|
||||
#[test]
|
||||
fn test() {
|
||||
return;
|
||||
let stuff = hex::decode("200100000a0106000000028000000100010051b3995774000000a6321c7f78847c1c5e9fb825eb26bd91841f1a40d92fc694159666119cb13527f1463ac48ad42a63e6613ede67041554b1770978112e6f1f3e177a2bfc75933216dbe38f70133a1eb28e2ae32a4b5c4b0c3e3efd4c02907992e259b257270b57a9dbe7792f4721b07f8fafb9e32d50f2555c616a015c0000004b007072756470733a2f5049443d323b7369643d313b73747265616d3d31303b747970653d323b616464726573733d322e3234332e39352e3131333b706f72743d31303030313b4349443d3100000000000100002c153ba51f00000033006272616e63683a6f726967696e2f70726f6a6563742f7775702d61676d6a206275696c643a335f385f31355f323030345f3000").unwrap();
|
||||
let stuff = RMCResponse::new(&mut Cursor::new(stuff)).unwrap();
|
||||
|
||||
let rnex_core::rmc::response::RMCResponseResult::Success { .. } = stuff.response_result
|
||||
else {
|
||||
panic!()
|
||||
};
|
||||
|
||||
// let stuff = hex::decode("0100010051B399577400000085F1736FCFBE93660275A3FE36FED6C2EFC57222AC99A9219CF54170A415B02DF1463AC48AD42A6307813FDE67041554B177097832ED000F892D9551A09F88E9CB0388DC1BC9527CC7384556A3287B2A349ABBF7E34A5A3EC14C2287CC7F78DA616BC3B03A035347FBD2E9A505C8EF42447CD809015F0000004E007072756470733A2F73747265616D3D31303B747970653D323B616464726573733D3139322E3136382E3137382E3132303B706F72743D31303030313B4349443D313B5049443D323B7369643D310000000000010000CDF53AA51F00000033006272616E63683A6F726967696E2F70726F6A6563742F7775702D61676D6A206275696C643A335F385F31355F323030345F3000").unwrap();
|
||||
let stuff = hex::decode("0100010051b399577400000037d3d4814d2b16dd546c94a75d32637b45f856b5abe73cf26cfaa235c5f2c1cef1463ac48ad42a637d873fde67041554b177097880cfa7e10bb810eaf686bfb0a0cf3d65b1f476ebc046d0855327986f557dca14fbb8594883c186b863f2206f22baa0309dbcc81da2f883cb2cdc12628ec7fced015c0000004b007072756470733a2f5049443d323b7369643d313b73747265616d3d31303b747970653d323b616464726573733d322e3234332e39352e3131333b706f72743d31303030313b4349443d310000000000010000b7f33aa51f00000033006272616e63683a6f726967696e2f70726f6a6563742f7775702d61676d6a206275696c643a335f385f31355f323030345f3000").unwrap();
|
||||
|
||||
let data = <(QResult, u32, Vec<u8>, ConnectionData, String) as RmcSerialize>::deserialize(
|
||||
&mut Cursor::new(stuff),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
println!("data: {:?}", data);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,10 +8,12 @@ use rnex_core::rmc::response::ErrorCode::Core_Exception;
|
|||
use rnex_core::prudp::socket_addr::PRUDPSockAddr;
|
||||
use rnex_core::rmc::response::ErrorCode;
|
||||
|
||||
use rnex_core::PID;
|
||||
|
||||
pub async fn get_station_urls(
|
||||
station_urls: &[StationUrl],
|
||||
addr: PRUDPSockAddr,
|
||||
pid: u32,
|
||||
pid: PID,
|
||||
cid: u32,
|
||||
) -> Result<Vec<StationUrl>, ErrorCode> {
|
||||
let mut public_station: Option<StationUrl> = None;
|
||||
|
|
@ -66,7 +68,7 @@ pub async fn get_station_urls(
|
|||
|
||||
public_station
|
||||
.options
|
||||
.push(Address(*addr.regular_socket_addr.ip()));
|
||||
.push(Address(addr.regular_socket_addr.ip().clone()));
|
||||
public_station
|
||||
.options
|
||||
.push(Port(addr.regular_socket_addr.port()));
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
use std::sync::{Arc, atomic::AtomicU32};
|
||||
use std::time::Duration;
|
||||
|
||||
use log::info;
|
||||
use macros::rmc_struct;
|
||||
|
|
@ -20,21 +19,33 @@ use rnex_core::{
|
|||
},
|
||||
};
|
||||
use std::sync::atomic::Ordering::Relaxed;
|
||||
use tokio::time::sleep;
|
||||
|
||||
use rnex_core::rmc::protocols::friends::{GameKey, MiiV2, PrincipalBasicInfo};
|
||||
|
||||
use rnex_core::PID;
|
||||
|
||||
define_rmc_proto!(
|
||||
proto FriendsUser{
|
||||
Secure,
|
||||
Friends
|
||||
}
|
||||
);
|
||||
define_rmc_proto!(
|
||||
proto FriendsGuest{
|
||||
Secure
|
||||
}
|
||||
);
|
||||
#[rmc_struct(FriendsUser)]
|
||||
pub struct FriendsUser {
|
||||
pub fm: Arc<FriendsManager>,
|
||||
pub addr: PRUDPSockAddr,
|
||||
pub pid: u32,
|
||||
pub pid: PID,
|
||||
}
|
||||
|
||||
#[rmc_struct(FriendsGuest)]
|
||||
pub struct FriendsGuest {
|
||||
pub fm: Arc<FriendsManager>,
|
||||
pub addr: PRUDPSockAddr,
|
||||
}
|
||||
|
||||
pub struct FriendsManager {
|
||||
|
|
@ -50,9 +61,9 @@ impl FriendsManager {
|
|||
impl Friends for FriendsUser {
|
||||
async fn update_and_get_all_information(
|
||||
&self,
|
||||
info: NNAInfo,
|
||||
presence: NintendoPresenceV2,
|
||||
date_time: KerberosDateTime,
|
||||
_info: NNAInfo,
|
||||
_presence: NintendoPresenceV2,
|
||||
_date_time: KerberosDateTime,
|
||||
) -> Result<
|
||||
(
|
||||
PrincipalPreference,
|
||||
|
|
@ -89,10 +100,10 @@ impl Friends for FriendsUser {
|
|||
nna_info: NNAInfo {
|
||||
principal_basic_info: PrincipalBasicInfo {
|
||||
pid: 101,
|
||||
nnid: "dummyaccount".to_string(),
|
||||
nnid: "dummy:3".to_string(),
|
||||
mii: MiiV2{
|
||||
date_time: KerberosDateTime::now(),
|
||||
name: "Dummy Account".to_string(),
|
||||
name: "TheDummy".to_string(),
|
||||
mii_data: hex::decode("030000402bd7c32986a771f2dc6b35e31da15e37ff7c0000391e6f006f006d0069000000000000000000000000004040001065033568641e2013661a611821640f0000290052485000000000000000000000000000000000000000000000e838").unwrap(),
|
||||
unk: 0,
|
||||
unk2: 0,
|
||||
|
|
@ -149,12 +160,37 @@ impl Secure for FriendsUser {
|
|||
async fn register_ex(
|
||||
&self,
|
||||
station_urls: Vec<StationUrl>,
|
||||
data: Any,
|
||||
_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> {
|
||||
async fn replace_url(&self, _target: StationUrl, _dest: StationUrl) -> Result<(), ErrorCode> {
|
||||
Err(ErrorCode::Core_NotImplemented)
|
||||
}
|
||||
}
|
||||
|
||||
impl Secure for FriendsGuest {
|
||||
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, 100, 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)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ 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::rmc::protocols::notifications::notification_types::{
|
||||
HOST_CHANGED, OWNERSHIP_CHANGED,
|
||||
|
|
@ -208,7 +209,7 @@ impl ExtendedMatchmakeSession {
|
|||
.process_notification_event(NotificationEvent {
|
||||
pid_source: initiating_pid,
|
||||
notif_type: 122000,
|
||||
param_1: self.session.gathering.self_gid,
|
||||
param_1: self.session.gathering.self_gid as PID,
|
||||
param_2: other_pid,
|
||||
str_param: "".into(),
|
||||
param_3: 0,
|
||||
|
|
@ -240,7 +241,7 @@ impl ExtendedMatchmakeSession {
|
|||
.process_notification_event(NotificationEvent {
|
||||
pid_source: initiating_pid,
|
||||
notif_type: 3001,
|
||||
param_1: self.session.gathering.self_gid,
|
||||
param_1: self.session.gathering.self_gid as PID,
|
||||
param_2: *pid,
|
||||
str_param: join_msg.clone(),
|
||||
param_3: self.connected_players.len() as _,
|
||||
|
|
@ -261,7 +262,7 @@ impl ExtendedMatchmakeSession {
|
|||
.process_notification_event(NotificationEvent {
|
||||
pid_source: initiating_pid,
|
||||
notif_type: 3001,
|
||||
param_1: self.session.gathering.self_gid,
|
||||
param_1: self.session.gathering.self_gid as PID,
|
||||
param_2: older_pid,
|
||||
str_param: join_msg.clone(),
|
||||
param_3: self.connected_players.len() as _,
|
||||
|
|
@ -393,7 +394,7 @@ impl ExtendedMatchmakeSession {
|
|||
Ok(true)
|
||||
}
|
||||
|
||||
pub async fn migrate_ownership(&mut self, initiator_pid: u32) -> Result<(), ErrorCode> {
|
||||
pub async fn migrate_ownership(&mut self, initiator_pid: PID) -> Result<(), ErrorCode> {
|
||||
let players: Vec<_> = self
|
||||
.connected_players
|
||||
.iter()
|
||||
|
|
@ -414,7 +415,7 @@ impl ExtendedMatchmakeSession {
|
|||
self.broadcast_notification(&NotificationEvent {
|
||||
pid_source: initiator_pid,
|
||||
notif_type: OWNERSHIP_CHANGED,
|
||||
param_1: self.session.gathering.self_gid,
|
||||
param_1: self.session.gathering.self_gid as PID,
|
||||
param_2: new_owner.pid,
|
||||
..Default::default()
|
||||
})
|
||||
|
|
@ -423,7 +424,7 @@ impl ExtendedMatchmakeSession {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn migrate_host(&mut self, initiator_pid: u32) -> Result<(), ErrorCode> {
|
||||
pub async fn migrate_host(&mut self, initiator_pid: PID) -> Result<(), ErrorCode> {
|
||||
// let players: Vec<_> = self.connected_players.iter().filter_map(|p| p.upgrade()).collect();
|
||||
|
||||
self.session.gathering.host_pid = self.session.gathering.owner_pid;
|
||||
|
|
@ -431,7 +432,7 @@ impl ExtendedMatchmakeSession {
|
|||
self.broadcast_notification(&NotificationEvent {
|
||||
pid_source: initiator_pid,
|
||||
notif_type: HOST_CHANGED,
|
||||
param_1: self.session.gathering.self_gid,
|
||||
param_1: self.session.gathering.self_gid as PID,
|
||||
..Default::default()
|
||||
})
|
||||
.await;
|
||||
|
|
@ -441,7 +442,7 @@ impl ExtendedMatchmakeSession {
|
|||
|
||||
pub async fn remove_player_from_session(
|
||||
&mut self,
|
||||
pid: u32,
|
||||
pid: PID,
|
||||
message: &str,
|
||||
) -> Result<(), ErrorCode> {
|
||||
self.connected_players
|
||||
|
|
@ -468,7 +469,7 @@ impl ExtendedMatchmakeSession {
|
|||
.process_notification_event(NotificationEvent {
|
||||
notif_type: 3008,
|
||||
pid_source: pid,
|
||||
param_1: self.session.gathering.self_gid,
|
||||
param_1: self.session.gathering.self_gid as PID,
|
||||
param_2: pid,
|
||||
str_param: message.to_owned(),
|
||||
..Default::default()
|
||||
|
|
|
|||
|
|
@ -9,9 +9,10 @@ use crate::rmc::protocols::nat_traversal::{
|
|||
NatTraversal, RawNatTraversal, RawNatTraversalInfo, RemoteNatTraversal,
|
||||
RemoteNatTraversalConsole,
|
||||
};
|
||||
use rnex_core::PID;
|
||||
use rnex_core::prudp::station_url::StationUrl;
|
||||
use rnex_core::prudp::station_url::UrlOptions::{
|
||||
Address, NatFiltering, NatMapping, NatType, Port, PrincipalID, RVConnectionID,
|
||||
Address, NatFiltering, NatMapping, Port, RVConnectionID,
|
||||
};
|
||||
use rnex_core::rmc::protocols::matchmake_ext::{
|
||||
MatchmakeExt, RawMatchmakeExt, RawMatchmakeExtInfo, RemoteMatchmakeExt,
|
||||
|
|
@ -31,10 +32,7 @@ use crate::rmc::protocols::notifications::{NotificationEvent, RemoteNotification
|
|||
use log::info;
|
||||
use macros::rmc_struct;
|
||||
use rnex_core::prudp::socket_addr::PRUDPSockAddr;
|
||||
use rnex_core::prudp::station_url::nat_types::PUBLIC;
|
||||
use rnex_core::rmc::response::ErrorCode::{
|
||||
Core_Exception, Core_InvalidArgument, RendezVous_AccountExpired,
|
||||
};
|
||||
use rnex_core::rmc::response::ErrorCode::{Core_InvalidArgument, RendezVous_AccountExpired};
|
||||
use rnex_core::rmc::structures::qresult::QResult;
|
||||
use std::sync::{Arc, Weak};
|
||||
use tokio::sync::{Mutex, RwLock};
|
||||
|
|
@ -52,7 +50,7 @@ define_rmc_proto!(
|
|||
|
||||
#[rmc_struct(UserProtocol)]
|
||||
pub struct User {
|
||||
pub pid: u32,
|
||||
pub pid: PID,
|
||||
pub ip: PRUDPSockAddr,
|
||||
pub this: Weak<User>,
|
||||
pub remote: RemoteConsole,
|
||||
|
|
@ -423,7 +421,7 @@ impl Matchmake for User {
|
|||
.process_notification_event(NotificationEvent {
|
||||
notif_type: 110000,
|
||||
pid_source: self.pid,
|
||||
param_1: gid,
|
||||
param_1: gid as PID,
|
||||
param_2: self.pid,
|
||||
param_3: 0,
|
||||
str_param: "".to_string(),
|
||||
|
|
@ -444,7 +442,7 @@ impl Matchmake for User {
|
|||
.process_notification_event(NotificationEvent {
|
||||
notif_type: 4000,
|
||||
pid_source: self.pid,
|
||||
param_1: gid,
|
||||
param_1: gid as PID,
|
||||
param_2: self.pid,
|
||||
param_3: 0,
|
||||
str_param: "".to_string(),
|
||||
|
|
@ -459,7 +457,7 @@ impl Matchmake for User {
|
|||
async fn migrate_gathering_ownership(
|
||||
&self,
|
||||
gid: u32,
|
||||
candidates: Vec<u32>,
|
||||
candidates: Vec<PID>,
|
||||
_participants_only: bool,
|
||||
) -> Result<(), ErrorCode> {
|
||||
let session = self.matchmake_manager.get_session(gid).await?;
|
||||
|
|
@ -479,8 +477,8 @@ impl Matchmake for User {
|
|||
.process_notification_event(NotificationEvent {
|
||||
notif_type: 4000,
|
||||
pid_source: self.pid,
|
||||
param_1: gid,
|
||||
param_2: *candidate,
|
||||
param_1: gid as PID,
|
||||
param_2: *candidate as PID,
|
||||
param_3: 0,
|
||||
str_param: "".to_string(),
|
||||
})
|
||||
|
|
|
|||
|
|
@ -3,19 +3,19 @@ use macros::RmcSerialize;
|
|||
use md5::digest::Mac;
|
||||
use rnex_core::prudp::virtual_port::VirtualPort;
|
||||
use std::io::Write;
|
||||
use std::net::SocketAddrV4;
|
||||
use std::net::{IpAddr, SocketAddr};
|
||||
|
||||
type Md5Hmac = Hmac<md5::Md5>;
|
||||
|
||||
#[derive(Eq, PartialEq, Hash, Debug, Copy, Clone, Ord, PartialOrd, RmcSerialize)]
|
||||
#[rmc_struct(0)]
|
||||
pub struct PRUDPSockAddr {
|
||||
pub regular_socket_addr: SocketAddrV4,
|
||||
pub regular_socket_addr: SocketAddr,
|
||||
pub virtual_port: VirtualPort,
|
||||
}
|
||||
|
||||
impl PRUDPSockAddr {
|
||||
pub fn new(regular_socket_addr: SocketAddrV4, virtual_port: VirtualPort) -> Self {
|
||||
pub fn new(regular_socket_addr: SocketAddr, virtual_port: VirtualPort) -> Self {
|
||||
Self {
|
||||
regular_socket_addr,
|
||||
virtual_port,
|
||||
|
|
@ -23,9 +23,12 @@ impl PRUDPSockAddr {
|
|||
}
|
||||
|
||||
pub fn calculate_connection_signature(&self) -> [u8; 16] {
|
||||
let mut hmac = Md5Hmac::new_from_slice(&[0; 16]).expect("fuck");
|
||||
let mut hmac = Md5Hmac::new_from_slice(&[0; 16]).expect("?");
|
||||
|
||||
let data = self.regular_socket_addr.ip().octets().to_vec();
|
||||
let data = match self.regular_socket_addr.ip() {
|
||||
IpAddr::V4(v) => v.octets().to_vec(),
|
||||
IpAddr::V6(v) => v.octets().to_vec(),
|
||||
};
|
||||
//data.extend_from_slice(&self.regular_socket_addr.port().to_be_bytes());
|
||||
|
||||
hmac.write_all(&data)
|
||||
|
|
|
|||
|
|
@ -1,32 +1,35 @@
|
|||
use std::net::Ipv4Addr;
|
||||
use crate::prudp::station_url::Type::{PRUDP, PRUDPS, UDP};
|
||||
use crate::prudp::station_url::UrlOptions::{
|
||||
Address, ConnectionID, NatFiltering, NatMapping, NatType, PID, PMP, Platform, Port,
|
||||
PrincipalID, RVConnectionID, StreamID, StreamType, UPNP,
|
||||
};
|
||||
use crate::rmc::structures::Error::StationUrlInvalid;
|
||||
use crate::rmc::structures::RmcSerialize;
|
||||
use crate::rmc::structures::helpers::DummyFormatWriter;
|
||||
use log::error;
|
||||
use std::fmt::{Debug, Display, Formatter, Write};
|
||||
use std::io::Read;
|
||||
use crate::prudp::station_url::Type::{PRUDP, PRUDPS, UDP};
|
||||
use crate::prudp::station_url::UrlOptions::{Address, ConnectionID, NatFiltering, NatMapping, NatType, Platform, PMP, Port, PrincipalID, RVConnectionID, StreamID, StreamType, UPNP, PID};
|
||||
use crate::rmc::structures::Error::StationUrlInvalid;
|
||||
use crate::rmc::structures::helpers::DummyFormatWriter;
|
||||
use crate::rmc::structures::RmcSerialize;
|
||||
use std::net::IpAddr;
|
||||
#[derive(Clone, Copy, PartialEq, Eq)]
|
||||
pub enum Type{
|
||||
pub enum Type {
|
||||
UDP,
|
||||
PRUDP,
|
||||
PRUDPS
|
||||
PRUDPS,
|
||||
}
|
||||
|
||||
pub mod nat_types{
|
||||
pub mod nat_types {
|
||||
pub const BEHIND_NAT: u8 = 1;
|
||||
pub const PUBLIC: u8 = 2;
|
||||
}
|
||||
|
||||
#[derive(Clone, Eq, PartialEq)]
|
||||
pub enum UrlOptions {
|
||||
Address(Ipv4Addr),
|
||||
Address(IpAddr),
|
||||
Port(u16),
|
||||
StreamType(u8),
|
||||
StreamID(u8),
|
||||
ConnectionID(u8),
|
||||
PrincipalID(u32),
|
||||
PrincipalID(rnex_core::PID),
|
||||
NatType(u8),
|
||||
NatMapping(u8),
|
||||
NatFiltering(u8),
|
||||
|
|
@ -35,82 +38,52 @@ pub enum UrlOptions {
|
|||
Platform(u8),
|
||||
PMP(u8),
|
||||
PID(u32),
|
||||
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq)]
|
||||
pub struct StationUrl{
|
||||
pub struct StationUrl {
|
||||
pub url_type: Type,
|
||||
pub options: Vec<UrlOptions>
|
||||
pub options: Vec<UrlOptions>,
|
||||
}
|
||||
|
||||
impl StationUrl{
|
||||
pub fn read_options(options: &str) -> Option<Vec<UrlOptions>>{
|
||||
impl StationUrl {
|
||||
pub fn read_options(options: &str) -> Option<Vec<UrlOptions>> {
|
||||
let mut options_out = Vec::new();
|
||||
|
||||
for option in options.split(';'){
|
||||
if option == "" { continue; }
|
||||
for option in options.split(';') {
|
||||
if option == "" {
|
||||
continue;
|
||||
}
|
||||
let mut option_parts = option.split('=');
|
||||
let option_name= option_parts.next()?.to_ascii_lowercase();
|
||||
let option_name = option_parts.next()?.to_ascii_lowercase();
|
||||
let option_value = option_parts.next()?;
|
||||
|
||||
match option_name.as_ref(){
|
||||
"address" => {
|
||||
options_out.push(Address(option_value.parse().ok()?))
|
||||
},
|
||||
"port" => {
|
||||
options_out.push(Port(option_value.parse().ok()?))
|
||||
}
|
||||
"natf" => {
|
||||
options_out.push(NatFiltering(option_value.parse().ok()?))
|
||||
}
|
||||
"natm" => {
|
||||
options_out.push(NatMapping(option_value.parse().ok()?))
|
||||
}
|
||||
"sid" => {
|
||||
options_out.push(StreamID(option_value.parse().ok()?))
|
||||
}
|
||||
"upnp" => {
|
||||
options_out.push(UPNP(option_value.parse().ok()?))
|
||||
}
|
||||
"type" => {
|
||||
options_out.push(NatType(option_value.parse().ok()?))
|
||||
}
|
||||
"stream" => {
|
||||
options_out.push(StreamType(option_value.parse().ok()?))
|
||||
}
|
||||
"RVCID" => {
|
||||
options_out.push(RVConnectionID(option_value.parse().ok()?))
|
||||
}
|
||||
"rvcid" => {
|
||||
options_out.push(RVConnectionID(option_value.parse().ok()?))
|
||||
}
|
||||
"pl" => {
|
||||
options_out.push(Platform(option_value.parse().ok()?))
|
||||
}
|
||||
"pmp" => {
|
||||
options_out.push(PMP(option_value.parse().ok()?))
|
||||
},
|
||||
"pid" => {
|
||||
options_out.push(PID(option_value.parse().ok()?))
|
||||
},
|
||||
"PID" => {
|
||||
options_out.push(PID(option_value.parse().ok()?))
|
||||
},
|
||||
match option_name.as_ref() {
|
||||
"address" => options_out.push(Address(option_value.parse().ok()?)),
|
||||
"port" => options_out.push(Port(option_value.parse().ok()?)),
|
||||
"natf" => options_out.push(NatFiltering(option_value.parse().ok()?)),
|
||||
"natm" => options_out.push(NatMapping(option_value.parse().ok()?)),
|
||||
"sid" => options_out.push(StreamID(option_value.parse().ok()?)),
|
||||
"upnp" => options_out.push(UPNP(option_value.parse().ok()?)),
|
||||
"type" => options_out.push(NatType(option_value.parse().ok()?)),
|
||||
"stream" => options_out.push(StreamType(option_value.parse().ok()?)),
|
||||
"RVCID" => options_out.push(RVConnectionID(option_value.parse().ok()?)),
|
||||
"rvcid" => options_out.push(RVConnectionID(option_value.parse().ok()?)),
|
||||
"pl" => options_out.push(Platform(option_value.parse().ok()?)),
|
||||
"pmp" => options_out.push(PMP(option_value.parse().ok()?)),
|
||||
"pid" => options_out.push(PID(option_value.parse().ok()?)),
|
||||
"PID" => options_out.push(PID(option_value.parse().ok()?)),
|
||||
_ => {
|
||||
error!("unimplemented option type, skipping: {}", option_name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
Some(options_out)
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&str> for StationUrl{
|
||||
impl TryFrom<&str> for StationUrl {
|
||||
type Error = ();
|
||||
|
||||
fn try_from(value: &str) -> Result<Self, ()> {
|
||||
|
|
@ -118,35 +91,30 @@ impl TryFrom<&str> for StationUrl{
|
|||
|
||||
let options = &options[2..];
|
||||
|
||||
let url_type = match url_type{
|
||||
let url_type = match url_type {
|
||||
"udp" => UDP,
|
||||
"prudp" => PRUDP,
|
||||
"prudps" => PRUDPS,
|
||||
_ => return Err(())
|
||||
_ => return Err(()),
|
||||
};
|
||||
|
||||
let options = Self::read_options(options).ok_or(())?;
|
||||
|
||||
Ok(
|
||||
Self{
|
||||
url_type,
|
||||
options
|
||||
}
|
||||
)
|
||||
Ok(Self { url_type, options })
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for StationUrl{
|
||||
impl Display for StationUrl {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
let url_type_str = match self.url_type{
|
||||
let url_type_str = match self.url_type {
|
||||
UDP => "udp:/",
|
||||
PRUDP => "prudp:/",
|
||||
PRUDPS => "prudps:/"
|
||||
PRUDPS => "prudps:/",
|
||||
};
|
||||
write!(f, "{}",url_type_str)?;
|
||||
write!(f, "{}", url_type_str)?;
|
||||
|
||||
for option in &self.options{
|
||||
match option{
|
||||
for option in &self.options {
|
||||
match option {
|
||||
Address(v) => write!(f, "address={}", v)?,
|
||||
Port(v) => write!(f, "port={}", v)?,
|
||||
StreamType(v) => write!(f, "stream={}", v)?,
|
||||
|
|
@ -168,15 +136,15 @@ impl Display for StationUrl{
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a> Into<String> for &'a StationUrl{
|
||||
impl<'a> Into<String> for &'a StationUrl {
|
||||
fn into(self) -> String {
|
||||
let url = self.to_string();
|
||||
|
||||
url[0..url.len()-1].into()
|
||||
|
||||
url[0..url.len() - 1].into()
|
||||
}
|
||||
}
|
||||
|
||||
impl RmcSerialize for StationUrl{
|
||||
impl RmcSerialize for StationUrl {
|
||||
fn deserialize(reader: &mut impl Read) -> crate::rmc::structures::Result<Self> {
|
||||
let str = String::deserialize(reader)?;
|
||||
|
||||
|
|
@ -197,9 +165,9 @@ impl RmcSerialize for StationUrl{
|
|||
}
|
||||
}
|
||||
|
||||
impl Debug for StationUrl{
|
||||
impl Debug for StationUrl {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
let str: String = self.into();
|
||||
f.write_str(&str)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ use std::io::Cursor;
|
|||
|
||||
use log::{error, info};
|
||||
use rc4::{KeyInit, Rc4, Rc4Core, StreamCipher, cipher::StreamCipherCoreWrapper};
|
||||
use typenum::{U16, U32};
|
||||
use typenum::U16;
|
||||
use v_byte_helpers::{IS_BIG_ENDIAN, ReadExtensions};
|
||||
|
||||
use crate::{
|
||||
|
|
@ -10,19 +10,17 @@ use crate::{
|
|||
nex::account::Account,
|
||||
rmc::structures::RmcSerialize,
|
||||
};
|
||||
use rnex_core::PID;
|
||||
|
||||
pub fn read_secure_connection_data(
|
||||
data: &[u8],
|
||||
act: &Account,
|
||||
) -> Option<([u8; SESSION_KEY_LENGTH], u32, u32)> {
|
||||
) -> Option<([u8; SESSION_KEY_LENGTH], PID, u32)> {
|
||||
let mut cursor = Cursor::new(data);
|
||||
|
||||
let mut ticket_data: Vec<u8> = Vec::deserialize(&mut cursor).ok()?;
|
||||
let mut request_data: Vec<u8> = Vec::deserialize(&mut cursor).ok()?;
|
||||
info!(
|
||||
"done
|
||||
request data"
|
||||
);
|
||||
info!("done request data {}", SESSION_KEY_LENGTH);
|
||||
|
||||
let ticket_data_size = ticket_data.len();
|
||||
|
||||
|
|
@ -62,7 +60,7 @@ pub fn read_secure_connection_data(
|
|||
|
||||
let mut reqest_data_cursor = Cursor::new(request_data);
|
||||
|
||||
let pid: u32 = reqest_data_cursor.read_struct(IS_BIG_ENDIAN).ok()?;
|
||||
let pid: PID = reqest_data_cursor.read_struct(IS_BIG_ENDIAN).ok()?;
|
||||
|
||||
if pid != ticket_source_pid {
|
||||
let ticket_created_on = issued_time.to_regular_time();
|
||||
|
|
|
|||
4
rnex-core/src/rmc/protocols/account_management.rs
Normal file
4
rnex-core/src/rmc/protocols/account_management.rs
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
use macros::rmc_proto;
|
||||
|
||||
#[rmc_proto(25)]
|
||||
pub trait AccountManagement {}
|
||||
|
|
@ -1,9 +1,21 @@
|
|||
use crate::rmc::structures::connection_data::{ConnectionData, ConnectionDataOld};
|
||||
use cfg_if::cfg_if;
|
||||
use macros::{method_id, rmc_proto};
|
||||
use rnex_core::PID;
|
||||
use rnex_core::rmc::response::ErrorCode;
|
||||
use rnex_core::rmc::structures::any::Any;
|
||||
use rnex_core::rmc::structures::qresult::QResult;
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(feature = "nx")]{
|
||||
type LOGIN_EX_RET = (QResult, PID, Vec<u8>, ConnectionData, String, String);
|
||||
type REQUEST_TICKET_RET = (QResult, Vec<u8>, String);
|
||||
} else {
|
||||
type LOGIN_EX_RET = (QResult, PID, Vec<u8>, ConnectionData, String);
|
||||
type REQUEST_TICKET_RET = (QResult, Vec<u8>);
|
||||
}
|
||||
}
|
||||
|
||||
/// This is the representation for `Ticket Granting`(for details see the
|
||||
/// [kinnay wiki entry](https://github.com/kinnay/NintendoClients/wiki/Authentication-Protocol))
|
||||
#[rmc_proto(10)]
|
||||
|
|
@ -14,25 +26,22 @@ pub trait Auth {
|
|||
async fn login(
|
||||
&self,
|
||||
name: String,
|
||||
) -> Result<(QResult, u32, Vec<u8>, ConnectionDataOld, String), ErrorCode>;
|
||||
) -> Result<(QResult, PID, Vec<u8>, ConnectionDataOld, String), ErrorCode>;
|
||||
|
||||
/// representation of the `LoginEx` method(for details see the
|
||||
/// [kinnay wiki entry](https://github.com/kinnay/NintendoClients/wiki/Authentication-Protocol))
|
||||
#[method_id(2)]
|
||||
async fn login_ex(
|
||||
&self,
|
||||
name: String,
|
||||
extra_data: Any,
|
||||
) -> Result<(QResult, u32, Vec<u8>, ConnectionData, String), ErrorCode>;
|
||||
async fn login_ex(&self, name: String, extra_data: Any) -> Result<LOGIN_EX_RET, ErrorCode>;
|
||||
|
||||
/// representation of the `RequestTicket` method(for details see the
|
||||
/// [kinnay wiki entry](https://github.com/kinnay/NintendoClients/wiki/Authentication-Protocol))
|
||||
#[method_id(3)]
|
||||
async fn request_ticket(
|
||||
&self,
|
||||
source_pid: u32,
|
||||
destination_pid: u32,
|
||||
) -> Result<(QResult, Vec<u8>), ErrorCode>;
|
||||
source_pid: PID,
|
||||
destination_pid: PID,
|
||||
) -> Result<REQUEST_TICKET_RET, ErrorCode>;
|
||||
|
||||
/// representation of the `RequestTicket` method(for details see the
|
||||
/// [kinnay wiki entry](https://github.com/kinnay/NintendoClients/wiki/Authentication-Protocol))
|
||||
|
||||
/// representation of the `GetPID` method(for details see the
|
||||
/// [kinnay wiki entry](https://github.com/kinnay/NintendoClients/wiki/Authentication-Protocol))
|
||||
|
|
@ -42,7 +51,7 @@ pub trait Auth {
|
|||
/// representation of the `LoginWithContext` method(for details see the
|
||||
/// [kinnay wiki entry](https://github.com/kinnay/NintendoClients/wiki/Authentication-Protocol))
|
||||
#[method_id(5)]
|
||||
async fn get_name(&self, pid: u32) -> Result<String, ErrorCode>;
|
||||
async fn get_name(&self, pid: PID) -> Result<String, ErrorCode>;
|
||||
|
||||
// `LoginWithContext` is left out here because we don't need it right now and versioning still
|
||||
// needs to be figured out
|
||||
|
|
|
|||
|
|
@ -2,8 +2,10 @@ use macros::{method_id, rmc_proto};
|
|||
use rnex_core::prudp::station_url::StationUrl;
|
||||
use rnex_core::rmc::response::ErrorCode;
|
||||
|
||||
use rnex_core::PID;
|
||||
|
||||
#[rmc_proto(21)]
|
||||
pub trait Matchmake{
|
||||
pub trait Matchmake {
|
||||
#[method_id(2)]
|
||||
async fn unregister_gathering(&self, gid: u32) -> Result<bool, ErrorCode>;
|
||||
#[method_id(41)]
|
||||
|
|
@ -11,5 +13,10 @@ pub trait Matchmake{
|
|||
#[method_id(42)]
|
||||
async fn update_session_host(&self, gid: u32, change_owner: bool) -> Result<(), ErrorCode>;
|
||||
#[method_id(44)]
|
||||
async fn migrate_gathering_ownership(&self, gid: u32, candidates: Vec<u32>, participants_only: bool) -> Result<(), ErrorCode>;
|
||||
}
|
||||
async fn migrate_gathering_ownership(
|
||||
&self,
|
||||
gid: u32,
|
||||
candidates: Vec<PID>,
|
||||
participants_only: bool,
|
||||
) -> Result<(), ErrorCode>;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
#![allow(async_fn_in_trait)]
|
||||
|
||||
pub mod account_management;
|
||||
pub mod auth;
|
||||
pub mod friends;
|
||||
pub mod matchmake;
|
||||
|
|
|
|||
|
|
@ -1,19 +1,21 @@
|
|||
use macros::{method_id, rmc_proto, rmc_struct, RmcSerialize};
|
||||
use macros::{RmcSerialize, method_id, rmc_proto, rmc_struct};
|
||||
|
||||
pub mod notification_types{
|
||||
use rnex_core::PID;
|
||||
|
||||
pub mod notification_types {
|
||||
pub const OWNERSHIP_CHANGED: u32 = 4000;
|
||||
pub const HOST_CHANGED: u32 = 110000;
|
||||
}
|
||||
|
||||
#[derive(RmcSerialize, Debug, Default, Clone)]
|
||||
#[rmc_struct(0)]
|
||||
pub struct NotificationEvent{
|
||||
pub pid_source: u32,
|
||||
pub struct NotificationEvent {
|
||||
pub pid_source: PID,
|
||||
pub notif_type: u32,
|
||||
pub param_1: u32,
|
||||
pub param_2: u32,
|
||||
pub param_1: PID,
|
||||
pub param_2: PID,
|
||||
pub str_param: String,
|
||||
pub param_3: u32,
|
||||
pub param_3: PID,
|
||||
}
|
||||
|
||||
#[rmc_proto(14, NoReturn)]
|
||||
|
|
@ -21,4 +23,3 @@ pub trait Notification {
|
|||
#[method_id(1)]
|
||||
async fn process_notification_event(&self, event: NotificationEvent);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ pub trait Secure {
|
|||
&self,
|
||||
station_urls: Vec<StationUrl>,
|
||||
) -> Result<(QResult, u32, StationUrl), ErrorCode>;
|
||||
|
||||
#[method_id(4)]
|
||||
async fn register_ex(
|
||||
&self,
|
||||
|
|
|
|||
|
|
@ -1,14 +1,16 @@
|
|||
use macros::RmcSerialize;
|
||||
use rnex_core::kerberos::KerberosDateTime;
|
||||
use rnex_core::rmc::structures::variant::Variant;
|
||||
use macros::RmcSerialize;
|
||||
|
||||
use rnex_core::PID;
|
||||
|
||||
// rmc structure
|
||||
#[derive(RmcSerialize, Debug, Clone, Default)]
|
||||
#[rmc_struct(0)]
|
||||
pub struct Gathering {
|
||||
pub self_gid: u32,
|
||||
pub owner_pid: u32,
|
||||
pub host_pid: u32,
|
||||
pub owner_pid: PID,
|
||||
pub host_pid: PID,
|
||||
pub minimum_participants: u16,
|
||||
pub maximum_participants: u16,
|
||||
pub participant_policy: u32,
|
||||
|
|
@ -73,7 +75,7 @@ pub struct MatchmakeSessionSearchCriteria {
|
|||
#[rmc_struct(0)]
|
||||
pub struct AutoMatchmakeParam {
|
||||
pub matchmake_session: MatchmakeSession,
|
||||
pub additional_participants: Vec<u32>,
|
||||
pub additional_participants: Vec<PID>,
|
||||
pub gid_for_participation_check: u32,
|
||||
pub auto_matchmake_option: u32,
|
||||
pub join_message: String,
|
||||
|
|
@ -86,7 +88,7 @@ pub struct AutoMatchmakeParam {
|
|||
#[rmc_struct(0)]
|
||||
pub struct CreateMatchmakeSessionParam {
|
||||
pub matchmake_session: MatchmakeSession,
|
||||
pub additional_participants: Vec<u32>,
|
||||
pub additional_participants: Vec<PID>,
|
||||
pub gid_for_participation_check: u32,
|
||||
pub create_matchmake_session_option: u32,
|
||||
pub join_message: String,
|
||||
|
|
@ -103,7 +105,7 @@ pub struct MatchmakeBlockListParam {
|
|||
#[rmc_struct(0)]
|
||||
pub struct JoinMatchmakeSessionParam {
|
||||
pub gid: u32,
|
||||
pub additional_participants: Vec<u32>,
|
||||
pub additional_participants: Vec<PID>,
|
||||
pub gid_for_participation_check: u32,
|
||||
pub join_matchmake_session_open: u32,
|
||||
pub join_matchmake_session_behavior: u8,
|
||||
|
|
|
|||
|
|
@ -1,9 +1,37 @@
|
|||
use std::io::{Read, Write};
|
||||
use std::net::{Ipv4Addr, SocketAddrV4};
|
||||
use crate::rmc::structures::{Error, Result, RmcSerialize};
|
||||
use rnex_core::prudp::virtual_port::VirtualPort;
|
||||
use crate::rmc::structures::RmcSerialize;
|
||||
use std::io::{Read, Write};
|
||||
use std::net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6};
|
||||
use v_byte_helpers::{IS_BIG_ENDIAN, ReadExtensions};
|
||||
|
||||
impl RmcSerialize for SocketAddrV4{
|
||||
impl RmcSerialize for SocketAddr {
|
||||
fn deserialize(reader: &mut impl std::io::Read) -> Result<Self>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
let val: u8 = reader.read_struct(IS_BIG_ENDIAN)?;
|
||||
match val {
|
||||
4 => Ok(SocketAddr::V4(SocketAddrV4::deserialize(reader)?)),
|
||||
6 => Ok(SocketAddr::V6(SocketAddrV6::deserialize(reader)?)),
|
||||
v => Err(Error::UnexpectedValue(v as u64)),
|
||||
}
|
||||
}
|
||||
fn serialize(&self, writer: &mut impl Write) -> Result<()> {
|
||||
match self {
|
||||
SocketAddr::V4(v) => {
|
||||
writer.write_all(&[4])?;
|
||||
v.serialize(writer)?;
|
||||
}
|
||||
SocketAddr::V6(v) => {
|
||||
writer.write_all(&[6])?;
|
||||
v.serialize(writer)?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl RmcSerialize for SocketAddrV4 {
|
||||
fn serialize(&self, writer: &mut impl Write) -> crate::rmc::structures::Result<()> {
|
||||
self.ip().to_bits().serialize(writer)?;
|
||||
self.port().serialize(writer)?;
|
||||
|
|
@ -21,9 +49,35 @@ impl RmcSerialize for SocketAddrV4{
|
|||
Ok(6)
|
||||
}
|
||||
}
|
||||
impl RmcSerialize for SocketAddrV6 {
|
||||
fn serialize(&self, writer: &mut impl Write) -> crate::rmc::structures::Result<()> {
|
||||
self.ip().to_bits().serialize(writer)?;
|
||||
self.port().serialize(writer)?;
|
||||
self.flowinfo().serialize(writer)?;
|
||||
self.scope_id().serialize(writer)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
impl RmcSerialize for VirtualPort{
|
||||
fn deserialize(reader: &mut impl Read) -> crate::rmc::structures::Result<Self> {
|
||||
let ip = u128::deserialize(reader)?;
|
||||
let port = u16::deserialize(reader)?;
|
||||
let flowinfo = u32::deserialize(reader)?;
|
||||
let scope_id = u32::deserialize(reader)?;
|
||||
|
||||
Ok(SocketAddrV6::new(
|
||||
Ipv6Addr::from_bits(ip),
|
||||
port,
|
||||
flowinfo,
|
||||
scope_id,
|
||||
))
|
||||
}
|
||||
fn serialize_write_size(&self) -> crate::rmc::structures::Result<u32> {
|
||||
Ok(6)
|
||||
}
|
||||
}
|
||||
|
||||
impl RmcSerialize for VirtualPort {
|
||||
fn serialize(&self, writer: &mut impl Write) -> crate::rmc::structures::Result<()> {
|
||||
self.0.serialize(writer)?;
|
||||
|
||||
|
|
@ -36,4 +90,4 @@ impl RmcSerialize for VirtualPort{
|
|||
fn serialize_write_size(&self) -> crate::rmc::structures::Result<u32> {
|
||||
Ok(1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use crate::rmc::structures::RmcSerialize;
|
||||
use bytemuck::bytes_of;
|
||||
use bytemuck::{bytes_of, bytes_of_mut};
|
||||
use std::io::{Read, Write};
|
||||
use v_byte_helpers::{IS_BIG_ENDIAN, ReadExtensions};
|
||||
|
||||
|
|
@ -110,6 +110,23 @@ impl RmcSerialize for u64 {
|
|||
}
|
||||
}
|
||||
|
||||
impl RmcSerialize for u128 {
|
||||
#[inline(always)]
|
||||
fn serialize(&self, writer: &mut impl Write) -> crate::rmc::structures::Result<()> {
|
||||
Ok(writer.write_all(bytes_of(self))?)
|
||||
}
|
||||
#[inline(always)]
|
||||
fn deserialize(reader: &mut impl Read) -> crate::rmc::structures::Result<Self> {
|
||||
let mut data = 0u128;
|
||||
reader.read_exact(&mut bytes_of_mut(&mut data))?;
|
||||
Ok(data)
|
||||
}
|
||||
#[inline(always)]
|
||||
fn serialize_write_size(&self) -> crate::rmc::structures::Result<u32> {
|
||||
Ok(8)
|
||||
}
|
||||
}
|
||||
|
||||
impl RmcSerialize for i64 {
|
||||
#[inline(always)]
|
||||
fn serialize(&self, writer: &mut impl Write) -> crate::rmc::structures::Result<()> {
|
||||
|
|
|
|||
|
|
@ -20,55 +20,3 @@ struct UploadCompetitionData {
|
|||
struct UserData {
|
||||
name: [u16; 0x10],
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use crate::rmc::structures::ranking::{UploadCompetitionData, UserData};
|
||||
use bytemuck::from_bytes;
|
||||
use rnex_core::rmc::structures::RmcSerialize;
|
||||
use std::io::Cursor;
|
||||
|
||||
#[test]
|
||||
fn test() {
|
||||
return;
|
||||
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())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,9 @@
|
|||
use crate::{PID, prudp::socket_addr::PRUDPSockAddr};
|
||||
use macros::RmcSerialize;
|
||||
use crate::prudp::socket_addr::PRUDPSockAddr;
|
||||
|
||||
#[derive(Debug, RmcSerialize)]
|
||||
#[rmc_struct(0)]
|
||||
pub struct ConnectionInitData{
|
||||
pub struct ConnectionInitData {
|
||||
pub prudpsock_addr: PRUDPSockAddr,
|
||||
pub pid: u32,
|
||||
|
||||
pub pid: PID,
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue