feat: implemented responses
This commit is contained in:
parent
1c868ff972
commit
e6fa8b694c
|
@ -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",
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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,
|
||||
}
|
99
src/lib.rs
99
src/lib.rs
|
@ -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(())
|
||||
}
|
||||
}
|
||||
|
|
Reference in New Issue