feat: split rmc off from prudp, make macros crate location independent and add tls connection setup

This commit is contained in:
DJMrTV 2025-06-13 10:05:38 +02:00
commit 9da91bb835
24 changed files with 1218 additions and 420 deletions

850
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -25,8 +25,8 @@ simplelog = "0.12.2"
chrono = "0.4.39" chrono = "0.4.39"
log = "0.4.25" log = "0.4.25"
anyhow = "1.0.95" anyhow = "1.0.95"
rand = "0.9.0-beta.3" rand = "0.8.5"
rustls = "^0.23.21"
hmac = "0.12.1" hmac = "0.12.1"
md-5 = "^0.10.6" md-5 = "^0.10.6"
tokio = { version = "1.43.0", features = ["macros", "rt-multi-thread", "net", "sync", "fs"] } tokio = { version = "1.43.0", features = ["macros", "rt-multi-thread", "net", "sync", "fs"] }
@ -45,6 +45,15 @@ futures = "0.3.31"
reqwest = "0.12.18" reqwest = "0.12.18"
json = "0.12.4" json = "0.12.4"
ctrlc = "3.4.7" ctrlc = "3.4.7"
rsa = "0.9.8"
sha2 = "0.10.9"
chacha20 = "0.9.1"
rustls = "0.23.27"
rustls-pki-types = "1.12.0"
rustls-webpki = "0.103.3"
tokio-rustls = "0.26.2"
@ -57,3 +66,14 @@ default = ["secure", "auth"]
secure = [] secure = []
auth = [] auth = []
[[bin]]
name = "proxy_insecure"
path = "src/executables/proxy_insecure.rs"
[[bin]]
name = "proxy_secure"
path = "src/executables/proxy_secure.rs"
[[bin]]
name = "backend_server"
path = "src/executables/backend_server.rs"

View file

@ -189,7 +189,7 @@ pub fn rmc_serialize(input: TokenStream) -> TokenStream {
quote! { quote! {
#pre_inner #pre_inner
crate::rmc::structures::rmc_struct::write_struct(writer, #version, |mut writer|{ splatoon_server_rust::rmc::structures::rmc_struct::write_struct(writer, #version, |mut writer|{
#serialize_base_content #serialize_base_content
})?; })?;
@ -218,7 +218,7 @@ pub fn rmc_serialize(input: TokenStream) -> TokenStream {
quote! { quote! {
#pre_inner #pre_inner
Ok(crate::rmc::structures::rmc_struct::read_struct(reader, #version, move |mut reader|{ Ok(splatoon_server_rust::rmc::structures::rmc_struct::read_struct(reader, #version, move |mut reader|{
#deserialize_base_content #deserialize_base_content
})?) })?)
} }
@ -229,14 +229,14 @@ pub fn rmc_serialize(input: TokenStream) -> TokenStream {
let ident = derive_input.ident; let ident = derive_input.ident;
let tokens = quote! { let tokens = quote! {
impl crate::rmc::structures::RmcSerialize for #ident{ impl splatoon_server_rust::rmc::structures::RmcSerialize for #ident{
fn serialize(&self, writer: &mut dyn ::std::io::Write) -> crate::rmc::structures::Result<()>{ fn serialize(&self, writer: &mut dyn ::std::io::Write) -> splatoon_server_rust::rmc::structures::Result<()>{
#serialize_base_content #serialize_base_content
} }
fn deserialize(reader: &mut dyn ::std::io::Read) -> crate::rmc::structures::Result<Self>{ fn deserialize(reader: &mut dyn ::std::io::Read) -> splatoon_server_rust::rmc::structures::Result<Self>{
#deserialize_base_content #deserialize_base_content
} }
} }
@ -367,8 +367,8 @@ pub fn rmc_struct(attr: TokenStream, input: TokenStream) -> TokenStream{
} }
impl crate::rmc::protocols::RmcCallable for #struct_name{ impl splatoon_server_rust::rmc::protocols::RmcCallable for #struct_name{
async fn rmc_call(&self, remote_response_connection: &crate::prudp::socket::SendingConnection, protocol_id: u16, method_id: u32, call_id: u32, rest: Vec<u8>){ async fn rmc_call(&self, remote_response_connection: &splatoon_server_rust::util::SendingBufferConnection, protocol_id: u16, method_id: u32, call_id: u32, rest: Vec<u8>){
<Self as #ident>::rmc_call(self, remote_response_connection, protocol_id, method_id, call_id, rest).await; <Self as #ident>::rmc_call(self, remote_response_connection, protocol_id, method_id, call_id, rest).await;
} }
} }

View file

