From 76502f5e00005b6b78beda9e2bc4d307ae0cd66b Mon Sep 17 00:00:00 2001 From: soruh Date: Sat, 24 Jun 2023 16:14:11 +0200 Subject: [PATCH] clean up packet errors --- src/client.rs | 1 + src/packets.rs | 80 ++++++++++++++++++++++++++++++++++++-------------- 2 files changed, 59 insertions(+), 22 deletions(-) diff --git a/src/client.rs b/src/client.rs index 387f103..b518d80 100644 --- a/src/client.rs +++ b/src/client.rs @@ -71,6 +71,7 @@ async fn authenticate( let _ip = dyn_ip_update(&config.dyn_ip_server, number, pin, port).await?; } + // TODO: do we want to cache this? If so, for how long? #[cfg(feature = "debug_server")] let name = peer_query(&config.dyn_ip_server, number).await?; diff --git a/src/packets.rs b/src/packets.rs index 5ef6d39..3ae3d30 100644 --- a/src/packets.rs +++ b/src/packets.rs @@ -1,7 +1,6 @@ -use std::fmt::Debug; +use std::fmt::{Debug, Display}; use bytemuck::{Pod, Zeroable}; -use eyre::eyre; use serde::Serialize; use smallvec::SmallVec; use tokio::{ @@ -12,6 +11,47 @@ use tokio::{ pub const REJECT_OOP: &[u8; 6] = b"\x04\x04oop\x00"; pub const REJECT_TIMEOUT: &[u8; 10] = b"\x04\x08timeout\x00"; +#[derive(Debug)] +pub enum Error { + TooLittleData { + expected: u8, + got: u8, + }, + Unexpected { + expected: PacketKind, + got: PacketKind, + }, + Io(std::io::Error), + Client(Option), +} + +impl std::error::Error for Error {} +impl Display for Error { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Error::TooLittleData { expected, got } => write!( + f, + "received too little data: expected {expected} bytes but received only {got}" + ), + Error::Unexpected { expected, got } => write!( + f, + "received an unexpected packet: expected {expected:?} but received {got:?}", + ), + Error::Io(inner) => Display::fmt(inner, f), + Error::Client(Some(inner)) => write!(f, "client reported an error: {inner}"), + Error::Client(None) => write!(f, "client reported a malformed error",), + } + } +} + +impl From for Error { + fn from(value: std::io::Error) -> Self { + Self::Io(value) + } +} + +type Result = std::result::Result; + #[repr(u8)] #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum PacketKind { @@ -151,10 +191,7 @@ impl Packet { } #[allow(clippy::missing_errors_doc)] - pub async fn recv_into_cancelation_safe( - &mut self, - stream: &mut ReadHalf<'_>, - ) -> eyre::Result<()> { + pub async fn recv_into_cancelation_safe(&mut self, stream: &mut ReadHalf<'_>) -> Result<()> { // Makes sure all data is available before reading let header_bytes = bytemuck::bytes_of_mut(&mut self.header); stream.peek(header_bytes).await?; @@ -166,7 +203,7 @@ impl Packet { } #[allow(clippy::missing_errors_doc)] - pub async fn recv_into(&mut self, stream: &mut ReadHalf<'_>) -> eyre::Result<()> { + pub async fn recv_into(&mut self, stream: &mut ReadHalf<'_>) -> Result<()> { let header_bytes = bytemuck::bytes_of_mut(&mut self.header); stream.read_exact(header_bytes).await?; @@ -176,10 +213,7 @@ impl Packet { stream.read_exact(&mut self.data).await?; if self.header.kind == PacketKind::Error.raw() { - return Err(eyre!( - "client reported error: {:?}", - self.as_string().unwrap_or("unknown dyn auth error") - )); + return Err(Error::Client(self.as_string().map(ToOwned::to_owned))); } Ok(()) @@ -199,24 +233,26 @@ impl Packet { /// # Errors /// the packet must be a `RemConnect` packet and must contain at least 6 bytes of data - pub fn as_rem_connect(&self) -> eyre::Result { + #[allow(clippy::missing_panics_doc)] + pub fn as_rem_connect(&self) -> Result { if self.kind() != PacketKind::RemConnect { - return Err(eyre!( - "Unexpected Packet: {:?} expected RemConnect", - self.kind() - )); + return Err(Error::Unexpected { + expected: PacketKind::RemConnect, + got: self.kind(), + }); } if self.data.len() < 6 { - return Err(eyre!( - "Too little data for RemConnect. Need at least 6 Bytes got {}", - self.data.len() - )); + #[allow(clippy::cast_possible_truncation)] + return Err(Error::TooLittleData { + expected: 6, + got: self.data.len() as u8, + }); } Ok(RemConnect { - number: u32::from_le_bytes(self.data[..4].try_into()?), - pin: u16::from_le_bytes(self.data[4..6].try_into()?), + number: u32::from_le_bytes(self.data[..4].try_into().unwrap()), + pin: u16::from_le_bytes(self.data[4..6].try_into().unwrap()), }) } }