refactor for new naming, new api and async

This commit is contained in:
DJMrTV 2025-01-21 20:10:58 +01:00
commit d53349c264
10 changed files with 717 additions and 246 deletions

View file

@ -6,9 +6,9 @@ use chrono::Local;
use log::{info, trace};
use once_cell::sync::Lazy;
use simplelog::{ColorChoice, CombinedLogger, Config, LevelFilter, TerminalMode, TermLogger, WriteLogger};
use crate::prudp::endpoint::Endpoint;
use crate::prudp::socket::{Socket, SocketImpl};
use crate::prudp::packet::VirtualPort;
use crate::prudp::server::NexServer;
use crate::prudp::router::Router;
mod endianness;
mod prudp;
@ -27,7 +27,8 @@ static OWN_IP: Lazy<Ipv4Addr> = Lazy::new(||{
.expect("no public ip specified")
});
fn main() {
#[tokio::main]
async fn main() {
CombinedLogger::init(
vec![
TermLogger::new(LevelFilter::Info, Config::default(), TerminalMode::Mixed, ColorChoice::Auto),
@ -40,23 +41,26 @@ fn main() {
dotenv::dotenv().ok();
start_servers().await;
}
async fn start_servers(){
info!("starting auth server on {}:{}", *OWN_IP, *AUTH_SERVER_PORT);
let (auth_server, auth_server_join_handle) =
NexServer::new(SocketAddrV4::new(*OWN_IP, *AUTH_SERVER_PORT))
.expect("unable to startauth server");
let auth_server_router =
Router::new(SocketAddrV4::new(*OWN_IP, *AUTH_SERVER_PORT)).await
.expect("unable to startauth server");
info!("setting up endpoints");
let auth_endpoints = vec![
Endpoint::new(auth_server.socket.try_clone().unwrap(), VirtualPort::new(1,10))
];
let mut socket =
Socket::new(
auth_server_router.clone(),
VirtualPort::new(1,10),
"6f599f81"
).await.expect("unable to create socket");
auth_server.endpoints.set(auth_endpoints)
.expect("endpoints were somehow set by something else???");
trace!("joining auth server");
auth_server_join_handle.join().unwrap();
let Some(connection) = socket.accept().await else {
return;
};
}

7
src/prudp/connection.rs Normal file
View file

@ -0,0 +1,7 @@
use tokio::sync::mpsc::Receiver;
//struct Connection(Arc<ConnectionImpl>, Receiver<>);
struct ConnectionImpl{
}

View file

@ -1,85 +0,0 @@
use std::collections::HashMap;
use std::net::UdpSocket;
use std::sync::{Arc, RwLock};
use log::{error, info};
use rand::random;
use crate::prudp::packet::{flags, PRUDPPacket, types, VirtualPort};
use crate::prudp::sockaddr::PRUDPSockAddr;
#[derive(Debug)]
pub struct Endpoint{
virtual_port: VirtualPort,
socket: UdpSocket,
connections: RwLock<HashMap<PRUDPSockAddr, Connection>>
}
#[derive(Debug)]
pub struct Connection{
sock_addr: PRUDPSockAddr,
id: u64
}
impl Endpoint{
pub fn new(socket: UdpSocket, port: VirtualPort) -> Self{
Self{
socket,
virtual_port: port,
connections: Default::default()
}
}
pub fn get_virual_port(&self) -> VirtualPort{
self.virtual_port
}
pub fn process_packet(&self, connection: PRUDPSockAddr, packet: &PRUDPPacket){
info!("recieved packet on endpoint");
let conn = self.connections.read().expect("poison");
if !conn.contains_key(&connection){
drop(conn);
let mut conn = self.connections.write().expect("poison");
//only insert if we STILL dont have the connection preventing double insertion
if !conn.contains_key(&connection) {
conn.insert(connection, Connection {
sock_addr: connection,
id: random()
});
}
drop(conn);
} else {
drop(conn);
}
let conn = self.connections.read().expect("poison");
let Some(conn) = conn.get(&connection) else {
error!("connection is still not present after making sure connection is present, giving up.");
return;
};
if //((packet.header.types_and_flags.get_flags() & flags::NEED_ACK) != 0) ||
((packet.header.types_and_flags.get_flags() & flags::ACK) != 0) ||
((packet.header.types_and_flags.get_flags() & flags::RELIABLE) != 0) ||
((packet.header.types_and_flags.get_flags() & flags::MULTI_ACK) != 0) {
let copy = packet.header.types_and_flags;
unimplemented!("{:?}", copy)
}
match packet.header.types_and_flags.get_types() {
types::SYN => {
// reset heartbeat?
let response_header = packet.base_response_header();
}
_ => unimplemented!()
}
}
}

View file

@ -1,5 +1,6 @@
pub mod packet;
pub mod server;
pub mod endpoint;
pub mod router;
pub mod socket;
mod auth_module;
mod sockaddr;
mod sockaddr;
mod connection;

View file

@ -1,15 +1,20 @@
use std::fmt::{Debug, Formatter};
use std::hint::unreachable_unchecked;
use std::io;
use std::io::{Cursor, ErrorKind, Read, Seek};
use std::io::{Cursor, ErrorKind, Read, Seek, Write};
use std::net::SocketAddrV4;
use bytemuck::{Pod, Zeroable};
use hmac::{Hmac, Mac};
use log::{error, warn};
use md5::{Md5, Digest};
use thiserror::Error;
use v_byte_macros::{EnumTryInto, SwapEndian};
use crate::endianness::{IS_BIG_ENDIAN, IS_LITTLE_ENDIAN, ReadExtensions};
use crate::prudp::packet::PacketOption::{ConnectionSignature, FragmentId, InitialSequenceId, MaximumSubstreamId, SupportedFunctions};
use crate::prudp::sockaddr::PRUDPSockAddr;
type Md5Hmac = Hmac<Md5>;
#[derive(Error, Debug)]
pub enum Error {
#[error("{0}")]
@ -34,21 +39,29 @@ pub type Result<T> = std::result::Result<T, Error>;
pub struct TypesFlags(u16);
impl TypesFlags {
pub fn get_types(self) -> u8 {
pub const fn get_types(self) -> u8 {
(self.0 & 0x000F) as u8
}
pub fn get_flags(self) -> u16 {
pub const fn get_flags(self) -> u16 {
(self.0 & 0xFFF0) >> 4
}
pub fn types(self, val: u8) -> Self {
pub const fn types(self, val: u8) -> Self {
Self((self.0 & 0xFFF0) | (val as u16 & 0x000F))
}
pub fn flags(self, val: u16) -> Self {
pub const fn flags(self, val: u16) -> Self {
Self((self.0 & 0x000F) | ((val << 4) & 0xFFF0))
}
pub const fn set_flag(&mut self, val: u16){
self.0 |= (val & 0xFFF) << 4;
}
pub const fn set_types(&mut self, val: u8){
self.0 |= val as u16 & 0x0F;
}
}
pub mod flags {
@ -116,7 +129,7 @@ impl Debug for VirtualPort {
}
}
#[repr(C, packed)]
#[repr(C)]
#[derive(Debug, Copy, Clone, Pod, Zeroable, SwapEndian)]
pub struct PRUDPHeader {
magic: [u8; 2],
@ -136,11 +149,64 @@ enum PacketSpecificData {
E = 0x10
}
#[derive(Debug, Clone)]
pub enum PacketOption{
SupportedFunctions(u32),
ConnectionSignature([u8; 16]),
FragmentId(u8),
InitialSequenceId(u16),
MaximumSubstreamId(u8)
}
impl PacketOption{
fn from(option_id: OptionId, option_data: &[u8]) -> io::Result<Self>{
let mut data_cursor = Cursor::new(option_data);
let val = match option_id.into(){
0 => SupportedFunctions(data_cursor.read_struct(IS_BIG_ENDIAN)?),
1 => ConnectionSignature(data_cursor.read_struct(IS_BIG_ENDIAN)?),
2 => FragmentId(data_cursor.read_struct(IS_BIG_ENDIAN)?),
3 => InitialSequenceId(data_cursor.read_struct(IS_BIG_ENDIAN)?),
4 => MaximumSubstreamId(data_cursor.read_struct(IS_BIG_ENDIAN)?),
_ => unsafe{ unreachable_unchecked() }
};
Ok(val)
}
fn write_to_stream(&self, stream: &mut impl Write) -> io::Result<()> {
match self {
SupportedFunctions(v) => {
stream.write_all(&[0, size_of_val(v) as u8])?;
stream.write_all(&v.to_le_bytes())?;
}
ConnectionSignature(v) => {
stream.write_all(&[1, size_of_val(v) as u8])?;
stream.write_all(v)?;
}
FragmentId(v) => {
stream.write_all(&[2, size_of_val(v) as u8])?;
stream.write_all(&v.to_le_bytes())?;
}
InitialSequenceId(v) => {
stream.write_all(&[3, size_of_val(v) as u8])?;
stream.write_all(&v.to_le_bytes())?;
}
MaximumSubstreamId(v) => {
stream.write_all(&[4, size_of_val(v) as u8])?;
stream.write_all(&v.to_le_bytes())?;
}
}
Ok(())
}
}
#[derive(Debug, Clone)]
pub struct PRUDPPacket {
pub header: PRUDPHeader,
pub packet_signature: [u8; 16],
pub payload: Vec<u8>,
pub options: Vec<(u8, Vec<u8>)>,
pub options: Vec<PacketOption>,
}
#[derive(Copy, Clone, Debug)]
@ -190,7 +256,7 @@ impl PRUDPPacket {
}
//discard it for now
let _: [u8; 16] = reader.read_struct(IS_BIG_ENDIAN)?;
let packet_signature: [u8; 16] = reader.read_struct(IS_BIG_ENDIAN)?;
assert_eq!(reader.stream_position().ok(), Some(14 + 16));
@ -236,7 +302,7 @@ impl PRUDPPacket {
break;
}
options.push((option_id.into(), option_data));
options.push(PacketOption::from(option_id, &option_data)?);
}
@ -244,8 +310,11 @@ impl PRUDPPacket {
reader.read_exact(&mut payload)?;
Ok(Self {
header,
packet_signature,
payload,
options,
})
@ -258,20 +327,84 @@ impl PRUDPPacket {
}
}
pub fn base_response_header(&self) -> PRUDPHeader {
PRUDPHeader {
magic: [0xEA, 0xD0],
types_and_flags: TypesFlags(0),
destination_port: self.header.source_port,
source_port: self.header.destination_port,
payload_size: 0,
version: 1,
packet_specific_size: 0,
sequence_id: 0,
session_id: 0,
substream_id: 0,
fn generate_options_bytes(&self) -> Vec<u8>{
let mut vec = Vec::new();
for option in &self.options{
option.write_to_stream(&mut vec).expect("vec should always automatically be able to extend");
}
vec
}
pub fn calculate_signature_value(&self, access_key: &str, session_key: Option<[u8; 32]>, connection_signature: Option<[u8; 16]>) -> [u8; 16]{
let access_key_bytes = access_key.as_bytes();
let access_key_sum: u32 = access_key_bytes.iter().map(|v| *v as u32).sum();
let access_key_sum_bytes: [u8; 4] = access_key_sum.to_le_bytes();
let header_data: [u8; 8] = bytemuck::bytes_of(&self.header)[0x8..].try_into().unwrap();
let option_bytes = self.generate_options_bytes();
let mut md5 = md5::Md5::default();
md5.update(access_key_bytes);
let key = md5.finalize();
let mut hmac = Md5Hmac::new_from_slice(&key).expect("fuck");
hmac.write(&header_data).expect("error during hmac calculation");
if let Some(session_key) = session_key {
hmac.write(&session_key).expect("error during hmac calculation");
}
hmac.write(&access_key_sum_bytes).expect("error during hmac calculation");
if let Some(connection_signature) = connection_signature {
hmac.write(&connection_signature).expect("error during hmac calculation");
}
hmac.write(&option_bytes).expect("error during hmac calculation");
hmac.write_all(&self.payload).expect("error during hmac calculation");
hmac.finalize().into_bytes()[0..16].try_into().expect("invalid hmac size")
}
pub fn calculate_and_assign_signature(&mut self, access_key: &str, session_key: Option<[u8; 32]>, connection_signature: Option<[u8; 16]>){
self.packet_signature = self.calculate_signature_value(access_key, session_key, connection_signature);
}
pub fn base_response_packet(&self) -> Self {
Self {
header: PRUDPHeader {
magic: [0xEA, 0xD0],
types_and_flags: TypesFlags(0),
destination_port: self.header.source_port,
source_port: self.header.destination_port,
payload_size: 0,
version: 1,
packet_specific_size: 0,
sequence_id: 0,
session_id: 0,
substream_id: 0,
},
packet_signature: [0; 16],
payload: Default::default(),
options: Default::default()
}
}
pub fn write_to(&self, writer: &mut impl Write) -> io::Result<()>{
writer.write_all(bytemuck::bytes_of(&self.header))?;
writer.write_all(&self.packet_signature)?;
for option in &self.options{
option.write_to_stream(writer)?;
}
writer.write_all(&self.payload)?;
Ok(())
}
}

173
src/prudp/router.rs Normal file
View file

@ -0,0 +1,173 @@
use std::{env, io, thread};
use std::cell::OnceCell;
use std::io::Cursor;
use std::marker::PhantomData;
use tokio::net::UdpSocket;
use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4};
use std::net::SocketAddr::V4;
use std::ops::{Deref, DerefMut};
use std::sync::{Arc, OnceLock};
use std::sync::atomic::{AtomicBool, Ordering};
use tokio::task::JoinHandle;
use once_cell::sync::Lazy;
use log::{error, info, trace, warn};
use thiserror::Error;
use tokio::sync::RwLock;
use crate::prudp::auth_module::AuthModule;
use crate::prudp::socket::{Socket, SocketImpl};
use crate::prudp::packet::{PRUDPPacket, VirtualPort};
use crate::prudp::router::Error::VirtualPortTaken;
use crate::prudp::sockaddr::PRUDPSockAddr;
static SERVER_DATAGRAMS: Lazy<u8> = Lazy::new(||{
env::var("SERVER_DATAGRAM_COUNT").ok()
.and_then(|s| s.parse().ok())
.unwrap_or(1)
});
pub struct Router {
endpoints: RwLock<[Option<Arc<SocketImpl>>; 16]>,
running: AtomicBool,
socket: Arc<UdpSocket>,
//pub auth_module: Arc<dyn AuthModule>
_no_outside_construction: PhantomData<()>
}
#[derive(Debug, Error)]
pub enum Error{
#[error("tried to register socket to a port which is already taken (port: {0})")]
VirtualPortTaken(u8)
}
impl Router {
fn process_prudp_packet(&self, packet: &PRUDPPacket){
}
async fn process_prudp_packets<'a>(&self, socket: &'a UdpSocket, addr: SocketAddrV4, udp_message: &[u8]){
let mut stream = Cursor::new(udp_message);
while stream.position() as usize != udp_message.len() {
let packet = match PRUDPPacket::new(&mut stream){
Ok(p) => p,
Err(e) => {
error!("Somebody({}) is fucking with the servers or their connection is bad", addr);
break;
},
};
trace!("got valid prudp packet from someone({}): \n{:?}", addr, packet);
let connection = packet.source_sockaddr(addr);
let endpoints = self.endpoints.read().await;
let Some(endpoint) = endpoints[packet.header.destination_port.get_port_number() as usize].as_ref() else {
error!("connection to invalid endpoint({}) attempted by {}", packet.header.destination_port.get_port_number(), connection.regular_socket_addr);
continue;
};
let endpoint = endpoint.clone();
// Dont keep the locked structure for too long
drop(endpoints);
trace!("sending packet to endpoint");
endpoint.process_packet(connection, &packet).await;
}
}
async fn server_thread_send_entry(self: Arc<Self>, socket: Arc<UdpSocket>){
info!("starting datagram thread");
while self.running.load(Ordering::Relaxed) {
// yes we actually allow the max udp to be read lol
let mut msg_buffer = vec![0u8; 65507];
let (len, addr) = socket.recv_from(&mut msg_buffer)
.await.expect("Datagram thread crashed due to unexpected error from recv_from");
let V4(addr) = addr else {
error!("somehow got ipv6 packet...? ignoring");
continue;
};
let current_msg = &msg_buffer[0..len];
info!("attempting to process message");
self.process_prudp_packets(&socket, addr, current_msg).await;
}
}
pub async fn new(addr: SocketAddrV4) -> io::Result<Arc<Self>>{
trace!("starting router on {}", addr);
let socket = Arc::new(UdpSocket::bind(addr).await?);
let own_impl = Router {
endpoints: Default::default(),
running: AtomicBool::new(true),
socket: socket.clone(),
_no_outside_construction: Default::default()
};
let arc = Arc::new(own_impl);
{
let socket = socket.clone();
let server= arc.clone();
tokio::spawn(async {
server.server_thread_send_entry(socket).await;
});
}
{
let socket = socket.clone();
let server= arc.clone();
tokio::spawn(async {
//server thread sender entry
// todo: make this run in the socket cause that makes more sense
//server.server_thread_recieve_entry(socket).await;
});
}
Ok(arc)
}
pub fn get_udp_socket(&self) -> Arc<UdpSocket>{
self.socket.clone()
}
// This will remove a socket from the router, this renders all instances of that socket unable
// to recieve any more data making the error out on trying to for example recieve connections
pub async fn remove_socket(&self, virtual_port: VirtualPort){
self.endpoints.write().await[virtual_port.get_port_number() as usize] = None;
}
// returns Some(()) i
pub(crate) async fn add_socket(&self, socket: Arc<SocketImpl>) -> Result<(), Error>{
let mut endpoints = self.endpoints.write().await;
let idx = socket.get_virual_port().get_port_number() as usize;
if endpoints[idx].is_none() {
endpoints[idx] = Some(socket);
} else {
return Err(VirtualPortTaken(idx as u8));
}
Ok(())
}
pub fn get_own_address(&self) -> SocketAddrV4{
match self.socket.local_addr().expect("unable to get socket address"){
SocketAddr::V4(v4) => v4,
_ => unreachable!()
}
}
}

View file

@ -1,121 +0,0 @@
use std::{env, io, thread};
use std::cell::OnceCell;
use std::io::Cursor;
use std::marker::PhantomData;
use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4, TcpStream, UdpSocket};
use std::net::SocketAddr::V4;
use std::ops::{Deref, DerefMut};
use std::sync::{Arc, Mutex, OnceLock, RwLock};
use std::sync::atomic::{AtomicBool, Ordering};
use std::thread::JoinHandle;
use once_cell::sync::Lazy;
use log::{error, info, trace, warn};
use crate::prudp::auth_module::AuthModule;
use crate::prudp::endpoint::Endpoint;
use crate::prudp::packet::{PRUDPPacket, VirtualPort};
use crate::prudp::sockaddr::PRUDPSockAddr;
static SERVER_DATAGRAMS: Lazy<u8> = Lazy::new(||{
env::var("SERVER_DATAGRAM_COUNT").ok()
.and_then(|s| s.parse().ok())
.unwrap_or(1)
});
pub struct NexServer{
pub endpoints: OnceLock<Vec<Endpoint>>,
pub socket: UdpSocket,
pub running: AtomicBool,
//pub auth_module: Arc<dyn AuthModule>
_no_outside_construction: PhantomData<()>
}
impl NexServer{
fn process_prudp_packet(&self, packet: &PRUDPPacket){
}
fn process_prudp_packets<'a>(&self, socket: &'a UdpSocket, addr: SocketAddrV4, udp_message: &[u8]){
let mut stream = Cursor::new(udp_message);
while stream.position() as usize != udp_message.len() {
let packet = match PRUDPPacket::new(&mut stream){
Ok(p) => p,
Err(e) => {
error!("Somebody({}) is fucking with the servers or their connection is bad", addr);
break;
},
};
trace!("got valid prudp packet from someone({}): \n{:?}", addr, packet);
let connection = packet.source_sockaddr(addr);
let Some(endpoints) = self.endpoints.get() else{
warn!("Got a message: ignoring because the server is still starting or the endpoints havent been set up");
break;
};
let Some(endpoint) = endpoints.iter().find(|e|{
e.get_virual_port().get_port_number() == packet.header.destination_port.get_port_number()
}) else {
error!("connection to invalid endpoint({}) attempted by {}", packet.header.destination_port.get_port_number(), connection.regular_socket_addr);
continue;
};
trace!("sending packet to endpoint");
endpoint.process_packet(connection, &packet);
}
}
fn server_thread_entry(self: Arc<Self>, socket: UdpSocket){
info!("starting datagram thread");
while self.running.load(Ordering::Relaxed) {
// yes we actually allow the max udp to be read lol
let mut msg_buffer = vec![0u8; 65507];
let (len, addr) = socket.recv_from(&mut msg_buffer)
.expect("Datagram thread crashed due to unexpected error from recv_from");
let V4(addr) = addr else {
error!("somehow got ipv6 packet...? ignoring");
continue;
};
let current_msg = &msg_buffer[0..len];
info!("attempting to process message");
self.process_prudp_packets(&socket, addr, current_msg);
}
}
pub fn new(addr: SocketAddrV4) -> io::Result<(Arc<Self>, JoinHandle<()>)>{
let socket = UdpSocket::bind(addr)?;
let own_impl = NexServer{
endpoints: Default::default(),
running: AtomicBool::new(true),
socket: socket.try_clone().unwrap(),
_no_outside_construction: Default::default()
};
let arc = Arc::new(own_impl);
let mut thread = None;
for _ in 0..*SERVER_DATAGRAMS {
let socket = socket.try_clone().unwrap();
let server= arc.clone();
thread = Some(thread::spawn(move || {
server.server_thread_entry(socket);
}));
}
let thread = thread.expect("cannot have less than 1 thread for a server");
Ok((arc, thread))
}
}

201
src/prudp/socket.rs Normal file
View file

@ -0,0 +1,201 @@
use std::array;
use std::collections::HashMap;
use std::io::Write;
use std::ops::Deref;
use tokio::net::UdpSocket;
use std::sync::{Arc};
use tokio::sync::{Mutex, RwLock};
use hmac::{Hmac, Mac};
use log::{error, info, trace};
use rand::random;
use rc4::consts::U256;
use tokio::sync::mpsc::{channel, Receiver, Sender};
use crate::prudp::packet::{flags, PacketOption, PRUDPPacket, types, VirtualPort};
use crate::prudp::packet::PacketOption::{MaximumSubstreamId, SupportedFunctions};
use crate::prudp::packet::types::SYN;
use crate::prudp::router::{Error, Router};
use crate::prudp::sockaddr::PRUDPSockAddr;
type Md5Hmac = Hmac<md5::Md5>;
/// PRUDP Socket for accepting connections to then send and recieve data from those clients
pub struct Socket(Arc<SocketImpl>, Arc<Router>, Receiver<Connection>);
#[derive(Debug)]
pub struct SocketImpl {
virtual_port: VirtualPort,
socket: Arc<UdpSocket>,
access_key: &'static str,
connections: RwLock<HashMap<PRUDPSockAddr, Arc<Mutex<Connection>>>>,
connection_creation_sender: Sender<Connection>
}
#[derive(Debug)]
pub struct Connection {
sock_addr: PRUDPSockAddr,
id: u64,
signature: [u8; 16],
}
impl Socket {
pub async fn new(router: Arc<Router>, port: VirtualPort, access_key: &'static str) -> Result<Self, Error> {
trace!("creating socket on router at {} on virtual port {:?}", router.get_own_address(), port);
let (send, recv) = channel(20);
let socket = Arc::new(
SocketImpl::new(&router, send, port, access_key)
);
router.add_socket(socket.clone()).await?;
Ok(Self(socket, router, recv))
}
pub async fn accept(&mut self) -> Option<Connection>{
self.2.recv().await
}
}
impl Drop for Socket{
fn drop(&mut self) {
{
let router = self.1.clone();
let virtual_port = self.virtual_port;
trace!("socket dropped socket will be removed from router soon");
// it's not that important to remove it immediately so we can delay the deletion a bit if needed
tokio::spawn(async move {
router.remove_socket(virtual_port).await;
trace!("socket removed from router successfully");
});
}
}
}
impl Deref for Socket{
type Target = SocketImpl;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl SocketImpl {
fn new(router: &Router, connection_creation_sender: Sender<Connection>, port: VirtualPort, access_key: &'static str) -> Self {
SocketImpl {
socket: router.get_udp_socket(),
virtual_port: port,
connections: Default::default(),
access_key,
connection_creation_sender
}
}
pub fn get_virual_port(&self) -> VirtualPort {
self.virtual_port
}
pub async fn process_packet(&self, connection: PRUDPSockAddr, packet: &PRUDPPacket) {
info!("recieved packet on endpoint");
let conn = self.connections.read().await;
if !conn.contains_key(&connection) {
drop(conn);
let mut conn = self.connections.write().await;
//only insert if we STILL dont have the connection preventing double insertion
if !conn.contains_key(&connection) {
conn.insert(connection, Arc::new(Mutex::new(Connection {
sock_addr: connection,
id: random(),
signature: [0; 16],
})));
}
drop(conn);
} else {
drop(conn);
}
let connections = self.connections.read().await;
let Some(conn) = connections.get(&connection) else {
error!("connection is still not present after making sure connection is present, giving up.");
return;
};
let conn = conn.clone();
// dont keep holding the connections list unnescesarily
drop(connections);
let mut conn = conn.lock().await;
if //((packet.header.types_and_flags.get_flags() & flags::NEED_ACK) != 0) ||
((packet.header.types_and_flags.get_flags() & flags::ACK) != 0) ||
((packet.header.types_and_flags.get_flags() & flags::RELIABLE) != 0) ||
((packet.header.types_and_flags.get_flags() & flags::MULTI_ACK) != 0) {
let copy = packet.header.types_and_flags;
unimplemented!("{:?}", copy)
}
match packet.header.types_and_flags.get_types() {
types::SYN => {
// reset heartbeat?
let mut response_packet = packet.base_response_packet();
response_packet.header.types_and_flags.set_types(SYN);
response_packet.header.types_and_flags.set_flag(flags::ACK);
response_packet.header.types_and_flags.set_flag(flags::HAS_SIZE);
let mut hmac = Md5Hmac::new_from_slice(&[0; 16]).expect("fuck");
let mut data = connection.regular_socket_addr.ip().octets().to_vec();
data.extend_from_slice(&connection.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");
conn.signature = result;
response_packet.options.push(PacketOption::ConnectionSignature(result));
response_packet.calculate_and_assign_signature(self.access_key, None, None);
for options in &packet.options{
match options{
SupportedFunctions(functions) => {
response_packet.options.push(SupportedFunctions(*functions))
}
MaximumSubstreamId(max_substream) => {
response_packet.options.push(MaximumSubstreamId(*max_substream))
},
_ => {/* ??? */}
}
}
let mut vec = Vec::new();
response_packet.write_to(&mut vec).expect("somehow failed to convert backet to bytes");
self.socket.send_to(&vec, connection.regular_socket_addr).await.expect("failed to send data back");
}
_ => unimplemented!("unimplemented packet type: {}", packet.header.types_and_flags.get_types())
}
}
}
#[cfg(test)]
mod test {
use hmac::Mac;
use crate::prudp::socket::Md5Hmac;
#[test]
fn fuck() {
let hmac = Md5Hmac::new_from_slice(&[0; 16]).expect("fuck");
}
}