//! Connection handling and send/receive queues pub mod handshake; mod packet; pub mod socket; use ::std::{sync::Arc, vec::Vec}; pub use crate::connection::{ handshake::Handshake, packet::{ConnectionID as ID, Packet, PacketData}, }; use crate::enc::{ hkdf::HkdfSha3, sym::{CipherKind, CipherRecv, CipherSend}, }; /// strong typedef for receiving connection id #[derive(Debug, Copy, Clone)] pub struct IDRecv(pub ID); /// strong typedef for sending connection id #[derive(Debug, Copy, Clone)] pub struct IDSend(pub ID); /// Version of the fenrir protocol in use #[derive(::num_derive::FromPrimitive, Debug, Copy, Clone)] #[repr(u8)] pub enum ProtocolVersion { /// First Fenrir Protocol Version V0 = 0, } impl ProtocolVersion { /// actual length of the protocol version field pub const fn len() -> usize { 1 } /// Serialize into raw bytes pub fn serialize(&self, out: &mut u8) { *out = *self as u8; } } /// A single connection and its data #[derive(Debug)] pub struct Connection { /// Receiving Connection ID pub id_recv: IDRecv, /// Sending Connection ID pub id_send: IDSend, /// The main hkdf used for all secrets in this connection pub hkdf: HkdfSha3, /// Cipher for decrypting data pub cipher_recv: CipherRecv, /// Cipher for encrypting data pub cipher_send: CipherSend, } /// Role: used to set the correct secrets /// * Server: Connection is Incoming /// * Client: Connection is Outgoing #[derive(Debug, Copy, Clone)] #[repr(u8)] pub enum Role { /// Server: we receive the connection Server = 0, /// Client: we initate the connection Client, } impl Connection { pub(crate) fn new( hkdf: HkdfSha3, cipher: CipherKind, role: Role, rand: &::ring::rand::SystemRandom, ) -> Self { let (secret_recv, secret_send) = match role { Role::Server => { (hkdf.get_secret(b"to_server"), hkdf.get_secret(b"to_client")) } Role::Client => { (hkdf.get_secret(b"to_client"), hkdf.get_secret(b"to_server")) } }; let mut cipher_recv = CipherRecv::new(cipher, secret_recv); let mut cipher_send = CipherSend::new(cipher, secret_send, rand); Self { id_recv: IDRecv(ID::Handshake), id_send: IDSend(ID::Handshake), hkdf, cipher_recv, cipher_send, } } } // PERF: Arc> loks a bit too much, need to find // faster ways to do this pub(crate) struct ConnList { connections: Vec>>, /// Bitmap to track which connection ids are used or free ids_used: Vec<::bitmaps::Bitmap<1024>>, } impl ConnList { pub(crate) fn new() -> Self { let mut bitmap_id = ::bitmaps::Bitmap::<1024>::new(); bitmap_id.set(0, true); // ID(0) == handshake Self { connections: Vec::with_capacity(128), ids_used: vec![bitmap_id], } } pub(crate) fn reserve_first( &mut self, mut conn: Connection, ) -> Arc { // uhm... bad things are going on here: // * id must be initialized, but only because: // * rust does not understand that after the `!found` id is always // initialized // * `ID::new_u64` is really safe only with >0, but here it always is // ...we should probably rewrite it in better, safer rust let mut id: u64 = 0; let mut found = false; for (i, b) in self.ids_used.iter_mut().enumerate() { match b.first_false_index() { Some(idx) => { b.set(idx, true); id = ((i as u64) * 1024) + (idx as u64); found = true; break; } None => {} } } if !found { let mut new_bitmap = ::bitmaps::Bitmap::<1024>::new(); new_bitmap.set(0, true); id = (self.ids_used.len() as u64) * 1024; self.ids_used.push(new_bitmap); } let new_id = IDRecv(ID::new_u64(id)); conn.id_recv = new_id; let conn = Arc::new(conn); if (self.connections.len() as u64) < id { self.connections.push(Some(conn.clone())); } else { // very probably redundant self.connections[id as usize] = Some(conn.clone()); } conn } }