Skip to content

Commit

Permalink
Command line interface change to flags
Browse files Browse the repository at this point in the history
  • Loading branch information
damian-tworek committed Aug 12, 2023
1 parent 9b64e17 commit af6100f
Show file tree
Hide file tree
Showing 7 changed files with 224 additions and 90 deletions.
76 changes: 74 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,5 @@ rtp = "0.6.8"
rtcp = "0.7.2"
webrtc-util = "0.7.0"
rfd = "0.11.3"

clap = "2.33"
# not using workspaces, as the crates use different targets
1 change: 0 additions & 1 deletion src/command_line_interface.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
mod device_selector;
mod file_selector;
pub mod start_interface;
44 changes: 15 additions & 29 deletions src/command_line_interface/device_selector.rs
Original file line number Diff line number Diff line change
@@ -1,36 +1,23 @@
use pcap::{ConnectionStatus, Device, IfFlags};
use std::io::stdin;
use std::net::IpAddr;
use std::thread::sleep;
use std::time::Duration;

pub(crate) fn select_device() -> String {
loop {
list_devices();
println!("Enter the name of the chosen device:");
let mut chosen_name = String::new();
stdin()
.read_line(&mut chosen_name)
.expect("Failed to read line");
let chosen_name = chosen_name.trim().to_string();

if Device::list()
.expect("Error listing devices")
.iter()
.any(|dev| dev.name == chosen_name)
{
return chosen_name;
} else {
println!("\nError: Invalid device name. Please choose a valid device.\n");
sleep(Duration::new(1, 0))
}
}
}

fn list_devices() {
pub(crate) fn list_devices(flags: Vec<String>) {
println!("Available network devices:");
let devices = Device::list().expect("Error listing devices");
for device in devices {
let formatted_flags = format_flags(device.flags.if_flags);
let mut should_print = true;
for flag_name in &flags {
if !formatted_flags.contains(flag_name) {
should_print = false;
}
}
if formatted_flags.eq("N/A") && !flags.is_empty() {
should_print = false
}
if !should_print {
continue;
}
println!("Name: {}", device.name);
println!("Description: {}", device.desc.unwrap_or("N/A".to_string()));
println!(
Expand All @@ -50,8 +37,7 @@ fn list_devices() {
);
println!(" Destination: {}\n", format_optional_ip(&address.dst_addr));
}

println!("Flags: {}", format_flags(device.flags.if_flags));
println!("Flags: {}", formatted_flags);
println!(
"Connection status: {}",
format_connection_status(device.flags.connection_status)
Expand Down
13 changes: 0 additions & 13 deletions src/command_line_interface/file_selector.rs

This file was deleted.

142 changes: 113 additions & 29 deletions src/command_line_interface/start_interface.rs
Original file line number Diff line number Diff line change
@@ -1,41 +1,125 @@
use crate::command_line_interface::device_selector::select_device;
use crate::command_line_interface::file_selector::show_pick_file_dialog;
use crate::command_line_interface::device_selector::list_devices;
use crate::command_line_interface::start_interface::Action::{AnalyzeFile, CapturePackets};
use std::io::stdin;
use clap::{App, Arg, ArgMatches, SubCommand};
use std::net::SocketAddr;
use std::process::exit;

pub enum Action {
CapturePackets(String),
AnalyzeFile(String),
CapturePackets(String, SocketAddr),
AnalyzeFile(String, SocketAddr),
}

pub fn command_line_interface() -> Action {
let selected_action;
loop {
println!("Welcome to the rtpeeker!");
println!("Please choose an option:");
println!("A) Capture packets from a network interface");
println!("B) Analyze packets from a file");

let choice = read_line();

if choice == "A" {
let device = select_device();
selected_action = CapturePackets(device);
break;
} else if choice == "B" {
let path = show_pick_file_dialog();
selected_action = AnalyzeFile(path);
break;
let args = get_args();

if let Some(sub_args) = args.subcommand_matches("list") {
let mut flags = Vec::new();

if sub_args.is_present("up") {
flags.push("UP".to_string());
}

if sub_args.is_present("running") {
flags.push("RUNNING".to_string());
}

if sub_args.is_present("loopback") {
flags.push("LOOPBACK".to_string());
}

if sub_args.is_present("wireless") {
flags.push("WIRELESS".to_string());
}
list_devices(flags);
exit(0);
}

if let Some(interface) = args.value_of("interface") {
let socket = args.value_of("socket").unwrap_or("");

if let Ok(socket_addr) = socket.parse() {
return CapturePackets(interface.to_string(), socket_addr);
} else {
print_parsing_address_error();
}
} else if let Some(file) = args.value_of("file") {
let socket = args.value_of("socket").unwrap_or("");

if let Ok(socket_addr) = socket.parse() {
return AnalyzeFile(file.to_string(), socket_addr);
} else {
println!("Invalid choice.\n");
print_parsing_address_error();
}
} else {
println!("Please provide either an interface or a file. Type --help");
}
selected_action
exit(1)
}

fn print_parsing_address_error() {
println!("Error parsing address! Expected 168.192.1.3:422 or [2001:db8::1]:8080")
}

fn read_line() -> String {
let mut choice = String::new();
stdin().read_line(&mut choice).expect("Failed to read line");
let choice = choice.trim().to_uppercase();
choice
fn get_args() -> ArgMatches<'static> {
App::new("rtpeeker")
.version("1.0")
.author("Your Name")
.about("Your Rust CLI App")
.subcommand(
SubCommand::with_name("list")
.about("List network interfaces")
.arg(
Arg::with_name("up")
.short("u")
.long("up")
.help("Filter devices that are UP"),
)
.arg(
Arg::with_name("running")
.short("r")
.long("running")
.help("Filter devices that are RUNNING"),
)
.arg(
Arg::with_name("loopback")
.short("l")
.long("loopback")
.help("Filter devices that are LOOPBACK"),
)
.arg(
Arg::with_name("wireless")
.short("w")
.long("wireless")
.help("Filter devices that are WIRELESS"),
),
)
.subcommand(
SubCommand::with_name("run")
.about("Run the program")
.arg(
Arg::with_name("interface")
.short("i")
.long("interface")
.takes_value(true)
.value_name("INTERFACE")
.help("Network interface name"),
)
.arg(
Arg::with_name("file")
.short("f")
.long("file")
.takes_value(true)
.value_name("PATH")
.help("Path to the file"),
)
.arg(
Arg::with_name("socket")
.short("s")
.long("socket")
.takes_value(true)
.value_name("SOCKET")
.help("Socket addr for example 1.1.1.1:21 or [2001:db8::1]:8080"),
),
)
.get_matches()
}
Loading

0 comments on commit af6100f

Please sign in to comment.