Skip to main content

eggress_protocol_socks/
detector.rs

1use eggress_core::detect::{DetectResult, ProtocolDetector};
2use eggress_core::ProtocolId;
3
4/// Protocol identifier for SOCKS4.
5pub const SOCKS4_PROTOCOL_ID: ProtocolId = ProtocolId::Socks4;
6
7/// Detector for SOCKS4/4a protocol.
8///
9/// SOCKS4 requests always start with version byte 0x04.
10pub struct Socks4Detector;
11
12impl ProtocolDetector for Socks4Detector {
13    fn id(&self) -> ProtocolId {
14        SOCKS4_PROTOCOL_ID
15    }
16
17    fn detect(&self, prefix: &[u8]) -> DetectResult {
18        if prefix.is_empty() {
19            DetectResult::NeedMore { minimum: 1 }
20        } else if prefix[0] == 0x04 {
21            DetectResult::Match { confidence: 100 }
22        } else {
23            DetectResult::NoMatch
24        }
25    }
26}
27
28#[cfg(test)]
29mod tests {
30    use super::*;
31
32    #[test]
33    fn test_detect_empty() {
34        let detector = Socks4Detector;
35        assert_eq!(detector.detect(b""), DetectResult::NeedMore { minimum: 1 });
36    }
37
38    #[test]
39    fn test_detect_match() {
40        let detector = Socks4Detector;
41        assert_eq!(
42            detector.detect(b"\x04"),
43            DetectResult::Match { confidence: 100 }
44        );
45    }
46
47    #[test]
48    fn test_detect_match_full_header() {
49        let detector = Socks4Detector;
50        // Full SOCKS4 CONNECT header
51        assert_eq!(
52            detector.detect(b"\x04\x01\x00\x50\x7f\x00\x00\x01"),
53            DetectResult::Match { confidence: 100 }
54        );
55    }
56
57    #[test]
58    fn test_detect_no_match() {
59        let detector = Socks4Detector;
60        assert_eq!(detector.detect(b"\x05"), DetectResult::NoMatch);
61        assert_eq!(detector.detect(b"\x03"), DetectResult::NoMatch);
62    }
63
64    #[test]
65    fn test_detector_id() {
66        let detector = Socks4Detector;
67        assert_eq!(detector.id(), ProtocolId::Socks4);
68    }
69}