rvoip_transaction_core/
error.rs

1use crate::transaction::{TransactionKey, TransactionKind, TransactionState};
2use std::io;
3use thiserror::Error;
4
5/// A type alias for handling `Result`s with `Error`
6pub type Result<T> = std::result::Result<T, Error>;
7
8/// Errors that can occur in SIP transaction handling
9#[derive(Error, Debug)]
10pub enum Error {
11    /// Error originating from the sip-core crate (parsing, building messages, etc.)
12    #[error("SIP core error: {0}")]
13    SipCoreError(#[from] rvoip_sip_core::Error),
14
15    /// Error originating from the sip-transport crate.
16    #[error("SIP transport error: {source}")]
17    TransportError { 
18        #[source]
19        source: TransportErrorWrapper,
20        context: Option<String>, 
21    },
22
23    /// Transaction not found for the given key.
24    #[error("Transaction not found: {key} (context: {context})")]
25    TransactionNotFound { 
26        key: TransactionKey,
27        context: String,
28    },
29
30    /// Transaction with the given key already exists.
31    #[error("Transaction already exists: {key} (kind: {kind:?})")]
32    TransactionExists { 
33        key: TransactionKey,
34        kind: TransactionKind,
35    },
36
37    /// Invalid transaction state transition attempted.
38    #[error("Invalid state transition: {from_state:?} -> {to_state:?} for {transaction_kind:?} transaction")]
39    InvalidStateTransition {
40        transaction_kind: TransactionKind,
41        from_state: TransactionState,
42        to_state: TransactionState,
43        transaction_id: Option<TransactionKey>,
44    },
45
46    /// Transaction timed out (specific timers T_B, T_F, T_H).
47    #[error("Transaction timed out: {key} (timer: {timer})")]
48    TransactionTimeout {
49        key: TransactionKey,
50        timer: String,
51    },
52    
53    /// Timer error
54    #[error("Timer error: {message}")]
55    TimerError {
56        message: String,
57    },
58
59    /// I/O error.
60    #[error("I/O error: {0}")]
61    Io(#[from] io::Error),
62
63    /// Internal channel error (e.g., receiver dropped).
64    #[error("Channel error: {context}")]
65    ChannelError {
66        context: String,
67    },
68    
69    /// Transaction creation error
70    #[error("Failed to create transaction: {message}")]
71    TransactionCreationError {
72        message: String,
73    },
74    
75    /// Transaction message processing error
76    #[error("Failed to process message: {message} for transaction {transaction_id:?}")]
77    MessageProcessingError {
78        message: String,
79        transaction_id: Option<TransactionKey>,
80    },
81
82    /// Transport manager error
83    #[error("Transport management error: {0}")]
84    Transport(String),
85
86    /// Other miscellaneous errors.
87    #[error("Other error: {0}")]
88    Other(String),
89}
90
91/// Wrapper for transport errors to provide consistent Debug/Display
92#[derive(Debug)]
93pub struct TransportErrorWrapper(pub String);
94
95impl std::fmt::Display for TransportErrorWrapper {
96    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
97        write!(f, "{}", self.0)
98    }
99}
100
101impl std::error::Error for TransportErrorWrapper {}
102
103// Manual From impl for transport errors
104impl From<rvoip_sip_transport::Error> for Error {
105    fn from(e: rvoip_sip_transport::Error) -> Self {
106        Error::TransportError { 
107            source: TransportErrorWrapper(e.to_string()),
108            context: None,
109        }
110    }
111}
112
113impl From<&str> for Error {
114    fn from(s: &str) -> Self {
115        Error::Other(s.to_string())
116    }
117}
118
119impl From<String> for Error {
120    fn from(s: String) -> Self {
121        Error::Other(s)
122    }
123}
124
125// More specific error for channel errors
126impl<T> From<tokio::sync::mpsc::error::SendError<T>> for Error {
127    fn from(e: tokio::sync::mpsc::error::SendError<T>) -> Self {
128        Error::ChannelError {
129            context: format!("Send error: channel closed while sending {:?}", std::any::type_name::<T>()),
130        }
131    }
132}
133
134// Add helper methods to create more specific errors with context
135impl Error {
136    /// Create a new TransactionNotFound error with context
137    pub fn transaction_not_found(key: TransactionKey, context: impl Into<String>) -> Self {
138        Error::TransactionNotFound { 
139            key, 
140            context: context.into(),
141        }
142    }
143    
144    /// Create a new TransportError with context
145    pub fn transport_error(source: rvoip_sip_transport::Error, context: impl Into<String>) -> Self {
146        Error::TransportError { 
147            source: TransportErrorWrapper(source.to_string()),
148            context: Some(context.into()),
149        }
150    }
151    
152    /// Create a new InvalidStateTransition error
153    pub fn invalid_state_transition(
154        transaction_kind: TransactionKind,
155        from_state: TransactionState,
156        to_state: TransactionState,
157        transaction_id: Option<TransactionKey>,
158    ) -> Self {
159        Error::InvalidStateTransition {
160            transaction_kind,
161            from_state,
162            to_state,
163            transaction_id,
164        }
165    }
166    
167    /// Create a new ChannelError with context
168    pub fn channel_error(context: impl Into<String>) -> Self {
169        Error::ChannelError {
170            context: context.into(),
171        }
172    }
173    
174    /// Create a new TransactionTimeout error
175    pub fn transaction_timeout(key: TransactionKey, timer: impl Into<String>) -> Self {
176        Error::TransactionTimeout {
177            key,
178            timer: timer.into(),
179        }
180    }
181}