@ -73,7 +73,7 @@ impl RmcProtocolData{
for (param_name, param_type) in parameters{ for (param_name, param_type) in parameters{
quote!{ quote!{
let Ok(#param_name) = let Ok(#param_name) =
<#param_type as crate::rmc::structures::RmcSerialize>::deserialize( <#param_type as splatoon_server_rust::rmc::structures::RmcSerialize>::deserialize(
&mut cursor &mut cursor
) else ) else
}.to_tokens(tokens); }.to_tokens(tokens);
@ -84,7 +84,7 @@ impl RmcProtocolData{
quote! { quote! {
{ {
log::error!(#error_msg); log::error!(#error_msg);
return Err(crate::rmc::response::ErrorCode::Core_InvalidArgument); return Err(splatoon_server_rust::rmc::response::ErrorCode::Core_InvalidArgument);
}; };
}.to_tokens(tokens) }.to_tokens(tokens)
} else { } else {
@ -116,7 +116,7 @@ impl RmcProtocolData{
quote!{ quote!{
let retval = retval?; let retval = retval?;
let mut vec = Vec::new(); let mut vec = Vec::new();
crate::rmc::structures::RmcSerialize::serialize(&retval, &mut vec).ok(); splatoon_server_rust::rmc::structures::RmcSerialize::serialize(&retval, &mut vec).ok();
Ok(vec) Ok(vec)
}.to_tokens(tokens); }.to_tokens(tokens);
} }
@ -126,7 +126,7 @@ impl RmcProtocolData{
quote!{ quote!{
async fn rmc_call_proto( async fn rmc_call_proto(
&self, &self,
remote_response_connection: &crate::prudp::socket::SendingConnection, remote_response_connection: &splatoon_server_rust::util::SendingBufferConnection,
method_id: u32, method_id: u32,
call_id: u32, call_id: u32,
data: Vec<u8>, data: Vec<u8>,
@ -165,7 +165,7 @@ impl RmcProtocolData{
}.to_tokens(tokens); }.to_tokens(tokens);
if self.has_returns { if self.has_returns {
quote! { quote! {
Err(crate::rmc::response::ErrorCode::Core_NotImplemented) Err(splatoon_server_rust::rmc::response::ErrorCode::Core_NotImplemented)
}.to_tokens(tokens); }.to_tokens(tokens);
} }
}); });
@ -176,7 +176,7 @@ impl RmcProtocolData{
if *has_returns{ if *has_returns{
quote!{ quote!{
crate::rmc::response::send_result( splatoon_server_rust::rmc::response::send_result(
remote_response_connection, remote_response_connection,
ret, ret,
#id, #id,
@ -209,7 +209,7 @@ impl RmcProtocolData{
// boilerplate tokens which all raw traits need // boilerplate tokens which all raw traits need
quote!{ quote!{
#[doc(hidden)] #[doc(hidden)]
pub trait #remote_name: crate::rmc::protocols::HasRmcConnection pub trait #remote_name: splatoon_server_rust::rmc::protocols::HasRmcConnection
}.to_tokens(tokens); }.to_tokens(tokens);
// generate the body of the raw protocol trait // generate the body of the raw protocol trait
@ -247,12 +247,12 @@ impl RmcProtocolData{
for (param_name, param_type) in parameters{ for (param_name, param_type) in parameters{
quote!{ quote!{
crate::result::ResultExtension::display_err_or_some( splatoon_server_rust::result::ResultExtension::display_err_or_some(
<#param_type as crate::rmc::structures::RmcSerialize>::serialize( <#param_type as splatoon_server_rust::rmc::structures::RmcSerialize>::serialize(
&#param_name, &#param_name,
&mut cursor &mut cursor
) )
).ok_or(crate::rmc::response::ErrorCode::Core_InvalidArgument) ).ok_or(splatoon_server_rust::rmc::response::ErrorCode::Core_InvalidArgument)
}.to_tokens(tokens); }.to_tokens(tokens);
if self.has_returns { if self.has_returns {
quote! { quote! {
@ -268,25 +268,25 @@ impl RmcProtocolData{
quote!{ quote!{
let call_id = rand::random(); let call_id = rand::random();
let message = crate::rmc::message::RMCMessage{ let message = splatoon_server_rust::rmc::message::RMCMessage{
call_id, call_id,
method_id: #method_id, method_id: #method_id,
protocol_id: #proto_id, protocol_id: #proto_id,
rest_of_data: send_data rest_of_data: send_data
}; };
let rmc_conn = <Self as crate::rmc::protocols::HasRmcConnection>::get_connection(self); let rmc_conn = <Self as splatoon_server_rust::rmc::protocols::HasRmcConnection>::get_connection(self);
}.to_tokens(tokens); }.to_tokens(tokens);
if *has_returns{ if *has_returns{
quote!{ quote!{
crate::result::ResultExtension::display_err_or_some( splatoon_server_rust::result::ResultExtension::display_err_or_some(
rmc_conn.make_raw_call(&message).await rmc_conn.make_raw_call(&message).await
).ok_or(crate::rmc::response::ErrorCode::Core_Exception) ).ok_or(splatoon_server_rust::rmc::response::ErrorCode::Core_Exception)
}.to_tokens(tokens); }.to_tokens(tokens);
} else { } else {
quote!{ quote!{
crate::result::ResultExtension::display_err_or_some( splatoon_server_rust::result::ResultExtension::display_err_or_some(
rmc_conn.make_raw_call_no_response(&message).await rmc_conn.make_raw_call_no_response(&message).await
); );
}.to_tokens(tokens); }.to_tokens(tokens);

37
src/common.rs Normal file
View file

@ -0,0 +1,37 @@
use std::fs;
use std::fs::File;
use chrono::{Local, SecondsFormat};
use log::LevelFilter;
use simplelog::{ColorChoice, CombinedLogger, Config, TermLogger, TerminalMode, WriteLogger};
pub fn setup(){
CombinedLogger::init(vec![
TermLogger::new(
LevelFilter::Info,
Config::default(),
TerminalMode::Mixed,
ColorChoice::Auto,
),
WriteLogger::new(LevelFilter::max(), Config::default(), {
fs::create_dir_all("log").unwrap();
let date = Local::now().to_rfc3339_opts(SecondsFormat::Secs, false);
// this fixes windows being windows
let date = date.replace(":", "-");
let filename = format!("{}.log", date);
if cfg!(windows) {
File::create(format!("log\\{}", filename)).unwrap()
} else {
File::create(format!("log/{}", filename)).unwrap()
}
}),
])
.unwrap();
/*ctrlc::set_handler(||{
FORCE_EXIT.call_once_force(|_|{
println!("attempting exit");
});
}).unwrap();*/
dotenv::dotenv().ok();
}

View file

@ -0,0 +1,58 @@
use log::error;
use once_cell::sync::Lazy;
use rustls::client::danger::HandshakeSignatureValid;
use rustls::pki_types::{CertificateDer, TrustAnchor, UnixTime};
use rustls::server::danger::{ClientCertVerified, ClientCertVerifier};
use rustls::server::{ClientCertVerifierBuilder, WebPkiClientVerifier};
use rustls::{
DigitallySignedStruct, DistinguishedName, Error, RootCertStore, ServerConfig, ServerConnection,
SignatureScheme,
};
use rustls_pki_types::PrivateKeyDer;
use splatoon_server_rust::common::setup;
use splatoon_server_rust::reggie::{get_configured_tls_acceptor, TestStruct, ROOT_TRUST_ANCHOR, SELF_CERT, SELF_KEY};
use std::borrow::ToOwned;
use std::fs;
use std::io::Cursor;
use std::net::{IpAddr, SocketAddr, SocketAddrV4};
use std::sync::Arc;
use macros::{method_id, rmc_proto, rmc_struct};
use tokio::io::AsyncReadExt;
use tokio::net::{TcpListener, TcpSocket};
use tokio::task;
use tokio_rustls::TlsAcceptor;
use splatoon_server_rust::define_rmc_proto;
use splatoon_server_rust::rmc::protocols::new_rmc_gateway_connection;
use splatoon_server_rust::rmc::response::ErrorCode;
use splatoon_server_rust::rmc::structures::RmcSerialize;
#[tokio::main]
async fn main() {
setup();
let acceptor = get_configured_tls_acceptor().await;
let listen = TcpListener::bind("192.168.178.120:2376").await.unwrap();
while let Ok((stream, addr)) = listen.accept().await {
let mut stream = match acceptor.accept(stream).await {
Ok(v) => v,
Err(e) => {
error!("an error ocurred whilest accepting tls connection: {:?}", e);
continue;
}
};
task::spawn(async move {
new_rmc_gateway_connection(stream.into(), |_| {
Arc::new(TestStruct)
});
println!("lost connection lol");
});
}
}

View file

@ -0,0 +1,131 @@
mod proxy_secure;
use std::env;
use std::ffi::CStr;
use std::io::{Read, Write};
use std::net::{Ipv4Addr, SocketAddrV4, TcpListener, TcpStream};
use bytemuck::{Pod, Zeroable};
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 splatoon_server_rust::common::setup;
use splatoon_server_rust::prudp::packet::VirtualPort;
use splatoon_server_rust::prudp::router::Router;
use splatoon_server_rust::prudp::unsecure::Unsecure;
use splatoon_server_rust::reggie::{establish_tls_connection_to, UnitPacketRead, UnitPacketWrite};
use splatoon_server_rust::rmc::structures::RmcSerialize;
use splatoon_server_rust::rnex_proxy_common::ConnectionInitData;
static OWN_IP_PRIVATE: Lazy<Ipv4Addr> = Lazy::new(|| {
env::var("SERVER_IP")
.ok()
.and_then(|s| s.parse().ok())
.expect("no public ip specified")
});
static OWN_IP_PUBLIC: Lazy<String> =
Lazy::new(|| env::var("SERVER_IP_PUBLIC").unwrap_or(OWN_IP_PRIVATE.to_string()));
static SERVER_PORT: Lazy<u16> = Lazy::new(|| {
env::var("AUTH_SERVER_PORT")
.ok()
.and_then(|s| s.parse().ok())
.unwrap_or(10000)
});
static FORWARD_DESTINATION: Lazy<String> =
Lazy::new(|| env::var("FORWARD_DESTINATION").unwrap_or(OWN_IP_PRIVATE.to_string()));
static RSA_PRIVKEY: Lazy<RsaPrivateKey> = Lazy::new(|| {
let path = env::var("RSA_PRIVKEY")
.expect("RSA_PRIVKEY not set");
RsaPrivateKey::read_pkcs8_pem_file(&path)
.expect("unable to read private key")
});
static RSA_PUBKEY: Lazy<RsaPublicKey> = Lazy::new(|| {
RSA_PRIVKEY.to_public_key()
});
static PUBKEY_ENCODED: Lazy<Document> = Lazy::new(|| {
RSA_PUBKEY.to_pkcs1_der().expect("unable to convert pubkey to der")
});
static RSA_SIGNKEY: Lazy<BlindedSigningKey<Sha256>> = Lazy::new(||
BlindedSigningKey::<Sha256>::new(RSA_PRIVKEY.clone())
);
#[tokio::main]
async fn main() {
setup();
let (router_secure, _) = Router::new(SocketAddrV4::new(*OWN_IP_PRIVATE, *SERVER_PORT))
.await
.expect("unable to start router");
let mut socket_secure = router_secure
.add_socket(VirtualPort::new(1, 10), Unsecure(
"6f599f81"
))
.await
.expect("unable to add socket");
// let conn = socket_secure.connect(auth_sockaddr).await.unwrap();
loop {
let Some(mut conn) = socket_secure.accept().await else {
error!("server crashed");
return;
};
task::spawn(async move {
let mut stream
= establish_tls_connection_to("192.168.178.120:2376", "account.spfn.net").await;
if let Err(e) = stream.send_buffer(&ConnectionInitData{
prudpsock_addr: conn.socket_addr
}.to_data()).await{
error!("error connecting to backend: {}", e);
return;
};
loop {
tokio::select! {
data = conn.recv() => {
let Some(data) = data else {
break;
};
if let Err(e) = stream.send_buffer(&data[..]).await{
error!("error sending data to backend: {}", e);
break;
}
},
data = stream.read_buffer() => {
let data = match data{
Ok(d) => d,
Err(e) => {
error!("error reveiving data from backend: {}", e);
break;
}
};
if conn.send(data).await == None{
return;
}
},
}
}
});
}
}

View file

@ -0,0 +1,26 @@
use splatoon_server_rust::reggie::RemoteRmcTestProto;
use std::fs;
use std::net::IpAddr;
use std::sync::Arc;
use rustls::ClientConfig;
use rustls_pki_types::ServerName;
use tokio::io::AsyncWriteExt;
use tokio::net::TcpStream;
use tokio_rustls::{TlsConnector, TlsStream};
use splatoon_server_rust::common::setup;
use splatoon_server_rust::reggie::{establish_tls_connection_to, get_configured_tls_connector, RemoteTestProto, UnitPacketWrite};
use splatoon_server_rust::rmc::protocols::{new_rmc_gateway_connection, OnlyRemote};
use splatoon_server_rust::rmc::structures::RmcSerialize;
#[tokio::main]
async fn main(){
setup();
let mut stream
= establish_tls_connection_to("192.168.178.120:2376", "account.spfn.net").await;
let remo = new_rmc_gateway_connection(stream.into(), |r| Arc::new(OnlyRemote::<RemoteTestProto>::new(r)) );
println!("{:?}", remo.test().await);
}

View file

@ -1,11 +1,17 @@
mod endianness; extern crate self as splatoon_server_rust;
mod prudp;
pub mod endianness;
pub mod prudp;
pub mod rmc; pub mod rmc;
//mod protocols; //mod protocols;
mod grpc; pub mod grpc;
mod kerberos; pub mod kerberos;
mod nex; pub mod nex;
mod result; pub mod result;
mod versions; pub mod versions;
mod web; pub mod web;
pub mod common;
pub mod reggie;
pub mod rnex_proxy_common;
pub mod util;

View file

@ -7,6 +7,8 @@
//! also the first and only current usage of rnex, expect this and rnex to be split into seperate //! also the first and only current usage of rnex, expect this and rnex to be split into seperate
//! repos soon. //! repos soon.
extern crate self as splatoon_server_rust;
use crate::nex::account::Account; use crate::nex::account::Account;
use crate::nex::auth_handler::{AuthHandler, RemoteAuthClientProtocol}; use crate::nex::auth_handler::{AuthHandler, RemoteAuthClientProtocol};
use crate::nex::remote_console::RemoteConsole; use crate::nex::remote_console::RemoteConsole;
@ -59,6 +61,10 @@ mod nex;
mod result; mod result;
mod versions; mod versions;
mod web; mod web;
pub mod reggie;
pub mod util;
static KERBEROS_SERVER_PASSWORD: Lazy<String> = Lazy::new(|| { static KERBEROS_SERVER_PASSWORD: Lazy<String> = Lazy::new(|| {
env::var("AUTH_SERVER_PASSWORD") env::var("AUTH_SERVER_PASSWORD")
@ -135,7 +141,7 @@ async fn main() {
dotenv::dotenv().ok(); dotenv::dotenv().ok();
start_servers().await; //start_servers().await;
} }
/* /*
@ -278,7 +284,7 @@ async fn start_secure_server() -> SecureServer{
socket, socket,
} }
}*/ }*/
/*
async fn start_auth() -> JoinHandle<()> { async fn start_auth() -> JoinHandle<()> {
tokio::spawn(async { tokio::spawn(async {
let (router_secure, _) = Router::new(SocketAddrV4::new(*OWN_IP_PRIVATE, *AUTH_SERVER_PORT)) let (router_secure, _) = Router::new(SocketAddrV4::new(*OWN_IP_PRIVATE, *AUTH_SERVER_PORT))
@ -414,3 +420,4 @@ async fn start_servers() {
#[cfg(feature = "secure")] #[cfg(feature = "secure")]
secure_server.await.expect("auth server crashed"); secure_server.await.expect("auth server crashed");
} }
*/

View file

@ -144,7 +144,7 @@ impl Debug for VirtualPort {
#[repr(C)] #[repr(C)]
#[derive(Debug, Copy, Clone, Pod, Zeroable, SwapEndian, Eq, PartialEq)] #[derive(Debug, Copy, Clone, Pod, Zeroable, SwapEndian, Eq, PartialEq)]
pub struct PRUDPHeader { pub struct PRUDPV1Header {
pub magic: [u8; 2], pub magic: [u8; 2],
pub version: u8, pub version: u8,
pub packet_specific_size: u8, pub packet_specific_size: u8,
@ -157,7 +157,7 @@ pub struct PRUDPHeader {
pub sequence_id: u16, pub sequence_id: u16,
} }
impl Default for PRUDPHeader{ impl Default for PRUDPV1Header {
fn default() -> Self { fn default() -> Self {
Self{ Self{
magic: [0xEA, 0xD0], magic: [0xEA, 0xD0],
@ -239,8 +239,8 @@ impl PacketOption{
} }
#[derive(Debug, Default, Clone, Eq, PartialEq)] #[derive(Debug, Default, Clone, Eq, PartialEq)]
pub struct PRUDPPacket { pub struct PRUDPV1Packet {
pub header: PRUDPHeader, pub header: PRUDPV1Header,
pub packet_signature: [u8; 16], pub packet_signature: [u8; 16],
pub payload: Vec<u8>, pub payload: Vec<u8>,
pub options: Vec<PacketOption>, pub options: Vec<PacketOption>,
@ -277,9 +277,9 @@ impl Into<u8> for OptionId {
} }
} }
impl PRUDPPacket { impl PRUDPV1Packet {
pub fn new(reader: &mut (impl Read + Seek)) -> Result<Self> { pub fn new(reader: &mut (impl Read + Seek)) -> Result<Self> {
let header: PRUDPHeader = reader.read_struct(IS_BIG_ENDIAN)?; let header: PRUDPV1Header = reader.read_struct(IS_BIG_ENDIAN)?;
if header.magic[0] != 0xEA || if header.magic[0] != 0xEA ||
header.magic[1] != 0xD0 { header.magic[1] != 0xD0 {
@ -372,7 +372,7 @@ impl PRUDPPacket {
Self{ Self{
header: PRUDPHeader{ header: PRUDPV1Header {
types_and_flags: flags, types_and_flags: flags,
sequence_id: self.header.sequence_id, sequence_id: self.header.sequence_id,
substream_id: self.header.substream_id, substream_id: self.header.substream_id,
@ -444,7 +444,7 @@ impl PRUDPPacket {
pub fn base_response_packet(&self) -> Self { pub fn base_response_packet(&self) -> Self {
Self { Self {
header: PRUDPHeader { header: PRUDPV1Header {
magic: [0xEA, 0xD0], magic: [0xEA, 0xD0],
types_and_flags: TypesFlags(0), types_and_flags: TypesFlags(0),
destination_port: self.header.source_port, destination_port: self.header.source_port,
@ -481,10 +481,10 @@ impl PRUDPPacket {
mod test { mod test {
use crate::prudp::packet::flags::{NEED_ACK, RELIABLE}; use crate::prudp::packet::flags::{NEED_ACK, RELIABLE};
use crate::prudp::packet::types::DATA; use crate::prudp::packet::types::DATA;
use super::{OptionId, PacketOption, PRUDPHeader, TypesFlags, VirtualPort}; use super::{OptionId, PacketOption, PRUDPV1Header, TypesFlags, VirtualPort};
#[test] #[test]
fn size_test() { fn size_test() {
assert_eq!(size_of::<PRUDPHeader>(), 14); assert_eq!(size_of::<PRUDPV1Header>(), 14);
} }
#[test] #[test]
@ -511,7 +511,7 @@ mod test {
#[test] #[test]
fn header_read(){ fn header_read(){
let header = PRUDPHeader{ let header = PRUDPV1Header {
version: 0, version: 0,
destination_port: VirtualPort(0), destination_port: VirtualPort(0),
substream_id: 0, substream_id: 0,

View file

@ -15,7 +15,7 @@ use tokio::select;
use tokio::sync::RwLock; use tokio::sync::RwLock;
use tokio::time::sleep; use tokio::time::sleep;
use crate::prudp::socket::{new_socket_pair, AnyInternalSocket, CryptoHandler, ExternalSocket}; use crate::prudp::socket::{new_socket_pair, AnyInternalSocket, CryptoHandler, ExternalSocket};
use crate::prudp::packet::{PRUDPPacket, VirtualPort}; use crate::prudp::packet::{PRUDPV1Packet, VirtualPort};
use crate::prudp::router::Error::VirtualPortTaken; use crate::prudp::router::Error::VirtualPortTaken;
static SERVER_DATAGRAMS: Lazy<u8> = Lazy::new(||{ static SERVER_DATAGRAMS: Lazy<u8> = Lazy::new(||{
@ -31,6 +31,7 @@ pub struct Router {
socket: Arc<UdpSocket>, socket: Arc<UdpSocket>,
_no_outside_construction: PhantomData<()> _no_outside_construction: PhantomData<()>
} }
#[derive(Debug, Error)] #[derive(Debug, Error)]
pub enum Error{ pub enum Error{
#[error("tried to register socket to a port which is already taken (port: {0})")] #[error("tried to register socket to a port which is already taken (port: {0})")]
@ -43,7 +44,7 @@ impl Router {
let mut stream = Cursor::new(&udp_message); let mut stream = Cursor::new(&udp_message);
while stream.position() as usize != udp_message.len() { while stream.position() as usize != udp_message.len() {
let packet = match PRUDPPacket::new(&mut stream){ let packet = match PRUDPV1Packet::new(&mut stream){
Ok(p) => p, Ok(p) => p,
Err(e) => { Err(e) => {
error!("Somebody({}) is fucking with the servers or their connection is bad (reason: {})", addr, e); error!("Somebody({}) is fucking with the servers or their connection is bad (reason: {})", addr, e);
@ -155,7 +156,7 @@ impl Router {
} }
// returns Some(()) i // returns Some(()) i
pub(crate) async fn add_socket<E: CryptoHandler>(&self, virtual_port: VirtualPort, encryption: E) pub async fn add_socket<E: CryptoHandler>(&self, virtual_port: VirtualPort, encryption: E)
-> Result<ExternalSocket, Error>{ -> Result<ExternalSocket, Error>{
let mut endpoints = self.endpoints.write().await; let mut endpoints = self.endpoints.write().await;

View file

@ -8,7 +8,7 @@ use typenum::U5;
use crate::endianness::{IS_BIG_ENDIAN, ReadExtensions}; use crate::endianness::{IS_BIG_ENDIAN, ReadExtensions};
use crate::kerberos::{derive_key, TicketInternalData}; use crate::kerberos::{derive_key, TicketInternalData};
use crate::nex::account::Account; use crate::nex::account::Account;
use crate::prudp::packet::PRUDPPacket; 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::prudp::unsecure::UnsecureInstance;
use crate::rmc::structures::RmcSerialize; use crate::rmc::structures::RmcSerialize;
@ -150,7 +150,7 @@ impl CryptoHandler for Secure {
)) ))
} }
fn sign_pre_handshake(&self, packet: &mut PRUDPPacket) { fn sign_pre_handshake(&self, packet: &mut PRUDPV1Packet) {
packet.set_sizes(); packet.set_sizes();
packet.calculate_and_assign_signature(self.0, None, None); packet.calculate_and_assign_signature(self.0, None, None);
} }
@ -176,17 +176,17 @@ impl CryptoHandlerConnectionInstance for SecureInstance {
self.pid self.pid
} }
fn sign_connect(&self, packet: &mut PRUDPPacket) { fn sign_connect(&self, packet: &mut PRUDPV1Packet) {
packet.set_sizes(); packet.set_sizes();
packet.calculate_and_assign_signature(self.access_key, None, Some(self.self_signature)); packet.calculate_and_assign_signature(self.access_key, None, Some(self.self_signature));
} }
fn sign_packet(&self, packet: &mut PRUDPPacket) { fn sign_packet(&self, packet: &mut PRUDPV1Packet) {
packet.set_sizes(); packet.set_sizes();
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: &PRUDPPacket) -> bool { fn verify_packet(&self, packet: &PRUDPV1Packet) -> bool {
true true
} }
} }

View file

@ -1,11 +1,13 @@
use std::io::Write; use std::io::Write;
use std::net::SocketAddrV4; use std::net::SocketAddrV4;
use hmac::{Hmac, Mac}; use hmac::{Hmac, Mac};
use macros::RmcSerialize;
use crate::prudp::packet::VirtualPort; use crate::prudp::packet::VirtualPort;
type Md5Hmac = Hmac<md5::Md5>; type Md5Hmac = Hmac<md5::Md5>;
#[derive(Eq, PartialEq, Hash, Debug, Copy, Clone, Ord, PartialOrd)] #[derive(Eq, PartialEq, Hash, Debug, Copy, Clone, Ord, PartialOrd, RmcSerialize)]
#[rmc_struct(0)]
pub struct PRUDPSockAddr{ pub struct PRUDPSockAddr{
pub regular_socket_addr: SocketAddrV4, pub regular_socket_addr: SocketAddrV4,
pub virtual_port: VirtualPort pub virtual_port: VirtualPort

View file

@ -4,7 +4,7 @@ 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, InitialSequenceId, MaximumSubstreamId, SupportedFunctions,
}; };
use crate::prudp::packet::{PRUDPHeader, PRUDPPacket, PacketOption, TypesFlags, VirtualPort}; use crate::prudp::packet::{PRUDPV1Header, PRUDPV1Packet, PacketOption, TypesFlags, VirtualPort};
use crate::prudp::router::{Error, Router}; 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;
@ -67,7 +67,7 @@ struct InternalConnection<E: CryptoHandlerConnectionInstance> {
crypto_handler_instance: E, crypto_handler_instance: E,
data_sender: Sender<Vec<u8>>, data_sender: Sender<Vec<u8>>,
socket: Arc<UdpSocket>, socket: Arc<UdpSocket>,
packet_queue: HashMap<u16, PRUDPPacket>, packet_queue: HashMap<u16, PRUDPV1Packet>,
last_packet_time: Instant, last_packet_time: Instant,
} }
@ -88,7 +88,7 @@ impl<E: CryptoHandlerConnectionInstance> InternalConnection<E> {
} }
#[inline] #[inline]
async fn send_raw_packet(&self, mut prudp_packet: PRUDPPacket) { async fn send_raw_packet(&self, mut prudp_packet: PRUDPV1Packet) {
prudp_packet.set_sizes(); prudp_packet.set_sizes();
let mut vec = Vec::new(); let mut vec = Vec::new();
@ -128,7 +128,7 @@ pub(super) struct InternalSocket<T: CryptoHandler> {
internal_connections: Arc< internal_connections: Arc<
Mutex<BTreeMap<PRUDPSockAddr, Arc<Mutex<InternalConnection<T::CryptoConnectionInstance>>>>>, Mutex<BTreeMap<PRUDPSockAddr, Arc<Mutex<InternalConnection<T::CryptoConnectionInstance>>>>>,
>, >,
connection_establishment_data_sender: Mutex<Option<Sender<PRUDPPacket>>>, connection_establishment_data_sender: Mutex<Option<Sender<PRUDPV1Packet>>>,
connection_sender: Sender<ExternalConnection>, connection_sender: Sender<ExternalConnection>,
} }
@ -170,7 +170,7 @@ impl<T: CryptoHandler> Deref for InternalSocket<T> {
pub(super) trait AnyInternalSocket: pub(super) trait AnyInternalSocket:
Send + Sync + Deref<Target = CommonSocket> + 'static Send + Sync + Deref<Target = CommonSocket> + 'static
{ {
async fn receive_packet(&self, address: PRUDPSockAddr, packet: PRUDPPacket); async fn receive_packet(&self, address: PRUDPSockAddr, packet: PRUDPV1Packet);
async fn connect(&self, address: PRUDPSockAddr) -> Option<()>; async fn connect(&self, address: PRUDPSockAddr) -> Option<()>;
} }
@ -186,8 +186,8 @@ pub(super) trait AnyInternalConnection:
#[async_trait] #[async_trait]
impl<T: CryptoHandlerConnectionInstance> AnyInternalConnection for InternalConnection<T> { impl<T: CryptoHandlerConnectionInstance> AnyInternalConnection for InternalConnection<T> {
async fn send_data_packet(&mut self, data: Vec<u8>) { async fn send_data_packet(&mut self, data: Vec<u8>) {
let mut packet = PRUDPPacket { let mut packet = PRUDPV1Packet {
header: PRUDPHeader { header: PRUDPV1Header {
sequence_id: self.next_server_count(), sequence_id: self.next_server_count(),
substream_id: 0, substream_id: 0,
session_id: self.session_id, session_id: self.session_id,
@ -214,8 +214,8 @@ impl<T: CryptoHandlerConnectionInstance> AnyInternalConnection for InternalConne
async fn close_connection(&mut self) { async fn close_connection(&mut self) {
// jon confirmed that this should be a safe way to dc a client // jon confirmed that this should be a safe way to dc a client
let mut packet = PRUDPPacket { let mut packet = PRUDPV1Packet {
header: PRUDPHeader { header: PRUDPV1Header {
sequence_id: self.next_server_count(), sequence_id: self.next_server_count(),
substream_id: 0, substream_id: 0,
session_id: self.session_id, session_id: self.session_id,
@ -269,7 +269,7 @@ impl<T: CryptoHandler> InternalSocket<T> {
Some(conn) Some(conn)
} }
async fn send_packet_unbuffered(&self, dest: PRUDPSockAddr, mut packet: PRUDPPacket) { async fn send_packet_unbuffered(&self, dest: PRUDPSockAddr, mut packet: PRUDPV1Packet) {
packet.set_sizes(); packet.set_sizes();
let mut vec = Vec::new(); let mut vec = Vec::new();
@ -284,7 +284,7 @@ impl<T: CryptoHandler> InternalSocket<T> {
.expect("failed to send data back"); .expect("failed to send data back");
} }
async fn handle_syn(&self, address: PRUDPSockAddr, packet: PRUDPPacket) { async fn handle_syn(&self, address: PRUDPSockAddr, packet: PRUDPV1Packet) {
info!("got syn"); info!("got syn");
let mut response = packet.base_response_packet(); let mut response = packet.base_response_packet();
@ -328,8 +328,8 @@ impl<T: CryptoHandler> InternalSocket<T> {
let mut conn = conn.lock().await; let mut conn = conn.lock().await;
if conn.last_packet_time < (Instant::now() - Duration::from_secs(5)) { if conn.last_packet_time < (Instant::now() - Duration::from_secs(5)) {
conn.send_raw_packet(PRUDPPacket { conn.send_raw_packet(PRUDPV1Packet {
header: PRUDPHeader { header: PRUDPV1Header {
sequence_id: 0, sequence_id: 0,
substream_id: 0, substream_id: 0,
session_id: 0, session_id: 0,
@ -408,7 +408,7 @@ impl<T: CryptoHandler> InternalSocket<T> {
.expect("connection to external socket lost"); .expect("connection to external socket lost");
} }
async fn handle_connect(&self, address: PRUDPSockAddr, packet: PRUDPPacket) { async fn handle_connect(&self, address: PRUDPSockAddr, packet: PRUDPV1Packet) {
info!("got connect"); info!("got connect");
let Some(MaximumSubstreamId(max_substream)) = packet let Some(MaximumSubstreamId(max_substream)) = packet
.options .options
@ -479,7 +479,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: PRUDPPacket) { async fn handle_data(&self, address: PRUDPSockAddr, mut 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)
@ -524,7 +524,7 @@ impl<T: CryptoHandler> InternalSocket<T> {
} }
} }
async fn handle_ping(&self, address: PRUDPSockAddr, packet: PRUDPPacket) { async fn handle_ping(&self, address: PRUDPSockAddr, packet: PRUDPV1Packet) {
let connections = self.internal_connections.lock().await; let connections = self.internal_connections.lock().await;
let Some(conn) = connections.get(&address) else { let Some(conn) = connections.get(&address) else {
error!("tried to send data on inactive connection!"); error!("tried to send data on inactive connection!");
@ -544,7 +544,7 @@ impl<T: CryptoHandler> InternalSocket<T> {
self.send_packet_unbuffered(address, response).await; self.send_packet_unbuffered(address, response).await;
} }
async fn handle_disconnect(&self, address: PRUDPSockAddr, packet: PRUDPPacket) { async fn handle_disconnect(&self, address: PRUDPSockAddr, packet: PRUDPV1Packet) {
let connections = self.internal_connections.lock().await; let connections = self.internal_connections.lock().await;
let Some(conn) = connections.get(&address) else { let Some(conn) = connections.get(&address) else {
error!("tried to send data on inactive connection!"); error!("tried to send data on inactive connection!");
@ -571,7 +571,7 @@ impl<T: CryptoHandler> InternalSocket<T> {
#[async_trait] #[async_trait]
impl<T: CryptoHandler> AnyInternalSocket for InternalSocket<T> { impl<T: CryptoHandler> AnyInternalSocket for InternalSocket<T> {
async fn receive_packet(&self, address: PRUDPSockAddr, packet: PRUDPPacket) { async fn receive_packet(&self, address: PRUDPSockAddr, packet: PRUDPV1Packet) {
// todo: handle acks and resending // todo: handle acks and resending
if let Some(conn) = self.get_connection(address).await { if let Some(conn) = self.get_connection(address).await {
@ -643,8 +643,8 @@ impl<T: CryptoHandler> AnyInternalSocket for InternalSocket<T> {
let remote_signature = address.calculate_connection_signature(); let remote_signature = address.calculate_connection_signature();
let packet = PRUDPPacket { let packet = PRUDPV1Packet {
header: PRUDPHeader { header: PRUDPV1Header {
source_port: self.virtual_port, source_port: self.virtual_port,
destination_port: address.virtual_port, destination_port: address.virtual_port,
types_and_flags: TypesFlags::default().types(SYN).flags(NEED_ACK), types_and_flags: TypesFlags::default().types(SYN).flags(NEED_ACK),
@ -674,8 +674,8 @@ impl<T: CryptoHandler> AnyInternalSocket for InternalSocket<T> {
return None; return None;
}; };
let packet = PRUDPPacket { let packet = PRUDPV1Packet {
header: PRUDPHeader { header: PRUDPV1Header {
source_port: self.virtual_port, source_port: self.virtual_port,
destination_port: address.virtual_port, destination_port: address.virtual_port,
types_and_flags: TypesFlags::default().types(CONNECT).flags(NEED_ACK), types_and_flags: TypesFlags::default().types(CONNECT).flags(NEED_ACK),
@ -746,9 +746,9 @@ pub trait CryptoHandlerConnectionInstance: Send + Sync + 'static {
fn encrypt_outgoing(&mut self, substream: u8, data: &mut [u8]); fn encrypt_outgoing(&mut self, substream: u8, data: &mut [u8]);
fn get_user_id(&self) -> u32; fn get_user_id(&self) -> u32;
fn sign_connect(&self, packet: &mut PRUDPPacket); fn sign_connect(&self, packet: &mut PRUDPV1Packet);
fn sign_packet(&self, packet: &mut PRUDPPacket); fn sign_packet(&self, packet: &mut PRUDPV1Packet);
fn verify_packet(&self, packet: &PRUDPPacket) -> bool; fn verify_packet(&self, packet: &PRUDPV1Packet) -> bool;
} }
pub trait CryptoHandler: Send + Sync + 'static { pub trait CryptoHandler: Send + Sync + 'static {
@ -762,7 +762,7 @@ pub trait CryptoHandler: Send + Sync + 'static {
substream_count: u8, substream_count: u8,
) -> Option<(Vec<u8>, Self::CryptoConnectionInstance)>; ) -> Option<(Vec<u8>, Self::CryptoConnectionInstance)>;
fn sign_pre_handshake(&self, packet: &mut PRUDPPacket); fn sign_pre_handshake(&self, packet: &mut PRUDPV1Packet);
} }
impl Deref for ExternalConnection { impl Deref for ExternalConnection {
@ -813,6 +813,12 @@ impl SendingConnection {
impl<E: CryptoHandlerConnectionInstance> Drop for InternalConnection<E> { impl<E: CryptoHandlerConnectionInstance> Drop for InternalConnection<E> {
fn drop(&mut self) { fn drop(&mut self) {
println!("yatta"); println!("yatta(internal conn)");
}
}
impl Drop for CommonConnection {
fn drop(&mut self) {
println!("yatta(common conn)");
} }
} }

View file

@ -1,7 +1,7 @@
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
use rc4::{Key, KeyInit, Rc4, StreamCipher}; use rc4::{Key, KeyInit, Rc4, StreamCipher};
use typenum::U5; use typenum::U5;
use crate::prudp::packet::PRUDPPacket; use crate::prudp::packet::PRUDPV1Packet;
use crate::prudp::socket::{CryptoHandler, CryptoHandlerConnectionInstance, EncryptionPair}; use crate::prudp::socket::{CryptoHandler, CryptoHandlerConnectionInstance, EncryptionPair};
pub struct Unsecure(pub &'static str); pub struct Unsecure(pub &'static str);
@ -43,7 +43,7 @@ impl CryptoHandler for Unsecure {
)) ))
} }
fn sign_pre_handshake(&self, packet: &mut PRUDPPacket) { fn sign_pre_handshake(&self, packet: &mut PRUDPV1Packet) {
packet.set_sizes(); packet.set_sizes();
packet.calculate_and_assign_signature(self.0, None, None); packet.calculate_and_assign_signature(self.0, None, None);
} }
@ -68,17 +68,17 @@ impl CryptoHandlerConnectionInstance for UnsecureInstance {
0 0
} }
fn sign_connect(&self, packet: &mut PRUDPPacket) { fn sign_connect(&self, packet: &mut PRUDPV1Packet) {
packet.set_sizes(); packet.set_sizes();
packet.calculate_and_assign_signature(self.key, None, Some(self.self_signature)); packet.calculate_and_assign_signature(self.key, None, Some(self.self_signature));
} }
fn sign_packet(&self, packet: &mut PRUDPPacket) { fn sign_packet(&self, packet: &mut PRUDPV1Packet) {
packet.set_sizes(); packet.set_sizes();
packet.calculate_and_assign_signature(self.key, None, Some(self.self_signature)); packet.calculate_and_assign_signature(self.key, None, Some(self.self_signature));
} }
fn verify_packet(&self, packet: &PRUDPPacket) -> bool { fn verify_packet(&self, packet: &PRUDPV1Packet) -> bool {
true true
} }
} }

144
src/reggie.rs Normal file
View file

@ -0,0 +1,144 @@
use std::{fs, io};
use std::sync::Arc;
use macros::{method_id, rmc_proto, rmc_struct};
use once_cell::sync::Lazy;
use rustls::{ClientConfig, RootCertStore, ServerConfig};
use rustls::client::WebPkiServerVerifier;
use rustls::server::WebPkiClientVerifier;
use rustls_pki_types::{CertificateDer, PrivateKeyDer, ServerName, TrustAnchor};
use tokio::io::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt};
use tokio::net::TcpStream;
use tokio_rustls::{TlsAcceptor, TlsConnector};
use tokio_rustls::client::TlsStream;
use webpki::anchor_from_trusted_cert;
use crate::define_rmc_proto;
use crate::endianness::IS_BIG_ENDIAN;
use crate::rmc::response::ErrorCode;
use crate::rmc::structures::RmcSerialize;
pub static SELF_CERT: Lazy<CertificateDer<'static>> = Lazy::new(|| CertificateDer::from(fs::read("/opt/reggie/certs/SELF.crt").expect("failed to read self cpub ertificate")));
pub static ROOT_CA: Lazy<CertificateDer<'static>> = Lazy::new(|| CertificateDer::from(fs::read("/opt/reggie/certs/CA.crt").expect("failed to read root certipub ficate")));
pub static SELF_KEY: Lazy<PrivateKeyDer<'static>> = Lazy::new(|| PrivateKeyDer::try_from(fs::read("/opt/reggie/certs/SELF.key").expect("failed to read self pub key")).expect("failed to read self key"));
pub static ROOT_TRUST_ANCHOR: Lazy<TrustAnchor<'static>> = Lazy::new(|| anchor_from_trusted_cert(&*ROOT_CA).expect("unable to create root ca trust anchor"));
pub fn get_root_store() -> RootCertStore {
RootCertStore {
roots: vec![
ROOT_TRUST_ANCHOR.clone()
],
}
}
pub fn get_root_cert_verifier() -> RootCertStore {
RootCertStore {
roots: vec![
ROOT_TRUST_ANCHOR.clone()
],
}
}
pub async fn get_configured_tls_acceptor() -> TlsAcceptor{
let store = get_root_store();
let cert_verifier = WebPkiClientVerifier::builder(store.into())
.build()
.expect("unable to build cert verifier");
let config = ServerConfig::builder()
//.with_no_client_auth()
.with_client_cert_verifier(cert_verifier)
.with_single_cert(vec![
SELF_CERT.clone(),
ROOT_CA.clone()
], SELF_KEY.clone_key())
.expect("unable to create server config");
TlsAcceptor::from(Arc::new(config))
}
pub async fn get_configured_tls_connector() -> TlsConnector{
let store = get_root_store();
let cert_verifier = WebPkiServerVerifier::builder(store.into())
.build()
.expect("unable to build cert verifier");
let config = ClientConfig::builder()
//.with_root_certificates(get_root_store())
.with_webpki_verifier(cert_verifier)
.with_client_auth_cert(vec![
SELF_CERT.clone(),
ROOT_CA.clone()
], SELF_KEY.clone_key())
.expect("unable to create client config");
TlsConnector::from(Arc::new(config))
}
pub trait UnitPacketRead: AsyncRead + Unpin{
async fn read_buffer(&mut self) -> Result<Vec<u8>, io::Error>{
let mut len_raw: [u8; 4] = [0; 4];
self.read_exact(&mut len_raw).await?;
let len = u32::from_le_bytes(len_raw);
let mut vec = vec![0u8; len as _];
self.read_exact(&mut vec).await?;
Ok(vec)
}
}
impl<T: AsyncRead + Unpin> UnitPacketRead for T{}
pub trait UnitPacketWrite: AsyncWrite + Unpin{
async fn send_buffer(&mut self, data: &[u8]) -> Result<(), io::Error> {
let mut dest_data = Vec::new();
data.serialize(&mut dest_data).expect("ran out of memory or something");
self.write_all(&dest_data[..]).await?;
self.flush().await?;
Ok(())
}
}
impl<T: AsyncWrite + Unpin> UnitPacketWrite for T{}
pub async fn establish_tls_connection_to(address: &str, server_name: &'static str) -> TlsStream<TcpStream>{
let connector = get_configured_tls_connector().await;
let stream = TcpStream::connect(address).await.unwrap();
let stream = connector.connect(ServerName::try_from(server_name).unwrap(), stream).await
.expect("unable to connect via tls");
stream
}
#[rmc_proto(1)]
pub trait RmcTestProto{
#[method_id(1)]
async fn test(&self) -> Result<String, ErrorCode>;
}
define_rmc_proto!(
proto TestProto{
RmcTestProto
}
);
#[rmc_struct(TestProto)]
pub struct TestStruct;
impl RmcTestProto for TestStruct{
async fn test(&self) -> Result<String, ErrorCode> {
Ok("heya".into())
}
}

View file

@ -9,6 +9,7 @@ pub mod nat_traversal;
pub mod matchmake_ext; pub mod matchmake_ext;
pub mod ranking; pub mod ranking;
use crate::util::{SendingBufferConnection, SplittableBufferConnection};
use crate::prudp::socket::{ExternalConnection, SendingConnection}; 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;
@ -45,7 +46,7 @@ pub enum RemoteCallError {
InvalidResponse(#[from] structures::Error), InvalidResponse(#[from] structures::Error),
} }
pub struct RmcConnection(pub SendingConnection, pub RmcResponseReceiver); pub struct RmcConnection(pub SendingBufferConnection, pub RmcResponseReceiver);
pub struct RmcResponseReceiver(Arc<Notify>, Arc<Mutex<HashMap<u32, RMCResponse>>>); pub struct RmcResponseReceiver(Arc<Notify>, Arc<Mutex<HashMap<u32, RMCResponse>>>);
@ -141,7 +142,7 @@ pub trait RmcCallable {
//type Remote: RemoteObject; //type Remote: RemoteObject;
fn rmc_call( fn rmc_call(
&self, &self,
responder: &SendingConnection, responder: &SendingBufferConnection,
protocol_id: u16, protocol_id: u16,
method_id: u32, method_id: u32,
call_id: u32, call_id: u32,
@ -156,7 +157,7 @@ macro_rules! define_rmc_proto {
}) => { }) => {
paste::paste!{ paste::paste!{
pub trait [<Local $name>]: std::any::Any $( + [<Raw $protocol>] + $protocol)* { pub trait [<Local $name>]: std::any::Any $( + [<Raw $protocol>] + $protocol)* {
async fn rmc_call(&self, remote_response_connection: &crate::prudp::socket::SendingConnection, protocol_id: u16, method_id: u32, call_id: u32, rest: Vec<u8>){ async fn rmc_call(&self, remote_response_connection: &splatoon_server_rust::util::SendingBufferConnection, protocol_id: u16, method_id: u32, call_id: u32, rest: Vec<u8>){
match protocol_id{ match protocol_id{
$( $(
[<Raw $protocol Info>]::PROTOCOL_ID => <Self as [<Raw $protocol>]>::rmc_call_proto(self, remote_response_connection, method_id, call_id, rest).await, [<Raw $protocol Info>]::PROTOCOL_ID => <Self as [<Raw $protocol>]>::rmc_call_proto(self, remote_response_connection, method_id, call_id, rest).await,
@ -166,16 +167,16 @@ macro_rules! define_rmc_proto {
} }
} }
pub struct [<Remote $name>](crate::rmc::protocols::RmcConnection); pub struct [<Remote $name>](splatoon_server_rust::rmc::protocols::RmcConnection);
impl crate::rmc::protocols::RemoteInstantiatable for [<Remote $name>]{ impl splatoon_server_rust::rmc::protocols::RemoteInstantiatable for [<Remote $name>]{
fn new(conn: crate::rmc::protocols::RmcConnection) -> Self{ fn new(conn: splatoon_server_rust::rmc::protocols::RmcConnection) -> Self{
Self(conn) Self(conn)
} }
} }
impl crate::rmc::protocols::HasRmcConnection for [<Remote $name>]{ impl splatoon_server_rust::rmc::protocols::HasRmcConnection for [<Remote $name>]{
fn get_connection(&self) -> &crate::rmc::protocols::RmcConnection{ fn get_connection(&self) -> &splatoon_server_rust::rmc::protocols::RmcConnection{
&self.0 &self.0
} }
} }
@ -191,7 +192,7 @@ macro_rules! define_rmc_proto {
impl RmcCallable for () { impl RmcCallable for () {
async fn rmc_call( async fn rmc_call(
&self, &self,
remote_response_connection: &crate::prudp::socket::SendingConnection, remote_response_connection: &SendingBufferConnection,
protocol_id: u16, protocol_id: u16,
method_id: u32, method_id: u32,
call_id: u32, call_id: u32,
@ -222,13 +223,13 @@ impl<T: RemoteInstantiatable> OnlyRemote<T>{
} }
impl<T: RemoteInstantiatable> RmcCallable for OnlyRemote<T>{ impl<T: RemoteInstantiatable> RmcCallable for OnlyRemote<T>{
fn rmc_call(&self, responder: &SendingConnection, 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 std::future::Future<Output = ()> + Send {
async{} async{}
} }
} }
async fn handle_incoming<T: RmcCallable + Send + Sync + 'static>( async fn handle_incoming<T: RmcCallable + Send + Sync + 'static>(
mut connection: ExternalConnection, mut connection: SplittableBufferConnection,
remote: Arc<T>, remote: Arc<T>,
notify: Arc<Notify>, notify: Arc<Notify>,
incoming: Arc<Mutex<HashMap<u32, RMCResponse>>>, incoming: Arc<Mutex<HashMap<u32, RMCResponse>>>,
@ -278,7 +279,7 @@ async fn handle_incoming<T: RmcCallable + Send + Sync + 'static>(
info!("rmc disconnected") info!("rmc disconnected")
} }
pub fn new_rmc_gateway_connection<T: RmcCallable + Sync + Send + 'static,F>(conn: ExternalConnection, create_internal: F) -> Arc<T> pub fn new_rmc_gateway_connection<T: RmcCallable + Sync + Send + 'static,F>(conn: SplittableBufferConnection, create_internal: F) -> Arc<T>
where where
F: FnOnce(RmcConnection) -> Arc<T>, F: FnOnce(RmcConnection) -> Arc<T>,
{ {

View file

@ -5,7 +5,7 @@ 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::{PRUDPPacket}; use crate::prudp::packet::{PRUDPV1Packet};
use crate::prudp::packet::flags::{NEED_ACK, RELIABLE}; use crate::prudp::packet::flags::{NEED_ACK, RELIABLE};
use crate::prudp::packet::PacketOption::FragmentId; use crate::prudp::packet::PacketOption::FragmentId;
use crate::prudp::packet::types::DATA; use crate::prudp::packet::types::DATA;
@ -13,6 +13,8 @@ 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::rmc::structures::RmcSerialize;
use crate::util::SendingBufferConnection;
pub enum RMCResponseResult { pub enum RMCResponseResult {
Success { Success {
call_id: u32, call_id: u32,
@ -145,7 +147,7 @@ pub fn generate_response(protocol_id: u8, response: RMCResponseResult) -> io::Re
} }
pub async fn send_result( pub async fn send_result(
connection: &SendingConnection, connection: &SendingBufferConnection,
result: Result<Vec<u8>, ErrorCode>, result: Result<Vec<u8>, ErrorCode>,
protocol_id: u8, protocol_id: u8,
method_id: u32, method_id: u32,
@ -173,7 +175,7 @@ pub async fn send_result(
send_response(connection, response).await send_response(connection, response).await
} }
pub async fn send_response(connection: &SendingConnection, rmcresponse: RMCResponse) { pub async fn send_response(connection: &SendingBufferConnection, rmcresponse: RMCResponse) {
connection.send(rmcresponse.to_data()).await; connection.send(rmcresponse.to_data()).await;
} }

View file

@ -33,10 +33,19 @@ pub mod primitives;
pub mod matchmake; pub mod matchmake;
pub mod variant; pub mod variant;
pub mod ranking; pub mod ranking;
mod networking;
pub trait RmcSerialize: Sized{ pub trait RmcSerialize: Sized{
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>;
fn to_data(&self) -> Vec<u8>{
let mut data = Vec::new();
self.serialize(&mut data).expect("out of memory or something");
data
}
} }
impl RmcSerialize for (){ impl RmcSerialize for (){
@ -46,4 +55,6 @@ impl RmcSerialize for (){
fn deserialize(reader: &mut dyn Read) -> Result<Self> { fn deserialize(reader: &mut dyn Read) -> Result<Self> {
Ok(()) Ok(())
} }
} }

View file

@ -0,0 +1,32 @@
use std::io::{Read, Write};
use std::net::{Ipv4Addr, SocketAddrV4};
use crate::prudp::packet::VirtualPort;
use crate::rmc::structures::RmcSerialize;
impl RmcSerialize for SocketAddrV4{
fn serialize(&self, writer: &mut dyn Write) -> crate::rmc::structures::Result<()> {
self.ip().to_bits().serialize(writer)?;
self.port().serialize(writer)?;
Ok(())
}
fn deserialize(reader: &mut dyn Read) -> crate::rmc::structures::Result<Self> {
let ip = u32::deserialize(reader)?;
let port = u16::deserialize(reader)?;
Ok(SocketAddrV4::new(Ipv4Addr::from_bits(ip), port))
}
}
impl RmcSerialize for VirtualPort{
fn serialize(&self, writer: &mut dyn Write) -> crate::rmc::structures::Result<()> {
self.0.serialize(writer)?;
Ok(())
}
fn deserialize(reader: &mut dyn Read) -> crate::rmc::structures::Result<Self> {
Ok(Self(u8::deserialize(reader)?))
}
}

10
src/rnex_proxy_common.rs Normal file
View file

@ -0,0 +1,10 @@
use macros::RmcSerialize;
use crate::kerberos::KerberosDateTime;
use crate::prudp::sockaddr::PRUDPSockAddr;
#[derive(Debug, RmcSerialize)]
#[rmc_struct(0)]
pub struct ConnectionInitData{
pub prudpsock_addr: PRUDPSockAddr,
}

94
src/util.rs Normal file
View file

@ -0,0 +1,94 @@
use std::cell::UnsafeCell;
use std::marker::PhantomData;
use std::ops::Deref;
use log::error;
use tokio::io::{AsyncRead, AsyncWrite};
use tokio::sync::mpsc::{channel, Receiver, Sender};
use tokio::task;
use splatoon_server_rust::reggie::{UnitPacketRead, UnitPacketWrite};
#[derive(Clone)]
pub struct SendingBufferConnection(Sender<Vec<u8>>);
pub struct SplittableBufferConnection(SendingBufferConnection, Receiver<Vec<u8>>);
impl AsRef<SendingBufferConnection> for SplittableBufferConnection{
fn as_ref(&self) -> &SendingBufferConnection {
&self.0
}
}
impl Deref for SplittableBufferConnection{
type Target = SendingBufferConnection;
fn deref(&self) -> &Self::Target {
self.as_ref()
}
}
impl<T: Send + Unpin + AsyncWrite + AsyncRead + 'static> From<T> for SplittableBufferConnection{
fn from(value: T) -> Self {
Self::new(value)
}
}
impl SplittableBufferConnection {
fn new<T: Send + Unpin + AsyncWrite + AsyncRead + 'static>(stream: T) -> Self {
let (outside_send, inside_recv) = channel::<Vec<u8>>(10);
let (inside_send, outside_recv) = channel::<Vec<u8>>(10);
task::spawn(async move {
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);
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{
error!("a send error occurred {}", e);
return;
}
},
}
}
});
Self(SendingBufferConnection(outside_send), outside_recv)
}
}
impl SendingBufferConnection{
pub async fn send(&self, buffer: Vec<u8>) -> Option<()>{
self.0.send(buffer).await.ok()
}
}
impl SplittableBufferConnection{
pub async fn recv(&mut self) -> Option<Vec<u8>>{
self.1.recv().await
}
pub fn duplicate_sender(&self) -> SendingBufferConnection{
self.0.clone()
}
}

View file

@ -45,7 +45,7 @@ async fn players_in_match(mmm: &State<Arc<MatchmakeManager>>, gid: u32) -> Optio
Some(Json(gathering.connected_players.iter().filter_map(|p| p.upgrade()).map(|p| p.pid).collect())) Some(Json(gathering.connected_players.iter().filter_map(|p| p.upgrade()).map(|p| p.pid).collect()))
} }
/*
#[get("/player/<pid>/disconnect")] #[get("/player/<pid>/disconnect")]
async fn disconnect_player(_auth: RnexApiAuth, mmm: &State<Arc<MatchmakeManager>>, pid: u32) -> Option<()>{ async fn disconnect_player(_auth: RnexApiAuth, mmm: &State<Arc<MatchmakeManager>>, pid: u32) -> Option<()>{
// this doesnt work and is broken, there might be some other way to remotely close gatherings... // this doesnt work and is broken, there might be some other way to remotely close gatherings...
@ -59,7 +59,7 @@ async fn disconnect_player(_auth: RnexApiAuth, mmm: &State<Arc<MatchmakeManager>
Some(()) Some(())
} }*/
#[get("/gathering/<gid>/close")] #[get("/gathering/<gid>/close")]
async fn close_gathering(_auth: RnexApiAuth, mmm: &State<Arc<MatchmakeManager>>, gid: u32) -> Option<()>{ async fn close_gathering(_auth: RnexApiAuth, mmm: &State<Arc<MatchmakeManager>>, gid: u32) -> Option<()>{
@ -89,7 +89,7 @@ async fn close_gathering(_auth: RnexApiAuth, mmm: &State<Arc<MatchmakeManager>>,
pub async fn start_web(mgr: Arc<MatchmakeManager>) -> JoinHandle<()> { pub async fn start_web(mgr: Arc<MatchmakeManager>) -> JoinHandle<()> {
tokio::spawn(async move { tokio::spawn(async move {
rocket::build() rocket::build()
.mount("/", routes![gatherings, players_in_match, close_gathering, disconnect_player]) .mount("/", routes![gatherings, players_in_match, close_gathering])
.manage(mgr) .manage(mgr)
.launch().await .launch().await
.expect("unable to start webserver"); .expect("unable to start webserver");