2026-07-12 18:21:18 +02:00
|
|
|
use rnex_prudp::{socket_addr::PRUDPSockAddr, virtual_port::VirtualPort};
|
|
|
|
|
use rnex_rmc::{
|
|
|
|
|
RemoteDisconnectable, RmcCallable, RmcConnection, RmcPureRemoteObject,
|
2026-08-09 17:29:06 +02:00
|
|
|
serialization::RmcSerialize,
|
2026-01-20 20:26:44 +01:00
|
|
|
};
|
2026-07-12 18:21:18 +02:00
|
|
|
use rnex_server::{ConnectionInitData, try_get_ip};
|
|
|
|
|
use rnex_util::{PID, SendingBufferConnection, SplittableBufferConnection, UnitPacketWrite};
|
2026-01-20 20:26:44 +01:00
|
|
|
use std::{
|
|
|
|
|
env::{self, VarError},
|
2026-07-12 18:21:18 +02:00
|
|
|
fmt::Debug,
|
2026-04-26 13:15:56 +02:00
|
|
|
net::{AddrParseError, Ipv4Addr, SocketAddr, SocketAddrV4},
|
2026-01-20 20:26:44 +01:00
|
|
|
ops::Deref,
|
|
|
|
|
panic,
|
|
|
|
|
str::FromStr,
|
2026-08-09 17:29:06 +02:00
|
|
|
sync::LazyLock,
|
2026-01-20 20:26:44 +01:00
|
|
|
};
|
|
|
|
|
use thiserror::Error;
|
|
|
|
|
use tokio::net::TcpStream;
|
2026-07-14 19:03:00 +02:00
|
|
|
use tracing::{error, info};
|
2026-01-20 20:26:44 +01:00
|
|
|
|
|
|
|
|
const RNEX_DEFAULT_PORT: u16 = match u16::from_str_radix(env!("RNEX_DEFAULT_PORT"), 10) {
|
|
|
|
|
Ok(v) => v,
|
|
|
|
|
Err(_) => panic!("unable to get default port from env"),
|
|
|
|
|
};
|
|
|
|
|
|
2026-04-12 22:35:07 +02:00
|
|
|
pub const RNEX_ACCESS_KEY: &'static str = env!("RNEX_ACCESS_KEY");
|
2026-04-12 22:15:15 +02:00
|
|
|
|
2026-01-20 20:26:44 +01:00
|
|
|
#[derive(Error, Debug)]
|
|
|
|
|
pub enum Error {
|
|
|
|
|
#[error("error getting environment variable \"{0}\": {1}")]
|
|
|
|
|
UnableToGetEnv(&'static str, VarError),
|
|
|
|
|
#[error("error parsing ip address environment variable \"{0}\": {1}")]
|
|
|
|
|
AddrParse(&'static str, AddrParseError),
|
|
|
|
|
#[error(
|
2026-05-29 09:00:10 +02:00
|
|
|
"error error getting public ip address: \n\tattempted to read from env var \"SERVER_IP_PUBLIC\" and got: {0}\n\tfor other attempts check logs"
|
2026-01-20 20:26:44 +01:00
|
|
|
)]
|
2026-05-29 09:00:10 +02:00
|
|
|
PubAddrGetErr(Box<Self>),
|
2026-01-20 20:26:44 +01:00
|
|
|
}
|
|
|
|
|
impl Into<Error> for (&'static str, AddrParseError) {
|
|
|
|
|
fn into(self) -> Error {
|
|
|
|
|
Error::AddrParse(self.0, self.1)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub struct ProxyStartupParam {
|
|
|
|
|
pub forward_destination: SocketAddr,
|
2026-08-09 20:55:35 +02:00
|
|
|
// pub edge_node_holder: SocketAddr,
|
2026-01-20 20:26:44 +01:00
|
|
|
pub self_public: SocketAddrV4,
|
|
|
|
|
pub self_private: SocketAddrV4,
|
|
|
|
|
pub virtual_port: VirtualPort,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn try_get_env<T: FromStr>(name: &'static str) -> Result<T, Error>
|
|
|
|
|
where
|
|
|
|
|
(&'static str, T::Err): Into<Error>,
|
|
|
|
|
{
|
|
|
|
|
T::from_str(&env::var(name).map_err(|e| Error::UnableToGetEnv(name, e))?)
|
|
|
|
|
.map_err(|e| (name, e).into())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub enum ProxyType {
|
|
|
|
|
Insecure,
|
|
|
|
|
Secure,
|
|
|
|
|
}
|
|
|
|
|
const VIRTUAL_PORT_INSECURE: LazyLock<VirtualPort> =
|
|
|
|
|
LazyLock::new(|| VirtualPort::parse(env!("RNEX_VIRTUAL_PORT_INSECURE")).unwrap());
|
|
|
|
|
const VIRTUAL_PORT_SECURE: LazyLock<VirtualPort> =
|
|
|
|
|
LazyLock::new(|| VirtualPort::parse(env!("RNEX_VIRTUAL_PORT_SECURE")).unwrap());
|
|
|
|
|
impl ProxyStartupParam {
|
2026-04-26 13:15:56 +02:00
|
|
|
#[inline(always)]
|
2026-01-20 20:26:44 +01:00
|
|
|
pub fn new(prox_ty: ProxyType) -> Result<Self, Error> {
|
|
|
|
|
let port = RNEX_DEFAULT_PORT
|
|
|
|
|
+ match prox_ty {
|
|
|
|
|
ProxyType::Insecure => 0,
|
|
|
|
|
ProxyType::Secure => 1,
|
|
|
|
|
};
|
|
|
|
|
let self_private = try_get_env("SERVER_IP_PRIVATE")
|
2026-04-26 13:15:56 +02:00
|
|
|
.unwrap_or(SocketAddrV4::new(Ipv4Addr::UNSPECIFIED, port));
|
2026-01-20 20:26:44 +01:00
|
|
|
let self_public: SocketAddrV4 = match try_get_env("SERVER_IP_PUBLIC") {
|
|
|
|
|
Ok(v) => v,
|
|
|
|
|
Err(e) => try_get_ip()
|
2026-03-24 15:48:56 +01:00
|
|
|
.map(|v| SocketAddrV4::new(v, self_private.port()))
|
2026-05-29 09:00:10 +02:00
|
|
|
.ok_or(Error::PubAddrGetErr(Box::new(e)))?,
|
2026-01-20 20:26:44 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
Ok(Self {
|
2026-01-27 14:44:10 +01:00
|
|
|
forward_destination: try_get_env("FORWARD_DESTINATION")?,
|
2026-08-09 20:55:35 +02:00
|
|
|
// edge_node_holder: try_get_env("EDGE_NODE_HOLDER")?,
|
2026-01-20 20:26:44 +01:00
|
|
|
self_private,
|
|
|
|
|
self_public,
|
|
|
|
|
virtual_port: match prox_ty {
|
|
|
|
|
ProxyType::Insecure => *VIRTUAL_PORT_INSECURE,
|
|
|
|
|
ProxyType::Secure => *VIRTUAL_PORT_SECURE,
|
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct OnRemoteDrop<T: RemoteDisconnectable, C: FnOnce() + Send + Sync + 'static>(T, Option<C>);
|
2026-07-12 18:21:18 +02:00
|
|
|
impl<T: RemoteDisconnectable + Debug, C: FnOnce() + Send + Sync + 'static> Debug
|
|
|
|
|
for OnRemoteDrop<T, C>
|
|
|
|
|
{
|
|
|
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
|
|
|
let mut tuple_builder = f.debug_tuple("OnRemoteDrop");
|
|
|
|
|
tuple_builder.field(&self.0);
|
|
|
|
|
tuple_builder.finish_non_exhaustive()
|
|
|
|
|
}
|
|
|
|
|
}
|
2026-01-20 20:26:44 +01:00
|
|
|
impl<T: RemoteDisconnectable, C: FnOnce() + Send + Sync + 'static> Deref for OnRemoteDrop<T, C> {
|
|
|
|
|
type Target = T;
|
|
|
|
|
|
|
|
|
|
fn deref(&self) -> &Self::Target {
|
|
|
|
|
&self.0
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// if we had something like a thread safe OnceConsume (basically the opposite of OnceLock)
|
|
|
|
|
// we could make C be an FnOnce
|
|
|
|
|
impl<T: RemoteDisconnectable + RmcPureRemoteObject, C: FnOnce() + Send + Sync + 'static>
|
|
|
|
|
OnRemoteDrop<T, C>
|
|
|
|
|
{
|
2026-08-09 17:29:06 +02:00
|
|
|
#[allow(dead_code)]
|
2026-01-20 20:26:44 +01:00
|
|
|
pub fn new(conn: RmcConnection, drop_func: C) -> Self {
|
|
|
|
|
Self(T::new(conn), Some(drop_func))
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-26 13:15:56 +02:00
|
|
|
#[allow(dead_code)]
|
2026-01-20 20:26:44 +01:00
|
|
|
pub async fn disconnect(&self) {
|
|
|
|
|
self.0.disconnect().await;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<T: RemoteDisconnectable, C: FnOnce() + Send + Sync + 'static> RmcCallable
|
|
|
|
|
for OnRemoteDrop<T, C>
|
|
|
|
|
{
|
|
|
|
|
fn rmc_call(
|
|
|
|
|
&self,
|
|
|
|
|
_responder: &SendingBufferConnection,
|
|
|
|
|
_protocol_id: u16,
|
|
|
|
|
_method_id: u32,
|
|
|
|
|
_call_id: u32,
|
2026-07-12 18:21:18 +02:00
|
|
|
_rest: &[u8],
|
|
|
|
|
) -> impl Future<Output = bool> + Send {
|
2026-01-20 20:26:44 +01:00
|
|
|
// maybe respond with not implemented or something
|
2026-07-12 18:21:18 +02:00
|
|
|
async { false }
|
2026-01-20 20:26:44 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<T: RemoteDisconnectable, C: FnOnce() + Send + Sync + 'static> Drop for OnRemoteDrop<T, C> {
|
|
|
|
|
fn drop(&mut self) {
|
|
|
|
|
self.1.take().unwrap()();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub async fn new_backend_connection(
|
|
|
|
|
param: &ProxyStartupParam,
|
|
|
|
|
addr: PRUDPSockAddr,
|
2026-03-24 15:48:56 +01:00
|
|
|
pid: PID,
|
2026-01-20 20:26:44 +01:00
|
|
|
) -> Option<SplittableBufferConnection> {
|
2026-01-27 14:44:10 +01:00
|
|
|
info!("attempting to connect to: {}", param.forward_destination);
|
2026-01-20 20:26:44 +01:00
|
|
|
let mut stream = match TcpStream::connect(param.forward_destination).await {
|
|
|
|
|
Ok(v) => v,
|
|
|
|
|
Err(e) => {
|
2026-01-27 14:44:10 +01:00
|
|
|
error!("unable to establish connection to backend: {}", e);
|
2026-01-20 20:26:44 +01:00
|
|
|
return None;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2026-04-06 16:42:08 +02:00
|
|
|
let data = ConnectionInitData {
|
2026-07-12 18:21:18 +02:00
|
|
|
addr: addr.regular_socket_addr,
|
2026-04-06 16:42:08 +02:00
|
|
|
pid: pid,
|
|
|
|
|
}
|
|
|
|
|
.to_data()
|
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
|
|
if let Err(e) = stream.send_buffer(&data).await {
|
2026-01-27 14:44:10 +01:00
|
|
|
error!("unable to send establishment data to backend: {}", e);
|
2026-01-20 20:26:44 +01:00
|
|
|
return None;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
Some(stream.into())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
|
mod test {
|
|
|
|
|
use crate::{VIRTUAL_PORT_INSECURE, VIRTUAL_PORT_SECURE};
|
|
|
|
|
|
2026-05-04 16:06:25 +02:00
|
|
|
#[test]
|
2026-01-20 20:26:44 +01:00
|
|
|
fn test_virtual_port_correct() {
|
|
|
|
|
println!("{:?}", VIRTUAL_PORT_INSECURE);
|
|
|
|
|
println!("{:?}", VIRTUAL_PORT_SECURE);
|
|
|
|
|
}
|
|
|
|
|
}
|