feat: implemented responses
This commit is contained in:
parent
1c868ff972
commit
e6fa8b694c
|
@ -53,12 +53,6 @@ dependencies = [
|
||||||
"zeroize",
|
"zeroize",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "anyhow"
|
|
||||||
version = "1.0.83"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "25bdb32cbbdce2b519a9cd7df3a678443100e265d5e25ca763b7572a5104f5f3"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "autocfg"
|
name = "autocfg"
|
||||||
version = "1.3.0"
|
version = "1.3.0"
|
||||||
|
@ -491,6 +485,26 @@ dependencies = [
|
||||||
"unicode-ident",
|
"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]]
|
[[package]]
|
||||||
name = "tokio"
|
name = "tokio"
|
||||||
version = "1.37.0"
|
version = "1.37.0"
|
||||||
|
@ -524,11 +538,11 @@ name = "triba-packet"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aes-gcm-siv",
|
"aes-gcm-siv",
|
||||||
"anyhow",
|
|
||||||
"interprocess",
|
"interprocess",
|
||||||
"rmp-serde",
|
"rmp-serde",
|
||||||
"serde",
|
"serde",
|
||||||
"strum",
|
"strum",
|
||||||
|
"thiserror",
|
||||||
"tokio",
|
"tokio",
|
||||||
"uuid",
|
"uuid",
|
||||||
"x25519-dalek",
|
"x25519-dalek",
|
||||||
|
|
|
@ -23,7 +23,7 @@ version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1.0"
|
thiserror = "1.0.60"
|
||||||
tokio = { version = "1.37", features = [
|
tokio = { version = "1.37", features = [
|
||||||
"macros",
|
"macros",
|
||||||
"rt-multi-thread",
|
"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 aes_gcm_siv::{AeadInPlace, Aes256GcmSiv, Nonce};
|
||||||
use anyhow::{anyhow, Result};
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use strum::Display;
|
use strum::Display;
|
||||||
use tokio::io::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt};
|
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)]
|
#[repr(u32)]
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, Display)]
|
#[derive(Debug, Clone, Serialize, Deserialize, Display)]
|
||||||
pub enum Body {
|
pub enum Request {
|
||||||
// Misc
|
// Misc
|
||||||
Exit(Error) = 0x000_00000,
|
Close = 0x000_00000,
|
||||||
|
|
||||||
// Handshake
|
// Handshake
|
||||||
HandshakeUpgradeConnection = 0x001_00000,
|
HandshakeUpgradeConnection = 0x001_00000,
|
||||||
HandshakeApiVersion(Version) = 0x001_00001,
|
HandshakeApiVersion(String) = 0x001_00001,
|
||||||
HandshakeConfig = 0x001_00002,
|
HandshakeConfig = 0x001_00002,
|
||||||
HandshakeSuccess = 0x001_00003,
|
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)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
pub struct Packet {
|
pub enum Packet {
|
||||||
id: u64,
|
Request { id: u64, body: Request },
|
||||||
body: Body,
|
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 {
|
impl Packet {
|
||||||
pub fn new(id_pool: &mut IdPool, body: Body) -> Self {
|
pub fn request(id: u64, body: Request) -> Self {
|
||||||
Self {
|
Self::Request { id, body }
|
||||||
id: id_pool.acquire(),
|
|
||||||
body,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn body(&self) -> &Body {
|
pub fn response(id: u64, req: u64, body: Response) -> Self {
|
||||||
&self.body
|
Self::Response { id, req, body }
|
||||||
}
|
}
|
||||||
|
|
||||||
// Serializes the packet to MessagePack and encrypts it.
|
// Serializes the packet to MessagePack and encrypts it.
|
||||||
pub fn pack(&self, cipher: &Aes256GcmSiv, nonce: &Nonce) -> Result<Vec<u8>> {
|
pub fn pack(&self, cipher: &Aes256GcmSiv, nonce: &Nonce) -> Result<Vec<u8>, Error> {
|
||||||
let mut data = rmp_serde::to_vec(self)?;
|
let mut data =
|
||||||
|
rmp_serde::to_vec(self).map_err(|e| Error::SerializationError(e.to_string()))?;
|
||||||
cipher
|
cipher
|
||||||
.encrypt_in_place(&nonce, b"", &mut data)
|
.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();
|
let mut vec = (data.len() as u32).to_le_bytes().to_vec();
|
||||||
vec.append(&mut data);
|
vec.append(&mut data);
|
||||||
|
@ -84,22 +88,25 @@ impl Packet {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deserializes a packet from encrypted MessagePack.
|
// 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
|
cipher
|
||||||
.decrypt_in_place(&nonce, b"", data)
|
.decrypt_in_place(&nonce, b"", data)
|
||||||
.map_err(|e| anyhow!("while unpacking packet: {e}"))?;
|
.map_err(|_| Error::DecryptionError)?;
|
||||||
Ok(rmp_serde::from_slice::<Packet>(data.as_slice())?)
|
Ok(rmp_serde::from_slice::<Packet>(data.as_slice())
|
||||||
|
.map_err(|e| Error::DeserializationError(e.to_string()))?)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn recv<T: AsyncRead + Unpin>(
|
pub async fn recv<T: AsyncRead + Unpin>(
|
||||||
rx: &mut T,
|
rx: &mut T,
|
||||||
cipher: &Aes256GcmSiv,
|
cipher: &Aes256GcmSiv,
|
||||||
nonce: &Nonce,
|
nonce: &Nonce,
|
||||||
) -> Result<Self> {
|
) -> Result<Self, Error> {
|
||||||
let size = rx.read_u32_le().await? as usize;
|
let size = rx.read_u32_le().await.map_err(|_| Error::StreamReadError)? as usize;
|
||||||
|
|
||||||
let mut buffer = vec![0u8; size];
|
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)
|
Packet::unpack(&mut buffer, &cipher, &nonce)
|
||||||
}
|
}
|
||||||
|
@ -109,9 +116,11 @@ impl Packet {
|
||||||
tx: &mut T,
|
tx: &mut T,
|
||||||
cipher: &Aes256GcmSiv,
|
cipher: &Aes256GcmSiv,
|
||||||
nonce: &Nonce,
|
nonce: &Nonce,
|
||||||
) -> Result<()> {
|
) -> Result<(), Error> {
|
||||||
let raw = self.pack(cipher, nonce)?;
|
let raw = self.pack(cipher, nonce)?;
|
||||||
tx.write(raw.as_slice()).await?;
|
tx.write(raw.as_slice())
|
||||||
|
.await
|
||||||
|
.map_err(|_| Error::StreamWriteError)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Reference in New Issue