lots of changes

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

View file

@ -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"] }

View file

@ -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
}
}
}

View file

@ -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
}
}
}

View 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;
}

View file

@ -1 +1,3 @@
pub mod common;
pub mod common;
pub mod friends_backend;
pub mod regular_backend;

View 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;
}

View file

@ -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,
}

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -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;

View file

@ -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
}
}
}

View 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))
}

View file

@ -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))

View 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,
>;
}

View file

@ -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

View file

@ -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>;
}

View file

@ -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 })
}
}
}

View file

@ -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()
}
}
}

View file

@ -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,
}

View file

@ -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())
}
}
}

View file

@ -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)),
}
}
}
}