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, PartialEq, Eq)]
25pub struct CodecInfo {
26 pub name: String,
28 pub srate: u32,
30 pub ch: u8,
32}
33
34#[derive(Debug, Clone)]
35pub enum AppEvent {
36 Registering {
37 account: String,
38 },
39 RegisterOk {
40 account: String,
41 },
42 RegisterFailed {
43 reason: String,
44 },
45 Unregistered {
46 account: String,
47 },
48 CallIncoming {
49 call_id: String,
50 number: String,
51 display_name: Option<String>,
52 },
53 CallOutgoing {
54 call_id: String,
55 number: String,
56 },
57 CallRinging {
58 call_id: String,
59 },
60 CallEstablished {
61 call_id: String,
62 },
63 CallClosed {
64 call_id: String,
65 reason: String,
66 error: bool,
67 },
68 CallDeflected {
69 from: String,
70 display_name: Option<String>,
71 target: String,
72 },
73 VoicemailStatus {
74 waiting: bool,
75 new_count: u32,
76 },
77 Response {
78 ok: bool,
79 data: String,
80 },
81 Unknown {
82 class: String,
83 type_: String,
84 },
85 BackendConnectFailed {
86 reason: String,
87 },
88}
89
90pub fn is_error_reason(reason: &str) -> bool {
93 if reason.is_empty() {
94 return false;
95 }
96 const NORMAL: &[&str] = &[
97 "Connection reset by peer",
98 "Connection closed",
99 "Rejected by user",
100 "Call transfered",
101 ];
102 !NORMAL
103 .iter()
104 .any(|n| reason.to_lowercase().starts_with(&n.to_lowercase()))
105}
106
107#[cfg(test)]
108mod tests {
109 use super::*;
110
111 #[test]
114 fn empty_reason_is_not_error() {
115 assert!(!is_error_reason(""));
116 }
117
118 #[test]
119 fn connection_reset_is_not_error() {
120 assert!(!is_error_reason("Connection reset by peer"));
121 }
122
123 #[test]
124 fn connection_reset_with_errno_is_not_error() {
125 assert!(!is_error_reason("Connection reset by peer [104]"));
126 }
127
128 #[test]
129 fn connection_closed_is_not_error() {
130 assert!(!is_error_reason("Connection closed"));
131 }
132
133 #[test]
134 fn rejected_by_user_is_not_error() {
135 assert!(!is_error_reason("Rejected by user"));
136 }
137
138 #[test]
139 fn sip_busy_is_error() {
140 assert!(is_error_reason("486 Busy Here"));
141 }
142
143 #[test]
144 fn sip_not_found_is_error() {
145 assert!(is_error_reason("404 Not Found"));
146 }
147}