1
0
mirror of https://gitlab.com/comunic/comunicapiv3 synced 2024-11-29 16:56:28 +00:00

Can leave a call

This commit is contained in:
Pierre HUBERT 2021-02-10 18:04:03 +01:00
parent 3c696bde5f
commit 7a0f9620b2
8 changed files with 117 additions and 7 deletions

View File

@ -0,0 +1,25 @@
//! # Left call message
//!
//! @author Pierre Hubert
use serde::Serialize;
use crate::data::conversation::ConvID;
use crate::data::user::UserID;
/// This structure is used to give information about a user who left a call
#[derive(Serialize)]
#[allow(non_snake_case)]
pub struct LeftCallMessage {
callID: u64,
userID: u64,
}
impl LeftCallMessage {
pub fn new(call_id: &ConvID, user_id: &UserID) -> Self {
Self {
callID: call_id.clone(),
userID: user_id.id(),
}
}
}

View File

@ -60,3 +60,4 @@ pub mod res_get_ws_token;
pub mod user_calls_config; pub mod user_calls_config;
pub mod joined_call_message; pub mod joined_call_message;
pub mod call_member_info; pub mod call_member_info;
pub mod left_call_message;

View File

@ -6,14 +6,16 @@ use std::collections::HashMap;
use crate::api_data::call_member_info::CallMemberInfo; use crate::api_data::call_member_info::CallMemberInfo;
use crate::api_data::joined_call_message::JoinedCallMessage; use crate::api_data::joined_call_message::JoinedCallMessage;
use crate::api_data::left_call_message::LeftCallMessage;
use crate::api_data::user_calls_config::UserCallsConfig; use crate::api_data::user_calls_config::UserCallsConfig;
use crate::controllers::routes::RequestResult; use crate::controllers::routes::RequestResult;
use crate::controllers::user_ws_controller; use crate::controllers::user_ws_controller;
use crate::data::base_request_handler::BaseRequestHandler; use crate::data::base_request_handler::BaseRequestHandler;
use crate::data::config::conf; use crate::data::config::conf;
use crate::data::conversation::ConvID;
use crate::data::error::{ExecError, Res}; use crate::data::error::{ExecError, Res};
use crate::data::http_request_handler::HttpRequestHandler; use crate::data::http_request_handler::HttpRequestHandler;
use crate::data::user_ws_connection::ActiveCall; use crate::data::user_ws_connection::{ActiveCall, UserWsConnection};
use crate::data::user_ws_message::UserWsMessage; use crate::data::user_ws_message::UserWsMessage;
use crate::data::user_ws_request_handler::UserWsRequestHandler; use crate::data::user_ws_request_handler::UserWsRequestHandler;
use crate::helpers::{calls_helper, conversations_helper, events_helper}; use crate::helpers::{calls_helper, conversations_helper, events_helper};
@ -57,11 +59,29 @@ pub fn join_call(r: &mut UserWsRequestHandler) -> RequestResult {
}))?; }))?;
// Propagate event // Propagate event
events_helper::propagate_event(&Event::UserJoinedCall(conv_id, r.user_id()?))?; events_helper::propagate_event(&Event::UserJoinedCall(&conv_id, r.user_id_ref()?))?;
Ok(()) Ok(())
} }
/// Leave a call
pub fn leave_call(r: &mut UserWsRequestHandler) -> RequestResult {
// 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
let conv_id = r.post_u64("convID")?;
// 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
make_user_leave_call(&conv_id, r.get_conn())?;
r.success("Left call!")
}
/// Get the list of members of a call /// Get the list of members of a call
pub fn get_members_list(r: &mut UserWsRequestHandler) -> RequestResult { pub fn get_members_list(r: &mut UserWsRequestHandler) -> RequestResult {
let conv_id = r.post_call_id("callID")?; let conv_id = r.post_call_id("callID")?;
@ -79,6 +99,25 @@ pub fn get_members_list(r: &mut UserWsRequestHandler) -> RequestResult {
} }
/// Make the user leave the call
pub fn make_user_leave_call(conv_id: &ConvID, connection: &UserWsConnection) -> Res {
connection.clone().replace(|c| c.active_call = None);
// Notify user (if possible)
if connection.session.connected() {
user_ws_controller::send_to_client(connection, &UserWsMessage::no_id_message("call_closed", conv_id)?)?;
}
// TODO : call main stream (sender)
// TODO : close receiver streams (other users streams)
// Create a notification
events_helper::propagate_event(&Event::UserLeftCall(conv_id, &connection.user_id))?;
Ok(())
}
/// Events handler /// Events handler
pub fn handle_event(e: &events_helper::Event) -> Res { pub fn handle_event(e: &events_helper::Event) -> Res {
match e { match e {
@ -90,6 +129,20 @@ pub fn handle_event(e: &events_helper::Event) -> Res {
)?; )?;
} }
Event::UserLeftCall(conv_id, user_id) => {
user_ws_controller::send_message_to_specific_connections(
|c| c.is_having_call_with_conversation(conv_id),
|_| UserWsMessage::no_id_message("user_left_call", LeftCallMessage::new(conv_id, user_id)),
None::<fn(&_) -> _>,
)?;
}
Event::UserWsClosed(c) => {
if let Some(call) = c.active_call.clone() {
make_user_leave_call(&call.conv_id, c)?;
}
}
_ => {} _ => {}
} }

