active_call/
lib.rs

1use anyhow::Result;
2use rsipstack::dialog::{authenticate::Credential, invitation::InviteOption};
3use serde::{Deserialize, Serialize};
4use serde_with::skip_serializing_none;
5use std::collections::HashMap;
6
7use crate::{
8    media::{recorder::RecorderOption, track::media_pass::MediaPassOption, vad::VADOption},
9    synthesis::SynthesisOption,
10    transcription::TranscriptionOption,
11};
12
13pub mod app;
14pub mod call;
15pub mod callrecord;
16pub mod config;
17pub mod event;
18pub mod handler;
19pub mod locator;
20pub mod media;
21pub mod net_tool;
22pub mod playbook;
23pub mod synthesis;
24pub mod transcription;
25pub mod useragent;
26
27#[derive(Debug, Deserialize, Serialize, Default, Clone)]
28#[serde(default)]
29pub struct SipOption {
30    pub username: Option<String>,
31    pub password: Option<String>,
32    pub realm: Option<String>,
33    pub contact: Option<String>,
34    pub headers: Option<HashMap<String, String>>,
35}
36
37#[skip_serializing_none]
38#[derive(Debug, Deserialize, Serialize, Clone)]
39#[serde(rename_all = "camelCase")]
40pub struct CallOption {
41    pub denoise: Option<bool>,
42    pub offer: Option<String>,
43    pub callee: Option<String>,
44    pub caller: Option<String>,
45    pub recorder: Option<RecorderOption>,
46    pub vad: Option<VADOption>,
47    pub asr: Option<TranscriptionOption>,
48    pub tts: Option<SynthesisOption>,
49    pub media_pass: Option<MediaPassOption>,
50    // handshake timeout in seconds
51    pub handshake_timeout: Option<u64>,
52    pub enable_ipv6: Option<bool>,
53    pub inactivity_timeout: Option<u64>, // inactivity timeout in seconds
54    pub sip: Option<SipOption>,
55    pub extra: Option<HashMap<String, String>>,
56    pub codec: Option<String>, // pcmu, pcma, g722, pcm, only for websocket call
57    pub eou: Option<EouOption>,
58}
59
60impl Default for CallOption {
61    fn default() -> Self {
62        Self {
63            denoise: None,
64            offer: None,
65            callee: None,
66            caller: None,
67            recorder: None,
68            asr: None,
69            vad: None,
70            tts: None,
71            media_pass: None,
72            handshake_timeout: None,
73            inactivity_timeout: Some(50), // default 50 seconds
74            enable_ipv6: None,
75            sip: None,
76            extra: None,
77            codec: None,
78            eou: None,
79        }
80    }
81}
82
83impl CallOption {
84    pub fn check_default(&mut self) {
85        if let Some(tts) = &mut self.tts {
86            tts.check_default();
87        }
88        if let Some(asr) = &mut self.asr {
89            asr.check_default();
90        }
91    }
92
93    pub fn build_invite_option(&self) -> Result<InviteOption> {
94        let mut invite_option = InviteOption::default();
95        if let Some(offer) = &self.offer {
96            invite_option.offer = Some(offer.clone().into());
97        }
98        if let Some(callee) = &self.callee {
99            invite_option.callee = callee.clone().try_into()?;
100        }
101        if let Some(caller) = &self.caller {
102            invite_option.caller = caller.clone().try_into()?;
103            invite_option.contact = invite_option.caller.clone();
104        }
105
106        if let Some(sip) = &self.sip {
107            invite_option.credential = Some(Credential {
108                username: sip.username.clone().unwrap_or_default(),
109                password: sip.password.clone().unwrap_or_default(),
110                realm: sip.realm.clone(),
111            });
112            invite_option.headers = sip.headers.as_ref().map(|h| {
113                h.iter()
114                    .map(|(k, v)| rsip::Header::Other(k.clone(), v.clone()))
115                    .collect::<Vec<_>>()
116            });
117            sip.contact.as_ref().map(|c| match c.clone().try_into() {
118                Ok(u) => {
119                    invite_option.contact = u;
120                }
121                Err(_) => {}
122            });
123        }
124        Ok(invite_option)
125    }
126}
127
128#[skip_serializing_none]
129#[derive(Debug, Deserialize, Serialize, Clone)]
130#[serde(rename_all = "camelCase")]
131pub struct ReferOption {
132    pub denoise: Option<bool>,
133    pub timeout: Option<u32>,
134    pub moh: Option<String>,
135    pub asr: Option<TranscriptionOption>,
136    /// hangup after the call is ended
137    pub auto_hangup: Option<bool>,
138    pub sip: Option<SipOption>,
139}
140
141#[skip_serializing_none]
142#[derive(Clone, Debug, Deserialize, Serialize)]
143#[serde(rename_all = "camelCase")]
144pub struct EouOption {
145    pub r#type: Option<String>,
146    pub endpoint: Option<String>,
147    pub secret_key: Option<String>,
148    pub secret_id: Option<String>,
149    /// max timeout in milliseconds
150    pub timeout: Option<u32>,
151    pub extra: Option<HashMap<String, String>>,
152}