2020-07-13 11:49:14 +02:00
|
|
|
//! # Calls controller
|
|
|
|
//!
|
|
|
|
//! @author Pierre Hubert
|
|
|
|
|
2021-02-11 18:29:29 +01:00
|
|
|
use webrtc_sdp::attribute_type::SdpAttribute;
|
|
|
|
|
2021-02-10 17:32:14 +01:00
|
|
|
use crate::api_data::call_member_info::CallMemberInfo;
|
2021-02-12 13:52:47 +01:00
|
|
|
use crate::api_data::call_peer_interrupted_streaming::CallPeerInterruptedStreamingAPI;
|
2021-02-11 19:21:24 +01:00
|
|
|
use crate::api_data::call_peer_ready::CallPeerReadyAPI;
|
2021-02-10 17:16:52 +01:00
|
|
|
use crate::api_data::joined_call_message::JoinedCallMessage;
|
2021-02-10 18:04:03 +01:00
|
|
|
use crate::api_data::left_call_message::LeftCallMessage;
|
2021-02-11 19:07:30 +01:00
|
|
|
use crate::api_data::new_call_signal::NewCallSignalAPI;
|
2021-02-08 18:24:28 +01:00
|
|
|
use crate::api_data::user_calls_config::UserCallsConfig;
|
2021-02-10 17:16:52 +01:00
|
|
|
use crate::controllers::user_ws_controller;
|
2021-02-05 09:11:30 +01:00
|
|
|
use crate::data::base_request_handler::BaseRequestHandler;
|
2023-05-31 19:10:05 +02:00
|
|
|
use crate::data::call_signal::{
|
|
|
|
CallSignal, CloseCallStream, IceCandidate, NewUserCallSignal, SdpType, UserCallOfferRequest,
|
|
|
|
};
|
2021-02-08 18:24:28 +01:00
|
|
|
use crate::data::config::conf;
|
2021-02-10 18:04:03 +01:00
|
|
|
use crate::data::conversation::ConvID;
|
2021-02-10 17:16:52 +01:00
|
|
|
use crate::data::error::{ExecError, Res};
|
2021-02-11 18:29:29 +01:00
|
|
|
use crate::data::user::UserID;
|
2021-02-10 18:04:03 +01:00
|
|
|
use crate::data::user_ws_connection::{ActiveCall, UserWsConnection};
|
2021-02-10 17:16:52 +01:00
|
|
|
use crate::data::user_ws_message::UserWsMessage;
|
2021-02-08 18:24:28 +01:00
|
|
|
use crate::data::user_ws_request_handler::UserWsRequestHandler;
|
2021-02-10 17:16:52 +01:00
|
|
|
use crate::helpers::events_helper::Event;
|
2023-05-31 19:10:05 +02:00
|
|
|
use crate::helpers::{calls_helper, conversations_helper, events_helper};
|
2021-03-04 18:51:52 +01:00
|
|
|
use crate::routes::RequestResult;
|
2020-07-13 11:49:14 +02:00
|
|
|
|
2021-02-11 18:29:29 +01:00
|
|
|
impl UserWsRequestHandler {
|
|
|
|
/// Get the ID of a call included in a WebSocket request
|
|
|
|
fn post_call_id(&mut self, name: &str) -> Res<ConvID> {
|
2021-03-04 18:51:52 +01:00
|
|
|
let conv_id = ConvID::new(self.post_u64(name)?);
|
2021-02-11 18:29:29 +01:00
|
|
|
|
|
|
|
if !self.get_conn().is_having_call_with_conversation(&conv_id) {
|
|
|
|
self.forbidden("You do not belong to this call!".to_string())?;
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(conv_id)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Get the ID of a peer for a call included in the WebSocket request
|
|
|
|
fn post_call_peer_id(&mut self, call_id: &ConvID, name: &str) -> Res<UserID> {
|
|
|
|
let peer_id = UserID::new(self.post_u64(name)?);
|
|
|
|
|
|
|
|
if peer_id == self.user_id_ref()? {
|
|
|
|
return Ok(peer_id);
|
|
|
|
}
|
|
|
|
|
|
|
|
let mut found = false;
|
|
|
|
user_ws_controller::foreach_connection(|p| {
|
2021-02-13 14:37:15 +01:00
|
|
|
if !found && p.user_id() == peer_id && p.is_having_call_with_conversation(call_id) {
|
2021-02-11 18:29:29 +01:00
|
|
|
found = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
})?;
|
|
|
|
|
|
|
|
if !found {
|
|
|
|
self.forbidden("This peer is not a member of the call !".to_string())?;
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(peer_id)
|
|
|
|
}
|
2021-02-11 19:21:24 +01:00
|
|
|
|
2021-02-12 13:52:47 +01:00
|
|
|
/// Get call information, if available
|
|
|
|
fn call_info(&mut self, call_id: &ConvID) -> Res<ActiveCall> {
|
2023-05-31 19:10:05 +02:00
|
|
|
let call = self
|
|
|
|
.get_conn()
|
2021-02-12 13:52:47 +01:00
|
|
|
.active_call
|
|
|
|
.clone()
|
|
|
|
.ok_or(ExecError::new("No call found !"))?;
|
|
|
|
|
|
|
|
if &call.conv_id != call_id {
|
|
|
|
self.bad_request("The call active is not the one requested!".to_string())?;
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(call)
|
|
|
|
}
|
|
|
|
|
2021-02-11 19:21:24 +01:00
|
|
|
/// Update call information
|
2023-05-31 19:10:05 +02:00
|
|
|
fn update_call<F>(&mut self, update: F) -> Res
|
|
|
|
where
|
|
|
|
F: FnOnce(&mut ActiveCall),
|
|
|
|
{
|
2021-02-11 19:21:24 +01:00
|
|
|
self.update_conn(|conn| {
|
|
|
|
if let Some(call) = &mut conn.active_call {
|
|
|
|
update(call);
|
|
|
|
}
|
|
|
|
})?;
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
2021-02-11 18:29:29 +01:00
|
|
|
}
|
|
|
|
|
2021-02-08 18:24:28 +01:00
|
|
|
/// Get calls configuration
|
2022-03-12 07:47:22 +01:00
|
|
|
pub async fn get_config(r: &mut UserWsRequestHandler) -> RequestResult {
|
2021-02-10 18:07:55 +01:00
|
|
|
// Check whether the user is the member of a call or not
|
|
|
|
if let None = r.get_conn().active_call {
|
|
|
|
r.forbidden("You do not belong to any call yet!".to_string())?;
|
|
|
|
}
|
2021-02-08 18:24:28 +01:00
|
|
|
|
2021-10-16 17:45:25 +02:00
|
|
|
if conf().is_rtc_relay_enabled() {
|
2023-05-31 19:10:05 +02:00
|
|
|
if let Some(conf) = conf().rtc_relay.as_ref() {
|
2021-10-16 17:45:25 +02:00
|
|
|
return r.set_response(UserCallsConfig::new(conf));
|
|
|
|
}
|
2021-02-08 18:24:28 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
r.internal_error(ExecError::boxed_new("Missing calls configuration!"))
|
2021-02-10 17:16:52 +01:00
|
|
|
}
|
|
|
|
|
2021-02-10 18:14:17 +01:00
|
|
|
/// Check out whether a conversation is having a call or not
|
|
|
|
pub fn is_conversation_having_call(conv_id: &ConvID) -> bool {
|
|
|
|
let mut found = false;
|
|
|
|
|
|
|
|
let res = user_ws_controller::foreach_connection(|f| {
|
|
|
|
if found || f.is_having_call_with_conversation(conv_id) {
|
|
|
|
found = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
});
|
|
|
|
|
|
|
|
if let Err(e) = res {
|
2023-05-31 19:10:05 +02:00
|
|
|
eprintln!(
|
|
|
|
"Failed to check if a conversation is having call! Conversation: {} / Error: {:#?}",
|
|
|
|
conv_id.id(),
|
|
|
|
e
|
|
|
|
);
|
2021-02-10 18:14:17 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
found
|
|
|
|
}
|
|
|
|
|
2021-02-10 17:16:52 +01:00
|
|
|
/// Join a call
|
2022-03-12 07:47:22 +01:00
|
|
|
pub async fn join_call(r: &mut UserWsRequestHandler) -> RequestResult {
|
2021-03-04 18:51:52 +01:00
|
|
|
let conv_id = r.post_conv("convID")?.conv_id;
|
2021-02-10 17:16:52 +01:00
|
|
|
|
|
|
|
// Check if the conversation can have a call
|
2021-03-04 18:51:52 +01:00
|
|
|
let conv = conversations_helper::get_single(conv_id)?;
|
2021-02-10 17:16:52 +01:00
|
|
|
if !calls_helper::can_have_call(&conv) {
|
|
|
|
r.forbidden("This conversation can not be used to make calls!".to_string())?;
|
|
|
|
}
|
|
|
|
|
2021-02-10 18:26:19 +01:00
|
|
|
// Remove any other active call with current WebSocket
|
|
|
|
if let Some(call) = &r.get_conn().active_call {
|
2022-03-12 07:47:22 +01:00
|
|
|
make_user_leave_call(&call.conv_id, r.get_conn()).await?;
|
2021-02-10 18:26:19 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Remove any other active connection to current call of current user
|
2022-03-12 07:47:22 +01:00
|
|
|
for conn in user_ws_controller::get_all_connections()? {
|
2021-02-13 14:37:15 +01:00
|
|
|
if conn.user_id() != r.user_id_ref()? || conn.session.eq(&r.get_conn().session) {
|
2022-03-12 08:15:52 +01:00
|
|
|
continue;
|
2021-02-10 18:26:19 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if let Some(call) = &conn.active_call {
|
|
|
|
if call.conv_id == conv_id {
|
2022-03-12 07:47:22 +01:00
|
|
|
make_user_leave_call(&call.conv_id, &conn).await?;
|
2021-02-10 18:26:19 +01:00
|
|
|
}
|
|
|
|
}
|
2023-05-31 19:10:05 +02:00
|
|
|
}
|
2021-02-10 17:16:52 +01:00
|
|
|
|
2023-05-31 19:10:05 +02:00
|
|
|
r.update_conn(|r| {
|
|
|
|
r.active_call = Some(ActiveCall {
|
|
|
|
conv_id,
|
|
|
|
ready: false,
|
|
|
|
})
|
|
|
|
})?;
|
2021-02-10 17:16:52 +01:00
|
|
|
|
|
|
|
// Propagate event
|
2022-03-12 07:47:22 +01:00
|
|
|
events_helper::propagate_event(Event::UserJoinedCall(conv_id, r.user_id()?)).await?;
|
2021-02-10 17:16:52 +01:00
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2021-02-10 18:04:03 +01:00
|
|
|
/// Leave a call
|
2022-03-12 07:47:22 +01:00
|
|
|
pub async fn leave_call(r: &mut UserWsRequestHandler) -> RequestResult {
|
2021-02-10 18:04:03 +01:00
|
|
|
// Warning ! For some technical reasons, we do not check if the user
|
|
|
|
// really belongs to the conversation, so be careful when manipulating
|
|
|
|
// conversation ID here
|
2021-03-04 18:51:52 +01:00
|
|
|
let conv_id = ConvID::new(r.post_u64("convID")?);
|
2021-02-10 18:04:03 +01:00
|
|
|
|
|
|
|
// Check if the user was not in the conversation
|
|
|
|
if !r.get_conn().is_having_call_with_conversation(&conv_id) {
|
|
|
|
return r.success("Left call!");
|
|
|
|
}
|
|
|
|
|
|
|
|
// Make the user leave the call
|
2022-03-12 07:47:22 +01:00
|
|
|
make_user_leave_call(&conv_id, r.get_conn()).await?;
|
2021-02-10 18:04:03 +01:00
|
|
|
|
|
|
|
r.success("Left call!")
|
|
|
|
}
|
|
|
|
|
2021-02-10 17:32:14 +01:00
|
|
|
/// Get the list of members of a call
|
2022-03-12 07:47:22 +01:00
|
|
|
pub async fn get_members_list(r: &mut UserWsRequestHandler) -> RequestResult {
|
2021-02-10 17:32:14 +01:00
|
|
|
let conv_id = r.post_call_id("callID")?;
|
|
|
|
let mut list = vec![];
|
|
|
|
|
|
|
|
user_ws_controller::foreach_connection(|conn| {
|
|
|
|
if conn.is_having_call_with_conversation(&conv_id) {
|
2023-05-31 19:10:05 +02:00
|
|
|
list.push(CallMemberInfo::new(
|
|
|
|
conn.user_id(),
|
|
|
|
&conn.active_call.as_ref().unwrap(),
|
|
|
|
));
|
2021-02-10 17:32:14 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
})?;
|
|
|
|
|
|
|
|
r.set_response(list)
|
|
|
|
}
|
|
|
|
|
2021-02-11 18:29:29 +01:00
|
|
|
/// Get the hash associated to a call
|
|
|
|
pub fn gen_call_hash(call_id: &ConvID, peer_id: &UserID) -> String {
|
2021-03-04 18:51:52 +01:00
|
|
|
format!("{}-{}", call_id.id(), peer_id.id())
|
2021-02-11 18:29:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Handles client signal
|
2022-03-12 07:47:22 +01:00
|
|
|
pub async fn on_client_signal(r: &mut UserWsRequestHandler) -> RequestResult {
|
2021-02-11 18:29:29 +01:00
|
|
|
let call_id = r.post_call_id("callID")?;
|
|
|
|
let peer_id = r.post_call_peer_id(&call_id, "peerID")?;
|
|
|
|
let sig_type = r.post_string("type")?;
|
|
|
|
|
|
|
|
let data: serde_json::Value = serde_json::from_str(&r.post_string("data")?)?;
|
|
|
|
let data = data
|
|
|
|
.as_object()
|
|
|
|
.ok_or(ExecError::boxed_new("Signal data is not an object !"))?;
|
|
|
|
|
|
|
|
let signal = match sig_type.as_str() {
|
|
|
|
"SDP" => {
|
|
|
|
// Get SDP type
|
2023-05-31 19:10:05 +02:00
|
|
|
let sdp_type = SdpType::from_str(
|
|
|
|
data.get("type")
|
|
|
|
.unwrap_or(&serde_json::Value::Null)
|
|
|
|
.as_str()
|
|
|
|
.ok_or(ExecError::boxed_new("Missing SDP type !"))?,
|
2021-02-11 18:29:29 +01:00
|
|
|
)?;
|
|
|
|
|
|
|
|
let sdp = data
|
|
|
|
.get("sdp")
|
|
|
|
.unwrap_or(&serde_json::Value::Null)
|
|
|
|
.as_str()
|
|
|
|
.ok_or(ExecError::boxed_new("Failed to get sdp message data!"))?;
|
|
|
|
|
|
|
|
let parsed_sdp = webrtc_sdp::parse_sdp(sdp, false)?;
|
|
|
|
|
|
|
|
CallSignal::SDP(sdp.to_string(), sdp_type, parsed_sdp)
|
|
|
|
}
|
|
|
|
|
|
|
|
"CANDIDATE" => {
|
|
|
|
let candidate = data
|
|
|
|
.get("candidate")
|
|
|
|
.unwrap_or(&serde_json::Value::Null)
|
|
|
|
.as_str()
|
2023-05-31 19:10:05 +02:00
|
|
|
.ok_or(ExecError::boxed_new(
|
|
|
|
"Failed to get candidate message data!",
|
|
|
|
))?
|
2021-02-11 18:29:29 +01:00
|
|
|
.to_string();
|
|
|
|
|
|
|
|
let sdp_m_line_index = data
|
|
|
|
.get("sdpMLineIndex")
|
|
|
|
.unwrap_or(&serde_json::Value::Null)
|
|
|
|
.as_u64()
|
|
|
|
.ok_or(ExecError::boxed_new("Failed to get sdp_mline_index data!"))?;
|
|
|
|
|
|
|
|
let sdp_mid = data
|
|
|
|
.get("sdpMid")
|
|
|
|
.unwrap_or(&serde_json::Value::Null)
|
|
|
|
.as_str()
|
|
|
|
.ok_or(ExecError::boxed_new("Failed to get sdpMid message data!"))?
|
|
|
|
.to_string();
|
|
|
|
|
|
|
|
let parsed_candidate: SdpAttribute = candidate.trim().parse()?;
|
|
|
|
|
2023-05-31 19:10:05 +02:00
|
|
|
CallSignal::Candidate(
|
|
|
|
IceCandidate {
|
|
|
|
candidate,
|
|
|
|
sdp_m_line_index,
|
|
|
|
sdp_mid,
|
|
|
|
},
|
|
|
|
parsed_candidate,
|
|
|
|
)
|
2021-02-11 18:29:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
_ => {
|
|
|
|
r.forbidden("Invalid signal type!".to_string())?;
|
|
|
|
unreachable!()
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2022-03-12 07:47:22 +01:00
|
|
|
events_helper::propagate_event(Event::NewUserCallSignal(NewUserCallSignal {
|
2021-02-11 18:29:29 +01:00
|
|
|
call_hash: gen_call_hash(&call_id, &peer_id),
|
2023-05-31 19:10:05 +02:00
|
|
|
user_id: if r.user_id_ref()? == &peer_id {
|
|
|
|
None
|
|
|
|
} else {
|
|
|
|
Some(r.user_id()?)
|
|
|
|
},
|
2021-02-11 18:29:29 +01:00
|
|
|
signal,
|
|
|
|
raw_data: r.post_string("data")?,
|
2023-05-31 19:10:05 +02:00
|
|
|
}))
|
|
|
|
.await?;
|
2021-02-11 18:29:29 +01:00
|
|
|
|
|
|
|
r.success("Signal sent")
|
|
|
|
}
|
|
|
|
|
2021-02-11 19:21:24 +01:00
|
|
|
/// Mark user ready for streaming
|
2022-03-12 07:47:22 +01:00
|
|
|
pub async fn mark_user_ready(r: &mut UserWsRequestHandler) -> Res {
|
2021-02-11 19:21:24 +01:00
|
|
|
let call_id = r.post_call_id("callID")?;
|
|
|
|
let user_id = r.user_id()?;
|
|
|
|
|
|
|
|
r.update_call(|call| call.ready = true)?;
|
|
|
|
|
|
|
|
user_ws_controller::send_message_to_specific_connections(
|
2021-02-13 14:37:15 +01:00
|
|
|
|c| c.user_id() != &user_id && c.is_having_call_with_conversation(&call_id),
|
2023-05-31 19:10:05 +02:00
|
|
|
|_| {
|
|
|
|
UserWsMessage::no_id_message(
|
|
|
|
"call_peer_ready",
|
|
|
|
CallPeerReadyAPI::new(&call_id, r.user_id_ref()?),
|
|
|
|
)
|
|
|
|
},
|
2021-02-11 19:21:24 +01:00
|
|
|
)?;
|
|
|
|
|
|
|
|
r.success("Information propagated.")
|
|
|
|
}
|
|
|
|
|
2021-02-12 13:32:36 +01:00
|
|
|
/// Request an offer from the server
|
2022-03-12 07:47:22 +01:00
|
|
|
pub async fn request_offer(r: &mut UserWsRequestHandler) -> Res {
|
2021-02-12 13:32:36 +01:00
|
|
|
let call_id = r.post_call_id("callID")?;
|
|
|
|
|
|
|
|
// The ID of the user we stream the audio / video from
|
|
|
|
let peer_id = r.post_call_peer_id(&call_id, "peerID")?;
|
|
|
|
|
|
|
|
if !peer_id.is_valid() || peer_id == r.user_id_ref()? {
|
|
|
|
r.forbidden("You can not request an offer for yourself!".to_string())?;
|
|
|
|
}
|
|
|
|
|
2022-03-12 07:47:22 +01:00
|
|
|
events_helper::propagate_event(Event::UserRequestedCallOffer(UserCallOfferRequest {
|
2021-02-12 13:32:36 +01:00
|
|
|
call_hash: gen_call_hash(&call_id, &peer_id),
|
|
|
|
user_id: r.user_id()?,
|
2023-05-31 19:10:05 +02:00
|
|
|
}))
|
|
|
|
.await?;
|
2021-02-12 13:32:36 +01:00
|
|
|
|
|
|
|
r.success("Request sent")
|
|
|
|
}
|
|
|
|
|
2021-02-12 13:52:47 +01:00
|
|
|
/// Notify the user stopped to stream
|
2022-03-12 07:47:22 +01:00
|
|
|
pub async fn stop_streaming(r: &mut UserWsRequestHandler) -> Res {
|
2021-02-12 13:52:47 +01:00
|
|
|
let call_id = r.post_call_id("callID")?;
|
|
|
|
let user_id = r.user_id()?;
|
|
|
|
|
|
|
|
// Propagate notification only if required
|
|
|
|
if r.call_info(&call_id)?.ready {
|
|
|
|
r.update_call(|c| c.ready = false)?;
|
|
|
|
|
|
|
|
// Notify all other users
|
|
|
|
user_ws_controller::send_message_to_specific_connections(
|
2021-02-13 14:37:15 +01:00
|
|
|
|c| c.is_having_call_with_conversation(&call_id) && c.user_id() != &user_id,
|
2023-05-31 19:10:05 +02:00
|
|
|
|_| {
|
|
|
|
UserWsMessage::no_id_message(
|
|
|
|
"call_peer_interrupted_streaming",
|
|
|
|
CallPeerInterruptedStreamingAPI::new(&call_id, &user_id),
|
|
|
|
)
|
|
|
|
},
|
2021-02-12 13:52:47 +01:00
|
|
|
)?;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Notify proxy
|
2022-03-12 07:47:22 +01:00
|
|
|
events_helper::propagate_event(Event::CloseCallStream(CloseCallStream {
|
2021-02-12 13:52:47 +01:00
|
|
|
call_hash: gen_call_hash(&call_id, &user_id),
|
|
|
|
peer_id: None,
|
2023-05-31 19:10:05 +02:00
|
|
|
}))
|
|
|
|
.await?;
|
2021-02-12 13:52:47 +01:00
|
|
|
|
|
|
|
r.success("ok")
|
|
|
|
}
|
|
|
|
|
2021-02-10 18:04:03 +01:00
|
|
|
/// Make the user leave the call
|
2022-03-12 07:47:22 +01:00
|
|
|
pub async fn make_user_leave_call(conv_id: &ConvID, connection: &UserWsConnection) -> Res {
|
2021-02-10 18:04:03 +01:00
|
|
|
connection.clone().replace(|c| c.active_call = None);
|
|
|
|
|
|
|
|
// Notify user (if possible)
|
|
|
|
if connection.session.connected() {
|
2023-05-31 19:10:05 +02:00
|
|
|
user_ws_controller::send_to_client(
|
|
|
|
connection,
|
|
|
|
&UserWsMessage::no_id_message("call_closed", conv_id.id())?,
|
|
|
|
)?;
|
2021-02-10 18:04:03 +01:00
|
|
|
}
|
|
|
|
|
2021-02-12 16:46:11 +01:00
|
|
|
// Close main stream (sender)
|
2022-03-12 07:47:22 +01:00
|
|
|
events_helper::propagate_event(Event::CloseCallStream(CloseCallStream {
|
2021-02-13 14:37:15 +01:00
|
|
|
call_hash: gen_call_hash(&conv_id, connection.user_id()),
|
2021-02-12 16:46:11 +01:00
|
|
|
peer_id: None,
|
2023-05-31 19:10:05 +02:00
|
|
|
}))
|
|
|
|
.await?;
|
2021-02-10 18:04:03 +01:00
|
|
|
|
2021-02-12 16:46:11 +01:00
|
|
|
// Close receiver streams (other users streams)
|
2022-03-12 07:47:22 +01:00
|
|
|
for peer_conn in user_ws_controller::get_all_connections()? {
|
2023-05-31 19:10:05 +02:00
|
|
|
if peer_conn.is_having_call_with_conversation(conv_id)
|
|
|
|
&& peer_conn.user_id() != connection.user_id()
|
|
|
|
{
|
2022-03-12 07:47:22 +01:00
|
|
|
events_helper::propagate_event(Event::CloseCallStream(CloseCallStream {
|
|
|
|
call_hash: gen_call_hash(&conv_id, peer_conn.user_id()),
|
|
|
|
peer_id: Some(connection.user_id().clone()),
|
2023-05-31 19:10:05 +02:00
|
|
|
}))
|
|
|
|
.await?;
|
2022-03-12 07:47:22 +01:00
|
|
|
}
|
2023-05-31 19:10:05 +02:00
|
|
|
}
|
2021-02-10 18:04:03 +01:00
|
|
|
|
|
|
|
// Create a notification
|
2022-03-12 07:47:22 +01:00
|
|
|
events_helper::propagate_event(Event::UserLeftCall(
|
|
|
|
conv_id.clone(),
|
|
|
|
connection.user_id().clone(),
|
2023-05-31 19:10:05 +02:00
|
|
|
))
|
|
|
|
.await?;
|
2021-02-10 18:04:03 +01:00
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2021-02-10 17:16:52 +01:00
|
|
|
/// Events handler
|
2022-03-12 07:47:22 +01:00
|
|
|
pub async fn handle_event(e: &events_helper::Event) -> Res {
|
2021-02-10 17:16:52 +01:00
|
|
|
match e {
|
|
|
|
Event::UserJoinedCall(conv_id, user_id) => {
|
|
|
|
user_ws_controller::send_message_to_specific_connections(
|
2021-02-13 14:37:15 +01:00
|
|
|
|c| c.is_having_call_with_conversation(conv_id) && c.user_id() != user_id,
|
2023-05-31 19:10:05 +02:00
|
|
|
|_| {
|
|
|
|
UserWsMessage::no_id_message(
|
|
|
|
"user_joined_call",
|
|
|
|
JoinedCallMessage::new(conv_id, user_id),
|
|
|
|
)
|
|
|
|
},
|
2021-02-10 17:16:52 +01:00
|
|
|
)?;
|
|
|
|
}
|
|
|
|
|
2021-02-10 18:04:03 +01:00
|
|
|
Event::UserLeftCall(conv_id, user_id) => {
|
|
|
|
user_ws_controller::send_message_to_specific_connections(
|
|
|
|
|c| c.is_having_call_with_conversation(conv_id),
|
2023-05-31 19:10:05 +02:00
|
|
|
|_| {
|
|
|
|
UserWsMessage::no_id_message(
|
|
|
|
"user_left_call",
|
|
|
|
LeftCallMessage::new(conv_id, user_id),
|
|
|
|
)
|
|
|
|
},
|
2021-02-10 18:04:03 +01:00
|
|
|
)?;
|
|
|
|
}
|
|
|
|
|
|
|
|
Event::UserWsClosed(c) => {
|
|
|
|
if let Some(call) = c.active_call.clone() {
|
2022-03-12 07:47:22 +01:00
|
|
|
make_user_leave_call(&call.conv_id, c).await?;
|
2021-02-10 18:04:03 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-02-11 19:07:30 +01:00
|
|
|
Event::NewRTCRelayMessage(msg) => {
|
|
|
|
// Get call hash
|
|
|
|
let split: Vec<&str> = msg.call_hash.split("-").collect();
|
|
|
|
if split.len() != 2 {
|
|
|
|
return Ok(());
|
|
|
|
}
|
|
|
|
|
2021-03-04 18:51:52 +01:00
|
|
|
let call_id = ConvID::new(split[0].parse::<u64>()?);
|
2021-02-11 19:07:30 +01:00
|
|
|
let peer_id = UserID::new(split[1].parse::<u64>()?);
|
|
|
|
|
|
|
|
let target_user = UserID::new(msg.peer_id.parse::<u64>()?);
|
|
|
|
let target_user = match target_user.is_valid() {
|
|
|
|
true => target_user,
|
2023-05-31 19:10:05 +02:00
|
|
|
false => peer_id.clone(),
|
2021-02-11 19:07:30 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
user_ws_controller::send_message_to_specific_connections(
|
2021-02-13 14:37:15 +01:00
|
|
|
|c| c.user_id() == target_user && c.is_having_call_with_conversation(&call_id),
|
2023-05-31 19:10:05 +02:00
|
|
|
|_| {
|
|
|
|
UserWsMessage::no_id_message(
|
|
|
|
"new_call_signal",
|
|
|
|
NewCallSignalAPI::new(&call_id, &peer_id, &msg.data)?,
|
|
|
|
)
|
|
|
|
},
|
2021-02-11 19:07:30 +01:00
|
|
|
)?;
|
|
|
|
}
|
|
|
|
|
2021-02-12 16:46:11 +01:00
|
|
|
// Handle proxy disconnect => close all active calls
|
|
|
|
Event::ClosedRTCRelayWebSocket => {
|
2022-03-12 07:47:22 +01:00
|
|
|
for f in user_ws_controller::get_all_connections()? {
|
2021-02-12 16:46:11 +01:00
|
|
|
// Close all active connections
|
|
|
|
if let Some(call) = &f.active_call {
|
2022-03-12 07:47:22 +01:00
|
|
|
make_user_leave_call(&call.conv_id, &f).await?;
|
2021-02-12 16:46:11 +01:00
|
|
|
}
|
2023-05-31 19:10:05 +02:00
|
|
|
}
|
2021-02-12 16:46:11 +01:00
|
|
|
}
|
2021-02-12 13:54:18 +01:00
|
|
|
|
2021-03-07 19:36:48 +01:00
|
|
|
// Call active call of user (if any)
|
|
|
|
Event::RemovedUserFromConversation(user_id, conv_id) => {
|
|
|
|
let mut conn = None;
|
|
|
|
user_ws_controller::foreach_connection(|f| {
|
|
|
|
if f.user_id() == user_id && f.is_having_call_with_conversation(conv_id) {
|
|
|
|
conn = Some(f.clone());
|
|
|
|
}
|
|
|
|
Ok(())
|
|
|
|
})?;
|
|
|
|
|
|
|
|
if let Some(c) = conn {
|
2022-03-12 07:47:22 +01:00
|
|
|
make_user_leave_call(conv_id, &c).await?;
|
2021-03-07 19:36:48 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-13 12:24:20 +01:00
|
|
|
// Call active call of user (if any)
|
|
|
|
Event::DeletedConversation(conv_id) => {
|
2021-03-13 13:46:36 +01:00
|
|
|
let mut connections = vec![];
|
2021-03-13 12:24:20 +01:00
|
|
|
user_ws_controller::foreach_connection(|f| {
|
|
|
|
if f.is_having_call_with_conversation(conv_id) {
|
2021-03-13 13:46:36 +01:00
|
|
|
connections.push(f.clone());
|
2021-03-13 12:24:20 +01:00
|
|
|
}
|
|
|
|
Ok(())
|
|
|
|
})?;
|
|
|
|
|
2021-03-13 13:46:36 +01:00
|
|
|
for con in connections {
|
2022-03-12 07:47:22 +01:00
|
|
|
make_user_leave_call(conv_id, &con).await?;
|
2021-03-13 12:24:20 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-02-10 17:16:52 +01:00
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
2023-05-31 19:10:05 +02:00
|
|
|
}
|