feat: almost done with rework communication with remotes now works
This commit is contained in:
parent
fa37331780
commit
a7c36c39ef
14 changed files with 696 additions and 155 deletions
54
Cargo.lock
generated
54
Cargo.lock
generated
|
|
@ -614,17 +614,14 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "getrandom"
|
name = "getrandom"
|
||||||
version = "0.3.0-rc.0"
|
version = "0.3.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8a78f88e84d239c7f2619ae8b091603c26208e1cb322571f5a29d6806f56ee5e"
|
checksum = "73fea8450eea4bac3940448fb7ae50d91f034f941199fcd9d909a5a07aa455f0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"js-sys",
|
|
||||||
"libc",
|
"libc",
|
||||||
"rustix",
|
"r-efi",
|
||||||
"wasi 0.13.3+wasi-0.2.2",
|
"wasi 0.14.2+wasi-0.2.4",
|
||||||
"wasm-bindgen",
|
|
||||||
"windows-targets 0.52.6",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -1051,6 +1048,7 @@ version = "0.0.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
"rand 0.9.0",
|
||||||
"syn 2.0.98",
|
"syn 2.0.98",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
@ -1425,6 +1423,12 @@ dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "r-efi"
|
||||||
|
version = "5.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rand"
|
name = "rand"
|
||||||
version = "0.8.5"
|
version = "0.8.5"
|
||||||
|
|
@ -1438,12 +1442,12 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rand"
|
name = "rand"
|
||||||
version = "0.9.0-beta.3"
|
version = "0.9.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6fccbfebb3972a41a31c605a59207d9fba5489b9a87d9d87024cb6df73a32ec7"
|
checksum = "3779b94aeb87e8bd4e834cee3650289ee9e0d5677f976ecdb6d219e5f4f6cd94"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"rand_chacha 0.9.0-beta.1",
|
"rand_chacha 0.9.0",
|
||||||
"rand_core 0.9.0-beta.1",
|
"rand_core 0.9.3",
|
||||||
"zerocopy 0.8.14",
|
"zerocopy 0.8.14",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
@ -1459,12 +1463,12 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rand_chacha"
|
name = "rand_chacha"
|
||||||
version = "0.9.0-beta.1"
|
version = "0.9.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f16da77124f4ee9fabd55ce6540866e9101431863b4876de58b68797f331adf2"
|
checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ppv-lite86",
|
"ppv-lite86",
|
||||||
"rand_core 0.9.0-beta.1",
|
"rand_core 0.9.3",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -1478,12 +1482,11 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rand_core"
|
name = "rand_core"
|
||||||
version = "0.9.0-beta.1"
|
version = "0.9.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a98fa0b8309344136abe6244130311e76997e546f76fae8054422a7539b43df7"
|
checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"getrandom 0.3.0-rc.0",
|
"getrandom 0.3.2",
|
||||||
"zerocopy 0.8.14",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -1871,7 +1874,7 @@ dependencies = [
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"paste",
|
"paste",
|
||||||
"prost",
|
"prost",
|
||||||
"rand 0.9.0-beta.3",
|
"rand 0.9.0",
|
||||||
"rc4",
|
"rc4",
|
||||||
"rocket",
|
"rocket",
|
||||||
"rustls",
|
"rustls",
|
||||||
|
|
@ -1882,6 +1885,7 @@ dependencies = [
|
||||||
"tokio-stream",
|
"tokio-stream",
|
||||||
"tonic",
|
"tonic",
|
||||||
"tonic-build",
|
"tonic-build",
|
||||||
|
"typenum",
|
||||||
"v_byte_macros",
|
"v_byte_macros",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
@ -2268,9 +2272,9 @@ checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "typenum"
|
name = "typenum"
|
||||||
version = "1.17.0"
|
version = "1.18.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
|
checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ubyte"
|
name = "ubyte"
|
||||||
|
|
@ -2348,9 +2352,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasi"
|
name = "wasi"
|
||||||
version = "0.13.3+wasi-0.2.2"
|
version = "0.14.2+wasi-0.2.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "26816d2e1a4a36a2940b96c5296ce403917633dff8f3440e9b236ed6f6bacad2"
|
checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"wit-bindgen-rt",
|
"wit-bindgen-rt",
|
||||||
]
|
]
|
||||||
|
|
@ -2624,9 +2628,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wit-bindgen-rt"
|
name = "wit-bindgen-rt"
|
||||||
version = "0.33.0"
|
version = "0.39.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3268f3d866458b787f390cf61f4bbb563b922d091359f9608842999eaee3943c"
|
checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,7 @@ rocket = { version = "0.5.1", features = ["json", "serde_json"] }
|
||||||
serde = { version = "1.0.217", features = ["derive"] }
|
serde = { version = "1.0.217", features = ["derive"] }
|
||||||
async-trait = "0.1.86"
|
async-trait = "0.1.86"
|
||||||
paste = "1.0.15"
|
paste = "1.0.15"
|
||||||
|
typenum = "1.18.0"
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
tonic-build = "0.12.3"
|
tonic-build = "0.12.3"
|
||||||
|
|
|
||||||
|
|
@ -13,4 +13,5 @@ proc-macro = true
|
||||||
quote = "1.0.38"
|
quote = "1.0.38"
|
||||||
proc-macro2 = "1.0.93"
|
proc-macro2 = "1.0.93"
|
||||||
syn = { version = "2.0.98", features = ["full"] }
|
syn = { version = "2.0.98", features = ["full"] }
|
||||||
|
rand = "0.9.0"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -323,7 +323,8 @@ pub fn rmc_proto(attr: TokenStream, input: TokenStream) -> TokenStream{
|
||||||
ProtoMethodData{
|
ProtoMethodData{
|
||||||
id,
|
id,
|
||||||
name: func.sig.ident.clone(),
|
name: func.sig.ident.clone(),
|
||||||
parameters: funcs
|
parameters: funcs,
|
||||||
|
ret_val: func.sig.output.clone()
|
||||||
}
|
}
|
||||||
}).collect()
|
}).collect()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,13 @@
|
||||||
use proc_macro2::{Ident, Span, TokenStream, TokenTree};
|
use proc_macro2::{Ident, Span, TokenStream, TokenTree};
|
||||||
use quote::{quote, ToTokens};
|
use quote::{quote, ToTokens};
|
||||||
use syn::{LitInt, Token, Type};
|
use syn::{LitInt, ReturnType, Token, Type};
|
||||||
use syn::token::{Brace, Paren, Semi};
|
use syn::token::{Brace, Paren, Semi};
|
||||||
|
|
||||||
pub struct ProtoMethodData{
|
pub struct ProtoMethodData{
|
||||||
pub id: LitInt,
|
pub id: LitInt,
|
||||||
pub name: Ident,
|
pub name: Ident,
|
||||||
pub parameters: Vec<(Ident, Type)>
|
pub parameters: Vec<(Ident, Type)>,
|
||||||
|
pub ret_val: ReturnType,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -22,8 +23,8 @@ pub struct RmcProtocolData{
|
||||||
pub methods: Vec<ProtoMethodData>
|
pub methods: Vec<ProtoMethodData>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToTokens for RmcProtocolData{
|
impl RmcProtocolData{
|
||||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
fn generate_raw_trait(&self, tokens: &mut TokenStream){
|
||||||
let Self{
|
let Self{
|
||||||
has_returns,
|
has_returns,
|
||||||
name,
|
name,
|
||||||
|
|
@ -73,7 +74,7 @@ impl ToTokens for RmcProtocolData{
|
||||||
<#param_type as crate::rmc::structures::RmcSerialize>::deserialize(
|
<#param_type as crate::rmc::structures::RmcSerialize>::deserialize(
|
||||||
&mut cursor
|
&mut cursor
|
||||||
) else {
|
) else {
|
||||||
return Err(ErrorCode::Core_InvalidArgument);
|
return Err(crate::rmc::response::ErrorCode::Core_InvalidArgument);
|
||||||
};
|
};
|
||||||
}.to_tokens(tokens)
|
}.to_tokens(tokens)
|
||||||
}
|
}
|
||||||
|
|
@ -156,6 +157,111 @@ impl ToTokens for RmcProtocolData{
|
||||||
quote!{
|
quote!{
|
||||||
impl<T: #name> RawAuth for T{}
|
impl<T: #name> RawAuth for T{}
|
||||||
}.to_tokens(tokens);
|
}.to_tokens(tokens);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn generate_raw_remote_trait(&self, tokens: &mut TokenStream) {
|
||||||
|
let Self {
|
||||||
|
has_returns,
|
||||||
|
name,
|
||||||
|
id: proto_id,
|
||||||
|
methods,
|
||||||
|
..
|
||||||
|
} = self;
|
||||||
|
|
||||||
|
// this gives us the name which the identifier of the corresponding Raw trait
|
||||||
|
let remote_name = Ident::new(&format!("Remote{}", name), name.span());
|
||||||
|
|
||||||
|
|
||||||
|
// boilerplate tokens which all raw traits need
|
||||||
|
quote!{
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub trait #remote_name: crate::rmc::protocols::HasRmcConnection
|
||||||
|
}.to_tokens(tokens);
|
||||||
|
|
||||||
|
// generate the body of the raw protocol trait
|
||||||
|
Brace::default().surround(tokens, |tokens|{
|
||||||
|
//generate each raw method
|
||||||
|
for method in methods{
|
||||||
|
let ProtoMethodData {
|
||||||
|
name,
|
||||||
|
parameters,
|
||||||
|
ret_val,
|
||||||
|
id: method_id,
|
||||||
|
..
|
||||||
|
} = method;
|
||||||
|
|
||||||
|
quote!{
|
||||||
|
async fn #name
|
||||||
|
}.to_tokens(tokens);
|
||||||
|
|
||||||
|
Paren::default().surround(tokens, |tokens|{
|
||||||
|
quote!{ &self, }.to_tokens(tokens);
|
||||||
|
for (param_ident, param_type) in parameters{
|
||||||
|
quote!{ #param_ident: #param_type, }.to_tokens(tokens);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
quote!{
|
||||||
|
#ret_val
|
||||||
|
}.to_tokens(tokens);
|
||||||
|
|
||||||
|
Brace::default().surround(tokens, |tokens|{
|
||||||
|
quote! {
|
||||||
|
let mut send_data = Vec::new();
|
||||||
|
let mut cursor = ::std::io::Cursor::new(&mut send_data);
|
||||||
|
}.to_tokens(tokens);
|
||||||
|
|
||||||
|
for (param_name, param_type) in parameters{
|
||||||
|
quote!{
|
||||||
|
crate::result::ResultExtension::display_err_or_some(
|
||||||
|
<#param_type as crate::rmc::structures::RmcSerialize>::serialize(
|
||||||
|
&#param_name,
|
||||||
|
&mut cursor
|
||||||
|
)
|
||||||
|
).ok_or(crate::rmc::response::ErrorCode::Core_InvalidArgument)?;
|
||||||
|
}.to_tokens(tokens)
|
||||||
|
}
|
||||||
|
|
||||||
|
quote!{
|
||||||
|
let call_id = rand::random();
|
||||||
|
|
||||||
|
let message = crate::rmc::message::RMCMessage{
|
||||||
|
call_id,
|
||||||
|
method_id: #method_id,
|
||||||
|
protocol_id: #proto_id,
|
||||||
|
rest_of_data: send_data
|
||||||
|
};
|
||||||
|
|
||||||
|
let rmc_conn = <Self as crate::rmc::protocols::HasRmcConnection>::get_connection(self);
|
||||||
|
}.to_tokens(tokens);
|
||||||
|
|
||||||
|
if *has_returns{
|
||||||
|
quote!{
|
||||||
|
crate::result::ResultExtension::display_err_or_some(
|
||||||
|
rmc_conn.make_raw_call(&message).await
|
||||||
|
).ok_or(crate::rmc::response::ErrorCode::Core_Exception)
|
||||||
|
}.to_tokens(tokens);
|
||||||
|
} else {
|
||||||
|
quote!{
|
||||||
|
crate::result::ResultExtension::display_err_or_some(
|
||||||
|
rmc_conn.make_raw_call_no_response(&message).await
|
||||||
|
);
|
||||||
|
}.to_tokens(tokens);
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fn generate_raw_info(&self, tokens: &mut TokenStream){
|
||||||
|
let Self{
|
||||||
|
name,
|
||||||
|
id,
|
||||||
|
..
|
||||||
|
} = self;
|
||||||
|
|
||||||
let raw_info_name = Ident::new(&format!("Raw{}Info", name), Span::call_site());
|
let raw_info_name = Ident::new(&format!("Raw{}Info", name), Span::call_site());
|
||||||
|
|
||||||
|
|
@ -171,3 +277,15 @@ impl ToTokens for RmcProtocolData{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ToTokens for RmcProtocolData{
|
||||||
|
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||||
|
self.generate_raw_trait(tokens);
|
||||||
|
self.generate_raw_info(tokens);
|
||||||
|
self.generate_raw_remote_trait(tokens);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
||||||
210
src/main.rs
210
src/main.rs
|
|
@ -2,92 +2,115 @@
|
||||||
#![warn(missing_docs)]
|
#![warn(missing_docs)]
|
||||||
|
|
||||||
//! # Splatoon RNEX server
|
//! # Splatoon RNEX server
|
||||||
//!
|
//!
|
||||||
//! This server still includes the code for rnex itself as this is the first rnex server and thus
|
//! This server still includes the code for rnex itself as this is the first rnex server and thus
|
||||||
//! also the first and only current usage of rnex, expect this and rnex to be split into seperate
|
//! also the first and only current usage of rnex, expect this and rnex to be split into seperate
|
||||||
//! repos soon.
|
//! repos soon.
|
||||||
|
|
||||||
use std::{env, fs};
|
use crate::rmc::protocols::auth::RemoteAuth;
|
||||||
use std::fs::File;
|
use crate::rmc::protocols::auth::RawAuthInfo;
|
||||||
use std::net::{Ipv4Addr, SocketAddrV4};
|
use crate::rmc::protocols::auth::RawAuth;
|
||||||
|
use crate::nex::account::Account;
|
||||||
|
use crate::prudp::packet::VirtualPort;
|
||||||
|
use crate::prudp::router::Router;
|
||||||
|
use crate::prudp::sockaddr::PRUDPSockAddr;
|
||||||
|
use crate::prudp::socket::Unsecure;
|
||||||
use chrono::{Local, SecondsFormat};
|
use chrono::{Local, SecondsFormat};
|
||||||
use log::info;
|
use log::info;
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
use simplelog::{ColorChoice, CombinedLogger, Config, LevelFilter, TerminalMode, TermLogger, WriteLogger};
|
use simplelog::{
|
||||||
use crate::nex::account::Account;
|
ColorChoice, CombinedLogger, Config, LevelFilter, TermLogger, TerminalMode, WriteLogger,
|
||||||
use crate::prudp::socket::Unsecure;
|
};
|
||||||
use crate::prudp::packet::{VirtualPort};
|
use std::fs::File;
|
||||||
use crate::prudp::router::Router;
|
use std::net::{Ipv4Addr, SocketAddrV4};
|
||||||
use crate::prudp::sockaddr::PRUDPSockAddr;
|
use std::{env, fs};
|
||||||
|
use std::marker::PhantomData;
|
||||||
|
use std::ops::{BitAnd, BitOr};
|
||||||
|
use std::str::FromStr;
|
||||||
|
use macros::rmc_struct;
|
||||||
|
use crate::rmc::protocols::auth::Auth;
|
||||||
|
use crate::rmc::protocols::{new_rmc_gateway_connection, OnlyRemote};
|
||||||
|
use crate::rmc::response::ErrorCode;
|
||||||
|
use crate::rmc::structures::any::Any;
|
||||||
|
use crate::rmc::structures::connection_data::ConnectionData;
|
||||||
|
use crate::rmc::structures::qresult::QResult;
|
||||||
|
|
||||||
mod endianness;
|
mod endianness;
|
||||||
mod prudp;
|
mod prudp;
|
||||||
pub mod rmc;
|
pub mod rmc;
|
||||||
//mod protocols;
|
//mod protocols;
|
||||||
|
|
||||||
mod nex;
|
|
||||||
mod grpc;
|
mod grpc;
|
||||||
mod kerberos;
|
mod kerberos;
|
||||||
|
mod nex;
|
||||||
mod web;
|
mod web;
|
||||||
|
mod versions;
|
||||||
|
mod result;
|
||||||
|
|
||||||
static KERBEROS_SERVER_PASSWORD: Lazy<String> = Lazy::new(||{
|
static KERBEROS_SERVER_PASSWORD: Lazy<String> = Lazy::new(|| {
|
||||||
env::var("AUTH_SERVER_PASSWORD")
|
env::var("AUTH_SERVER_PASSWORD")
|
||||||
.ok()
|
.ok()
|
||||||
.unwrap_or("password".to_owned())
|
.unwrap_or("password".to_owned())
|
||||||
});
|
});
|
||||||
|
|
||||||
|
static AUTH_SERVER_ACCOUNT: Lazy<Account> =
|
||||||
|
Lazy::new(|| Account::new(1, "Quazal Authentication", &KERBEROS_SERVER_PASSWORD));
|
||||||
|
static SECURE_SERVER_ACCOUNT: Lazy<Account> =
|
||||||
|
Lazy::new(|| Account::new(2, "Quazal Rendez-Vous", &KERBEROS_SERVER_PASSWORD));
|
||||||
|
|
||||||
static AUTH_SERVER_ACCOUNT: Lazy<Account> = Lazy::new(|| Account::new(1, "Quazal Authentication", &KERBEROS_SERVER_PASSWORD));
|
static AUTH_SERVER_PORT: Lazy<u16> = Lazy::new(|| {
|
||||||
static SECURE_SERVER_ACCOUNT: Lazy<Account> = Lazy::new(|| Account::new(2, "Quazal Rendez-Vous", &KERBEROS_SERVER_PASSWORD));
|
|
||||||
|
|
||||||
static AUTH_SERVER_PORT: Lazy<u16> = Lazy::new(||{
|
|
||||||
env::var("AUTH_SERVER_PORT")
|
env::var("AUTH_SERVER_PORT")
|
||||||
.ok()
|
.ok()
|
||||||
.and_then(|s| s.parse().ok())
|
.and_then(|s| s.parse().ok())
|
||||||
.unwrap_or(10000)
|
.unwrap_or(10000)
|
||||||
});
|
});
|
||||||
static SECURE_SERVER_PORT: Lazy<u16> = Lazy::new(||{
|
static SECURE_SERVER_PORT: Lazy<u16> = Lazy::new(|| {
|
||||||
env::var("SECURE_SERVER_PORT")
|
env::var("SECURE_SERVER_PORT")
|
||||||
.ok()
|
.ok()
|
||||||
.and_then(|s| s.parse().ok())
|
.and_then(|s| s.parse().ok())
|
||||||
.unwrap_or(10001)
|
.unwrap_or(10002)
|
||||||
});
|
});
|
||||||
|
|
||||||
static OWN_IP_PRIVATE: Lazy<Ipv4Addr> = Lazy::new(||{
|
static OWN_IP_PRIVATE: Lazy<Ipv4Addr> = Lazy::new(|| {
|
||||||
env::var("SERVER_IP")
|
env::var("SERVER_IP")
|
||||||
.ok()
|
.ok()
|
||||||
.and_then(|s| s.parse().ok())
|
.and_then(|s| s.parse().ok())
|
||||||
.expect("no public ip specified")
|
.expect("no public ip specified")
|
||||||
});
|
});
|
||||||
|
|
||||||
static OWN_IP_PUBLIC: Lazy<String> = Lazy::new(||{
|
static OWN_IP_PUBLIC: Lazy<String> =
|
||||||
env::var("SERVER_IP_PUBLIC")
|
Lazy::new(|| env::var("SERVER_IP_PUBLIC").unwrap_or(OWN_IP_PRIVATE.to_string()));
|
||||||
.unwrap_or(OWN_IP_PRIVATE.to_string())
|
|
||||||
});
|
|
||||||
|
|
||||||
static SECURE_STATION_URL: Lazy<String> = Lazy::new(||
|
static SECURE_STATION_URL: Lazy<String> = Lazy::new(|| {
|
||||||
format!("prudps:/PID=2;sid=1;stream=10;type=2;address={};port={};CID=1", *OWN_IP_PUBLIC, *SECURE_SERVER_PORT)
|
format!(
|
||||||
);
|
"prudps:/PID=2;sid=1;stream=10;type=2;address={};port={};CID=1",
|
||||||
|
*OWN_IP_PUBLIC, *SECURE_SERVER_PORT
|
||||||
|
)
|
||||||
|
});
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
CombinedLogger::init(
|
CombinedLogger::init(vec![
|
||||||
vec![
|
TermLogger::new(
|
||||||
TermLogger::new(LevelFilter::Info, Config::default(), TerminalMode::Mixed, ColorChoice::Auto),
|
LevelFilter::Info,
|
||||||
WriteLogger::new(LevelFilter::max(), Config::default(), {
|
Config::default(),
|
||||||
fs::create_dir_all("log").unwrap();
|
TerminalMode::Mixed,
|
||||||
let date = Local::now().to_rfc3339_opts(SecondsFormat::Secs, false);
|
ColorChoice::Auto,
|
||||||
// this fixes windows being windows
|
),
|
||||||
let date = date.replace(":", "-");
|
WriteLogger::new(LevelFilter::max(), Config::default(), {
|
||||||
let filename = format!("{}.log", date);
|
fs::create_dir_all("log").unwrap();
|
||||||
if cfg!(windows) {
|
let date = Local::now().to_rfc3339_opts(SecondsFormat::Secs, false);
|
||||||
File::create(format!("log\\{}", filename)).unwrap()
|
// this fixes windows being windows
|
||||||
} else {
|
let date = date.replace(":", "-");
|
||||||
File::create(format!("log/{}", filename)).unwrap()
|
let filename = format!("{}.log", date);
|
||||||
}
|
if cfg!(windows) {
|
||||||
})
|
File::create(format!("log\\{}", filename)).unwrap()
|
||||||
]
|
} else {
|
||||||
).unwrap();
|
File::create(format!("log/{}", filename)).unwrap()
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
])
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
dotenv::dotenv().ok();
|
dotenv::dotenv().ok();
|
||||||
|
|
||||||
|
|
@ -234,68 +257,63 @@ async fn start_secure_server() -> SecureServer{
|
||||||
socket,
|
socket,
|
||||||
}
|
}
|
||||||
}*/
|
}*/
|
||||||
/*
|
|
||||||
define_rmc_proto!(
|
define_rmc_proto!(
|
||||||
proto AuthClientProtocol{
|
proto AuthClientProtocol{
|
||||||
Auth
|
Auth
|
||||||
}
|
}
|
||||||
);*/
|
);
|
||||||
|
|
||||||
|
impl Auth for AuthClient{
|
||||||
|
async fn login(&self, name: String) -> Result<(), ErrorCode> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
//#[rmc_struct(AuthClientProtocol)]
|
async fn login_ex(&self, name: String, extra_data: Any) -> Result<(QResult, u32, Vec<u8>, ConnectionData, String), ErrorCode> {
|
||||||
struct AuthClient{
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn request_ticket(&self, source_pid: u32, destination_pid: u32) -> Result<(QResult, Vec<u8>), ErrorCode> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn get_pid(&self, username: String) -> Result<u32, ErrorCode> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn get_name(&self, pid: u32) -> Result<String, ErrorCode> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn start_servers(){
|
#[rmc_struct(AuthClientProtocol)]
|
||||||
|
struct AuthClient {}
|
||||||
|
|
||||||
|
async fn start_servers() {
|
||||||
|
|
||||||
|
|
||||||
|
//let auth_ip = SocketAddrV4::from_str("157.90.13.221:30039").unwrap();
|
||||||
|
let auth_ip = SocketAddrV4::from_str("31.220.75.208:10000").unwrap();
|
||||||
|
let auth_port = VirtualPort::new(1, 10);
|
||||||
|
|
||||||
|
let auth_sockaddr = PRUDPSockAddr::new(auth_ip, auth_port);
|
||||||
|
|
||||||
|
let (router_secure, _) = Router::new(SocketAddrV4::new(*OWN_IP_PRIVATE, *SECURE_SERVER_PORT))
|
||||||
|
.await
|
||||||
|
.expect("unable to start router");
|
||||||
|
|
||||||
|
let mut socket_secure = router_secure
|
||||||
|
.add_socket(VirtualPort::new(1, 10), Unsecure("CD&ML"))
|
||||||
|
.await
|
||||||
|
.expect("unable to add socket");
|
||||||
|
|
||||||
|
let conn = socket_secure.connect(auth_sockaddr).await.unwrap();
|
||||||
|
|
||||||
|
let obj = new_rmc_gateway_connection(conn, OnlyRemote::<RemoteAuthClientProtocol>::new);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
let a = tokio::spawn(async{
|
|
||||||
let (router_auth, _) =
|
|
||||||
Router::new(SocketAddrV4::new(*OWN_IP_PRIVATE, *AUTH_SERVER_PORT)).await.expect("unable to start router");
|
|
||||||
|
|
||||||
let mut socket_auth = router_auth.add_socket(VirtualPort::new(1,10), Unsecure("CD&ML")).await
|
|
||||||
.expect("unable to add socket");
|
|
||||||
|
|
||||||
let mut conn = socket_auth.accept().await.unwrap();
|
|
||||||
info!("got conn");
|
|
||||||
|
|
||||||
if let Some(data) = conn.recv().await{
|
|
||||||
let str = String::from_utf8(data).unwrap();
|
|
||||||
|
|
||||||
println!("{}", str)
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
let b = tokio::spawn(async{
|
|
||||||
let auth_ip = SocketAddrV4::new(*OWN_IP_PRIVATE, *AUTH_SERVER_PORT);
|
|
||||||
let auth_port = VirtualPort::new(1,10);
|
|
||||||
|
|
||||||
let auth_sockaddr = PRUDPSockAddr::new(auth_ip,auth_port);
|
|
||||||
|
|
||||||
|
|
||||||
let (router_secure, _) =
|
|
||||||
Router::new(SocketAddrV4::new(*OWN_IP_PRIVATE, *SECURE_SERVER_PORT)).await.expect("unable to start router");
|
|
||||||
|
|
||||||
let mut socket_secure = router_secure.add_socket(VirtualPort::new(1,10), Unsecure("CD&ML")).await
|
|
||||||
.expect("unable to add socket");
|
|
||||||
|
|
||||||
let conn = socket_secure.connect(auth_sockaddr).await.unwrap();
|
|
||||||
|
|
||||||
let conn = conn.duplicate_sender();
|
|
||||||
|
|
||||||
conn.send("Yippie".as_bytes().to_owned()).await;
|
|
||||||
|
|
||||||
info!("got conn");
|
|
||||||
});
|
|
||||||
|
|
||||||
a.await;
|
|
||||||
b.await;
|
|
||||||
|
|
||||||
/*
|
|
||||||
#[cfg(feature = "auth")]
|
#[cfg(feature = "auth")]
|
||||||
let auth_server = start_auth_server().await;
|
let auth_server = start_auth_server().await;
|
||||||
#[cfg(feature = "secure")]
|
#[cfg(feature = "secure")]
|
||||||
|
|
@ -307,4 +325,4 @@ async fn start_servers(){
|
||||||
#[cfg(feature = "secure")]
|
#[cfg(feature = "secure")]
|
||||||
secure_server.join_handle.await.expect("auth server crashed");
|
secure_server.join_handle.await.expect("auth server crashed");
|
||||||
web_server.await.expect("webserver crashed");*/
|
web_server.await.expect("webserver crashed");*/
|
||||||
}
|
}
|
||||||
23
src/result.rs
Normal file
23
src/result.rs
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
use std::error::Error;
|
||||||
|
use log::error;
|
||||||
|
|
||||||
|
pub trait ResultExtension{
|
||||||
|
type Output;
|
||||||
|
|
||||||
|
fn display_err_or_some(self) -> Option<Self::Output>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T, U: Error> ResultExtension for Result<T, U>{
|
||||||
|
type Output = T;
|
||||||
|
|
||||||
|
fn display_err_or_some(self) -> Option<Self::Output> {
|
||||||
|
match self{
|
||||||
|
Ok(v) => Some(v),
|
||||||
|
Err(e) => {
|
||||||
|
error!("{}", e);
|
||||||
|
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -9,9 +9,13 @@ use macros::{method_id, rmc_proto};
|
||||||
/// [kinnay wiki entry](https://github.com/kinnay/NintendoClients/wiki/Authentication-Protocol))
|
/// [kinnay wiki entry](https://github.com/kinnay/NintendoClients/wiki/Authentication-Protocol))
|
||||||
#[rmc_proto(10)]
|
#[rmc_proto(10)]
|
||||||
pub trait Auth {
|
pub trait Auth {
|
||||||
|
/// representation of the `Login` method(for details see the
|
||||||
|
/// [kinnay wiki entry](https://github.com/kinnay/NintendoClients/wiki/Authentication-Protocol))
|
||||||
#[method_id(1)]
|
#[method_id(1)]
|
||||||
async fn login(&self, name: String) -> Result<(), ErrorCode>;
|
async fn login(&self, name: String) -> Result<(), ErrorCode>;
|
||||||
|
|
||||||
|
/// representation of the `LoginEx` method(for details see the
|
||||||
|
/// [kinnay wiki entry](https://github.com/kinnay/NintendoClients/wiki/Authentication-Protocol))
|
||||||
#[method_id(2)]
|
#[method_id(2)]
|
||||||
async fn login_ex(
|
async fn login_ex(
|
||||||
&self,
|
&self,
|
||||||
|
|
@ -19,6 +23,8 @@ pub trait Auth {
|
||||||
extra_data: Any,
|
extra_data: Any,
|
||||||
) -> Result<(QResult, u32, Vec<u8>, ConnectionData, String), ErrorCode>;
|
) -> Result<(QResult, u32, Vec<u8>, ConnectionData, String), ErrorCode>;
|
||||||
|
|
||||||
|
/// representation of the `RequestTicket` method(for details see the
|
||||||
|
/// [kinnay wiki entry](https://github.com/kinnay/NintendoClients/wiki/Authentication-Protocol))
|
||||||
#[method_id(3)]
|
#[method_id(3)]
|
||||||
async fn request_ticket(
|
async fn request_ticket(
|
||||||
&self,
|
&self,
|
||||||
|
|
@ -26,9 +32,16 @@ pub trait Auth {
|
||||||
destination_pid: u32,
|
destination_pid: u32,
|
||||||
) -> Result<(QResult, Vec<u8>), ErrorCode>;
|
) -> Result<(QResult, Vec<u8>), ErrorCode>;
|
||||||
|
|
||||||
|
/// representation of the `GetPID` method(for details see the
|
||||||
|
/// [kinnay wiki entry](https://github.com/kinnay/NintendoClients/wiki/Authentication-Protocol))
|
||||||
#[method_id(4)]
|
#[method_id(4)]
|
||||||
async fn get_pid(&self, username: String) -> Result<u32, ErrorCode>;
|
async fn get_pid(&self, username: String) -> Result<u32, ErrorCode>;
|
||||||
|
|
||||||
|
/// representation of the `LoginWithContext` method(for details see the
|
||||||
|
/// [kinnay wiki entry](https://github.com/kinnay/NintendoClients/wiki/Authentication-Protocol))
|
||||||
#[method_id(5)]
|
#[method_id(5)]
|
||||||
async fn get_name(&self, pid: u32) -> Result<String, ErrorCode>;
|
async fn get_name(&self, pid: u32) -> Result<String, ErrorCode>;
|
||||||
|
|
||||||
|
// `LoginWithContext` is left out here because we don't need it right now and versioning still
|
||||||
|
// needs to be figured out
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,52 +2,113 @@
|
||||||
|
|
||||||
pub mod auth;
|
pub mod auth;
|
||||||
|
|
||||||
use macros::method_id;
|
use crate::prudp::socket::{ExternalConnection, SendingConnection};
|
||||||
use std::collections::HashMap;
|
use crate::rmc::message::RMCMessage;
|
||||||
use std::ops::Add;
|
use crate::rmc::protocols::RemoteCallError::ConnectionBroke;
|
||||||
use std::sync::{Arc, Condvar};
|
use crate::rmc::response::{ErrorCode, RMCResponse, RMCResponseResult};
|
||||||
use std::time::Duration;
|
use crate::rmc::structures;
|
||||||
|
use crate::rmc::structures::connection_data::ConnectionData;
|
||||||
|
use crate::rmc::structures::matchmake::AutoMatchmakeParam;
|
||||||
|
use crate::rmc::structures::{Error, RmcSerialize};
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use chrono::TimeDelta;
|
use chrono::TimeDelta;
|
||||||
|
use log::{error, info};
|
||||||
|
use macros::method_id;
|
||||||
use macros::{rmc_proto, rmc_struct};
|
use macros::{rmc_proto, rmc_struct};
|
||||||
use paste::paste;
|
use paste::paste;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::io::Cursor;
|
||||||
|
use std::ops::{Add, Deref};
|
||||||
|
use std::sync::{Arc, Condvar};
|
||||||
|
use std::time::Duration;
|
||||||
|
use thiserror::Error;
|
||||||
use tokio::sync::{Mutex, Notify};
|
use tokio::sync::{Mutex, Notify};
|
||||||
use tokio::time::{sleep_until, Instant};
|
use tokio::time::{sleep_until, Instant};
|
||||||
use crate::prudp::socket::{ExternalConnection, SendingConnection};
|
use crate::result::ResultExtension;
|
||||||
use crate::rmc::response::ErrorCode;
|
|
||||||
use crate::rmc::structures::connection_data::ConnectionData;
|
#[derive(Error, Debug)]
|
||||||
use crate::rmc::structures::Error;
|
pub enum RemoteCallError {
|
||||||
use crate::rmc::structures::matchmake::AutoMatchmakeParam;
|
#[error("Call to remote timed out whilest waiting on response.")]
|
||||||
|
Timeout,
|
||||||
|
#[error("A server side rmc error occurred: {0:?}")]
|
||||||
|
ServerError(ErrorCode),
|
||||||
|
#[error("Connection broke")]
|
||||||
|
ConnectionBroke,
|
||||||
|
#[error("Error reading response data")]
|
||||||
|
InvalidResponse(#[from] structures::Error),
|
||||||
|
}
|
||||||
|
|
||||||
pub struct RmcConnection(pub SendingConnection, pub RmcResponseReceiver);
|
pub struct RmcConnection(pub SendingConnection, pub RmcResponseReceiver);
|
||||||
|
|
||||||
pub struct RmcResponseReceiver(Notify, Mutex<HashMap<(u32), Vec<u8>>>);
|
pub struct RmcResponseReceiver(Arc<Notify>, Arc<Mutex<HashMap<u32, RMCResponse>>>);
|
||||||
|
|
||||||
impl RmcResponseReceiver{
|
impl RmcConnection {
|
||||||
|
pub async fn make_raw_call<T: RmcSerialize>(
|
||||||
|
&self,
|
||||||
|
message: &RMCMessage,
|
||||||
|
) -> Result<T, RemoteCallError> {
|
||||||
|
self.make_raw_call_no_response(message).await?;
|
||||||
|
|
||||||
|
let data = self.1.get_response_data(message.call_id).await?;
|
||||||
|
|
||||||
|
let out = <T as RmcSerialize>::deserialize(&mut Cursor::new(data))?;
|
||||||
|
|
||||||
|
Ok(out)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn make_raw_call_no_response(
|
||||||
|
&self,
|
||||||
|
message: &RMCMessage,
|
||||||
|
) -> Result<(), RemoteCallError> {
|
||||||
|
let message_data = message.to_data();
|
||||||
|
|
||||||
|
self.0.send(message_data).await.ok_or(ConnectionBroke)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RmcResponseReceiver {
|
||||||
// returns none if timed out
|
// returns none if timed out
|
||||||
pub async fn get_response_data(&self, call_id: u32) -> Option<Vec<u8>>{
|
pub async fn get_response_data(&self, call_id: u32) -> Result<Vec<u8>, RemoteCallError> {
|
||||||
let mut end_wait_time = Instant::now();
|
let mut end_wait_time = Instant::now();
|
||||||
end_wait_time += Duration::from_secs(5);
|
end_wait_time += Duration::from_secs(5);
|
||||||
|
|
||||||
let sleep_fut = sleep_until(end_wait_time);
|
let sleep_fut = sleep_until(end_wait_time);
|
||||||
tokio::pin!(sleep_fut);
|
tokio::pin!(sleep_fut);
|
||||||
|
|
||||||
|
let mut sleep_manual_unlock_fut = Instant::now();
|
||||||
|
sleep_manual_unlock_fut += Duration::from_secs(4);
|
||||||
|
|
||||||
|
let sleep_manual_unlock_fut = sleep_until(sleep_manual_unlock_fut);
|
||||||
|
tokio::pin!(sleep_manual_unlock_fut);
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let mut locked = self.1.lock().await;
|
let mut locked = self.1.lock().await;
|
||||||
|
|
||||||
if let Some(v) = locked.remove(&call_id){
|
if let Some(v) = locked.remove(&call_id) {
|
||||||
return Some(v);
|
match v.response_result{
|
||||||
|
RMCResponseResult::Success {
|
||||||
|
data,
|
||||||
|
..
|
||||||
|
} => return Ok(data),
|
||||||
|
RMCResponseResult::Error {
|
||||||
|
error_code,
|
||||||
|
..
|
||||||
|
} => return Err(RemoteCallError::ServerError(error_code))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
drop(locked);
|
drop(locked);
|
||||||
|
|
||||||
|
|
||||||
let notif_fut = self.0.notified();
|
let notif_fut = self.0.notified();
|
||||||
|
|
||||||
|
|
||||||
tokio::select! {
|
tokio::select! {
|
||||||
|
_ = &mut sleep_manual_unlock_fut => {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
_ = &mut sleep_fut => {
|
_ = &mut sleep_fut => {
|
||||||
return None;
|
return Err(RemoteCallError::Timeout);
|
||||||
}
|
}
|
||||||
_ = notif_fut => {
|
_ = notif_fut => {
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -57,28 +118,30 @@ impl RmcResponseReceiver{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait HasRmcConnection{
|
pub trait HasRmcConnection {
|
||||||
fn get_response_receiver(&self) -> &RmcConnection;
|
fn get_connection(&self) -> &RmcConnection;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait RemoteObject{
|
pub trait RemoteObject {
|
||||||
fn new(conn: RmcConnection) -> Self;
|
fn new(conn: RmcConnection) -> Self;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RemoteObject for (){
|
impl RemoteObject for () {
|
||||||
fn new(_: RmcConnection) -> Self {}
|
fn new(_: RmcConnection) -> Self {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait RmcCallable {
|
||||||
|
|
||||||
pub trait RmcCallable{
|
|
||||||
//type Remote: RemoteObject;
|
//type Remote: RemoteObject;
|
||||||
//fn new_callable(remote: Self::Remote);
|
async fn rmc_call(
|
||||||
async fn rmc_call(&self, responder: &SendingConnection, protocol_id: u16, method_id: u32, call_id: u32, rest: Vec<u8>);
|
&self,
|
||||||
|
responder: &SendingConnection,
|
||||||
|
protocol_id: u16,
|
||||||
|
method_id: u32,
|
||||||
|
call_id: u32,
|
||||||
|
rest: Vec<u8>,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! define_rmc_proto {
|
macro_rules! define_rmc_proto {
|
||||||
(proto $name:ident{
|
(proto $name:ident{
|
||||||
|
|
@ -98,7 +161,131 @@ macro_rules! define_rmc_proto {
|
||||||
|
|
||||||
struct [<Remote $name>](crate::rmc::protocols::RmcConnection);
|
struct [<Remote $name>](crate::rmc::protocols::RmcConnection);
|
||||||
|
|
||||||
|
impl crate::rmc::protocols::RemoteInstantiatable for [<Remote $name>]{
|
||||||
|
fn new(conn: crate::rmc::protocols::RmcConnection) -> Self{
|
||||||
|
Self(conn)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl crate::rmc::protocols::HasRmcConnection for [<Remote $name>]{
|
||||||
|
fn get_connection(&self) -> &crate::rmc::protocols::RmcConnection{
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$(
|
||||||
|
impl [<Remote $protocol>] for [<Remote $name>]{}
|
||||||
|
)*
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// This is a special case to allow unit to represent the fact that no object is represented.
|
||||||
|
impl RmcCallable for () {
|
||||||
|
async fn rmc_call(
|
||||||
|
&self,
|
||||||
|
remote_response_connection: &crate::prudp::socket::SendingConnection,
|
||||||
|
protocol_id: u16,
|
||||||
|
method_id: u32,
|
||||||
|
call_id: u32,
|
||||||
|
rest: Vec<u8>,
|
||||||
|
) {
|
||||||
|
//todo: maybe reply with not implemented(?)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait RemoteInstantiatable{
|
||||||
|
fn new(conn: RmcConnection) -> Self;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct OnlyRemote<T: RemoteInstantiatable>(T);
|
||||||
|
|
||||||
|
impl<T: RemoteInstantiatable> Deref for OnlyRemote<T>{
|
||||||
|
type Target = T;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: RemoteInstantiatable> OnlyRemote<T>{
|
||||||
|
pub fn new(conn: RmcConnection) -> Self{
|
||||||
|
Self(T::new(conn))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: RemoteInstantiatable> RmcCallable for OnlyRemote<T>{
|
||||||
|
async fn rmc_call(&self, responder: &SendingConnection, protocol_id: u16, method_id: u32, call_id: u32, rest: Vec<u8>) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn handle_incoming<T: RmcCallable>(
|
||||||
|
mut connection: ExternalConnection,
|
||||||
|
remote: Arc<T>,
|
||||||
|
notify: Arc<Notify>,
|
||||||
|
incoming: Arc<Mutex<HashMap<u32, RMCResponse>>>,
|
||||||
|
) {
|
||||||
|
let sending_conn = connection.duplicate_sender();
|
||||||
|
|
||||||
|
while let Some(v) = connection.recv().await{
|
||||||
|
let Some(proto_id) = v.get(5) else {
|
||||||
|
error!("received too small rmc message.");
|
||||||
|
error!("ending rmc gateway.");
|
||||||
|
return
|
||||||
|
};
|
||||||
|
|
||||||
|
if proto_id & 0x80 == 0{
|
||||||
|
let Some(response) = RMCResponse::new(&mut Cursor::new(v)).display_err_or_some() else {
|
||||||
|
error!("ending rmc gateway.");
|
||||||
|
return
|
||||||
|
};
|
||||||
|
|
||||||
|
info!("got rmc response");
|
||||||
|
|
||||||
|
let mut locked = incoming.lock().await;
|
||||||
|
|
||||||
|
locked.insert(response.get_call_id(), response);
|
||||||
|
notify.notify_waiters();
|
||||||
|
} else {
|
||||||
|
let Some(message) = RMCMessage::new(&mut Cursor::new(v)).display_err_or_some() else {
|
||||||
|
error!("ending rmc gateway.");
|
||||||
|
return
|
||||||
|
};
|
||||||
|
|
||||||
|
info!("got rmc request");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new_rmc_gateway_connection<T: RmcCallable + Sync + Send + 'static,F>(conn: ExternalConnection, create_internal: F) -> Arc<T>
|
||||||
|
where
|
||||||
|
F: FnOnce(RmcConnection) -> T,
|
||||||
|
{
|
||||||
|
let notify = Arc::new(Notify::new());
|
||||||
|
let incoming: Arc<Mutex<HashMap<u32, RMCResponse>>> = Default::default();
|
||||||
|
|
||||||
|
let response_recv = RmcResponseReceiver(notify.clone(), incoming.clone());
|
||||||
|
|
||||||
|
let sending_conn = conn.duplicate_sender();
|
||||||
|
|
||||||
|
let rmc_conn = RmcConnection(sending_conn, response_recv);
|
||||||
|
|
||||||
|
let exposed_object = (create_internal)(rmc_conn);
|
||||||
|
|
||||||
|
let exposed_object = Arc::new(exposed_object);
|
||||||
|
|
||||||
|
{
|
||||||
|
let exposed_object = exposed_object.clone();
|
||||||
|
tokio::spawn(async move {
|
||||||
|
handle_incoming(
|
||||||
|
conn,
|
||||||
|
exposed_object,
|
||||||
|
notify,
|
||||||
|
incoming
|
||||||
|
).await;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
exposed_object
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,16 @@
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::io::{Write};
|
use std::io::{Read, Seek, Write};
|
||||||
use std::mem::transmute;
|
use std::mem::transmute;
|
||||||
use bytemuck::bytes_of;
|
use bytemuck::bytes_of;
|
||||||
|
use log::error;
|
||||||
|
use v_byte_macros::EnumTryInto;
|
||||||
|
use crate::endianness::{ReadExtensions, IS_BIG_ENDIAN};
|
||||||
use crate::prudp::packet::{PRUDPPacket};
|
use crate::prudp::packet::{PRUDPPacket};
|
||||||
use crate::prudp::packet::flags::{NEED_ACK, RELIABLE};
|
use crate::prudp::packet::flags::{NEED_ACK, RELIABLE};
|
||||||
use crate::prudp::packet::PacketOption::FragmentId;
|
use crate::prudp::packet::PacketOption::FragmentId;
|
||||||
use crate::prudp::packet::types::DATA;
|
use crate::prudp::packet::types::DATA;
|
||||||
use crate::prudp::socket::{ExternalConnection, SendingConnection};
|
use crate::prudp::socket::{ExternalConnection, SendingConnection};
|
||||||
|
use crate::rmc::response::ErrorCode::Core_Exception;
|
||||||
use crate::rmc::structures::qresult::ERROR_MASK;
|
use crate::rmc::structures::qresult::ERROR_MASK;
|
||||||
use crate::rmc::structures::RmcSerialize;
|
use crate::rmc::structures::RmcSerialize;
|
||||||
use crate::web::DirectionalData::{Incoming, Outgoing};
|
use crate::web::DirectionalData::{Incoming, Outgoing};
|
||||||
|
|
@ -30,6 +34,69 @@ pub struct RMCResponse {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RMCResponse {
|
impl RMCResponse {
|
||||||
|
pub fn new(stream: &mut (impl Seek + Read)) -> io::Result<Self>{
|
||||||
|
// ignore the size for now this will only be used for checking
|
||||||
|
let _: u32 = stream.read_struct(IS_BIG_ENDIAN)?;
|
||||||
|
|
||||||
|
let protocol_id: u8 = stream.read_struct(IS_BIG_ENDIAN)?;
|
||||||
|
|
||||||
|
/*let protocol_id: u16 = match protocol_id{
|
||||||
|
0x7F => {
|
||||||
|
stream.read_struct(IS_BIG_ENDIAN)?
|
||||||
|
},
|
||||||
|
_ => protocol_id as u16
|
||||||
|
};*/
|
||||||
|
|
||||||
|
let is_success: u8 = stream.read_struct(IS_BIG_ENDIAN)?;
|
||||||
|
|
||||||
|
let response_result = if is_success == 0x01{
|
||||||
|
let call_id: u32 = stream.read_struct(IS_BIG_ENDIAN)?;
|
||||||
|
let method_id: u32 = stream.read_struct(IS_BIG_ENDIAN)?;
|
||||||
|
let method_id = method_id & (!0x8000);
|
||||||
|
|
||||||
|
let mut data: Vec<u8> = Vec::new();
|
||||||
|
|
||||||
|
stream.read_to_end(&mut data)?;
|
||||||
|
|
||||||
|
|
||||||
|
RMCResponseResult::Success {
|
||||||
|
call_id,
|
||||||
|
method_id,
|
||||||
|
data
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let error_code: u32 = stream.read_struct(IS_BIG_ENDIAN)?;
|
||||||
|
let error_code = error_code & (!0x80000000);
|
||||||
|
let call_id: u32 = stream.read_struct(IS_BIG_ENDIAN)?;
|
||||||
|
|
||||||
|
RMCResponseResult::Error {
|
||||||
|
error_code: {
|
||||||
|
match ErrorCode::try_from(error_code){
|
||||||
|
Ok(v) => v,
|
||||||
|
Err(e) => {
|
||||||
|
error!("invalid error code {:#010x}", error_code);
|
||||||
|
Core_Exception
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
call_id,
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(Self{
|
||||||
|
protocol_id,
|
||||||
|
response_result
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_call_id(&self) -> u32{
|
||||||
|
match &self.response_result{
|
||||||
|
RMCResponseResult::Success { call_id, ..} => *call_id,
|
||||||
|
RMCResponseResult::Error { call_id, .. } => *call_id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn to_data(self) -> Vec<u8> {
|
pub fn to_data(self) -> Vec<u8> {
|
||||||
generate_response(self.protocol_id, self.response_result).expect("failed to generate response")
|
generate_response(self.protocol_id, self.response_result).expect("failed to generate response")
|
||||||
}
|
}
|
||||||
|
|
@ -120,6 +187,7 @@ pub async fn send_response(connection: &SendingConnection, rmcresponse: RMCRespo
|
||||||
//taken from kinnays error list directly
|
//taken from kinnays error list directly
|
||||||
#[allow(nonstandard_style)]
|
#[allow(nonstandard_style)]
|
||||||
#[repr(u32)]
|
#[repr(u32)]
|
||||||
|
#[derive(Debug, EnumTryInto)]
|
||||||
pub enum ErrorCode {
|
pub enum ErrorCode {
|
||||||
Core_Unknown = 0x00010001,
|
Core_Unknown = 0x00010001,
|
||||||
Core_NotImplemented = 0x00010002,
|
Core_NotImplemented = 0x00010002,
|
||||||
|
|
|
||||||
|
|
@ -2,15 +2,24 @@ use std::io::{Read, Write};
|
||||||
use crate::endianness::{IS_BIG_ENDIAN, ReadExtensions};
|
use crate::endianness::{IS_BIG_ENDIAN, ReadExtensions};
|
||||||
use super::{Result, RmcSerialize};
|
use super::{Result, RmcSerialize};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Default)]
|
||||||
pub struct Any{
|
pub struct Any{
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub data: Vec<u8>
|
pub data: Vec<u8>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RmcSerialize for Any{
|
impl RmcSerialize for Any{
|
||||||
fn serialize(&self, _writer: &mut dyn Write) -> Result<()> {
|
fn serialize(&self, writer: &mut dyn Write) -> Result<()> {
|
||||||
todo!()
|
self.name.serialize(writer)?;
|
||||||
|
|
||||||
|
let u32_len = self.data.len() as u32;
|
||||||
|
|
||||||
|
u32_len.serialize(writer)?;
|
||||||
|
u32_len.serialize(writer)?;
|
||||||
|
|
||||||
|
self.data.serialize(writer)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
fn deserialize(mut reader: &mut dyn Read) -> Result<Self> {
|
fn deserialize(mut reader: &mut dyn Read) -> Result<Self> {
|
||||||
let name = String::deserialize(reader)?;
|
let name = String::deserialize(reader)?;
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ use bytemuck::bytes_of;
|
||||||
use crate::kerberos::KerberosDateTime;
|
use crate::kerberos::KerberosDateTime;
|
||||||
use crate::rmc::structures::{rmc_struct, RmcSerialize};
|
use crate::rmc::structures::{rmc_struct, RmcSerialize};
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct ConnectionData<'a>{
|
pub struct ConnectionData<'a>{
|
||||||
pub station_url: &'a str,
|
pub station_url: &'a str,
|
||||||
pub special_protocols: Vec<u8>,
|
pub special_protocols: Vec<u8>,
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ use crate::rmc::structures::{RmcSerialize, Result};
|
||||||
|
|
||||||
pub const ERROR_MASK: u32 = 1 << 31;
|
pub const ERROR_MASK: u32 = 1 << 31;
|
||||||
|
|
||||||
#[derive(Pod, Zeroable, Copy, Clone, SwapEndian)]
|
#[derive(Pod, Zeroable, Copy, Clone, SwapEndian, Debug)]
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
pub struct QResult(u32);
|
pub struct QResult(u32);
|
||||||
|
|
||||||
|
|
|
||||||
97
src/versions.rs
Normal file
97
src/versions.rs
Normal file
|
|
@ -0,0 +1,97 @@
|
||||||
|
use std::marker::PhantomData;
|
||||||
|
use std::ops::{BitAnd, BitOr};
|
||||||
|
use typenum::{Cmp, IsEqual, IsLess, IsLessOrEqual, Unsigned, U1, U2, U3};
|
||||||
|
|
||||||
|
/// This trait represents a version at compile time
|
||||||
|
trait Version{
|
||||||
|
type Major: Unsigned;
|
||||||
|
type Minor: Unsigned;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// This struct contains nothing and is used to represent specific versions as an instance of
|
||||||
|
/// [`Version`]. It is instances as `Ver<Major, Minor>`
|
||||||
|
struct Ver<MAJ: Unsigned, MIN: Unsigned>{
|
||||||
|
_phantom: PhantomData<(MAJ, MIN)>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<MAJ: Unsigned, MIN: Unsigned> Version for Ver<MAJ, MIN>{
|
||||||
|
type Major = MAJ;
|
||||||
|
type Minor = MIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Represents two versions which can be compared
|
||||||
|
trait ComparableVersion<T: Version>: Version{
|
||||||
|
type IsAtLeast: SameOrUnit;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Version, U: Version> ComparableVersion<T> for U where
|
||||||
|
<T as Version>::Major: Cmp<Self::Major>,
|
||||||
|
<T as Version>::Minor: IsLessOrEqual<Self::Minor>,
|
||||||
|
<T as Version>::Major: IsEqual<
|
||||||
|
Self::Major,
|
||||||
|
Output: BitAnd<
|
||||||
|
typenum::LeEq<T::Minor, Self::Minor>
|
||||||
|
>,
|
||||||
|
>,
|
||||||
|
<T as Version>::Major: IsLess<
|
||||||
|
Self::Major,
|
||||||
|
Output: BitOr<
|
||||||
|
typenum::And<
|
||||||
|
typenum::Eq<T::Major, Self::Major>,
|
||||||
|
typenum::LeEq<T::Minor, Self::Minor>,
|
||||||
|
>,
|
||||||
|
Output: SameOrUnit
|
||||||
|
>
|
||||||
|
> {
|
||||||
|
|
||||||
|
type IsAtLeast = typenum::Or<
|
||||||
|
typenum::Le<T::Major, Self::Major>,
|
||||||
|
typenum::And<
|
||||||
|
typenum::Eq<T::Major, Self::Major>,
|
||||||
|
typenum::LeEq<T::Minor, Self::Minor>,
|
||||||
|
>
|
||||||
|
>;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// Simple check for testing if the `TEST` version is at least `REQ` or higher.
|
||||||
|
type VersionAbove<REQ, TEST> = <TEST as ComparableVersion<REQ>>::IsAtLeast;
|
||||||
|
|
||||||
|
trait VersionIsAtLeast<VER: Version>{}
|
||||||
|
|
||||||
|
impl<VER: Version, T: ComparableVersion<VER, IsAtLeast = typenum::True>> VersionIsAtLeast<VER> for T{}
|
||||||
|
|
||||||
|
|
||||||
|
/// Trait for containing the result of elements which only conditionally exist
|
||||||
|
trait CondElemResult{
|
||||||
|
type Output;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Empty helper struct which only servers to give a concrete type when creating fields in rmc
|
||||||
|
/// structs which have a version requirement. This is not meant to be used directly, use
|
||||||
|
/// [`MinVersion`] instead.
|
||||||
|
struct MinVersionElementHelper<T, REQUIRED: Version, VER: Version + ComparableVersion<REQUIRED>>{
|
||||||
|
_phantom: PhantomData<(T, REQUIRED, VER)>
|
||||||
|
}
|
||||||
|
|
||||||
|
/// This should be used either with [`typenum::True`] or [`typenum::False`]. When `True` the [`Self::Output`]
|
||||||
|
/// will be the same as the `T` you put into Output. When `False` it will always be `()`
|
||||||
|
trait SameOrUnit{
|
||||||
|
type Output<T>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SameOrUnit for typenum::True{
|
||||||
|
type Output<T> = T;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SameOrUnit for typenum::False{
|
||||||
|
type Output<T> = ();
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T, REQUIRED: Version, VER: Version + ComparableVersion<REQUIRED>> CondElemResult for MinVersionElementHelper<T, REQUIRED, VER> where {
|
||||||
|
type Output = <<VER as ComparableVersion<REQUIRED>>::IsAtLeast as SameOrUnit>::Output<T>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// When the version condition is met the field will exist and will simply be `T` if not it will be
|
||||||
|
/// replaced by `()`. Use this when you need to add versioning to rmc structs.
|
||||||
|
type MinVersion<T, REQUIRED, VER> = <MinVersionElementHelper<T, REQUIRED, VER> as CondElemResult>::Output;
|
||||||
Loading…
Add table
Add a link
Reference in a new issue