1use aerosocket_core::error::Error;
7use std::fmt;
8use std::io;
9
10#[derive(Debug, thiserror::Error)]
12pub enum ServerError {
13 #[error("Configuration error: {0}")]
15 Config(#[from] ConfigError),
16
17 #[error("Connection error: {0}")]
19 Connection(#[from] ConnectionError),
20
21 #[error("Handshake error: {0}")]
23 Handshake(#[from] HandshakeError),
24
25 #[error("Protocol error: {0}")]
27 Protocol(#[from] ProtocolError),
28
29 #[error("Transport error: {0}")]
31 Transport(#[from] TransportError),
32
33 #[error("Handler error: {0}")]
35 Handler(#[from] HandlerError),
36
37 #[error("Manager error: {0}")]
39 Manager(#[from] ManagerError),
40
41 #[error("I/O error: {0}")]
43 Io(#[from] io::Error),
44
45 #[error("Core error: {0}")]
47 Core(#[from] Error),
48
49 #[error("Operation timed out after {duration:?}")]
51 Timeout { duration: std::time::Duration },
52
53 #[error("Capacity exceeded: {0}")]
55 Capacity(String),
56
57 #[error("Authentication failed: {0}")]
59 Authentication(String),
60
61 #[error("Access denied: {0}")]
63 Authorization(String),
64
65 #[error("Rate limit exceeded: {0}")]
67 RateLimit(String),
68
69 #[error("Internal server error: {0}")]
71 Internal(String),
72}
73
74#[derive(Debug, thiserror::Error)]
76pub enum ConfigError {
77 #[error("Invalid bind address: {0}")]
79 InvalidBindAddress(String),
80
81 #[error("Invalid timeout value: {0}")]
83 InvalidTimeout(String),
84
85 #[error("Invalid buffer size: {0}")]
87 InvalidBufferSize(String),
88
89 #[error("Missing required configuration: {0}")]
91 MissingRequired(String),
92
93 #[error("Invalid TLS configuration: {0}")]
95 InvalidTlsConfig(String),
96
97 #[error("Invalid compression configuration: {0}")]
99 InvalidCompressionConfig(String),
100}
101
102#[derive(Debug, thiserror::Error)]
104pub enum ConnectionError {
105 #[error("Connection closed")]
107 Closed,
108
109 #[error("Connection timed out")]
111 TimedOut,
112
113 #[error("Connection reset by peer")]
115 Reset,
116
117 #[error("Connection refused")]
119 Refused,
120
121 #[error("Connection limit exceeded: {current}/{max}")]
123 LimitExceeded { current: usize, max: usize },
124
125 #[error("Invalid connection state: {state}")]
127 InvalidState { state: String },
128
129 #[error("Connection not found: {id}")]
131 NotFound { id: u64 },
132
133 #[error("Connection already exists: {id}")]
135 AlreadyExists { id: u64 },
136}
137
138#[derive(Debug, thiserror::Error)]
140pub enum HandshakeError {
141 #[error("Invalid HTTP method: {method}")]
143 InvalidMethod { method: String },
144
145 #[error("Invalid WebSocket version: {version}")]
147 InvalidVersion { version: String },
148
149 #[error("Missing required header: {header}")]
151 MissingHeader { header: String },
152
153 #[error("Invalid header value for '{header}': {value}")]
155 InvalidHeaderValue { header: String, value: String },
156
157 #[error("Unsupported subprotocol: {protocol}")]
159 UnsupportedSubprotocol { protocol: String },
160
161 #[error("Unsupported extension: {extension}")]
163 UnsupportedExtension { extension: String },
164
165 #[error("Invalid origin: {origin}")]
167 InvalidOrigin { origin: String },
168
169 #[error("WebSocket key mismatch")]
171 KeyMismatch,
172
173 #[error("Handshake authentication failed: {reason}")]
175 AuthenticationFailed { reason: String },
176}
177
178#[derive(Debug, thiserror::Error)]
180pub enum ProtocolError {
181 #[error("Invalid WebSocket opcode: {opcode}")]
183 InvalidOpcode { opcode: u8 },
184
185 #[error("Invalid frame format: {reason}")]
187 InvalidFrame { reason: String },
188
189 #[error("Frame too large: {size}/{max_size}")]
191 FrameTooLarge { size: usize, max_size: usize },
192
193 #[error("Message too large: {size}/{max_size}")]
195 MessageTooLarge { size: usize, max_size: usize },
196
197 #[error("Invalid UTF-8 sequence in text frame")]
199 InvalidUtf8,
200
201 #[error("Control frame fragmented")]
203 FragmentedControlFrame,
204
205 #[error("Invalid continuation frame")]
207 InvalidContinuation,
208
209 #[error("Client frames must be masked")]
211 MaskingRequired,
212
213 #[error("Server frames must not be masked")]
215 MaskingForbidden,
216
217 #[error("Reserved bits are set")]
219 ReservedBitsSet,
220}
221
222#[derive(Debug, thiserror::Error)]
224pub enum TransportError {
225 #[error("Failed to accept connection: {0}")]
227 AcceptFailed(String),
228
229 #[error("Failed to bind to address: {0}")]
231 BindFailed(String),
232
233 #[error("Read failed: {0}")]
235 ReadFailed(String),
236
237 #[error("Write failed: {0}")]
239 WriteFailed(String),
240
241 #[error("Flush failed: {0}")]
243 FlushFailed(String),
244
245 #[error("Close failed: {0}")]
247 CloseFailed(String),
248
249 #[error("TLS error: {0}")]
251 Tls(String),
252}
253
254#[derive(Debug, thiserror::Error)]
256pub enum HandlerError {
257 #[error("Handler panicked: {0}")]
259 Panicked(String),
260
261 #[error("Handler returned error: {0}")]
263 ReturnedError(String),
264
265 #[error("Handler timed out after {duration:?}")]
267 Timeout { duration: std::time::Duration },
268
269 #[error("Handler not found for path: {path}")]
271 NotFound { path: String },
272}
273
274#[derive(Debug, thiserror::Error)]
276pub enum ManagerError {
277 #[error("Connection manager not initialized")]
279 NotInitialized,
280
281 #[error("Connection manager is shutting down")]
283 Shutdown,
284
285 #[error("Invalid connection ID: {id}")]
287 InvalidId { id: u64 },
288
289 #[error("Operation failed: {0}")]
291 OperationFailed(String),
292}
293
294impl From<ServerError> for Error {
295 fn from(err: ServerError) -> Self {
296 Error::Other(err.to_string())
297 }
298}
299
300#[derive(Debug, Clone)]
302pub struct ErrorContext {
303 pub connection_id: Option<u64>,
305 pub remote_addr: Option<std::net::SocketAddr>,
307 pub operation: Option<String>,
309 pub context: std::collections::HashMap<String, String>,
311}
312
313impl ErrorContext {
314 pub fn new() -> Self {
316 Self {
317 connection_id: None,
318 remote_addr: None,
319 operation: None,
320 context: std::collections::HashMap::new(),
321 }
322 }
323
324 pub fn with_connection_id(mut self, id: u64) -> Self {
326 self.connection_id = Some(id);
327 self
328 }
329
330 pub fn with_remote_addr(mut self, addr: std::net::SocketAddr) -> Self {
332 self.remote_addr = Some(addr);
333 self
334 }
335
336 pub fn with_operation(mut self, op: impl Into<String>) -> Self {
338 self.operation = Some(op.into());
339 self
340 }
341
342 pub fn with_context(mut self, key: impl Into<String>, value: impl Into<String>) -> Self {
344 self.context.insert(key.into(), value.into());
345 self
346 }
347}
348
349impl Default for ErrorContext {
350 fn default() -> Self {
351 Self::new()
352 }
353}
354
355pub type ContextResult<T> = Result<T, ContextError>;
357
358#[derive(Debug)]
360pub struct ContextError {
361 pub error: ServerError,
363 pub context: ErrorContext,
365}
366
367impl fmt::Display for ContextError {
368 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
369 write!(f, "{}", self.error)?;
370
371 if let Some(id) = self.context.connection_id {
372 write!(f, " (connection: {})", id)?;
373 }
374
375 if let Some(addr) = self.context.remote_addr {
376 write!(f, " (remote: {})", addr)?;
377 }
378
379 if let Some(op) = &self.context.operation {
380 write!(f, " (operation: {})", op)?;
381 }
382
383 if !self.context.context.is_empty() {
384 write!(f, " (context: {:?})", self.context.context)?;
385 }
386
387 Ok(())
388 }
389}
390
391impl std::error::Error for ContextError {
392 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
393 Some(&self.error)
394 }
395}
396
397#[cfg(feature = "logging")]
399pub mod logging {
400 use super::*;
401 use tracing::{error, warn, info, debug, trace, instrument, Level};
402
403 pub fn init_default() {
405 tracing_subscriber::fmt()
406 .with_max_level(Level::INFO)
407 .init();
408 }
409
410 pub fn init_with_level(level: Level) {
412 tracing_subscriber::fmt()
413 .with_max_level(level)
414 .init();
415 }
416
417 #[instrument]
419 pub fn log_server_start(config: &crate::config::ServerConfig) {
420 info!(
421 bind_address = %config.bind_address,
422 max_connections = config.max_connections,
423 max_frame_size = config.max_frame_size,
424 max_message_size = config.max_message_size,
425 handshake_timeout = ?config.handshake_timeout,
426 idle_timeout = ?config.idle_timeout,
427 "WebSocket server starting"
428 );
429 }
430
431 #[instrument]
433 pub fn log_server_shutdown() {
434 info!("WebSocket server shutting down");
435 }
436
437 #[instrument]
439 pub fn log_connection_established(id: u64, remote_addr: std::net::SocketAddr) {
440 info!(
441 connection_id = id,
442 remote_addr = %remote_addr,
443 "WebSocket connection established"
444 );
445 }
446
447 #[instrument]
449 pub fn log_connection_closed(id: u64, reason: &str) {
450 info!(
451 connection_id = id,
452 reason = reason,
453 "WebSocket connection closed"
454 );
455 }
456
457 #[instrument]
459 pub fn log_message_received(id: u64, message_type: &str, size: usize) {
460 trace!(
461 connection_id = id,
462 message_type = message_type,
463 size = size,
464 "Message received"
465 );
466 }
467
468 #[instrument]
470 pub fn log_message_sent(id: u64, message_type: &str, size: usize) {
471 trace!(
472 connection_id = id,
473 message_type = message_type,
474 size = size,
475 "Message sent"
476 );
477 }
478
479 #[instrument]
481 pub fn log_error(error: &ContextError) {
482 error!(
483 error = %error,
484 connection_id = ?error.context.connection_id,
485 remote_addr = ?error.context.remote_addr,
486 operation = ?error.context.operation,
487 "Server error occurred"
488 );
489 }
490
491 #[instrument]
493 pub fn log_warning(message: &str, context: &ErrorContext) {
494 warn!(
495 message = message,
496 connection_id = ?context.connection_id,
497 remote_addr = ?context.remote_addr,
498 operation = ?context.operation,
499 "Server warning"
500 );
501 }
502
503 #[instrument]
505 pub fn log_performance_metrics(stats: &crate::manager::ManagerStats) {
506 info!(
507 active_connections = stats.active_connections,
508 total_connections = stats.total_connections,
509 timeout_closures = stats.timeout_closures,
510 error_closures = stats.error_closures,
511 normal_closures = stats.normal_closures,
512 peak_connections = stats.peak_connections,
513 "Performance metrics"
514 );
515 }
516}
517
518#[cfg(not(feature = "logging"))]
520pub mod logging {
521 use super::*;
522
523 pub fn init_default() {
525 }
527
528 pub fn init_with_level(_level: log::Level) {
530 }
532
533 pub fn log_server_start(_config: &crate::config::ServerConfig) {
535 }
537
538 pub fn log_server_shutdown() {
540 }
542
543 pub fn log_connection_established(_id: u64, _remote_addr: std::net::SocketAddr) {
545 }
547
548 pub fn log_connection_closed(_id: u64, _reason: &str) {
550 }
552
553 pub fn log_message_received(_id: u64, _message_type: &str, _size: usize) {
555 }
557
558 pub fn log_message_sent(_id: u64, _message_type: &str, _size: usize) {
560 }
562
563 pub fn log_error(_error: &ContextError) {
565 }
567
568 pub fn log_warning(_message: &str, _context: &ErrorContext) {
570 }
572
573 pub fn log_performance_metrics(_stats: &crate::manager::ManagerStats) {
575 }
577}