rvoip_client_core/
error.rs

1//! Error types and handling for the client-core library
2//! 
3//! This module defines all error types that can occur during client operations
4//! and provides guidance on how to handle them.
5//! 
6//! # Error Categories
7//! 
8//! Errors are categorized to help with recovery strategies:
9//! 
10//! - **Configuration Errors** - Invalid settings, can't recover without fixing config
11//! - **Network Errors** - Temporary network issues, usually recoverable with retry
12//! - **Protocol Errors** - SIP protocol violations, may need different approach
13//! - **Media Errors** - Audio/RTP issues, might need codec renegotiation
14//! - **State Errors** - Invalid operation for current state, check state first
15//! 
16//! # Error Handling Guide
17//! 
18//! ## Basic Pattern
19//! 
20//! ```rust
21//! # use rvoip_client_core::{Client, ClientError};
22//! # use std::sync::Arc;
23//! # async fn example(client: Arc<Client>) {
24//! match client.make_call(
25//!     "sip:alice@example.com".to_string(),
26//!     "sip:bob@example.com".to_string(),
27//!     None
28//! ).await {
29//!     Ok(call_id) => {
30//!         println!("Call started: {}", call_id);
31//!     }
32//!     Err(ClientError::NetworkError { reason }) => {
33//!         eprintln!("Network problem: {}", reason);
34//!         // Retry after checking network connectivity
35//!     }
36//!     Err(ClientError::InvalidConfiguration { field, reason }) => {
37//!         eprintln!("Config error in {}: {}", field, reason);
38//!         // Fix configuration before retrying
39//!     }
40//!     Err(e) => {
41//!         eprintln!("Unexpected error: {}", e);
42//!         // Log and notify user
43//!     }
44//! }
45//! # }
46//! ```
47//! 
48//! ## Recovery Strategies
49//! 
50//! ### Network Errors
51//! 
52//! Network errors are often temporary. Implement exponential backoff:
53//! 
54//! ```rust
55//! # use rvoip_client_core::{Client, ClientError};
56//! # use std::sync::Arc;
57//! # use std::time::Duration;
58//! # async fn example(client: Arc<Client>) -> Result<(), Box<dyn std::error::Error>> {
59//! async fn with_retry<T, F, Fut>(
60//!     mut operation: F,
61//!     max_attempts: u32,
62//! ) -> Result<T, ClientError>
63//! where
64//!     F: FnMut() -> Fut,
65//!     Fut: std::future::Future<Output = Result<T, ClientError>>,
66//! {
67//!     let mut attempt = 0;
68//!     let mut delay = Duration::from_millis(100);
69//!     
70//!     loop {
71//!         match operation().await {
72//!             Ok(result) => return Ok(result),
73//!             Err(e) if e.is_recoverable() && attempt < max_attempts => {
74//!                 attempt += 1;
75//!                 tokio::time::sleep(delay).await;
76//!                 delay *= 2; // Exponential backoff
77//!             }
78//!             Err(e) => return Err(e),
79//!         }
80//!     }
81//! }
82//! 
83//! // Use with any operation
84//! let call_id = with_retry(|| async {
85//!     client.make_call(
86//!         "sip:alice@example.com".to_string(),
87//!         "sip:bob@example.com".to_string(),
88//!         None
89//!     ).await
90//! }, 3).await?;
91//! # Ok(())
92//! # }
93//! ```
94//! 
95//! ### Registration Errors
96//! 
97//! Handle authentication and server errors:
98//! 
99//! ```rust
100//! # use rvoip_client_core::{Client, ClientError};
101//! # use std::sync::Arc;
102//! # use std::time::Duration;
103//! # async fn example(client: Arc<Client>) -> Result<(), Box<dyn std::error::Error>> {
104//! match client.register_simple(
105//!     "sip:alice@example.com",
106//!     &"127.0.0.1:5060".parse().unwrap(),
107//!     Duration::from_secs(3600)
108//! ).await {
109//!     Ok(()) => {
110//!         println!("Registered successfully");
111//!     }
112//!     Err(e) if e.is_auth_error() => {
113//!         // Prompt user for credentials
114//!         println!("Please check your username and password");
115//!     }
116//!     Err(ClientError::RegistrationFailed { reason }) => {
117//!         if reason.contains("timeout") {
118//!             // Server might be down
119//!             println!("Server not responding, try again later");
120//!         } else if reason.contains("forbidden") {
121//!             // Account might be disabled
122//!             println!("Registration forbidden, contact support");
123//!         }
124//!     }
125//!     Err(e) => eprintln!("Registration error: {}", e),
126//! }
127//! # Ok(())
128//! # }
129//! ```
130//! 
131//! ### Call State Errors
132//! 
133//! Check state before operations:
134//! 
135//! ```rust
136//! # use rvoip_client_core::{Client, ClientError, CallId};
137//! # use std::sync::Arc;
138//! # async fn example(client: Arc<Client>, call_id: CallId) -> Result<(), Box<dyn std::error::Error>> {
139//! // Safe call control with state checking
140//! async fn safe_hold_call(client: &Arc<Client>, call_id: &CallId) -> Result<(), ClientError> {
141//!     // Get call info first
142//!     let info = client.get_call(call_id).await?;
143//!     
144//!     // Check if we can hold
145//!     match info.state {
146//!         rvoip_client_core::call::CallState::Connected => {
147//!             client.hold_call(call_id).await
148//!         }
149//!         rvoip_client_core::call::CallState::Failed => {
150//!             // Call failed, cannot hold
151//!             Err(ClientError::InvalidCallStateGeneric {
152//!                 expected: "Connected".to_string(),
153//!                 actual: "Failed".to_string(),
154//!             })
155//!         }
156//!         _ => {
157//!             Err(ClientError::InvalidCallStateGeneric {
158//!                 expected: "Connected".to_string(),
159//!                 actual: format!("{:?}", info.state),
160//!             })
161//!         }
162//!     }
163//! }
164//! 
165//! safe_hold_call(&client, &call_id).await?;
166//! # Ok(())
167//! # }
168//! ```
169//! 
170//! ### Media Errors
171//! 
172//! Handle codec and port allocation issues:
173//! 
174//! ```rust
175//! # use rvoip_client_core::{Client, ClientError, CallId};
176//! # use std::sync::Arc;
177//! # async fn example(client: Arc<Client>, call_id: CallId) -> Result<(), Box<dyn std::error::Error>> {
178//! match client.establish_media(&call_id, "remote.example.com:30000").await {
179//!     Ok(_) => println!("Media established"),
180//!     Err(ClientError::MediaNegotiationFailed { reason }) => {
181//!         if reason.contains("codec") {
182//!             // Try with different codec
183//!             println!("Codec mismatch, trying fallback");
184//!         } else if reason.contains("port") {
185//!             // Port allocation failed
186//!             println!("No available media ports");
187//!         }
188//!     }
189//!     Err(e) => eprintln!("Media setup failed: {}", e),
190//! }
191//! # Ok(())
192//! # }
193//! ```
194//! 
195//! ## Error Context
196//! 
197//! Always log errors with context for debugging:
198//! 
199//! ```rust
200//! # use rvoip_client_core::{Client, ClientError, CallId};
201//! # use std::sync::Arc;
202//! # let call_id = CallId::new_v4();
203//! # async fn example(client: Arc<Client>, call_id: CallId) {
204//! use tracing::{error, warn, info};
205//! 
206//! match client.answer_call(&call_id).await {
207//!     Ok(_) => info!(call_id = %call_id, "Call answered successfully"),
208//!     Err(e) => {
209//!         error!(
210//!             call_id = %call_id,
211//!             error = %e,
212//!             error_type = ?e,
213//!             category = e.category(),
214//!             "Failed to answer call"
215//!         );
216//!         
217//!         // Take appropriate action based on error type
218//!         match e {
219//!             ClientError::CallNotFound { .. } => {
220//!                 // Call might have been cancelled
221//!             }
222//!             ClientError::MediaNegotiationFailed { .. } => {
223//!                 // Try to recover media session
224//!             }
225//!             _ => {
226//!                 // Generic error handling
227//!             }
228//!         }
229//!     }
230//! }
231//! # }
232//! ```
233//! 
234//! ## Error Categories Helper
235//! 
236//! Use the `category()` method to group errors for metrics:
237//! 
238//! ```rust
239//! # use rvoip_client_core::ClientError;
240//! # use std::collections::HashMap;
241//! # let errors: Vec<ClientError> = vec![];
242//! let mut error_counts: HashMap<&'static str, usize> = HashMap::new();
243//! 
244//! for error in errors {
245//!     *error_counts.entry(error.category()).or_insert(0) += 1;
246//! }
247//! 
248//! // Report metrics
249//! for (category, count) in error_counts {
250//!     println!("{}: {} errors", category, count);
251//! }
252//! ```
253
254use thiserror::Error;
255use uuid::Uuid;
256
257/// Result type alias for client-core operations
258pub type ClientResult<T> = Result<T, ClientError>;
259
260/// Comprehensive error types for SIP client operations
261/// 
262/// This enum covers all possible error conditions that can occur during
263/// VoIP client operations, organized by functional area for easy handling.
264/// 
265/// # Error Categories
266/// 
267/// - **Registration Errors** - SIP server registration and authentication issues
268/// - **Call Errors** - Call lifecycle and state management issues  
269/// - **Media Errors** - Audio, codecs, and RTP stream issues
270/// - **Network Errors** - Connectivity and transport problems
271/// - **Protocol Errors** - SIP protocol violations and parsing issues
272/// - **Configuration Errors** - Invalid settings and missing parameters
273/// - **System Errors** - Internal failures and resource limitations
274/// 
275/// # Examples
276/// 
277/// ```rust
278/// use rvoip_client_core::ClientError;
279/// 
280/// // Check error categories for appropriate handling
281/// let error = ClientError::registration_failed("Invalid credentials");
282/// assert_eq!(error.category(), "registration");
283/// 
284/// // Check authentication errors
285/// let auth_error = ClientError::authentication_failed("Invalid password");
286/// assert!(auth_error.is_auth_error());
287/// 
288/// // Create specific error types
289/// let timeout_error = ClientError::OperationTimeout { duration_ms: 5000 };
290/// assert!(timeout_error.is_recoverable());
291/// ```
292#[derive(Error, Debug, Clone)]
293pub enum ClientError {
294    /// Registration related errors
295    
296    /// Registration attempt failed due to server or authentication issues
297    /// 
298    /// This error occurs when the SIP REGISTER request is rejected by the server,
299    /// typically due to authentication failures, server errors, or network issues.
300    /// 
301    /// # Examples
302    /// 
303    /// ```rust
304    /// use rvoip_client_core::ClientError;
305    /// 
306    /// let error = ClientError::RegistrationFailed {
307    ///     reason: "401 Unauthorized - Invalid credentials".to_string()
308    /// };
309    /// 
310    /// assert_eq!(error.category(), "registration");
311    /// ```
312    #[error("Registration failed: {reason}")]
313    RegistrationFailed { 
314        /// Detailed reason for the registration failure
315        reason: String 
316    },
317
318    /// Client is not currently registered with any SIP server
319    /// 
320    /// This error occurs when attempting operations that require an active
321    /// registration (like making calls) when no registration is active.
322    /// 
323    /// # Examples
324    /// 
325    /// ```rust
326    /// use rvoip_client_core::ClientError;
327    /// 
328    /// let error = ClientError::NotRegistered;
329    /// assert!(error.is_auth_error());
330    /// ```
331    #[error("Not registered with server")]
332    NotRegistered,
333
334    /// SIP registration has expired and needs to be renewed
335    /// 
336    /// This error occurs when the registration lifetime has elapsed and
337    /// the server no longer considers this client registered.
338    /// 
339    /// # Examples
340    /// 
341    /// ```rust
342    /// use rvoip_client_core::ClientError;
343    /// 
344    /// let error = ClientError::RegistrationExpired;
345    /// assert!(error.is_auth_error());
346    /// assert_eq!(error.category(), "registration");
347    /// ```
348    #[error("Registration expired")]
349    RegistrationExpired,
350
351    /// SIP digest authentication failed
352    /// 
353    /// This error occurs when the server rejects the authentication credentials
354    /// provided during registration or call setup.
355    /// 
356    /// # Examples
357    /// 
358    /// ```rust
359    /// use rvoip_client_core::ClientError;
360    /// 
361    /// let error = ClientError::AuthenticationFailed {
362    ///     reason: "Wrong password for user alice".to_string()
363    /// };
364    /// 
365    /// assert!(error.is_auth_error());
366    /// ```
367    #[error("Authentication failed: {reason}")]
368    AuthenticationFailed { 
369        /// Specific reason for authentication failure
370        reason: String 
371    },
372
373    /// Call related errors
374
375    /// Attempted to operate on a call that doesn't exist
376    /// 
377    /// This error occurs when referencing a call ID that is not found
378    /// in the client's active call list.
379    /// 
380    /// # Examples
381    /// 
382    /// ```rust
383    /// use rvoip_client_core::ClientError;
384    /// use uuid::Uuid;
385    /// 
386    /// let call_id = Uuid::new_v4();
387    /// let error = ClientError::CallNotFound { call_id };
388    /// 
389    /// assert!(error.is_call_error());
390    /// assert_eq!(error.category(), "call");
391    /// ```
392    #[error("Call not found: {call_id}")]
393    CallNotFound { 
394        /// The call ID that was not found
395        call_id: Uuid 
396    },
397
398    /// Attempted to create a call with an ID that already exists
399    /// 
400    /// This error occurs when trying to create a new call with a call ID
401    /// that is already in use by another active call.
402    /// 
403    /// # Examples
404    /// 
405    /// ```rust
406    /// use rvoip_client_core::ClientError;
407    /// use uuid::Uuid;
408    /// 
409    /// let call_id = Uuid::new_v4();
410    /// let error = ClientError::CallAlreadyExists { call_id };
411    /// 
412    /// assert!(error.is_call_error());
413    /// ```
414    #[error("Call already exists: {call_id}")]
415    CallAlreadyExists { 
416        /// The call ID that already exists
417        call_id: Uuid 
418    },
419
420    /// Operation is not valid for the current call state
421    /// 
422    /// This error occurs when attempting an operation that is not allowed
423    /// in the call's current state (e.g., trying to answer an already connected call).
424    /// 
425    /// # Examples
426    /// 
427    /// ```rust
428    /// use rvoip_client_core::ClientError;
429    /// use rvoip_client_core::call::CallState;
430    /// use uuid::Uuid;
431    /// 
432    /// let call_id = Uuid::new_v4();
433    /// let error = ClientError::InvalidCallState {
434    ///     call_id,
435    ///     current_state: CallState::Terminated
436    /// };
437    /// 
438    /// assert!(error.is_call_error());
439    /// ```
440    #[error("Invalid call state for call {call_id}: current state is {current_state:?}")]
441    InvalidCallState { 
442        /// The call ID that has an invalid state
443        call_id: Uuid, 
444        /// The current state that prevents the operation
445        current_state: crate::call::CallState 
446    },
447
448    /// Generic call state validation error with string descriptions
449    /// 
450    /// This error provides a more flexible way to report call state issues
451    /// when the specific CallState enum values are not available.
452    /// 
453    /// # Examples
454    /// 
455    /// ```rust
456    /// use rvoip_client_core::ClientError;
457    /// 
458    /// let error = ClientError::InvalidCallStateGeneric {
459    ///     expected: "Connected".to_string(),
460    ///     actual: "Terminated".to_string()
461    /// };
462    /// 
463    /// assert!(error.is_call_error());
464    /// ```
465    #[error("Invalid call state: expected {expected}, got {actual}")]
466    InvalidCallStateGeneric { 
467        /// The expected call state for the operation
468        expected: String, 
469        /// The actual call state that was encountered
470        actual: String 
471    },
472
473    /// Call establishment or setup failed
474    /// 
475    /// This error occurs during the call setup phase when the INVITE
476    /// request fails due to network, server, or remote party issues.
477    /// 
478    /// # Examples
479    /// 
480    /// ```rust
481    /// use rvoip_client_core::ClientError;
482    /// 
483    /// let error = ClientError::CallSetupFailed {
484    ///     reason: "486 Busy Here".to_string()
485    /// };
486    /// 
487    /// assert!(error.is_call_error());
488    /// ```
489    #[error("Call setup failed: {reason}")]
490    CallSetupFailed { 
491        /// Specific reason for call setup failure
492        reason: String 
493    },
494
495    /// Call was terminated unexpectedly
496    /// 
497    /// This error occurs when a call ends due to network issues,
498    /// remote party disconnect, or other unexpected conditions.
499    /// 
500    /// # Examples
501    /// 
502    /// ```rust
503    /// use rvoip_client_core::ClientError;
504    /// 
505    /// let error = ClientError::CallTerminated {
506    ///     reason: "Network connection lost".to_string()
507    /// };
508    /// 
509    /// assert!(error.is_call_error());
510    /// ```
511    #[error("Call terminated: {reason}")]
512    CallTerminated { 
513        /// Reason for call termination
514        reason: String 
515    },
516
517    /// Media related errors
518
519    /// SDP negotiation or media setup failed
520    /// 
521    /// This error occurs when the client cannot establish media streams
522    /// due to codec mismatches, network issues, or SDP parsing problems.
523    /// 
524    /// # Examples
525    /// 
526    /// ```rust
527    /// use rvoip_client_core::ClientError;
528    /// 
529    /// let error = ClientError::MediaNegotiationFailed {
530    ///     reason: "No common codecs found".to_string()
531    /// };
532    /// 
533    /// assert_eq!(error.category(), "media");
534    /// ```
535    #[error("Media negotiation failed: {reason}")]
536    MediaNegotiationFailed { 
537        /// Specific reason for media negotiation failure
538        reason: String 
539    },
540    
541    /// General media processing error
542    /// 
543    /// This error covers various media-related issues including RTP
544    /// processing problems, audio device failures, and codec errors.
545    /// 
546    /// # Examples
547    /// 
548    /// ```rust
549    /// use rvoip_client_core::ClientError;
550    /// 
551    /// let error = ClientError::MediaError {
552    ///     details: "RTP packet processing failed".to_string()
553    /// };
554    /// 
555    /// assert_eq!(error.category(), "media");
556    /// ```
557    #[error("Media error: {details}")]
558    MediaError { 
559        /// Detailed description of the media error
560        details: String 
561    },
562
563    /// No audio codecs are compatible between endpoints
564    /// 
565    /// This error occurs when the local and remote endpoints cannot
566    /// agree on a common audio codec for the call.
567    /// 
568    /// # Examples
569    /// 
570    /// ```rust
571    /// use rvoip_client_core::ClientError;
572    /// 
573    /// let error = ClientError::NoCompatibleCodecs;
574    /// assert_eq!(error.category(), "media");
575    /// ```
576    #[error("No compatible codecs")]
577    NoCompatibleCodecs,
578
579    /// Audio device (microphone/speaker) error
580    /// 
581    /// This error occurs when there are problems accessing or using
582    /// the system's audio input/output devices.
583    /// 
584    /// # Examples
585    /// 
586    /// ```rust
587    /// use rvoip_client_core::ClientError;
588    /// 
589    /// let error = ClientError::AudioDeviceError {
590    ///     reason: "Microphone permission denied".to_string()
591    /// };
592    /// 
593    /// assert_eq!(error.category(), "media");
594    /// ```
595    #[error("Audio device error: {reason}")]
596    AudioDeviceError { 
597        /// Specific reason for audio device failure
598        reason: String 
599    },
600
601    /// Network and transport errors
602
603    /// General network connectivity or communication error
604    /// 
605    /// This error occurs for various network-related issues including
606    /// DNS resolution failures, socket errors, and packet loss.
607    /// 
608    /// # Examples
609    /// 
610    /// ```rust
611    /// use rvoip_client_core::ClientError;
612    /// 
613    /// let error = ClientError::NetworkError {
614    ///     reason: "DNS resolution failed for server.example.com".to_string()
615    /// };
616    /// 
617    /// assert!(error.is_recoverable());
618    /// assert_eq!(error.category(), "network");
619    /// ```
620    #[error("Network error: {reason}")]
621    NetworkError { 
622        /// Specific description of the network error
623        reason: String 
624    },
625
626    /// Operation timed out waiting for network response
627    /// 
628    /// This error occurs when network operations (like SIP requests)
629    /// do not receive a response within the configured timeout period.
630    /// 
631    /// # Examples
632    /// 
633    /// ```rust
634    /// use rvoip_client_core::ClientError;
635    /// 
636    /// let error = ClientError::ConnectionTimeout;
637    /// assert!(error.is_recoverable());
638    /// assert_eq!(error.category(), "network");
639    /// ```
640    #[error("Connection timeout")]
641    ConnectionTimeout,
642
643    /// Cannot reach the specified SIP server
644    /// 
645    /// This error occurs when the client cannot establish a connection
646    /// to the SIP server due to network issues or incorrect server address.
647    /// 
648    /// # Examples
649    /// 
650    /// ```rust
651    /// use rvoip_client_core::ClientError;
652    /// 
653    /// let error = ClientError::ServerUnreachable {
654    ///     server: "sip.example.com:5060".to_string()
655    /// };
656    /// 
657    /// assert_eq!(error.category(), "network");
658    /// ```
659    #[error("Server unreachable: {server}")]
660    ServerUnreachable { 
661        /// The server address that could not be reached
662        server: String 
663    },
664
665    /// Protocol errors
666
667    /// SIP protocol violation or parsing error
668    /// 
669    /// This error occurs when receiving malformed SIP messages or
670    /// encountering protocol violations that prevent proper communication.
671    /// 
672    /// # Examples
673    /// 
674    /// ```rust
675    /// use rvoip_client_core::ClientError;
676    /// 
677    /// let error = ClientError::ProtocolError {
678    ///     reason: "Invalid SIP URI format".to_string()
679    /// };
680    /// 
681    /// assert_eq!(error.category(), "protocol");
682    /// ```
683    #[error("SIP protocol error: {reason}")]
684    ProtocolError { 
685        /// Specific description of the protocol error
686        reason: String 
687    },
688
689    /// Received an invalid or malformed SIP message
690    /// 
691    /// This error occurs when parsing SIP messages that do not conform
692    /// to the SIP specification or contain invalid syntax.
693    /// 
694    /// # Examples
695    /// 
696    /// ```rust
697    /// use rvoip_client_core::ClientError;
698    /// 
699    /// let error = ClientError::InvalidSipMessage {
700    ///     reason: "Missing required Via header".to_string()
701    /// };
702    /// 
703    /// assert_eq!(error.category(), "protocol");
704    /// ```
705    #[error("Invalid SIP message: {reason}")]
706    InvalidSipMessage { 
707        /// Specific reason why the SIP message is invalid
708        reason: String 
709    },
710
711    /// SIP protocol version mismatch
712    /// 
713    /// This error occurs when the client and server are using incompatible
714    /// versions of the SIP protocol.
715    /// 
716    /// # Examples
717    /// 
718    /// ```rust
719    /// use rvoip_client_core::ClientError;
720    /// 
721    /// let error = ClientError::ProtocolVersionMismatch {
722    ///     expected: "SIP/2.0".to_string(),
723    ///     actual: "SIP/3.0".to_string()
724    /// };
725    /// 
726    /// assert_eq!(error.category(), "protocol");
727    /// ```
728    #[error("Protocol version mismatch: expected {expected}, got {actual}")]
729    ProtocolVersionMismatch { 
730        /// The expected protocol version
731        expected: String, 
732        /// The actual protocol version received
733        actual: String 
734    },
735
736    /// Configuration errors
737
738    /// Client configuration is invalid
739    /// 
740    /// This error occurs when the client is configured with invalid
741    /// settings that prevent proper operation.
742    /// 
743    /// # Examples
744    /// 
745    /// ```rust
746    /// use rvoip_client_core::ClientError;
747    /// 
748    /// let error = ClientError::InvalidConfiguration {
749    ///     field: "sip_port".to_string(),
750    ///     reason: "Port must be between 1024 and 65535".to_string()
751    /// };
752    /// 
753    /// assert_eq!(error.category(), "configuration");
754    /// ```
755    #[error("Invalid configuration: {field} - {reason}")]
756    InvalidConfiguration { 
757        /// The configuration field that is invalid
758        field: String, 
759        /// Explanation of why the configuration is invalid
760        reason: String 
761    },
762
763    /// Required configuration parameter is missing
764    /// 
765    /// This error occurs when mandatory configuration values are not
766    /// provided to the client.
767    /// 
768    /// # Examples
769    /// 
770    /// ```rust
771    /// use rvoip_client_core::ClientError;
772    /// 
773    /// let error = ClientError::MissingConfiguration {
774    ///     field: "server_address".to_string()
775    /// };
776    /// 
777    /// assert_eq!(error.category(), "configuration");
778    /// ```
779    #[error("Missing required configuration: {field}")]
780    MissingConfiguration { 
781        /// The configuration field that is missing
782        field: String 
783    },
784
785    /// Transport errors
786
787    /// Network transport layer failure
788    /// 
789    /// This error occurs when the underlying transport (UDP/TCP/TLS)
790    /// encounters failures that prevent SIP communication.
791    /// 
792    /// # Examples
793    /// 
794    /// ```rust
795    /// use rvoip_client_core::ClientError;
796    /// 
797    /// let error = ClientError::TransportFailed {
798    ///     reason: "TLS handshake failed".to_string()
799    /// };
800    /// 
801    /// assert!(error.is_recoverable());
802    /// assert_eq!(error.category(), "network");
803    /// ```
804    #[error("Transport failed: {reason}")]
805    TransportFailed { 
806        /// Specific reason for transport failure
807        reason: String 
808    },
809
810    /// Requested transport type is not available
811    /// 
812    /// This error occurs when trying to use a transport protocol
813    /// that is not supported or configured in the client.
814    /// 
815    /// # Examples
816    /// 
817    /// ```rust
818    /// use rvoip_client_core::ClientError;
819    /// 
820    /// let error = ClientError::TransportNotAvailable {
821    ///     transport_type: "WSS".to_string()
822    /// };
823    /// 
824    /// assert_eq!(error.category(), "network");
825    /// ```
826    #[error("Transport not available: {transport_type}")]
827    TransportNotAvailable { 
828        /// The transport type that is not available
829        transport_type: String 
830    },
831
832    /// Session management errors
833
834    /// Session manager internal error
835    /// 
836    /// This error occurs when the session management layer encounters
837    /// internal failures that prevent proper session handling.
838    /// 
839    /// # Examples
840    /// 
841    /// ```rust
842    /// use rvoip_client_core::ClientError;
843    /// 
844    /// let error = ClientError::SessionManagerError {
845    ///     reason: "Session state corruption detected".to_string()
846    /// };
847    /// 
848    /// assert_eq!(error.category(), "session");
849    /// ```
850    #[error("Session manager error: {reason}")]
851    SessionManagerError { 
852        /// Specific reason for session manager failure
853        reason: String 
854    },
855
856    /// Maximum number of concurrent sessions exceeded
857    /// 
858    /// This error occurs when attempting to create more sessions than
859    /// the configured or system-imposed limit allows.
860    /// 
861    /// # Examples
862    /// 
863    /// ```rust
864    /// use rvoip_client_core::ClientError;
865    /// 
866    /// let error = ClientError::TooManySessions {
867    ///     limit: 10
868    /// };
869    /// 
870    /// assert_eq!(error.category(), "session");
871    /// ```
872    #[error("Too many sessions: limit is {limit}")]
873    TooManySessions { 
874        /// The maximum number of sessions allowed
875        limit: usize 
876    },
877
878    /// Generic errors
879
880    /// Internal client error
881    /// 
882    /// This error indicates an unexpected internal failure within the
883    /// client library that should not normally occur.
884    /// 
885    /// # Examples
886    /// 
887    /// ```rust
888    /// use rvoip_client_core::ClientError;
889    /// 
890    /// let error = ClientError::InternalError {
891    ///     message: "Unexpected null pointer in call handler".to_string()
892    /// };
893    /// 
894    /// assert_eq!(error.category(), "system");
895    /// ```
896    #[error("Internal error: {message}")]
897    InternalError { 
898        /// Description of the internal error
899        message: String 
900    },
901
902    /// Operation exceeded its timeout deadline
903    /// 
904    /// This error occurs when an operation takes longer than its
905    /// configured timeout period to complete.
906    /// 
907    /// # Examples
908    /// 
909    /// ```rust
910    /// use rvoip_client_core::ClientError;
911    /// 
912    /// let error = ClientError::OperationTimeout {
913    ///     duration_ms: 5000
914    /// };
915    /// 
916    /// assert_eq!(error.category(), "system");
917    /// ```
918    #[error("Operation timeout after {duration_ms}ms")]
919    OperationTimeout { 
920        /// The timeout duration in milliseconds
921        duration_ms: u64 
922    },
923
924    /// Requested feature is not yet implemented
925    /// 
926    /// This error occurs when attempting to use functionality that
927    /// is planned but not yet available in the current version.
928    /// 
929    /// # Examples
930    /// 
931    /// ```rust
932    /// use rvoip_client_core::ClientError;
933    /// 
934    /// let error = ClientError::NotImplemented {
935    ///     feature: "Video calls".to_string(),
936    ///     reason: "Planned for version 2.0".to_string()
937    /// };
938    /// 
939    /// assert_eq!(error.category(), "system");
940    /// ```
941    #[error("Not implemented: {feature} - {reason}")]
942    NotImplemented { 
943        /// The feature that is not implemented
944        feature: String, 
945        /// Explanation of implementation status
946        reason: String 
947    },
948
949    /// Operation not permitted in current context
950    /// 
951    /// This error occurs when the user or system lacks the necessary
952    /// permissions to perform the requested operation.
953    /// 
954    /// # Examples
955    /// 
956    /// ```rust
957    /// use rvoip_client_core::ClientError;
958    /// 
959    /// let error = ClientError::PermissionDenied {
960    ///     operation: "Access microphone".to_string()
961    /// };
962    /// 
963    /// assert_eq!(error.category(), "system");
964    /// ```
965    #[error("Permission denied: {operation}")]
966    PermissionDenied { 
967        /// The operation that was denied
968        operation: String 
969    },
970
971    /// Required resource is not available
972    /// 
973    /// This error occurs when the system cannot allocate or access
974    /// a required resource (memory, ports, devices, etc.).
975    /// 
976    /// # Examples
977    /// 
978    /// ```rust
979    /// use rvoip_client_core::ClientError;
980    /// 
981    /// let error = ClientError::ResourceUnavailable {
982    ///     resource: "RTP port range 10000-20000".to_string()
983    /// };
984    /// 
985    /// assert_eq!(error.category(), "system");
986    /// ```
987    #[error("Resource unavailable: {resource}")]
988    ResourceUnavailable { 
989        /// The resource that is unavailable
990        resource: String 
991    },
992
993    /// Codec and media format errors
994
995    /// Audio codec is not supported
996    /// 
997    /// This error occurs when attempting to use an audio codec that
998    /// is not available in the current client configuration.
999    /// 
1000    /// # Examples
1001    /// 
1002    /// ```rust
1003    /// use rvoip_client_core::ClientError;
1004    /// 
1005    /// let error = ClientError::UnsupportedCodec {
1006    ///     codec: "G.729".to_string()
1007    /// };
1008    /// 
1009    /// assert_eq!(error.category(), "media");
1010    /// ```
1011    #[error("Unsupported codec: {codec}")]
1012    UnsupportedCodec { 
1013        /// The codec that is not supported
1014        codec: String 
1015    },
1016
1017    /// Codec processing error
1018    /// 
1019    /// This error occurs when there are problems encoding or decoding
1020    /// audio using the selected codec.
1021    /// 
1022    /// # Examples
1023    /// 
1024    /// ```rust
1025    /// use rvoip_client_core::ClientError;
1026    /// 
1027    /// let error = ClientError::CodecError {
1028    ///     reason: "OPUS encoder initialization failed".to_string()
1029    /// };
1030    /// 
1031    /// assert_eq!(error.category(), "media");
1032    /// ```
1033    #[error("Codec error: {reason}")]
1034    CodecError { 
1035        /// Specific reason for codec error
1036        reason: String 
1037    },
1038
1039    /// External service errors
1040
1041    /// External service or dependency failure
1042    /// 
1043    /// This error occurs when an external service (STUN server, media relay,
1044    /// authentication service, etc.) fails or becomes unavailable.
1045    /// 
1046    /// # Examples
1047    /// 
1048    /// ```rust
1049    /// use rvoip_client_core::ClientError;
1050    /// 
1051    /// let error = ClientError::ExternalServiceError {
1052    ///     service: "STUN server".to_string(),
1053    ///     reason: "stun.example.com connection refused".to_string()
1054    /// };
1055    /// 
1056    /// assert_eq!(error.category(), "system");
1057    /// ```
1058    #[error("External service error: {service} - {reason}")]
1059    ExternalServiceError { 
1060        /// The external service that failed
1061        service: String, 
1062        /// Specific reason for the service failure
1063        reason: String 
1064    },
1065}
1066
1067impl ClientError {
1068    /// Create a registration failed error
1069    pub fn registration_failed(reason: impl Into<String>) -> Self {
1070        Self::RegistrationFailed { reason: reason.into() }
1071    }
1072
1073    /// Create an authentication failed error
1074    pub fn authentication_failed(reason: impl Into<String>) -> Self {
1075        Self::AuthenticationFailed { reason: reason.into() }
1076    }
1077
1078    /// Create a call setup failed error
1079    pub fn call_setup_failed(reason: impl Into<String>) -> Self {
1080        Self::CallSetupFailed { reason: reason.into() }
1081    }
1082
1083    /// Create a media negotiation failed error
1084    pub fn media_negotiation_failed(reason: impl Into<String>) -> Self {
1085        Self::MediaNegotiationFailed { reason: reason.into() }
1086    }
1087
1088    /// Create a network error
1089    pub fn network_error(reason: impl Into<String>) -> Self {
1090        Self::NetworkError { reason: reason.into() }
1091    }
1092
1093    /// Create a protocol error
1094    pub fn protocol_error(reason: impl Into<String>) -> Self {
1095        Self::ProtocolError { reason: reason.into() }
1096    }
1097
1098    /// Create an internal error
1099    pub fn internal_error(reason: impl Into<String>) -> Self {
1100        Self::InternalError { message: reason.into() }
1101    }
1102
1103    /// Check if this error is recoverable
1104    pub fn is_recoverable(&self) -> bool {
1105        match self {
1106            // Recoverable errors
1107            ClientError::NetworkError { .. } |
1108            ClientError::ConnectionTimeout |
1109            ClientError::TransportFailed { .. } |
1110            ClientError::OperationTimeout { .. } |
1111            ClientError::ExternalServiceError { .. } => true,
1112            
1113            // Non-recoverable errors
1114            ClientError::InvalidConfiguration { .. } |
1115            ClientError::MissingConfiguration { .. } |
1116            ClientError::ProtocolVersionMismatch { .. } |
1117            ClientError::PermissionDenied { .. } |
1118            ClientError::NotImplemented { .. } |
1119            ClientError::UnsupportedCodec { .. } => false,
1120            
1121            // Context-dependent errors
1122            _ => false,
1123        }
1124    }
1125
1126    /// Check if error indicates authentication issue
1127    pub fn is_auth_error(&self) -> bool {
1128        matches!(
1129            self,
1130            ClientError::AuthenticationFailed { .. }
1131                | ClientError::NotRegistered
1132                | ClientError::RegistrationExpired
1133        )
1134    }
1135
1136    /// Check if error is call-related
1137    pub fn is_call_error(&self) -> bool {
1138        matches!(
1139            self,
1140            ClientError::CallNotFound { .. }
1141                | ClientError::CallAlreadyExists { .. }
1142                | ClientError::InvalidCallState { .. }
1143                | ClientError::InvalidCallStateGeneric { .. }
1144                | ClientError::CallSetupFailed { .. }
1145                | ClientError::CallTerminated { .. }
1146        )
1147    }
1148
1149    /// Get error category for metrics/logging
1150    pub fn category(&self) -> &'static str {
1151        match self {
1152            ClientError::RegistrationFailed { .. } |
1153            ClientError::NotRegistered |
1154            ClientError::RegistrationExpired |
1155            ClientError::AuthenticationFailed { .. } => "registration",
1156            
1157            ClientError::CallNotFound { .. } |
1158            ClientError::CallAlreadyExists { .. } |
1159            ClientError::InvalidCallState { .. } |
1160            ClientError::InvalidCallStateGeneric { .. } |
1161            ClientError::CallSetupFailed { .. } |
1162            ClientError::CallTerminated { .. } => "call",
1163            
1164            ClientError::MediaNegotiationFailed { .. } |
1165            ClientError::MediaError { .. } |
1166            ClientError::NoCompatibleCodecs |
1167            ClientError::AudioDeviceError { .. } |
1168            ClientError::UnsupportedCodec { .. } |
1169            ClientError::CodecError { .. } => "media",
1170            
1171            ClientError::NetworkError { .. } |
1172            ClientError::ConnectionTimeout |
1173            ClientError::ServerUnreachable { .. } |
1174            ClientError::TransportFailed { .. } |
1175            ClientError::TransportNotAvailable { .. } => "network",
1176            
1177            ClientError::ProtocolError { .. } |
1178            ClientError::InvalidSipMessage { .. } |
1179            ClientError::ProtocolVersionMismatch { .. } => "protocol",
1180            
1181            ClientError::InvalidConfiguration { .. } |
1182            ClientError::MissingConfiguration { .. } => "configuration",
1183            
1184            ClientError::SessionManagerError { .. } |
1185            ClientError::TooManySessions { .. } => "session",
1186            
1187            ClientError::InternalError { .. } |
1188            ClientError::OperationTimeout { .. } |
1189            ClientError::NotImplemented { .. } |
1190            ClientError::PermissionDenied { .. } |
1191            ClientError::ResourceUnavailable { .. } |
1192            ClientError::ExternalServiceError { .. } => "system",
1193        }
1194    }
1195}