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}