fix port binding

This commit is contained in:
Maple 2026-03-24 15:48:56 +01:00
commit 785341e883
43 changed files with 1543 additions and 431 deletions

View file

@ -3,19 +3,19 @@ use macros::RmcSerialize;
use md5::digest::Mac;
use rnex_core::prudp::virtual_port::VirtualPort;
use std::io::Write;
use std::net::SocketAddrV4;
use std::net::{IpAddr, SocketAddr};
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 regular_socket_addr: SocketAddr,
pub virtual_port: VirtualPort,
}
impl PRUDPSockAddr {
pub fn new(regular_socket_addr: SocketAddrV4, virtual_port: VirtualPort) -> Self {
pub fn new(regular_socket_addr: SocketAddr, virtual_port: VirtualPort) -> Self {
Self {
regular_socket_addr,
virtual_port,
@ -23,9 +23,12 @@ impl PRUDPSockAddr {
}
pub fn calculate_connection_signature(&self) -> [u8; 16] {
let mut hmac = Md5Hmac::new_from_slice(&[0; 16]).expect("fuck");
let mut hmac = Md5Hmac::new_from_slice(&[0; 16]).expect("?");
let data = self.regular_socket_addr.ip().octets().to_vec();
let data = match self.regular_socket_addr.ip() {
IpAddr::V4(v) => v.octets().to_vec(),
IpAddr::V6(v) => v.octets().to_vec(),
};
//data.extend_from_slice(&self.regular_socket_addr.port().to_be_bytes());
hmac.write_all(&data)

View file

@ -1,32 +1,35 @@
use std::net::Ipv4Addr;
use crate::prudp::station_url::Type::{PRUDP, PRUDPS, UDP};
use crate::prudp::station_url::UrlOptions::{
Address, ConnectionID, NatFiltering, NatMapping, NatType, PID, PMP, Platform, Port,
PrincipalID, RVConnectionID, StreamID, StreamType, UPNP,
};
use crate::rmc::structures::Error::StationUrlInvalid;
use crate::rmc::structures::RmcSerialize;
use crate::rmc::structures::helpers::DummyFormatWriter;
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::helpers::DummyFormatWriter;
use crate::rmc::structures::RmcSerialize;
use std::net::IpAddr;
#[derive(Clone, Copy, PartialEq, Eq)]
pub enum Type{
pub enum Type {
UDP,
PRUDP,
PRUDPS
PRUDPS,
}
pub mod nat_types{
pub mod nat_types {
pub const BEHIND_NAT: u8 = 1;
pub const PUBLIC: u8 = 2;
}
#[derive(Clone, Eq, PartialEq)]
pub enum UrlOptions {
Address(Ipv4Addr),
Address(IpAddr),
Port(u16),
StreamType(u8),
StreamID(u8),
ConnectionID(u8),
PrincipalID(u32),
PrincipalID(rnex_core::PID),
NatType(u8),
NatMapping(u8),
NatFiltering(u8),
@ -35,82 +38,52 @@ pub enum UrlOptions {
Platform(u8),
PMP(u8),
PID(u32),
}
#[derive(Clone, PartialEq, Eq)]
pub struct StationUrl{
pub struct StationUrl {
pub url_type: Type,
pub options: Vec<UrlOptions>
pub options: Vec<UrlOptions>,
}
impl StationUrl{
pub fn read_options(options: &str) -> Option<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; }
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_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()?))
},
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{
impl TryFrom<&str> for StationUrl {
type Error = ();
fn try_from(value: &str) -> Result<Self, ()> {
@ -118,35 +91,30 @@ impl TryFrom<&str> for StationUrl{
let options = &options[2..];
let url_type = match url_type{
let url_type = match url_type {
"udp" => UDP,
"prudp" => PRUDP,
"prudps" => PRUDPS,
_ => return Err(())
_ => return Err(()),
};
let options = Self::read_options(options).ok_or(())?;
Ok(
Self{
url_type,
options
}
)
Ok(Self { url_type, options })
}
}
impl Display for StationUrl{
impl Display for StationUrl {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
let url_type_str = match self.url_type{
let url_type_str = match self.url_type {
UDP => "udp:/",
PRUDP => "prudp:/",
PRUDPS => "prudps:/"
PRUDPS => "prudps:/",
};
write!(f, "{}",url_type_str)?;
write!(f, "{}", url_type_str)?;
for option in &self.options{
match option{
for option in &self.options {
match option {
Address(v) => write!(f, "address={}", v)?,
Port(v) => write!(f, "port={}", v)?,
StreamType(v) => write!(f, "stream={}", v)?,
@ -168,15 +136,15 @@ impl Display for StationUrl{
}
}
impl<'a> Into<String> for &'a StationUrl{
impl<'a> Into<String> for &'a StationUrl {
fn into(self) -> String {
let url = self.to_string();
url[0..url.len()-1].into()
url[0..url.len() - 1].into()
}
}
impl RmcSerialize for StationUrl{
impl RmcSerialize for StationUrl {
fn deserialize(reader: &mut impl Read) -> crate::rmc::structures::Result<Self> {
let str = String::deserialize(reader)?;
@ -197,9 +165,9 @@ impl RmcSerialize for StationUrl{
}
}
impl Debug for StationUrl{
impl Debug for StationUrl {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
let str: String = self.into();
f.write_str(&str)
}
}
}

View file

@ -2,7 +2,7 @@ use std::io::Cursor;
use log::{error, info};
use rc4::{KeyInit, Rc4, Rc4Core, StreamCipher, cipher::StreamCipherCoreWrapper};
use typenum::{U16, U32};
use typenum::U16;
use v_byte_helpers::{IS_BIG_ENDIAN, ReadExtensions};
use crate::{
@ -10,19 +10,17 @@ use crate::{
nex::account::Account,
rmc::structures::RmcSerialize,
};
use rnex_core::PID;
pub fn read_secure_connection_data(
data: &[u8],
act: &Account,
) -> Option<([u8; SESSION_KEY_LENGTH], u32, u32)> {
) -> Option<([u8; SESSION_KEY_LENGTH], PID, u32)> {
let mut cursor = Cursor::new(data);
let mut ticket_data: Vec<u8> = Vec::deserialize(&mut cursor).ok()?;
let mut request_data: Vec<u8> = Vec::deserialize(&mut cursor).ok()?;
info!(
"done
request data"
);
info!("done request data {}", SESSION_KEY_LENGTH);
let ticket_data_size = ticket_data.len();
@ -62,7 +60,7 @@ pub fn read_secure_connection_data(
let mut reqest_data_cursor = Cursor::new(request_data);
let pid: u32 = reqest_data_cursor.read_struct(IS_BIG_ENDIAN).ok()?;
let pid: PID = reqest_data_cursor.read_struct(IS_BIG_ENDIAN).ok()?;
if pid != ticket_source_pid {
let ticket_created_on = issued_time.to_regular_time();