code wiki / (root) / nx_net_governor.nx

nx_net_governor.nx source

↩ module page · 70 lines · 2847 B

1// nx_net_governor.nx -- general network traffic-shaping governor (ISP-safe). 2// 3// module: nishi-core.net.governor 4// depends: nx_syscalls.nx 5// capability: CORE_COMPUTE 6// wired_status: FULLY_WIRED 7// 8// A REUSABLE bits-up primitive for ANY network client that must not look like 9// abuse to an ISP/IDS (which penalize BitTorrent-like / scan-like behavior: 10// many rapid connections to many IPs, sustained high bandwidth, DNS floods). 11// It shapes aggregate activity to a slow, ordinary profile: 12// * GLOBAL min-interval between ANY two requests/connections (low steady rate) 13// * total request/connection cap + total byte budget per run (low volume) 14// * per-transfer size cap (no huge transfers) 15// Pair with: standard ports, GET-only / no-seed, sequential concurrency, DNS 16// caching. Used by the crawler today; the SAME governor will pace the future 17// torrent client (per-peer connection rate + upload/download byte budgets) and 18// any other network worker. Deterministic; the caller passes the clock. 19 20import "nx_syscalls.nx" 21 22struct NxNetGov { 23 min_interval_ms: i64, // floor between ANY two requests/connections 24 max_requests: i64, // hard cap on requests/connections this run 25 byte_budget: i64, // hard cap on bytes transferred this run 26 max_resp_bytes: i64, // per-transfer size cap 27 n_requests: i64, 28 bytes_used: i64, 29 last_ms: i64, 30} 31const NX_NETGOV_BYTES: i64 = 56 // 7 * 8 32 33func nx_gov_init(g: *NxNetGov, min_interval_ms: i64, max_requests: i64, 34 byte_budget: i64, max_resp_bytes: i64) -> i64 { 35 g.min_interval_ms = min_interval_ms 36 g.max_requests = max_requests 37 g.byte_budget = byte_budget 38 g.max_resp_bytes = max_resp_bytes 39 g.n_requests = 0 40 g.bytes_used = 0 41 g.last_ms = 0 - min_interval_ms // allow the very first request immediately 42 return 0 43} 44 45// Still under the run's request + byte budgets? (0 => stop.) 46func nx_gov_can_fetch(g: *NxNetGov) -> i64 { 47 if g.n_requests >= g.max_requests { return 0 } 48 if g.bytes_used >= g.byte_budget { return 0 } 49 return 1 50} 51 52// ms to sleep before the next request to honor the GLOBAL min-interval (keeps 53// the connection rate low + steady, not bursty/scan-like). 54func nx_gov_wait_ms(g: *NxNetGov, now_ms: i64) -> i64 { 55 let elapsed: i64 = now_ms - g.last_ms 56 if elapsed >= g.min_interval_ms { return 0 } 57 return g.min_interval_ms - elapsed 58} 59 60// Record a completed request/transfer (updates rate clock + budgets). 61func nx_gov_record(g: *NxNetGov, now_ms: i64, bytes: i64) -> i64 { 62 g.n_requests = g.n_requests + 1 63 g.bytes_used = g.bytes_used + bytes 64 g.last_ms = now_ms 65 return 0 66} 67 68// Per-transfer size cap (truncate large transfers so one doesn't blow the 69// bandwidth profile). 70func nx_gov_resp_cap(g: *NxNetGov) -> i64 { return g.max_resp_bytes }