Skip to main content

asterisk_rs_ami/
error.rs

1//! AMI-specific error types.
2
3use asterisk_rs_core::error::{AuthError, ConnectionError, ProtocolError, TimeoutError};
4
5/// Cloneable terminal connection cause retained after the background actor exits.
6#[derive(Debug, Clone, PartialEq, Eq)]
7pub struct AmiTerminalError {
8    pub kind: AmiTerminalErrorKind,
9    pub details: String,
10}
11
12#[derive(Debug, Clone, Copy, PartialEq, Eq)]
13#[non_exhaustive]
14pub enum AmiTerminalErrorKind {
15    Authentication,
16    Connection,
17    Timeout,
18    Protocol,
19    Io,
20    Other,
21}
22
23impl AmiTerminalError {
24    pub(crate) fn from_error(error: &AmiError) -> Self {
25        let kind = match error {
26            AmiError::Auth(_) => AmiTerminalErrorKind::Authentication,
27            AmiError::Connection(_) => AmiTerminalErrorKind::Connection,
28            AmiError::Timeout(_) => AmiTerminalErrorKind::Timeout,
29            AmiError::Protocol(_) => AmiTerminalErrorKind::Protocol,
30            AmiError::Io(_) => AmiTerminalErrorKind::Io,
31            _ => AmiTerminalErrorKind::Other,
32        };
33        Self {
34            kind,
35            details: error.to_string(),
36        }
37    }
38}
39
40/// errors specific to AMI operations
41#[derive(Debug, thiserror::Error)]
42#[non_exhaustive]
43pub enum AmiError {
44    #[error("connection error: {0}")]
45    Connection(#[from] ConnectionError),
46
47    #[error("authentication error: {0}")]
48    Auth(#[from] AuthError),
49
50    #[error("timeout: {0}")]
51    Timeout(#[from] TimeoutError),
52
53    #[error("protocol error: {0}")]
54    Protocol(#[from] ProtocolError),
55
56    #[error("I/O error: {0}")]
57    Io(#[from] std::io::Error),
58
59    #[error("client is disconnected")]
60    Disconnected,
61
62    #[error("action response channel closed")]
63    ResponseChannelClosed,
64
65    /// the action reached the wire, but no definitive response was received
66    #[error("outcome unknown for AMI action {action_id}: it may have been executed")]
67    OutcomeUnknown { action_id: String },
68
69    #[error("AMI in-flight action limit exceeded ({limit})")]
70    InFlightLimitExceeded { limit: usize },
71
72    #[error("AMI event list {action_id} exceeded the {limit}-event limit")]
73    EventListEventLimitExceeded { action_id: String, limit: usize },
74
75    #[error("AMI event list {action_id} exceeded the {limit}-byte limit")]
76    EventListByteLimitExceeded { action_id: String, limit: usize },
77
78    #[error("AMI event-list in-flight action limit exceeded ({limit})")]
79    EventListInFlightLimitExceeded { limit: usize },
80
81    #[error(
82        "AMI event lists exceeded the connection-wide {limit}-byte limit while collecting {action_id}"
83    )]
84    EventListConnectionByteLimitExceeded { action_id: String, limit: usize },
85
86    #[error("AMI event list {action_id} was cancelled by Asterisk")]
87    EventListCancelled { action_id: String },
88
89    #[error("invalid configuration: {details}")]
90    InvalidConfig { details: String },
91}
92
93pub type Result<T> = std::result::Result<T, AmiError>;