1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
//! `flowscope::correlate` — generic helpers for cross-flow
//! correlation patterns.
//!
//! Three small, composable primitives that consumers stitch into
//! detectors:
//!
//! - [`TimeBucketedCounter`] — windowed rate counting per key
//! (DDoS rate-limits, SYN-flood thresholds, "did key K cross N
//! in W seconds").
//! - [`KeyIndexed`] — TTL'd LRU cache with monotonic-timestamp
//! eviction (DNS query/response correlation, ICMP error tying
//! back to original flow, generic request/response matching).
//! - [`SequencePattern`] / [`KeylessSequencePattern`] — generic
//! FSM trait for event-stream pattern detectors (port scans,
//! "auth failure → success", retry storms).
//!
//! These are tracker-clock aware: `now: Timestamp` is the packet
//! timestamp, not wall clock, so live and offline pipelines
//! produce identical detector output for identical inputs.
//!
//! # Quick start: bucketed counter
//!
//! ```
//! use flowscope::correlate::TimeBucketedCounter;
//! use flowscope::Timestamp;
//! use std::time::Duration;
//!
//! let mut c: TimeBucketedCounter<u32> =
//! TimeBucketedCounter::new(Duration::from_secs(60), Duration::from_secs(10), 1024);
//!
//! c.bump(42, Timestamp::new(0, 0));
//! c.bump(42, Timestamp::new(1, 0));
//! c.bump(42, Timestamp::new(2, 0));
//! assert_eq!(c.count(&42, Timestamp::new(3, 0)), 3);
//! ```
//!
//! # Quick start: KeyIndexed
//!
//! ```
//! use flowscope::correlate::KeyIndexed;
//! use flowscope::Timestamp;
//! use std::time::Duration;
//!
//! let mut q: KeyIndexed<u16, String> = KeyIndexed::new(Duration::from_secs(5), 1024);
//! q.insert(0x1234, "example.com".to_string(), Timestamp::new(0, 0));
//! assert_eq!(q.get(&0x1234, Timestamp::new(1, 0)).map(|s| s.as_str()), Some("example.com"));
//!
//! // Past TTL — entry is logically expired.
//! q.evict_expired(Timestamp::new(10, 0));
//! assert!(q.get(&0x1234, Timestamp::new(10, 0)).is_none());
//! ```
// FlowStateMap defaults its key type to `crate::extract::FiveTupleKey`,
// which only exists under the `extractors` feature. Gate the module
// here so consumers running with `--no-default-features` (no extractors)
// still get the rest of `correlate`.
pub use TimeBucketedCounter;
pub use ;
pub use Ewma;
pub use FlowStateMap;
pub use KeyIndexed;
pub use ;
pub use TimeBucketedSet;
pub use TopK;