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::{debug, error, info, instrument, trace, warn, Level};
402
403 pub fn init_default() {
405 tracing_subscriber::fmt().with_max_level(Level::INFO).init();
406 }
407
408 pub fn init_with_level(level: Level) {
410 tracing_subscriber::fmt().with_max_level(level).init();
411 }
412
413 #[instrument]
415 pub fn log_server_start(config: &crate::config::ServerConfig) {
416 info!(
417 bind_address = %config.bind_address,
418 max_connections = config.max_connections,
419 max_frame_size = config.max_frame_size,
420 max_message_size = config.max_message_size,
421 handshake_timeout = ?config.handshake_timeout,
422 idle_timeout = ?config.idle_timeout,
423 "WebSocket server starting"
424 );
425 }
426
427 #[instrument]
429 pub fn log_server_shutdown() {
430 info!("WebSocket server shutting down");
431 }
432
433 #[instrument]
435 pub fn log_connection_established(id: u64, remote_addr: std::net::SocketAddr) {
436 info!(
437 connection_id = id,
438 remote_addr = %remote_addr,
439 "WebSocket connection established"
440 );
441 }
442
443 #[instrument]
445 pub fn log_connection_closed(id: u64, reason: &str) {
446 info!(
447 connection_id = id,
448 reason = reason,
449 "WebSocket connection closed"
450 );
451 }
452
453 #[instrument]
455 pub fn log_message_received(id: u64, message_type: &str, size: usize) {
456 trace!(
457 connection_id = id,
458 message_type = message_type,
459 size = size,
460 "Message received"
461 );
462 }
463
464 #[instrument]
466 pub fn log_message_sent(id: u64, message_type: &str, size: usize) {
467 trace!(
468 connection_id = id,
469 message_type = message_type,
470 size = size,
471 "Message sent"
472 );
473 }
474
475 #[instrument]
477 pub fn log_error(error: &ContextError) {
478 error!(
479 error = %error,
480 connection_id = ?error.context.connection_id,
481 remote_addr = ?error.context.remote_addr,
482 operation = ?error.context.operation,
483 "Server error occurred"
484 );
485 }
486
487 #[instrument]
489 pub fn log_warning(message: &str, context: &ErrorContext) {
490 warn!(
491 message = message,
492 connection_id = ?context.connection_id,
493 remote_addr = ?context.remote_addr,
494 operation = ?context.operation,
495 "Server warning"
496 );
497 }
498
499 #[instrument]
501 pub fn log_performance_metrics(stats: &crate::manager::ManagerStats) {
502 info!(
503 active_connections = stats.active_connections,
504 total_connections = stats.total_connections,
505 timeout_closures = stats.timeout_closures,
506 error_closures = stats.error_closures,
507 normal_closures = stats.normal_closures,
508 peak_connections = stats.peak_connections,
509 "Performance metrics"
510 );
511 }
512}
513
514#[cfg(not(feature = "logging"))]
516pub mod logging {
517 use super::*;
518
519 pub fn init_default() {
521 }
523
524 pub fn init_with_level(_level: log::Level) {
526 }
528
529 pub fn log_server_start(_config: &crate::config::ServerConfig) {
531 }
533
534 pub fn log_server_shutdown() {
536 }
538
539 pub fn log_connection_established(_id: u64, _remote_addr: std::net::SocketAddr) {
541 }
543
544 pub fn log_connection_closed(_id: u64, _reason: &str) {
546 }
548
549 pub fn log_message_received(_id: u64, _message_type: &str, _size: usize) {
551 }
553
554 pub fn log_message_sent(_id: u64, _message_type: &str, _size: usize) {
556 }
558
559 pub fn log_error(_error: &ContextError) {
561 }
563
564 pub fn log_warning(_message: &str, _context: &ErrorContext) {
566 }
568
569 pub fn log_performance_metrics(_stats: &crate::manager::ManagerStats) {
571 }
573}