V0 #2
24 changed files with 879 additions and 258 deletions
lots of changes
commit
3b6de6968d
|
|
@ -14,7 +14,7 @@ simplelog = "0.12.2"
|
|||
chrono = "0.4.39"
|
||||
log = "0.4.25"
|
||||
rand = "0.8.5"
|
||||
|
||||
cfg-if = "1.0.4"
|
||||
hmac = "0.12.1"
|
||||
md-5 = "^0.10.6"
|
||||
tokio = { version = "1.43.0", features = ["macros", "rt-multi-thread", "net", "sync", "fs"] }
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
use cfg_if::cfg_if;
|
||||
use once_cell::sync::Lazy;
|
||||
use rnex_core::common::setup;
|
||||
use rnex_core::executables::common::{SECURE_SERVER_ACCOUNT, new_simple_backend};
|
||||
use rnex_core::executables::regular_backend;
|
||||
use rnex_core::nex::auth_handler::AuthHandler;
|
||||
use rnex_core::reggie::EdgeNodeHolderConnectOption::DontRegister;
|
||||
use rnex_core::reggie::RemoteEdgeNodeHolder;
|
||||
|
|
@ -23,25 +25,11 @@ pub static FORWARD_EDGE_NODE_HOLDER: Lazy<SocketAddrV4> = Lazy::new(|| {
|
|||
async fn main() {
|
||||
setup();
|
||||
|
||||
let conn = TcpStream::connect(&*FORWARD_EDGE_NODE_HOLDER)
|
||||
.await
|
||||
.unwrap();
|
||||
cfg_if! {
|
||||
if #[cfg(features = "friends")]{
|
||||
|
||||
let conn: SplittableBufferConnection = conn.into();
|
||||
|
||||
conn.send(DontRegister.to_data().unwrap()).await;
|
||||
|
||||
let conn = new_rmc_gateway_connection(conn, |r| {
|
||||
Arc::new(OnlyRemote::<RemoteEdgeNodeHolder>::new(r))
|
||||
});
|
||||
|
||||
new_simple_backend(move |_, _| {
|
||||
let controller = conn.clone();
|
||||
Arc::new(AuthHandler {
|
||||
destination_server_acct: &SECURE_SERVER_ACCOUNT,
|
||||
build_name: "branch:origin/project/wup-agmj build:3_8_15_2004_0",
|
||||
control_server: controller,
|
||||
})
|
||||
})
|
||||
.await;
|
||||
} else {
|
||||
regular_backend::start_regular_backend().await
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
use cfg_if::cfg_if;
|
||||
use rnex_core::common::setup;
|
||||
use rnex_core::executables::common::new_simple_backend;
|
||||
use rnex_core::executables::friends_backend::start_friends_backend;
|
||||
use rnex_core::nex::matchmake::MatchmakeManager;
|
||||
use rnex_core::nex::remote_console::RemoteConsole;
|
||||
use rnex_core::nex::user::User;
|
||||
|
|
@ -11,27 +13,11 @@ use std::sync::atomic::AtomicU32;
|
|||
async fn main() {
|
||||
setup();
|
||||
|
||||
let mmm = Arc::new(MatchmakeManager {
|
||||
//gid_counter: AtomicU32::new(1),
|
||||
sessions: Default::default(),
|
||||
users: Default::default(),
|
||||
rv_cid_counter: AtomicU32::new(1),
|
||||
});
|
||||
|
||||
let weak_mmm = Arc::downgrade(&mmm);
|
||||
|
||||
MatchmakeManager::initialize_garbage_collect_thread(weak_mmm).await;
|
||||
|
||||
new_simple_backend(move |c, r| {
|
||||
let mmm = mmm.clone();
|
||||
Arc::new_cyclic(move |this| User {
|
||||
this: this.clone(),
|
||||
ip: c.prudpsock_addr,
|
||||
pid: c.pid,
|
||||
remote: RemoteConsole::new(r),
|
||||
matchmake_manager: mmm,
|
||||
station_url: Default::default(),
|
||||
})
|
||||
})
|
||||
.await;
|
||||
cfg_if! {
|
||||
if #[cfg(feature = "friends")]{
|
||||
start_friends_backend().await;
|
||||
} else {
|
||||
regular_backend::start_regular_backend().await
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
22
rnex-core/src/executables/friends_backend.rs
Normal file
22
rnex-core/src/executables/friends_backend.rs
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
use std::sync::{Arc, atomic::AtomicU32};
|
||||
|
||||
use crate::{
|
||||
executables::common::new_simple_backend,
|
||||
nex::friends_handler::{FriendsManager, FriendsUser},
|
||||
};
|
||||
|
||||
pub async fn start_friends_backend() {
|
||||
let fm = Arc::new(FriendsManager {
|
||||
cid_counter: AtomicU32::new(1),
|
||||
});
|
||||
|
||||
new_simple_backend(move |c, r| {
|
||||
let fm = fm.clone();
|
||||
Arc::new_cyclic(move |this| FriendsUser {
|
||||
fm,
|
||||
addr: c.prudpsock_addr,
|
||||
pid: c.pid,
|
||||
})
|
||||
})
|
||||
.await;
|
||||
}
|
||||
|
|
@ -1 +1,3 @@
|
|||
pub mod common;
|
||||
pub mod common;
|
||||
pub mod friends_backend;
|
||||
pub mod regular_backend;
|
||||
|
|
|
|||
33
rnex-core/src/executables/regular_backend.rs
Normal file
33
rnex-core/src/executables/regular_backend.rs
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
use std::sync::{Arc, atomic::AtomicU32};
|
||||
|
||||
use crate::{
|
||||
executables::common::new_simple_backend,
|
||||
nex::{matchmake::MatchmakeManager, remote_console::RemoteConsole, user::User},
|
||||
rmc::protocols::RmcPureRemoteObject,
|
||||
};
|
||||
|
||||
pub async fn start_regular_backend() {
|
||||
let mmm = Arc::new(MatchmakeManager {
|
||||
//gid_counter: AtomicU32::new(1),
|
||||
sessions: Default::default(),
|
||||
users: Default::default(),
|
||||
rv_cid_counter: AtomicU32::new(1),
|
||||
});
|
||||
|
||||
let weak_mmm = Arc::downgrade(&mmm);
|
||||
|
||||
MatchmakeManager::initialize_garbage_collect_thread(weak_mmm).await;
|
||||
|
||||
new_simple_backend(move |c, r| {
|
||||
let mmm = mmm.clone();
|
||||
Arc::new_cyclic(move |this| User {
|
||||
this: this.clone(),
|
||||
ip: c.prudpsock_addr,
|
||||
pid: c.pid,
|
||||
remote: RemoteConsole::new(r),
|
||||
matchmake_manager: mmm,
|
||||
station_url: Default::default(),
|
||||
})
|
||||
})
|
||||
.await;
|
||||
}
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
use crate::rmc::structures::RmcSerialize;
|
||||
use bytemuck::{Pod, Zeroable, bytes_of};
|
||||
use cfg_if::cfg_if;
|
||||
use chrono::{Datelike, NaiveDate, NaiveDateTime, NaiveTime, Timelike, Utc};
|
||||
use hmac::Hmac;
|
||||
use hmac::Mac;
|
||||
|
|
@ -8,7 +8,20 @@ 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::Unsigned;
|
||||
|
||||
use rnex_core::rmc::structures::Result;
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(feature = "friends")]{
|
||||
pub type SESSION_KEY_LENGTH_TY = U16;
|
||||
} else {
|
||||
pub type SESSION_KEY_LENGTH_TY = U32;
|
||||
}
|
||||
}
|
||||
pub const SESSION_KEY_LENGTH: usize = SESSION_KEY_LENGTH_TY::USIZE;
|
||||
|
||||
type Md5Hmac = Hmac<md5::Md5>;
|
||||
|
||||
|
|
@ -99,11 +112,11 @@ impl KerberosDateTime {
|
|||
}
|
||||
|
||||
impl RmcSerialize for KerberosDateTime {
|
||||
fn serialize(&self, writer: &mut impl Write) -> crate::rmc::structures::Result<()> {
|
||||
fn serialize(&self, writer: &mut impl Write) -> Result<()> {
|
||||
Ok(self.0.serialize(writer)?)
|
||||
}
|
||||
|
||||
fn deserialize(reader: &mut impl Read) -> crate::rmc::structures::Result<Self> {
|
||||
fn deserialize(reader: &mut impl Read) -> Result<Self> {
|
||||
Ok(Self(u64::deserialize(reader)?))
|
||||
}
|
||||
}
|
||||
|
|
@ -113,7 +126,7 @@ impl RmcSerialize for KerberosDateTime {
|
|||
pub struct TicketInternalData {
|
||||
pub issued_time: KerberosDateTime,
|
||||
pub pid: u32,
|
||||
pub session_key: [u8; 32],
|
||||
pub session_key: [u8; SESSION_KEY_LENGTH],
|
||||
}
|
||||
|
||||
impl TicketInternalData {
|
||||
|
|
@ -148,7 +161,7 @@ impl TicketInternalData {
|
|||
#[derive(Pod, Zeroable, Copy, Clone)]
|
||||
#[repr(C, packed)]
|
||||
pub struct Ticket {
|
||||
pub session_key: [u8; 32],
|
||||
pub session_key: [u8; SESSION_KEY_LENGTH],
|
||||
pub pid: u32,
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
use crate::grpc::account;
|
||||
use crate::reggie::{RemoteEdgeNodeHolder, RemoteEdgeNodeManagement};
|
||||
use crate::{define_rmc_proto, kerberos};
|
||||
use cfg_if::cfg_if;
|
||||
use log::{info, warn};
|
||||
use macros::rmc_struct;
|
||||
use rnex_core::kerberos::{KerberosDateTime, Ticket, derive_key};
|
||||
|
|
@ -11,6 +12,7 @@ use rnex_core::rmc::response::ErrorCode;
|
|||
use rnex_core::rmc::response::ErrorCode::Core_Unknown;
|
||||
use rnex_core::rmc::structures::any::Any;
|
||||
use rnex_core::rmc::structures::connection_data::ConnectionData;
|
||||
use rnex_core::rmc::structures::connection_data::ConnectionDataOld;
|
||||
use rnex_core::rmc::structures::qresult::QResult;
|
||||
use std::hash::{DefaultHasher, Hasher};
|
||||
use std::net::SocketAddrV4;
|
||||
|
|
@ -49,7 +51,13 @@ pub fn generate_ticket(
|
|||
encrypted_session_ticket
|
||||
}
|
||||
|
||||
async fn get_login_data_by_pid(pid: u32) -> Option<(u32, [u8; 16])> {
|
||||
async fn get_login_data_by_pid(pid: u32) -> Option<(u32, Box<[u8]>)> {
|
||||
if pid == GUEST_ACCOUNT.pid {
|
||||
let source_login_data = GUEST_ACCOUNT.get_login_data();
|
||||
|
||||
return Some((source_login_data.0, source_login_data.1.into()));
|
||||
}
|
||||
|
||||
let Ok(mut client) = account::Client::new().await else {
|
||||
return None;
|
||||
};
|
||||
|
|
@ -58,7 +66,7 @@ async fn get_login_data_by_pid(pid: u32) -> Option<(u32, [u8; 16])> {
|
|||
return None;
|
||||
};
|
||||
|
||||
Some((pid, passwd))
|
||||
Some((pid, passwd.into()))
|
||||
}
|
||||
|
||||
fn station_url_from_sock_addr(sock_addr: SocketAddrV4) -> String {
|
||||
|
|
@ -118,6 +126,42 @@ impl Auth for AuthHandler {
|
|||
async fn login(
|
||||
&self,
|
||||
name: String,
|
||||
) -> Result<(QResult, u32, Vec<u8>, ConnectionDataOld, String), ErrorCode> {
|
||||
let (pid, ticket) = self.generate_ticket_from_name(&name).await?;
|
||||
|
||||
let result = QResult::success(Core_Unknown);
|
||||
|
||||
let mut hasher = DefaultHasher::new();
|
||||
|
||||
hasher.write(name.as_bytes());
|
||||
|
||||
let Ok(addr) = self.control_server.get_url(hasher.finish()).await else {
|
||||
warn!("no secure proxies");
|
||||
return Err(ErrorCode::Core_Exception);
|
||||
};
|
||||
|
||||
let connection_data = ConnectionDataOld {
|
||||
station_url: station_url_from_sock_addr(addr),
|
||||
special_station_url: "".to_string(),
|
||||
special_protocols: Vec::new(),
|
||||
};
|
||||
|
||||
let ret = (
|
||||
result,
|
||||
pid,
|
||||
ticket.into(),
|
||||
connection_data,
|
||||
self.build_name.to_string(),
|
||||
);
|
||||
|
||||
info!("data: {:?}", ret);
|
||||
Ok(ret)
|
||||
}
|
||||
|
||||
async fn login_ex(
|
||||
&self,
|
||||
name: String,
|
||||
_extra_data: Any,
|
||||
) -> Result<(QResult, u32, Vec<u8>, ConnectionData, String), ErrorCode> {
|
||||
let (pid, ticket) = self.generate_ticket_from_name(&name).await?;
|
||||
|
||||
|
|
@ -152,14 +196,6 @@ impl Auth for AuthHandler {
|
|||
Ok(ret)
|
||||
}
|
||||
|
||||
async fn login_ex(
|
||||
&self,
|
||||
name: String,
|
||||
_extra_data: Any,
|
||||
) -> Result<(QResult, u32, Vec<u8>, ConnectionData, String), ErrorCode> {
|
||||
self.login(name).await
|
||||
}
|
||||
|
||||
async fn request_ticket(
|
||||
&self,
|
||||
source_pid: u32,
|
||||
|
|
|
|||
93
rnex-core/src/nex/common.rs
Normal file
93
rnex-core/src/nex/common.rs
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
use rnex_core::prudp::station_url::StationUrl;
|
||||
use rnex_core::prudp::station_url::UrlOptions::{
|
||||
Address, NatFiltering, NatMapping, NatType, Port, PrincipalID, RVConnectionID,
|
||||
};
|
||||
use rnex_core::prudp::station_url::nat_types::PUBLIC;
|
||||
use rnex_core::rmc::response::ErrorCode::Core_Exception;
|
||||
|
||||
use rnex_core::prudp::socket_addr::PRUDPSockAddr;
|
||||
use rnex_core::rmc::response::ErrorCode;
|
||||
|
||||
pub async fn get_station_urls(
|
||||
station_urls: &[StationUrl],
|
||||
addr: PRUDPSockAddr,
|
||||
pid: u32,
|
||||
cid: u32,
|
||||
) -> Result<Vec<StationUrl>, ErrorCode> {
|
||||
let mut public_station: Option<StationUrl> = None;
|
||||
let mut private_station: Option<StationUrl> = None;
|
||||
|
||||
for station in station_urls {
|
||||
let is_public = station.options.iter().any(|v| {
|
||||
if let NatType(v) = v {
|
||||
if *v & PUBLIC != 0 {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
false
|
||||
});
|
||||
|
||||
let Some(nat_filtering) = station.options.iter().find_map(|v| match v {
|
||||
NatFiltering(v) => Some(v),
|
||||
_ => None,
|
||||
}) else {
|
||||
return Err(Core_Exception);
|
||||
};
|
||||
|
||||
let Some(nat_mapping) = station.options.iter().find_map(|v| match v {
|
||||
NatMapping(v) => Some(v),
|
||||
_ => None,
|
||||
}) else {
|
||||
return Err(Core_Exception);
|
||||
};
|
||||
|
||||
if !is_public || (*nat_filtering == 0 && *nat_mapping == 0) {
|
||||
private_station = Some(station.clone());
|
||||
}
|
||||
|
||||
if is_public {
|
||||
public_station = Some(station.clone());
|
||||
}
|
||||
}
|
||||
|
||||
let Some(mut private_station) = private_station else {
|
||||
return Err(Core_Exception);
|
||||
};
|
||||
|
||||
let mut public_station = if let Some(public_station) = public_station {
|
||||
public_station
|
||||
} else {
|
||||
let mut public_station = private_station.clone();
|
||||
|
||||
public_station.options.retain(|v| match v {
|
||||
Address(_) | Port(_) | NatFiltering(_) | NatMapping(_) | NatType(_) => false,
|
||||
_ => true,
|
||||
});
|
||||
|
||||
public_station
|
||||
.options
|
||||
.push(Address(*addr.regular_socket_addr.ip()));
|
||||
public_station
|
||||
.options
|
||||
.push(Port(addr.regular_socket_addr.port()));
|
||||
public_station.options.push(NatFiltering(0));
|
||||
public_station.options.push(NatMapping(0));
|
||||
public_station.options.push(NatType(3));
|
||||
|
||||
public_station
|
||||
};
|
||||
|
||||
let both = [&mut public_station, &mut private_station];
|
||||
|
||||
for station in both {
|
||||
station.options.retain(|v| match v {
|
||||
PrincipalID(_) | RVConnectionID(_) => false,
|
||||
_ => true,
|
||||
});
|
||||
|
||||
station.options.push(PrincipalID(pid));
|
||||
station.options.push(RVConnectionID(cid));
|
||||
}
|
||||
|
||||
Ok(vec![public_station])
|
||||
}
|
||||
160
rnex-core/src/nex/friends_handler.rs
Normal file
160
rnex-core/src/nex/friends_handler.rs
Normal file
|
|
@ -0,0 +1,160 @@
|
|||
use std::sync::{Arc, atomic::AtomicU32};
|
||||
use std::time::Duration;
|
||||
|
||||
use log::info;
|
||||
use macros::rmc_struct;
|
||||
use rnex_core::rmc::protocols::friends::{Friends, RawFriends, RawFriendsInfo, RemoteFriends};
|
||||
use rnex_core::rmc::protocols::secure::{RawSecure, RawSecureInfo, RemoteSecure, Secure};
|
||||
use rnex_core::{
|
||||
define_rmc_proto,
|
||||
kerberos::KerberosDateTime,
|
||||
nex::common::get_station_urls,
|
||||
prudp::{socket_addr::PRUDPSockAddr, station_url::StationUrl},
|
||||
rmc::{
|
||||
protocols::friends::{
|
||||
BlacklistedPrincipal, Comment, FriendInfo, FriendRequest, NNAInfo, NintendoPresenceV2,
|
||||
PersistentNotification, PrincipalPreference,
|
||||
},
|
||||
response::ErrorCode,
|
||||
structures::{any::Any, qresult::QResult},
|
||||
},
|
||||
};
|
||||
use std::sync::atomic::Ordering::Relaxed;
|
||||
use tokio::time::sleep;
|
||||
|
||||
use rnex_core::rmc::protocols::friends::{GameKey, MiiV2, PrincipalBasicInfo};
|
||||
|
||||
define_rmc_proto!(
|
||||
proto FriendsUser{
|
||||
Secure,
|
||||
Friends
|
||||
}
|
||||
);
|
||||
#[rmc_struct(FriendsUser)]
|
||||
pub struct FriendsUser {
|
||||
pub fm: Arc<FriendsManager>,
|
||||
pub addr: PRUDPSockAddr,
|
||||
pub pid: u32,
|
||||
}
|
||||
|
||||
pub struct FriendsManager {
|
||||
pub cid_counter: AtomicU32,
|
||||
}
|
||||
|
||||
impl FriendsManager {
|
||||
pub fn next_cid(&self) -> u32 {
|
||||
self.cid_counter.fetch_add(1, Relaxed)
|
||||
}
|
||||
}
|
||||
|
||||
impl Friends for FriendsUser {
|
||||
async fn update_and_get_all_information(
|
||||
&self,
|
||||
info: NNAInfo,
|
||||
presence: NintendoPresenceV2,
|
||||
date_time: KerberosDateTime,
|
||||
) -> Result<
|
||||
(
|
||||
PrincipalPreference,
|
||||
Comment,
|
||||
Vec<FriendInfo>,
|
||||
Vec<FriendRequest>,
|
||||
Vec<FriendRequest>,
|
||||
Vec<BlacklistedPrincipal>,
|
||||
bool,
|
||||
Vec<PersistentNotification>,
|
||||
bool,
|
||||
),
|
||||
ErrorCode,
|
||||
> {
|
||||
Ok((
|
||||
PrincipalPreference {
|
||||
block_friend_request: false,
|
||||
show_online: false,
|
||||
show_playing_title: false,
|
||||
},
|
||||
Comment {
|
||||
last_changed: KerberosDateTime::now(),
|
||||
message: "".to_string(),
|
||||
unk: 0,
|
||||
},
|
||||
vec![FriendInfo {
|
||||
became_friends: KerberosDateTime::now(),
|
||||
comment: Comment {
|
||||
last_changed: KerberosDateTime::now(),
|
||||
message: "I'm just a dummy account :3".to_string(),
|
||||
unk: 0,
|
||||
},
|
||||
last_online: KerberosDateTime::now(),
|
||||
nna_info: NNAInfo {
|
||||
principal_basic_info: PrincipalBasicInfo {
|
||||
pid: 101,
|
||||
nnid: "dummyaccount".to_string(),
|
||||
mii: MiiV2{
|
||||
date_time: KerberosDateTime::now(),
|
||||
name: "Dummy Account".to_string(),
|
||||
mii_data: hex::decode("030000402bd7c32986a771f2dc6b35e31da15e37ff7c0000391e6f006f006d0069000000000000000000000000004040001065033568641e2013661a611821640f0000290052485000000000000000000000000000000000000000000000e838").unwrap(),
|
||||
unk: 0,
|
||||
unk2: 0,
|
||||
},
|
||||
unk: 0
|
||||
},
|
||||
unk: 0,
|
||||
unk2: 0
|
||||
},
|
||||
presence: NintendoPresenceV2{
|
||||
changed_flags: 0,
|
||||
message: "".to_string(),
|
||||
app_data: vec![],
|
||||
game_key: GameKey{
|
||||
tid: 0x00050002101ce400,
|
||||
version: 0x0
|
||||
},
|
||||
game_server_id: 0,
|
||||
is_online: true,
|
||||
gid: 0,
|
||||
pid: 101,
|
||||
unk: 0,
|
||||
unk2: 0,
|
||||
unk3: 0,
|
||||
unk4: 0,
|
||||
unk5: 0,
|
||||
unk6: 0,
|
||||
unk7: 0
|
||||
},
|
||||
unk: 0
|
||||
}],
|
||||
vec![],
|
||||
vec![],
|
||||
vec![],
|
||||
false,
|
||||
vec![],
|
||||
false,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
impl Secure for FriendsUser {
|
||||
async fn register(
|
||||
&self,
|
||||
station_urls: Vec<StationUrl>,
|
||||
) -> Result<(QResult, u32, StationUrl), ErrorCode> {
|
||||
let cid = self.fm.next_cid();
|
||||
Ok((
|
||||
QResult::success(ErrorCode::Core_Unknown),
|
||||
cid,
|
||||
get_station_urls(&station_urls, self.addr, self.pid, cid).await?[0].clone(),
|
||||
))
|
||||
}
|
||||
async fn register_ex(
|
||||
&self,
|
||||
station_urls: Vec<StationUrl>,
|
||||
data: Any,
|
||||
) -> Result<(QResult, u32, StationUrl), ErrorCode> {
|
||||
info!("register");
|
||||
self.register(station_urls).await
|
||||
}
|
||||
async fn replace_url(&self, target: StationUrl, dest: StationUrl) -> Result<(), ErrorCode> {
|
||||
Err(ErrorCode::Core_NotImplemented)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,7 @@
|
|||
pub mod account;
|
||||
pub mod auth_handler;
|
||||
pub mod user;
|
||||
pub mod common;
|
||||
pub mod friends_handler;
|
||||
pub mod matchmake;
|
||||
pub mod remote_console;
|
||||
pub mod matchmake;
|
||||
pub mod user;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
use crate::define_rmc_proto;
|
||||
use crate::nex::common::get_station_urls;
|
||||
use crate::nex::matchmake::{ExtendedMatchmakeSession, MatchmakeManager};
|
||||
use crate::nex::remote_console::RemoteConsole;
|
||||
use crate::rmc::protocols::matchmake::{
|
||||
|
|
@ -21,6 +22,7 @@ use rnex_core::rmc::protocols::matchmake_extension::{
|
|||
use rnex_core::rmc::protocols::ranking::{Ranking, RawRanking, RawRankingInfo, RemoteRanking};
|
||||
use rnex_core::rmc::protocols::secure::{RawSecure, RawSecureInfo, RemoteSecure, Secure};
|
||||
use rnex_core::rmc::response::ErrorCode;
|
||||
use rnex_core::rmc::structures::any::Any;
|
||||
use rnex_core::rmc::structures::matchmake::{
|
||||
AutoMatchmakeParam, CreateMatchmakeSessionParam, JoinMatchmakeSessionParam, MatchmakeSession,
|
||||
};
|
||||
|
|
@ -71,97 +73,27 @@ impl Secure for User {
|
|||
users.insert(cid, self.this.clone());
|
||||
drop(users);
|
||||
|
||||
let mut public_station: Option<StationUrl> = None;
|
||||
let mut private_station: Option<StationUrl> = None;
|
||||
let stations = get_station_urls(&station_urls, self.ip, self.pid, cid).await?;
|
||||
|
||||
for station in station_urls {
|
||||
let is_public = station.options.iter().any(|v| {
|
||||
if let NatType(v) = v {
|
||||
if *v & PUBLIC != 0 {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
false
|
||||
});
|
||||
|
||||
let Some(nat_filtering) = station.options.iter().find_map(|v| match v {
|
||||
NatFiltering(v) => Some(v),
|
||||
_ => None,
|
||||
}) else {
|
||||
return Err(Core_Exception);
|
||||
};
|
||||
|
||||
let Some(nat_mapping) = station.options.iter().find_map(|v| match v {
|
||||
NatMapping(v) => Some(v),
|
||||
_ => None,
|
||||
}) else {
|
||||
return Err(Core_Exception);
|
||||
};
|
||||
|
||||
if !is_public || (*nat_filtering == 0 && *nat_mapping == 0) {
|
||||
private_station = Some(station.clone());
|
||||
}
|
||||
|
||||
if is_public {
|
||||
public_station = Some(station);
|
||||
}
|
||||
}
|
||||
|
||||
let Some(mut private_station) = private_station else {
|
||||
return Err(Core_Exception);
|
||||
};
|
||||
|
||||
let mut public_station = if let Some(public_station) = public_station {
|
||||
public_station
|
||||
} else {
|
||||
let mut public_station = private_station.clone();
|
||||
|
||||
public_station.options.retain(|v| match v {
|
||||
Address(_) | Port(_) | NatFiltering(_) | NatMapping(_) | NatType(_) => false,
|
||||
_ => true,
|
||||
});
|
||||
|
||||
public_station
|
||||
.options
|
||||
.push(Address(*self.ip.regular_socket_addr.ip()));
|
||||
public_station
|
||||
.options
|
||||
.push(Port(self.ip.regular_socket_addr.port()));
|
||||
public_station.options.push(NatFiltering(0));
|
||||
public_station.options.push(NatMapping(0));
|
||||
public_station.options.push(NatType(3));
|
||||
|
||||
public_station
|
||||
};
|
||||
|
||||
let both = [&mut public_station, &mut private_station];
|
||||
|
||||
for station in both {
|
||||
station.options.retain(|v| match v {
|
||||
PrincipalID(_) | RVConnectionID(_) => false,
|
||||
_ => true,
|
||||
});
|
||||
|
||||
station.options.push(PrincipalID(self.pid));
|
||||
station.options.push(RVConnectionID(cid));
|
||||
}
|
||||
let first = stations.first().unwrap().clone();
|
||||
|
||||
let mut lock = self.station_url.write().await;
|
||||
|
||||
*lock = vec![
|
||||
public_station.clone(),
|
||||
// private_station.clone()
|
||||
];
|
||||
*lock = stations;
|
||||
|
||||
drop(lock);
|
||||
|
||||
let result = QResult::success(ErrorCode::Core_Unknown);
|
||||
|
||||
let out = public_station.to_string();
|
||||
Ok((result, cid, first))
|
||||
}
|
||||
|
||||
println!("out: {}", out);
|
||||
|
||||
Ok((result, cid, public_station))
|
||||
async fn register_ex(
|
||||
&self,
|
||||
station_urls: Vec<StationUrl>,
|
||||
_data: Any,
|
||||
) -> Result<(QResult, u32, StationUrl), ErrorCode> {
|
||||
self.register(station_urls).await
|
||||
}
|
||||
|
||||
async fn replace_url(&self, target_url: StationUrl, dest: StationUrl) -> Result<(), ErrorCode> {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
pub mod encryption;
|
||||
pub mod socket_addr;
|
||||
pub mod station_url;
|
||||
pub mod ticket;
|
||||
pub mod types_flags;
|
||||
pub mod virtual_port;
|
||||
|
|
|
|||
|
|
@ -1,26 +1,24 @@
|
|||
use hmac::Hmac;
|
||||
use macros::RmcSerialize;
|
||||
use md5::digest::Mac;
|
||||
use rnex_core::prudp::virtual_port::VirtualPort;
|
||||
use std::io::Write;
|
||||
use std::net::SocketAddrV4;
|
||||
use hmac::{Hmac};
|
||||
use md5::digest::Mac;
|
||||
use macros::RmcSerialize;
|
||||
use rnex_core::prudp::virtual_port::VirtualPort;
|
||||
|
||||
type Md5Hmac = Hmac<md5::Md5>;
|
||||
|
||||
#[derive(Eq, PartialEq, Hash, Debug, Copy, Clone, Ord, PartialOrd, RmcSerialize)]
|
||||
#[rmc_struct(0)]
|
||||
pub struct PRUDPSockAddr{
|
||||
pub struct PRUDPSockAddr {
|
||||
pub regular_socket_addr: SocketAddrV4,
|
||||
pub virtual_port: VirtualPort
|
||||
pub virtual_port: VirtualPort,
|
||||
}
|
||||
|
||||
|
||||
|
||||
impl PRUDPSockAddr{
|
||||
pub fn new(regular_socket_addr: SocketAddrV4, virtual_port: VirtualPort) -> Self{
|
||||
Self{
|
||||
impl PRUDPSockAddr {
|
||||
pub fn new(regular_socket_addr: SocketAddrV4, virtual_port: VirtualPort) -> Self {
|
||||
Self {
|
||||
regular_socket_addr,
|
||||
virtual_port
|
||||
virtual_port,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -30,8 +28,11 @@ impl PRUDPSockAddr{
|
|||
let data = self.regular_socket_addr.ip().octets().to_vec();
|
||||
//data.extend_from_slice(&self.regular_socket_addr.port().to_be_bytes());
|
||||
|
||||
hmac.write_all(&data).expect("figuring this out was complete ass");
|
||||
let result: [u8; 16] = hmac.finalize().into_bytes()[0..16].try_into().expect("fuck");
|
||||
hmac.write_all(&data)
|
||||
.expect("figuring this out was complete ass");
|
||||
let result: [u8; 16] = hmac.finalize().into_bytes()[0..16]
|
||||
.try_into()
|
||||
.expect("fuck");
|
||||
result
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
81
rnex-core/src/prudp/ticket.rs
Normal file
81
rnex-core/src/prudp/ticket.rs
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
use std::io::Cursor;
|
||||
|
||||
use log::{error, info};
|
||||
use rc4::{KeyInit, Rc4, Rc4Core, StreamCipher, cipher::StreamCipherCoreWrapper};
|
||||
use typenum::{U16, U32};
|
||||
use v_byte_helpers::{IS_BIG_ENDIAN, ReadExtensions};
|
||||
|
||||
use crate::{
|
||||
kerberos::{SESSION_KEY_LENGTH, SESSION_KEY_LENGTH_TY, TicketInternalData, derive_key},
|
||||
nex::account::Account,
|
||||
rmc::structures::RmcSerialize,
|
||||
};
|
||||
|
||||
pub fn read_secure_connection_data(
|
||||
data: &[u8],
|
||||
act: &Account,
|
||||
) -> Option<([u8; SESSION_KEY_LENGTH], u32, 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"
|
||||
);
|
||||
|
||||
let ticket_data_size = ticket_data.len();
|
||||
|
||||
let ticket_data = &mut ticket_data[0..ticket_data_size - 0x10];
|
||||
|
||||
let server_key = derive_key(act.pid, &act.kerbros_password[..]);
|
||||
|
||||
let mut rc4: StreamCipherCoreWrapper<Rc4Core<U16>> =
|
||||
Rc4::new_from_slice(&server_key).expect("unable to init rc4 keystream");
|
||||
|
||||
rc4.apply_keystream(ticket_data);
|
||||
|
||||
let ticket_data: &TicketInternalData = match bytemuck::try_from_bytes(ticket_data) {
|
||||
Ok(v) => v,
|
||||
Err(e) => {
|
||||
error!("unable to read internal ticket data: {}", e);
|
||||
return None;
|
||||
}
|
||||
};
|
||||
|
||||
// todo: add ticket expiration
|
||||
|
||||
let TicketInternalData {
|
||||
session_key,
|
||||
pid: ticket_source_pid,
|
||||
issued_time,
|
||||
} = *ticket_data;
|
||||
|
||||
// todo: add checking if tickets are signed with a valid md5-hmac
|
||||
let request_data_length = request_data.len();
|
||||
let request_data = &mut request_data[0..request_data_length - 0x10];
|
||||
|
||||
let mut rc4: StreamCipherCoreWrapper<Rc4Core<SESSION_KEY_LENGTH_TY>> =
|
||||
Rc4::new_from_slice(&session_key).expect("unable to init rc4 keystream");
|
||||
|
||||
rc4.apply_keystream(request_data);
|
||||
|
||||
let mut reqest_data_cursor = Cursor::new(request_data);
|
||||
|
||||
let pid: u32 = reqest_data_cursor.read_struct(IS_BIG_ENDIAN).ok()?;
|
||||
|
||||
if pid != ticket_source_pid {
|
||||
let ticket_created_on = issued_time.to_regular_time();
|
||||
|
||||
error!(
|
||||
"someone tried to spoof their pid, ticket was created on: {}",
|
||||
ticket_created_on.to_rfc2822()
|
||||
);
|
||||
return None;
|
||||
}
|
||||
|
||||
let _cid: u32 = reqest_data_cursor.read_struct(IS_BIG_ENDIAN).ok()?;
|
||||
let response_check: u32 = reqest_data_cursor.read_struct(IS_BIG_ENDIAN).ok()?;
|
||||
|
||||
Some((session_key, pid, response_check))
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
use crate::rmc::structures::connection_data::ConnectionData;
|
||||
use crate::rmc::structures::connection_data::{ConnectionData, ConnectionDataOld};
|
||||
use macros::{method_id, rmc_proto};
|
||||
use rnex_core::rmc::response::ErrorCode;
|
||||
use rnex_core::rmc::structures::any::Any;
|
||||
|
|
@ -14,7 +14,7 @@ pub trait Auth {
|
|||
async fn login(
|
||||
&self,
|
||||
name: String,
|
||||
) -> Result<(QResult, u32, Vec<u8>, ConnectionData, String), ErrorCode>;
|
||||
) -> Result<(QResult, u32, 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))
|
||||
|
|
|
|||
146
rnex-core/src/rmc/protocols/friends.rs
Normal file
146
rnex-core/src/rmc/protocols/friends.rs
Normal file
|
|
@ -0,0 +1,146 @@
|
|||
use macros::{RmcSerialize, method_id, rmc_proto};
|
||||
|
||||
use rnex_core::{kerberos::KerberosDateTime, rmc::response::ErrorCode};
|
||||
|
||||
#[derive(RmcSerialize)]
|
||||
#[rmc_struct(0)]
|
||||
pub struct MiiV2 {
|
||||
pub name: String,
|
||||
pub unk: u8,
|
||||
pub unk2: u8,
|
||||
pub mii_data: Vec<u8>,
|
||||
pub date_time: KerberosDateTime,
|
||||
}
|
||||
|
||||
#[derive(RmcSerialize)]
|
||||
#[rmc_struct(0)]
|
||||
pub struct PrincipalBasicInfo {
|
||||
pub pid: u32,
|
||||
pub nnid: String,
|
||||
pub mii: MiiV2,
|
||||
pub unk: u8,
|
||||
}
|
||||
|
||||
#[derive(RmcSerialize)]
|
||||
#[rmc_struct(0)]
|
||||
pub struct NNAInfo {
|
||||
pub principal_basic_info: PrincipalBasicInfo,
|
||||
pub unk: u8,
|
||||
pub unk2: u8,
|
||||
}
|
||||
|
||||
#[derive(RmcSerialize)]
|
||||
#[rmc_struct(0)]
|
||||
pub struct GameKey {
|
||||
pub tid: u64,
|
||||
pub version: u16,
|
||||
}
|
||||
|
||||
#[derive(RmcSerialize)]
|
||||
#[rmc_struct(0)]
|
||||
pub struct NintendoPresenceV2 {
|
||||
pub changed_flags: u32,
|
||||
pub is_online: bool,
|
||||
pub game_key: GameKey,
|
||||
pub unk: u8,
|
||||
pub message: String,
|
||||
pub unk2: u32,
|
||||
pub unk3: u8,
|
||||
pub game_server_id: u32,
|
||||
pub unk4: u32,
|
||||
pub pid: u32,
|
||||
pub gid: u32,
|
||||
pub app_data: Vec<u8>,
|
||||
pub unk5: u8,
|
||||
pub unk6: u8,
|
||||
pub unk7: u8,
|
||||
}
|
||||
#[derive(RmcSerialize)]
|
||||
#[rmc_struct(0)]
|
||||
pub struct PrincipalPreference {
|
||||
pub show_online: bool,
|
||||
pub show_playing_title: bool,
|
||||
pub block_friend_request: bool,
|
||||
}
|
||||
|
||||
#[derive(RmcSerialize)]
|
||||
#[rmc_struct(0)]
|
||||
pub struct Comment {
|
||||
pub unk: u8,
|
||||
pub message: String,
|
||||
pub last_changed: KerberosDateTime,
|
||||
}
|
||||
|
||||
#[derive(RmcSerialize)]
|
||||
#[rmc_struct(0)]
|
||||
pub struct FriendInfo {
|
||||
pub nna_info: NNAInfo,
|
||||
pub presence: NintendoPresenceV2,
|
||||
pub comment: Comment,
|
||||
pub became_friends: KerberosDateTime,
|
||||
pub last_online: KerberosDateTime,
|
||||
pub unk: u64,
|
||||
}
|
||||
|
||||
#[derive(RmcSerialize)]
|
||||
#[rmc_struct(0)]
|
||||
pub struct FriendRequestMessage {
|
||||
pub friend_request_id: u64,
|
||||
pub is_recieved: u8,
|
||||
pub unk: u8,
|
||||
pub message: String,
|
||||
pub unk2: u8,
|
||||
pub unk3: String,
|
||||
pub game_key: GameKey,
|
||||
pub unk4: KerberosDateTime,
|
||||
pub expires_on: KerberosDateTime,
|
||||
}
|
||||
|
||||
#[derive(RmcSerialize)]
|
||||
#[rmc_struct(0)]
|
||||
pub struct FriendRequest {
|
||||
pub basic_info: PrincipalBasicInfo,
|
||||
pub request_message: FriendRequestMessage,
|
||||
pub sent_on: KerberosDateTime,
|
||||
}
|
||||
|
||||
#[derive(RmcSerialize)]
|
||||
#[rmc_struct(0)]
|
||||
pub struct BlacklistedPrincipal {
|
||||
pub basic_info: PrincipalBasicInfo,
|
||||
pub game_key: GameKey,
|
||||
pub since: KerberosDateTime,
|
||||
}
|
||||
#[derive(RmcSerialize)]
|
||||
#[rmc_struct(0)]
|
||||
pub struct PersistentNotification {
|
||||
pub unk1: u64,
|
||||
pub unk2: u32,
|
||||
pub unk3: u32,
|
||||
pub unk4: u32,
|
||||
pub unk5: String,
|
||||
}
|
||||
|
||||
#[rmc_proto(102)]
|
||||
pub trait Friends {
|
||||
#[method_id(1)]
|
||||
async fn update_and_get_all_information(
|
||||
&self,
|
||||
info: NNAInfo,
|
||||
presence: NintendoPresenceV2,
|
||||
date_time: KerberosDateTime,
|
||||
) -> Result<
|
||||
(
|
||||
PrincipalPreference,
|
||||
Comment,
|
||||
Vec<FriendInfo>,
|
||||
Vec<FriendRequest>,
|
||||
Vec<FriendRequest>,
|
||||
Vec<BlacklistedPrincipal>,
|
||||
bool,
|
||||
Vec<PersistentNotification>,
|
||||
bool,
|
||||
),
|
||||
ErrorCode,
|
||||
>;
|
||||
}
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
#![allow(async_fn_in_trait)]
|
||||
|
||||
pub mod auth;
|
||||
pub mod friends;
|
||||
pub mod matchmake;
|
||||
pub mod matchmake_ext;
|
||||
pub mod matchmake_extension;
|
||||
|
|
@ -294,8 +295,8 @@ async fn handle_incoming<T: RmcCallable + Send + Sync + 'static>(
|
|||
} = message;
|
||||
|
||||
info!(
|
||||
"RMC REQUEST: Proto: {}; Method: {};",
|
||||
protocol_id, method_id
|
||||
"RMC REQUEST: Proto: {}; Method: {}; cid: {}",
|
||||
protocol_id, method_id, call_id
|
||||
);
|
||||
|
||||
remote
|
||||
|
|
|
|||
|
|
@ -3,10 +3,21 @@ use rnex_core::prudp::station_url::StationUrl;
|
|||
use rnex_core::rmc::response::ErrorCode;
|
||||
use rnex_core::rmc::structures::qresult::QResult;
|
||||
|
||||
use crate::rmc::structures::any::Any;
|
||||
|
||||
#[rmc_proto(11)]
|
||||
pub trait Secure {
|
||||
#[method_id(1)]
|
||||
async fn register(&self, station_urls: Vec<StationUrl>) -> Result<(QResult, u32, StationUrl), ErrorCode>;
|
||||
async fn register(
|
||||
&self,
|
||||
station_urls: Vec<StationUrl>,
|
||||
) -> Result<(QResult, u32, StationUrl), ErrorCode>;
|
||||
#[method_id(4)]
|
||||
async fn register_ex(
|
||||
&self,
|
||||
station_urls: Vec<StationUrl>,
|
||||
data: Any,
|
||||
) -> Result<(QResult, u32, StationUrl), ErrorCode>;
|
||||
#[method_id(7)]
|
||||
async fn replace_url(&self, target: StationUrl, dest: StationUrl) -> Result<(), ErrorCode>;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
use rnex_core::rmc::structures::{Result, RmcSerialize};
|
||||
use std::io::{Read, Write};
|
||||
use v_byte_helpers::{IS_BIG_ENDIAN, ReadExtensions};
|
||||
use super::{Result, RmcSerialize};
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct Any{
|
||||
pub struct Any {
|
||||
pub name: String,
|
||||
pub data: Vec<u8>
|
||||
pub data: Vec<u8>,
|
||||
}
|
||||
|
||||
impl RmcSerialize for Any{
|
||||
impl RmcSerialize for Any {
|
||||
fn serialize(&self, writer: &mut impl Write) -> Result<()> {
|
||||
self.name.serialize(writer)?;
|
||||
|
||||
|
|
@ -32,11 +32,6 @@ impl RmcSerialize for Any{
|
|||
|
||||
reader.read_exact(&mut data)?;
|
||||
|
||||
Ok(
|
||||
Any{
|
||||
name,
|
||||
data
|
||||
}
|
||||
)
|
||||
Ok(Any { name, data })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
use std::io::{Read, Write};
|
||||
use crate::rmc::structures::Result;
|
||||
use crate::rmc::structures::RmcSerialize;
|
||||
use std::io::{Read, Write};
|
||||
|
||||
|
||||
|
||||
impl<'a> RmcSerialize for &'a [u8]{
|
||||
fn serialize(&self, writer: &mut impl Write) -> crate::rmc::structures::Result<()> {
|
||||
impl<'a> RmcSerialize for &'a [u8] {
|
||||
fn serialize(&self, writer: &mut impl Write) -> Result<()> {
|
||||
let u32_size = self.len() as u32;
|
||||
writer.write(bytemuck::bytes_of(&u32_size))?;
|
||||
writer.write(self)?;
|
||||
|
|
@ -13,25 +12,25 @@ impl<'a> RmcSerialize for &'a [u8]{
|
|||
}
|
||||
|
||||
/// DO NOT USE (also maybe split off the serialize and deserialize functions at some point)
|
||||
fn deserialize(_reader: &mut impl Read) -> crate::rmc::structures::Result<Self> {
|
||||
fn deserialize(_reader: &mut impl Read) -> Result<Self> {
|
||||
panic!("cannot deserialize to a u8 slice reference (use this ONLY for writing)")
|
||||
}
|
||||
|
||||
fn serialize_write_size(&self) -> crate::rmc::structures::Result<u32> {
|
||||
fn serialize_write_size(&self) -> Result<u32> {
|
||||
Ok(4 + self.len() as u32)
|
||||
}
|
||||
}
|
||||
|
||||
impl RmcSerialize for Box<[u8]>{
|
||||
fn serialize(&self, writer: &mut impl Write) -> crate::rmc::structures::Result<()> {
|
||||
impl RmcSerialize for Box<[u8]> {
|
||||
fn serialize(&self, writer: &mut impl Write) -> Result<()> {
|
||||
(&self[..]).serialize(writer)
|
||||
}
|
||||
|
||||
fn deserialize(reader: &mut impl Read) -> crate::rmc::structures::Result<Self> {
|
||||
fn deserialize(reader: &mut impl Read) -> Result<Self> {
|
||||
Vec::deserialize(reader).map(|v| v.into_boxed_slice())
|
||||
}
|
||||
|
||||
fn serialize_write_size(&self) -> crate::rmc::structures::Result<u32> {
|
||||
fn serialize_write_size(&self) -> Result<u32> {
|
||||
(&self[..]).serialize_write_size()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,13 +1,19 @@
|
|||
|
||||
use macros::RmcSerialize;
|
||||
use rnex_core::kerberos::KerberosDateTime;
|
||||
|
||||
#[derive(Debug, RmcSerialize)]
|
||||
#[rmc_struct(1)]
|
||||
pub struct ConnectionData{
|
||||
pub struct ConnectionData {
|
||||
pub station_url: String,
|
||||
pub special_protocols: Vec<u8>,
|
||||
pub special_station_url: String,
|
||||
pub date_time: KerberosDateTime
|
||||
pub date_time: KerberosDateTime,
|
||||
}
|
||||
|
||||
#[derive(Debug, RmcSerialize)]
|
||||
#[rmc_struct(1)]
|
||||
pub struct ConnectionDataOld {
|
||||
pub station_url: String,
|
||||
pub special_protocols: Vec<u8>,
|
||||
pub special_station_url: String,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
use std::io::{Read, Write};
|
||||
use bytemuck::bytes_of;
|
||||
use v_byte_helpers::{IS_BIG_ENDIAN, ReadExtensions};
|
||||
use crate::rmc::structures::RmcSerialize;
|
||||
use bytemuck::bytes_of;
|
||||
use std::io::{Read, Write};
|
||||
use v_byte_helpers::{IS_BIG_ENDIAN, ReadExtensions};
|
||||
|
||||
impl RmcSerialize for u8{
|
||||
impl RmcSerialize for u8 {
|
||||
#[inline(always)]
|
||||
fn serialize(&self, writer: &mut impl Write) -> crate::rmc::structures::Result<()> {
|
||||
Ok(writer.write_all(bytes_of(self))?)
|
||||
|
|
@ -19,7 +19,7 @@ impl RmcSerialize for u8{
|
|||
}
|
||||
}
|
||||
|
||||
impl RmcSerialize for i8{
|
||||
impl RmcSerialize for i8 {
|
||||
#[inline(always)]
|
||||
fn serialize(&self, writer: &mut impl Write) -> crate::rmc::structures::Result<()> {
|
||||
Ok(writer.write_all(bytes_of(self))?)
|
||||
|
|
@ -35,7 +35,7 @@ impl RmcSerialize for i8{
|
|||
}
|
||||
}
|
||||
|
||||
impl RmcSerialize for u16{
|
||||
impl RmcSerialize for u16 {
|
||||
#[inline(always)]
|
||||
fn serialize(&self, writer: &mut impl Write) -> crate::rmc::structures::Result<()> {
|
||||
Ok(writer.write_all(bytes_of(self))?)
|
||||
|
|
@ -50,7 +50,7 @@ impl RmcSerialize for u16{
|
|||
}
|
||||
}
|
||||
|
||||
impl RmcSerialize for i16{
|
||||
impl RmcSerialize for i16 {
|
||||
#[inline(always)]
|
||||
fn serialize(&self, writer: &mut impl Write) -> crate::rmc::structures::Result<()> {
|
||||
Ok(writer.write_all(bytes_of(self))?)
|
||||
|
|
@ -65,7 +65,7 @@ impl RmcSerialize for i16{
|
|||
}
|
||||
}
|
||||
|
||||
impl RmcSerialize for u32{
|
||||
impl RmcSerialize for u32 {
|
||||
#[inline(always)]
|
||||
fn serialize(&self, writer: &mut impl Write) -> crate::rmc::structures::Result<()> {
|
||||
Ok(writer.write_all(bytes_of(self))?)
|
||||
|
|
@ -80,7 +80,7 @@ impl RmcSerialize for u32{
|
|||
}
|
||||
}
|
||||
|
||||
impl RmcSerialize for i32{
|
||||
impl RmcSerialize for i32 {
|
||||
#[inline(always)]
|
||||
fn serialize(&self, writer: &mut impl Write) -> crate::rmc::structures::Result<()> {
|
||||
Ok(writer.write_all(bytes_of(self))?)
|
||||
|
|
@ -95,7 +95,7 @@ impl RmcSerialize for i32{
|
|||
}
|
||||
}
|
||||
|
||||
impl RmcSerialize for u64{
|
||||
impl RmcSerialize for u64 {
|
||||
#[inline(always)]
|
||||
fn serialize(&self, writer: &mut impl Write) -> crate::rmc::structures::Result<()> {
|
||||
Ok(writer.write_all(bytes_of(self))?)
|
||||
|
|
@ -110,7 +110,7 @@ impl RmcSerialize for u64{
|
|||
}
|
||||
}
|
||||
|
||||
impl RmcSerialize for i64{
|
||||
impl RmcSerialize for i64 {
|
||||
#[inline(always)]
|
||||
fn serialize(&self, writer: &mut impl Write) -> crate::rmc::structures::Result<()> {
|
||||
Ok(writer.write_all(bytes_of(self))?)
|
||||
|
|
@ -125,7 +125,7 @@ impl RmcSerialize for i64{
|
|||
}
|
||||
}
|
||||
|
||||
impl RmcSerialize for f64{
|
||||
impl RmcSerialize for f64 {
|
||||
#[inline(always)]
|
||||
fn serialize(&self, writer: &mut impl Write) -> crate::rmc::structures::Result<()> {
|
||||
Ok(writer.write_all(bytes_of(self))?)
|
||||
|
|
@ -141,10 +141,10 @@ impl RmcSerialize for f64{
|
|||
}
|
||||
}
|
||||
|
||||
impl RmcSerialize for bool{
|
||||
impl RmcSerialize for bool {
|
||||
#[inline(always)]
|
||||
fn serialize(&self, writer: &mut impl Write) -> crate::rmc::structures::Result<()> {
|
||||
match self{
|
||||
match self {
|
||||
true => writer.write_all(&[1])?,
|
||||
false => writer.write_all(&[0])?,
|
||||
}
|
||||
|
|
@ -161,8 +161,7 @@ impl RmcSerialize for bool{
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
impl<T: RmcSerialize, U: RmcSerialize> RmcSerialize for (T, U){
|
||||
impl<T: RmcSerialize, U: RmcSerialize> RmcSerialize for (T, U) {
|
||||
#[inline(always)]
|
||||
fn serialize(&self, writer: &mut impl Write) -> crate::rmc::structures::Result<()> {
|
||||
self.0.serialize(writer)?;
|
||||
|
|
@ -178,14 +177,11 @@ impl<T: RmcSerialize, U: RmcSerialize> RmcSerialize for (T, U){
|
|||
}
|
||||
#[inline(always)]
|
||||
fn serialize_write_size(&self) -> crate::rmc::structures::Result<u32> {
|
||||
Ok(
|
||||
self.0.serialize_write_size()? +
|
||||
self.1.serialize_write_size()?
|
||||
)
|
||||
Ok(self.0.serialize_write_size()? + self.1.serialize_write_size()?)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: RmcSerialize, U: RmcSerialize, V: RmcSerialize> RmcSerialize for (T, U, V){
|
||||
impl<T: RmcSerialize, U: RmcSerialize, V: RmcSerialize> RmcSerialize for (T, U, V) {
|
||||
#[inline(always)]
|
||||
fn serialize(&self, writer: &mut impl Write) -> crate::rmc::structures::Result<()> {
|
||||
self.0.serialize(writer)?;
|
||||
|
|
@ -203,15 +199,15 @@ impl<T: RmcSerialize, U: RmcSerialize, V: RmcSerialize> RmcSerialize for (T, U,
|
|||
}
|
||||
#[inline(always)]
|
||||
fn serialize_write_size(&self) -> crate::rmc::structures::Result<u32> {
|
||||
Ok(
|
||||
self.0.serialize_write_size()? +
|
||||
self.1.serialize_write_size()? +
|
||||
self.2.serialize_write_size()?
|
||||
)
|
||||
Ok(self.0.serialize_write_size()?
|
||||
+ self.1.serialize_write_size()?
|
||||
+ self.2.serialize_write_size()?)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: RmcSerialize, U: RmcSerialize, V: RmcSerialize, W: RmcSerialize> RmcSerialize for (T, U, V, W){
|
||||
impl<T: RmcSerialize, U: RmcSerialize, V: RmcSerialize, W: RmcSerialize> RmcSerialize
|
||||
for (T, U, V, W)
|
||||
{
|
||||
#[inline(always)]
|
||||
fn serialize(&self, writer: &mut impl Write) -> crate::rmc::structures::Result<()> {
|
||||
self.0.serialize(writer)?;
|
||||
|
|
@ -231,16 +227,16 @@ impl<T: RmcSerialize, U: RmcSerialize, V: RmcSerialize, W: RmcSerialize> RmcSeri
|
|||
}
|
||||
#[inline(always)]
|
||||
fn serialize_write_size(&self) -> crate::rmc::structures::Result<u32> {
|
||||
Ok(
|
||||
self.0.serialize_write_size()? +
|
||||
self.1.serialize_write_size()? +
|
||||
self.2.serialize_write_size()? +
|
||||
self.3.serialize_write_size()?
|
||||
)
|
||||
Ok(self.0.serialize_write_size()?
|
||||
+ self.1.serialize_write_size()?
|
||||
+ self.2.serialize_write_size()?
|
||||
+ self.3.serialize_write_size()?)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: RmcSerialize, U: RmcSerialize, V: RmcSerialize, W: RmcSerialize, X: RmcSerialize> RmcSerialize for (T, U, V, W, X){
|
||||
impl<T: RmcSerialize, U: RmcSerialize, V: RmcSerialize, W: RmcSerialize, X: RmcSerialize>
|
||||
RmcSerialize for (T, U, V, W, X)
|
||||
{
|
||||
#[inline(always)]
|
||||
fn serialize(&self, writer: &mut impl Write) -> crate::rmc::structures::Result<()> {
|
||||
self.0.serialize(writer)?;
|
||||
|
|
@ -264,17 +260,23 @@ impl<T: RmcSerialize, U: RmcSerialize, V: RmcSerialize, W: RmcSerialize, X: RmcS
|
|||
}
|
||||
#[inline(always)]
|
||||
fn serialize_write_size(&self) -> crate::rmc::structures::Result<u32> {
|
||||
Ok(
|
||||
self.0.serialize_write_size()? +
|
||||
self.1.serialize_write_size()? +
|
||||
self.2.serialize_write_size()? +
|
||||
self.2.serialize_write_size()? +
|
||||
self.3.serialize_write_size()?
|
||||
)
|
||||
Ok(self.0.serialize_write_size()?
|
||||
+ self.1.serialize_write_size()?
|
||||
+ self.2.serialize_write_size()?
|
||||
+ self.2.serialize_write_size()?
|
||||
+ self.3.serialize_write_size()?)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: RmcSerialize, U: RmcSerialize, V: RmcSerialize, W: RmcSerialize, X: RmcSerialize, Y: RmcSerialize> RmcSerialize for (T, U, V, W, X, Y){
|
||||
impl<
|
||||
T: RmcSerialize,
|
||||
U: RmcSerialize,
|
||||
V: RmcSerialize,
|
||||
W: RmcSerialize,
|
||||
X: RmcSerialize,
|
||||
Y: RmcSerialize,
|
||||
> RmcSerialize for (T, U, V, W, X, Y)
|
||||
{
|
||||
#[inline(always)]
|
||||
fn serialize(&self, writer: &mut impl Write) -> crate::rmc::structures::Result<()> {
|
||||
self.0.serialize(writer)?;
|
||||
|
|
@ -300,18 +302,25 @@ impl<T: RmcSerialize, U: RmcSerialize, V: RmcSerialize, W: RmcSerialize, X: RmcS
|
|||
}
|
||||
#[inline(always)]
|
||||
fn serialize_write_size(&self) -> crate::rmc::structures::Result<u32> {
|
||||
Ok(
|
||||
self.0.serialize_write_size()? +
|
||||
self.1.serialize_write_size()? +
|
||||
self.2.serialize_write_size()? +
|
||||
self.3.serialize_write_size()? +
|
||||
self.4.serialize_write_size()? +
|
||||
self.5.serialize_write_size()?
|
||||
)
|
||||
Ok(self.0.serialize_write_size()?
|
||||
+ self.1.serialize_write_size()?
|
||||
+ self.2.serialize_write_size()?
|
||||
+ self.3.serialize_write_size()?
|
||||
+ self.4.serialize_write_size()?
|
||||
+ self.5.serialize_write_size()?)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: RmcSerialize, U: RmcSerialize, V: RmcSerialize, W: RmcSerialize, X: RmcSerialize, Y: RmcSerialize, Z: RmcSerialize> RmcSerialize for (T, U, V, W, X, Y, Z){
|
||||
impl<
|
||||
T: RmcSerialize,
|
||||
U: RmcSerialize,
|
||||
V: RmcSerialize,
|
||||
W: RmcSerialize,
|
||||
X: RmcSerialize,
|
||||
Y: RmcSerialize,
|
||||
Z: RmcSerialize,
|
||||
> RmcSerialize for (T, U, V, W, X, Y, Z)
|
||||
{
|
||||
#[inline(always)]
|
||||
fn serialize(&self, writer: &mut impl Write) -> crate::rmc::structures::Result<()> {
|
||||
self.0.serialize(writer)?;
|
||||
|
|
@ -338,19 +347,123 @@ impl<T: RmcSerialize, U: RmcSerialize, V: RmcSerialize, W: RmcSerialize, X: RmcS
|
|||
}
|
||||
#[inline(always)]
|
||||
fn serialize_write_size(&self) -> crate::rmc::structures::Result<u32> {
|
||||
Ok(
|
||||
self.0.serialize_write_size()? +
|
||||
self.1.serialize_write_size()? +
|
||||
self.2.serialize_write_size()? +
|
||||
self.3.serialize_write_size()? +
|
||||
self.4.serialize_write_size()? +
|
||||
self.5.serialize_write_size()? +
|
||||
self.6.serialize_write_size()?
|
||||
)
|
||||
Ok(self.0.serialize_write_size()?
|
||||
+ self.1.serialize_write_size()?
|
||||
+ self.2.serialize_write_size()?
|
||||
+ self.3.serialize_write_size()?
|
||||
+ self.4.serialize_write_size()?
|
||||
+ self.5.serialize_write_size()?
|
||||
+ self.6.serialize_write_size()?)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: RmcSerialize> RmcSerialize for Box<T>{
|
||||
impl<
|
||||
T: RmcSerialize,
|
||||
U: RmcSerialize,
|
||||
V: RmcSerialize,
|
||||
W: RmcSerialize,
|
||||
X: RmcSerialize,
|
||||
Y: RmcSerialize,
|
||||
Z: RmcSerialize,
|
||||
A: RmcSerialize,
|
||||
> RmcSerialize for (T, U, V, W, X, Y, Z, A)
|
||||
{
|
||||
#[inline(always)]
|
||||
fn serialize(&self, writer: &mut impl Write) -> crate::rmc::structures::Result<()> {
|
||||
self.0.serialize(writer)?;
|
||||
self.1.serialize(writer)?;
|
||||
self.2.serialize(writer)?;
|
||||
self.3.serialize(writer)?;
|
||||
self.4.serialize(writer)?;
|
||||
self.5.serialize(writer)?;
|
||||
self.6.serialize(writer)?;
|
||||
self.7.serialize(writer)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
#[inline(always)]
|
||||
fn deserialize(reader: &mut impl Read) -> crate::rmc::structures::Result<Self> {
|
||||
let first = T::deserialize(reader)?;
|
||||
let second = U::deserialize(reader)?;
|
||||
let third = V::deserialize(reader)?;
|
||||
let fourth = W::deserialize(reader)?;
|
||||
let fifth = X::deserialize(reader)?;
|
||||
let sixth = Y::deserialize(reader)?;
|
||||
let seventh = Z::deserialize(reader)?;
|
||||
let eighth = A::deserialize(reader)?;
|
||||
|
||||
Ok((first, second, third, fourth, fifth, sixth, seventh, eighth))
|
||||
}
|
||||
#[inline(always)]
|
||||
fn serialize_write_size(&self) -> crate::rmc::structures::Result<u32> {
|
||||
Ok(self.0.serialize_write_size()?
|
||||
+ self.1.serialize_write_size()?
|
||||
+ self.2.serialize_write_size()?
|
||||
+ self.3.serialize_write_size()?
|
||||
+ self.4.serialize_write_size()?
|
||||
+ self.5.serialize_write_size()?
|
||||
+ self.6.serialize_write_size()?
|
||||
+ self.7.serialize_write_size()?)
|
||||
}
|
||||
}
|
||||
|
||||
impl<
|
||||
T: RmcSerialize,
|
||||
U: RmcSerialize,
|
||||
V: RmcSerialize,
|
||||
W: RmcSerialize,
|
||||
X: RmcSerialize,
|
||||
Y: RmcSerialize,
|
||||
Z: RmcSerialize,
|
||||
A: RmcSerialize,
|
||||
B: RmcSerialize,
|
||||
> RmcSerialize for (T, U, V, W, X, Y, Z, A, B)
|
||||
{
|
||||
#[inline(always)]
|
||||
fn serialize(&self, writer: &mut impl Write) -> crate::rmc::structures::Result<()> {
|
||||
self.0.serialize(writer)?;
|
||||
self.1.serialize(writer)?;
|
||||
self.2.serialize(writer)?;
|
||||
self.3.serialize(writer)?;
|
||||
self.4.serialize(writer)?;
|
||||
self.5.serialize(writer)?;
|
||||
self.6.serialize(writer)?;
|
||||
self.7.serialize(writer)?;
|
||||
self.8.serialize(writer)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
#[inline(always)]
|
||||
fn deserialize(reader: &mut impl Read) -> crate::rmc::structures::Result<Self> {
|
||||
let first = T::deserialize(reader)?;
|
||||
let second = U::deserialize(reader)?;
|
||||
let third = V::deserialize(reader)?;
|
||||
let fourth = W::deserialize(reader)?;
|
||||
let fifth = X::deserialize(reader)?;
|
||||
let sixth = Y::deserialize(reader)?;
|
||||
let seventh = Z::deserialize(reader)?;
|
||||
let eighth = A::deserialize(reader)?;
|
||||
let nineth = B::deserialize(reader)?;
|
||||
|
||||
Ok((
|
||||
first, second, third, fourth, fifth, sixth, seventh, eighth, nineth,
|
||||
))
|
||||
}
|
||||
#[inline(always)]
|
||||
fn serialize_write_size(&self) -> crate::rmc::structures::Result<u32> {
|
||||
Ok(self.0.serialize_write_size()?
|
||||
+ self.1.serialize_write_size()?
|
||||
+ self.2.serialize_write_size()?
|
||||
+ self.3.serialize_write_size()?
|
||||
+ self.4.serialize_write_size()?
|
||||
+ self.5.serialize_write_size()?
|
||||
+ self.6.serialize_write_size()?
|
||||
+ self.7.serialize_write_size()?
|
||||
+ self.8.serialize_write_size()?)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: RmcSerialize> RmcSerialize for Box<T> {
|
||||
#[inline(always)]
|
||||
fn serialize(&self, writer: &mut impl Write) -> crate::rmc::structures::Result<()> {
|
||||
self.as_ref().serialize(writer)
|
||||
|
|
@ -363,4 +476,4 @@ impl<T: RmcSerialize> RmcSerialize for Box<T>{
|
|||
fn serialize_write_size(&self) -> crate::rmc::structures::Result<u32> {
|
||||
T::serialize_write_size(self.as_ref())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
use rnex_core::kerberos::KerberosDateTime;
|
||||
use rnex_core::rmc::structures;
|
||||
use rnex_core::rmc::structures::{Result, RmcSerialize};
|
||||
use std::io::{Read, Write};
|
||||
use crate::kerberos::KerberosDateTime;
|
||||
use crate::rmc::structures;
|
||||
use crate::rmc::structures::RmcSerialize;
|
||||
|
||||
#[derive(Debug, Clone, Default)]
|
||||
pub enum Variant{
|
||||
pub enum Variant {
|
||||
#[default]
|
||||
None,
|
||||
SInt64(i64),
|
||||
|
|
@ -15,9 +15,9 @@ pub enum Variant{
|
|||
UInt64(u64),
|
||||
}
|
||||
|
||||
impl RmcSerialize for Variant{
|
||||
fn serialize(&self, writer: &mut impl Write) -> crate::rmc::structures::Result<()> {
|
||||
match self{
|
||||
impl RmcSerialize for Variant {
|
||||
fn serialize(&self, writer: &mut impl Write) -> Result<()> {
|
||||
match self {
|
||||
Variant::None => {
|
||||
writer.write_all(&[0])?;
|
||||
}
|
||||
|
|
@ -50,8 +50,8 @@ impl RmcSerialize for Variant{
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn deserialize(reader: &mut impl Read) -> crate::rmc::structures::Result<Self> {
|
||||
match u8::deserialize(reader)?{
|
||||
fn deserialize(reader: &mut impl Read) -> Result<Self> {
|
||||
match u8::deserialize(reader)? {
|
||||
0 => Ok(Variant::None),
|
||||
1 => Ok(Variant::SInt64(i64::deserialize(reader)?)),
|
||||
2 => Ok(Variant::Double(f64::deserialize(reader)?)),
|
||||
|
|
@ -59,7 +59,7 @@ impl RmcSerialize for Variant{
|
|||
4 => Ok(Variant::String(String::deserialize(reader)?)),
|
||||
5 => Ok(Variant::DateTime(KerberosDateTime::deserialize(reader)?)),
|
||||
6 => Ok(Variant::UInt64(u64::deserialize(reader)?)),
|
||||
v => Err(structures::Error::UnexpectedValue(v as u64))
|
||||
v => Err(structures::Error::UnexpectedValue(v as u64)),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue