use std::{
any::Any,
num::ParseIntError,
sync::{
MutexGuard, PoisonError,
mpsc::{RecvError, SendError},
},
};
use thiserror::Error;
use crate::{
packet::{
arp_packet::ArpPacketBuilderError,
heartbeat_packet::HeartbeatPacketBuilderError,
rst_packet::RstPacketBuilderError, syn_packet::SynPacketBuilderError,
},
scanners::{
ScanMessage, arp_scanner::ARPScannerBuilderError,
heartbeat::HeartBeatBuilderError, syn_scanner::SYNScannerBuilderError,
},
wire::{Reader, Sender},
};
#[derive(Error, Debug)]
pub enum RLanLibError {
#[error("oui: {_0}")]
Oui(String),
#[error("wire error: {_0}")]
Wire(String),
#[error("failed to send notification message: {:#?}", _0)]
NotifierSendError(#[from] SendError<Box<ScanMessage>>),
#[error("failed to get lock on packet reader: {_0}")]
PacketReaderLock(String),
#[error("failed to get lock on packet sender: {_0}")]
PacketSenderLock(String),
#[error("thread error: {_0}")]
ThreadError(String),
#[error("failed to receive message from channel: {:#?}", _0)]
ChannelReceive(#[from] RecvError),
#[error("failed to build ARP packet: {_0}")]
ArpPacketBuild(#[from] ArpPacketBuilderError),
#[error("failed to build arp scanner: {_0}")]
ArpScannerBuild(#[from] ARPScannerBuilderError),
#[error("failed to build syn scanner: {_0}")]
SynScannerBuild(#[from] SYNScannerBuilderError),
#[error("failed to build heartbeat: {_0}")]
HeartBeatBuild(#[from] HeartBeatBuilderError),
#[error("failed to build RST packet: {_0}")]
RstPacketBuild(#[from] RstPacketBuilderError),
#[error("failed to build SYN packet: {_0}")]
SynPacketBuild(#[from] SynPacketBuilderError),
#[error("failed to build heartbeat packet: {_0}")]
HeartbeatPacketBuild(#[from] HeartbeatPacketBuilderError),
#[error("network interface error: {_0}")]
NetworkInterface(String),
#[error("scanning error: {error} - ip: {:#?}, port: {:#?}", ip, port)]
Scan {
error: String,
ip: Option<String>,
port: Option<String>,
},
}
impl From<Box<dyn Any + Send>> for RLanLibError {
fn from(value: Box<dyn Any + Send>) -> Self {
if let Some(s) = value.downcast_ref::<&'static str>() {
Self::ThreadError(format!("Thread panicked with: {}", s))
} else if let Some(s) = value.downcast_ref::<String>() {
Self::ThreadError(format!("Thread panicked with: {}", s))
} else {
Self::ThreadError("Thread panicked with an unknown type".into())
}
}
}
impl<'a> From<PoisonError<MutexGuard<'a, dyn Reader + 'static>>>
for RLanLibError
{
fn from(value: PoisonError<MutexGuard<'a, dyn Reader + 'static>>) -> Self {
Self::PacketReaderLock(value.to_string())
}
}
impl<'a> From<PoisonError<MutexGuard<'a, dyn Sender + 'static>>>
for RLanLibError
{
fn from(value: PoisonError<MutexGuard<'a, dyn Sender + 'static>>) -> Self {
Self::PacketSenderLock(value.to_string())
}
}
impl RLanLibError {
pub fn from_net_addr_parse_error(
ip: &str,
error: std::net::AddrParseError,
) -> Self {
Self::Scan {
error: error.to_string(),
ip: Some(ip.to_string()),
port: None,
}
}
pub fn from_ipnet_addr_parse_error(
ip: &str,
error: ipnet::AddrParseError,
) -> Self {
Self::Scan {
error: error.to_string(),
ip: Some(ip.to_string()),
port: None,
}
}
pub fn from_port_parse_int_err(port: &str, error: ParseIntError) -> Self {
Self::Scan {
error: error.to_string(),
ip: None,
port: Some(port.to_string()),
}
}
pub fn from_channel_send_error(e: SendError<ScanMessage>) -> Self {
RLanLibError::NotifierSendError(SendError(Box::from(e.0)))
}
}
unsafe impl Send for RLanLibError {}
unsafe impl Sync for RLanLibError {}
pub type Result<T> = std::result::Result<T, RLanLibError>;