clean up packet errors

This commit is contained in:
soruh 2023-06-24 16:14:11 +02:00
parent eb5e5fd0fa
commit 76502f5e00
2 changed files with 59 additions and 22 deletions

View File

@ -71,6 +71,7 @@ async fn authenticate(
let _ip = dyn_ip_update(&config.dyn_ip_server, number, pin, port).await?; 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")] #[cfg(feature = "debug_server")]
let name = peer_query(&config.dyn_ip_server, number).await?; let name = peer_query(&config.dyn_ip_server, number).await?;

View File

@ -1,7 +1,6 @@
use std::fmt::Debug; use std::fmt::{Debug, Display};
use bytemuck::{Pod, Zeroable}; use bytemuck::{Pod, Zeroable};
use eyre::eyre;
use serde::Serialize; use serde::Serialize;
use smallvec::SmallVec; use smallvec::SmallVec;
use tokio::{ use tokio::{
@ -12,6 +11,47 @@ use tokio::{
pub const REJECT_OOP: &[u8; 6] = b"\x04\x04oop\x00"; pub const REJECT_OOP: &[u8; 6] = b"\x04\x04oop\x00";
pub const REJECT_TIMEOUT: &[u8; 10] = b"\x04\x08timeout\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<String>),
}
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<std::io::Error> for Error {
fn from(value: std::io::Error) -> Self {
Self::Io(value)
}
}
type Result<T> = std::result::Result<T, Error>;
#[repr(u8)] #[repr(u8)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum PacketKind { pub enum PacketKind {
@ -151,10 +191,7 @@ impl Packet {
} }
#[allow(clippy::missing_errors_doc)] #[allow(clippy::missing_errors_doc)]
pub async fn recv_into_cancelation_safe( pub async fn recv_into_cancelation_safe(&mut self, stream: &mut ReadHalf<'_>) -> Result<()> {
&mut self,
stream: &mut ReadHalf<'_>,
) -> eyre::Result<()> {
// Makes sure all data is available before reading // Makes sure all data is available before reading
let header_bytes = bytemuck::bytes_of_mut(&mut self.header); let header_bytes = bytemuck::bytes_of_mut(&mut self.header);
stream.peek(header_bytes).await?; stream.peek(header_bytes).await?;
@ -166,7 +203,7 @@ impl Packet {
} }
#[allow(clippy::missing_errors_doc)] #[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); let header_bytes = bytemuck::bytes_of_mut(&mut self.header);
stream.read_exact(header_bytes).await?; stream.read_exact(header_bytes).await?;
@ -176,10 +213,7 @@ impl Packet {
stream.read_exact(&mut self.data).await?; stream.read_exact(&mut self.data).await?;
if self.header.kind == PacketKind::Error.raw() { if self.header.kind == PacketKind::Error.raw() {
return Err(eyre!( return Err(Error::Client(self.as_string().map(ToOwned::to_owned)));
"client reported error: {:?}",
self.as_string().unwrap_or("unknown dyn auth error")
));
} }
Ok(()) Ok(())
@ -199,24 +233,26 @@ impl Packet {
/// # Errors /// # Errors
/// the packet must be a `RemConnect` packet and must contain at least 6 bytes of data /// the packet must be a `RemConnect` packet and must contain at least 6 bytes of data
pub fn as_rem_connect(&self) -> eyre::Result<RemConnect> { #[allow(clippy::missing_panics_doc)]
pub fn as_rem_connect(&self) -> Result<RemConnect> {
if self.kind() != PacketKind::RemConnect { if self.kind() != PacketKind::RemConnect {
return Err(eyre!( return Err(Error::Unexpected {
"Unexpected Packet: {:?} expected RemConnect", expected: PacketKind::RemConnect,
self.kind() got: self.kind(),
)); });
} }
if self.data.len() < 6 { if self.data.len() < 6 {
return Err(eyre!( #[allow(clippy::cast_possible_truncation)]
"Too little data for RemConnect. Need at least 6 Bytes got {}", return Err(Error::TooLittleData {
self.data.len() expected: 6,
)); got: self.data.len() as u8,
});
} }
Ok(RemConnect { Ok(RemConnect {
number: u32::from_le_bytes(self.data[..4].try_into()?), number: u32::from_le_bytes(self.data[..4].try_into().unwrap()),
pin: u16::from_le_bytes(self.data[4..6].try_into()?), pin: u16::from_le_bytes(self.data[4..6].try_into().unwrap()),
}) })
} }
} }