use crate::host::Host;
use crate::scan::setting::{HostScanSetting, PortScanSetting};
use std::collections::HashMap;
use std::net::SocketAddr;
use std::sync::mpsc::{Receiver, Sender, channel};
use std::sync::{Arc, Mutex};
use tokio::runtime::{Builder, Runtime};
use super::async_io;
use super::blocking;
use super::result::{ScanError, ScanResult, ServiceProbeResult};
use super::setting::ServiceProbeSetting;
#[derive(Clone, Debug)]
pub struct HostScanner {
pub scan_setting: HostScanSetting,
pub tx: Arc<Mutex<Sender<Host>>>,
pub rx: Arc<Mutex<Receiver<Host>>>,
}
impl HostScanner {
fn runtime() -> Runtime {
Builder::new_multi_thread()
.enable_io()
.enable_time()
.build()
.expect("failed to initialize tokio runtime")
}
pub fn new(scan_setting: HostScanSetting) -> Self {
let (tx, rx) = channel();
Self {
scan_setting,
tx: Arc::new(Mutex::new(tx)),
rx: Arc::new(Mutex::new(rx)),
}
}
pub fn get_progress_receiver(&self) -> Arc<Mutex<Receiver<Host>>> {
self.rx.clone()
}
pub async fn scan_async(&self) -> ScanResult {
if self.scan_setting.async_scan {
async_io::scan_hosts(self.scan_setting.clone(), &self.tx).await
} else {
let setting = self.scan_setting.clone();
let tx = self.tx.clone();
match tokio::task::spawn_blocking(move || blocking::scan_hosts(setting, &tx)).await {
Ok(result) => result,
Err(e) => ScanResult::error(ScanError::RuntimeError(format!(
"blocking scan task join error: {}",
e
))),
}
}
}
pub fn scan(&self) -> ScanResult {
Self::runtime().block_on(self.scan_async())
}
}
#[derive(Clone, Debug)]
pub struct PortScanner {
pub scan_setting: PortScanSetting,
pub tx: Arc<Mutex<Sender<SocketAddr>>>,
pub rx: Arc<Mutex<Receiver<SocketAddr>>>,
}
impl PortScanner {
fn runtime() -> Runtime {
Builder::new_multi_thread()
.enable_io()
.enable_time()
.build()
.expect("failed to initialize tokio runtime")
}
pub fn new(scan_setting: PortScanSetting) -> Self {
let (tx, rx) = channel();
Self {
scan_setting,
tx: Arc::new(Mutex::new(tx)),
rx: Arc::new(Mutex::new(rx)),
}
}
pub fn get_progress_receiver(&self) -> Arc<Mutex<Receiver<SocketAddr>>> {
self.rx.clone()
}
pub async fn scan_async(&self) -> ScanResult {
match self.scan_setting.scan_type {
crate::scan::setting::PortScanType::TcpSynScan => {
if self.scan_setting.async_scan {
async_io::scan_ports(self.scan_setting.clone(), &self.tx).await
} else {
let setting = self.scan_setting.clone();
let tx = self.tx.clone();
match tokio::task::spawn_blocking(move || blocking::scan_ports(setting, &tx))
.await
{
Ok(result) => result,
Err(e) => ScanResult::error(ScanError::RuntimeError(format!(
"blocking scan task join error: {}",
e
))),
}
}
}
crate::scan::setting::PortScanType::TcpConnectScan => {
async_io::run_connect_scan(self.scan_setting.clone(), &self.tx).await
}
}
}
pub fn scan(&self) -> ScanResult {
Self::runtime().block_on(self.scan_async())
}
}
#[derive(Clone, Debug)]
pub struct ServiceDetector {
pub setting: ServiceProbeSetting,
pub tx: Arc<Mutex<Sender<SocketAddr>>>,
pub rx: Arc<Mutex<Receiver<SocketAddr>>>,
}
impl ServiceDetector {
fn runtime() -> Runtime {
Builder::new_multi_thread()
.enable_io()
.enable_time()
.build()
.expect("failed to initialize tokio runtime")
}
pub fn new(setting: ServiceProbeSetting) -> Self {
let (tx, rx) = channel();
Self {
setting,
tx: Arc::new(Mutex::new(tx)),
rx: Arc::new(Mutex::new(rx)),
}
}
pub fn get_progress_receiver(&self) -> Arc<Mutex<Receiver<SocketAddr>>> {
self.rx.clone()
}
pub async fn run_async(&self) -> HashMap<u16, ServiceProbeResult> {
super::service::run_service_probe(&self.setting, &self.tx).await
}
pub fn run(&self) -> HashMap<u16, ServiceProbeResult> {
Self::runtime().block_on(self.run_async())
}
}