mirror of
https://github.com/rzuasti/oott.git
synced 2026-07-08 19:21:54 +02:00
Consolidate backend scanner status, paging, and query-param duplication
Add ActiveStatusCell/PassiveStatusCell wrappers in the scanners common module so the five per-scanner status.rs files reduce to a single static; replace parse_parameter_bool/int/string with one generic parse_parameter over FromStr; extract the shared LIMIT/OFFSET paging clause into db::apply_paging; and drop a no-op for-loop in the ARP sender. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
c022e672d1
commit
8749ff33c1
@@ -41,6 +41,26 @@ pub fn get_db_connection() -> PooledConnection<SqliteConnectionManager> {
|
||||
}
|
||||
}
|
||||
|
||||
// Appends the shared `LIMIT ? OFFSET ?` paging clause (and its bound parameters) to a list query
|
||||
// when both an offset and a limit are supplied. Used by the list endpoints (devices, notifications,
|
||||
// device_events) so they page identically.
|
||||
pub fn apply_paging(
|
||||
sql: &mut String,
|
||||
params: &mut Vec<rusqlite::types::Value>,
|
||||
page_offset: Option<i64>,
|
||||
page_limit: Option<i64>,
|
||||
) {
|
||||
if let (Some(page_offset), Some(page_limit)) = (page_offset, page_limit) {
|
||||
debug!(
|
||||
"Adding paging to list with offset={} and limit={}",
|
||||
page_offset, page_limit
|
||||
);
|
||||
sql.push_str(" LIMIT ? OFFSET ?");
|
||||
params.push(page_limit.into());
|
||||
params.push(page_offset.into());
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn init_db() -> Result<(), DbError> {
|
||||
let mut initialised = INITIALISED.lock().await;
|
||||
if *initialised {
|
||||
|
||||
@@ -89,15 +89,7 @@ pub fn list(
|
||||
|
||||
sql_statement.push_str(" ORDER BY created_on DESC, id DESC");
|
||||
|
||||
if let (Some(page_offset), Some(page_limit)) = (page_offset, page_limit) {
|
||||
debug!(
|
||||
"Adding paging with offset={} and limit={}",
|
||||
page_offset, page_limit
|
||||
);
|
||||
sql_statement.push_str(" LIMIT ? OFFSET ?");
|
||||
params.push(page_limit.into());
|
||||
params.push(page_offset.into());
|
||||
}
|
||||
db::apply_paging(&mut sql_statement, &mut params, page_offset, page_limit);
|
||||
|
||||
let mut stmt = conn.prepare(sql_statement.as_str())?;
|
||||
|
||||
|
||||
@@ -118,16 +118,7 @@ pub fn list_devices(
|
||||
));
|
||||
|
||||
// Paging
|
||||
if let (Some(page_offset), Some(page_limit)) = (page_offset, page_limit) {
|
||||
debug!(
|
||||
"Adding paging to list with offset={} and limit={}",
|
||||
page_offset, page_limit
|
||||
);
|
||||
sql_statement.push_str("LIMIT ? OFFSET ?");
|
||||
|
||||
params.push(page_limit.into());
|
||||
params.push(page_offset.into());
|
||||
};
|
||||
db::apply_paging(&mut sql_statement, &mut params, page_offset, page_limit);
|
||||
|
||||
let mut stmt = conn.prepare(sql_statement.as_str())?;
|
||||
|
||||
|
||||
@@ -32,16 +32,7 @@ pub fn list(
|
||||
sql_statement.push_str(" ORDER BY created_on DESC");
|
||||
|
||||
// Paging
|
||||
if let (Some(page_offset), Some(page_limit)) = (page_offset, page_limit) {
|
||||
debug!(
|
||||
"Adding paging to list with offset={} and limit={}",
|
||||
page_offset, page_limit
|
||||
);
|
||||
sql_statement.push_str(" LIMIT ? OFFSET ?");
|
||||
|
||||
params.push(page_limit.into());
|
||||
params.push(page_offset.into());
|
||||
};
|
||||
db::apply_paging(&mut sql_statement, &mut params, page_offset, page_limit);
|
||||
|
||||
let mut stmt = conn.prepare(sql_statement.as_str())?;
|
||||
|
||||
|
||||
+5
-5
@@ -57,11 +57,11 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
db::init_db().await?;
|
||||
|
||||
// Initialize scanner status tracking
|
||||
scanners::arp::status::init();
|
||||
scanners::mdns::status::init();
|
||||
scanners::ssdp::status::init();
|
||||
scanners::dhcp::status::init();
|
||||
scanners::snmp::status::init();
|
||||
scanners::arp::status::STATUS.init();
|
||||
scanners::mdns::status::STATUS.init();
|
||||
scanners::ssdp::status::STATUS.init();
|
||||
scanners::dhcp::status::STATUS.init();
|
||||
scanners::snmp::status::STATUS.init();
|
||||
|
||||
// Start the device scanners, web server, and retention cleaner in parallel
|
||||
tokio::join!(
|
||||
|
||||
@@ -25,35 +25,35 @@ pub async fn send_packet(
|
||||
continue;
|
||||
}
|
||||
trace!("Sending ARP packet to {}", target_ip);
|
||||
for _ in 0..1 {
|
||||
//arp packet
|
||||
let mut arp_buf = [0u8; 28];
|
||||
let mut arp_packet = MutableArpPacket::new(&mut arp_buf).unwrap();
|
||||
|
||||
arp_packet.set_hardware_type(ArpHardwareTypes::Ethernet);
|
||||
arp_packet.set_protocol_type(EtherTypes::Ipv4);
|
||||
arp_packet.set_hw_addr_len(6);
|
||||
arp_packet.set_operation(ArpOperations::Request);
|
||||
arp_packet.set_proto_addr_len(4);
|
||||
arp_packet.set_sender_hw_addr(sender_macaddr);
|
||||
arp_packet.set_sender_proto_addr(sender_ip.ip());
|
||||
arp_packet.set_target_hw_addr(MacAddr::zero());
|
||||
arp_packet.set_target_proto_addr(target_ip);
|
||||
//arp packet
|
||||
let mut arp_buf = [0u8; 28];
|
||||
let mut arp_packet = MutableArpPacket::new(&mut arp_buf).unwrap();
|
||||
|
||||
//ethernet packet
|
||||
let mut ethernet_buf = [0u8; 42];
|
||||
let mut ethernet_packet = MutableEthernetPacket::new(&mut ethernet_buf).unwrap();
|
||||
arp_packet.set_hardware_type(ArpHardwareTypes::Ethernet);
|
||||
arp_packet.set_protocol_type(EtherTypes::Ipv4);
|
||||
arp_packet.set_hw_addr_len(6);
|
||||
arp_packet.set_operation(ArpOperations::Request);
|
||||
arp_packet.set_proto_addr_len(4);
|
||||
arp_packet.set_sender_hw_addr(sender_macaddr);
|
||||
arp_packet.set_sender_proto_addr(sender_ip.ip());
|
||||
arp_packet.set_target_hw_addr(MacAddr::zero());
|
||||
arp_packet.set_target_proto_addr(target_ip);
|
||||
|
||||
ethernet_packet.set_destination(MacAddr::broadcast());
|
||||
ethernet_packet.set_source(sender_macaddr);
|
||||
ethernet_packet.set_ethertype(EtherTypes::Arp);
|
||||
ethernet_packet.set_payload(arp_packet.packet_mut());
|
||||
//ethernet packet
|
||||
let mut ethernet_buf = [0u8; 42];
|
||||
let mut ethernet_packet = MutableEthernetPacket::new(&mut ethernet_buf).unwrap();
|
||||
|
||||
ethernet_packet.set_destination(MacAddr::broadcast());
|
||||
ethernet_packet.set_source(sender_macaddr);
|
||||
ethernet_packet.set_ethertype(EtherTypes::Arp);
|
||||
ethernet_packet.set_payload(arp_packet.packet_mut());
|
||||
|
||||
tx.send_to(
|
||||
ethernet_packet.to_immutable().packet(),
|
||||
Some(interface.clone()),
|
||||
);
|
||||
|
||||
tx.send_to(
|
||||
ethernet_packet.to_immutable().packet(),
|
||||
Some(interface.clone()),
|
||||
);
|
||||
}
|
||||
count += 1;
|
||||
// Sleep 1 millisecond every 255 packets
|
||||
if (count % 255) == 0 {
|
||||
|
||||
@@ -14,14 +14,14 @@ pub async fn scan() -> Result<(), Box<dyn std::error::Error>> {
|
||||
}
|
||||
|
||||
loop {
|
||||
status::set_running();
|
||||
status::STATUS.set_running();
|
||||
|
||||
// Find online devices via ARP
|
||||
let devices = finder::find(get_settings().networking.interface.clone()).await?;
|
||||
|
||||
info!("Done with ARP probes");
|
||||
info!("Found {} online devices", devices.len());
|
||||
status::record_scan(&devices);
|
||||
status::STATUS.record_scan(&devices);
|
||||
|
||||
// Process found devices
|
||||
for device in devices.iter() {
|
||||
@@ -35,7 +35,7 @@ pub async fn scan() -> Result<(), Box<dyn std::error::Error>> {
|
||||
"Scan finished. Sleeping for {}",
|
||||
get_settings().arp_scanner.wait_between_scans
|
||||
);
|
||||
status::set_waiting(next_scan_at);
|
||||
status::STATUS.set_waiting(next_scan_at);
|
||||
sleep(wait).await;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,34 +1,3 @@
|
||||
use chrono::{DateTime, Utc};
|
||||
use once_cell::sync::OnceCell;
|
||||
use std::sync::Mutex;
|
||||
use crate::scanners::common::active_status::ActiveStatusCell;
|
||||
|
||||
use crate::model::devices::Device;
|
||||
use crate::scanners::common::active_status::{ActiveSnapshot, ActiveStatus};
|
||||
|
||||
static STATUS: OnceCell<Mutex<ActiveStatus>> = OnceCell::new();
|
||||
|
||||
pub fn init() {
|
||||
STATUS.set(Mutex::new(ActiveStatus::new())).ok();
|
||||
}
|
||||
|
||||
pub fn set_running() {
|
||||
if let Some(m) = STATUS.get() {
|
||||
m.lock().unwrap().set_running();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_waiting(next_scan_at: DateTime<Utc>) {
|
||||
if let Some(m) = STATUS.get() {
|
||||
m.lock().unwrap().set_waiting(next_scan_at);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn record_scan(devices: &[Device]) {
|
||||
if let Some(m) = STATUS.get() {
|
||||
m.lock().unwrap().record_scan(devices);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get() -> Option<ActiveSnapshot> {
|
||||
STATUS.get().map(|m| m.lock().unwrap().snapshot())
|
||||
}
|
||||
pub static STATUS: ActiveStatusCell = ActiveStatusCell::new();
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
use crate::model::devices::Device;
|
||||
use chrono::{DateTime, Utc};
|
||||
use once_cell::sync::OnceCell;
|
||||
use std::collections::HashSet;
|
||||
use std::sync::Mutex;
|
||||
|
||||
/// Status state for the active (polling) scanners — ARP and SNMP. Each scanner owns its own
|
||||
/// `OnceCell<Mutex<ActiveStatus>>` and delegates to these methods (see e.g.
|
||||
@@ -67,6 +69,50 @@ impl ActiveStatus {
|
||||
}
|
||||
}
|
||||
|
||||
/// A lazily-initialised, mutex-guarded [`ActiveStatus`] owned by a single active scanner. Each
|
||||
/// scanner declares one as a `static` and the API layer reads it back via [`get`](Self::get).
|
||||
/// All methods are no-ops until [`init`](Self::init) is called (mirroring the previous
|
||||
/// per-scanner `OnceCell` behaviour).
|
||||
pub struct ActiveStatusCell(OnceCell<Mutex<ActiveStatus>>);
|
||||
|
||||
impl ActiveStatusCell {
|
||||
pub const fn new() -> Self {
|
||||
Self(OnceCell::new())
|
||||
}
|
||||
|
||||
pub fn init(&self) {
|
||||
self.0.set(Mutex::new(ActiveStatus::new())).ok();
|
||||
}
|
||||
|
||||
pub fn set_running(&self) {
|
||||
if let Some(m) = self.0.get() {
|
||||
m.lock().unwrap().set_running();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_waiting(&self, next_scan_at: DateTime<Utc>) {
|
||||
if let Some(m) = self.0.get() {
|
||||
m.lock().unwrap().set_waiting(next_scan_at);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn record_scan(&self, devices: &[Device]) {
|
||||
if let Some(m) = self.0.get() {
|
||||
m.lock().unwrap().record_scan(devices);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get(&self) -> Option<ActiveSnapshot> {
|
||||
self.0.get().map(|m| m.lock().unwrap().snapshot())
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for ActiveStatusCell {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
use std::collections::HashMap;
|
||||
use std::sync::Mutex;
|
||||
|
||||
use chrono::{DateTime, Duration, Utc};
|
||||
use once_cell::sync::OnceCell;
|
||||
|
||||
/// A device counts as "seen" only if its most recent sighting falls within this rolling window.
|
||||
const RECENT_WINDOW_SECONDS: i64 = 3600;
|
||||
@@ -58,6 +60,44 @@ impl PassiveStatus {
|
||||
}
|
||||
}
|
||||
|
||||
/// A lazily-initialised, mutex-guarded [`PassiveStatus`] owned by a single passive scanner. Each
|
||||
/// scanner declares one as a `static` and the API layer reads it back via [`get`](Self::get).
|
||||
/// All methods are no-ops until [`init`](Self::init) is called (mirroring the previous
|
||||
/// per-scanner `OnceCell` behaviour).
|
||||
pub struct PassiveStatusCell(OnceCell<Mutex<PassiveStatus>>);
|
||||
|
||||
impl PassiveStatusCell {
|
||||
pub const fn new() -> Self {
|
||||
Self(OnceCell::new())
|
||||
}
|
||||
|
||||
pub fn init(&self) {
|
||||
self.0.set(Mutex::new(PassiveStatus::new())).ok();
|
||||
}
|
||||
|
||||
pub fn set_listening(&self) {
|
||||
if let Some(m) = self.0.get() {
|
||||
m.lock().unwrap().set_listening();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn record_discovery(&self, mac: &str) {
|
||||
if let Some(m) = self.0.get() {
|
||||
m.lock().unwrap().record_discovery(mac);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get(&self) -> Option<PassiveSnapshot> {
|
||||
self.0.get().map(|m| m.lock().unwrap().snapshot())
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for PassiveStatusCell {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
@@ -18,7 +18,7 @@ pub async fn listen() -> Result<(), Box<dyn std::error::Error>> {
|
||||
}
|
||||
|
||||
let socket = finder::open_socket()?;
|
||||
status::set_listening();
|
||||
status::STATUS.set_listening();
|
||||
info!("DHCP scanner listening for client requests");
|
||||
|
||||
let mut buf = [0u8; 1500];
|
||||
@@ -54,5 +54,5 @@ fn process_discovery(discovery: finder::DhcpDiscovery) {
|
||||
let device = build_device(mac.clone(), ipv4, &[], discovery.hostname);
|
||||
|
||||
pipeline::record_sighting(device, DeviceEventScanner::Dhcp);
|
||||
status::record_discovery(&mac);
|
||||
status::STATUS.record_discovery(&mac);
|
||||
}
|
||||
|
||||
@@ -1,26 +1,3 @@
|
||||
use once_cell::sync::OnceCell;
|
||||
use std::sync::Mutex;
|
||||
use crate::scanners::common::passive_status::PassiveStatusCell;
|
||||
|
||||
use crate::scanners::common::passive_status::{PassiveSnapshot, PassiveStatus};
|
||||
|
||||
static STATUS: OnceCell<Mutex<PassiveStatus>> = OnceCell::new();
|
||||
|
||||
pub fn init() {
|
||||
STATUS.set(Mutex::new(PassiveStatus::new())).ok();
|
||||
}
|
||||
|
||||
pub fn set_listening() {
|
||||
if let Some(m) = STATUS.get() {
|
||||
m.lock().unwrap().set_listening();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn record_discovery(mac: &str) {
|
||||
if let Some(m) = STATUS.get() {
|
||||
m.lock().unwrap().record_discovery(mac);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get() -> Option<PassiveSnapshot> {
|
||||
STATUS.get().map(|m| m.lock().unwrap().snapshot())
|
||||
}
|
||||
pub static STATUS: PassiveStatusCell = PassiveStatusCell::new();
|
||||
|
||||
@@ -20,7 +20,7 @@ pub async fn listen() -> Result<(), Box<dyn std::error::Error>> {
|
||||
|
||||
let interface = get_settings().networking.interface.clone();
|
||||
let socket = finder::open_socket(interface.clone())?;
|
||||
status::set_listening();
|
||||
status::STATUS.set_listening();
|
||||
info!("mDNS scanner listening for announcements");
|
||||
|
||||
let probe_timeout = Duration::from(get_settings().mdns_scanner.probe_timeout);
|
||||
@@ -83,5 +83,5 @@ async fn process_announcement(
|
||||
);
|
||||
|
||||
pipeline::record_sighting(device, DeviceEventScanner::Mdns);
|
||||
status::record_discovery(&mac);
|
||||
status::STATUS.record_discovery(&mac);
|
||||
}
|
||||
|
||||
@@ -1,26 +1,3 @@
|
||||
use once_cell::sync::OnceCell;
|
||||
use std::sync::Mutex;
|
||||
use crate::scanners::common::passive_status::PassiveStatusCell;
|
||||
|
||||
use crate::scanners::common::passive_status::{PassiveSnapshot, PassiveStatus};
|
||||
|
||||
static STATUS: OnceCell<Mutex<PassiveStatus>> = OnceCell::new();
|
||||
|
||||
pub fn init() {
|
||||
STATUS.set(Mutex::new(PassiveStatus::new())).ok();
|
||||
}
|
||||
|
||||
pub fn set_listening() {
|
||||
if let Some(m) = STATUS.get() {
|
||||
m.lock().unwrap().set_listening();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn record_discovery(mac: &str) {
|
||||
if let Some(m) = STATUS.get() {
|
||||
m.lock().unwrap().record_discovery(mac);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get() -> Option<PassiveSnapshot> {
|
||||
STATUS.get().map(|m| m.lock().unwrap().snapshot())
|
||||
}
|
||||
pub static STATUS: PassiveStatusCell = PassiveStatusCell::new();
|
||||
|
||||
@@ -25,14 +25,14 @@ pub async fn scan() -> Result<(), Box<dyn std::error::Error>> {
|
||||
info!("SNMP scanner polling agent at {}", config.target);
|
||||
|
||||
loop {
|
||||
status::set_running();
|
||||
status::STATUS.set_running();
|
||||
|
||||
// A failed poll (unreachable agent, timeout, bad community) must not stop the loop;
|
||||
// log it and try again next cycle.
|
||||
match finder::find(config).await {
|
||||
Ok(devices) => {
|
||||
info!("SNMP poll found {} devices in the ARP cache", devices.len());
|
||||
status::record_scan(&devices);
|
||||
status::STATUS.record_scan(&devices);
|
||||
for device in devices.iter() {
|
||||
pipeline::record_sighting(device.clone(), DeviceEventScanner::Snmp);
|
||||
}
|
||||
@@ -46,7 +46,7 @@ pub async fn scan() -> Result<(), Box<dyn std::error::Error>> {
|
||||
"SNMP scan finished. Sleeping for {}",
|
||||
config.wait_between_scans
|
||||
);
|
||||
status::set_waiting(next_scan_at);
|
||||
status::STATUS.set_waiting(next_scan_at);
|
||||
sleep(wait).await;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,34 +1,3 @@
|
||||
use chrono::{DateTime, Utc};
|
||||
use once_cell::sync::OnceCell;
|
||||
use std::sync::Mutex;
|
||||
use crate::scanners::common::active_status::ActiveStatusCell;
|
||||
|
||||
use crate::model::devices::Device;
|
||||
use crate::scanners::common::active_status::{ActiveSnapshot, ActiveStatus};
|
||||
|
||||
static STATUS: OnceCell<Mutex<ActiveStatus>> = OnceCell::new();
|
||||
|
||||
pub fn init() {
|
||||
STATUS.set(Mutex::new(ActiveStatus::new())).ok();
|
||||
}
|
||||
|
||||
pub fn set_running() {
|
||||
if let Some(m) = STATUS.get() {
|
||||
m.lock().unwrap().set_running();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_waiting(next_scan_at: DateTime<Utc>) {
|
||||
if let Some(m) = STATUS.get() {
|
||||
m.lock().unwrap().set_waiting(next_scan_at);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn record_scan(devices: &[Device]) {
|
||||
if let Some(m) = STATUS.get() {
|
||||
m.lock().unwrap().record_scan(devices);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get() -> Option<ActiveSnapshot> {
|
||||
STATUS.get().map(|m| m.lock().unwrap().snapshot())
|
||||
}
|
||||
pub static STATUS: ActiveStatusCell = ActiveStatusCell::new();
|
||||
|
||||
@@ -20,7 +20,7 @@ pub async fn listen() -> Result<(), Box<dyn std::error::Error>> {
|
||||
|
||||
let interface = get_settings().networking.interface.clone();
|
||||
let socket = finder::open_socket(interface.clone())?;
|
||||
status::set_listening();
|
||||
status::STATUS.set_listening();
|
||||
info!("SSDP scanner listening for announcements");
|
||||
|
||||
let probe_timeout = Duration::from(get_settings().ssdp_scanner.probe_timeout);
|
||||
@@ -77,5 +77,5 @@ async fn process_announcement(
|
||||
let device = build_device(mac.clone(), src_ip.to_string(), &device_types, server_hint);
|
||||
|
||||
pipeline::record_sighting(device, DeviceEventScanner::Ssdp);
|
||||
status::record_discovery(&mac);
|
||||
status::STATUS.record_discovery(&mac);
|
||||
}
|
||||
|
||||
@@ -1,26 +1,3 @@
|
||||
use once_cell::sync::OnceCell;
|
||||
use std::sync::Mutex;
|
||||
use crate::scanners::common::passive_status::PassiveStatusCell;
|
||||
|
||||
use crate::scanners::common::passive_status::{PassiveSnapshot, PassiveStatus};
|
||||
|
||||
static STATUS: OnceCell<Mutex<PassiveStatus>> = OnceCell::new();
|
||||
|
||||
pub fn init() {
|
||||
STATUS.set(Mutex::new(PassiveStatus::new())).ok();
|
||||
}
|
||||
|
||||
pub fn set_listening() {
|
||||
if let Some(m) = STATUS.get() {
|
||||
m.lock().unwrap().set_listening();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn record_discovery(mac: &str) {
|
||||
if let Some(m) = STATUS.get() {
|
||||
m.lock().unwrap().record_discovery(mac);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get() -> Option<PassiveSnapshot> {
|
||||
STATUS.get().map(|m| m.lock().unwrap().snapshot())
|
||||
}
|
||||
pub static STATUS: PassiveStatusCell = PassiveStatusCell::new();
|
||||
|
||||
@@ -13,5 +13,5 @@ use crate::web_server::scanner_status::{ActiveScannerStatusResponse, active_resp
|
||||
security(("bearer_auth" = []))
|
||||
)]
|
||||
pub async fn status() -> Result<Json<ActiveScannerStatusResponse>, StatusCode> {
|
||||
active_response(crate::scanners::arp::status::get()).map(Json)
|
||||
active_response(crate::scanners::arp::status::STATUS.get()).map(Json)
|
||||
}
|
||||
|
||||
@@ -30,8 +30,8 @@ pub async fn list(
|
||||
Query(params): Query<HashMap<String, String>>,
|
||||
) -> Result<Json<Vec<DeviceEvent>>, StatusCode> {
|
||||
let created_from = utils::parse_parameter_date(¶ms, "created_from");
|
||||
let page_offset: Option<i64> = utils::parse_parameter_int(¶ms, "page_offset");
|
||||
let page_limit: Option<i64> = utils::parse_parameter_int(¶ms, "page_limit");
|
||||
let page_offset: Option<i64> = utils::parse_parameter(¶ms, "page_offset");
|
||||
let page_limit: Option<i64> = utils::parse_parameter(¶ms, "page_limit");
|
||||
|
||||
match db::device_events::list(Some(mac_address), created_from, page_offset, page_limit) {
|
||||
Ok(value) => Ok(Json(value)),
|
||||
|
||||
@@ -40,17 +40,17 @@ use crate::web_server::utils;
|
||||
pub async fn list(
|
||||
Query(params): Query<HashMap<String, String>>,
|
||||
) -> Result<Json<DeviceListResponse>, StatusCode> {
|
||||
let is_registered: Option<bool> = utils::parse_parameter_bool(¶ms, "is_registered");
|
||||
let is_registered: Option<bool> = utils::parse_parameter(¶ms, "is_registered");
|
||||
let last_seen_from: Option<DateTime<Utc>> =
|
||||
utils::parse_parameter_date(¶ms, "last_seen_from");
|
||||
let last_seen_to: Option<DateTime<Utc>> = utils::parse_parameter_date(¶ms, "last_seen_to");
|
||||
let owner: Option<String> = utils::parse_parameter_string(¶ms, "owner");
|
||||
let device_type: Option<String> = utils::parse_parameter_string(¶ms, "device_type");
|
||||
let vendor: Option<String> = utils::parse_parameter_string(¶ms, "vendor");
|
||||
let sort_by: Option<String> = utils::parse_parameter_string(¶ms, "sort_by");
|
||||
let sort_order: Option<String> = utils::parse_parameter_string(¶ms, "sort_order");
|
||||
let page_offset: Option<i64> = utils::parse_parameter_int(¶ms, "page_offset");
|
||||
let page_limit: Option<i64> = utils::parse_parameter_int(¶ms, "page_limit");
|
||||
let owner: Option<String> = utils::parse_parameter(¶ms, "owner");
|
||||
let device_type: Option<String> = utils::parse_parameter(¶ms, "device_type");
|
||||
let vendor: Option<String> = utils::parse_parameter(¶ms, "vendor");
|
||||
let sort_by: Option<String> = utils::parse_parameter(¶ms, "sort_by");
|
||||
let sort_order: Option<String> = utils::parse_parameter(¶ms, "sort_order");
|
||||
let page_offset: Option<i64> = utils::parse_parameter(¶ms, "page_offset");
|
||||
let page_limit: Option<i64> = utils::parse_parameter(¶ms, "page_limit");
|
||||
|
||||
let items = match db::devices::list_devices(
|
||||
is_registered,
|
||||
|
||||
@@ -13,5 +13,5 @@ use crate::web_server::scanner_status::{PassiveScannerStatusResponse, passive_re
|
||||
security(("bearer_auth" = []))
|
||||
)]
|
||||
pub async fn status() -> Result<Json<PassiveScannerStatusResponse>, StatusCode> {
|
||||
passive_response(crate::scanners::dhcp::status::get()).map(Json)
|
||||
passive_response(crate::scanners::dhcp::status::STATUS.get()).map(Json)
|
||||
}
|
||||
|
||||
@@ -13,5 +13,5 @@ use crate::web_server::scanner_status::{PassiveScannerStatusResponse, passive_re
|
||||
security(("bearer_auth" = []))
|
||||
)]
|
||||
pub async fn status() -> Result<Json<PassiveScannerStatusResponse>, StatusCode> {
|
||||
passive_response(crate::scanners::mdns::status::get()).map(Json)
|
||||
passive_response(crate::scanners::mdns::status::STATUS.get()).map(Json)
|
||||
}
|
||||
|
||||
@@ -130,9 +130,9 @@ pub async fn mark_all_as_old() -> impl IntoResponse {
|
||||
pub async fn list(
|
||||
Query(params): Query<HashMap<String, String>>,
|
||||
) -> Result<Json<NotificationListResponse>, StatusCode> {
|
||||
let is_new: Option<bool> = utils::parse_parameter_bool(¶ms, "is_new");
|
||||
let page_offset: Option<i64> = utils::parse_parameter_int(¶ms, "page_offset");
|
||||
let page_limit: Option<i64> = utils::parse_parameter_int(¶ms, "page_limit");
|
||||
let is_new: Option<bool> = utils::parse_parameter(¶ms, "is_new");
|
||||
let page_offset: Option<i64> = utils::parse_parameter(¶ms, "page_offset");
|
||||
let page_limit: Option<i64> = utils::parse_parameter(¶ms, "page_limit");
|
||||
|
||||
let items = match db::notifications::list(is_new, page_offset, page_limit) {
|
||||
Ok(value) => value,
|
||||
|
||||
@@ -13,5 +13,5 @@ use crate::web_server::scanner_status::{ActiveScannerStatusResponse, active_resp
|
||||
security(("bearer_auth" = []))
|
||||
)]
|
||||
pub async fn status() -> Result<Json<ActiveScannerStatusResponse>, StatusCode> {
|
||||
active_response(crate::scanners::snmp::status::get()).map(Json)
|
||||
active_response(crate::scanners::snmp::status::STATUS.get()).map(Json)
|
||||
}
|
||||
|
||||
@@ -13,5 +13,5 @@ use crate::web_server::scanner_status::{PassiveScannerStatusResponse, passive_re
|
||||
security(("bearer_auth" = []))
|
||||
)]
|
||||
pub async fn status() -> Result<Json<PassiveScannerStatusResponse>, StatusCode> {
|
||||
passive_response(crate::scanners::ssdp::status::get()).map(Json)
|
||||
passive_response(crate::scanners::ssdp::status::STATUS.get()).map(Json)
|
||||
}
|
||||
|
||||
@@ -1,41 +1,21 @@
|
||||
use std::collections::HashMap;
|
||||
use std::str::FromStr;
|
||||
|
||||
use chrono::{DateTime, Utc};
|
||||
use log::{debug, warn};
|
||||
|
||||
pub fn parse_parameter_bool(params: &HashMap<String, String>, name: &str) -> Option<bool> {
|
||||
if params.contains_key(name) {
|
||||
let param_value = params.get(name).unwrap().as_str();
|
||||
debug!("Found parameter {name} with value {}", param_value);
|
||||
param_value.parse::<bool>().ok()
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse_parameter_int(params: &HashMap<String, String>, name: &str) -> Option<i64> {
|
||||
if params.contains_key(name) {
|
||||
let param_value = params.get(name).unwrap().as_str();
|
||||
debug!("Found parameter {name} with value {}", param_value);
|
||||
param_value.parse::<i64>().ok()
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse_parameter_string(params: &HashMap<String, String>, name: &str) -> Option<String> {
|
||||
if params.contains_key(name) {
|
||||
let param_value = params.get(name).unwrap().as_str();
|
||||
debug!("Found parameter {name} with value {}", param_value);
|
||||
Some(param_value.to_string())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
// Parses a query parameter into any `FromStr` type (e.g. bool, i64, String). Returns `None` when
|
||||
// the parameter is absent or fails to parse. The target type is inferred from the call site, so
|
||||
// callers annotate the binding: `let limit: Option<i64> = parse_parameter(¶ms, "page_limit");`
|
||||
pub fn parse_parameter<T: FromStr>(params: &HashMap<String, String>, name: &str) -> Option<T> {
|
||||
let param_value = params.get(name)?;
|
||||
debug!("Found parameter {name} with value {param_value}");
|
||||
param_value.parse::<T>().ok()
|
||||
}
|
||||
|
||||
pub fn parse_parameter_date(params: &HashMap<String, String>, name: &str) -> Option<DateTime<Utc>> {
|
||||
if params.contains_key(name) {
|
||||
let mut param_value = params.get(name).unwrap().to_ascii_uppercase();
|
||||
if let Some(value) = params.get(name) {
|
||||
let mut param_value = value.to_ascii_uppercase();
|
||||
if !param_value.ends_with("Z") {
|
||||
param_value.push('Z');
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user