use dashmap::DashMap;
use smol::net::TcpStream;
use std::{
net::{IpAddr, Ipv4Addr, SocketAddr},
sync::Arc,
};
use crate::cli::Cli;
#[derive(Clone)]
pub struct PortScanner {
addr: IpAddr,
pub port_map: Arc<DashMap<u16, bool>>,
}
impl PortScanner {
pub fn new(address: IpAddr) -> Self {
Self {
addr: address,
port_map: Arc::new(DashMap::new()),
}
}
pub async fn check_port_open(&self, port_num: &u16, cli: Option<&Cli>) -> bool {
let socket_address = SocketAddr::new(self.addr, *port_num);
match TcpStream::connect(socket_address).await {
Ok(_) => {
if let Some(c) = cli {
if c.verbose {
log::info!("port {port_num} open!");
}
if c.greppable {
log::info!("{port_num}");
}
}
true
}
Err(_) => false,
}
}
pub async fn scan_ports(&mut self, ports: &Vec<u16>, cli: Option<&Cli>) {
for x in ports {
if self.check_port_open(x, cli).await {
self.port_map.insert(*x, true);
} else {
self.port_map.insert(*x, false);
}
}
}
}
impl Default for PortScanner {
fn default() -> Self {
Self {
addr: IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)),
port_map: Arc::default(),
}
}
}
impl From<&Cli> for PortScanner {
fn from(cli: &Cli) -> Self {
let cap = cli.get_ports().1 - cli.get_ports().0;
Self {
addr: cli.addr,
port_map: Arc::new(DashMap::with_capacity(cap as usize)),
}
}
}