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
|
|
@ -23,9 +23,11 @@ use tokio::net::{TcpListener, TcpSocket};
|
|||
use tokio::task;
|
||||
use tokio_rustls::TlsAcceptor;
|
||||
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::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::structures::RmcSerialize;
|
||||
use rust_nex::rnex_proxy_common::ConnectionInitData;
|
||||
|
|
@ -44,17 +46,21 @@ pub static SECURE_PROXY_PORT: Lazy<u16> = Lazy::new(|| {
|
|||
.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]
|
||||
async fn main() {
|
||||
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 listen = TcpListener::bind(SocketAddrV4::new(*OWN_IP_PRIVATE, *SERVER_PORT)).await.unwrap();
|
||||
|
|
@ -84,14 +90,14 @@ async fn main() {
|
|||
continue;
|
||||
}
|
||||
};
|
||||
|
||||
let controller = conn.clone();
|
||||
task::spawn(async move {
|
||||
info!("connection to secure backend established");
|
||||
new_rmc_gateway_connection(stream.into(), |_| {
|
||||
Arc::new(AuthHandler {
|
||||
destination_server_acct: &SECURE_SERVER_ACCOUNT,
|
||||
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::task;
|
||||
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::remote_console::RemoteConsole;
|
||||
use rust_nex::nex::user::User;
|
||||
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::rmc::protocols::RemoteInstantiatable;
|
||||
|
||||
|
|
@ -22,6 +24,16 @@ use rust_nex::rmc::protocols::RemoteInstantiatable;
|
|||
async fn main() {
|
||||
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 listen = TcpListener::bind(SocketAddrV4::new(*OWN_IP_PRIVATE, *SERVER_PORT)).await.unwrap();
|
||||
|
|
|
|||
|
|
@ -1,7 +1,12 @@
|
|||
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 tonic::transport::Server;
|
||||
use rust_nex::define_rmc_proto;
|
||||
use rust_nex::prudp::station_url::StationUrl;
|
||||
use crate::nex::account::Account;
|
||||
use crate::rmc::response::ErrorCode;
|
||||
|
||||
pub static OWN_IP_PRIVATE: Lazy<Ipv4Addr> = Lazy::new(|| {
|
||||
env::var("SERVER_IP")
|
||||
|
|
@ -10,6 +15,13 @@ pub static OWN_IP_PRIVATE: Lazy<Ipv4Addr> = Lazy::new(|| {
|
|||
.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(|| {
|
||||
env::var("SERVER_PORT")
|
||||
.ok()
|
||||
|
|
@ -27,3 +39,52 @@ 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_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::ffi::CStr;
|
||||
use std::io::{Read, Write};
|
||||
use std::net::{Ipv4Addr, SocketAddrV4, TcpListener, TcpStream};
|
||||
use std::sync::{Arc, OnceLock};
|
||||
use std::time::Duration;
|
||||
use bytemuck::{Pod, Zeroable};
|
||||
use chacha20::{ChaCha20, Key};
|
||||
use chacha20::cipher::{Iv, KeyIvInit, StreamCipher};
|
||||
use log::error;
|
||||
use log::{error, warn};
|
||||
use macros::rmc_struct;
|
||||
use once_cell::sync::Lazy;
|
||||
use rsa::pkcs8::{DecodePrivateKey, DecodePublicKey, Document};
|
||||
use rsa::{BigUint, Pkcs1v15Encrypt, RsaPrivateKey, RsaPublicKey};
|
||||
|
|
@ -16,13 +20,20 @@ use rsa::pss::BlindedSigningKey;
|
|||
use rsa::signature::{RandomizedSigner, SignatureEncoding};
|
||||
use sha2::Sha256;
|
||||
use tokio::net::TcpSocket;
|
||||
use tokio::sync::RwLock;
|
||||
use tokio::task;
|
||||
use tokio::time::sleep;
|
||||
use rust_nex::common::setup;
|
||||
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::router::Router;
|
||||
use rust_nex::prudp::station_url::StationUrl;
|
||||
use rust_nex::prudp::unsecure::Unsecure;
|
||||
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::rnex_proxy_common::ConnectionInitData;
|
||||
|
||||
|
|
@ -33,30 +44,41 @@ static FORWARD_DESTINATION: Lazy<String> =
|
|||
static FORWARD_DESTINATION_NAME: Lazy<String> =
|
||||
Lazy::new(|| env::var("FORWARD_DESTINATION_NAME").expect("no forward destination name given"));
|
||||
|
||||
static RSA_PRIVKEY: Lazy<RsaPrivateKey> = Lazy::new(|| {
|
||||
let path = env::var("RSA_PRIVKEY")
|
||||
.expect("RSA_PRIVKEY not set");
|
||||
#[rmc_struct(Proxy)]
|
||||
#[derive(Default)]
|
||||
struct DestinationHolder{
|
||||
url: RwLock<String>
|
||||
}
|
||||
|
||||
RsaPrivateKey::read_pkcs8_pem_file(&path)
|
||||
.expect("unable to read private key")
|
||||
});
|
||||
impl ProxyManagement for DestinationHolder{
|
||||
async fn update_url(&self, new_url: String) -> Result<(), ErrorCode> {
|
||||
println!("updating url");
|
||||
|
||||
static RSA_PUBKEY: Lazy<RsaPublicKey> = Lazy::new(|| {
|
||||
RSA_PRIVKEY.to_public_key()
|
||||
});
|
||||
let mut url = self.url.write().await;
|
||||
|
||||
static PUBKEY_ENCODED: Lazy<Document> = Lazy::new(|| {
|
||||
RSA_PUBKEY.to_pkcs1_der().expect("unable to convert pubkey to der")
|
||||
});
|
||||
*url = new_url;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
static RSA_SIGNKEY: Lazy<BlindedSigningKey<Sha256>> = Lazy::new(||
|
||||
BlindedSigningKey::<Sha256>::new(RSA_PRIVKEY.clone())
|
||||
);
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
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))
|
||||
.await
|
||||
.expect("unable to start router");
|
||||
|
|
@ -76,9 +98,18 @@ async fn main() {
|
|||
return;
|
||||
};
|
||||
|
||||
let dest_holder = dest_holder.clone();
|
||||
|
||||
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
|
||||
= 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{
|
||||
prudpsock_addr: conn.socket_addr,
|
||||
|
|
@ -113,6 +144,9 @@ async fn main() {
|
|||
return;
|
||||
}
|
||||
},
|
||||
_ = sleep(Duration::from_secs(10)) => {
|
||||
conn.send([0,0,0,0,0].to_vec()).await;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,43 +1,65 @@
|
|||
|
||||
|
||||
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 std::net::SocketAddrV4;
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
use futures::future::Remote;
|
||||
use log::{error, warn};
|
||||
use macros::rmc_struct;
|
||||
use tokio::sync::RwLock;
|
||||
use tokio::task;
|
||||
use tokio::time::sleep;
|
||||
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::router::Router;
|
||||
use rust_nex::prudp::secure::Secure;
|
||||
use rust_nex::prudp::unsecure::Unsecure;
|
||||
use rust_nex::reggie::{establish_tls_connection_to, UnitPacketRead, UnitPacketWrite};
|
||||
use rust_nex::rmc::structures::RmcSerialize;
|
||||
use rust_nex::reggie::establish_tls_connection_to;
|
||||
use rust_nex::rmc::response::ErrorCode;
|
||||
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]
|
||||
async fn main() {
|
||||
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))
|
||||
.await
|
||||
.expect("unable to start router");
|
||||
|
|
@ -45,7 +67,7 @@ async fn main() {
|
|||
let mut socket_secure = router_secure
|
||||
.add_socket(VirtualPort::new(1, 10), Secure(
|
||||
"6f599f81",
|
||||
&SECURE_SERVER_ACCOUNT
|
||||
dest_holder.controller.get_secure_account().await.unwrap()
|
||||
))
|
||||
.await
|
||||
.expect("unable to add socket");
|
||||
|
|
@ -58,9 +80,18 @@ async fn main() {
|
|||
return;
|
||||
};
|
||||
|
||||
let dest_holder = dest_holder.clone();
|
||||
|
||||
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
|
||||
= 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{
|
||||
prudpsock_addr: conn.socket_addr,
|
||||
|
|
@ -70,6 +101,8 @@ async fn main() {
|
|||
return;
|
||||
};
|
||||
|
||||
|
||||
|
||||
loop {
|
||||
tokio::select! {
|
||||
data = conn.recv() => {
|
||||
|
|
@ -95,6 +128,9 @@ async fn main() {
|
|||
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::array::TryFromSliceError;
|
||||
use std::net::{Ipv4Addr};
|
||||
use std::str::FromStr;
|
||||
use json::{object, JsonValue};
|
||||
use once_cell::sync::Lazy;
|
||||
use reqwest::{Body, Method, Url};
|
||||
use reqwest::header::HeaderValue;
|
||||
use rocket::serde::json::Json;
|
||||
use serde::Serialize;
|
||||
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::InterceptorFunc;
|
||||
use crate::grpc::protobufs::account::account_client::AccountClient;
|
||||
use crate::grpc::protobufs::account::{GetNexPasswordRequest, GetUserDataRequest, GetUserDataResponse};
|
||||
|
||||
static API_KEY: Lazy<String> = Lazy::new(||{
|
||||
let key = env::var("ACCOUNT_GQL_API_KEY")
|
||||
.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;
|
||||
|
||||
pub mod endianness;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
#![allow(dead_code)]
|
||||
#![warn(missing_docs)]
|
||||
#![allow(async_fn_in_trait)]
|
||||
//#![warn(missing_docs)]
|
||||
|
||||
//! # Splatoon RNEX server
|
||||
//!
|
||||
|
|
@ -63,6 +64,7 @@ mod versions;
|
|||
mod web;
|
||||
pub mod reggie;
|
||||
pub mod util;
|
||||
pub mod common;
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,11 @@
|
|||
use macros::RmcSerialize;
|
||||
|
||||
|
||||
#[derive(RmcSerialize)]
|
||||
#[derive(Clone)]
|
||||
pub struct Account{
|
||||
pub pid: u32,
|
||||
pub username: Box<str>,
|
||||
pub username: String,
|
||||
pub kerbros_password: [u8; 16],
|
||||
|
||||
}
|
||||
|
||||
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::kerberos::{derive_key, KerberosDateTime, Ticket};
|
||||
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::connection_data::ConnectionData;
|
||||
use crate::rmc::structures::qresult::QResult;
|
||||
use crate::rmc::structures::RmcSerialize;
|
||||
use crate::{define_rmc_proto, kerberos, rmc};
|
||||
use crate::{define_rmc_proto, kerberos};
|
||||
use macros::rmc_struct;
|
||||
use crate::rmc::protocols::OnlyRemote;
|
||||
|
||||
define_rmc_proto!(
|
||||
proto AuthClientProtocol{
|
||||
|
|
@ -21,7 +24,8 @@ define_rmc_proto!(
|
|||
pub struct AuthHandler {
|
||||
pub destination_server_acct: &'static Account,
|
||||
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(
|
||||
|
|
@ -56,14 +60,14 @@ async fn get_login_data_by_pid(pid: u32) -> Option<(u32, [u8; 16])> {
|
|||
}
|
||||
|
||||
impl Auth for AuthHandler {
|
||||
async fn login(&self, name: String) -> Result<(), ErrorCode> {
|
||||
async fn login(&self, _name: String) -> Result<(), ErrorCode> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
async fn login_ex(
|
||||
&self,
|
||||
name: String,
|
||||
extra_data: Any,
|
||||
_extra_data: Any,
|
||||
) -> Result<(QResult, u32, Vec<u8>, ConnectionData, String), ErrorCode> {
|
||||
let Ok(pid) = name.parse() else {
|
||||
return Err(ErrorCode::Core_InvalidArgument);
|
||||
|
|
@ -83,9 +87,13 @@ impl Auth for AuthHandler {
|
|||
let ticket = generate_ticket(source_login_data, destination_login_data);
|
||||
|
||||
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 {
|
||||
station_url: self.station_url.to_string(),
|
||||
station_url: addr,
|
||||
special_station_url: "".to_string(),
|
||||
//date_time: KerberosDateTime::new(1,1,1,1,1,1),
|
||||
date_time: KerberosDateTime::now(),
|
||||
|
|
@ -126,11 +134,11 @@ impl Auth for AuthHandler {
|
|||
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)
|
||||
}
|
||||
|
||||
async fn get_name(&self, pid: u32) -> Result<String, ErrorCode> {
|
||||
async fn get_name(&self, _pid: u32) -> Result<String, ErrorCode> {
|
||||
Err(ErrorCode::Core_Exception)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ use std::collections::HashMap;
|
|||
use std::str::FromStr;
|
||||
use std::sync::{Arc, Weak};
|
||||
use std::sync::atomic::AtomicU32;
|
||||
use std::sync::atomic::Ordering::{Relaxed, Release};
|
||||
use std::sync::atomic::Ordering::Relaxed;
|
||||
use std::time::Duration;
|
||||
use log::info;
|
||||
use rand::random;
|
||||
|
|
@ -50,7 +50,7 @@ impl MatchmakeManager{
|
|||
async fn garbage_collect(&self){
|
||||
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();
|
||||
|
||||
|
|
@ -64,7 +64,7 @@ impl MatchmakeManager{
|
|||
|
||||
session_pair
|
||||
}{
|
||||
let mut session = session.lock().await;
|
||||
let session = session.lock().await;
|
||||
|
||||
if !session.is_reachable(){
|
||||
to_be_deleted_gids.push(gid);
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
use macros::rmc_struct;
|
||||
use crate::rmc::protocols::notifications::{Notification, NotificationEvent, RawNotification, RawNotificationInfo, RemoteNotification};
|
||||
use crate::rmc::protocols::notifications::{Notification, RawNotification, RawNotificationInfo, RemoteNotification};
|
||||
use crate::rmc::protocols::nat_traversal::{NatTraversalConsole, RemoteNatTraversalConsole, RawNatTraversalConsoleInfo, RawNatTraversalConsole};
|
||||
use crate::define_rmc_proto;
|
||||
use crate::nex::user::RemoteUserProtocol;
|
||||
|
||||
define_rmc_proto!(
|
||||
proto Console{
|
||||
|
|
|
|||
|
|
@ -1,14 +1,12 @@
|
|||
use std::io::ErrorKind::HostUnreachable;
|
||||
use crate::define_rmc_proto;
|
||||
use crate::nex::matchmake::{ExtendedMatchmakeSession, MatchmakeManager};
|
||||
use crate::nex::remote_console::RemoteConsole;
|
||||
use crate::prudp::sockaddr::PRUDPSockAddr;
|
||||
use crate::prudp::station_url::Type::{PRUDP, PRUDPS};
|
||||
use crate::prudp::station_url::UrlOptions::{
|
||||
Address, NatFiltering, NatMapping, NatType, Platform, Port, PrincipalID, RVConnectionID,
|
||||
StreamID, PMP, UPNP,
|
||||
Address, NatFiltering, NatMapping, NatType, Port, PrincipalID, RVConnectionID,
|
||||
|
||||
};
|
||||
use crate::prudp::station_url::{nat_types, StationUrl, Type};
|
||||
use crate::prudp::station_url::{StationUrl};
|
||||
use crate::rmc::protocols::matchmake::{
|
||||
Matchmake, RawMatchmake, RawMatchmakeInfo, RemoteMatchmake,
|
||||
};
|
||||
|
|
@ -24,15 +22,12 @@ use crate::rmc::structures::matchmake::{AutoMatchmakeParam, CreateMatchmakeSessi
|
|||
|
||||
use crate::rmc::structures::qresult::QResult;
|
||||
use macros::rmc_struct;
|
||||
use std::net::{Ipv4Addr, SocketAddrV4};
|
||||
use std::sync::{Arc, Weak};
|
||||
use log::{error, info};
|
||||
use rocket::http::ext::IntoCollection;
|
||||
use log::info;
|
||||
use tokio::sync::{Mutex, RwLock};
|
||||
use tonic::Code::InvalidArgument;
|
||||
use crate::prudp::station_url::nat_types::PUBLIC;
|
||||
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!(
|
||||
proto UserProtocol{
|
||||
|
|
@ -129,7 +124,7 @@ impl Secure for User {
|
|||
public_station
|
||||
};
|
||||
|
||||
let mut both = [&mut public_station, &mut private_station];
|
||||
let both = [&mut public_station, &mut private_station];
|
||||
|
||||
for station in both {
|
||||
station.options.retain(|v| {
|
||||
|
|
@ -208,7 +203,7 @@ impl MatchmakeExtension for User {
|
|||
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())
|
||||
}
|
||||
|
||||
|
|
@ -385,7 +380,7 @@ impl MatchmakeExtension 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)
|
||||
}
|
||||
async fn get_session_urls(&self, gid: u32) -> Result<Vec<StationUrl>, ErrorCode> {
|
||||
|
|
@ -460,7 +455,7 @@ impl Matchmake for User {
|
|||
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 mut session = session.lock().await;
|
||||
|
||||
|
|
@ -522,11 +517,11 @@ impl NatTraversal for User {
|
|||
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(())
|
||||
}
|
||||
|
||||
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!");
|
||||
Err(RendezVous_AccountExpired)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ use std::io::{Cursor, Read, Seek, Write};
|
|||
use std::net::SocketAddrV4;
|
||||
use bytemuck::{Pod, Zeroable};
|
||||
use hmac::{Hmac, Mac};
|
||||
use log::{error, trace, warn};
|
||||
use log::{error, warn};
|
||||
use md5::{Md5, Digest};
|
||||
use thiserror::Error;
|
||||
use v_byte_macros::{SwapEndian};
|
||||
|
|
|
|||
|
|
@ -5,11 +5,11 @@ use tokio::net::UdpSocket;
|
|||
use std::net::{SocketAddr, SocketAddrV4};
|
||||
use std::net::SocketAddr::V4;
|
||||
use std::sync::{Arc, Weak};
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::atomic::{AtomicBool};
|
||||
use std::time::Duration;
|
||||
use tokio::task::JoinHandle;
|
||||
use once_cell::sync::Lazy;
|
||||
use log::{error, info, trace};
|
||||
use log::{error, info};
|
||||
use thiserror::Error;
|
||||
use tokio::select;
|
||||
use tokio::sync::RwLock;
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ use crate::kerberos::{derive_key, TicketInternalData};
|
|||
use crate::nex::account::Account;
|
||||
use crate::prudp::packet::PRUDPV1Packet;
|
||||
use crate::prudp::socket::{CryptoHandler, CryptoHandlerConnectionInstance, EncryptionPair};
|
||||
use crate::prudp::unsecure::UnsecureInstance;
|
||||
use crate::rmc::structures::RmcSerialize;
|
||||
|
||||
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 {
|
||||
|
|
@ -186,7 +185,7 @@ impl CryptoHandlerConnectionInstance for SecureInstance {
|
|||
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
|
||||
}
|
||||
}
|
||||
|
|
@ -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::types::{CONNECT, DATA, DISCONNECT, PING, SYN};
|
||||
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::router::{Error, Router};
|
||||
use crate::prudp::packet::{PRUDPV1Header, PRUDPV1Packet, TypesFlags, VirtualPort};
|
||||
use crate::prudp::sockaddr::PRUDPSockAddr;
|
||||
use async_trait::async_trait;
|
||||
use chrono::NaiveTime;
|
||||
use hmac::digest::consts::U5;
|
||||
use log::info;
|
||||
use log::{error, trace, warn};
|
||||
use once_cell::sync::Lazy;
|
||||
use rand::random;
|
||||
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 log::error;
|
||||
use rc4::StreamCipher;
|
||||
use std::collections::{BTreeMap, HashMap};
|
||||
use std::marker::PhantomData;
|
||||
use std::mem;
|
||||
use std::net::SocketAddrV4;
|
||||
use std::ops::Deref;
|
||||
use std::pin::Pin;
|
||||
use std::sync::{Arc, Weak};
|
||||
|
||||
use std::time::Duration;
|
||||
use tokio::net::UdpSocket;
|
||||
use tokio::sync::mpsc::{channel, Receiver, Sender};
|
||||
use tokio::sync::{Mutex, RwLock};
|
||||
use tokio::sync::Mutex;
|
||||
use tokio::time::{sleep, Instant};
|
||||
use tokio_stream::Stream;
|
||||
// due to the way this is designed crashing the router thread causes deadlock, sorry ;-;
|
||||
// (maybe i will fix that some day)
|
||||
|
||||
|
|
@ -479,7 +466,7 @@ impl<T: CryptoHandler> InternalSocket<T> {
|
|||
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");
|
||||
|
||||
if packet.header.types_and_flags.get_flags() & (NEED_ACK | RELIABLE)
|
||||
|
|
@ -533,7 +520,7 @@ impl<T: CryptoHandler> InternalSocket<T> {
|
|||
let conn = conn.clone();
|
||||
drop(connections);
|
||||
|
||||
let mut conn = conn.lock().await;
|
||||
let conn = conn.lock().await;
|
||||
|
||||
let mut response = packet.base_acknowledgement_packet();
|
||||
response.header.types_and_flags.set_flag(HAS_SIZE | ACK);
|
||||
|
|
@ -553,7 +540,7 @@ impl<T: CryptoHandler> InternalSocket<T> {
|
|||
let conn = conn.clone();
|
||||
drop(connections);
|
||||
|
||||
let mut conn = conn.lock().await;
|
||||
let conn = conn.lock().await;
|
||||
|
||||
let mut response = packet.base_acknowledgement_packet();
|
||||
response.header.types_and_flags.set_flag(HAS_SIZE | ACK);
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ use std::net::Ipv4Addr;
|
|||
use log::error;
|
||||
use std::fmt::{Debug, Display, Formatter, Write};
|
||||
use std::io::Read;
|
||||
use rocket::delete;
|
||||
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::rmc::structures::Error::StationUrlInvalid;
|
||||
|
|
|
|||
228
src/reggie.rs
228
src/reggie.rs
|
|
@ -1,18 +1,26 @@
|
|||
use std::{env, fs, io};
|
||||
use std::io::{Error, ErrorKind};
|
||||
use std::pin::Pin;
|
||||
use std::sync::Arc;
|
||||
use std::task::{Context, Poll};
|
||||
use futures::{SinkExt, StreamExt};
|
||||
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 thiserror::Error;
|
||||
use tokio::io::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt, ReadBuf};
|
||||
use tokio::net::{TcpListener, TcpStream};
|
||||
use tokio_rustls::{TlsAcceptor, TlsConnector};
|
||||
use tokio_rustls::client::TlsStream;
|
||||
use tokio_tungstenite::{connect_async, WebSocketStream};
|
||||
use tokio_tungstenite::tungstenite::Message;
|
||||
use webpki::anchor_from_trusted_cert;
|
||||
use rust_nex::common::setup;
|
||||
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::structures::RmcSerialize;
|
||||
|
||||
|
|
@ -116,12 +124,12 @@ pub trait UnitPacketWrite: AsyncWrite + Unpin{
|
|||
|
||||
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 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");
|
||||
|
||||
stream
|
||||
|
|
@ -147,3 +155,213 @@ impl RmcTestProto for TestStruct{
|
|||
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 crate::prudp::station_url::StationUrl;
|
||||
use crate::rmc::response::ErrorCode;
|
||||
|
||||
#[rmc_proto(50)]
|
||||
|
|
|
|||
|
|
@ -10,28 +10,21 @@ pub mod matchmake_ext;
|
|||
pub mod ranking;
|
||||
|
||||
use crate::util::{SendingBufferConnection, SplittableBufferConnection};
|
||||
use crate::prudp::socket::{ExternalConnection, SendingConnection};
|
||||
use crate::rmc::message::RMCMessage;
|
||||
use crate::rmc::protocols::RemoteCallError::ConnectionBroke;
|
||||
use crate::rmc::response::{ErrorCode, RMCResponse, RMCResponseResult};
|
||||
use crate::rmc::structures;
|
||||
use crate::rmc::structures::connection_data::ConnectionData;
|
||||
use crate::rmc::structures::matchmake::AutoMatchmakeParam;
|
||||
use crate::rmc::structures::{Error, RmcSerialize};
|
||||
use async_trait::async_trait;
|
||||
use chrono::TimeDelta;
|
||||
use crate::rmc::structures::RmcSerialize;
|
||||
use log::{error, info};
|
||||
use macros::method_id;
|
||||
use macros::{rmc_proto, rmc_struct};
|
||||
use paste::paste;
|
||||
use std::collections::HashMap;
|
||||
use std::future::Future;
|
||||
use std::io::Cursor;
|
||||
use std::ops::{Add, Deref};
|
||||
use std::sync::{Arc, Condvar};
|
||||
use std::ops::Deref;
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
use thiserror::Error;
|
||||
use tokio::sync::{Mutex, Notify};
|
||||
use tokio::time::{sleep_until, Instant};
|
||||
use tokio::time::{sleep, sleep_until, Instant};
|
||||
use crate::result::ResultExtension;
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
|
|
@ -74,6 +67,10 @@ impl RmcConnection {
|
|||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn disconnect(&self){
|
||||
self.0.disconnect().await;
|
||||
}
|
||||
}
|
||||
|
||||
impl RmcResponseReceiver {
|
||||
|
|
@ -173,6 +170,9 @@ macro_rules! define_rmc_proto {
|
|||
fn new(conn: rust_nex::rmc::protocols::RmcConnection) -> Self{
|
||||
Self(conn)
|
||||
}
|
||||
async fn disconnect(&self){
|
||||
self.0.disconnect().await;
|
||||
}
|
||||
}
|
||||
|
||||
impl rust_nex::rmc::protocols::HasRmcConnection for [<Remote $name>]{
|
||||
|
|
@ -192,11 +192,11 @@ macro_rules! define_rmc_proto {
|
|||
impl RmcCallable for () {
|
||||
async fn rmc_call(
|
||||
&self,
|
||||
remote_response_connection: &SendingBufferConnection,
|
||||
protocol_id: u16,
|
||||
method_id: u32,
|
||||
call_id: u32,
|
||||
rest: Vec<u8>,
|
||||
_remote_response_connection: &SendingBufferConnection,
|
||||
_protocol_id: u16,
|
||||
_method_id: u32,
|
||||
_call_id: u32,
|
||||
_rest: Vec<u8>,
|
||||
) {
|
||||
//todo: maybe reply with not implemented(?)
|
||||
}
|
||||
|
|
@ -204,6 +204,7 @@ impl RmcCallable for () {
|
|||
|
||||
pub trait RemoteInstantiatable{
|
||||
fn new(conn: RmcConnection) -> Self;
|
||||
async fn disconnect(&self);
|
||||
}
|
||||
|
||||
pub struct OnlyRemote<T: RemoteInstantiatable>(T);
|
||||
|
|
@ -220,10 +221,15 @@ impl<T: RemoteInstantiatable> OnlyRemote<T>{
|
|||
pub fn new(conn: RmcConnection) -> Self{
|
||||
Self(T::new(conn))
|
||||
}
|
||||
|
||||
pub async fn disconnect(&self) {
|
||||
self.0.disconnect().await;
|
||||
}
|
||||
}
|
||||
|
||||
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{}
|
||||
}
|
||||
}
|
||||
|
|
@ -243,6 +249,12 @@ async fn handle_incoming<T: RmcCallable + Send + Sync + 'static>(
|
|||
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{
|
||||
let Some(response) = RMCResponse::new(&mut Cursor::new(v)).display_err_or_some() else {
|
||||
error!("ending rmc gateway.");
|
||||
|
|
@ -292,6 +304,8 @@ where
|
|||
|
||||
let rmc_conn = RmcConnection(sending_conn, response_recv);
|
||||
|
||||
let sending_conn = conn.duplicate_sender();
|
||||
|
||||
let exposed_object = (create_internal)(rmc_conn);
|
||||
|
||||
{
|
||||
|
|
@ -304,7 +318,25 @@ where
|
|||
incoming
|
||||
).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
|
||||
}
|
||||
|
||||
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 crate::rmc::response::ErrorCode;
|
||||
use crate::rmc::structures::matchmake::{CreateMatchmakeSessionParam, MatchmakeSession};
|
||||
|
||||
#[rmc_proto(3)]
|
||||
pub trait NatTraversal{
|
||||
|
|
|
|||
|
|
@ -1,6 +1,4 @@
|
|||
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 const OWNERSHIP_CHANGED: u32 = 4000;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use macros::{method_id, rmc_proto};
|
||||
use macros::rmc_proto;
|
||||
|
||||
#[rmc_proto(112)]
|
||||
pub trait Ranking{
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
use macros::{method_id, rmc_proto};
|
||||
use crate::prudp::station_url::StationUrl;
|
||||
use crate::rmc::response::ErrorCode;
|
||||
use crate::rmc::structures::any::Any;
|
||||
use crate::rmc::structures::connection_data::ConnectionData;
|
||||
use crate::rmc::structures::qresult::QResult;
|
||||
|
||||
#[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::{Read, Seek, Write};
|
||||
use std::mem::transmute;
|
||||
|
|
@ -5,14 +9,8 @@ use bytemuck::bytes_of;
|
|||
use log::error;
|
||||
use v_byte_macros::EnumTryInto;
|
||||
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::structures::qresult::ERROR_MASK;
|
||||
use crate::rmc::structures::RmcSerialize;
|
||||
use crate::util::SendingBufferConnection;
|
||||
|
||||
pub enum RMCResponseResult {
|
||||
|
|
@ -72,7 +70,7 @@ impl RMCResponse {
|
|||
error_code: {
|
||||
match ErrorCode::try_from(error_code){
|
||||
Ok(v) => v,
|
||||
Err(e) => {
|
||||
Err(()) => {
|
||||
error!("invalid error code {:#010x}", error_code);
|
||||
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<()> {
|
||||
(&self[..]).serialize(writer)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
use std::io::{Read, Write};
|
||||
use bytemuck::bytes_of;
|
||||
|
||||
use macros::RmcSerialize;
|
||||
use crate::kerberos::KerberosDateTime;
|
||||
use crate::rmc::structures::{rmc_struct, RmcSerialize};
|
||||
use crate::rmc::structures::RmcSerialize;
|
||||
|
||||
#[derive(Debug, RmcSerialize)]
|
||||
#[rmc_struct(1)]
|
||||
|
|
|
|||
|
|
@ -1,5 +1,8 @@
|
|||
use std::array::from_fn;
|
||||
use std::io::{Read, Write};
|
||||
use std::mem::MaybeUninit;
|
||||
use bytemuck::bytes_of;
|
||||
use serde::Serialize;
|
||||
use crate::endianness::{IS_BIG_ENDIAN, ReadExtensions};
|
||||
use crate::rmc::structures::RmcSerialize;
|
||||
|
||||
|
|
@ -31,3 +34,27 @@ impl<T: RmcSerialize> RmcSerialize for Vec<T>{
|
|||
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;
|
||||
mod networking;
|
||||
|
||||
pub trait RmcSerialize: Sized{
|
||||
pub trait RmcSerialize{
|
||||
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>{
|
||||
let mut data = Vec::new();
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ impl RmcSerialize for SocketAddrV4{
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
impl RmcSerialize for VirtualPort{
|
||||
fn serialize(&self, writer: &mut dyn Write) -> crate::rmc::structures::Result<()> {
|
||||
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))
|
||||
}
|
||||
}
|
||||
|
||||
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 crate::endianness::{IS_BIG_ENDIAN, ReadExtensions};
|
||||
use crate::rmc::structures::{Result, RmcSerialize};
|
||||
use crate::rmc::structures::qresult::QResult;
|
||||
|
||||
|
||||
#[derive(Debug)]
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
use macros::RmcSerialize;
|
||||
use crate::kerberos::KerberosDateTime;
|
||||
use crate::prudp::sockaddr::PRUDPSockAddr;
|
||||
|
||||
#[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 log::error;
|
||||
use tokio::io::{AsyncRead, AsyncWrite};
|
||||
use std::sync::Arc;
|
||||
use log::{error, info};
|
||||
use tokio::io::{AsyncRead, AsyncWrite, AsyncWriteExt};
|
||||
use tokio::sync::mpsc::{channel, Receiver, Sender};
|
||||
use tokio::sync::Notify;
|
||||
use tokio::task;
|
||||
use rust_nex::reggie::{UnitPacketRead, UnitPacketWrite};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct SendingBufferConnection(Sender<Vec<u8>>);
|
||||
pub struct SendingBufferConnection(Sender<Vec<u8>>, Arc<Notify>);
|
||||
|
||||
pub struct SplittableBufferConnection(SendingBufferConnection, Receiver<Vec<u8>>);
|
||||
|
||||
|
|
@ -39,41 +39,53 @@ impl SplittableBufferConnection {
|
|||
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;
|
||||
};
|
||||
let notify = Arc::new(Notify::new());
|
||||
|
||||
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);
|
||||
{
|
||||
let notify = notify.clone();
|
||||
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;
|
||||
if let Err(e) = sender.send(data).await{
|
||||
error!("a send error occurred {}", e);
|
||||
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<()>{
|
||||
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{
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use std::marker::PhantomData;
|
||||
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
|
||||
trait Version{
|
||||
|
|
|
|||
|
|
@ -1,15 +1,10 @@
|
|||
use std::net::SocketAddrV4;
|
||||
use std::sync::Arc;
|
||||
use async_trait::async_trait;
|
||||
use once_cell::sync::Lazy;
|
||||
use rocket::{get, routes, Request, Rocket, State};
|
||||
use rocket::{get, routes, Request, State};
|
||||
use rocket::request::{FromRequest, Outcome};
|
||||
use rocket::serde::json::Json;
|
||||
use tokio::task::JoinHandle;
|
||||
use serde::Serialize;
|
||||
use tokio::sync::Mutex;
|
||||
use crate::nex::matchmake::MatchmakeManager;
|
||||
use crate::rmc::protocols::HasRmcConnection;
|
||||
use crate::rmc::protocols::notifications::NotificationEvent;
|
||||
|
||||
struct RnexApiAuth;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue