summaryrefslogtreecommitdiffstats
path: root/src/os/shared.rs
diff options
context:
space:
mode:
authoryossarian <sergiybiluk@gmail.com>2020-03-01 13:17:00 +0100
committerGitHub <noreply@github.com>2020-03-01 13:17:00 +0100
commitc45b3c82bf17c2e8f2a0ae4e9b611139c1d55d79 (patch)
tree9701742c4fb3618dc4f36eaa557c2756a82035e4 /src/os/shared.rs
parent5bd64ddac0fb4b98e71212c4acace065e7fe9daf (diff)
fix(error-handling): add custom error handling (#104)
* Initial * Add errors file * Update * Add error message * Update * Add kind method * Update error kind * Update get_datalink_channel * Update unused var * Initial * Add errors file * Update * Add error message * Update * Add kind method * Update error kind * Update error message * Update error name * Update error messages * Update message * Update * Update error message * format * format2 * update * Update error checking * format * refactor * reduce message * remove unused code * fix lint * wip * add multiline * add handle_errors * update fold * update * clippy * Update * spaces * fix(error-handling): display interface names in errors * style(format): rustfmt Co-authored-by: Aram Drevekenin <aram@poor.dev>
Diffstat (limited to 'src/os/shared.rs')
-rw-r--r--src/os/shared.rs107
1 files changed, 93 insertions, 14 deletions
diff --git a/src/os/shared.rs b/src/os/shared.rs
index c509f91..64d26d5 100644
--- a/src/os/shared.rs
+++ b/src/os/shared.rs
@@ -1,14 +1,14 @@
use ::pnet_bandwhich_fork::datalink::Channel::Ethernet;
use ::pnet_bandwhich_fork::datalink::DataLinkReceiver;
use ::pnet_bandwhich_fork::datalink::{self, Config, NetworkInterface};
-use ::std::io::{self, stdin, Write};
+use ::std::io::{self, stdin, ErrorKind, Write};
use ::termion::event::Event;
use ::termion::input::TermRead;
use ::tokio::runtime::Runtime;
-use ::std::io::ErrorKind;
use ::std::time;
+use crate::os::errors::GetInterfaceErrorKind;
use signal_hook::iterator::Signals;
#[cfg(target_os = "linux")]
@@ -34,17 +34,25 @@ impl Iterator for KeyboardEvents {
fn get_datalink_channel(
interface: &NetworkInterface,
-) -> Result<Box<dyn DataLinkReceiver>, std::io::Error> {
+) -> Result<Box<dyn DataLinkReceiver>, GetInterfaceErrorKind> {
let mut config = Config::default();
config.read_timeout = Some(time::Duration::new(1, 0));
match datalink::channel(interface, config) {
Ok(Ethernet(_tx, rx)) => Ok(rx),
- Ok(_) => Err(std::io::Error::new(
- ErrorKind::Other,
- "Unsupported interface type",
- )),
- Err(e) => Err(e),
+ Ok(_) => Err(GetInterfaceErrorKind::OtherError(format!(
+ "{}: Unsupported interface type",
+ interface.name
+ ))),
+ Err(e) => match e.kind() {
+ ErrorKind::PermissionDenied => Err(GetInterfaceErrorKind::PermissionError(
+ interface.name.to_owned(),
+ )),
+ _ => Err(GetInterfaceErrorKind::OtherError(format!(
+ "{}: {}",
+ &interface.name, e
+ ))),
+ },
}
}
@@ -82,6 +90,79 @@ fn create_write_to_stdout() -> Box<dyn FnMut(String) + Send> {
})
}
+#[derive(Debug)]
+pub struct UserErrors {
+ permission: Option<String>,
+ other: Option<String>,
+}
+
+pub fn collect_errors<'a, I>(network_frames: I) -> String
+where
+ I: Iterator<
+ Item = (
+ &'a NetworkInterface,
+ Result<Box<dyn DataLinkReceiver>, GetInterfaceErrorKind>,
+ ),
+ >,
+{
+ let errors = network_frames.fold(
+ UserErrors {
+ permission: None,
+ other: None,
+ },
+ |acc, (_, elem)| {
+ if let Some(iface_error) = elem.err() {
+ match iface_error {
+ GetInterfaceErrorKind::PermissionError(interface_name) => {
+ if let Some(prev_interface) = acc.permission {
+ return UserErrors {
+ permission: Some(format!("{}, {}", prev_interface, interface_name)),
+ ..acc
+ };
+ } else {
+ return UserErrors {
+ permission: Some(interface_name),
+ ..acc
+ };
+ }
+ }
+ error => {
+ if let Some(prev_errors) = acc.other {
+ return UserErrors {
+ other: Some(format!("{} \n {}", prev_errors, error)),
+ ..acc
+ };
+ } else {
+ return UserErrors {
+ other: Some(format!("{}", error)),
+ ..acc
+ };
+ }
+ }
+ };
+ }
+ acc
+ },
+ );
+ if let Some(interface_name) = errors.permission {
+ if let Some(other_errors) = errors.other {
+ format!(
+ "\n\n{}: {} \nAdditional Errors: \n {}",
+ interface_name,
+ eperm_message(),
+ other_errors
+ )
+ } else {
+ format!("\n\n{}: {}", interface_name, eperm_message())
+ }
+ } else {
+ let other_errors = errors
+ .other
+ .expect("asked to collect errors but found no errors");
+ format!("\n\n {}", other_errors)
+ }
+}
+
pub fn get_input(
interface_name: &Option<String>,
resolve: bool,
@@ -121,13 +202,11 @@ pub fn get_input(
};
if available_network_frames.is_empty() {
- for (_, iface) in network_frames {
- if let Some(iface_error) = iface.err() {
- if let ErrorKind::PermissionDenied = iface_error.kind() {
- failure::bail!(eperm_message())
- }
- }
+ let all_errors = collect_errors(network_frames.clone());
+ if !all_errors.is_empty() {
+ failure::bail!(all_errors);
}
+
failure::bail!("Failed to find any network interface to listen on.");
}