View File

@ -119,8 +119,8 @@ mod ws_connections_list {
continue; continue;
} }
do_update(&mut self); do_update(&mut list[i]);
list[i] = self.clone(); self = list[i].clone();
break; break;
} }
@ -324,7 +324,12 @@ impl Actor for WsSession {
} }
fn stopping(&mut self, ctx: &mut Self::Context) -> Running { fn stopping(&mut self, ctx: &mut Self::Context) -> Running {
// TODO : send an event (user_ws_closed) // Send an event (user_ws_closed)
if let Some(conn) = find_connection(ctx.address()) {
if let Err(e) = events_helper::propagate_event(&Event::UserWsClosed(&conn)) {
eprintln!("Failed to propagate web socket closed event ! {:#?}", e);
}
}
remove_connection(ctx.address()); remove_connection(ctx.address());
Running::Stop Running::Stop
@ -490,6 +495,11 @@ pub fn send_message_to_user(msg: &UserWsMessage, user: &UserID) -> Res {
Ok(()) Ok(())
} }
/// Send a message to a specific connection
pub fn send_to_client(conn: &UserWsConnection, msg: &UserWsMessage) -> Res {
send_message(conn.session.clone(), msg)
}
/// Send a message to specific users /// Send a message to specific users
pub fn send_message_to_specific_connections<F, M, A>(filter: F, msg_generator: M, after_send: Option<A>) -> Res pub fn send_message_to_specific_connections<F, M, A>(filter: F, msg_generator: M, after_send: Option<A>) -> Res
where F: Fn(&UserWsConnection) -> bool, where F: Fn(&UserWsConnection) -> bool,

View File

@ -40,6 +40,7 @@ pub fn get_user_ws_routes() -> Vec<UserWsRoute> {
// Calls controller // Calls controller
UserWsRoute::new("calls/config", calls_controller::get_config), UserWsRoute::new("calls/config", calls_controller::get_config),
UserWsRoute::new("calls/join", calls_controller::join_call), UserWsRoute::new("calls/join", calls_controller::join_call),
UserWsRoute::new("calls/leave", calls_controller::leave_call),
UserWsRoute::new("calls/members", calls_controller::get_members_list), UserWsRoute::new("calls/members", calls_controller::get_members_list),
] ]
} }

View File

@ -44,6 +44,12 @@ impl Hash for UserID {
} }
} }
impl PartialEq<&UserID> for UserID {
fn eq(&self, other: &&UserID) -> bool {
self.0 == other.0
}
}
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
pub enum UserPageStatus { pub enum UserPageStatus {
OPEN, OPEN,

View File

@ -51,6 +51,11 @@ impl UserWsRequestHandler {
return self.response.unwrap(); return self.response.unwrap();
} }
/// Get a pointer to the websocket connection
pub fn get_conn(&self) -> &UserWsConnection {
&self.connection
}
/// Update information about the WebSocket connection /// Update information about the WebSocket connection
pub fn update_conn<H>(&mut self, do_updates: H) -> ResultBoxError where H: FnOnce(&mut UserWsConnection) { pub fn update_conn<H>(&mut self, do_updates: H) -> ResultBoxError where H: FnOnce(&mut UserWsConnection) {
self.connection = self.connection.clone().replace(do_updates); self.connection = self.connection.clone().replace(do_updates);

View File

@ -11,8 +11,14 @@ use crate::data::conversation::ConvID;
use crate::data::conversation_message::ConversationMessage; use crate::data::conversation_message::ConversationMessage;
use crate::data::error::Res; use crate::data::error::Res;
use crate::data::user::UserID; use crate::data::user::UserID;
use crate::data::user_ws_connection::UserWsConnection;
pub enum Event<'a> { pub enum Event<'a> {
/// Websocket of a user was closed
///
/// This event is propagated BEFORE the removal of the connection from the list
UserWsClosed(&'a UserWsConnection),
/// Destroyed a login token /// Destroyed a login token
DestroyedLoginToken(UserID, &'a APIClient), DestroyedLoginToken(UserID, &'a APIClient),
@ -44,7 +50,10 @@ pub enum Event<'a> {
ClosedRTCRelayWebSocket, ClosedRTCRelayWebSocket,
/// User joined call /// User joined call
UserJoinedCall(ConvID, UserID), UserJoinedCall(&'a ConvID, &'a UserID),
/// User left call
UserLeftCall(&'a ConvID, &'a UserID),
/// No event /// No event
None, None,