Skip to content

Commit

Permalink
feat: add context information to IoError (#153)
Browse files Browse the repository at this point in the history
  • Loading branch information
fujiapple852 committed May 15, 2023
1 parent e050424 commit 108dbbc
Show file tree
Hide file tree
Showing 6 changed files with 312 additions and 129 deletions.
103 changes: 102 additions & 1 deletion src/tracing/error.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
use crate::tracing::util::RequiredError;
use std::fmt::{Display, Formatter};
use std::io;
use std::io::ErrorKind;
use std::net::{IpAddr, SocketAddr};
use thiserror::Error;

/// A tracer error result.
pub type TraceResult<T> = Result<T, TracerError>;

/// A tracer error.
#[derive(Error, Debug)]
pub enum TracerError {
#[error("invalid packet size: {0}")]
Expand All @@ -16,11 +20,108 @@ pub enum TracerError {
#[error("missing required field: {0}")]
Required(#[from] RequiredError),
#[error("IO error: {0}")]
IoError(#[from] io::Error),
IoError(#[from] IoError),
#[error("insufficient buffer capacity")]
InsufficientCapacity,
#[error("address not available: {0}")]
AddressNotAvailable(SocketAddr),
#[error("invalid source IP address: {0}")]
InvalidSourceAddr(IpAddr),
}

/// Custom IO error result.
pub type IoResult<T> = Result<T, IoError>;

/// Custom IO error.
#[derive(Error, Debug)]
pub enum IoError {
#[error("Bind error for {1}: {0}")]
Bind(io::Error, SocketAddr),
#[error("Connect error for {1}: {0}")]
Connect(io::Error, SocketAddr),
#[error("Sendto error for {1}: {0}")]
SendTo(io::Error, SocketAddr),
#[error("Failed to {0}: {1}")]
Other(io::Error, IoOperation),
}

impl IoError {
pub fn raw_os_error(&self) -> Option<i32> {
match self {
Self::Bind(e, _) | Self::Connect(e, _) | Self::SendTo(e, _) | Self::Other(e, _) => {
e.raw_os_error()
}
}
}
pub fn kind(&self) -> ErrorKind {
match self {
Self::Bind(e, _) | Self::Connect(e, _) | Self::SendTo(e, _) | Self::Other(e, _) => {
e.kind()
}
}
}
}

/// Io operation.
#[derive(Debug)]
pub enum IoOperation {
NewSocket,
SetNonBlocking,
Select,
RecvFrom,
Read,
Shutdown,
LocalAddr,
PeerAddr,
TakeError,
SetTos,
SetTtl,
SetReusePort,
SetHeaderIncluded,
SetUnicastHopsV6,
Close,
WSACreateEvent,
WSARecvFrom,
WSAEventSelect,
WSAResetEvent,
WSAGetOverlappedResult,
WaitForSingleObject,
SetTcpFailConnectOnIcmpError,
TcpIcmpErrorInfo,
ConvertSocketAddress,
SioRoutingInterfaceQuery,
Startup,
}

impl Display for IoOperation {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
Self::NewSocket => write!(f, "create new socket"),
Self::SetNonBlocking => write!(f, "set non-blocking"),
Self::Select => write!(f, "select"),
Self::RecvFrom => write!(f, "recv from"),
Self::Read => write!(f, "read"),
Self::Shutdown => write!(f, "shutdown"),
Self::LocalAddr => write!(f, "local addr"),
Self::PeerAddr => write!(f, "peer addr"),
Self::TakeError => write!(f, "take error"),
Self::SetTos => write!(f, "set TOS"),
Self::SetTtl => write!(f, "set TTL"),
Self::SetReusePort => write!(f, "set reuse port"),
Self::SetHeaderIncluded => write!(f, "set header included"),
Self::SetUnicastHopsV6 => write!(f, "set unicast hops v6"),
Self::Close => write!(f, "close"),
Self::WSACreateEvent => write!(f, "WSA create event"),
Self::WSARecvFrom => write!(f, "WSA recv from"),
Self::WSAEventSelect => write!(f, "WSA event select"),
Self::WSAResetEvent => write!(f, "WSA reset event"),
Self::WSAGetOverlappedResult => write!(f, "WSA get overlapped result"),
Self::WaitForSingleObject => write!(f, "wait for single object"),
Self::SetTcpFailConnectOnIcmpError => write!(f, "set TCP failed connect on ICMP error"),
Self::TcpIcmpErrorInfo => write!(f, "get TCP ICMP error info"),
Self::ConvertSocketAddress => write!(f, "convert socket address"),
Self::SioRoutingInterfaceQuery => write!(f, "SIO routing interface query"),
Self::Startup => write!(f, "startup"),
}
}
}
4 changes: 2 additions & 2 deletions src/tracing/net/ipv4.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::tracing::error::TracerError::AddressNotAvailable;
use crate::tracing::error::{TraceResult, TracerError};
use crate::tracing::error::{IoResult, TraceResult, TracerError};
use crate::tracing::net::channel::MAX_PACKET_SIZE;
use crate::tracing::net::platform;
use crate::tracing::net::platform::Socket;
Expand Down Expand Up @@ -152,7 +152,7 @@ pub fn dispatch_tcp_probe(
dest_addr: Ipv4Addr,
tos: TypeOfService,
) -> TraceResult<Socket> {
fn process_result(addr: SocketAddr, res: std::io::Result<()>) -> TraceResult<()> {
fn process_result(addr: SocketAddr, res: IoResult<()>) -> TraceResult<()> {
match res {
Ok(_) => Ok(()),
Err(err) => {
Expand Down
6 changes: 2 additions & 4 deletions src/tracing/net/ipv6.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::tracing::error::TracerError::AddressNotAvailable;
use crate::tracing::error::{TraceResult, TracerError};
use crate::tracing::error::{IoResult, TraceResult, TracerError};
use crate::tracing::net::channel::MAX_PACKET_SIZE;
use crate::tracing::net::platform;
use crate::tracing::net::platform::Socket;
Expand Down Expand Up @@ -104,7 +104,7 @@ pub fn dispatch_tcp_probe(
src_addr: Ipv6Addr,
dest_addr: Ipv6Addr,
) -> TraceResult<Socket> {
fn process_result(addr: SocketAddr, res: std::io::Result<()>) -> TraceResult<()> {
fn process_result(addr: SocketAddr, res: IoResult<()>) -> TraceResult<()> {
match res {
Ok(_) => Ok(()),
Err(err) => {
Expand Down Expand Up @@ -143,12 +143,10 @@ pub fn recv_icmp_probe(
match recv_socket.recv_from(&mut buf) {
Ok((_bytes_read, addr)) => {
let icmp_v6 = IcmpPacket::new_view(&buf).req()?;

let src_addr = match addr.as_ref().req()? {
SocketAddr::V6(addr) => addr.ip(),
SocketAddr::V4(_) => panic!(),
};

Ok(extract_probe_resp(protocol, &icmp_v6, *src_addr)?)
}
Err(err) => match err.kind() {
Expand Down
Loading

0 comments on commit 108dbbc

Please sign in to comment.