Skip to content

Commit

Permalink
discovery update
Browse files Browse the repository at this point in the history
- add switching modes (normal / input)
- add discovery component for scanning local networks
- add key handling logic
  • Loading branch information
Chleba committed Dec 14, 2023
1 parent ea06c88 commit 2888e82
Show file tree
Hide file tree
Showing 11 changed files with 139 additions and 30 deletions.
8 changes: 6 additions & 2 deletions .config/config.json5
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
{
"keybindings": {
"Home": {
"Normal": {
"<q>": "Quit", // Quit the application
"<Ctrl-d>": "Quit", // Another way to quit
"<Ctrl-c>": "Quit", // Yet another way to quit
"<Ctrl-z>": "Suspend" // Suspend the application
"<Ctrl-z>": "Suspend", // Suspend the application
"<i>": "InputMode"
},
"Input": {
"<Esc>": "NormalMode"
}
}
}
2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ repository = "https://github.com/Chleba/netscanner"
[dependencies]
better-panic = "0.3.0"
chrono = "0.4.31"
cidr = "0.2.2"
clap = { version = "4.4.5", features = ["derive", "cargo", "wrap_help", "unicode", "string", "unstable-styles"] }
color-eyre = "0.6.2"
config = "0.13.3"
Expand All @@ -27,6 +28,7 @@ json5 = "0.4.1"
lazy_static = "1.4.0"
libc = "0.2.148"
log = "0.4.20"
ping = "0.5.1"
pnet = "0.34.0"
pretty_assertions = "1.4.0"
ratatui = { version = "0.24.0", features = ["serde", "macros"] }
Expand Down
16 changes: 16 additions & 0 deletions examples/cidr.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
use cidr::Ipv4Cidr;
use std::net::Ipv4Addr;

fn main() {
let cidr_range = "192.168.1.0/24"; // Replace with your CIDR range
match cidr_range.parse::<Ipv4Cidr>() {
Ok(ip_cidr) => {
for ip in ip_cidr.iter() {
println!("IP Address: {}", ip);
}
}
Err(e) => {
eprintln!("Error parsing CIDR range: {}", e);
}
}
}
8 changes: 7 additions & 1 deletion src/action.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ pub enum Action {

// -- custom actions
Scan(Vec<WifiInfo>),
Mode(Mode),
ModeChange(Mode),
}

impl<'de> Deserialize<'de> for Action {
Expand All @@ -46,6 +46,12 @@ impl<'de> Deserialize<'de> for Action {
E: de::Error,
{
match value {
// -- custom actions
// "InputMode" => Ok(Action::InputMode),
"InputMode" => Ok(Action::ModeChange(Mode::Input)),
"NormalMode" => Ok(Action::ModeChange(Mode::Normal)),

// -- default actions
"Tick" => Ok(Action::Tick),
"Render" => Ok(Action::Render),
"Suspend" => Ok(Action::Suspend),
Expand Down
6 changes: 5 additions & 1 deletion src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ impl App {
let wifi_chart = WifiChart::default();
let discovery = Discovery::default();
let config = Config::new()?;
let mode = Mode::Home;
let mode = Mode::Normal;
Ok(Self {
tick_rate: 1.0,
frame_rate,
Expand Down Expand Up @@ -120,6 +120,10 @@ impl App {
log::debug!("{action:?}");
}
match action {
Action::ModeChange(mode) => {
self.mode = mode;
},

Action::Tick => {
self.last_tick_key_events.drain(..);
}
Expand Down
105 changes: 92 additions & 13 deletions src/components/discovery.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
use chrono::Timelike;
use cidr::Ipv4Cidr;
use color_eyre::eyre::Result;
use itertools::Position;
use pnet::datalink::{self, NetworkInterface};
use ratatui::{prelude::*, widgets::*};
use std::collections::HashMap;
use std::net::Ipv4Addr;
use std::process::{Command, Output};
use std::time::Instant;
use tokio::sync::mpsc::UnboundedSender;

use super::Component;
use crate::{action::Action, mode::Mode, tui::Frame};
use tui_input::backend::crossterm::EventHandler;
use tui_input::Input;
use crossterm::event::{KeyEvent, KeyCode};

struct ScannedIp {
ip: String,
Expand All @@ -22,8 +26,12 @@ struct ScannedIp {
pub struct Discovery {
action_tx: Option<UnboundedSender<Action>>,
last_update_time: Instant,
scanning: bool,
scanned_ips: Vec<ScannedIp>,
ips_to_scan: Vec<Ipv4Addr>,
input: Input,
cidr: Option<Ipv4Cidr>,
mode: Mode,
}

impl Default for Discovery {
Expand All @@ -37,12 +45,28 @@ impl Discovery {
Self {
action_tx: None,
last_update_time: Instant::now(),
scanning: false,
scanned_ips: Vec::new(),
ips_to_scan: Vec::new(),
input: Input::default(),
cidr: None,
mode: Mode::Normal,
}
}

fn app_tick(&mut self) -> Result<()> {
if self.cidr == None {
let cidr_range = "192.168.1.0/24"; // Replace with your CIDR range
match cidr_range.parse::<Ipv4Cidr>() {
Ok(ip_cidr) => {
self.cidr = Some(ip_cidr);
}
Err(e) => {
// eprintln!("Error parsing CIDR range: {}", e);
}
}
}

Ok(())
}

Expand All @@ -51,6 +75,23 @@ impl Discovery {
.style(Style::default().fg(Color::Yellow))
.bottom_margin(1);
let mut rows = Vec::new();

if let Some(cidr) = self.cidr {
for ip in cidr.iter() {
let ip = ip.address().to_string();
rows.push(Row::new(vec![
// Cell::from(ip.addr().to_string()),
Cell::from(Span::styled(
format!("{ip:<2}"),
Style::default().fg(Color::Blue),
)),
Cell::from("maslo"),
Cell::from("chleba"),
Cell::from("rohlik"),
]));
}
};

// for w in &self.interfaces {
// let name = w.name.clone();
// let mac = w.mac.unwrap().to_string();
Expand Down Expand Up @@ -105,7 +146,7 @@ impl Discovery {
.padding(Padding::new(1, 0, 1, 0)),
)
.widths(&[
Constraint::Length(8),
Constraint::Length(16),
Constraint::Length(18),
Constraint::Length(14),
Constraint::Length(25),
Expand All @@ -114,19 +155,18 @@ impl Discovery {
table
}

fn make_input(&mut self) -> Paragraph {
let scroll = self.input.visual_scroll(40);
fn make_input(&mut self, scroll: usize) -> Paragraph {
// let scroll = self.input.visual_scroll(40);
let input = Paragraph::new(self.input.value())
// .style(match self.mode {
// Mode::Insert => Style::default().fg(Color::Yellow),
// _ => Style::default(),
// })
.style(Style::default().fg(Color::Yellow))
.scroll((0, scroll as u16))
.block(
Block::default()
.borders(Borders::ALL)
.border_style(Style::default().fg(Color::Rgb(100, 100, 100)))
.border_style(match self.mode {
Mode::Input => Style::default().fg(Color::Green),
Mode::Normal => Style::default().fg(Color::Rgb(100, 100, 100)),
})
.title(Line::from(vec![
Span::raw("|"),
Span::styled(
Expand Down Expand Up @@ -154,14 +194,41 @@ impl Component for Discovery {
Ok(())
}

fn handle_key_events(&mut self, key: KeyEvent) -> Result<Option<Action>> {
let action = match self.mode {
Mode::Normal => return Ok(None),
Mode::Input=> match key.code {
KeyCode::Enter => {
if let Some(sender) = &self.action_tx {
// if let Err(e) =
// // sender.send(Action::CompleteInput(self.input.value().to_string()))
// {
// error!("Failed to send action: {:?}", e);
// }
}
Action::ModeChange(Mode::Normal)
}
_ => {
self.input.handle_event(&crossterm::event::Event::Key(key));
return Ok(None)
}
},
};
Ok(Some(action))
}

fn update(&mut self, action: Action) -> Result<Option<Action>> {
if let Action::Tick = action {
self.app_tick()?
}
// -- custom actions
// if let Action::Scan(nets) = action {
// self.parse_char_data(&nets);
// }
if let Action::ModeChange(mode) = action {
if mode == Mode::Input {
self.input.reset();
}
self.mode = mode;
}

Ok(None)
}

Expand All @@ -174,13 +241,25 @@ impl Component for Discovery {
table_rect.y += 1;
table_rect.height -= 1;

let input_rect = Rect::new(table_rect.width-41, table_rect.y+1, 40, 3);
let input_rect = Rect::new(table_rect.width - 41, table_rect.y + 1, 40, 3);

let block = self.make_ui();
f.render_widget(block, table_rect);

let block = self.make_input();

let scroll = self.input.visual_scroll(40);
let block = self.make_input(scroll);
f.render_widget(block, input_rect);
// -- cursor
match self.mode {
Mode::Input => {
f.set_cursor(
input_rect.x + ((self.input.visual_cursor()).max(scroll) - scroll) as u16 + 1,
input_rect.y + 1,
);
}
Mode::Normal => {}
}

Ok(())
}
Expand Down
7 changes: 4 additions & 3 deletions src/components/home.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,22 +10,20 @@ use super::{Component, Frame};
use crate::{
action::Action,
config::{Config, KeyBindings},
mode::Mode,
// mode::Mode,
};

#[derive(Default)]
pub struct Home {
command_tx: Option<UnboundedSender<Action>>,
config: Config,
mode: Mode,
}

impl Home {
pub fn new() -> Self {
Self {
command_tx: None,
config: Config::default(),
mode: Mode::Home,
}
}
}
Expand All @@ -44,6 +42,9 @@ impl Component for Home {
fn update(&mut self, action: Action) -> Result<Option<Action>> {
match action {
Action::Tick => {}
// Action::Scan(nets) => {
// self.parse_char_data(&nets);
// }
_ => {}
}
Ok(None)
Expand Down
4 changes: 2 additions & 2 deletions src/components/interfaces.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ pub struct Interfaces {
pub action_tx: Option<UnboundedSender<Action>>,
pub interfaces: Vec<NetworkInterface>,
pub last_update_time: Instant,
pub mode: Mode,
// pub mode: Mode,
}

impl Default for Interfaces {
Expand All @@ -27,7 +27,7 @@ impl Interfaces {
action_tx: None,
interfaces: Vec::new(),
last_update_time: Instant::now(),
mode: Mode::Interfaces,
// mode: Mode::Interfaces,
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/components/wifi_chart.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use crate::components::wifi_scan::WifiInfo;
use chrono::Timelike;

use super::Component;
use crate::{action::Action, mode::Mode, tui::Frame};
use crate::{action::Action, tui::Frame};

#[derive(Debug)]
pub struct WifiDataset {
Expand Down
4 changes: 2 additions & 2 deletions src/components/wifi_scan.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ pub struct WifiScan {
pub scan_start_time: Instant,
pub wifis: Vec<WifiInfo>,
pub signal_tick: [f64; 2],
pub mode: Mode,
// pub mode: Mode,
}

impl Default for WifiScan {
Expand Down Expand Up @@ -72,7 +72,7 @@ impl WifiScan {
wifis: Vec::new(),
action_tx: None,
signal_tick: [0.0, 40.0],
mode: Mode::Networks,
// mode: Mode::Networks,
}
}

Expand Down
7 changes: 2 additions & 5 deletions src/mode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,7 @@ use ratatui::style::Color;
#[derive(Default, Debug, Copy, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum Mode {
#[default]
Home,
Networks,
Interfaces,
Normal,
Input,
}

pub const MODE_ACTIVE_COLOR: Color = Color::Green;
pub const MODE_NORMAL_COLOR: Color = Color::Gray;

0 comments on commit 2888e82

Please sign in to comment.