feat: a lot of things(i lost track)
This commit is contained in:
parent
29f3ab6348
commit
98193a58d8
42 changed files with 1207 additions and 366 deletions
54
Cargo.lock
generated
54
Cargo.lock
generated
|
|
@ -435,6 +435,12 @@ dependencies = [
|
||||||
"windows-sys 0.59.0",
|
"windows-sys 0.59.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "data-encoding"
|
||||||
|
version = "2.9.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2a2330da5de22e8a3cb63252ce2abb30116bf5265e89c0e01bc17015ce30a476"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "der"
|
name = "der"
|
||||||
version = "0.7.10"
|
version = "0.7.10"
|
||||||
|
|
@ -2239,8 +2245,10 @@ dependencies = [
|
||||||
"tokio",
|
"tokio",
|
||||||
"tokio-rustls",
|
"tokio-rustls",
|
||||||
"tokio-stream",
|
"tokio-stream",
|
||||||
|
"tokio-tungstenite",
|
||||||
"tonic",
|
"tonic",
|
||||||
"tonic-build",
|
"tonic-build",
|
||||||
|
"tungstenite",
|
||||||
"typenum",
|
"typenum",
|
||||||
"v_byte_macros",
|
"v_byte_macros",
|
||||||
]
|
]
|
||||||
|
|
@ -2428,6 +2436,17 @@ dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sha1"
|
||||||
|
version = "0.10.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"cpufeatures",
|
||||||
|
"digest",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sha2"
|
name = "sha2"
|
||||||
version = "0.10.9"
|
version = "0.10.9"
|
||||||
|
|
@ -2772,6 +2791,18 @@ dependencies = [
|
||||||
"tokio",
|
"tokio",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tokio-tungstenite"
|
||||||
|
version = "0.27.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "489a59b6730eda1b0171fcfda8b121f4bee2b35cba8645ca35c5f7ba3eb736c1"
|
||||||
|
dependencies = [
|
||||||
|
"futures-util",
|
||||||
|
"log",
|
||||||
|
"tokio",
|
||||||
|
"tungstenite",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tokio-util"
|
name = "tokio-util"
|
||||||
version = "0.7.15"
|
version = "0.7.15"
|
||||||
|
|
@ -3002,6 +3033,23 @@ version = "0.2.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b"
|
checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tungstenite"
|
||||||
|
version = "0.27.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "eadc29d668c91fcc564941132e17b28a7ceb2f3ebf0b9dae3e03fd7a6748eb0d"
|
||||||
|
dependencies = [
|
||||||
|
"bytes",
|
||||||
|
"data-encoding",
|
||||||
|
"http 1.3.1",
|
||||||
|
"httparse",
|
||||||
|
"log",
|
||||||
|
"rand 0.9.1",
|
||||||
|
"sha1",
|
||||||
|
"thiserror",
|
||||||
|
"utf-8",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "typenum"
|
name = "typenum"
|
||||||
version = "1.18.0"
|
version = "1.18.0"
|
||||||
|
|
@ -3056,6 +3104,12 @@ dependencies = [
|
||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "utf-8"
|
||||||
|
version = "0.7.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "utf8_iter"
|
name = "utf8_iter"
|
||||||
version = "1.0.4"
|
version = "1.0.4"
|
||||||
|
|
|
||||||
|
|
@ -54,6 +54,8 @@ rustls = "0.23.27"
|
||||||
rustls-pki-types = "1.12.0"
|
rustls-pki-types = "1.12.0"
|
||||||
rustls-webpki = "0.103.3"
|
rustls-webpki = "0.103.3"
|
||||||
tokio-rustls = "0.26.2"
|
tokio-rustls = "0.26.2"
|
||||||
|
tokio-tungstenite = "0.27.0"
|
||||||
|
tungstenite = "0.27.0"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -65,6 +67,7 @@ tonic-build = "0.12.3"
|
||||||
default = ["secure", "auth"]
|
default = ["secure", "auth"]
|
||||||
secure = []
|
secure = []
|
||||||
auth = []
|
auth = []
|
||||||
|
no_tls = []
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "proxy_insecure"
|
name = "proxy_insecure"
|
||||||
|
|
@ -81,4 +84,8 @@ path = "src/executables/backend_server_insecure.rs"
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "backend_server_secure"
|
name = "backend_server_secure"
|
||||||
path = "src/executables/backend_server_secure.rs"
|
path = "src/executables/backend_server_secure.rs"
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "control_server"
|
||||||
|
path = "src/executables/control_server.rs"
|
||||||
|
|
@ -2,128 +2,74 @@ mod protos;
|
||||||
|
|
||||||
extern crate proc_macro;
|
extern crate proc_macro;
|
||||||
|
|
||||||
use proc_macro2::{Ident, Literal, Span, TokenTree};
|
use crate::protos::{ProtoMethodData, RmcProtocolData};
|
||||||
use proc_macro::TokenStream;
|
use proc_macro::TokenStream;
|
||||||
use std::iter::FromIterator;
|
use proc_macro2::{Ident, Literal, Span};
|
||||||
use std::mem;
|
use quote::{quote, TokenStreamExt};
|
||||||
use syn::{parse_macro_input, DeriveInput, Data, PathSegment, TraitItem, FieldsNamed, Fields, Visibility, Type, TypePath, Path, ImplItem, ImplItemConst, Expr, ExprLit, Lit, TypeParamBound, TraitBound, TraitBoundModifier, LitInt, Token, FnArg, Receiver, PatType, Pat, TypeInfer, TypeReference, TraitItemFn, Signature, Block, Stmt, Local, LocalInit, LitStr, PathArguments, ReturnType};
|
use syn::parse::{Parse, ParseStream};
|
||||||
use quote::{quote, ToTokens, TokenStreamExt};
|
|
||||||
use syn::buffer::TokenBuffer;
|
|
||||||
use syn::parse::{Parse, ParseBuffer, ParseStream};
|
|
||||||
use syn::punctuated::Punctuated;
|
use syn::punctuated::Punctuated;
|
||||||
use syn::spanned::Spanned;
|
use syn::spanned::Spanned;
|
||||||
use syn::token::Comma;
|
use syn::{
|
||||||
use syn::Visibility::Public;
|
parse_macro_input, Attribute, Data, DataStruct, DeriveInput, Fields, FnArg, LitInt, Pat, Token,
|
||||||
use crate::protos::{ProtoMethodData, RmcProtocolData};
|
TraitItem,
|
||||||
|
};
|
||||||
|
|
||||||
fn self_referece_type() -> Type {
|
struct ProtoInputParams {
|
||||||
Type::Reference(
|
|
||||||
TypeReference {
|
|
||||||
and_token: Default::default(),
|
|
||||||
lifetime: None,
|
|
||||||
mutability: None,
|
|
||||||
elem: Box::new(Type::Path(
|
|
||||||
TypePath {
|
|
||||||
qself: None,
|
|
||||||
path: Path {
|
|
||||||
leading_colon: None,
|
|
||||||
segments: {
|
|
||||||
let mut punct = Punctuated::new();
|
|
||||||
|
|
||||||
punct.push_value(PathSegment{
|
|
||||||
ident: Ident::new("Self", Span::call_site()),
|
|
||||||
arguments: PathArguments::None
|
|
||||||
});
|
|
||||||
|
|
||||||
punct
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
))
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
struct ProtoInputParams{
|
|
||||||
proto_num: LitInt,
|
proto_num: LitInt,
|
||||||
properties: Option<(Token![,], Punctuated<Ident, Token![,]>)>
|
properties: Option<(Token![,], Punctuated<Ident, Token![,]>)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for ProtoInputParams{
|
impl Parse for ProtoInputParams {
|
||||||
fn parse(input: ParseStream) -> syn::Result<Self> {
|
fn parse(input: ParseStream) -> syn::Result<Self> {
|
||||||
let proto_num = input.parse()?;
|
let proto_num = input.parse()?;
|
||||||
|
|
||||||
if let Some(seperator) = input.parse()?{
|
if let Some(seperator) = input.parse()? {
|
||||||
let mut punctuated = Punctuated::new();
|
let mut punctuated = Punctuated::new();
|
||||||
loop {
|
loop {
|
||||||
punctuated.push_value(
|
punctuated.push_value(input.parse()?);
|
||||||
input.parse()?
|
|
||||||
);
|
|
||||||
if let Some(punct) = input.parse()? {
|
if let Some(punct) = input.parse()? {
|
||||||
punctuated.push_punct(punct);
|
punctuated.push_punct(punct);
|
||||||
} else {
|
} else {
|
||||||
return Ok(
|
return Ok(Self {
|
||||||
Self{
|
proto_num,
|
||||||
proto_num,
|
properties: Some((seperator, punctuated)),
|
||||||
properties: Some((seperator, punctuated))
|
});
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Ok(
|
Ok(Self {
|
||||||
Self{
|
proto_num,
|
||||||
proto_num,
|
properties: None,
|
||||||
properties: None
|
})
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn single_ident_path(ident: Ident) -> Path{
|
fn gen_serialize_data_struct(
|
||||||
Path{
|
s: DataStruct,
|
||||||
segments: {
|
struct_attr: Option<&Attribute>,
|
||||||
let mut punc = Punctuated::new();
|
) -> (proc_macro2::TokenStream, proc_macro2::TokenStream) {
|
||||||
punc.push(PathSegment::from(ident));
|
|
||||||
punc
|
|
||||||
},
|
|
||||||
leading_colon: None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#[proc_macro_derive(RmcSerialize, attributes(extends, rmc_struct))]
|
|
||||||
pub fn rmc_serialize(input: TokenStream) -> TokenStream {
|
|
||||||
let derive_input = parse_macro_input!(input as DeriveInput);
|
|
||||||
|
|
||||||
let struct_attr = derive_input.attrs.iter()
|
|
||||||
.find(|a| a.path().segments.len() == 1 &&
|
|
||||||
a.path().segments.first().is_some_and(|p| p.ident.to_string() == "rmc_struct"));
|
|
||||||
|
|
||||||
let Data::Struct(s) = derive_input.data else {
|
|
||||||
panic!("rmc struct type MUST be a struct");
|
|
||||||
};
|
|
||||||
|
|
||||||
// generate base data
|
|
||||||
|
|
||||||
let serialize_base_content = {
|
let serialize_base_content = {
|
||||||
let mut serialize_content = quote! {};
|
let mut serialize_content = quote! {};
|
||||||
|
|
||||||
for f in &s.fields{
|
for f in &s.fields {
|
||||||
if f.attrs.iter()
|
if f.attrs.iter().any(|a| {
|
||||||
.any(|a| a.path().segments.len() == 1 &&
|
a.path().segments.len() == 1
|
||||||
a.path().segments.first().is_some_and(|p| p.ident.to_string() == "extends")){
|
&& a.path()
|
||||||
|
.segments
|
||||||
|
.first()
|
||||||
|
.is_some_and(|p| p.ident.to_string() == "extends")
|
||||||
|
}) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let ident = f.ident.as_ref().unwrap();
|
let ident = f.ident.as_ref().unwrap();
|
||||||
|
|
||||||
serialize_content.append_all(quote!{
|
serialize_content.append_all(quote! {
|
||||||
self.#ident.serialize(writer)?;
|
self.#ident.serialize(writer)?;
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
quote!{
|
quote! {
|
||||||
#serialize_content
|
#serialize_content
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
@ -135,10 +81,10 @@ pub fn rmc_serialize(input: TokenStream) -> TokenStream {
|
||||||
for f in &s.fields {
|
for f in &s.fields {
|
||||||
let ident = f.ident.as_ref().unwrap();
|
let ident = f.ident.as_ref().unwrap();
|
||||||
|
|
||||||
structure_content.append_all(quote!{#ident, });
|
structure_content.append_all(quote! {#ident, });
|
||||||
}
|
}
|
||||||
|
|
||||||
quote!{
|
quote! {
|
||||||
Ok(Self{
|
Ok(Self{
|
||||||
#structure_content
|
#structure_content
|
||||||
})
|
})
|
||||||
|
|
@ -148,22 +94,26 @@ pub fn rmc_serialize(input: TokenStream) -> TokenStream {
|
||||||
let deserialize_base_content = {
|
let deserialize_base_content = {
|
||||||
let mut deserialize_content = quote! {};
|
let mut deserialize_content = quote! {};
|
||||||
|
|
||||||
for f in &s.fields{
|
for f in &s.fields {
|
||||||
if f.attrs.iter()
|
if f.attrs.iter().any(|a| {
|
||||||
.any(|a| a.path().segments.len() == 1 &&
|
a.path().segments.len() == 1
|
||||||
a.path().segments.first().is_some_and(|p| p.ident.to_string() == "extends")){
|
&& a.path()
|
||||||
|
.segments
|
||||||
|
.first()
|
||||||
|
.is_some_and(|p| p.ident.to_string() == "extends")
|
||||||
|
}) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
let ident = f.ident.as_ref().unwrap();
|
let ident = f.ident.as_ref().unwrap();
|
||||||
let ty = &f.ty;
|
let ty = &f.ty;
|
||||||
|
|
||||||
deserialize_content.append_all(quote!{
|
deserialize_content.append_all(quote! {
|
||||||
let #ident = <#ty> :: deserialize(reader)?;
|
let #ident = <#ty> :: deserialize(reader)?;
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
quote!{
|
quote! {
|
||||||
#deserialize_content
|
#deserialize_content
|
||||||
#struct_ctor
|
#struct_ctor
|
||||||
}
|
}
|
||||||
|
|
@ -171,15 +121,19 @@ pub fn rmc_serialize(input: TokenStream) -> TokenStream {
|
||||||
|
|
||||||
// generate base with extends stuff
|
// generate base with extends stuff
|
||||||
|
|
||||||
let serialize_base_content = if let Some(attr) = struct_attr{
|
let serialize_base_content = if let Some(attr) = struct_attr {
|
||||||
let version: Literal = attr.parse_args().expect("has to be a literal");
|
let version: Literal = attr.parse_args().expect("has to be a literal");
|
||||||
|
|
||||||
let pre_inner = if let Some(f) = s.fields.iter().find(|f| {
|
let pre_inner = if let Some(f) = s.fields.iter().find(|f| {
|
||||||
f.attrs.iter()
|
f.attrs.iter().any(|a| {
|
||||||
.any(|a| a.path().segments.len() == 1 &&
|
a.path().segments.len() == 1
|
||||||
a.path().segments.first().is_some_and(|p| p.ident.to_string() == "extends"))
|
&& a.path()
|
||||||
}){
|
.segments
|
||||||
let ident= f.ident.as_ref().unwrap();
|
.first()
|
||||||
|
.is_some_and(|p| p.ident.to_string() == "extends")
|
||||||
|
})
|
||||||
|
}) {
|
||||||
|
let ident = f.ident.as_ref().unwrap();
|
||||||
quote! {
|
quote! {
|
||||||
self.#ident.serialize(writer)?;
|
self.#ident.serialize(writer)?;
|
||||||
}
|
}
|
||||||
|
|
@ -199,16 +153,20 @@ pub fn rmc_serialize(input: TokenStream) -> TokenStream {
|
||||||
serialize_base_content
|
serialize_base_content
|
||||||
};
|
};
|
||||||
|
|
||||||
let deserialize_base_content = if let Some(attr) = struct_attr{
|
let deserialize_base_content = if let Some(attr) = struct_attr {
|
||||||
let version: Literal = attr.parse_args().expect("has to be a literal");
|
let version: Literal = attr.parse_args().expect("has to be a literal");
|
||||||
|
|
||||||
let pre_inner = if let Some(f) = s.fields.iter().find(|f| {
|
let pre_inner = if let Some(f) = s.fields.iter().find(|f| {
|
||||||
f.attrs.iter()
|
f.attrs.iter().any(|a| {
|
||||||
.any(|a| a.path().segments.len() == 1 &&
|
a.path().segments.len() == 1
|
||||||
a.path().segments.first().is_some_and(|p| p.ident.to_string() == "extends"))
|
&& a.path()
|
||||||
}){
|
.segments
|
||||||
let ident= f.ident.as_ref().unwrap();
|
.first()
|
||||||
let ty= &f.ty;
|
.is_some_and(|p| p.ident.to_string() == "extends")
|
||||||
|
})
|
||||||
|
}) {
|
||||||
|
let ident = f.ident.as_ref().unwrap();
|
||||||
|
let ty = &f.ty;
|
||||||
quote! {
|
quote! {
|
||||||
let #ident = <#ty> :: deserialize(reader)?;
|
let #ident = <#ty> :: deserialize(reader)?;
|
||||||
}
|
}
|
||||||
|
|
@ -226,6 +184,183 @@ pub fn rmc_serialize(input: TokenStream) -> TokenStream {
|
||||||
deserialize_base_content
|
deserialize_base_content
|
||||||
};
|
};
|
||||||
|
|
||||||
|
(serialize_base_content, deserialize_base_content)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[proc_macro_derive(RmcSerialize, attributes(extends, rmc_struct))]
|
||||||
|
pub fn rmc_serialize(input: TokenStream) -> TokenStream {
|
||||||
|
let derive_input = parse_macro_input!(input as DeriveInput);
|
||||||
|
|
||||||
|
let struct_attr = derive_input.attrs.iter().find(|a| {
|
||||||
|
a.path().segments.len() == 1
|
||||||
|
&& a.path()
|
||||||
|
.segments
|
||||||
|
.first()
|
||||||
|
.is_some_and(|p| p.ident.to_string() == "rmc_struct")
|
||||||
|
});
|
||||||
|
let repr_attr = derive_input.attrs.iter().find(|a| {
|
||||||
|
a.path().segments.len() == 1
|
||||||
|
&& a.path()
|
||||||
|
.segments
|
||||||
|
.first()
|
||||||
|
.is_some_and(|p| p.ident.to_string() == "repr")
|
||||||
|
});
|
||||||
|
|
||||||
|
/*let Data::Struct(s) = derive_input.data else {
|
||||||
|
panic!("rmc struct type MUST be a struct");
|
||||||
|
};*/
|
||||||
|
|
||||||
|
let (serialize_base_content, deserialize_base_content) = match derive_input.data {
|
||||||
|
Data::Struct(s) => gen_serialize_data_struct(s, struct_attr),
|
||||||
|
Data::Enum(e) => {
|
||||||
|
let Some(repr_attr) = repr_attr else {
|
||||||
|
panic!("missing repr attribute");
|
||||||
|
};
|
||||||
|
|
||||||
|
let ty: Ident = repr_attr.parse_args().unwrap();
|
||||||
|
|
||||||
|
let mut inner_match_de = quote! {};
|
||||||
|
let mut inner_match_se = quote! {};
|
||||||
|
|
||||||
|
for variant in e.variants {
|
||||||
|
let Some((_, val)) = variant.discriminant else {
|
||||||
|
panic!("missing discriminant");
|
||||||
|
};
|
||||||
|
|
||||||
|
let field_data_de = match &variant.fields {
|
||||||
|
Fields::Named(v) => {
|
||||||
|
let mut base = quote! {};
|
||||||
|
for field in v.named.iter() {
|
||||||
|
let ty = &field.ty;
|
||||||
|
let name = &field.ident;
|
||||||
|
|
||||||
|
base.append_all(quote!{
|
||||||
|
#name: <#ty as rust_nex::rmc::structures::RmcSerialize>::deserialize(reader)?,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
quote! {{#base}}
|
||||||
|
}
|
||||||
|
Fields::Unnamed(n) => {
|
||||||
|
let mut base = quote! {};
|
||||||
|
|
||||||
|
for field in n.unnamed.iter() {
|
||||||
|
let ty = &field.ty;
|
||||||
|
|
||||||
|
base.append_all(quote!{
|
||||||
|
<#ty as rust_nex::rmc::structures::RmcSerialize>::deserialize(reader)?,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
quote! {(#base)}
|
||||||
|
}
|
||||||
|
Fields::Unit => {
|
||||||
|
quote! {}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut se_with_fields = quote! {
|
||||||
|
<#ty as rust_nex::rmc::structures::RmcSerialize>::serialize(&#val, writer)?;
|
||||||
|
};
|
||||||
|
|
||||||
|
match &variant.fields {
|
||||||
|
Fields::Named(v) => {
|
||||||
|
for field in v.named.iter() {
|
||||||
|
let ty = &field.ty;
|
||||||
|
let name = &field.ident;
|
||||||
|
|
||||||
|
se_with_fields.append_all(quote!{
|
||||||
|
<#ty as rust_nex::rmc::structures::RmcSerialize>::serialize(#name ,writer)?;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Fields::Unnamed(n) => {
|
||||||
|
for (i, field) in n.unnamed.iter().enumerate() {
|
||||||
|
let ty = &field.ty;
|
||||||
|
|
||||||
|
let ident = Ident::new(&format!("val_{}", i), Span::call_site());
|
||||||
|
|
||||||
|
se_with_fields.append_all(quote!{
|
||||||
|
<#ty as rust_nex::rmc::structures::RmcSerialize>::serialize(#ident, writer)?;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Fields::Unit => {}
|
||||||
|
};
|
||||||
|
|
||||||
|
let field_match_se = match &variant.fields {
|
||||||
|
Fields::Named(v) => {
|
||||||
|
let mut base = quote! {};
|
||||||
|
|
||||||
|
for field in v.named.iter() {
|
||||||
|
let name = &field.ident;
|
||||||
|
|
||||||
|
base.append_all(quote! {
|
||||||
|
#name,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
quote! {{#base}}
|
||||||
|
}
|
||||||
|
Fields::Unnamed(n) => {
|
||||||
|
let mut base = quote! {};
|
||||||
|
|
||||||
|
for (i, _field) in n.unnamed.iter().enumerate() {
|
||||||
|
let ident = Ident::new(&format!("val_{}", i), Span::call_site());
|
||||||
|
|
||||||
|
base.append_all(quote! {
|
||||||
|
#ident,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
quote! {(#base)}
|
||||||
|
}
|
||||||
|
Fields::Unit => {
|
||||||
|
quote! {}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let name = variant.ident;
|
||||||
|
|
||||||
|
inner_match_de.append_all(quote! {
|
||||||
|
#val => Self::#name #field_data_de,
|
||||||
|
});
|
||||||
|
|
||||||
|
inner_match_se.append_all(quote! {
|
||||||
|
Self::#name #field_match_se => {
|
||||||
|
#se_with_fields
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
let serialize_base_content = quote! {
|
||||||
|
match self{
|
||||||
|
#inner_match_se
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
};
|
||||||
|
|
||||||
|
let deserialize_base_content = quote! {
|
||||||
|
let val: Self = match <#ty as rust_nex::rmc::structures::RmcSerialize>::deserialize(reader)?{
|
||||||
|
#inner_match_de
|
||||||
|
v => return Err(rust_nex::rmc::structures::Error::UnexpectedValue(v as _))
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(val)
|
||||||
|
};
|
||||||
|
|
||||||
|
(serialize_base_content, deserialize_base_content)
|
||||||
|
}
|
||||||
|
Data::Union(_) => {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// generate base data
|
||||||
|
|
||||||
let ident = derive_input.ident;
|
let ident = derive_input.ident;
|
||||||
|
|
||||||
let tokens = quote! {
|
let tokens = quote! {
|
||||||
|
|
@ -255,7 +390,7 @@ pub fn rmc_serialize(input: TokenStream) -> TokenStream {
|
||||||
/// [`macro@method_id`] attribute.
|
/// [`macro@method_id`] attribute.
|
||||||
///
|
///
|
||||||
/// You can also specify to have the protocol to be non-returning by adding a second parameter to
|
/// You can also specify to have the protocol to be non-returning by adding a second parameter to
|
||||||
/// the attribute which is just `NoReturn` e.g. ` #[rmc_proto(1, NoReturn)]`
|
/// the attribute which is just `NoReturn` e.g. `#[rmc_proto(1, NoReturn)]`
|
||||||
///
|
///
|
||||||
/// Example
|
/// Example
|
||||||
/// ```
|
/// ```
|
||||||
|
|
@ -270,34 +405,39 @@ pub fn rmc_serialize(input: TokenStream) -> TokenStream {
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
#[proc_macro_attribute]
|
#[proc_macro_attribute]
|
||||||
pub fn rmc_proto(attr: TokenStream, input: TokenStream) -> TokenStream{
|
pub fn rmc_proto(attr: TokenStream, input: TokenStream) -> TokenStream {
|
||||||
|
let params = parse_macro_input!(attr as ProtoInputParams);
|
||||||
|
|
||||||
let mut params = parse_macro_input!(attr as ProtoInputParams);
|
let ProtoInputParams {
|
||||||
|
|
||||||
let ProtoInputParams{
|
|
||||||
proto_num,
|
proto_num,
|
||||||
properties
|
properties,
|
||||||
} = params;
|
} = params;
|
||||||
|
|
||||||
let no_return_data = properties.is_some_and(|p| p.1.iter().any(|i|{
|
let no_return_data =
|
||||||
i.to_string() == "NoReturn"
|
properties.is_some_and(|p| p.1.iter().any(|i| i.to_string() == "NoReturn"));
|
||||||
}));
|
|
||||||
|
|
||||||
let mut input = parse_macro_input!(input as syn::ItemTrait);
|
let input = parse_macro_input!(input as syn::ItemTrait);
|
||||||
|
|
||||||
// gigantic ass struct initializer (to summarize this gets all of the data)
|
// gigantic ass struct initializer (to summarize this gets all of the data)
|
||||||
let raw_data = RmcProtocolData{
|
let raw_data = RmcProtocolData {
|
||||||
has_returns: !no_return_data,
|
has_returns: !no_return_data,
|
||||||
name: input.ident.clone(),
|
name: input.ident.clone(),
|
||||||
id: proto_num,
|
id: proto_num,
|
||||||
methods: input
|
methods: input
|
||||||
.items
|
.items
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|v| match v{ TraitItem::Fn(v) => Some(v), _ => None })
|
.filter_map(|v| match v {
|
||||||
.map(|func|{
|
TraitItem::Fn(v) => Some(v),
|
||||||
let Some(attr) = func.attrs.iter()
|
_ => None,
|
||||||
.find(|a| a.path().segments.last().is_some_and(|s| s.ident.to_string() == "method_id")) else {
|
})
|
||||||
panic!( "every function inside of an rmc protocol must have a method id");
|
.map(|func| {
|
||||||
|
let Some(attr) = func.attrs.iter().find(|a| {
|
||||||
|
a.path()
|
||||||
|
.segments
|
||||||
|
.last()
|
||||||
|
.is_some_and(|s| s.ident.to_string() == "method_id")
|
||||||
|
}) else {
|
||||||
|
panic!("every function inside of an rmc protocol must have a method id");
|
||||||
};
|
};
|
||||||
|
|
||||||
let Ok(id): Result<LitInt, _> = attr.parse_args() else {
|
let Ok(id): Result<LitInt, _> = attr.parse_args() else {
|
||||||
|
|
@ -314,26 +454,30 @@ pub fn rmc_proto(attr: TokenStream, input: TokenStream) -> TokenStream{
|
||||||
panic!("what");
|
panic!("what");
|
||||||
};
|
};
|
||||||
let Pat::Ident(i) = &*t.pat else {
|
let Pat::Ident(i) = &*t.pat else {
|
||||||
panic!("unable to handle non identifier patterns as parameter bindings");
|
panic!(
|
||||||
|
"unable to handle non identifier patterns as parameter bindings"
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
(i.ident.clone(), t.ty.as_ref().clone())
|
(i.ident.clone(), t.ty.as_ref().clone())
|
||||||
}).collect();
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
ProtoMethodData{
|
ProtoMethodData {
|
||||||
id,
|
id,
|
||||||
name: func.sig.ident.clone(),
|
name: func.sig.ident.clone(),
|
||||||
parameters: funcs,
|
parameters: funcs,
|
||||||
ret_val: func.sig.output.clone()
|
ret_val: func.sig.output.clone(),
|
||||||
}
|
}
|
||||||
}).collect()
|
})
|
||||||
|
.collect(),
|
||||||
};
|
};
|
||||||
|
|
||||||
quote!{
|
quote! {
|
||||||
#input
|
#input
|
||||||
#raw_data
|
#raw_data
|
||||||
}.into()
|
}
|
||||||
|
.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Used to specify the method id of methods when making rmc protocols.
|
/// Used to specify the method id of methods when making rmc protocols.
|
||||||
|
|
@ -342,25 +486,25 @@ pub fn rmc_proto(attr: TokenStream, input: TokenStream) -> TokenStream{
|
||||||
/// Note: This attribute doesn't do anything by itself and just returns the thing it was attached to
|
/// Note: This attribute doesn't do anything by itself and just returns the thing it was attached to
|
||||||
/// unchanged.
|
/// unchanged.
|
||||||
#[proc_macro_attribute]
|
#[proc_macro_attribute]
|
||||||
pub fn method_id(_attr: TokenStream, input: TokenStream) -> TokenStream{
|
pub fn method_id(_attr: TokenStream, input: TokenStream) -> TokenStream {
|
||||||
// this attribute doesnt do anything by itself, see `rmc_proto`
|
// this attribute doesnt do anything by itself, see `rmc_proto`
|
||||||
input
|
input
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#[proc_macro_attribute]
|
#[proc_macro_attribute]
|
||||||
pub fn rmc_struct(attr: TokenStream, input: TokenStream) -> TokenStream{
|
pub fn rmc_struct(attr: TokenStream, input: TokenStream) -> TokenStream {
|
||||||
let mut type_data = parse_macro_input!(input as DeriveInput);
|
let type_data = parse_macro_input!(input as DeriveInput);
|
||||||
let mut ident = parse_macro_input!(attr as syn::Path);
|
let mut ident = parse_macro_input!(attr as syn::Path);
|
||||||
let last_token = ident.segments.last_mut().expect("empty path?");
|
let last_token = ident.segments.last_mut().expect("empty path?");
|
||||||
|
|
||||||
last_token.ident = Ident::new(&("Local".to_owned() + &last_token.ident.to_string()), last_token.span());
|
last_token.ident = Ident::new(
|
||||||
|
&("Local".to_owned() + &last_token.ident.to_string()),
|
||||||
|
last_token.span(),
|
||||||
|
);
|
||||||
|
|
||||||
let struct_name = &type_data.ident;
|
let struct_name = &type_data.ident;
|
||||||
|
|
||||||
let out = quote!{
|
let out = quote! {
|
||||||
#type_data
|
#type_data
|
||||||
|
|
||||||
impl #ident for #struct_name{
|
impl #ident for #struct_name{
|
||||||
|
|
@ -378,7 +522,7 @@ pub fn rmc_struct(attr: TokenStream, input: TokenStream) -> TokenStream{
|
||||||
}
|
}
|
||||||
|
|
||||||
#[proc_macro_attribute]
|
#[proc_macro_attribute]
|
||||||
pub fn connection(_attr: TokenStream, input: TokenStream) -> TokenStream{
|
pub fn connection(_attr: TokenStream, input: TokenStream) -> TokenStream {
|
||||||
// this attribute doesnt do anything by itself, see `rmc_struct`
|
// this attribute doesnt do anything by itself, see `rmc_struct`
|
||||||
input
|
input
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
use proc_macro2::{Ident, Span, TokenStream, TokenTree};
|
use proc_macro2::{Ident, Span, TokenStream};
|
||||||
use quote::{quote, ToTokens};
|
use quote::{quote, ToTokens};
|
||||||
use syn::{LitInt, LitStr, ReturnType, Token, Type};
|
use syn::{LitInt, LitStr, ReturnType, Type};
|
||||||
use syn::token::{Brace, Bracket, Paren, Semi};
|
use syn::token::{Brace, Paren, Semi};
|
||||||
|
|
||||||
pub struct ProtoMethodData{
|
pub struct ProtoMethodData{
|
||||||
pub id: LitInt,
|
pub id: LitInt,
|
||||||
|
|
|
||||||
|
|
@ -23,9 +23,11 @@ use tokio::net::{TcpListener, TcpSocket};
|
||||||
use tokio::task;
|
use tokio::task;
|
||||||
use tokio_rustls::TlsAcceptor;
|
use tokio_rustls::TlsAcceptor;
|
||||||
use rust_nex::define_rmc_proto;
|
use rust_nex::define_rmc_proto;
|
||||||
use rust_nex::executables::common::{OWN_IP_PRIVATE, SECURE_SERVER_ACCOUNT, SERVER_PORT};
|
use rust_nex::executables::common::{RemoteController, OWN_IP_PRIVATE, SECURE_SERVER_ACCOUNT, SERVER_PORT};
|
||||||
|
use rust_nex::executables::common::ServerCluster::{Auth, Secure};
|
||||||
|
use rust_nex::executables::common::ServerType::Backend;
|
||||||
use rust_nex::nex::auth_handler::AuthHandler;
|
use rust_nex::nex::auth_handler::AuthHandler;
|
||||||
use rust_nex::rmc::protocols::new_rmc_gateway_connection;
|
use rust_nex::rmc::protocols::{new_rmc_gateway_connection, OnlyRemote};
|
||||||
use rust_nex::rmc::response::ErrorCode;
|
use rust_nex::rmc::response::ErrorCode;
|
||||||
use rust_nex::rmc::structures::RmcSerialize;
|
use rust_nex::rmc::structures::RmcSerialize;
|
||||||
use rust_nex::rnex_proxy_common::ConnectionInitData;
|
use rust_nex::rnex_proxy_common::ConnectionInitData;
|
||||||
|
|
@ -44,17 +46,21 @@ pub static SECURE_PROXY_PORT: Lazy<u16> = Lazy::new(|| {
|
||||||
.unwrap_or(10000)
|
.unwrap_or(10000)
|
||||||
});
|
});
|
||||||
|
|
||||||
static SECURE_STATION_URL: Lazy<String> = Lazy::new(|| {
|
|
||||||
format!(
|
|
||||||
"prudps:/PID=2;sid=1;stream=10;type=2;address={};port={};CID=1",
|
|
||||||
*SECURE_PROXY_ADDR, *SECURE_PROXY_PORT
|
|
||||||
)
|
|
||||||
});
|
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
setup();
|
setup();
|
||||||
|
|
||||||
|
let conn = rust_nex::reggie::rmc_connect_to(
|
||||||
|
"agmp-control.spfn.net",
|
||||||
|
Backend{
|
||||||
|
name: "agmp-auth-1.spfn.net".to_string(),
|
||||||
|
cluster: Auth
|
||||||
|
},
|
||||||
|
|r| Arc::new(OnlyRemote::<RemoteController>::new(r))
|
||||||
|
).await;
|
||||||
|
let conn = conn.unwrap();
|
||||||
|
|
||||||
|
|
||||||
let acceptor = get_configured_tls_acceptor().await;
|
let acceptor = get_configured_tls_acceptor().await;
|
||||||
|
|
||||||
let listen = TcpListener::bind(SocketAddrV4::new(*OWN_IP_PRIVATE, *SERVER_PORT)).await.unwrap();
|
let listen = TcpListener::bind(SocketAddrV4::new(*OWN_IP_PRIVATE, *SERVER_PORT)).await.unwrap();
|
||||||
|
|
@ -84,14 +90,14 @@ async fn main() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
let controller = conn.clone();
|
||||||
task::spawn(async move {
|
task::spawn(async move {
|
||||||
info!("connection to secure backend established");
|
info!("connection to secure backend established");
|
||||||
new_rmc_gateway_connection(stream.into(), |_| {
|
new_rmc_gateway_connection(stream.into(), |_| {
|
||||||
Arc::new(AuthHandler {
|
Arc::new(AuthHandler {
|
||||||
destination_server_acct: &SECURE_SERVER_ACCOUNT,
|
destination_server_acct: &SECURE_SERVER_ACCOUNT,
|
||||||
build_name: "branch:origin/project/wup-agmj build:3_8_15_2004_0",
|
build_name: "branch:origin/project/wup-agmj build:3_8_15_2004_0",
|
||||||
station_url: &SECURE_STATION_URL,
|
control_server: controller
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -8,12 +8,14 @@ use log::{error, info};
|
||||||
use tokio::net::TcpListener;
|
use tokio::net::TcpListener;
|
||||||
use tokio::task;
|
use tokio::task;
|
||||||
use rust_nex::common::setup;
|
use rust_nex::common::setup;
|
||||||
use rust_nex::executables::common::{OWN_IP_PRIVATE, SERVER_PORT};
|
use rust_nex::executables::common::{RemoteController, RemoteControllerManagement, OWN_IP_PRIVATE, SERVER_PORT};
|
||||||
|
use rust_nex::executables::common::ServerCluster::Secure;
|
||||||
|
use rust_nex::executables::common::ServerType::Backend;
|
||||||
use rust_nex::nex::matchmake::MatchmakeManager;
|
use rust_nex::nex::matchmake::MatchmakeManager;
|
||||||
use rust_nex::nex::remote_console::RemoteConsole;
|
use rust_nex::nex::remote_console::RemoteConsole;
|
||||||
use rust_nex::nex::user::User;
|
use rust_nex::nex::user::User;
|
||||||
use rust_nex::reggie::get_configured_tls_acceptor;
|
use rust_nex::reggie::get_configured_tls_acceptor;
|
||||||
use rust_nex::rmc::protocols::new_rmc_gateway_connection;
|
use rust_nex::rmc::protocols::{new_rmc_gateway_connection, OnlyRemote};
|
||||||
use rust_nex::rnex_proxy_common::ConnectionInitData;
|
use rust_nex::rnex_proxy_common::ConnectionInitData;
|
||||||
use rust_nex::rmc::protocols::RemoteInstantiatable;
|
use rust_nex::rmc::protocols::RemoteInstantiatable;
|
||||||
|
|
||||||
|
|
@ -22,6 +24,16 @@ use rust_nex::rmc::protocols::RemoteInstantiatable;
|
||||||
async fn main() {
|
async fn main() {
|
||||||
setup();
|
setup();
|
||||||
|
|
||||||
|
let conn = rust_nex::reggie::rmc_connect_to(
|
||||||
|
"agmp-control.spfn.net",
|
||||||
|
Backend{
|
||||||
|
name: "agmp-secure-1.spfn.net".to_string(),
|
||||||
|
cluster: Secure
|
||||||
|
},
|
||||||
|
|r| Arc::new(OnlyRemote::<RemoteController>::new(r))
|
||||||
|
).await;
|
||||||
|
let conn = conn.unwrap();
|
||||||
|
|
||||||
let acceptor = get_configured_tls_acceptor().await;
|
let acceptor = get_configured_tls_acceptor().await;
|
||||||
|
|
||||||
let listen = TcpListener::bind(SocketAddrV4::new(*OWN_IP_PRIVATE, *SERVER_PORT)).await.unwrap();
|
let listen = TcpListener::bind(SocketAddrV4::new(*OWN_IP_PRIVATE, *SERVER_PORT)).await.unwrap();
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,12 @@
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::net::Ipv4Addr;
|
use std::net::{Ipv4Addr, SocketAddrV4};
|
||||||
|
use macros::{method_id, rmc_proto, RmcSerialize};
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
|
use tonic::transport::Server;
|
||||||
|
use rust_nex::define_rmc_proto;
|
||||||
|
use rust_nex::prudp::station_url::StationUrl;
|
||||||
use crate::nex::account::Account;
|
use crate::nex::account::Account;
|
||||||
|
use crate::rmc::response::ErrorCode;
|
||||||
|
|
||||||
pub static OWN_IP_PRIVATE: Lazy<Ipv4Addr> = Lazy::new(|| {
|
pub static OWN_IP_PRIVATE: Lazy<Ipv4Addr> = Lazy::new(|| {
|
||||||
env::var("SERVER_IP")
|
env::var("SERVER_IP")
|
||||||
|
|
@ -10,6 +15,13 @@ pub static OWN_IP_PRIVATE: Lazy<Ipv4Addr> = Lazy::new(|| {
|
||||||
.expect("no private ip specified")
|
.expect("no private ip specified")
|
||||||
});
|
});
|
||||||
|
|
||||||
|
pub static OWN_IP_PUBLIC: Lazy<Ipv4Addr> = Lazy::new(|| {
|
||||||
|
env::var("SERVER_IP_PUBLIC")
|
||||||
|
.ok()
|
||||||
|
.and_then(|s| s.parse().ok())
|
||||||
|
.expect("no private ip specified")
|
||||||
|
});
|
||||||
|
|
||||||
pub static SERVER_PORT: Lazy<u16> = Lazy::new(|| {
|
pub static SERVER_PORT: Lazy<u16> = Lazy::new(|| {
|
||||||
env::var("SERVER_PORT")
|
env::var("SERVER_PORT")
|
||||||
.ok()
|
.ok()
|
||||||
|
|
@ -27,3 +39,52 @@ pub static AUTH_SERVER_ACCOUNT: Lazy<Account> =
|
||||||
Lazy::new(|| Account::new(1, "Quazal Authentication", &KERBEROS_SERVER_PASSWORD));
|
Lazy::new(|| Account::new(1, "Quazal Authentication", &KERBEROS_SERVER_PASSWORD));
|
||||||
pub static SECURE_SERVER_ACCOUNT: Lazy<Account> =
|
pub static SECURE_SERVER_ACCOUNT: Lazy<Account> =
|
||||||
Lazy::new(|| Account::new(2, "Quazal Rendez-Vous", &KERBEROS_SERVER_PASSWORD));
|
Lazy::new(|| Account::new(2, "Quazal Rendez-Vous", &KERBEROS_SERVER_PASSWORD));
|
||||||
|
|
||||||
|
|
||||||
|
#[rmc_proto(1)]
|
||||||
|
pub trait ProxyManagement {
|
||||||
|
#[method_id(1)]
|
||||||
|
async fn update_url(&self, url: String) -> Result<(), ErrorCode>;
|
||||||
|
}
|
||||||
|
|
||||||
|
define_rmc_proto!(
|
||||||
|
proto Proxy{
|
||||||
|
ProxyManagement
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
#[rmc_proto(2)]
|
||||||
|
pub trait ControllerManagement {
|
||||||
|
#[method_id(1)]
|
||||||
|
async fn get_secure_proxy_url(&self) -> Result<String, ErrorCode>;
|
||||||
|
|
||||||
|
#[method_id(2)]
|
||||||
|
async fn get_secure_account(&self) -> Result<Account, ErrorCode>;
|
||||||
|
}
|
||||||
|
|
||||||
|
define_rmc_proto!(
|
||||||
|
proto Controller{
|
||||||
|
ControllerManagement
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
#[derive(RmcSerialize)]
|
||||||
|
#[repr(u32)]
|
||||||
|
pub enum ServerCluster{
|
||||||
|
Auth = 0,
|
||||||
|
Secure = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(RmcSerialize)]
|
||||||
|
#[repr(u32)]
|
||||||
|
pub enum ServerType{
|
||||||
|
Proxy{
|
||||||
|
addr: SocketAddrV4,
|
||||||
|
cluster: ServerCluster
|
||||||
|
} = 1,
|
||||||
|
Backend{
|
||||||
|
name: String,
|
||||||
|
cluster: ServerCluster
|
||||||
|
} = 2,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
||||||
209
src/executables/control_server.rs
Normal file
209
src/executables/control_server.rs
Normal file
|
|
@ -0,0 +1,209 @@
|
||||||
|
use std::future::Future;
|
||||||
|
use rust_nex::rmc::protocols::{LocalNoProto, RmcCallable};
|
||||||
|
use rust_nex::rmc::structures::RmcSerialize;
|
||||||
|
use std::io::Cursor;
|
||||||
|
use std::net::{Ipv4Addr, SocketAddrV4};
|
||||||
|
use macros::rmc_struct;
|
||||||
|
use rust_nex::common::setup;
|
||||||
|
use rust_nex::executables::common::{ControllerManagement, LocalController, RemoteProxy, RemoteProxyManagement, ServerCluster, ServerType, KERBEROS_SERVER_PASSWORD};
|
||||||
|
use rust_nex::prudp::station_url::StationUrl;
|
||||||
|
use rust_nex::reggie::{get_configured_tls_acceptor, TestStruct, WebStreamSocket};
|
||||||
|
use rust_nex::rmc::protocols::{new_rmc_gateway_connection, OnlyRemote};
|
||||||
|
use rust_nex::rmc::response::ErrorCode;
|
||||||
|
use rust_nex::reggie::UnitPacketRead;
|
||||||
|
use std::sync::{Arc, Weak};
|
||||||
|
use log::error;
|
||||||
|
use once_cell::sync::Lazy;
|
||||||
|
use rand::random;
|
||||||
|
use tokio::net::TcpListener;
|
||||||
|
use tokio::sync::RwLock;
|
||||||
|
use tokio::task;
|
||||||
|
use tungstenite::client;
|
||||||
|
use rust_nex::nex::account::Account;
|
||||||
|
use rust_nex::rmc::response::ErrorCode::{Core_Exception, Core_InvalidIndex};
|
||||||
|
use rust_nex::rmc::protocols::RemoteInstantiatable;
|
||||||
|
use rust_nex::util::SendingBufferConnection;
|
||||||
|
|
||||||
|
pub static AUTH_SERVER_ACCOUNT: Lazy<Account> =
|
||||||
|
Lazy::new(|| Account::new(1, "Quazal Authentication", &KERBEROS_SERVER_PASSWORD));
|
||||||
|
pub static SECURE_SERVER_ACCOUNT: Lazy<Account> =
|
||||||
|
Lazy::new(|| Account::new(2, "Quazal Rendez-Vous", &KERBEROS_SERVER_PASSWORD));
|
||||||
|
|
||||||
|
#[rmc_struct(Controller)]
|
||||||
|
struct ServerController {
|
||||||
|
insecure_proxies: RwLock<Vec<Weak<Proxy>>>,
|
||||||
|
insecure_backend_url: RwLock<String>,
|
||||||
|
secure_proxies: RwLock<Vec<Weak<Proxy>>>,
|
||||||
|
secure_backend_url: RwLock<String>,
|
||||||
|
account: Account
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ServerController{
|
||||||
|
async fn update_urls(&self, cluster: ServerCluster){
|
||||||
|
let url = match cluster{
|
||||||
|
ServerCluster::Auth => {
|
||||||
|
self.insecure_backend_url.read().await
|
||||||
|
}
|
||||||
|
ServerCluster::Secure => {
|
||||||
|
self.secure_backend_url.read().await
|
||||||
|
}
|
||||||
|
}.clone();
|
||||||
|
|
||||||
|
let read_lock = match cluster{
|
||||||
|
ServerCluster::Auth => {
|
||||||
|
self.insecure_proxies.read().await
|
||||||
|
}
|
||||||
|
ServerCluster::Secure => {
|
||||||
|
self.secure_proxies.read().await
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
for proxy in read_lock.iter().filter_map(|v| v.upgrade()){
|
||||||
|
if let Err(e) = proxy.proxy.update_url(url.clone()).await {
|
||||||
|
error!("error whilest updating proxy url: {:?}", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Proxy{
|
||||||
|
proxy: RemoteProxy,
|
||||||
|
ip: SocketAddrV4,
|
||||||
|
controller: Arc<ServerController>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RmcCallable for Proxy{
|
||||||
|
fn rmc_call(&self, responder: &SendingBufferConnection, protocol_id: u16, method_id: u32, call_id: u32, rest: Vec<u8>) -> impl Future<Output=()> + Send {
|
||||||
|
self.controller.rmc_call(responder, protocol_id, method_id, call_id, rest)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
impl ControllerManagement for ServerController {
|
||||||
|
async fn get_secure_proxy_url(&self) -> Result<String, ErrorCode> {
|
||||||
|
let proxy = self.secure_proxies.write().await;
|
||||||
|
|
||||||
|
let proxies = proxy.iter().filter_map(|v| v.upgrade());
|
||||||
|
|
||||||
|
let idx: usize = random::<usize>() % proxy.len();
|
||||||
|
// do not switch this to using regular array indexing i specifically wrote it like this as
|
||||||
|
// to have absolutely now way of panicking, we cant have the control server panicking after
|
||||||
|
// all
|
||||||
|
let Some(proxy) = proxies.clone().nth(idx).or_else(|| proxies.clone().nth(0)) else {
|
||||||
|
return Err(Core_InvalidIndex);
|
||||||
|
};
|
||||||
|
|
||||||
|
let station_url = format!(
|
||||||
|
"prudps:/PID=2;sid=1;stream=10;type=2;address={};port={};CID=1",
|
||||||
|
proxy.ip.ip(), proxy.ip.port()
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(station_url)
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn get_secure_account(&self) -> Result<Account, ErrorCode> {
|
||||||
|
Ok(self.account.clone())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#[tokio::main]
|
||||||
|
async fn main() {
|
||||||
|
setup();
|
||||||
|
|
||||||
|
let socket = TcpListener::bind("0.0.0.0:10003").await.unwrap();
|
||||||
|
|
||||||
|
let acceptor = get_configured_tls_acceptor().await;
|
||||||
|
|
||||||
|
let server_controller = Arc::new(ServerController {
|
||||||
|
account: SECURE_SERVER_ACCOUNT.clone(),
|
||||||
|
secure_proxies: Default::default(),
|
||||||
|
secure_backend_url: Default::default(),
|
||||||
|
insecure_backend_url: Default::default(),
|
||||||
|
insecure_proxies: Default::default(),
|
||||||
|
});
|
||||||
|
|
||||||
|
while let Ok((stream, _sock_addr)) = socket.accept().await {
|
||||||
|
let websocket = tokio_tungstenite::accept_async(stream).await.unwrap();
|
||||||
|
|
||||||
|
let stream = WebStreamSocket::new(websocket);
|
||||||
|
|
||||||
|
let mut stream = acceptor.accept(stream).await.unwrap();
|
||||||
|
let server_controller = server_controller.clone();
|
||||||
|
tokio::spawn(async move {
|
||||||
|
let server_controller = server_controller;
|
||||||
|
let Ok(server_type) = stream.read_buffer().await else {
|
||||||
|
error!("failed to read server type");
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
let Ok(server_type) = ServerType::deserialize(&mut Cursor::new(server_type)) else {
|
||||||
|
error!("failed to read server type");
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
match server_type {
|
||||||
|
ServerType::Proxy{
|
||||||
|
addr,
|
||||||
|
cluster
|
||||||
|
} => {
|
||||||
|
|
||||||
|
let mut write_lock = match cluster{
|
||||||
|
ServerCluster::Auth => {
|
||||||
|
server_controller.insecure_proxies.write().await
|
||||||
|
}
|
||||||
|
ServerCluster::Secure => {
|
||||||
|
server_controller.secure_proxies.write().await
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let server_controller_internal = server_controller.clone();
|
||||||
|
|
||||||
|
let remo = new_rmc_gateway_connection(stream.into(), move |r|
|
||||||
|
Arc::new(Proxy {
|
||||||
|
proxy: RemoteProxy::new(r),
|
||||||
|
ip: addr,
|
||||||
|
controller: server_controller_internal
|
||||||
|
}));
|
||||||
|
|
||||||
|
write_lock.push(Arc::downgrade(&remo));
|
||||||
|
|
||||||
|
let url = match cluster{
|
||||||
|
ServerCluster::Auth => {
|
||||||
|
server_controller.insecure_backend_url.read().await
|
||||||
|
}
|
||||||
|
ServerCluster::Secure => {
|
||||||
|
server_controller.secure_backend_url.read().await
|
||||||
|
}
|
||||||
|
}.clone();
|
||||||
|
|
||||||
|
if let Err(e) = remo.proxy.update_url(url.clone()).await {
|
||||||
|
error!("error whilest updating proxy url: {:?}", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
ServerType::Backend{
|
||||||
|
name,
|
||||||
|
cluster
|
||||||
|
} => {
|
||||||
|
let mut url = match cluster{
|
||||||
|
ServerCluster::Auth => {
|
||||||
|
server_controller.insecure_backend_url.write().await
|
||||||
|
}
|
||||||
|
ServerCluster::Secure => {
|
||||||
|
server_controller.secure_backend_url.write().await
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
*url = name;
|
||||||
|
drop(url);
|
||||||
|
|
||||||
|
server_controller.update_urls(cluster).await;
|
||||||
|
|
||||||
|
new_rmc_gateway_connection(stream.into(), |_| server_controller);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,13 +1,17 @@
|
||||||
|
|
||||||
|
|
||||||
|
use rust_nex::executables::common::{LocalProxy, ProxyManagement, RemoteController, OWN_IP_PUBLIC};
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::ffi::CStr;
|
use std::ffi::CStr;
|
||||||
use std::io::{Read, Write};
|
use std::io::{Read, Write};
|
||||||
use std::net::{Ipv4Addr, SocketAddrV4, TcpListener, TcpStream};
|
use std::net::{Ipv4Addr, SocketAddrV4, TcpListener, TcpStream};
|
||||||
|
use std::sync::{Arc, OnceLock};
|
||||||
|
use std::time::Duration;
|
||||||
use bytemuck::{Pod, Zeroable};
|
use bytemuck::{Pod, Zeroable};
|
||||||
use chacha20::{ChaCha20, Key};
|
use chacha20::{ChaCha20, Key};
|
||||||
use chacha20::cipher::{Iv, KeyIvInit, StreamCipher};
|
use chacha20::cipher::{Iv, KeyIvInit, StreamCipher};
|
||||||
use log::error;
|
use log::{error, warn};
|
||||||
|
use macros::rmc_struct;
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
use rsa::pkcs8::{DecodePrivateKey, DecodePublicKey, Document};
|
use rsa::pkcs8::{DecodePrivateKey, DecodePublicKey, Document};
|
||||||
use rsa::{BigUint, Pkcs1v15Encrypt, RsaPrivateKey, RsaPublicKey};
|
use rsa::{BigUint, Pkcs1v15Encrypt, RsaPrivateKey, RsaPublicKey};
|
||||||
|
|
@ -16,13 +20,20 @@ use rsa::pss::BlindedSigningKey;
|
||||||
use rsa::signature::{RandomizedSigner, SignatureEncoding};
|
use rsa::signature::{RandomizedSigner, SignatureEncoding};
|
||||||
use sha2::Sha256;
|
use sha2::Sha256;
|
||||||
use tokio::net::TcpSocket;
|
use tokio::net::TcpSocket;
|
||||||
|
use tokio::sync::RwLock;
|
||||||
use tokio::task;
|
use tokio::task;
|
||||||
|
use tokio::time::sleep;
|
||||||
use rust_nex::common::setup;
|
use rust_nex::common::setup;
|
||||||
use rust_nex::executables::common::{OWN_IP_PRIVATE, SERVER_PORT};
|
use rust_nex::executables::common::{OWN_IP_PRIVATE, SERVER_PORT};
|
||||||
|
use rust_nex::executables::common::ServerCluster::Auth;
|
||||||
|
use rust_nex::executables::common::ServerType::{Backend, Proxy};
|
||||||
use rust_nex::prudp::packet::VirtualPort;
|
use rust_nex::prudp::packet::VirtualPort;
|
||||||
use rust_nex::prudp::router::Router;
|
use rust_nex::prudp::router::Router;
|
||||||
|
use rust_nex::prudp::station_url::StationUrl;
|
||||||
use rust_nex::prudp::unsecure::Unsecure;
|
use rust_nex::prudp::unsecure::Unsecure;
|
||||||
use rust_nex::reggie::{establish_tls_connection_to, UnitPacketRead, UnitPacketWrite};
|
use rust_nex::reggie::{establish_tls_connection_to, UnitPacketRead, UnitPacketWrite};
|
||||||
|
use rust_nex::rmc::protocols::OnlyRemote;
|
||||||
|
use rust_nex::rmc::response::ErrorCode;
|
||||||
use rust_nex::rmc::structures::RmcSerialize;
|
use rust_nex::rmc::structures::RmcSerialize;
|
||||||
use rust_nex::rnex_proxy_common::ConnectionInitData;
|
use rust_nex::rnex_proxy_common::ConnectionInitData;
|
||||||
|
|
||||||
|
|
@ -33,30 +44,41 @@ static FORWARD_DESTINATION: Lazy<String> =
|
||||||
static FORWARD_DESTINATION_NAME: Lazy<String> =
|
static FORWARD_DESTINATION_NAME: Lazy<String> =
|
||||||
Lazy::new(|| env::var("FORWARD_DESTINATION_NAME").expect("no forward destination name given"));
|
Lazy::new(|| env::var("FORWARD_DESTINATION_NAME").expect("no forward destination name given"));
|
||||||
|
|
||||||
static RSA_PRIVKEY: Lazy<RsaPrivateKey> = Lazy::new(|| {
|
#[rmc_struct(Proxy)]
|
||||||
let path = env::var("RSA_PRIVKEY")
|
#[derive(Default)]
|
||||||
.expect("RSA_PRIVKEY not set");
|
struct DestinationHolder{
|
||||||
|
url: RwLock<String>
|
||||||
|
}
|
||||||
|
|
||||||
RsaPrivateKey::read_pkcs8_pem_file(&path)
|
impl ProxyManagement for DestinationHolder{
|
||||||
.expect("unable to read private key")
|
async fn update_url(&self, new_url: String) -> Result<(), ErrorCode> {
|
||||||
});
|
println!("updating url");
|
||||||
|
|
||||||
static RSA_PUBKEY: Lazy<RsaPublicKey> = Lazy::new(|| {
|
let mut url = self.url.write().await;
|
||||||
RSA_PRIVKEY.to_public_key()
|
|
||||||
});
|
|
||||||
|
|
||||||
static PUBKEY_ENCODED: Lazy<Document> = Lazy::new(|| {
|
*url = new_url;
|
||||||
RSA_PUBKEY.to_pkcs1_der().expect("unable to convert pubkey to der")
|
|
||||||
});
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static RSA_SIGNKEY: Lazy<BlindedSigningKey<Sha256>> = Lazy::new(||
|
|
||||||
BlindedSigningKey::<Sha256>::new(RSA_PRIVKEY.clone())
|
|
||||||
);
|
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
setup();
|
setup();
|
||||||
|
|
||||||
|
let conn =
|
||||||
|
rust_nex::reggie::rmc_connect_to(
|
||||||
|
"agmp-control.spfn.net",
|
||||||
|
Proxy {
|
||||||
|
addr: SocketAddrV4::new(*OWN_IP_PUBLIC, *SERVER_PORT),
|
||||||
|
cluster: Auth
|
||||||
|
},
|
||||||
|
|r| Arc::new(DestinationHolder::default())
|
||||||
|
).await;
|
||||||
|
let dest_holder = conn.unwrap();
|
||||||
|
|
||||||
|
|
||||||
let (router_secure, _) = Router::new(SocketAddrV4::new(*OWN_IP_PRIVATE, *SERVER_PORT))
|
let (router_secure, _) = Router::new(SocketAddrV4::new(*OWN_IP_PRIVATE, *SERVER_PORT))
|
||||||
.await
|
.await
|
||||||
.expect("unable to start router");
|
.expect("unable to start router");
|
||||||
|
|
@ -76,9 +98,18 @@ async fn main() {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let dest_holder = dest_holder.clone();
|
||||||
|
|
||||||
task::spawn(async move {
|
task::spawn(async move {
|
||||||
|
let dest = dest_holder.url.read().await;
|
||||||
|
|
||||||
|
if *dest == ""{
|
||||||
|
warn!("no destination set yet but connection attempted");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let mut stream
|
let mut stream
|
||||||
= establish_tls_connection_to(FORWARD_DESTINATION.as_str(), FORWARD_DESTINATION_NAME.as_str()).await;
|
= establish_tls_connection_to(&dest, &dest).await;
|
||||||
|
|
||||||
if let Err(e) = stream.send_buffer(&ConnectionInitData{
|
if let Err(e) = stream.send_buffer(&ConnectionInitData{
|
||||||
prudpsock_addr: conn.socket_addr,
|
prudpsock_addr: conn.socket_addr,
|
||||||
|
|
@ -113,6 +144,9 @@ async fn main() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
_ = sleep(Duration::from_secs(10)) => {
|
||||||
|
conn.send([0,0,0,0,0].to_vec()).await;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,43 +1,65 @@
|
||||||
|
use std::net::SocketAddrV4;
|
||||||
|
use std::sync::Arc;
|
||||||
use std::env;
|
use std::time::Duration;
|
||||||
use std::ffi::CStr;
|
use futures::future::Remote;
|
||||||
use std::io::{Read, Write};
|
use log::{error, warn};
|
||||||
use std::net::{Ipv4Addr, SocketAddrV4, TcpListener, TcpStream};
|
use macros::rmc_struct;
|
||||||
use bytemuck::{Pod, Zeroable};
|
use tokio::sync::RwLock;
|
||||||
use chacha20::{ChaCha20, Key};
|
|
||||||
use chacha20::cipher::{Iv, KeyIvInit, StreamCipher};
|
|
||||||
use log::error;
|
|
||||||
use once_cell::sync::Lazy;
|
|
||||||
use rsa::pkcs8::{DecodePrivateKey, DecodePublicKey, Document};
|
|
||||||
use rsa::{BigUint, Pkcs1v15Encrypt, RsaPrivateKey, RsaPublicKey};
|
|
||||||
use rsa::pkcs1::EncodeRsaPublicKey;
|
|
||||||
use rsa::pss::BlindedSigningKey;
|
|
||||||
use rsa::signature::{RandomizedSigner, SignatureEncoding};
|
|
||||||
use sha2::Sha256;
|
|
||||||
use tokio::net::TcpSocket;
|
|
||||||
use tokio::task;
|
use tokio::task;
|
||||||
|
use tokio::time::sleep;
|
||||||
use rust_nex::common::setup;
|
use rust_nex::common::setup;
|
||||||
use rust_nex::executables::common::{OWN_IP_PRIVATE, SECURE_SERVER_ACCOUNT, SERVER_PORT};
|
use rust_nex::executables::common::{ProxyManagement, RemoteController, RemoteControllerManagement, OWN_IP_PRIVATE, OWN_IP_PUBLIC, SECURE_SERVER_ACCOUNT, SERVER_PORT};
|
||||||
|
use rust_nex::executables::common::ServerCluster::Auth;
|
||||||
|
use rust_nex::executables::common::ServerType::Proxy;
|
||||||
use rust_nex::prudp::packet::VirtualPort;
|
use rust_nex::prudp::packet::VirtualPort;
|
||||||
use rust_nex::prudp::router::Router;
|
use rust_nex::prudp::router::Router;
|
||||||
use rust_nex::prudp::secure::Secure;
|
use rust_nex::prudp::secure::Secure;
|
||||||
use rust_nex::prudp::unsecure::Unsecure;
|
use rust_nex::prudp::unsecure::Unsecure;
|
||||||
use rust_nex::reggie::{establish_tls_connection_to, UnitPacketRead, UnitPacketWrite};
|
use rust_nex::reggie::establish_tls_connection_to;
|
||||||
use rust_nex::rmc::structures::RmcSerialize;
|
use rust_nex::rmc::response::ErrorCode;
|
||||||
use rust_nex::rnex_proxy_common::ConnectionInitData;
|
use rust_nex::rnex_proxy_common::ConnectionInitData;
|
||||||
|
use rust_nex::executables::common::LocalProxy;
|
||||||
|
use rust_nex::reggie::UnitPacketWrite;
|
||||||
|
use rust_nex::rmc::structures::RmcSerialize;
|
||||||
|
use rust_nex::reggie::UnitPacketRead;
|
||||||
|
use rust_nex::rmc::protocols::RemoteInstantiatable;
|
||||||
|
|
||||||
|
#[rmc_struct(Proxy)]
|
||||||
|
struct DestinationHolder{
|
||||||
|
url: RwLock<String>,
|
||||||
|
controller: RemoteController
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ProxyManagement for DestinationHolder{
|
||||||
|
async fn update_url(&self, new_url: String) -> Result<(), ErrorCode> {
|
||||||
|
let mut url = self.url.write().await;
|
||||||
|
|
||||||
|
*url = new_url;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static FORWARD_DESTINATION: Lazy<String> =
|
|
||||||
Lazy::new(|| env::var("FORWARD_DESTINATION").expect("no forward destination given"));
|
|
||||||
static FORWARD_DESTINATION_NAME: Lazy<String> =
|
|
||||||
Lazy::new(|| env::var("FORWARD_DESTINATION_NAME").expect("no forward destination name given"));
|
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
setup();
|
setup();
|
||||||
|
|
||||||
|
let conn =
|
||||||
|
rust_nex::reggie::rmc_connect_to(
|
||||||
|
"agmp-control.spfn.net",
|
||||||
|
Proxy {
|
||||||
|
addr: SocketAddrV4::new(*OWN_IP_PUBLIC, *SERVER_PORT),
|
||||||
|
cluster: Auth
|
||||||
|
},
|
||||||
|
|r| Arc::new(DestinationHolder{
|
||||||
|
url: Default::default(),
|
||||||
|
controller: RemoteController::new(r)
|
||||||
|
})
|
||||||
|
).await;
|
||||||
|
let dest_holder = conn.unwrap();
|
||||||
|
|
||||||
|
|
||||||
let (router_secure, _) = Router::new(SocketAddrV4::new(*OWN_IP_PRIVATE, *SERVER_PORT))
|
let (router_secure, _) = Router::new(SocketAddrV4::new(*OWN_IP_PRIVATE, *SERVER_PORT))
|
||||||
.await
|
.await
|
||||||
.expect("unable to start router");
|
.expect("unable to start router");
|
||||||
|
|
@ -45,7 +67,7 @@ async fn main() {
|
||||||
let mut socket_secure = router_secure
|
let mut socket_secure = router_secure
|
||||||
.add_socket(VirtualPort::new(1, 10), Secure(
|
.add_socket(VirtualPort::new(1, 10), Secure(
|
||||||
"6f599f81",
|
"6f599f81",
|
||||||
&SECURE_SERVER_ACCOUNT
|
dest_holder.controller.get_secure_account().await.unwrap()
|
||||||
))
|
))
|
||||||
.await
|
.await
|
||||||
.expect("unable to add socket");
|
.expect("unable to add socket");
|
||||||
|
|
@ -58,9 +80,18 @@ async fn main() {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let dest_holder = dest_holder.clone();
|
||||||
|
|
||||||
task::spawn(async move {
|
task::spawn(async move {
|
||||||
|
let dest = dest_holder.url.read().await;
|
||||||
|
|
||||||
|
if *dest == ""{
|
||||||
|
warn!("no destination set yet but connection attempted");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let mut stream
|
let mut stream
|
||||||
= establish_tls_connection_to(FORWARD_DESTINATION.as_str(), FORWARD_DESTINATION_NAME.as_str()).await;
|
= establish_tls_connection_to(&dest, &dest).await;
|
||||||
|
|
||||||
if let Err(e) = stream.send_buffer(&ConnectionInitData{
|
if let Err(e) = stream.send_buffer(&ConnectionInitData{
|
||||||
prudpsock_addr: conn.socket_addr,
|
prudpsock_addr: conn.socket_addr,
|
||||||
|
|
@ -70,6 +101,8 @@ async fn main() {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
tokio::select! {
|
tokio::select! {
|
||||||
data = conn.recv() => {
|
data = conn.recv() => {
|
||||||
|
|
@ -95,6 +128,9 @@ async fn main() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
_ = sleep(Duration::from_secs(10)) => {
|
||||||
|
conn.send([0,0,0,0,0].to_vec()).await;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,23 +1,12 @@
|
||||||
use std::{env, result};
|
use std::{env, result};
|
||||||
use std::array::TryFromSliceError;
|
use std::array::TryFromSliceError;
|
||||||
use std::net::{Ipv4Addr};
|
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use json::{object, JsonValue};
|
use json::{object, JsonValue};
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
use reqwest::{Body, Method, Url};
|
use reqwest::{Body, Method, Url};
|
||||||
use reqwest::header::HeaderValue;
|
use reqwest::header::HeaderValue;
|
||||||
use rocket::serde::json::Json;
|
|
||||||
use serde::Serialize;
|
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
use tonic::metadata::{Ascii, MetadataValue};
|
|
||||||
use tonic::{Request, transport};
|
|
||||||
use tonic::codegen::InterceptedService;
|
|
||||||
use tonic::transport::Channel;
|
|
||||||
use crate::grpc::account::Error::SomethingHappened;
|
use crate::grpc::account::Error::SomethingHappened;
|
||||||
use crate::grpc::InterceptorFunc;
|
|
||||||
use crate::grpc::protobufs::account::account_client::AccountClient;
|
|
||||||
use crate::grpc::protobufs::account::{GetNexPasswordRequest, GetUserDataRequest, GetUserDataResponse};
|
|
||||||
|
|
||||||
static API_KEY: Lazy<String> = Lazy::new(||{
|
static API_KEY: Lazy<String> = Lazy::new(||{
|
||||||
let key = env::var("ACCOUNT_GQL_API_KEY")
|
let key = env::var("ACCOUNT_GQL_API_KEY")
|
||||||
.expect("no graphql ip specified");
|
.expect("no graphql ip specified");
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,11 @@
|
||||||
|
#![allow(dead_code)]
|
||||||
|
// rnex makes extensive use of async functions in public traits
|
||||||
|
// this is however fine because these traits should never(and i mean NEVER) be used dynamically
|
||||||
|
#![allow(async_fn_in_trait)]
|
||||||
|
//#![warn(missing_docs)]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
extern crate self as rust_nex;
|
extern crate self as rust_nex;
|
||||||
|
|
||||||
pub mod endianness;
|
pub mod endianness;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
#![warn(missing_docs)]
|
#![allow(async_fn_in_trait)]
|
||||||
|
//#![warn(missing_docs)]
|
||||||
|
|
||||||
//! # Splatoon RNEX server
|
//! # Splatoon RNEX server
|
||||||
//!
|
//!
|
||||||
|
|
@ -63,6 +64,7 @@ mod versions;
|
||||||
mod web;
|
mod web;
|
||||||
pub mod reggie;
|
pub mod reggie;
|
||||||
pub mod util;
|
pub mod util;
|
||||||
|
pub mod common;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,11 @@
|
||||||
|
use macros::RmcSerialize;
|
||||||
|
|
||||||
|
#[derive(RmcSerialize)]
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct Account{
|
pub struct Account{
|
||||||
pub pid: u32,
|
pub pid: u32,
|
||||||
pub username: Box<str>,
|
pub username: String,
|
||||||
pub kerbros_password: [u8; 16],
|
pub kerbros_password: [u8; 16],
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Account{
|
impl Account{
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,6 @@
|
||||||
|
use crate::executables::common::RemoteControllerManagement;
|
||||||
|
use std::sync::Arc;
|
||||||
|
use rust_nex::executables::common::RemoteController;
|
||||||
use crate::grpc::account;
|
use crate::grpc::account;
|
||||||
use crate::kerberos::{derive_key, KerberosDateTime, Ticket};
|
use crate::kerberos::{derive_key, KerberosDateTime, Ticket};
|
||||||
use crate::nex::account::Account;
|
use crate::nex::account::Account;
|
||||||
|
|
@ -7,9 +10,9 @@ use crate::rmc::response::ErrorCode::Core_Unknown;
|
||||||
use crate::rmc::structures::any::Any;
|
use crate::rmc::structures::any::Any;
|
||||||
use crate::rmc::structures::connection_data::ConnectionData;
|
use crate::rmc::structures::connection_data::ConnectionData;
|
||||||
use crate::rmc::structures::qresult::QResult;
|
use crate::rmc::structures::qresult::QResult;
|
||||||
use crate::rmc::structures::RmcSerialize;
|
use crate::{define_rmc_proto, kerberos};
|
||||||
use crate::{define_rmc_proto, kerberos, rmc};
|
|
||||||
use macros::rmc_struct;
|
use macros::rmc_struct;
|
||||||
|
use crate::rmc::protocols::OnlyRemote;
|
||||||
|
|
||||||
define_rmc_proto!(
|
define_rmc_proto!(
|
||||||
proto AuthClientProtocol{
|
proto AuthClientProtocol{
|
||||||
|
|
@ -21,7 +24,8 @@ define_rmc_proto!(
|
||||||
pub struct AuthHandler {
|
pub struct AuthHandler {
|
||||||
pub destination_server_acct: &'static Account,
|
pub destination_server_acct: &'static Account,
|
||||||
pub build_name: &'static str,
|
pub build_name: &'static str,
|
||||||
pub station_url: &'static str,
|
//pub station_url: &'static str,
|
||||||
|
pub control_server: Arc<OnlyRemote<RemoteController>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn generate_ticket(
|
pub fn generate_ticket(
|
||||||
|
|
@ -56,14 +60,14 @@ async fn get_login_data_by_pid(pid: u32) -> Option<(u32, [u8; 16])> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Auth for AuthHandler {
|
impl Auth for AuthHandler {
|
||||||
async fn login(&self, name: String) -> Result<(), ErrorCode> {
|
async fn login(&self, _name: String) -> Result<(), ErrorCode> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn login_ex(
|
async fn login_ex(
|
||||||
&self,
|
&self,
|
||||||
name: String,
|
name: String,
|
||||||
extra_data: Any,
|
_extra_data: Any,
|
||||||
) -> Result<(QResult, u32, Vec<u8>, ConnectionData, String), ErrorCode> {
|
) -> Result<(QResult, u32, Vec<u8>, ConnectionData, String), ErrorCode> {
|
||||||
let Ok(pid) = name.parse() else {
|
let Ok(pid) = name.parse() else {
|
||||||
return Err(ErrorCode::Core_InvalidArgument);
|
return Err(ErrorCode::Core_InvalidArgument);
|
||||||
|
|
@ -83,9 +87,13 @@ impl Auth for AuthHandler {
|
||||||
let ticket = generate_ticket(source_login_data, destination_login_data);
|
let ticket = generate_ticket(source_login_data, destination_login_data);
|
||||||
|
|
||||||
let result = QResult::success(Core_Unknown);
|
let result = QResult::success(Core_Unknown);
|
||||||
|
|
||||||
|
let Ok(addr) = self.control_server.get_secure_proxy_url().await else {
|
||||||
|
return Err(ErrorCode::Core_Exception);
|
||||||
|
};
|
||||||
|
|
||||||
let connection_data = ConnectionData {
|
let connection_data = ConnectionData {
|
||||||
station_url: self.station_url.to_string(),
|
station_url: addr,
|
||||||
special_station_url: "".to_string(),
|
special_station_url: "".to_string(),
|
||||||
//date_time: KerberosDateTime::new(1,1,1,1,1,1),
|
//date_time: KerberosDateTime::new(1,1,1,1,1,1),
|
||||||
date_time: KerberosDateTime::now(),
|
date_time: KerberosDateTime::now(),
|
||||||
|
|
@ -126,11 +134,11 @@ impl Auth for AuthHandler {
|
||||||
Ok((result, ticket.into()))
|
Ok((result, ticket.into()))
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_pid(&self, username: String) -> Result<u32, ErrorCode> {
|
async fn get_pid(&self, _username: String) -> Result<u32, ErrorCode> {
|
||||||
Err(ErrorCode::Core_Exception)
|
Err(ErrorCode::Core_Exception)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_name(&self, pid: u32) -> Result<String, ErrorCode> {
|
async fn get_name(&self, _pid: u32) -> Result<String, ErrorCode> {
|
||||||
Err(ErrorCode::Core_Exception)
|
Err(ErrorCode::Core_Exception)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ use std::collections::HashMap;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use std::sync::{Arc, Weak};
|
use std::sync::{Arc, Weak};
|
||||||
use std::sync::atomic::AtomicU32;
|
use std::sync::atomic::AtomicU32;
|
||||||
use std::sync::atomic::Ordering::{Relaxed, Release};
|
use std::sync::atomic::Ordering::Relaxed;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use log::info;
|
use log::info;
|
||||||
use rand::random;
|
use rand::random;
|
||||||
|
|
@ -50,7 +50,7 @@ impl MatchmakeManager{
|
||||||
async fn garbage_collect(&self){
|
async fn garbage_collect(&self){
|
||||||
info!("running rnex garbage collector over all sessions and users");
|
info!("running rnex garbage collector over all sessions and users");
|
||||||
|
|
||||||
let mut idx = 0;
|
let idx = 0;
|
||||||
|
|
||||||
let mut to_be_deleted_gids = Vec::new();
|
let mut to_be_deleted_gids = Vec::new();
|
||||||
|
|
||||||
|
|
@ -64,7 +64,7 @@ impl MatchmakeManager{
|
||||||
|
|
||||||
session_pair
|
session_pair
|
||||||
}{
|
}{
|
||||||
let mut session = session.lock().await;
|
let session = session.lock().await;
|
||||||
|
|
||||||
if !session.is_reachable(){
|
if !session.is_reachable(){
|
||||||
to_be_deleted_gids.push(gid);
|
to_be_deleted_gids.push(gid);
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,6 @@
|
||||||
use macros::rmc_struct;
|
use crate::rmc::protocols::notifications::{Notification, RawNotification, RawNotificationInfo, RemoteNotification};
|
||||||
use crate::rmc::protocols::notifications::{Notification, NotificationEvent, RawNotification, RawNotificationInfo, RemoteNotification};
|
|
||||||
use crate::rmc::protocols::nat_traversal::{NatTraversalConsole, RemoteNatTraversalConsole, RawNatTraversalConsoleInfo, RawNatTraversalConsole};
|
use crate::rmc::protocols::nat_traversal::{NatTraversalConsole, RemoteNatTraversalConsole, RawNatTraversalConsoleInfo, RawNatTraversalConsole};
|
||||||
use crate::define_rmc_proto;
|
use crate::define_rmc_proto;
|
||||||
use crate::nex::user::RemoteUserProtocol;
|
|
||||||
|
|
||||||
define_rmc_proto!(
|
define_rmc_proto!(
|
||||||
proto Console{
|
proto Console{
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,12 @@
|
||||||
use std::io::ErrorKind::HostUnreachable;
|
|
||||||
use crate::define_rmc_proto;
|
use crate::define_rmc_proto;
|
||||||
use crate::nex::matchmake::{ExtendedMatchmakeSession, MatchmakeManager};
|
use crate::nex::matchmake::{ExtendedMatchmakeSession, MatchmakeManager};
|
||||||
use crate::nex::remote_console::RemoteConsole;
|
use crate::nex::remote_console::RemoteConsole;
|
||||||
use crate::prudp::sockaddr::PRUDPSockAddr;
|
use crate::prudp::sockaddr::PRUDPSockAddr;
|
||||||
use crate::prudp::station_url::Type::{PRUDP, PRUDPS};
|
|
||||||
use crate::prudp::station_url::UrlOptions::{
|
use crate::prudp::station_url::UrlOptions::{
|
||||||
Address, NatFiltering, NatMapping, NatType, Platform, Port, PrincipalID, RVConnectionID,
|
Address, NatFiltering, NatMapping, NatType, Port, PrincipalID, RVConnectionID,
|
||||||
StreamID, PMP, UPNP,
|
|
||||||
};
|
};
|
||||||
use crate::prudp::station_url::{nat_types, StationUrl, Type};
|
use crate::prudp::station_url::{StationUrl};
|
||||||
use crate::rmc::protocols::matchmake::{
|
use crate::rmc::protocols::matchmake::{
|
||||||
Matchmake, RawMatchmake, RawMatchmakeInfo, RemoteMatchmake,
|
Matchmake, RawMatchmake, RawMatchmakeInfo, RemoteMatchmake,
|
||||||
};
|
};
|
||||||
|
|
@ -24,15 +22,12 @@ use crate::rmc::structures::matchmake::{AutoMatchmakeParam, CreateMatchmakeSessi
|
||||||
|
|
||||||
use crate::rmc::structures::qresult::QResult;
|
use crate::rmc::structures::qresult::QResult;
|
||||||
use macros::rmc_struct;
|
use macros::rmc_struct;
|
||||||
use std::net::{Ipv4Addr, SocketAddrV4};
|
|
||||||
use std::sync::{Arc, Weak};
|
use std::sync::{Arc, Weak};
|
||||||
use log::{error, info};
|
use log::info;
|
||||||
use rocket::http::ext::IntoCollection;
|
|
||||||
use tokio::sync::{Mutex, RwLock};
|
use tokio::sync::{Mutex, RwLock};
|
||||||
use tonic::Code::InvalidArgument;
|
|
||||||
use crate::prudp::station_url::nat_types::PUBLIC;
|
use crate::prudp::station_url::nat_types::PUBLIC;
|
||||||
use crate::rmc::protocols::notifications::{NotificationEvent, RemoteNotification};
|
use crate::rmc::protocols::notifications::{NotificationEvent, RemoteNotification};
|
||||||
use crate::rmc::response::ErrorCode::{Core_Exception, Core_InvalidArgument, RendezVous_AccountExpired, RendezVous_SessionVoid};
|
use crate::rmc::response::ErrorCode::{Core_Exception, Core_InvalidArgument, RendezVous_AccountExpired};
|
||||||
|
|
||||||
define_rmc_proto!(
|
define_rmc_proto!(
|
||||||
proto UserProtocol{
|
proto UserProtocol{
|
||||||
|
|
@ -129,7 +124,7 @@ impl Secure for User {
|
||||||
public_station
|
public_station
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut both = [&mut public_station, &mut private_station];
|
let both = [&mut public_station, &mut private_station];
|
||||||
|
|
||||||
for station in both {
|
for station in both {
|
||||||
station.options.retain(|v| {
|
station.options.retain(|v| {
|
||||||
|
|
@ -208,7 +203,7 @@ impl MatchmakeExtension for User {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_playing_session(&self, pids: Vec<u32>) -> Result<Vec<()>, ErrorCode> {
|
async fn get_playing_session(&self, _pids: Vec<u32>) -> Result<Vec<()>, ErrorCode> {
|
||||||
Ok(Vec::new())
|
Ok(Vec::new())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -385,7 +380,7 @@ impl MatchmakeExtension for User {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Matchmake for User {
|
impl Matchmake for User {
|
||||||
async fn unregister_gathering(&self, gid: u32) -> Result<bool, ErrorCode> {
|
async fn unregister_gathering(&self, _gid: u32) -> Result<bool, ErrorCode> {
|
||||||
Ok(true)
|
Ok(true)
|
||||||
}
|
}
|
||||||
async fn get_session_urls(&self, gid: u32) -> Result<Vec<StationUrl>, ErrorCode> {
|
async fn get_session_urls(&self, gid: u32) -> Result<Vec<StationUrl>, ErrorCode> {
|
||||||
|
|
@ -460,7 +455,7 @@ impl Matchmake for User {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn migrate_gathering_ownership(&self, gid: u32, candidates: Vec<u32>, participants_only: bool) -> Result<(), ErrorCode> {
|
async fn migrate_gathering_ownership(&self, gid: u32, candidates: Vec<u32>, _participants_only: bool) -> Result<(), ErrorCode> {
|
||||||
let session = self.matchmake_manager.get_session(gid).await?;
|
let session = self.matchmake_manager.get_session(gid).await?;
|
||||||
let mut session = session.lock().await;
|
let mut session = session.lock().await;
|
||||||
|
|
||||||
|
|
@ -522,11 +517,11 @@ impl NatTraversal for User {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn report_nat_traversal_result(&self, cid: u32, result: bool, rtt: u32) -> Result<(), ErrorCode> {
|
async fn report_nat_traversal_result(&self, _cid: u32, _result: bool, _rtt: u32) -> Result<(), ErrorCode> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn request_probe_initiation(&self, station_to_probe: String) -> Result<(), ErrorCode> {
|
async fn request_probe_initiation(&self, _station_to_probe: String) -> Result<(), ErrorCode> {
|
||||||
info!("NO!");
|
info!("NO!");
|
||||||
Err(RendezVous_AccountExpired)
|
Err(RendezVous_AccountExpired)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ use std::io::{Cursor, Read, Seek, Write};
|
||||||
use std::net::SocketAddrV4;
|
use std::net::SocketAddrV4;
|
||||||
use bytemuck::{Pod, Zeroable};
|
use bytemuck::{Pod, Zeroable};
|
||||||
use hmac::{Hmac, Mac};
|
use hmac::{Hmac, Mac};
|
||||||
use log::{error, trace, warn};
|
use log::{error, warn};
|
||||||
use md5::{Md5, Digest};
|
use md5::{Md5, Digest};
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
use v_byte_macros::{SwapEndian};
|
use v_byte_macros::{SwapEndian};
|
||||||
|
|
|
||||||
|
|
@ -5,11 +5,11 @@ use tokio::net::UdpSocket;
|
||||||
use std::net::{SocketAddr, SocketAddrV4};
|
use std::net::{SocketAddr, SocketAddrV4};
|
||||||
use std::net::SocketAddr::V4;
|
use std::net::SocketAddr::V4;
|
||||||
use std::sync::{Arc, Weak};
|
use std::sync::{Arc, Weak};
|
||||||
use std::sync::atomic::{AtomicBool, Ordering};
|
use std::sync::atomic::{AtomicBool};
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use tokio::task::JoinHandle;
|
use tokio::task::JoinHandle;
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
use log::{error, info, trace};
|
use log::{error, info};
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
use tokio::select;
|
use tokio::select;
|
||||||
use tokio::sync::RwLock;
|
use tokio::sync::RwLock;
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,6 @@ use crate::kerberos::{derive_key, TicketInternalData};
|
||||||
use crate::nex::account::Account;
|
use crate::nex::account::Account;
|
||||||
use crate::prudp::packet::PRUDPV1Packet;
|
use crate::prudp::packet::PRUDPV1Packet;
|
||||||
use crate::prudp::socket::{CryptoHandler, CryptoHandlerConnectionInstance, EncryptionPair};
|
use crate::prudp::socket::{CryptoHandler, CryptoHandlerConnectionInstance, EncryptionPair};
|
||||||
use crate::prudp::unsecure::UnsecureInstance;
|
|
||||||
use crate::rmc::structures::RmcSerialize;
|
use crate::rmc::structures::RmcSerialize;
|
||||||
|
|
||||||
pub fn read_secure_connection_data(data: &[u8], act: &Account) -> Option<([u8; 32], u32, u32)>{
|
pub fn read_secure_connection_data(data: &[u8], act: &Account) -> Option<([u8; 32], u32, u32)>{
|
||||||
|
|
@ -103,7 +102,7 @@ pub fn generate_secure_encryption_pairs(mut session_key: [u8; 32], count: u8) ->
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub struct Secure(pub &'static str, pub &'static Account);
|
pub struct Secure(pub &'static str, pub Account);
|
||||||
|
|
||||||
|
|
||||||
pub struct SecureInstance {
|
pub struct SecureInstance {
|
||||||
|
|
@ -186,7 +185,7 @@ impl CryptoHandlerConnectionInstance for SecureInstance {
|
||||||
packet.calculate_and_assign_signature(self.access_key, Some(self.session_key), Some(self.self_signature));
|
packet.calculate_and_assign_signature(self.access_key, Some(self.session_key), Some(self.self_signature));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn verify_packet(&self, packet: &PRUDPV1Packet) -> bool {
|
fn verify_packet(&self, _packet: &PRUDPV1Packet) -> bool {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,37 +1,24 @@
|
||||||
use crate::nex::account::Account;
|
|
||||||
use crate::prudp::packet::flags::{ACK, HAS_SIZE, MULTI_ACK, NEED_ACK, RELIABLE};
|
use crate::prudp::packet::flags::{ACK, HAS_SIZE, MULTI_ACK, NEED_ACK, RELIABLE};
|
||||||
use crate::prudp::packet::types::{CONNECT, DATA, DISCONNECT, PING, SYN};
|
use crate::prudp::packet::types::{CONNECT, DATA, DISCONNECT, PING, SYN};
|
||||||
use crate::prudp::packet::PacketOption::{
|
use crate::prudp::packet::PacketOption::{
|
||||||
ConnectionSignature, FragmentId, InitialSequenceId, MaximumSubstreamId, SupportedFunctions,
|
ConnectionSignature, FragmentId, MaximumSubstreamId, SupportedFunctions,
|
||||||
};
|
};
|
||||||
use crate::prudp::packet::{PRUDPV1Header, PRUDPV1Packet, PacketOption, TypesFlags, VirtualPort};
|
use crate::prudp::packet::{PRUDPV1Header, PRUDPV1Packet, TypesFlags, VirtualPort};
|
||||||
use crate::prudp::router::{Error, Router};
|
|
||||||
use crate::prudp::sockaddr::PRUDPSockAddr;
|
use crate::prudp::sockaddr::PRUDPSockAddr;
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use chrono::NaiveTime;
|
|
||||||
use hmac::digest::consts::U5;
|
|
||||||
use log::info;
|
use log::info;
|
||||||
use log::{error, trace, warn};
|
use log::error;
|
||||||
use once_cell::sync::Lazy;
|
use rc4::StreamCipher;
|
||||||
use rand::random;
|
use std::collections::{BTreeMap, HashMap};
|
||||||
use rc4::{Key, KeyInit, Rc4, StreamCipher};
|
|
||||||
use rocket::http::hyper::body::HttpBody;
|
|
||||||
use std::collections::{BTreeMap, HashMap, VecDeque};
|
|
||||||
use std::fmt::{Debug, Formatter};
|
|
||||||
use std::future::Future;
|
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use std::mem;
|
|
||||||
use std::net::SocketAddrV4;
|
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
use std::pin::Pin;
|
|
||||||
use std::sync::{Arc, Weak};
|
use std::sync::{Arc, Weak};
|
||||||
|
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use tokio::net::UdpSocket;
|
use tokio::net::UdpSocket;
|
||||||
use tokio::sync::mpsc::{channel, Receiver, Sender};
|
use tokio::sync::mpsc::{channel, Receiver, Sender};
|
||||||
use tokio::sync::{Mutex, RwLock};
|
use tokio::sync::Mutex;
|
||||||
use tokio::time::{sleep, Instant};
|
use tokio::time::{sleep, Instant};
|
||||||
use tokio_stream::Stream;
|
|
||||||
// due to the way this is designed crashing the router thread causes deadlock, sorry ;-;
|
// due to the way this is designed crashing the router thread causes deadlock, sorry ;-;
|
||||||
// (maybe i will fix that some day)
|
// (maybe i will fix that some day)
|
||||||
|
|
||||||
|
|
@ -479,7 +466,7 @@ impl<T: CryptoHandler> InternalSocket<T> {
|
||||||
self.send_packet_unbuffered(address, response).await;
|
self.send_packet_unbuffered(address, response).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn handle_data(&self, address: PRUDPSockAddr, mut packet: PRUDPV1Packet) {
|
async fn handle_data(&self, address: PRUDPSockAddr, packet: PRUDPV1Packet) {
|
||||||
info!("got data");
|
info!("got data");
|
||||||
|
|
||||||
if packet.header.types_and_flags.get_flags() & (NEED_ACK | RELIABLE)
|
if packet.header.types_and_flags.get_flags() & (NEED_ACK | RELIABLE)
|
||||||
|
|
@ -533,7 +520,7 @@ impl<T: CryptoHandler> InternalSocket<T> {
|
||||||
let conn = conn.clone();
|
let conn = conn.clone();
|
||||||
drop(connections);
|
drop(connections);
|
||||||
|
|
||||||
let mut conn = conn.lock().await;
|
let conn = conn.lock().await;
|
||||||
|
|
||||||
let mut response = packet.base_acknowledgement_packet();
|
let mut response = packet.base_acknowledgement_packet();
|
||||||
response.header.types_and_flags.set_flag(HAS_SIZE | ACK);
|
response.header.types_and_flags.set_flag(HAS_SIZE | ACK);
|
||||||
|
|
@ -553,7 +540,7 @@ impl<T: CryptoHandler> InternalSocket<T> {
|
||||||
let conn = conn.clone();
|
let conn = conn.clone();
|
||||||
drop(connections);
|
drop(connections);
|
||||||
|
|
||||||
let mut conn = conn.lock().await;
|
let conn = conn.lock().await;
|
||||||
|
|
||||||
let mut response = packet.base_acknowledgement_packet();
|
let mut response = packet.base_acknowledgement_packet();
|
||||||
response.header.types_and_flags.set_flag(HAS_SIZE | ACK);
|
response.header.types_and_flags.set_flag(HAS_SIZE | ACK);
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,6 @@ use std::net::Ipv4Addr;
|
||||||
use log::error;
|
use log::error;
|
||||||
use std::fmt::{Debug, Display, Formatter, Write};
|
use std::fmt::{Debug, Display, Formatter, Write};
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
use rocket::delete;
|
|
||||||
use crate::prudp::station_url::Type::{PRUDP, PRUDPS, UDP};
|
use crate::prudp::station_url::Type::{PRUDP, PRUDPS, UDP};
|
||||||
use crate::prudp::station_url::UrlOptions::{Address, ConnectionID, NatFiltering, NatMapping, NatType, Platform, PMP, Port, PrincipalID, RVConnectionID, StreamID, StreamType, UPNP, PID};
|
use crate::prudp::station_url::UrlOptions::{Address, ConnectionID, NatFiltering, NatMapping, NatType, Platform, PMP, Port, PrincipalID, RVConnectionID, StreamID, StreamType, UPNP, PID};
|
||||||
use crate::rmc::structures::Error::StationUrlInvalid;
|
use crate::rmc::structures::Error::StationUrlInvalid;
|
||||||
|
|
|
||||||
228
src/reggie.rs
228
src/reggie.rs
|
|
@ -1,18 +1,26 @@
|
||||||
use std::{env, fs, io};
|
use std::{env, fs, io};
|
||||||
|
use std::io::{Error, ErrorKind};
|
||||||
|
use std::pin::Pin;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
use std::task::{Context, Poll};
|
||||||
|
use futures::{SinkExt, StreamExt};
|
||||||
use macros::{method_id, rmc_proto, rmc_struct};
|
use macros::{method_id, rmc_proto, rmc_struct};
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
use rustls::{ClientConfig, RootCertStore, ServerConfig};
|
use rustls::{ClientConfig, RootCertStore, ServerConfig};
|
||||||
use rustls::client::WebPkiServerVerifier;
|
use rustls::client::WebPkiServerVerifier;
|
||||||
use rustls::server::WebPkiClientVerifier;
|
use rustls::server::WebPkiClientVerifier;
|
||||||
use rustls_pki_types::{CertificateDer, PrivateKeyDer, ServerName, TrustAnchor};
|
use rustls_pki_types::{CertificateDer, PrivateKeyDer, ServerName, TrustAnchor};
|
||||||
use tokio::io::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt};
|
use thiserror::Error;
|
||||||
use tokio::net::TcpStream;
|
use tokio::io::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt, ReadBuf};
|
||||||
|
use tokio::net::{TcpListener, TcpStream};
|
||||||
use tokio_rustls::{TlsAcceptor, TlsConnector};
|
use tokio_rustls::{TlsAcceptor, TlsConnector};
|
||||||
use tokio_rustls::client::TlsStream;
|
use tokio_rustls::client::TlsStream;
|
||||||
|
use tokio_tungstenite::{connect_async, WebSocketStream};
|
||||||
|
use tokio_tungstenite::tungstenite::Message;
|
||||||
use webpki::anchor_from_trusted_cert;
|
use webpki::anchor_from_trusted_cert;
|
||||||
|
use rust_nex::common::setup;
|
||||||
use crate::define_rmc_proto;
|
use crate::define_rmc_proto;
|
||||||
use crate::endianness::IS_BIG_ENDIAN;
|
use crate::rmc::protocols::{new_rmc_gateway_connection, OnlyRemote, RmcCallable, RmcConnection};
|
||||||
use crate::rmc::response::ErrorCode;
|
use crate::rmc::response::ErrorCode;
|
||||||
use crate::rmc::structures::RmcSerialize;
|
use crate::rmc::structures::RmcSerialize;
|
||||||
|
|
||||||
|
|
@ -116,12 +124,12 @@ pub trait UnitPacketWrite: AsyncWrite + Unpin{
|
||||||
|
|
||||||
impl<T: AsyncWrite + Unpin> UnitPacketWrite for T{}
|
impl<T: AsyncWrite + Unpin> UnitPacketWrite for T{}
|
||||||
|
|
||||||
pub async fn establish_tls_connection_to(address: &str, server_name: &'static str) -> TlsStream<TcpStream>{
|
pub async fn establish_tls_connection_to(address: &str, server_name: &str) -> TlsStream<TcpStream>{
|
||||||
let connector = get_configured_tls_connector().await;
|
let connector = get_configured_tls_connector().await;
|
||||||
|
|
||||||
let stream = TcpStream::connect(address).await.unwrap();
|
let stream = TcpStream::connect(address).await.unwrap();
|
||||||
|
|
||||||
let stream = connector.connect(ServerName::try_from(server_name).unwrap(), stream).await
|
let stream = connector.connect(ServerName::try_from(server_name.to_owned()).unwrap(), stream).await
|
||||||
.expect("unable to connect via tls");
|
.expect("unable to connect via tls");
|
||||||
|
|
||||||
stream
|
stream
|
||||||
|
|
@ -147,3 +155,213 @@ impl RmcTestProto for TestStruct{
|
||||||
Ok("heya".into())
|
Ok("heya".into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pub struct WebStreamSocket<T: AsyncRead + AsyncWrite + Unpin> {
|
||||||
|
socket: WebSocketStream<T>,
|
||||||
|
incoming_buffer: Vec<u8>,
|
||||||
|
finished_reading: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: AsyncRead + AsyncWrite + Unpin> WebStreamSocket<T> {
|
||||||
|
pub fn new(socket: WebSocketStream<T>) -> Self{
|
||||||
|
Self{
|
||||||
|
incoming_buffer: Default::default(),
|
||||||
|
socket,
|
||||||
|
finished_reading: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: AsyncRead + AsyncWrite + Unpin> AsyncWrite for WebStreamSocket<T> {
|
||||||
|
fn poll_write(self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &[u8]) -> Poll<Result<usize, Error>> {
|
||||||
|
let this = &mut self.get_mut().socket;
|
||||||
|
|
||||||
|
let msg = Message::binary(buf.to_vec());
|
||||||
|
|
||||||
|
match this.poll_ready_unpin(cx) {
|
||||||
|
Poll::Pending => return Poll::Pending,
|
||||||
|
Poll::Ready(Err(e)) => return Poll::Ready(Err(Error::new(ErrorKind::Other, e))),
|
||||||
|
Poll::Ready(Ok(())) => {
|
||||||
|
// continue on
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let Err(e) = this.start_send_unpin(msg) else {
|
||||||
|
return Poll::Ready(Ok(buf.len()));
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Poll::Ready(Err(Error::new(ErrorKind::Other, e)))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Error>> {
|
||||||
|
let this = &mut self.get_mut().socket;
|
||||||
|
|
||||||
|
match this.poll_flush_unpin(cx) {
|
||||||
|
Poll::Pending => Poll::Pending,
|
||||||
|
Poll::Ready(Err(e)) => Poll::Ready(Err(Error::new(ErrorKind::Other, e))),
|
||||||
|
Poll::Ready(Ok(())) => Poll::Ready(Ok(()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn poll_shutdown(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Error>> {
|
||||||
|
let this = &mut self.get_mut().socket;
|
||||||
|
|
||||||
|
match this.poll_close_unpin(cx) {
|
||||||
|
Poll::Pending => Poll::Pending,
|
||||||
|
Poll::Ready(Err(e)) => Poll::Ready(Err(Error::new(ErrorKind::Other, e))),
|
||||||
|
Poll::Ready(Ok(())) => Poll::Ready(Ok(()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: AsyncRead + AsyncWrite + Unpin> AsyncRead for WebStreamSocket<T> {
|
||||||
|
fn poll_read(self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &mut ReadBuf<'_>) -> Poll<io::Result<()>> {
|
||||||
|
let Self {
|
||||||
|
incoming_buffer,
|
||||||
|
socket,
|
||||||
|
finished_reading
|
||||||
|
} = &mut self.get_mut();
|
||||||
|
|
||||||
|
if !*finished_reading {
|
||||||
|
match socket.poll_next_unpin(cx) {
|
||||||
|
Poll::Ready(Some(Ok(msg))) => {
|
||||||
|
let Message::Binary(data) = msg else {
|
||||||
|
return Poll::Ready(Err(Error::new(ErrorKind::InvalidData, "got non binary data when trying to emulate stream")));
|
||||||
|
};
|
||||||
|
|
||||||
|
incoming_buffer.extend_from_slice(&data);
|
||||||
|
}
|
||||||
|
Poll::Ready(Some(Err(e))) if incoming_buffer.is_empty() => {
|
||||||
|
return Poll::Ready(Err(Error::new(ErrorKind::Other, e)));
|
||||||
|
}
|
||||||
|
Poll::Ready(None) if incoming_buffer.is_empty() => {
|
||||||
|
*finished_reading = true;
|
||||||
|
}
|
||||||
|
Poll::Pending if incoming_buffer.is_empty() => {
|
||||||
|
return Poll::Pending
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if !incoming_buffer.is_empty(){
|
||||||
|
let read_ammount = buf.remaining();
|
||||||
|
|
||||||
|
let ammount_taken = read_ammount.min(incoming_buffer.len());
|
||||||
|
|
||||||
|
buf.put_slice(&incoming_buffer[0..ammount_taken]);
|
||||||
|
|
||||||
|
*incoming_buffer = (&incoming_buffer.get(ammount_taken..).unwrap_or(&[])).to_vec();
|
||||||
|
}
|
||||||
|
|
||||||
|
Poll::Ready(Ok(()))
|
||||||
|
|
||||||
|
|
||||||
|
/*if buf.remaining() == 0{
|
||||||
|
|
||||||
|
|
||||||
|
return Poll::Ready(Ok(()));
|
||||||
|
}
|
||||||
|
|
||||||
|
match socket.poll_next_unpin(cx) {
|
||||||
|
Poll::Ready(Some(Ok(msg))) => {
|
||||||
|
let Message::Binary(data) = msg else {
|
||||||
|
return Poll::Ready(Err(Error::new(ErrorKind::InvalidData, "got non binary data when trying to emulate stream")));
|
||||||
|
};
|
||||||
|
|
||||||
|
if data.len() <= buf.remaining() {
|
||||||
|
// if no data remains there is no reason to store anything
|
||||||
|
buf.put_slice(&data);
|
||||||
|
} else {
|
||||||
|
let read_ammount = buf.remaining();
|
||||||
|
|
||||||
|
let ammount_taken = read_ammount.min(data.len());
|
||||||
|
|
||||||
|
buf.put_slice(&data[..ammount_taken]);
|
||||||
|
|
||||||
|
*incoming_buffer = data[ammount_taken..].to_vec();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Poll::Ready(Ok(()))
|
||||||
|
}
|
||||||
|
Poll::Ready(Some(Err(e))) => Poll::Ready(Err(Error::new(ErrorKind::Other, e))),
|
||||||
|
// EOF
|
||||||
|
Poll::Ready(None) => Poll::Ready(Ok(())),
|
||||||
|
Poll::Pending => Poll::Pending
|
||||||
|
}*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Error, Debug)]
|
||||||
|
pub enum ConnectError{
|
||||||
|
#[error(transparent)]
|
||||||
|
Tungstenite(#[from] tungstenite::error::Error),
|
||||||
|
#[error(transparent)]
|
||||||
|
DataSendError(#[from] io::Error),
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn rmc_connect_to<T: RmcCallable + Sync + Send + 'static, U: RmcSerialize, F>(url: &str, init_data: U, create_func: F) -> Result<Arc<T>, ConnectError>
|
||||||
|
where
|
||||||
|
F: FnOnce(RmcConnection) -> Arc<T>{
|
||||||
|
let (stream, _)= connect_async(format!("ws://{}/", url)).await?;
|
||||||
|
|
||||||
|
let webstreamsocket = WebStreamSocket::new(stream);
|
||||||
|
|
||||||
|
let connector = get_configured_tls_connector().await;
|
||||||
|
|
||||||
|
let mut connection = connector.connect(ServerName::try_from(url.to_string()).unwrap(), webstreamsocket).await.unwrap();
|
||||||
|
|
||||||
|
connection.send_buffer(&init_data.to_data()).await?;
|
||||||
|
|
||||||
|
let rmc = new_rmc_gateway_connection(connection.into(), create_func);
|
||||||
|
|
||||||
|
Ok(rmc)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test(){
|
||||||
|
setup();
|
||||||
|
|
||||||
|
let socket = connect_async("ws://192.168.178.120:12345/").await;
|
||||||
|
let (stream, resp) = socket.unwrap();
|
||||||
|
|
||||||
|
let mut webstreamsocket = WebStreamSocket::new(stream);
|
||||||
|
|
||||||
|
let connector = get_configured_tls_connector().await;
|
||||||
|
|
||||||
|
let connection = connector.connect(ServerName::try_from("agmp-tv.spfn.net").unwrap(), webstreamsocket).await.unwrap();
|
||||||
|
|
||||||
|
let rmc = new_rmc_gateway_connection(connection.into(), |r| {
|
||||||
|
Arc::new(OnlyRemote::<RemoteTestProto>::new(r))
|
||||||
|
});
|
||||||
|
|
||||||
|
println!("{:?}", rmc.test().await);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_server(){
|
||||||
|
setup();
|
||||||
|
|
||||||
|
let socket = TcpListener::bind("192.168.178.120:12345").await.unwrap();
|
||||||
|
|
||||||
|
let acceptor = get_configured_tls_acceptor().await;
|
||||||
|
|
||||||
|
while let Ok((stream, _sock_addr)) = socket.accept().await{
|
||||||
|
let websocket = tokio_tungstenite::accept_async(stream).await.unwrap();
|
||||||
|
|
||||||
|
let webstreamsocket = WebStreamSocket::new(websocket);
|
||||||
|
|
||||||
|
let stream = acceptor.accept(webstreamsocket).await.unwrap();
|
||||||
|
|
||||||
|
new_rmc_gateway_connection(stream.into(), |_| {
|
||||||
|
Arc::new(
|
||||||
|
TestStruct
|
||||||
|
)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
use macros::{method_id, rmc_proto};
|
use macros::{method_id, rmc_proto};
|
||||||
use crate::prudp::station_url::StationUrl;
|
|
||||||
use crate::rmc::response::ErrorCode;
|
use crate::rmc::response::ErrorCode;
|
||||||
|
|
||||||
#[rmc_proto(50)]
|
#[rmc_proto(50)]
|
||||||
|
|
|
||||||
|
|
@ -10,28 +10,21 @@ pub mod matchmake_ext;
|
||||||
pub mod ranking;
|
pub mod ranking;
|
||||||
|
|
||||||
use crate::util::{SendingBufferConnection, SplittableBufferConnection};
|
use crate::util::{SendingBufferConnection, SplittableBufferConnection};
|
||||||
use crate::prudp::socket::{ExternalConnection, SendingConnection};
|
|
||||||
use crate::rmc::message::RMCMessage;
|
use crate::rmc::message::RMCMessage;
|
||||||
use crate::rmc::protocols::RemoteCallError::ConnectionBroke;
|
use crate::rmc::protocols::RemoteCallError::ConnectionBroke;
|
||||||
use crate::rmc::response::{ErrorCode, RMCResponse, RMCResponseResult};
|
use crate::rmc::response::{ErrorCode, RMCResponse, RMCResponseResult};
|
||||||
use crate::rmc::structures;
|
use crate::rmc::structures;
|
||||||
use crate::rmc::structures::connection_data::ConnectionData;
|
use crate::rmc::structures::RmcSerialize;
|
||||||
use crate::rmc::structures::matchmake::AutoMatchmakeParam;
|
|
||||||
use crate::rmc::structures::{Error, RmcSerialize};
|
|
||||||
use async_trait::async_trait;
|
|
||||||
use chrono::TimeDelta;
|
|
||||||
use log::{error, info};
|
use log::{error, info};
|
||||||
use macros::method_id;
|
|
||||||
use macros::{rmc_proto, rmc_struct};
|
|
||||||
use paste::paste;
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
use std::future::Future;
|
||||||
use std::io::Cursor;
|
use std::io::Cursor;
|
||||||
use std::ops::{Add, Deref};
|
use std::ops::Deref;
|
||||||
use std::sync::{Arc, Condvar};
|
use std::sync::Arc;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
use tokio::sync::{Mutex, Notify};
|
use tokio::sync::{Mutex, Notify};
|
||||||
use tokio::time::{sleep_until, Instant};
|
use tokio::time::{sleep, sleep_until, Instant};
|
||||||
use crate::result::ResultExtension;
|
use crate::result::ResultExtension;
|
||||||
|
|
||||||
#[derive(Error, Debug)]
|
#[derive(Error, Debug)]
|
||||||
|
|
@ -74,6 +67,10 @@ impl RmcConnection {
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn disconnect(&self){
|
||||||
|
self.0.disconnect().await;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RmcResponseReceiver {
|
impl RmcResponseReceiver {
|
||||||
|
|
@ -173,6 +170,9 @@ macro_rules! define_rmc_proto {
|
||||||
fn new(conn: rust_nex::rmc::protocols::RmcConnection) -> Self{
|
fn new(conn: rust_nex::rmc::protocols::RmcConnection) -> Self{
|
||||||
Self(conn)
|
Self(conn)
|
||||||
}
|
}
|
||||||
|
async fn disconnect(&self){
|
||||||
|
self.0.disconnect().await;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl rust_nex::rmc::protocols::HasRmcConnection for [<Remote $name>]{
|
impl rust_nex::rmc::protocols::HasRmcConnection for [<Remote $name>]{
|
||||||
|
|
@ -192,11 +192,11 @@ macro_rules! define_rmc_proto {
|
||||||
impl RmcCallable for () {
|
impl RmcCallable for () {
|
||||||
async fn rmc_call(
|
async fn rmc_call(
|
||||||
&self,
|
&self,
|
||||||
remote_response_connection: &SendingBufferConnection,
|
_remote_response_connection: &SendingBufferConnection,
|
||||||
protocol_id: u16,
|
_protocol_id: u16,
|
||||||
method_id: u32,
|
_method_id: u32,
|
||||||
call_id: u32,
|
_call_id: u32,
|
||||||
rest: Vec<u8>,
|
_rest: Vec<u8>,
|
||||||
) {
|
) {
|
||||||
//todo: maybe reply with not implemented(?)
|
//todo: maybe reply with not implemented(?)
|
||||||
}
|
}
|
||||||
|
|
@ -204,6 +204,7 @@ impl RmcCallable for () {
|
||||||
|
|
||||||
pub trait RemoteInstantiatable{
|
pub trait RemoteInstantiatable{
|
||||||
fn new(conn: RmcConnection) -> Self;
|
fn new(conn: RmcConnection) -> Self;
|
||||||
|
async fn disconnect(&self);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct OnlyRemote<T: RemoteInstantiatable>(T);
|
pub struct OnlyRemote<T: RemoteInstantiatable>(T);
|
||||||
|
|
@ -220,10 +221,15 @@ impl<T: RemoteInstantiatable> OnlyRemote<T>{
|
||||||
pub fn new(conn: RmcConnection) -> Self{
|
pub fn new(conn: RmcConnection) -> Self{
|
||||||
Self(T::new(conn))
|
Self(T::new(conn))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn disconnect(&self) {
|
||||||
|
self.0.disconnect().await;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: RemoteInstantiatable> RmcCallable for OnlyRemote<T>{
|
impl<T: RemoteInstantiatable> RmcCallable for OnlyRemote<T>{
|
||||||
fn rmc_call(&self, responder: &SendingBufferConnection, protocol_id: u16, method_id: u32, call_id: u32, rest: Vec<u8>) -> impl std::future::Future<Output = ()> + Send {
|
fn rmc_call(&self, _responder: &SendingBufferConnection, _protocol_id: u16, _method_id: u32, _call_id: u32, _rest: Vec<u8>) -> impl Future<Output = ()> + Send {
|
||||||
|
// maybe respond with not implemented or something
|
||||||
async{}
|
async{}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -243,6 +249,12 @@ async fn handle_incoming<T: RmcCallable + Send + Sync + 'static>(
|
||||||
return
|
return
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// protocol 0 is hardcoded to be the no protocol protocol aka keepalive protocol
|
||||||
|
if *proto_id == 0{
|
||||||
|
println!("got keepalive");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (proto_id & 0x80) == 0{
|
if (proto_id & 0x80) == 0{
|
||||||
let Some(response) = RMCResponse::new(&mut Cursor::new(v)).display_err_or_some() else {
|
let Some(response) = RMCResponse::new(&mut Cursor::new(v)).display_err_or_some() else {
|
||||||
error!("ending rmc gateway.");
|
error!("ending rmc gateway.");
|
||||||
|
|
@ -292,6 +304,8 @@ where
|
||||||
|
|
||||||
let rmc_conn = RmcConnection(sending_conn, response_recv);
|
let rmc_conn = RmcConnection(sending_conn, response_recv);
|
||||||
|
|
||||||
|
let sending_conn = conn.duplicate_sender();
|
||||||
|
|
||||||
let exposed_object = (create_internal)(rmc_conn);
|
let exposed_object = (create_internal)(rmc_conn);
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
@ -304,7 +318,25 @@ where
|
||||||
incoming
|
incoming
|
||||||
).await;
|
).await;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
tokio::spawn(async move {
|
||||||
|
while sending_conn.is_alive(){
|
||||||
|
sending_conn.send([0,0,0,0,0].to_vec()).await;
|
||||||
|
sleep(Duration::from_secs(10)).await;
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
exposed_object
|
exposed_object
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T: RmcCallable> RmcCallable for Arc<T>{
|
||||||
|
fn rmc_call(&self, responder: &SendingBufferConnection, protocol_id: u16, method_id: u32, call_id: u32, rest: Vec<u8>) -> impl Future<Output=()> + Send {
|
||||||
|
self.as_ref().rmc_call(responder, protocol_id, method_id, call_id, rest)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
define_rmc_proto! {
|
||||||
|
proto NoProto{}
|
||||||
|
}
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
use macros::{method_id, rmc_proto};
|
use macros::{method_id, rmc_proto};
|
||||||
use crate::rmc::response::ErrorCode;
|
use crate::rmc::response::ErrorCode;
|
||||||
use crate::rmc::structures::matchmake::{CreateMatchmakeSessionParam, MatchmakeSession};
|
|
||||||
|
|
||||||
#[rmc_proto(3)]
|
#[rmc_proto(3)]
|
||||||
pub trait NatTraversal{
|
pub trait NatTraversal{
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,4 @@
|
||||||
use macros::{method_id, rmc_proto, rmc_struct, RmcSerialize};
|
use macros::{method_id, rmc_proto, rmc_struct, RmcSerialize};
|
||||||
use crate::rmc::response::ErrorCode;
|
|
||||||
use crate::rmc::structures::qresult::QResult;
|
|
||||||
|
|
||||||
pub mod notification_types{
|
pub mod notification_types{
|
||||||
pub const OWNERSHIP_CHANGED: u32 = 4000;
|
pub const OWNERSHIP_CHANGED: u32 = 4000;
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use macros::{method_id, rmc_proto};
|
use macros::rmc_proto;
|
||||||
|
|
||||||
#[rmc_proto(112)]
|
#[rmc_proto(112)]
|
||||||
pub trait Ranking{
|
pub trait Ranking{
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,6 @@
|
||||||
use macros::{method_id, rmc_proto};
|
use macros::{method_id, rmc_proto};
|
||||||
use crate::prudp::station_url::StationUrl;
|
use crate::prudp::station_url::StationUrl;
|
||||||
use crate::rmc::response::ErrorCode;
|
use crate::rmc::response::ErrorCode;
|
||||||
use crate::rmc::structures::any::Any;
|
|
||||||
use crate::rmc::structures::connection_data::ConnectionData;
|
|
||||||
use crate::rmc::structures::qresult::QResult;
|
use crate::rmc::structures::qresult::QResult;
|
||||||
|
|
||||||
#[rmc_proto(11)]
|
#[rmc_proto(11)]
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,7 @@
|
||||||
|
// i seriously dont know why the compiler is complaining about unused parentheses in the repr
|
||||||
|
// attributes but this gets it to not complain anymore
|
||||||
|
#![allow(unused_parens)]
|
||||||
|
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::io::{Read, Seek, Write};
|
use std::io::{Read, Seek, Write};
|
||||||
use std::mem::transmute;
|
use std::mem::transmute;
|
||||||
|
|
@ -5,14 +9,8 @@ use bytemuck::bytes_of;
|
||||||
use log::error;
|
use log::error;
|
||||||
use v_byte_macros::EnumTryInto;
|
use v_byte_macros::EnumTryInto;
|
||||||
use crate::endianness::{ReadExtensions, IS_BIG_ENDIAN};
|
use crate::endianness::{ReadExtensions, IS_BIG_ENDIAN};
|
||||||
use crate::prudp::packet::{PRUDPV1Packet};
|
|
||||||
use crate::prudp::packet::flags::{NEED_ACK, RELIABLE};
|
|
||||||
use crate::prudp::packet::PacketOption::FragmentId;
|
|
||||||
use crate::prudp::packet::types::DATA;
|
|
||||||
use crate::prudp::socket::{ExternalConnection, SendingConnection};
|
|
||||||
use crate::rmc::response::ErrorCode::Core_Exception;
|
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::util::SendingBufferConnection;
|
use crate::util::SendingBufferConnection;
|
||||||
|
|
||||||
pub enum RMCResponseResult {
|
pub enum RMCResponseResult {
|
||||||
|
|
@ -72,7 +70,7 @@ impl RMCResponse {
|
||||||
error_code: {
|
error_code: {
|
||||||
match ErrorCode::try_from(error_code){
|
match ErrorCode::try_from(error_code){
|
||||||
Ok(v) => v,
|
Ok(v) => v,
|
||||||
Err(e) => {
|
Err(()) => {
|
||||||
error!("invalid error code {:#010x}", error_code);
|
error!("invalid error code {:#010x}", error_code);
|
||||||
Core_Exception
|
Core_Exception
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ impl<'a> RmcSerialize for &'a [u8]{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> RmcSerialize for Box<[u8]>{
|
impl RmcSerialize for Box<[u8]>{
|
||||||
fn serialize(&self, writer: &mut dyn Write) -> crate::rmc::structures::Result<()> {
|
fn serialize(&self, writer: &mut dyn Write) -> crate::rmc::structures::Result<()> {
|
||||||
(&self[..]).serialize(writer)
|
(&self[..]).serialize(writer)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,7 @@
|
||||||
use std::io::{Read, Write};
|
|
||||||
use bytemuck::bytes_of;
|
|
||||||
use macros::RmcSerialize;
|
use macros::RmcSerialize;
|
||||||
use crate::kerberos::KerberosDateTime;
|
use crate::kerberos::KerberosDateTime;
|
||||||
use crate::rmc::structures::{rmc_struct, RmcSerialize};
|
use crate::rmc::structures::RmcSerialize;
|
||||||
|
|
||||||
#[derive(Debug, RmcSerialize)]
|
#[derive(Debug, RmcSerialize)]
|
||||||
#[rmc_struct(1)]
|
#[rmc_struct(1)]
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,8 @@
|
||||||
|
use std::array::from_fn;
|
||||||
use std::io::{Read, Write};
|
use std::io::{Read, Write};
|
||||||
|
use std::mem::MaybeUninit;
|
||||||
use bytemuck::bytes_of;
|
use bytemuck::bytes_of;
|
||||||
|
use serde::Serialize;
|
||||||
use crate::endianness::{IS_BIG_ENDIAN, ReadExtensions};
|
use crate::endianness::{IS_BIG_ENDIAN, ReadExtensions};
|
||||||
use crate::rmc::structures::RmcSerialize;
|
use crate::rmc::structures::RmcSerialize;
|
||||||
|
|
||||||
|
|
@ -31,3 +34,27 @@ impl<T: RmcSerialize> RmcSerialize for Vec<T>{
|
||||||
Ok(vec)
|
Ok(vec)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<const LEN: usize, T: RmcSerialize> RmcSerialize for [T; LEN]{
|
||||||
|
fn serialize(&self, writer: &mut dyn Write) -> crate::rmc::structures::Result<()> {
|
||||||
|
for i in 0..LEN{
|
||||||
|
self[i].serialize(writer)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize(reader: &mut dyn Read) -> crate::rmc::structures::Result<Self> {
|
||||||
|
let mut arr = [const { MaybeUninit::<T>::uninit() }; LEN];
|
||||||
|
|
||||||
|
for i in 0..LEN{
|
||||||
|
arr[i] = MaybeUninit::new(T::deserialize(reader)?);
|
||||||
|
}
|
||||||
|
|
||||||
|
// all of the elements are now initialized so it is safe to assume they are initialized
|
||||||
|
|
||||||
|
let arr = arr.map(|v| unsafe{ v.assume_init() });
|
||||||
|
|
||||||
|
Ok(arr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -35,9 +35,9 @@ pub mod variant;
|
||||||
pub mod ranking;
|
pub mod ranking;
|
||||||
mod networking;
|
mod networking;
|
||||||
|
|
||||||
pub trait RmcSerialize: Sized{
|
pub trait RmcSerialize{
|
||||||
fn serialize(&self, writer: &mut dyn Write) -> Result<()>;
|
fn serialize(&self, writer: &mut dyn Write) -> Result<()>;
|
||||||
fn deserialize(reader: &mut dyn Read) -> Result<Self>;
|
fn deserialize(reader: &mut dyn Read) -> Result<Self> where Self: Sized;
|
||||||
|
|
||||||
fn to_data(&self) -> Vec<u8>{
|
fn to_data(&self) -> Vec<u8>{
|
||||||
let mut data = Vec::new();
|
let mut data = Vec::new();
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ impl RmcSerialize for SocketAddrV4{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
impl RmcSerialize for VirtualPort{
|
impl RmcSerialize for VirtualPort{
|
||||||
fn serialize(&self, writer: &mut dyn Write) -> crate::rmc::structures::Result<()> {
|
fn serialize(&self, writer: &mut dyn Write) -> crate::rmc::structures::Result<()> {
|
||||||
self.0.serialize(writer)?;
|
self.0.serialize(writer)?;
|
||||||
|
|
|
||||||
|
|
@ -229,4 +229,13 @@ impl<T: RmcSerialize, U: RmcSerialize, V: RmcSerialize, W: RmcSerialize, X: RmcS
|
||||||
|
|
||||||
Ok((first, second, third, fourth, fifth, sixth, seventh))
|
Ok((first, second, third, fourth, fifth, sixth, seventh))
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: RmcSerialize> RmcSerialize for Box<T>{
|
||||||
|
fn serialize(&self, writer: &mut dyn Write) -> crate::rmc::structures::Result<()> {
|
||||||
|
self.as_ref().serialize(writer)
|
||||||
|
}
|
||||||
|
fn deserialize(reader: &mut dyn Read) -> crate::rmc::structures::Result<Self> {
|
||||||
|
T::deserialize(reader).map(Box::new)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2,7 +2,6 @@ use std::io::{Read, Write};
|
||||||
use bytemuck::bytes_of;
|
use bytemuck::bytes_of;
|
||||||
use crate::endianness::{IS_BIG_ENDIAN, ReadExtensions};
|
use crate::endianness::{IS_BIG_ENDIAN, ReadExtensions};
|
||||||
use crate::rmc::structures::{Result, RmcSerialize};
|
use crate::rmc::structures::{Result, RmcSerialize};
|
||||||
use crate::rmc::structures::qresult::QResult;
|
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
use macros::RmcSerialize;
|
use macros::RmcSerialize;
|
||||||
use crate::kerberos::KerberosDateTime;
|
|
||||||
use crate::prudp::sockaddr::PRUDPSockAddr;
|
use crate::prudp::sockaddr::PRUDPSockAddr;
|
||||||
|
|
||||||
#[derive(Debug, RmcSerialize)]
|
#[derive(Debug, RmcSerialize)]
|
||||||
|
|
|
||||||
87
src/util.rs
87
src/util.rs
|
|
@ -1,14 +1,14 @@
|
||||||
use std::cell::UnsafeCell;
|
|
||||||
use std::marker::PhantomData;
|
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
use log::error;
|
use std::sync::Arc;
|
||||||
use tokio::io::{AsyncRead, AsyncWrite};
|
use log::{error, info};
|
||||||
|
use tokio::io::{AsyncRead, AsyncWrite, AsyncWriteExt};
|
||||||
use tokio::sync::mpsc::{channel, Receiver, Sender};
|
use tokio::sync::mpsc::{channel, Receiver, Sender};
|
||||||
|
use tokio::sync::Notify;
|
||||||
use tokio::task;
|
use tokio::task;
|
||||||
use rust_nex::reggie::{UnitPacketRead, UnitPacketWrite};
|
use rust_nex::reggie::{UnitPacketRead, UnitPacketWrite};
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct SendingBufferConnection(Sender<Vec<u8>>);
|
pub struct SendingBufferConnection(Sender<Vec<u8>>, Arc<Notify>);
|
||||||
|
|
||||||
pub struct SplittableBufferConnection(SendingBufferConnection, Receiver<Vec<u8>>);
|
pub struct SplittableBufferConnection(SendingBufferConnection, Receiver<Vec<u8>>);
|
||||||
|
|
||||||
|
|
@ -39,41 +39,53 @@ impl SplittableBufferConnection {
|
||||||
let (outside_send, inside_recv) = channel::<Vec<u8>>(10);
|
let (outside_send, inside_recv) = channel::<Vec<u8>>(10);
|
||||||
let (inside_send, outside_recv) = channel::<Vec<u8>>(10);
|
let (inside_send, outside_recv) = channel::<Vec<u8>>(10);
|
||||||
|
|
||||||
task::spawn(async move {
|
let notify = Arc::new(Notify::new());
|
||||||
let sender = inside_send;
|
|
||||||
let mut recver = inside_recv;
|
|
||||||
let mut stream = stream;
|
|
||||||
loop {
|
|
||||||
tokio::select! {
|
|
||||||
data = recver.recv() => {
|
|
||||||
let Some(data) = data else {
|
|
||||||
break;
|
|
||||||
};
|
|
||||||
|
|
||||||
if let Err(e) = stream.send_buffer(&data[..]).await{
|
{
|
||||||
error!("error sending data to backend: {}", e);
|
let notify = notify.clone();
|
||||||
break;
|
task::spawn(async move {
|
||||||
}
|
let sender = inside_send;
|
||||||
},
|
let mut recver = inside_recv;
|
||||||
data = stream.read_buffer() => {
|
let mut stream = stream;
|
||||||
let data = match data{
|
|
||||||
Ok(d) => d,
|
|
||||||
Err(e) => {
|
loop {
|
||||||
error!("error reveiving data from backend: {}", e);
|
tokio::select! {
|
||||||
|
data = recver.recv() => {
|
||||||
|
let Some(data) = data else {
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Err(e) = stream.send_buffer(&data[..]).await{
|
||||||
|
error!("error sending data to backend: {}", e);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
};
|
},
|
||||||
|
data = stream.read_buffer() => {
|
||||||
|
let data = match data{
|
||||||
|
Ok(d) => d,
|
||||||
|
Err(e) => {
|
||||||
|
error!("error reveiving data from backend: {}", e);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
if let Err(e) = sender.send(data).await{
|
if let Err(e) = sender.send(data).await{
|
||||||
error!("a send error occurred {}", e);
|
error!("a send error occurred {}", e);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ = notify.notified() => {
|
||||||
|
info!("shutting down connection");
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
}
|
stream.shutdown().await;
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
Self(SendingBufferConnection(outside_send), outside_recv)
|
Self(SendingBufferConnection(outside_send, notify), outside_recv)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -81,6 +93,15 @@ impl SendingBufferConnection{
|
||||||
pub async fn send(&self, buffer: Vec<u8>) -> Option<()>{
|
pub async fn send(&self, buffer: Vec<u8>) -> Option<()>{
|
||||||
self.0.send(buffer).await.ok()
|
self.0.send(buffer).await.ok()
|
||||||
}
|
}
|
||||||
|
pub fn is_alive(&self) -> bool{
|
||||||
|
!self.0.is_closed()
|
||||||
|
}
|
||||||
|
pub async fn disconnect(&self) {
|
||||||
|
while !self.0.is_closed() {
|
||||||
|
self.1.notify_waiters();
|
||||||
|
tokio::task::yield_now().await;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SplittableBufferConnection{
|
impl SplittableBufferConnection{
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use std::ops::{BitAnd, BitOr};
|
use std::ops::{BitAnd, BitOr};
|
||||||
use typenum::{Cmp, IsEqual, IsLess, IsLessOrEqual, Unsigned, U1, U2, U3};
|
use typenum::{Cmp, IsEqual, IsLess, IsLessOrEqual, Unsigned};
|
||||||
|
|
||||||
/// This trait represents a version at compile time
|
/// This trait represents a version at compile time
|
||||||
trait Version{
|
trait Version{
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,10 @@
|
||||||
use std::net::SocketAddrV4;
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use once_cell::sync::Lazy;
|
use rocket::{get, routes, Request, State};
|
||||||
use rocket::{get, routes, Request, Rocket, State};
|
|
||||||
use rocket::request::{FromRequest, Outcome};
|
use rocket::request::{FromRequest, Outcome};
|
||||||
use rocket::serde::json::Json;
|
use rocket::serde::json::Json;
|
||||||
use tokio::task::JoinHandle;
|
use tokio::task::JoinHandle;
|
||||||
use serde::Serialize;
|
|
||||||
use tokio::sync::Mutex;
|
|
||||||
use crate::nex::matchmake::MatchmakeManager;
|
use crate::nex::matchmake::MatchmakeManager;
|
||||||
use crate::rmc::protocols::HasRmcConnection;
|
|
||||||
use crate::rmc::protocols::notifications::NotificationEvent;
|
use crate::rmc::protocols::notifications::NotificationEvent;
|
||||||
|
|
||||||
struct RnexApiAuth;
|
struct RnexApiAuth;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue