1use std::collections::HashMap;
2
3pub type InviteHeaders = HashMap<String, Vec<(String, String)>>;
6
7#[derive(Debug, Clone, Copy)]
10pub struct MediaStats {
11 pub rtt_ms: f64,
13 pub jitter_ms: f64,
15 pub rx_lost: i32,
17 pub packet_loss_pct: f64,
19 pub mos: f64,
21}
22
23#[derive(Debug, Clone)]
24pub enum AppEvent {
25 Registering {
26 account: String,
27 },
28 RegisterOk {
29 account: String,
30 },
31 RegisterFailed {
32 reason: String,
33 },
34 Unregistered {
35 account: String,
36 },
37 CallIncoming {
38 call_id: String,
39 number: String,
40 display_name: Option<String>,
41 },
42 CallOutgoing {
43 call_id: String,
44 number: String,
45 },
46 CallRinging {
47 call_id: String,
48 },
49 CallEstablished {
50 call_id: String,
51 },
52 CallClosed {
53 call_id: String,
54 reason: String,
55 error: bool,
56 },
57 VoicemailStatus {
58 waiting: bool,
59 new_count: u32,
60 },
61 Response {
62 ok: bool,
63 data: String,
64 },
65 Unknown {
66 class: String,
67 type_: String,
68 },
69 BackendConnectFailed {
70 reason: String,
71 },
72}
73
74pub fn is_error_reason(reason: &str) -> bool {
77 if reason.is_empty() {
78 return false;
79 }
80 const NORMAL: &[&str] = &[
81 "Connection reset by peer",
82 "Connection closed",
83 "Rejected by user",
84 "Call transfered",
85 ];
86 !NORMAL
87 .iter()
88 .any(|n| reason.to_lowercase().starts_with(&n.to_lowercase()))
89}
90
91#[cfg(test)]
92mod tests {
93 use super::*;
94
95 #[test]
98 fn empty_reason_is_not_error() {
99 assert!(!is_error_reason(""));
100 }
101
102 #[test]
103 fn connection_reset_is_not_error() {
104 assert!(!is_error_reason("Connection reset by peer"));
105 }
106
107 #[test]
108 fn connection_reset_with_errno_is_not_error() {
109 assert!(!is_error_reason("Connection reset by peer [104]"));
110 }
111
112 #[test]
113 fn connection_closed_is_not_error() {
114 assert!(!is_error_reason("Connection closed"));
115 }
116
117 #[test]
118 fn rejected_by_user_is_not_error() {
119 assert!(!is_error_reason("Rejected by user"));
120 }
121
122 #[test]
123 fn sip_busy_is_error() {
124 assert!(is_error_reason("486 Busy Here"));
125 }
126
127 #[test]
128 fn sip_not_found_is_error() {
129 assert!(is_error_reason("404 Not Found"));
130 }
131}