Skip to main content

r_lanlib/
error.rs

1//! Custom Error and Result types for this library
2
3use std::{
4    any::Any,
5    num::ParseIntError,
6    sync::{
7        MutexGuard, PoisonError,
8        mpsc::{RecvError, SendError},
9    },
10};
11use thiserror::Error;
12
13use crate::{
14    packet::{
15        arp_packet::ArpPacketBuilderError,
16        heartbeat_packet::HeartbeatPacketBuilderError,
17        rst_packet::RstPacketBuilderError, syn_packet::SynPacketBuilderError,
18    },
19    scanners::{
20        ScanMessage, arp_scanner::ARPScannerBuilderError,
21        heartbeat::HeartBeatBuilderError, syn_scanner::SYNScannerBuilderError,
22    },
23    wire::{Reader, Sender},
24};
25
26/// Custom Error type for this library
27#[derive(Error, Debug)]
28pub enum RLanLibError {
29    /// Error coming directly off the wire
30    #[error("wire error: {_0}")]
31    Wire(String),
32
33    /// Errors resulting from events channel
34    #[error("failed to send notification message: {:#?}", _0)]
35    NotifierSendError(#[from] SendError<Box<ScanMessage>>),
36
37    /// Error obtaining lock on packet reader
38    #[error("failed to get lock on packet reader: {_0}")]
39    PacketReaderLock(String),
40
41    /// Error obtaining lock on packet sender
42    #[error("failed to get lock on packet sender: {_0}")]
43    PacketSenderLock(String),
44
45    /// Generic thread error
46    #[error("thread error: {_0}")]
47    ThreadError(String),
48
49    /// Errors when consuming messages from channels
50    #[error("failed to receive message from channel: {:#?}", _0)]
51    ChannelReceive(#[from] RecvError),
52
53    /// Error generated during ARP packet construction
54    #[error("failed to build ARP packet: {_0}")]
55    ArpPacketBuild(#[from] ArpPacketBuilderError),
56
57    /// Error resulting from failure to build ARP scanner
58    #[error("failed to build arp scanner: {_0}")]
59    ArpScannerBuild(#[from] ARPScannerBuilderError),
60
61    /// Error resulting from failure to build SYN scanner
62    #[error("failed to build syn scanner: {_0}")]
63    SynScannerBuild(#[from] SYNScannerBuilderError),
64
65    /// Error resulting from failure to build Heartbeat
66    #[error("failed to build heartbeat: {_0}")]
67    HeartBeatBuild(#[from] HeartBeatBuilderError),
68
69    /// Error generated during RST packet construction
70    #[error("failed to build RST packet: {_0}")]
71    RstPacketBuild(#[from] RstPacketBuilderError),
72
73    /// Error generated during SYN packet construction
74    #[error("failed to build SYN packet: {_0}")]
75    SynPacketBuild(#[from] SynPacketBuilderError),
76
77    /// Error generated during heartbeat packet construction
78    #[error("failed to build heartbeat packet: {_0}")]
79    HeartbeatPacketBuild(#[from] HeartbeatPacketBuilderError),
80
81    /// Errors generated accessing device interfaces
82    #[error("network interface error: {_0}")]
83    NetworkInterface(String),
84
85    /// Wrapping errors related to scanning
86    #[error("scanning error: {error} - ip: {:#?}, port: {:#?}", ip, port)]
87    Scan {
88        /// The error message encountered
89        error: String,
90        /// The associated IP address being scanned
91        ip: Option<String>,
92        /// The associated port being scanned
93        port: Option<String>,
94    },
95}
96
97impl From<Box<dyn Any + Send>> for RLanLibError {
98    fn from(value: Box<dyn Any + Send>) -> Self {
99        if let Some(s) = value.downcast_ref::<&'static str>() {
100            Self::ThreadError(format!("Thread panicked with: {}", s))
101        } else if let Some(s) = value.downcast_ref::<String>() {
102            Self::ThreadError(format!("Thread panicked with: {}", s))
103        } else {
104            Self::ThreadError("Thread panicked with an unknown type".into())
105        }
106    }
107}
108
109impl<'a> From<PoisonError<MutexGuard<'a, dyn Reader + 'static>>>
110    for RLanLibError
111{
112    fn from(value: PoisonError<MutexGuard<'a, dyn Reader + 'static>>) -> Self {
113        Self::PacketReaderLock(value.to_string())
114    }
115}
116
117impl<'a> From<PoisonError<MutexGuard<'a, dyn Sender + 'static>>>
118    for RLanLibError
119{
120    fn from(value: PoisonError<MutexGuard<'a, dyn Sender + 'static>>) -> Self {
121        Self::PacketSenderLock(value.to_string())
122    }
123}
124
125impl RLanLibError {
126    /// Converter for std::net::AddrParseError
127    pub fn from_net_addr_parse_error(
128        ip: &str,
129        error: std::net::AddrParseError,
130    ) -> Self {
131        Self::Scan {
132            error: error.to_string(),
133            ip: Some(ip.to_string()),
134            port: None,
135        }
136    }
137
138    /// Converter for ipnet::AddrParseError
139    pub fn from_ipnet_addr_parse_error(
140        ip: &str,
141        error: ipnet::AddrParseError,
142    ) -> Self {
143        Self::Scan {
144            error: error.to_string(),
145            ip: Some(ip.to_string()),
146            port: None,
147        }
148    }
149
150    /// Converter for ParseIntError
151    pub fn from_port_parse_int_err(port: &str, error: ParseIntError) -> Self {
152        Self::Scan {
153            error: error.to_string(),
154            ip: None,
155            port: Some(port.to_string()),
156        }
157    }
158
159    /// Converter for channel send errors
160    pub fn from_channel_send_error(e: SendError<ScanMessage>) -> Self {
161        RLanLibError::NotifierSendError(SendError(Box::from(e.0)))
162    }
163}
164
165unsafe impl Send for RLanLibError {}
166unsafe impl Sync for RLanLibError {}
167
168/// Custom Result type for this library. All Errors exposed by this library
169/// will be returned as [`RLanLibError`]
170pub type Result<T> = std::result::Result<T, RLanLibError>;