nntp_proxy/
constants.rs

1//! Constants used throughout the NNTP proxy
2//!
3//! This module centralizes magic numbers and configuration values
4//! to improve maintainability and reduce duplication.
5
6use std::time::Duration;
7
8/// Buffer size constants
9///
10/// All buffer sizes are carefully chosen for NNTP workloads:
11/// - Commands are small (< 512 bytes)
12/// - Articles range from 1KB to 100KB typically
13/// - Pooled buffers (256KB) handle most articles in one read
14pub mod buffer {
15    // Buffer pool configuration
16
17    /// Size of each pooled buffer (256KB)
18    /// Large enough to handle most Usenet articles in a single read
19    pub const POOL: usize = 256 * 1024;
20
21    /// Number of buffers in the buffer pool
22    /// Sized for ~32 concurrent connections with one buffer each
23    pub const POOL_COUNT: usize = 32;
24
25    // Command and response limits
26
27    /// Maximum command line size (512 bytes)
28    /// NNTP commands are typically small: "ARTICLE <msgid@example.com>"
29    pub const COMMAND: usize = 512;
30
31    /// Maximum size for a single response (1MB)
32    /// Prevents memory exhaustion from malicious/malformed responses
33    pub const RESPONSE_MAX: usize = 1024 * 1024;
34
35    /// Initial capacity for response accumulation buffers (8KB)
36    /// Sized for typical status lines and small responses
37    pub const RESPONSE_INITIAL: usize = 8192;
38
39    // Streaming configuration
40
41    /// Chunk size for streaming responses (64KB)
42    /// Balance between latency and throughput
43    pub const STREAM_CHUNK: usize = 65536;
44}
45
46/// Socket buffer size constants
47pub mod socket {
48    /// TCP socket receive buffer size for high-throughput transfers (16MB)
49    pub const HIGH_THROUGHPUT_RECV_BUFFER: usize = 16 * 1024 * 1024;
50
51    /// TCP socket send buffer size for high-throughput transfers (16MB)
52    pub const HIGH_THROUGHPUT_SEND_BUFFER: usize = 16 * 1024 * 1024;
53
54    /// TCP socket receive buffer size for connection pools (4MB)
55    /// Smaller than high-throughput to avoid memory exhaustion with many connections
56    pub const POOL_RECV_BUFFER: usize = 4 * 1024 * 1024;
57
58    /// TCP socket send buffer size for connection pools (4MB)
59    pub const POOL_SEND_BUFFER: usize = 4 * 1024 * 1024;
60}
61
62/// Timeout constants
63pub mod timeout {
64    use super::Duration;
65
66    /// Timeout for reading responses from backend servers
67    pub const BACKEND_READ: Duration = Duration::from_secs(30);
68
69    /// Timeout for executing a command on backend
70    pub const COMMAND_EXECUTION: Duration = Duration::from_secs(60);
71
72    /// Connection timeout for backend connections
73    pub const CONNECTION: Duration = Duration::from_secs(10);
74}
75
76/// Connection pool constants
77pub mod pool {
78    use super::Duration;
79
80    /// Default maximum connections per backend pool
81    pub const DEFAULT_MAX_CONNECTIONS: usize = 10;
82
83    /// Default minimum idle connections to maintain
84    pub const DEFAULT_MIN_IDLE: usize = 2;
85
86    /// Connection pool timeout for getting a connection
87    pub const GET_TIMEOUT_SECS: u64 = 5;
88
89    /// Buffer size for TCP peek during health checks
90    /// Only 1 byte needed to detect if connection is readable/closed
91    pub const TCP_PEEK_BUFFER_SIZE: usize = 1;
92
93    /// Health check timeout - how long to wait for DATE command response
94    pub const HEALTH_CHECK_TIMEOUT: Duration = Duration::from_secs(2);
95
96    /// Buffer size for reading health check responses
97    pub const HEALTH_CHECK_BUFFER_SIZE: usize = 512;
98
99    /// DATE command bytes sent during health check
100    pub const DATE_COMMAND: &[u8] = b"DATE\r\n";
101
102    /// Expected prefix of DATE command response (NNTP 111 response code)
103    pub const EXPECTED_DATE_RESPONSE_PREFIX: &str = "111 ";
104
105    /// Minimum recommended keep-alive interval in seconds
106    /// Values below this may cause excessive health check traffic
107    pub const MIN_RECOMMENDED_KEEPALIVE_SECS: u64 = 30;
108
109    /// Maximum recommended keep-alive interval in seconds (5 minutes)
110    /// Values above this may not detect stale connections quickly enough
111    pub const MAX_RECOMMENDED_KEEPALIVE_SECS: u64 = 300;
112
113    /// Maximum number of idle connections to check per health check cycle
114    /// Checking too many at once can temporarily starve the pool
115    pub const MAX_CONNECTIONS_PER_HEALTH_CHECK_CYCLE: usize = 5;
116
117    /// Timeout when attempting to get a connection for health checking (milliseconds)
118    /// Short timeout to avoid blocking if pool is busy
119    pub const HEALTH_CHECK_POOL_TIMEOUT_MS: u64 = 100;
120}
121
122/// Per-command routing constants
123pub mod per_command_routing {
124    /// Number of chunks to read ahead when checking for response terminator
125    pub const TERMINATOR_LOOKAHEAD_CHUNKS: usize = 4;
126
127    /// Maximum number of bytes to check for spanning terminator
128    pub const MAX_TERMINATOR_SPAN_CHECK: usize = 9;
129}
130
131/// Stateless proxy protocol constants
132pub mod stateless_proxy {
133    pub const NNTP_BACKEND_UNAVAILABLE: &[u8] = b"400 Backend server unavailable\r\n";
134    pub const NNTP_COMMAND_NOT_SUPPORTED: &[u8] =
135        b"500 Command not supported by this proxy (stateless proxy mode)\r\n";
136
137    /// Prewarming configuration constants
138    pub const PREWARMING_BATCH_SIZE: usize = 5; // Create connections in batches of 5
139    pub const BATCH_DELAY_MS: u64 = 100; // Wait 100ms between prewarming batches
140}
141
142#[cfg(test)]
143mod tests {
144    use super::*;
145
146    #[test]
147    fn test_buffer_sizes() {
148        // Compile-time assertions for buffer size relationships
149        const _: () = assert!(buffer::RESPONSE_INITIAL >= buffer::COMMAND);
150        const _: () = assert!(buffer::RESPONSE_MAX > buffer::RESPONSE_INITIAL);
151        const _: () = assert!(buffer::POOL >= buffer::STREAM_CHUNK);
152    }
153
154    #[test]
155    fn test_timeouts() {
156        assert!(timeout::BACKEND_READ.as_secs() > 0);
157        assert!(timeout::COMMAND_EXECUTION >= timeout::BACKEND_READ);
158    }
159}