bitfold_core/
interceptor.rs

1//! Packet interception for custom processing.
2//!
3//! This module provides a trait for intercepting raw UDP packets before/after processing.
4//! Useful for custom encryption, logging, packet inspection, and analytics.
5
6use std::net::SocketAddr;
7
8/// Trait for intercepting packets before/after processing.
9///
10/// Interceptors can inspect, modify, or drop packets at the raw UDP level.
11/// This is useful for implementing custom encryption, logging, analytics, or packet inspection.
12///
13/// # Examples
14/// ```
15/// use std::net::SocketAddr;
16/// use bitfold_core::interceptor::Interceptor;
17///
18/// struct LoggingInterceptor;
19///
20/// impl Interceptor for LoggingInterceptor {
21///     fn on_receive(&mut self, _addr: &SocketAddr, data: &mut [u8]) -> bool {
22///         println!("Received {} bytes", data.len());
23///         true // Continue processing
24///     }
25///
26///     fn on_send(&mut self, _addr: &SocketAddr, data: &mut Vec<u8>) -> bool {
27///         println!("Sending {} bytes", data.len());
28///         true // Continue sending
29///     }
30/// }
31/// ```
32pub trait Interceptor: Send {
33    /// Called when a packet is received from the network, before protocol processing.
34    ///
35    /// # Arguments
36    /// * `addr` - The source address of the packet
37    /// * `data` - The raw packet data (mutable, can be modified)
38    ///
39    /// # Returns
40    /// * `true` - Continue processing the packet
41    /// * `false` - Drop the packet (do not process)
42    fn on_receive(&mut self, addr: &SocketAddr, data: &mut [u8]) -> bool;
43
44    /// Called when a packet is about to be sent to the network, after protocol encoding.
45    ///
46    /// # Arguments
47    /// * `addr` - The destination address of the packet
48    /// * `data` - The raw packet data (mutable, can be modified or resized)
49    ///
50    /// # Returns
51    /// * `true` - Continue sending the packet
52    /// * `false` - Drop the packet (do not send)
53    fn on_send(&mut self, addr: &SocketAddr, data: &mut Vec<u8>) -> bool;
54}
55
56/// No-op interceptor that passes all packets through unchanged.
57///
58/// This is the default interceptor when none is specified.
59#[derive(Debug, Clone, Copy)]
60pub struct NoOpInterceptor;
61
62impl Interceptor for NoOpInterceptor {
63    fn on_receive(&mut self, _addr: &SocketAddr, _data: &mut [u8]) -> bool {
64        true
65    }
66
67    fn on_send(&mut self, _addr: &SocketAddr, _data: &mut Vec<u8>) -> bool {
68        true
69    }
70}
71
72#[cfg(test)]
73mod tests {
74    use std::net::{IpAddr, Ipv4Addr};
75
76    use super::*;
77
78    struct CountingInterceptor {
79        received: usize,
80        sent: usize,
81    }
82
83    impl Interceptor for CountingInterceptor {
84        fn on_receive(&mut self, _addr: &SocketAddr, _data: &mut [u8]) -> bool {
85            self.received += 1;
86            true
87        }
88
89        fn on_send(&mut self, _addr: &SocketAddr, _data: &mut Vec<u8>) -> bool {
90            self.sent += 1;
91            true
92        }
93    }
94
95    #[test]
96    fn test_counting_interceptor() {
97        let mut interceptor = CountingInterceptor { received: 0, sent: 0 };
98        let addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080);
99
100        let mut data = vec![1, 2, 3];
101        assert!(interceptor.on_receive(&addr, &mut data));
102        assert_eq!(interceptor.received, 1);
103
104        assert!(interceptor.on_send(&addr, &mut data));
105        assert_eq!(interceptor.sent, 1);
106    }
107
108    struct DroppingInterceptor;
109
110    impl Interceptor for DroppingInterceptor {
111        fn on_receive(&mut self, _addr: &SocketAddr, _data: &mut [u8]) -> bool {
112            false // Drop all received packets
113        }
114
115        fn on_send(&mut self, _addr: &SocketAddr, _data: &mut Vec<u8>) -> bool {
116            false // Drop all sent packets
117        }
118    }
119
120    #[test]
121    fn test_dropping_interceptor() {
122        let mut interceptor = DroppingInterceptor;
123        let addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080);
124
125        let mut data = vec![1, 2, 3];
126        assert!(!interceptor.on_receive(&addr, &mut data));
127        assert!(!interceptor.on_send(&addr, &mut data));
128    }
129
130    struct ModifyingInterceptor;
131
132    impl Interceptor for ModifyingInterceptor {
133        fn on_receive(&mut self, _addr: &SocketAddr, data: &mut [u8]) -> bool {
134            // XOR decrypt
135            for byte in data.iter_mut() {
136                *byte ^= 0x55;
137            }
138            true
139        }
140
141        fn on_send(&mut self, _addr: &SocketAddr, data: &mut Vec<u8>) -> bool {
142            // XOR encrypt
143            for byte in data.iter_mut() {
144                *byte ^= 0x55;
145            }
146            true
147        }
148    }
149
150    #[test]
151    fn test_modifying_interceptor() {
152        let mut interceptor = ModifyingInterceptor;
153        let addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080);
154
155        let mut data = vec![0xAA, 0xBB, 0xCC];
156        let original = data.clone();
157
158        assert!(interceptor.on_send(&addr, &mut data));
159        assert_ne!(data, original); // Should be modified
160
161        assert!(interceptor.on_receive(&addr, &mut data));
162        assert_eq!(data, original); // Should be decrypted back
163    }
164
165    #[test]
166    fn test_noop_interceptor() {
167        let mut interceptor = NoOpInterceptor;
168        let addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080);
169
170        let mut data = vec![1, 2, 3];
171        let original = data.clone();
172
173        assert!(interceptor.on_receive(&addr, &mut data));
174        assert_eq!(data, original);
175
176        assert!(interceptor.on_send(&addr, &mut data));
177        assert_eq!(data, original);
178    }
179}