1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
|
use ::pnet::datalink::Channel::Ethernet;
use ::pnet::datalink::DataLinkReceiver;
use ::pnet::datalink::{self, Config, NetworkInterface};
use ::std::io::{self, stdin, Write};
use ::termion::event::Event;
use ::termion::input::TermRead;
use ::std::time;
use signal_hook::iterator::Signals;
#[cfg(target_os = "linux")]
use crate::os::linux::get_open_sockets;
#[cfg(target_os = "macos")]
use crate::os::macos::get_open_sockets;
use crate::{network::dns, OsInputOutput};
pub type OnSigWinch = dyn Fn(Box<dyn Fn()>) + Send;
pub type SigCleanup = dyn Fn() + Send;
pub struct KeyboardEvents;
impl Iterator for KeyboardEvents {
type Item = Event;
fn next(&mut self) -> Option<Event> {
match stdin().events().next() {
Some(Ok(ev)) => Some(ev),
_ => None,
}
}
}
fn get_datalink_channel(
interface: &NetworkInterface,
) -> Result<Box<dyn DataLinkReceiver>, failure::Error> {
let mut config = Config::default();
config.read_timeout = Some(time::Duration::new(0, 1));
match datalink::channel(interface, config) {
Ok(Ethernet(_tx, rx)) => Ok(rx),
Ok(_) => failure::bail!("Unknown interface type"),
Err(e) => failure::bail!("Failed to listen to network interface: {}", e),
}
}
fn get_interface(interface_name: &str) -> Option<NetworkInterface> {
datalink::interfaces()
.into_iter()
.find(|iface| iface.name == interface_name)
}
fn sigwinch() -> (Box<OnSigWinch>, Box<SigCleanup>) {
let signals = Signals::new(&[signal_hook::SIGWINCH]).unwrap();
let on_winch = {
let signals = signals.clone();
move |cb: Box<dyn Fn()>| {
for signal in signals.forever() {
match signal {
signal_hook::SIGWINCH => cb(),
_ => unreachable!(),
}
}
}
};
let cleanup = move || {
signals.close();
};
(Box::new(on_winch), Box::new(cleanup))
}
fn create_write_to_stdout() -> Box<dyn FnMut(String) + Send> {
Box::new({
let mut stdout = io::stdout();
move |output: String| {
writeln!(stdout, "{}", output).unwrap();
}
})
}
pub fn get_input(interface_name: &str, resolve: bool) -> Result<OsInputOutput, failure::Error> {
let keyboard_events = Box::new(KeyboardEvents);
let network_interface = match get_interface(interface_name) {
Some(interface) => interface,
None => {
failure::bail!("Cannot find interface {}", interface_name);
}
};
let network_frames = get_datalink_channel(&network_interface)?;
let write_to_stdout = create_write_to_stdout();
let (on_winch, cleanup) = sigwinch();
let dns_client = if resolve {
let (resolver, background) = dns::Resolver::new()?;
let dns_client = dns::Client::new(resolver, background)?;
Some(dns_client)
} else {
None
};
Ok(OsInputOutput {
network_interface,
network_frames,
get_open_sockets,
keyboard_events,
dns_client,
on_winch,
cleanup,
write_to_stdout,
})
}
|