1use serde::{Deserialize, Serialize};
2use serde_with::skip_serializing_none;
3use std::{
4 collections::HashMap,
5 sync::{Arc, Mutex},
6};
7use voice_engine::{
8 CallOption, ReferOption, media::recorder::RecorderOption, synthesis::SynthesisOption,
9};
10
11pub mod active_call;
12pub mod sip;
13pub use active_call::ActiveCall;
14pub use active_call::ActiveCallRef;
15pub use active_call::ActiveCallType;
16
17pub type CommandSender = tokio::sync::broadcast::Sender<Command>;
18pub type CommandReceiver = tokio::sync::broadcast::Receiver<Command>;
19
20#[skip_serializing_none]
22#[derive(Debug, Deserialize, Serialize, Clone)]
23#[serde(
24 tag = "command",
25 rename_all = "camelCase",
26 rename_all_fields = "camelCase"
27)]
28pub enum Command {
29 Invite {
30 option: CallOption,
31 },
32 Accept {
33 option: CallOption,
34 },
35 Reject {
36 reason: String,
37 code: Option<u32>,
38 },
39 Ringing {
40 recorder: Option<RecorderOption>,
41 early_media: Option<bool>,
42 ringtone: Option<String>,
43 },
44 Tts {
45 text: String,
46 speaker: Option<String>,
47 play_id: Option<String>,
49 auto_hangup: Option<bool>,
51 streaming: Option<bool>,
55 end_of_stream: Option<bool>,
57 option: Option<SynthesisOption>,
58 wait_input_timeout: Option<u32>,
59 base64: Option<bool>,
61 },
62 Play {
63 url: String,
64 play_id: Option<String>,
65 auto_hangup: Option<bool>,
66 wait_input_timeout: Option<u32>,
67 },
68 Interrupt {
69 graceful: Option<bool>,
70 },
71 Pause {},
72 Resume {},
73 Hangup {
74 reason: Option<String>,
75 initiator: Option<String>,
76 },
77 Refer {
78 caller: String,
79 callee: String,
81 options: Option<ReferOption>,
82 },
83 Mute {
84 track_id: Option<String>,
85 },
86 Unmute {
87 track_id: Option<String>,
88 },
89 History {
90 speaker: String,
91 text: String,
92 },
93}
94
95#[derive(Debug)]
97pub struct RoutingState {
98 round_robin_counters: Arc<Mutex<HashMap<String, usize>>>,
100}
101
102impl Default for RoutingState {
103 fn default() -> Self {
104 Self::new()
105 }
106}
107
108impl RoutingState {
109 pub fn new() -> Self {
110 Self {
111 round_robin_counters: Arc::new(Mutex::new(HashMap::new())),
112 }
113 }
114
115 pub fn next_round_robin_index(&self, destination_key: &str, trunk_count: usize) -> usize {
117 if trunk_count == 0 {
118 return 0;
119 }
120
121 let mut counters = self.round_robin_counters.lock().unwrap();
122 let counter = counters
123 .entry(destination_key.to_string())
124 .or_insert_with(|| 0);
125 let r = *counter % trunk_count;
126 *counter += 1;
127 return r;
128 }
129}