This commit is contained in:
Maple 2025-09-21 15:59:27 +02:00
commit aab4414904
71 changed files with 293 additions and 4316 deletions

View file

@ -0,0 +1,3 @@
pub mod virtual_port;
pub mod station_url;
pub mod socket_addr;

View file

@ -0,0 +1,38 @@
use std::io::Write;
use std::net::SocketAddrV4;
use hmac::{Hmac};
use md5::digest::Mac;
use macros::RmcSerialize;
use rnex_core::prudp::virtual_port::VirtualPort;
type Md5Hmac = Hmac<md5::Md5>;
#[derive(Eq, PartialEq, Hash, Debug, Copy, Clone, Ord, PartialOrd, RmcSerialize)]
#[rmc_struct(0)]
pub struct PRUDPSockAddr{
pub regular_socket_addr: SocketAddrV4,
pub virtual_port: VirtualPort
}
impl PRUDPSockAddr{
pub fn new(regular_socket_addr: SocketAddrV4, virtual_port: VirtualPort) -> Self{
Self{
regular_socket_addr,
virtual_port
}
}
pub fn calculate_connection_signature(&self) -> [u8; 16] {
let mut hmac = Md5Hmac::new_from_slice(&[0; 16]).expect("fuck");
let mut data = self.regular_socket_addr.ip().octets().to_vec();
//data.extend_from_slice(&self.regular_socket_addr.port().to_be_bytes());
hmac.write_all(&data).expect("figuring this out was complete ass");
let result: [u8; 16] = hmac.finalize().into_bytes()[0..16].try_into().expect("fuck");
result
}
}

View file

