Implement CBS API handling on the trinitrix core side. #23
|
@ -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",
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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};
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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(())
|
||||
}
|
||||
}
|
Reference in New Issue