use std::collections::HashMap;
pub type InviteHeaders = HashMap<String, Vec<(String, String)>>;
#[derive(Debug, Clone)]
pub enum AppEvent {
Registering {
account: String,
},
RegisterOk {
account: String,
},
RegisterFailed {
reason: String,
},
Unregistered {
account: String,
},
CallIncoming {
call_id: String,
number: String,
display_name: Option<String>,
},
CallOutgoing {
call_id: String,
number: String,
},
CallRinging {
call_id: String,
},
CallEstablished {
call_id: String,
},
CallClosed {
call_id: String,
reason: String,
error: bool,
},
VoicemailStatus {
waiting: bool,
new_count: u32,
},
Response {
ok: bool,
data: String,
},
Unknown {
class: String,
type_: String,
},
BackendConnectFailed {
reason: String,
},
}
pub fn is_error_reason(reason: &str) -> bool {
if reason.is_empty() {
return false;
}
const NORMAL: &[&str] = &[
"Connection reset by peer",
"Connection closed",
"Rejected by user",
"Call transfered",
];
!NORMAL
.iter()
.any(|n| reason.to_lowercase().starts_with(&n.to_lowercase()))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn empty_reason_is_not_error() {
assert!(!is_error_reason(""));
}
#[test]
fn connection_reset_is_not_error() {
assert!(!is_error_reason("Connection reset by peer"));
}
#[test]
fn connection_reset_with_errno_is_not_error() {
assert!(!is_error_reason("Connection reset by peer [104]"));
}
#[test]
fn connection_closed_is_not_error() {
assert!(!is_error_reason("Connection closed"));
}
#[test]
fn rejected_by_user_is_not_error() {
assert!(!is_error_reason("Rejected by user"));
}
#[test]
fn sip_busy_is_error() {
assert!(is_error_reason("486 Busy Here"));
}
#[test]
fn sip_not_found_is_error() {
assert!(is_error_reason("404 Not Found"));
}
}