feat: implemented responses

This commit is contained in:
antifallobst 2024-05-21 04:16:51 +02:00
parent 1c868ff972
commit e6fa8b694c
Signed by: antifallobst
GPG Key ID: 2B4F402172791BAF
4 changed files with 98 additions and 53 deletions

28
Cargo.lock generated
View File

@ -53,12 +53,6 @@ dependencies = [
"zeroize",
]
[[package]]
name = "anyhow"
version = "1.0.83"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "25bdb32cbbdce2b519a9cd7df3a678443100e265d5e25ca763b7572a5104f5f3"
[[package]]
name = "autocfg"
version = "1.3.0"
@ -491,6 +485,26 @@ dependencies = [
"unicode-ident",
]
[[package]]
name = "thiserror"
version = "1.0.61"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.61"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "tokio"
version = "1.37.0"
@ -524,11 +538,11 @@ name = "triba-packet"
version = "0.1.0"
dependencies = [
"aes-gcm-siv",
"anyhow",
"interprocess",
"rmp-serde",
"serde",
"strum",
"thiserror",
"tokio",
"uuid",
"x25519-dalek",

View File

@ -23,7 +23,7 @@ version = "0.1.0"
edition = "2021"
[dependencies]
anyhow = "1.0"
thiserror = "1.0.60"
tokio = { version = "1.37", features = [
"macros",
"rt-multi-thread",

22
src/error.rs Normal file
View File

@ -0,0 +1,22 @@
use thiserror::Error;
#[derive(Debug, Error)]
pub enum Error {
#[error("Failed to encrypt packet")]
EncryptionError,
#[error("Failed to decrypt packet")]
DecryptionError,
#[error("Failed to serialize packet: {0}")]
SerializationError(String),
#[error("Failed to deserialize packet: {0}")]
DeserializationError(String),
#[error("Failed to read data from the stream")]
StreamReadError,
#[error("Failed to write data to the stream")]
StreamWriteError,
}

View File

@ -1,5 +1,9 @@
mod error;
pub use error::Error;
use std::fmt::Formatter;
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};
@ -19,63 +23,63 @@ impl IdPool {
}
}
#[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 {
pub enum Request {
// Misc
Exit(Error) = 0x000_00000,
Close = 0x000_00000,
// Handshake
HandshakeUpgradeConnection = 0x001_00000,
HandshakeApiVersion(Version) = 0x001_00001,
HandshakeApiVersion(String) = 0x001_00001,
HandshakeConfig = 0x001_00002,
HandshakeSuccess = 0x001_00003,
}
#[repr(u32)]
#[derive(Debug, Clone, Serialize, Deserialize, Display)]
pub enum Response {
// Standard success / neutral responses
Success = 0xFFE_00000,
Ackknowledged = 0xFFE_00001,
// Standard error responses
RessourceTimeout = 0xFFF_00000,
PermissionDenied = 0xFFF_00001,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Packet {
id: u64,
body: Body,
pub enum Packet {
Request { id: u64, body: Request },
Response { id: u64, req: u64, body: Response },
}
impl std::fmt::Display for Packet {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
Self::Request { body, .. } => write!(f, "Request::{body}")?,
Self::Response { body, .. } => write!(f, "Response::{body}")?,
}
Ok(())
}
}
impl Packet {
pub fn new(id_pool: &mut IdPool, body: Body) -> Self {
Self {
id: id_pool.acquire(),
body,
}
pub fn request(id: u64, body: Request) -> Self {
Self::Request { id, body }
}
pub fn body(&self) -> &Body {
&self.body
pub fn response(id: u64, req: u64, body: Response) -> Self {
Self::Response { id, req, 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)?;
pub fn pack(&self, cipher: &Aes256GcmSiv, nonce: &Nonce) -> Result<Vec<u8>, Error> {
let mut data =
rmp_serde::to_vec(self).map_err(|e| Error::SerializationError(e.to_string()))?;
cipher
.encrypt_in_place(&nonce, b"", &mut data)
.map_err(|e| anyhow!("while packing packet: {e}"))?;
.map_err(|_| Error::EncryptionError)?;
let mut vec = (data.len() as u32).to_le_bytes().to_vec();
vec.append(&mut data);
@ -84,22 +88,25 @@ impl Packet {
}
// Deserializes a packet from encrypted MessagePack.
pub fn unpack(data: &mut Vec<u8>, cipher: &Aes256GcmSiv, nonce: &Nonce) -> Result<Self> {
pub fn unpack(data: &mut Vec<u8>, cipher: &Aes256GcmSiv, nonce: &Nonce) -> Result<Self, Error> {
cipher
.decrypt_in_place(&nonce, b"", data)
.map_err(|e| anyhow!("while unpacking packet: {e}"))?;
Ok(rmp_serde::from_slice::<Packet>(data.as_slice())?)
.map_err(|_| Error::DecryptionError)?;
Ok(rmp_serde::from_slice::<Packet>(data.as_slice())
.map_err(|e| Error::DeserializationError(e.to_string()))?)
}
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;
) -> Result<Self, Error> {
let size = rx.read_u32_le().await.map_err(|_| Error::StreamReadError)? as usize;
let mut buffer = vec![0u8; size];
rx.read(&mut buffer).await?;
rx.read(&mut buffer)
.await
.map_err(|_| Error::StreamReadError)?;
Packet::unpack(&mut buffer, &cipher, &nonce)
}
@ -109,9 +116,11 @@ impl Packet {
tx: &mut T,
cipher: &Aes256GcmSiv,
nonce: &Nonce,
) -> Result<()> {
) -> Result<(), Error> {
let raw = self.pack(cipher, nonce)?;
tx.write(raw.as_slice()).await?;
tx.write(raw.as_slice())
.await
.map_err(|_| Error::StreamWriteError)?;
Ok(())
}
}