@ -0,0 +1,198 @@
use std::net::Ipv4Addr;
use log::error;
use std::fmt::{Debug, Display, Formatter, Write};
use std::io::Read;
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;
use crate::rmc::structures::RmcSerialize;
#[derive(Clone, Copy, PartialEq, Eq)]
pub enum Type{
UDP,
PRUDP,
PRUDPS
}
pub mod nat_types{
pub const BEHIND_NAT: u8 = 1;
pub const PUBLIC: u8 = 2;
}
#[derive(Clone, Eq, PartialEq)]
pub enum UrlOptions {
Address(Ipv4Addr),
Port(u16),
StreamType(u8),
StreamID(u8),
ConnectionID(u8),
PrincipalID(u32),
NatType(u8),
NatMapping(u8),
NatFiltering(u8),
UPNP(u8),
RVConnectionID(u32),
Platform(u8),
PMP(u8),
PID(u32),
}
#[derive(Clone, PartialEq, Eq)]
pub struct StationUrl{
pub url_type: Type,
pub options: Vec<UrlOptions>
}
impl StationUrl{
pub fn read_options(options: &str) -> Option<Vec<UrlOptions>>{
let mut options_out = Vec::new();
for option in options.split(';'){
if option == "" { continue; }
let mut option_parts = option.split('=');
let option_name= option_parts.next()?.to_ascii_lowercase();
let option_value = option_parts.next()?;
match option_name.as_ref(){
"address" => {
options_out.push(Address(option_value.parse().ok()?))
},
"port" => {
options_out.push(Port(option_value.parse().ok()?))
}
"natf" => {
options_out.push(NatFiltering(option_value.parse().ok()?))
}
"natm" => {
options_out.push(NatMapping(option_value.parse().ok()?))
}
"sid" => {
options_out.push(StreamID(option_value.parse().ok()?))
}
"upnp" => {
options_out.push(UPNP(option_value.parse().ok()?))
}
"type" => {
options_out.push(NatType(option_value.parse().ok()?))
}
"stream" => {
options_out.push(StreamType(option_value.parse().ok()?))
}
"RVCID" => {
options_out.push(RVConnectionID(option_value.parse().ok()?))
}
"rvcid" => {
options_out.push(RVConnectionID(option_value.parse().ok()?))
}
"pl" => {
options_out.push(Platform(option_value.parse().ok()?))
}
"pmp" => {
options_out.push(PMP(option_value.parse().ok()?))
},
"pid" => {
options_out.push(PID(option_value.parse().ok()?))
},
"PID" => {
options_out.push(PID(option_value.parse().ok()?))
},
_ => {
error!("unimplemented option type, skipping: {}", option_name);
}
}
}
Some(options_out)
}
}
impl TryFrom<&str> for StationUrl{
type Error = ();
fn try_from(value: &str) -> Result<Self, ()> {
let (url_type, options) = value.split_at(value.find(":/").ok_or(())?);
let options = &options[2..];
let url_type = match url_type{
"udp" => UDP,
"prudp" => PRUDP,
"prudps" => PRUDPS,
_ => return Err(())
};
let options = Self::read_options(options).ok_or(())?;
Ok(
Self{
url_type,
options
}
)
}
}
impl<'a> Into<String> for &'a StationUrl{
fn into(self) -> String {
let mut url = match self.url_type{
UDP => "udp:/",
PRUDP => "prudp:/",
PRUDPS => "prudps:/"
}.to_owned();
for option in &self.options{
match option{
Address(v) => write!(url, "address={}", v).expect("failed to write"),
Port(v) => write!(url, "port={}", v).expect("failed to write"),
StreamType(v) => write!(url, "stream={}", v).expect("failed to write"),
StreamID(v) => write!(url, "sid={}", v).expect("failed to write"),
ConnectionID(v) => write!(url, "CID={}", v).expect("failed to write"),
PrincipalID(v) => write!(url, "PID={}", v).expect("failed to write"),
NatType(v) => write!(url, "type={}", v).expect("failed to write"),
NatMapping(v) => write!(url, "natm={}", v).expect("failed to write"),
NatFiltering(v) => write!(url, "natf={}", v).expect("failed to write"),
UPNP(v) => write!(url, "upnp={}", v).expect("failed to write"),
RVConnectionID(v) => write!(url, "RVCID={}", v).expect("failed to write"),
Platform(v) => write!(url, "pl={}", v).expect("failed to write"),
PMP(v) => write!(url, "pmp={}", v).expect("failed to write"),
PID(v) => write!(url, "PID={}", v).expect("failed to write"),
}
write!(url, ";").expect("failed to write");
}
url[0..url.len()-1].into()
}
}
impl Display for StationUrl{
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
let str: String = self.into();
write!(f, "{}", str)
}
}
impl RmcSerialize for StationUrl{
fn deserialize(reader: &mut dyn Read) -> crate::rmc::structures::Result<Self> {
let str = String::deserialize(reader)?;
Self::try_from(str.as_str()).map_err(|_| StationUrlInvalid)
}
fn serialize(&self, writer: &mut dyn std::io::Write) -> crate::rmc::structures::Result<()> {
let str: String = self.into();
str.serialize(writer)
}
}
impl Debug for StationUrl{
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
let str: String = self.into();
f.write_str(&str)
}
}

View file

@ -0,0 +1,49 @@
use std::fmt::{Debug, Formatter};
use bytemuck::{Pod, Zeroable};
use v_byte_helpers::SwapEndian;
#[repr(transparent)]
#[derive(PartialEq, Eq, Ord, PartialOrd, Copy, Clone, Pod, Zeroable, SwapEndian, Hash, Default)]
pub struct VirtualPort(pub u8);
impl VirtualPort {
#[inline]
pub const fn get_stream_type(self) -> u8 {
(self.0 & 0xF0) >> 4
}
#[inline]
pub const fn get_port_number(self) -> u8 {
self.0 & 0x0F
}
#[inline]
pub fn stream_type(self, val: u8) -> Self {
let masked_val = val & 0x0F;
assert_eq!(masked_val, val);
Self((self.0 & 0x0F) | (masked_val << 4))
}
#[inline]
pub fn port_number(self, val: u8) -> Self {
let masked_val = val & 0x0F;
assert_eq!(masked_val, val);
Self((self.0 & 0xF0) | masked_val)
}
#[inline]
pub fn new(port: u8, stream_type: u8) -> Self {
Self(0).stream_type(stream_type).port_number(port)
}
}
impl Debug for VirtualPort {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
let stream_type = self.get_stream_type();
let port_number = self.get_port_number();
write!(f, "VirtualPort{{ stream_type: {}, port_number: {} }}", stream_type, port_number)
}
}