Implement CBS API handling on the trinitrix core side. #23

Merged
antifallobst merged 8 commits from cbs-core into main 2024-05-21 21:09:48 +00:00
7 changed files with 22 additions and 125 deletions
Showing only changes of commit 4519fe5db6 - Show all commits

16
Cargo.lock generated
View File

@ -1441,6 +1441,21 @@ dependencies = [
"tokio",
]
[[package]]
name = "triba-packet"
version = "0.1.0"
dependencies = [
"aes-gcm-siv",
"anyhow",
"interprocess",
"rmp-serde",
"serde",
"strum",
"tokio",
"uuid",
"x25519-dalek",
]
[[package]]
name = "trinitrix"
version = "0.1.0"
@ -1464,6 +1479,7 @@ dependencies = [
"strum",
"tokio",
"tokio-util",
"triba-packet",
"trinitry",
"trixy",
"tui-textarea",

View File

@ -69,6 +69,7 @@ crossterm = { version = "0.25" }
# Trinitrx Backend API specific
interprocess = { version = "2.1.0", features = ["tokio"] }
triba-packet = { path = "../triba-packet" }
[dev-dependencies]
pretty_assertions = "1.4.0"

View File

@ -1,5 +1,3 @@
use super::packet::{self, IdPool, Packet};
use aes_gcm_siv::{Aes256GcmSiv, Nonce};
use anyhow::{anyhow, Result};
use interprocess::local_socket::tokio::{RecvHalf, SendHalf};
@ -8,6 +6,7 @@ use tokio::{
sync::mpsc,
};
use tokio_util::sync::CancellationToken;
use triba_packet::{self as packet, IdPool, Packet};
use uuid::Uuid;
pub struct Connection {

View File

@ -1,13 +1,11 @@
use super::packet;
use crate::cbs::packet::Packet;
use aes_gcm_siv::{Aes256GcmSiv, KeyInit, Nonce};
use anyhow::anyhow;
use interprocess::local_socket::{
self,
tokio::{prelude::*, Stream},
};
use rand::thread_rng;
use tokio::io::{AsyncReadExt, AsyncWriteExt, BufReader};
use triba_packet::{self as packet, IdPool, Packet};
use uuid::Uuid;
use x25519_dalek::{EphemeralSecret, PublicKey};
@ -40,7 +38,7 @@ pub async fn cbs(sock_name: local_socket::Name<'_>, id: Uuid) {
let cipher = Aes256GcmSiv::new(shared_secret.as_bytes().into());
let mut id_pool = packet::IdPool::new();
let mut id_pool = IdPool::new();
tx.write(
Packet::new(&mut id_pool, packet::Body::HandshakeUpgradeConnection)

View File

@ -1,4 +1,4 @@
use super::{packet, Connection, UnstableConnection};
use super::{Connection, UnstableConnection};
use aes_gcm_siv::{Aes256GcmSiv, KeyInit, Nonce};
use anyhow::{anyhow, Result};
@ -17,6 +17,7 @@ use tokio::{
sync::{mpsc, oneshot},
};
use tokio_util::sync::CancellationToken;
use triba_packet as packet;
use uuid::Uuid;
use x25519_dalek::{EphemeralSecret, PublicKey};

View File

@ -1,7 +1,6 @@
pub mod connection;
mod dummy;
pub mod manager;
pub(self) mod packet;
// TODO: This whole module uses hell a lot of unwraps,
// which need to be replaced by proper error handling. - antifallobst 2024-05-14

View File

@ -1,117 +0,0 @@
use aes_gcm_siv::{AeadInPlace, Aes256GcmSiv, Nonce};
use anyhow::{anyhow, Result};
use serde::{Deserialize, Serialize};
use strum::Display;
use tokio::io::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt};
pub struct IdPool {
last: u64,
}
impl IdPool {
pub fn new() -> Self {
Self { last: 0 }
}
pub fn acquire(&mut self) -> u64 {
self.last += 1;
self.last
}
}
#[derive(Debug, Copy, Clone, Serialize, Deserialize)]
pub struct Version(u32);
impl Version {
/// Splits the version into its three parts: (major, minor, patch)
pub fn extract(self) -> (u8, u16, u8) {
let major = ((self.0 & 0xFF000000) >> 24) as u8;
let minor = ((self.0 & 0x00FFFF00) >> 8) as u16;
let patch = (self.0 & 0x000000FF) as u8;
(major, minor, patch)
}
}
#[repr(u8)]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum Error {
Fatal(String),
}
#[repr(u32)]
#[derive(Debug, Clone, Serialize, Deserialize, Display)]
pub enum Body {
// Misc
Exit(Error) = 0x000_00000,
// Handshake
HandshakeUpgradeConnection = 0x001_00000,
HandshakeApiVersion(Version) = 0x001_00001,
HandshakeConfig = 0x001_00002,
HandshakeSuccess = 0x001_00003,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Packet {
id: u64,
body: Body,
}
impl Packet {
pub fn new(id_pool: &mut IdPool, body: Body) -> Self {
Self {
id: id_pool.acquire(),
body,
}
}
pub fn body(&self) -> &Body {
&self.body
}
// Serializes the packet to MessagePack and encrypts it.
pub fn pack(&self, cipher: &Aes256GcmSiv, nonce: &Nonce) -> Result<Vec<u8>> {
let mut data = rmp_serde::to_vec(self)?;
cipher
.encrypt_in_place(&nonce, b"", &mut data)
.map_err(|e| anyhow!("while packing packet: {e}"))?;
let mut vec = (data.len() as u32).to_le_bytes().to_vec();
vec.append(&mut data);
Ok(vec)
}
// Deserializes a packet from encrypted MessagePack.
pub fn unpack(data: &mut Vec<u8>, cipher: &Aes256GcmSiv, nonce: &Nonce) -> Result<Self> {
cipher
.decrypt_in_place(&nonce, b"", data)
.map_err(|e| anyhow!("while unpacking packet: {e}"))?;
Ok(rmp_serde::from_slice::<Packet>(data.as_slice())?)
}
pub async fn recv<T: AsyncRead + Unpin>(
rx: &mut T,
cipher: &Aes256GcmSiv,
nonce: &Nonce,
) -> Result<Self> {
let size = rx.read_u32_le().await? as usize;
let mut buffer = vec![0u8; size];
rx.read(&mut buffer).await?;
Packet::unpack(&mut buffer, &cipher, &nonce)
}
pub async fn send<T: AsyncWrite + Unpin>(
&self,
tx: &mut T,
cipher: &Aes256GcmSiv,
nonce: &Nonce,
) -> Result<()> {
let raw = self.pack(cipher, nonce)?;
tx.write(raw.as_slice()).await?;
Ok(())
}
}