Stream stubs, start using namespaces as intended

Signed-off-by: Luca Fulchir <luca.fulchir@runesauth.com>
This commit is contained in:
Luca Fulchir 2023-06-19 18:37:28 +02:00
parent d6825980fd
commit cd7be0ff69
Signed by: luca.fulchir
GPG Key ID: 8F6440603D13A78E
9 changed files with 382 additions and 152 deletions

View File

@ -5,11 +5,11 @@
"systems": "systems" "systems": "systems"
}, },
"locked": { "locked": {
"lastModified": 1681202837, "lastModified": 1685518550,
"narHash": "sha256-H+Rh19JDwRtpVPAWp64F+rlEtxUWBAQW28eAi3SRSzg=", "narHash": "sha256-o2d0KcvaXzTrPRIo0kOLV0/QXHhDQ5DTi+OxcjO8xqY=",
"owner": "numtide", "owner": "numtide",
"repo": "flake-utils", "repo": "flake-utils",
"rev": "cfacdce06f30d2b68473a46042957675eebb3401", "rev": "a1720a10a6cfe8234c0e93907ffe81be440f4cef",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -38,11 +38,11 @@
}, },
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1684922889, "lastModified": 1686921029,
"narHash": "sha256-l0WZAmln8959O7RdYUJ3gnAIM9OPKFLKHKGX4q+Blrk=", "narHash": "sha256-J1bX9plPCFhTSh6E3TWn9XSxggBh/zDD4xigyaIQBy8=",
"owner": "nixos", "owner": "nixos",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "04aaf8511678a0d0f347fdf1e8072fe01e4a509e", "rev": "c7ff1b9b95620ce8728c0d7bd501c458e6da9e04",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -54,11 +54,11 @@
}, },
"nixpkgs-unstable": { "nixpkgs-unstable": {
"locked": { "locked": {
"lastModified": 1684844536, "lastModified": 1686960236,
"narHash": "sha256-M7HhXYVqAuNb25r/d3FOO0z4GxPqDIZp5UjHFbBgw0Q=", "narHash": "sha256-AYCC9rXNLpUWzD9hm+askOfpliLEC9kwAo7ITJc4HIw=",
"owner": "nixos", "owner": "nixos",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "d30264c2691128adc261d7c9388033645f0e742b", "rev": "04af42f3b31dba0ef742d254456dc4c14eedac86",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -98,11 +98,11 @@
"nixpkgs": "nixpkgs_2" "nixpkgs": "nixpkgs_2"
}, },
"locked": { "locked": {
"lastModified": 1684894917, "lastModified": 1687055571,
"narHash": "sha256-kwKCfmliHIxKuIjnM95TRcQxM/4AAEIZ+4A9nDJ6cJs=", "narHash": "sha256-UvLoO6u5n9TzY80BpM4DaacxvyJl7u9mm9CA72d309g=",
"owner": "oxalica", "owner": "oxalica",
"repo": "rust-overlay", "repo": "rust-overlay",
"rev": "9ea38d547100edcf0da19aaebbdffa2810585495", "rev": "2de557c780dcb127128ae987fca9d6c2b0d7dc0f",
"type": "github" "type": "github"
}, },
"original": { "original": {

View File

@ -5,7 +5,7 @@ use crate::{
connection::{ connection::{
self, self,
handshake::{self, Error, Handshake}, handshake::{self, Error, Handshake},
Connection, IDRecv, IDSend, Conn, IDRecv, IDSend,
}, },
enc::{ enc::{
self, self,
@ -29,7 +29,7 @@ pub(crate) type ConnectAnswer = Result<(KeyID, IDSend), crate::Error>;
pub(crate) struct HandshakeClient { pub(crate) struct HandshakeClient {
pub service_id: ServiceID, pub service_id: ServiceID,
pub service_conn_id: IDRecv, pub service_conn_id: IDRecv,
pub connection: Connection, pub connection: Conn,
pub timeout: Option<::tokio::task::JoinHandle<()>>, pub timeout: Option<::tokio::task::JoinHandle<()>>,
pub answer: oneshot::Sender<ConnectAnswer>, pub answer: oneshot::Sender<ConnectAnswer>,
pub srv_key_id: KeyID, pub srv_key_id: KeyID,
@ -79,7 +79,7 @@ impl HandshakeClientList {
pub_key: PubKey, pub_key: PubKey,
service_id: ServiceID, service_id: ServiceID,
service_conn_id: IDRecv, service_conn_id: IDRecv,
connection: Connection, connection: Conn,
answer: oneshot::Sender<ConnectAnswer>, answer: oneshot::Sender<ConnectAnswer>,
srv_key_id: KeyID, srv_key_id: KeyID,
) -> Result<(KeyID, &mut HandshakeClient), oneshot::Sender<ConnectAnswer>> ) -> Result<(KeyID, &mut HandshakeClient), oneshot::Sender<ConnectAnswer>>
@ -144,8 +144,8 @@ pub(crate) struct ClientConnectInfo {
pub service_connection_id: IDRecv, pub service_connection_id: IDRecv,
/// Parsed handshake packet /// Parsed handshake packet
pub handshake: Handshake, pub handshake: Handshake,
/// Connection /// Conn
pub connection: Connection, pub connection: Conn,
/// where to wake up the waiting client /// where to wake up the waiting client
pub answer: oneshot::Sender<ConnectAnswer>, pub answer: oneshot::Sender<ConnectAnswer>,
/// server public key id that we used on the handshake /// server public key id that we used on the handshake
@ -233,7 +233,7 @@ impl HandshakeTracker {
pub_key: PubKey, pub_key: PubKey,
service_id: ServiceID, service_id: ServiceID,
service_conn_id: IDRecv, service_conn_id: IDRecv,
connection: Connection, connection: Conn,
answer: oneshot::Sender<ConnectAnswer>, answer: oneshot::Sender<ConnectAnswer>,
srv_key_id: KeyID, srv_key_id: KeyID,
) -> Result<(KeyID, &mut HandshakeClient), oneshot::Sender<ConnectAnswer>> ) -> Result<(KeyID, &mut HandshakeClient), oneshot::Sender<ConnectAnswer>>

View File

@ -3,13 +3,11 @@
pub mod handshake; pub mod handshake;
pub mod packet; pub mod packet;
pub mod socket; pub mod socket;
pub mod stream;
use ::std::{rc::Rc, vec::Vec}; use ::std::{rc::Rc, vec::Vec};
pub use crate::connection::{ pub use crate::connection::{handshake::Handshake, packet::Packet};
handshake::Handshake,
packet::{ConnectionID as ID, Packet, PacketData},
};
use crate::{ use crate::{
dnssec, dnssec,
@ -21,12 +19,93 @@ use crate::{
}, },
inner::ThreadTracker, inner::ThreadTracker,
}; };
use ::std::rc;
/// Fenrir Connection ID
///
/// 0 is special as it represents the handshake
/// Connection IDs are to be considered u64 little endian
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub enum ID {
/// Connection id 0 represent the handshake
Handshake,
/// Non-zero id can represent any connection
ID(::core::num::NonZeroU64),
}
impl ID {
/// Set the conenction id to handshake
pub fn new_handshake() -> Self {
Self::Handshake
}
/// New id from u64. PLZ NON ZERO
pub(crate) fn new_u64(raw: u64) -> Self {
#[allow(unsafe_code)]
unsafe {
ID::ID(::core::num::NonZeroU64::new_unchecked(raw))
}
}
pub(crate) fn as_u64(&self) -> u64 {
match self {
ID::Handshake => 0,
ID::ID(id) => id.get(),
}
}
/// New random service ID
pub fn new_rand(rand: &Random) -> Self {
let mut raw = [0; 8];
let mut num = 0;
while num == 0 {
rand.fill(&mut raw);
num = u64::from_le_bytes(raw);
}
#[allow(unsafe_code)]
unsafe {
ID::ID(::core::num::NonZeroU64::new_unchecked(num))
}
}
/// Quick check to know if this is an handshake
pub fn is_handshake(&self) -> bool {
*self == ID::Handshake
}
/// length if the connection ID in bytes
pub const fn len() -> usize {
8
}
/// write the ID to a buffer
pub fn serialize(&self, out: &mut [u8]) {
match self {
ID::Handshake => out[..8].copy_from_slice(&[0; 8]),
ID::ID(id) => out[..8].copy_from_slice(&id.get().to_le_bytes()),
}
}
}
impl From<u64> for ID {
fn from(raw: u64) -> Self {
if raw == 0 {
ID::Handshake
} else {
#[allow(unsafe_code)]
unsafe {
ID::ID(::core::num::NonZeroU64::new_unchecked(raw))
}
}
}
}
impl From<[u8; 8]> for ID {
fn from(raw: [u8; 8]) -> Self {
let raw_u64 = u64::from_le_bytes(raw);
raw_u64.into()
}
}
/// strong typedef for receiving connection id /// strong typedef for receiving connection id
#[derive(Debug, Copy, Clone, PartialEq)] #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct IDRecv(pub ID); pub struct IDRecv(pub ID);
/// strong typedef for sending connection id /// strong typedef for sending connection id
#[derive(Debug, Copy, Clone, PartialEq)] #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct IDSend(pub ID); pub struct IDSend(pub ID);
/// Version of the fenrir protocol in use /// Version of the fenrir protocol in use
@ -47,12 +126,16 @@ impl ProtocolVersion {
} }
} }
/// The connection, as seen from a user of libFenrir
#[derive(Debug)]
pub struct Connection(rc::Weak<Conn>);
/// A single connection and its data /// A single connection and its data
#[derive(Debug)] #[derive(Debug)]
pub struct Connection { pub(crate) struct Conn {
/// Receiving Connection ID /// Receiving Conn ID
pub id_recv: IDRecv, pub id_recv: IDRecv,
/// Sending Connection ID /// Sending Conn ID
pub id_send: IDSend, pub id_send: IDSend,
/// The main hkdf used for all secrets in this connection /// The main hkdf used for all secrets in this connection
pub hkdf: Hkdf, pub hkdf: Hkdf,
@ -62,9 +145,12 @@ pub struct Connection {
pub cipher_send: CipherSend, pub cipher_send: CipherSend,
} }
/// Role: used to set the correct secrets /// Role: track the connection direction
/// * Server: Connection is Incoming ///
/// * Client: Connection is Outgoing /// The Role is used to select the correct secrets, and track the direction
/// of the connection
/// * Server: Conn is Incoming
/// * Client: Conn is Outgoing
#[derive(Debug, Copy, Clone)] #[derive(Debug, Copy, Clone)]
#[repr(u8)] #[repr(u8)]
pub enum Role { pub enum Role {
@ -74,7 +160,7 @@ pub enum Role {
Client, Client,
} }
impl Connection { impl Conn {
pub(crate) fn new( pub(crate) fn new(
hkdf: Hkdf, hkdf: Hkdf,
cipher: CipherKind, cipher: CipherKind,
@ -102,11 +188,9 @@ impl Connection {
} }
} }
// PERF: Arc<RwLock<ConnList>> loks a bit too much, need to find
// faster ways to do this
pub(crate) struct ConnList { pub(crate) struct ConnList {
thread_id: ThreadTracker, thread_id: ThreadTracker,
connections: Vec<Option<Rc<Connection>>>, connections: Vec<Option<Rc<Conn>>>,
/// Bitmap to track which connection ids are used or free /// Bitmap to track which connection ids are used or free
ids_used: Vec<::bitmaps::Bitmap<1024>>, ids_used: Vec<::bitmaps::Bitmap<1024>>,
} }
@ -177,7 +261,7 @@ impl ConnList {
new_id new_id
} }
/// NOTE: does NOT check if the connection has been previously reserved! /// NOTE: does NOT check if the connection has been previously reserved!
pub(crate) fn track(&mut self, conn: Rc<Connection>) -> Result<(), ()> { pub(crate) fn track(&mut self, conn: Rc<Conn>) -> Result<(), ()> {
let conn_id = match conn.id_recv { let conn_id = match conn.id_recv {
IDRecv(ID::Handshake) => { IDRecv(ID::Handshake) => {
return Err(()); return Err(());

View File

@ -1,107 +1,26 @@
// //
//! Raw packet handling, encryption, decryption, parsing //! Raw packet handling, encryption, decryption, parsing
use crate::enc::{ use crate::{
sym::{HeadLen, TagLen}, connection,
Random, enc::sym::{HeadLen, TagLen},
}; };
/// Fenrir Connection id
/// 0 is special as it represents the handshake
/// Connection IDs are to be considered u64 little endian
#[derive(Debug, Copy, Clone, PartialEq)]
pub enum ConnectionID {
/// Connection id 0 represent the handshake
Handshake,
/// Non-zero id can represent any connection
ID(::core::num::NonZeroU64),
}
impl ConnectionID {
/// Set the conenction id to handshake
pub fn new_handshake() -> Self {
Self::Handshake
}
/// New id from u64. PLZ NON ZERO
pub(crate) fn new_u64(raw: u64) -> Self {
#[allow(unsafe_code)]
unsafe {
ConnectionID::ID(::core::num::NonZeroU64::new_unchecked(raw))
}
}
pub(crate) fn as_u64(&self) -> u64 {
match self {
ConnectionID::Handshake => 0,
ConnectionID::ID(id) => id.get(),
}
}
/// New random service ID
pub fn new_rand(rand: &Random) -> Self {
let mut raw = [0; 8];
let mut num = 0;
while num == 0 {
rand.fill(&mut raw);
num = u64::from_le_bytes(raw);
}
#[allow(unsafe_code)]
unsafe {
ConnectionID::ID(::core::num::NonZeroU64::new_unchecked(num))
}
}
/// Quick check to know if this is an handshake
pub fn is_handshake(&self) -> bool {
*self == ConnectionID::Handshake
}
/// length if the connection ID in bytes
pub const fn len() -> usize {
8
}
/// write the ID to a buffer
pub fn serialize(&self, out: &mut [u8]) {
match self {
ConnectionID::Handshake => out[..8].copy_from_slice(&[0; 8]),
ConnectionID::ID(id) => {
out[..8].copy_from_slice(&id.get().to_le_bytes())
}
}
}
}
impl From<u64> for ConnectionID {
fn from(raw: u64) -> Self {
if raw == 0 {
ConnectionID::Handshake
} else {
#[allow(unsafe_code)]
unsafe {
ConnectionID::ID(::core::num::NonZeroU64::new_unchecked(raw))
}
}
}
}
impl From<[u8; 8]> for ConnectionID {
fn from(raw: [u8; 8]) -> Self {
let raw_u64 = u64::from_le_bytes(raw);
raw_u64.into()
}
}
/// Enumerate the possible data in a fenrir packet /// Enumerate the possible data in a fenrir packet
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub enum PacketData { pub enum Data {
/// A parsed handshake packet /// A parsed handshake packet
Handshake(super::Handshake), Handshake(super::Handshake),
/// Raw packet. we only have the connection ID and packet length /// Raw packet. we only have the connection ID and packet length
Raw(usize), Raw(usize),
} }
impl PacketData { impl Data {
/// total length of the data in bytes /// total length of the data in bytes
pub fn len(&self, head_len: HeadLen, tag_len: TagLen) -> usize { pub fn len(&self, head_len: HeadLen, tag_len: TagLen) -> usize {
match self { match self {
PacketData::Handshake(h) => h.len(head_len, tag_len), Data::Handshake(h) => h.len(head_len, tag_len),
PacketData::Raw(len) => *len, Data::Raw(len) => *len,
} }
} }
/// serialize data into bytes /// serialize data into bytes
@ -114,12 +33,12 @@ impl PacketData {
) { ) {
assert!( assert!(
self.len(head_len, tag_len) == out.len(), self.len(head_len, tag_len) == out.len(),
"PacketData: wrong buffer length" "Data: wrong buffer length"
); );
match self { match self {
PacketData::Handshake(h) => h.serialize(head_len, tag_len, out), Data::Handshake(h) => h.serialize(head_len, tag_len, out),
PacketData::Raw(_) => { Data::Raw(_) => {
::tracing::error!("Tried to serialize a raw PacketData!"); ::tracing::error!("Tried to serialize a raw Data!");
} }
} }
} }
@ -131,9 +50,9 @@ const MIN_PACKET_BYTES: usize = 16;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Packet { pub struct Packet {
/// Id of the Fenrir connection. /// Id of the Fenrir connection.
pub id: ConnectionID, pub id: connection::ID,
/// actual data inside the packet /// actual data inside the packet
pub data: PacketData, pub data: Data,
} }
impl Packet { impl Packet {
@ -146,12 +65,12 @@ impl Packet {
let raw_id: [u8; 8] = (raw[..8]).try_into().expect("unreachable"); let raw_id: [u8; 8] = (raw[..8]).try_into().expect("unreachable");
Ok(Packet { Ok(Packet {
id: raw_id.into(), id: raw_id.into(),
data: PacketData::Raw(raw.len()), data: Data::Raw(raw.len()),
}) })
} }
/// get the total length of the packet /// get the total length of the packet
pub fn len(&self, head_len: HeadLen, tag_len: TagLen) -> usize { pub fn len(&self, head_len: HeadLen, tag_len: TagLen) -> usize {
ConnectionID::len() + self.data.len(head_len, tag_len) connection::ID::len() + self.data.len(head_len, tag_len)
} }
/// serialize packet into buffer /// serialize packet into buffer
/// NOTE: assumes that there is exactly asa much buffer as needed /// NOTE: assumes that there is exactly asa much buffer as needed
@ -162,11 +81,14 @@ impl Packet {
out: &mut [u8], out: &mut [u8],
) { ) {
assert!( assert!(
out.len() > ConnectionID::len(), out.len() > connection::ID::len(),
"Packet: not enough buffer to serialize" "Packet: not enough buffer to serialize"
); );
self.id.serialize(&mut out[0..ConnectionID::len()]); self.id.serialize(&mut out[0..connection::ID::len()]);
self.data self.data.serialize(
.serialize(head_len, tag_len, &mut out[ConnectionID::len()..]); head_len,
tag_len,
&mut out[connection::ID::len()..],
);
} }
} }

View File

@ -0,0 +1,10 @@
//! Errors while parsing streams
/// Crypto errors
#[derive(::thiserror::Error, Debug, Copy, Clone)]
pub enum Error {
/// Error while parsing key material
#[error("Not enough data for stream chunk: {0}")]
NotEnoughData(usize),
}

View File

@ -0,0 +1,183 @@
//! Here we implement the multiplexing stream feature of Fenrir
//!
//! For now we will only have the TCP-like, reliable, in-order delivery
mod errors;
mod rob;
pub use errors::Error;
use crate::{connection::stream::rob::ReliableOrderedBytestream, enc::Random};
/// Kind of stream. any combination of:
/// reliable/unreliable ordered/unordered, bytestream/datagram
#[derive(Debug, Copy, Clone)]
#[repr(u8)]
pub enum Kind {
/// ROB: Reliable, Ordered, Bytestream
/// AKA: TCP-like
ROB = 0,
}
/// Id of the stream
#[derive(Debug, Copy, Clone)]
pub struct ID(pub u16);
impl ID {
/// Length of the serialized field
pub const fn len() -> usize {
2
}
}
/// length of the chunk
#[derive(Debug, Copy, Clone)]
pub struct ChunkLen(pub u16);
impl ChunkLen {
/// Length of the serialized field
pub const fn len() -> usize {
2
}
}
/// Sequence number to rebuild the stream correctly
#[derive(Debug, Copy, Clone)]
pub struct Sequence(pub ::core::num::Wrapping<u32>);
impl Sequence {
const SEQ_NOFLAG: u32 = 0x3FFFFFFF;
/// return a new sequence number, starting at random
pub fn new(rand: &Random) -> Self {
let seq: u32 = 0;
rand.fill(&mut seq.to_le_bytes());
Self(::core::num::Wrapping(seq & Self::SEQ_NOFLAG))
}
/// Length of the serialized field
pub const fn len() -> usize {
4
}
}
/// Chunk of data representing a stream
/// Every chunk is as follows:
/// | id (2 bytes) | length (2 bytes) |
/// | flag_start (1 BIT) | flag_end (1 BIT) | sequence (30 bits) |
#[derive(Debug, Clone)]
pub struct Chunk<'a> {
/// Id of the stream this chunk is part of
pub id: ID,
/// Is this the beginning of a message?
pub flag_start: bool,
/// Is this the end of a message?
pub flag_end: bool,
/// Sequence number to reconstruct the Stream
pub sequence: Sequence,
data: &'a [u8],
}
impl<'a> Chunk<'a> {
const FLAGS_EXCLUDED_BITMASK: u8 = 0x3F;
const FLAG_START_BITMASK: u8 = 0x80;
const FLAG_END_BITMASK: u8 = 0x40;
/// Returns the total length of the chunk, including headers
pub fn len(&self) -> usize {
ID::len() + ChunkLen::len() + Sequence::len() + self.data.len()
}
/// deserialize a chunk of a stream
pub fn deserialize(raw: &'a [u8]) -> Result<Self, Error> {
if raw.len() <= ID::len() + ChunkLen::len() + Sequence::len() {
return Err(Error::NotEnoughData(0));
}
let id = ID(u16::from_le_bytes(raw[0..ID::len()].try_into().unwrap()));
let mut bytes_next = ID::len() + ChunkLen::len();
let length = ChunkLen(u16::from_le_bytes(
raw[ID::len()..bytes_next].try_into().unwrap(),
));
if ID::len() + ChunkLen::len() + Sequence::len() + length.0 as usize
> raw.len()
{
return Err(Error::NotEnoughData(4));
}
let flag_start = (raw[bytes_next] & Self::FLAG_START_BITMASK) != 0;
let flag_end = (raw[bytes_next] & Self::FLAG_END_BITMASK) != 0;
let bytes = bytes_next + 1;
bytes_next = bytes + Sequence::len();
let mut sequence_bytes: [u8; Sequence::len()] =
raw[bytes..bytes_next].try_into().unwrap();
sequence_bytes[0] = sequence_bytes[0] & Self::FLAGS_EXCLUDED_BITMASK;
let sequence =
Sequence(::core::num::Wrapping(u32::from_le_bytes(sequence_bytes)));
Ok(Self {
id,
flag_start,
flag_end,
sequence,
data: &raw[bytes_next..(bytes_next + length.0 as usize)],
})
}
/// serialize a chunk of a stream
pub fn serialize(&self, raw_out: &mut [u8]) {
raw_out[0..ID::len()].copy_from_slice(&self.id.0.to_le_bytes());
let mut bytes_next = ID::len() + ChunkLen::len();
raw_out[ID::len()..bytes_next]
.copy_from_slice(&(self.data.len() as u16).to_le_bytes());
let bytes = bytes_next;
bytes_next = bytes_next + Sequence::len();
raw_out[bytes..bytes_next]
.copy_from_slice(&self.sequence.0 .0.to_le_bytes());
let mut flag_byte = raw_out[bytes] & Self::FLAGS_EXCLUDED_BITMASK;
if self.flag_start {
flag_byte = flag_byte | Self::FLAG_START_BITMASK;
}
if self.flag_end {
flag_byte = flag_byte | Self::FLAG_END_BITMASK;
}
raw_out[bytes] = flag_byte;
let bytes = bytes_next;
bytes_next = bytes_next + self.data.len();
raw_out[bytes..bytes_next].copy_from_slice(&self.data);
}
}
/// Kind of stream. any combination of:
/// reliable/unreliable ordered/unordered, bytestream/datagram
/// differences from Kind:
/// * not public
/// * has actual data
#[derive(Debug, Clone)]
pub(crate) enum Tracker {
/// ROB: Reliable, Ordered, Bytestream
/// AKA: TCP-like
ROB(ReliableOrderedBytestream),
}
impl Tracker {
pub(crate) fn new(kind: Kind, rand: &Random) -> Self {
match kind {
Kind::ROB => Tracker::ROB(ReliableOrderedBytestream::new(rand)),
}
}
}
/// Actual stream-tracking structure
#[derive(Debug, Clone)]
pub(crate) struct Stream {
id: ID,
data: Tracker,
}
impl Stream {
pub(crate) fn new(kind: Kind, rand: &Random) -> Self {
let id: u16 = 0;
rand.fill(&mut id.to_le_bytes());
Self {
id: ID(id),
data: Tracker::new(kind, rand),
}
}
}

View File

@ -0,0 +1,29 @@
//! Implementation of the Reliable, Ordered, Bytestream transmission model
//! AKA: TCP-like
use crate::{
connection::stream::{Chunk, Error, Sequence},
enc::Random,
};
/// Reliable, Ordered, Bytestream stream tracker
/// AKA: TCP-like
#[derive(Debug, Clone)]
pub(crate) struct ReliableOrderedBytestream {
window_start: Sequence,
window_len: usize,
data: Vec<u8>,
}
impl ReliableOrderedBytestream {
pub(crate) fn new(rand: &Random) -> Self {
Self {
window_start: Sequence::new(rand),
window_len: 1048576, // 1MB. should be enough for anybody. (lol)
data: Vec::new(),
}
}
pub(crate) fn recv(&mut self, chunk: Chunk) -> Result<(), Error> {
todo!()
}
}

View File

@ -10,8 +10,9 @@ use crate::{
tracker::{HandshakeAction, HandshakeTracker}, tracker::{HandshakeAction, HandshakeTracker},
Handshake, HandshakeData, Handshake, HandshakeData,
}, },
packet::{self, Packet},
socket::{UdpClient, UdpServer}, socket::{UdpClient, UdpServer},
ConnList, Connection, IDSend, Packet, Conn, ConnList, IDSend,
}, },
dnssec, dnssec,
enc::{ enc::{
@ -125,6 +126,7 @@ impl Worker {
handshakes, handshakes,
}) })
} }
/// Continuously loop and process work as needed /// Continuously loop and process work as needed
pub async fn work_loop(&mut self) { pub async fn work_loop(&mut self) {
'mainloop: loop { 'mainloop: loop {
@ -292,7 +294,7 @@ impl Worker {
// are PubKey::Exchange // are PubKey::Exchange
unreachable!() unreachable!()
} }
let mut conn = Connection::new( let mut conn = Conn::new(
hkdf, hkdf,
cipher_selected, cipher_selected,
connection::Role::Client, connection::Role::Client,
@ -345,7 +347,8 @@ impl Worker {
exchange_key: pub_key, exchange_key: pub_key,
data: dirsync::ReqInner::ClearText(req_data), data: dirsync::ReqInner::ClearText(req_data),
}; };
let encrypt_start = ID::len() + req.encrypted_offset(); let encrypt_start =
connection::ID::len() + req.encrypted_offset();
let encrypt_end = encrypt_start let encrypt_end = encrypt_start
+ req.encrypted_length( + req.encrypted_length(
cipher_selected.nonce_len(), cipher_selected.nonce_len(),
@ -354,10 +357,9 @@ impl Worker {
let h_req = Handshake::new(HandshakeData::DirSync( let h_req = Handshake::new(HandshakeData::DirSync(
DirSync::Req(req), DirSync::Req(req),
)); ));
use connection::{PacketData, ID};
let packet = Packet { let packet = Packet {
id: ID::Handshake, id: connection::ID::Handshake,
data: PacketData::Handshake(h_req), data: packet::Data::Handshake(h_req),
}; };
let tot_len = packet.len( let tot_len = packet.len(
@ -510,12 +512,12 @@ impl Worker {
// Client has correctly authenticated // Client has correctly authenticated
// TODO: contact the service, get the key and // TODO: contact the service, get the key and
// connection ID // connection ID
let srv_conn_id = ID::new_rand(&self.rand); let srv_conn_id = connection::ID::new_rand(&self.rand);
let srv_secret = Secret::new_rand(&self.rand); let srv_secret = Secret::new_rand(&self.rand);
let head_len = req.cipher.nonce_len(); let head_len = req.cipher.nonce_len();
let tag_len = req.cipher.tag_len(); let tag_len = req.cipher.tag_len();
let mut auth_conn = Connection::new( let mut auth_conn = Conn::new(
authinfo.hkdf, authinfo.hkdf,
req.cipher, req.cipher,
connection::Role::Server, connection::Role::Server,
@ -541,16 +543,16 @@ impl Worker {
client_key_id: req_data.client_key_id, client_key_id: req_data.client_key_id,
data: RespInner::ClearText(resp_data), data: RespInner::ClearText(resp_data),
}; };
let encrypt_from = ID::len() + resp.encrypted_offset(); let encrypt_from =
connection::ID::len() + resp.encrypted_offset();
let encrypt_until = let encrypt_until =
encrypt_from + resp.encrypted_length(head_len, tag_len); encrypt_from + resp.encrypted_length(head_len, tag_len);
let resp_handshake = Handshake::new( let resp_handshake = Handshake::new(
HandshakeData::DirSync(DirSync::Resp(resp)), HandshakeData::DirSync(DirSync::Resp(resp)),
); );
use connection::{PacketData, ID};
let packet = Packet { let packet = Packet {
id: ID::new_handshake(), id: connection::ID::new_handshake(),
data: PacketData::Handshake(resp_handshake), data: packet::Data::Handshake(resp_handshake),
}; };
let tot_len = packet.len(head_len, tag_len); let tot_len = packet.len(head_len, tag_len);
let mut raw_out = Vec::<u8>::with_capacity(tot_len); let mut raw_out = Vec::<u8>::with_capacity(tot_len);
@ -611,7 +613,7 @@ impl Worker {
cci.service_id.as_bytes(), cci.service_id.as_bytes(),
resp_data.service_key, resp_data.service_key,
); );
let mut service_connection = Connection::new( let mut service_connection = Conn::new(
hkdf, hkdf,
cipher, cipher,
connection::Role::Client, connection::Role::Client,

View File

@ -39,6 +39,7 @@ use crate::{
}, },
}; };
pub use config::Config; pub use config::Config;
pub use connection::Connection;
/// Main fenrir library errors /// Main fenrir library errors
#[derive(::thiserror::Error, Debug)] #[derive(::thiserror::Error, Debug)]
@ -332,7 +333,7 @@ impl Fenrir {
let data: Vec<u8> = buffer[..bytes].to_vec(); let data: Vec<u8> = buffer[..bytes].to_vec();
// we very likely have multiple threads, pinned to different cpus. // we very likely have multiple threads, pinned to different cpus.
// use the ConnectionID to send the same connection // use the connection::ID to send the same connection
// to the same thread. // to the same thread.
// Handshakes have connection ID 0, so we use the sender's UDP port // Handshakes have connection ID 0, so we use the sender's UDP port
@ -341,13 +342,12 @@ impl Fenrir {
Err(_) => continue, // packet way too short, ignore. Err(_) => continue, // packet way too short, ignore.
}; };
let thread_idx: usize = { let thread_idx: usize = {
use connection::packet::ConnectionID;
match packet.id { match packet.id {
ConnectionID::Handshake => { connection::ID::Handshake => {
let send_port = sock_sender.0.port() as u64; let send_port = sock_sender.0.port() as u64;
(send_port % queues_num) as usize (send_port % queues_num) as usize
} }
ConnectionID::ID(id) => (id.get() % queues_num) as usize, connection::ID::ID(id) => (id.get() % queues_num) as usize,
} }
}; };
let _ = work_queues[thread_idx] let _ = work_queues[thread_idx]