Skip to main content

netscli_core/ops/
config.rs

1use crate::{
2    DEFAULT_CONCURRENCY, DEFAULT_DNS_TIMEOUT_MS, DEFAULT_PING_TIMEOUT_MS, DEFAULT_SCAN_TIMEOUT_MS,
3};
4
5#[derive(Debug, Clone)]
6pub struct OpsConfig {
7    pub concurrency: usize,
8    pub scan_timeout_ms: u64,
9    pub ping_timeout_ms: u64,
10    pub dns_timeout_ms: u64,
11}
12
13impl Default for OpsConfig {
14    fn default() -> Self {
15        Self {
16            concurrency: DEFAULT_CONCURRENCY,
17            scan_timeout_ms: DEFAULT_SCAN_TIMEOUT_MS,
18            ping_timeout_ms: DEFAULT_PING_TIMEOUT_MS,
19            dns_timeout_ms: DEFAULT_DNS_TIMEOUT_MS,
20        }
21    }
22}
23
24/// High-level operations used by CLI/TUI/GUI/MCP to keep behavior consistent.
25#[derive(Debug, Clone, Default)]
26pub struct Ops {
27    pub(super) cfg: OpsConfig,
28}
29
30/// Upper bound on in-flight probes.
31///
32/// Exported so callers clamp to the same value rather than guessing: the MCP
33/// server used to clamp to 4096 here, which meant 1025..=4096 was accepted at
34/// the API boundary and then silently reduced by `Ops::new` (C-10).
35pub const MAX_CONCURRENCY: usize = 1024;
36
37impl Ops {
38    pub fn new(cfg: OpsConfig) -> Self {
39        let mut cfg = cfg;
40        // Lower bound prevents semaphore deadlock; the upper bound stops users
41        // from triggering kernel ephemeral-port exhaustion on aggressive
42        // --concurrency values.
43        cfg.concurrency = cfg.concurrency.clamp(1, MAX_CONCURRENCY);
44        cfg.scan_timeout_ms = cfg.scan_timeout_ms.max(1);
45        cfg.ping_timeout_ms = cfg.ping_timeout_ms.max(1);
46        cfg.dns_timeout_ms = cfg.dns_timeout_ms.max(1);
47        Self { cfg }
48    }
49
50    pub fn config(&self) -> &OpsConfig {
51        &self.cfg
52    }
53}