mirror of
https://gitlab.linphone.org/BC/public/linphone-iphone.git
synced 2026-01-22 05:38:14 +00:00
Allows incoming call to be accepted even if an outgoing call is in progress. In such case, outgoing call is automatically canceled.
This commit is contained in:
parent
705384ebb4
commit
e8aef044fb
5 changed files with 159 additions and 27 deletions
|
|
@ -245,18 +245,6 @@ static bool_t already_a_call_with_remote_address(const LinphoneCore *lc, const L
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
static bool_t already_an_outgoing_call_pending(LinphoneCore *lc){
|
||||
MSList *elem;
|
||||
for(elem=lc->calls;elem!=NULL;elem=elem->next){
|
||||
LinphoneCall *call=(LinphoneCall*)elem->data;
|
||||
if (call->state==LinphoneCallOutgoingInit
|
||||
|| call->state==LinphoneCallOutgoingProgress
|
||||
|| call->state==LinphoneCallOutgoingRinging){
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void call_received(SalOp *h){
|
||||
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(h));
|
||||
|
|
@ -264,9 +252,9 @@ static void call_received(SalOp *h){
|
|||
char *alt_contact;
|
||||
LinphoneAddress *from_addr=NULL;
|
||||
LinphoneAddress *to_addr=NULL;
|
||||
/*this mode is deprcated because probably useless*/
|
||||
bool_t prevent_colliding_calls=lp_config_get_int(lc->config,"sip","prevent_colliding_calls",FALSE);
|
||||
LinphoneAddress *from_address_to_search_if_me=NULL; /*address used to know if I'm the caller*/
|
||||
SalMediaDescription *md;
|
||||
const char * p_asserted_id;
|
||||
|
||||
/* first check if we can answer successfully to this invite */
|
||||
if (linphone_presence_model_get_basic_status(lc->presence_model) == LinphonePresenceBasicStatusClosed) {
|
||||
|
|
@ -300,9 +288,9 @@ static void call_received(SalOp *h){
|
|||
sal_op_release(h);
|
||||
return;
|
||||
}
|
||||
p_asserted_id = sal_custom_header_find(sal_op_get_recv_custom_header(h),"P-Asserted-Identity");
|
||||
/*in some situation, better to trust the network rather than the UAC*/
|
||||
if (lp_config_get_int(lc->config,"sip","call_logs_use_asserted_id_instead_of_from",0)) {
|
||||
const char * p_asserted_id = sal_custom_header_find(sal_op_get_recv_custom_header(h),"P-Asserted-Identity");
|
||||
LinphoneAddress *p_asserted_id_addr;
|
||||
if (!p_asserted_id) {
|
||||
ms_warning("No P-Asserted-Identity header found so cannot use it for op [%p] instead of from",h);
|
||||
|
|
@ -321,13 +309,26 @@ static void call_received(SalOp *h){
|
|||
from_addr=linphone_address_new(sal_op_get_from(h));
|
||||
to_addr=linphone_address_new(sal_op_get_to(h));
|
||||
|
||||
if ((already_a_call_with_remote_address(lc,from_addr) && prevent_colliding_calls) || already_an_outgoing_call_pending(lc)){
|
||||
ms_warning("Receiving a call while one is initiated, refusing this one with busy message.");
|
||||
if (sal_op_get_privacy(h) == SalPrivacyNone) {
|
||||
from_address_to_search_if_me=linphone_address_clone(from_addr);
|
||||
} else if (p_asserted_id) {
|
||||
from_address_to_search_if_me = linphone_address_new(p_asserted_id);
|
||||
} else {
|
||||
ms_warning ("Hidden from identity, don't know if it's me");
|
||||
}
|
||||
|
||||
if (from_address_to_search_if_me && already_a_call_with_remote_address(lc,from_address_to_search_if_me)){
|
||||
char *addr = linphone_address_as_string(from_addr);
|
||||
ms_warning("Receiving a call while one with same address [%s] is initiated, refusing this one with busy message.",addr);
|
||||
sal_call_decline(h,SalReasonBusy,NULL);
|
||||
sal_op_release(h);
|
||||
linphone_address_destroy(from_addr);
|
||||
linphone_address_destroy(to_addr);
|
||||
linphone_address_destroy(from_address_to_search_if_me);
|
||||
ms_free(addr);
|
||||
return;
|
||||
} else if (from_address_to_search_if_me) {
|
||||
linphone_address_destroy(from_address_to_search_if_me);
|
||||
}
|
||||
|
||||
call=linphone_call_new_incoming(lc,from_addr,to_addr,h);
|
||||
|
|
|
|||
|
|
@ -3721,6 +3721,7 @@ int linphone_core_accept_call_with_params(LinphoneCore *lc, LinphoneCall *call,
|
|||
SalOp *replaced;
|
||||
SalMediaDescription *new_md;
|
||||
bool_t was_ringing=FALSE;
|
||||
MSList * iterator;
|
||||
|
||||
if (call==NULL){
|
||||
//if just one call is present answer the only one ...
|
||||
|
|
@ -3741,6 +3742,28 @@ int linphone_core_accept_call_with_params(LinphoneCore *lc, LinphoneCall *call,
|
|||
break;
|
||||
}
|
||||
|
||||
|
||||
for (iterator=ms_list_copy(linphone_core_get_calls(lc));iterator!=NULL;iterator=iterator->next) {
|
||||
LinphoneCall *a_call=(LinphoneCall*)iterator->data;
|
||||
if (a_call==call) continue;
|
||||
switch(a_call->state){
|
||||
case LinphoneCallOutgoingInit:
|
||||
case LinphoneCallOutgoingProgress:
|
||||
case LinphoneCallOutgoingRinging:
|
||||
case LinphoneCallOutgoingEarlyMedia:
|
||||
|
||||
ms_message("Already existing call [%p] in state [%s], canceling it before accepting new call [%p]" ,a_call
|
||||
,linphone_call_state_to_string(a_call->state)
|
||||
,call);
|
||||
linphone_core_terminate_call(lc,a_call);
|
||||
break;
|
||||
default:
|
||||
break; /*nothing to do*/
|
||||
}
|
||||
|
||||
}
|
||||
if (iterator) ms_list_free(iterator);
|
||||
|
||||
/* check if this call is supposed to replace an already running one*/
|
||||
replaced=sal_call_get_replaces(call->op);
|
||||
if (replaced){
|
||||
|
|
@ -4138,9 +4161,17 @@ static int remote_address_compare(LinphoneCall *call, const LinphoneAddress *rad
|
|||
* @ingroup call_control
|
||||
*/
|
||||
LinphoneCall *linphone_core_get_call_by_remote_address(LinphoneCore *lc, const char *remote_address){
|
||||
LinphoneCall *call=NULL;
|
||||
LinphoneAddress *raddr=linphone_address_new(remote_address);
|
||||
if (raddr) {
|
||||
call=linphone_core_get_call_by_remote_address2(lc, raddr);
|
||||
linphone_address_unref(raddr);
|
||||
}
|
||||
return call;
|
||||
}
|
||||
LinphoneCall *linphone_core_get_call_by_remote_address2(LinphoneCore *lc, LinphoneAddress *raddr){
|
||||
MSList *elem=ms_list_find_custom(lc->calls,(int (*)(const void*,const void *))remote_address_compare,raddr);
|
||||
linphone_address_unref(raddr);
|
||||
|
||||
if (elem) return (LinphoneCall*) elem->data;
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2237,6 +2237,17 @@ LINPHONE_PUBLIC LinphoneCallParams *linphone_core_create_call_params(LinphoneCor
|
|||
|
||||
LINPHONE_PUBLIC LinphoneCall *linphone_core_get_call_by_remote_address(LinphoneCore *lc, const char *remote_address);
|
||||
|
||||
/**
|
||||
* Get the call with the remote_address specified
|
||||
* @param lc
|
||||
* @param remote_address
|
||||
* @return the LinphoneCall of the call if found
|
||||
*
|
||||
* @ingroup call_control
|
||||
*/
|
||||
LINPHONE_PUBLIC LinphoneCall *linphone_core_get_call_by_remote_address2(LinphoneCore *lc, LinphoneAddress *remote_address);
|
||||
|
||||
|
||||
/**
|
||||
* Send the specified dtmf.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -207,6 +207,7 @@ bool_t call_with_params2(LinphoneCoreManager* caller_mgr
|
|||
LinphoneCallParams *caller_params = caller_test_params->base;
|
||||
LinphoneCallParams *callee_params = callee_test_params->base;
|
||||
bool_t did_receive_call;
|
||||
LinphoneCall *callee_call=NULL;
|
||||
|
||||
setup_sdp_handling(caller_test_params, caller_mgr);
|
||||
setup_sdp_handling(callee_test_params, callee_mgr);
|
||||
|
|
@ -229,7 +230,8 @@ bool_t call_with_params2(LinphoneCoreManager* caller_mgr
|
|||
if (!did_receive_call) return 0;
|
||||
|
||||
|
||||
CU_ASSERT_TRUE(linphone_core_inc_invite_pending(callee_mgr->lc));
|
||||
if (linphone_core_get_calls_nb(callee_mgr->lc)<=1)
|
||||
CU_ASSERT_TRUE(linphone_core_inc_invite_pending(callee_mgr->lc));
|
||||
CU_ASSERT_EQUAL(caller_mgr->stat.number_of_LinphoneCallOutgoingProgress,initial_caller.number_of_LinphoneCallOutgoingProgress+1);
|
||||
|
||||
|
||||
|
|
@ -247,6 +249,8 @@ bool_t call_with_params2(LinphoneCoreManager* caller_mgr
|
|||
|
||||
|
||||
CU_ASSERT_PTR_NOT_NULL(linphone_core_get_current_call_remote_address(callee_mgr->lc));
|
||||
callee_call=linphone_core_get_call_by_remote_address2(callee_mgr->lc,caller_mgr->identity);
|
||||
|
||||
if(!linphone_core_get_current_call(caller_mgr->lc) || !linphone_core_get_current_call(callee_mgr->lc) || !linphone_core_get_current_call_remote_address(callee_mgr->lc)) {
|
||||
return 0;
|
||||
} else if (caller_mgr->identity){
|
||||
|
|
@ -256,21 +260,23 @@ bool_t call_with_params2(LinphoneCoreManager* caller_mgr
|
|||
if (linphone_call_params_get_privacy(linphone_call_get_current_params(linphone_core_get_current_call(caller_mgr->lc))) == LinphonePrivacyNone) {
|
||||
/*don't check in case of p asserted id*/
|
||||
if (!lp_config_get_int(callee_mgr->lc->config,"sip","call_logs_use_asserted_id_instead_of_from",0))
|
||||
CU_ASSERT_TRUE(linphone_address_weak_equal(callee_from,linphone_core_get_current_call_remote_address(callee_mgr->lc)));
|
||||
CU_ASSERT_TRUE(linphone_address_weak_equal(callee_from,linphone_call_get_remote_address(callee_call)));
|
||||
} else {
|
||||
CU_ASSERT_FALSE(linphone_address_weak_equal(callee_from,linphone_core_get_current_call_remote_address(callee_mgr->lc)));
|
||||
CU_ASSERT_FALSE(linphone_address_weak_equal(callee_from,linphone_call_get_remote_address(linphone_core_get_current_call(callee_mgr->lc))));
|
||||
}
|
||||
linphone_address_destroy(callee_from);
|
||||
}
|
||||
|
||||
|
||||
if (callee_params){
|
||||
linphone_core_accept_call_with_params(callee_mgr->lc,linphone_core_get_current_call(callee_mgr->lc),callee_params);
|
||||
linphone_core_accept_call_with_params(callee_mgr->lc,callee_call,callee_params);
|
||||
}else if (build_callee_params){
|
||||
LinphoneCallParams *default_params=linphone_core_create_call_params(callee_mgr->lc,linphone_core_get_current_call(callee_mgr->lc));
|
||||
LinphoneCallParams *default_params=linphone_core_create_call_params(callee_mgr->lc,callee_call);
|
||||
ms_message("Created default call params with video=%i", linphone_call_params_video_enabled(default_params));
|
||||
linphone_core_accept_call_with_params(callee_mgr->lc,linphone_core_get_current_call(callee_mgr->lc),default_params);
|
||||
linphone_core_accept_call_with_params(callee_mgr->lc,callee_call,default_params);
|
||||
linphone_call_params_destroy(default_params);
|
||||
}else{
|
||||
linphone_core_accept_call(callee_mgr->lc,linphone_core_get_current_call(callee_mgr->lc));
|
||||
linphone_core_accept_call(callee_mgr->lc,callee_call);
|
||||
}
|
||||
|
||||
CU_ASSERT_TRUE(wait_for(callee_mgr->lc,caller_mgr->lc,&callee_mgr->stat.number_of_LinphoneCallConnected,initial_callee.number_of_LinphoneCallConnected+1));
|
||||
|
|
@ -291,7 +297,7 @@ bool_t call_with_params2(LinphoneCoreManager* caller_mgr
|
|||
|| (linphone_core_get_media_encryption(caller_mgr->lc) == LinphoneMediaEncryptionDTLS) /*also take care of caller policy*/ )
|
||||
wait_for(callee_mgr->lc,caller_mgr->lc,&callee_mgr->stat.number_of_LinphoneCallEncryptedOn,initial_callee.number_of_LinphoneCallEncryptedOn+1);
|
||||
{
|
||||
const LinphoneCallParams* call_param = linphone_call_get_current_params(linphone_core_get_current_call(callee_mgr->lc));
|
||||
const LinphoneCallParams* call_param = linphone_call_get_current_params(callee_call);
|
||||
CU_ASSERT_EQUAL(linphone_call_params_get_media_encryption(call_param),linphone_core_get_media_encryption(caller_mgr->lc));
|
||||
call_param = linphone_call_get_current_params(linphone_core_get_current_call(caller_mgr->lc));
|
||||
CU_ASSERT_EQUAL(linphone_call_params_get_media_encryption(call_param),linphone_core_get_media_encryption(caller_mgr->lc));
|
||||
|
|
@ -902,6 +908,21 @@ static void early_declined_call(void) {
|
|||
linphone_core_manager_destroy(pauline);
|
||||
}
|
||||
|
||||
static void call_busy_when_calling_self(void) {
|
||||
LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc");
|
||||
LinphoneCall *out_call=linphone_core_invite_address(marie->lc,marie->identity);
|
||||
linphone_call_ref(out_call);
|
||||
|
||||
/*wait until flexisip transfers the busy...*/
|
||||
CU_ASSERT_TRUE(wait_for_until(marie->lc,marie->lc,&marie->stat.number_of_LinphoneCallError,1,33000));
|
||||
CU_ASSERT_EQUAL(marie->stat.number_of_LinphoneCallError,1);
|
||||
|
||||
CU_ASSERT_EQUAL(linphone_call_get_reason(out_call),LinphoneReasonBusy);
|
||||
linphone_call_unref(out_call);
|
||||
linphone_core_manager_destroy(marie);
|
||||
}
|
||||
|
||||
|
||||
static void call_declined(void) {
|
||||
LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc");
|
||||
LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc");
|
||||
|
|
@ -4040,6 +4061,7 @@ test_t call_tests[] = {
|
|||
{ "Early cancelled call", early_cancelled_call},
|
||||
{ "Call with DNS timeout", call_with_dns_time_out },
|
||||
{ "Cancelled ringing call", cancelled_ringing_call },
|
||||
{ "Call busy when calling self", call_busy_when_calling_self},
|
||||
{ "Simple call", simple_call },
|
||||
{ "Call with timeouted bye", call_with_timeouted_bye },
|
||||
{ "Direct call over IPv6", direct_call_over_ipv6},
|
||||
|
|
|
|||
|
|
@ -115,6 +115,70 @@ static void call_waiting_indication_with_privacy(void) {
|
|||
call_waiting_indication_with_param(TRUE);
|
||||
}
|
||||
|
||||
static void incoming_call_accepted_when_outgoing_call_in_state(LinphoneCallState state) {
|
||||
LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc");
|
||||
LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc");
|
||||
LinphoneCoreManager* laure = linphone_core_manager_new( "laure_rc");
|
||||
MSList* lcs;
|
||||
LinphoneCallParams *laure_params=linphone_core_create_default_call_parameters(laure->lc);
|
||||
LinphoneCallParams *marie_params=linphone_core_create_default_call_parameters(marie->lc);
|
||||
|
||||
lcs=ms_list_append(NULL,marie->lc);
|
||||
lcs=ms_list_append(lcs,pauline->lc);
|
||||
lcs=ms_list_append(lcs,laure->lc);
|
||||
|
||||
|
||||
if (state==LinphoneCallOutgoingRinging || state==LinphoneCallOutgoingEarlyMedia) {
|
||||
CU_ASSERT_PTR_NOT_NULL(linphone_core_invite_address_with_params(marie->lc,pauline->identity,marie_params));
|
||||
|
||||
CU_ASSERT_TRUE(wait_for(marie->lc
|
||||
,pauline->lc
|
||||
,&pauline->stat.number_of_LinphoneCallIncomingReceived
|
||||
,1));
|
||||
|
||||
if (state==LinphoneCallOutgoingEarlyMedia)
|
||||
linphone_core_accept_early_media(pauline->lc,linphone_core_get_current_call(pauline->lc));
|
||||
|
||||
CU_ASSERT_EQUAL(marie->stat.number_of_LinphoneCallOutgoingProgress,1);
|
||||
CU_ASSERT_TRUE(wait_for(marie->lc
|
||||
,pauline->lc
|
||||
,state==LinphoneCallOutgoingEarlyMedia?&marie->stat.number_of_LinphoneCallOutgoingEarlyMedia:&marie->stat.number_of_LinphoneCallOutgoingRinging
|
||||
,1));
|
||||
} else if (state==LinphoneCallOutgoingProgress) {
|
||||
CU_ASSERT_PTR_NOT_NULL(linphone_core_invite_address(marie->lc,pauline->identity));
|
||||
} else {
|
||||
ms_error("Unsupported state");
|
||||
return;
|
||||
}
|
||||
|
||||
CU_ASSERT_TRUE(call_with_caller_params(laure,marie,laure_params));
|
||||
|
||||
|
||||
CU_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneCallEnd,1,10000));
|
||||
|
||||
|
||||
linphone_core_terminate_all_calls(marie->lc);
|
||||
|
||||
CU_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneCallEnd,1,10000));
|
||||
CU_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneCallEnd,1,10000));
|
||||
CU_ASSERT_TRUE(wait_for_list(lcs,&laure->stat.number_of_LinphoneCallEnd,1,10000));
|
||||
|
||||
|
||||
linphone_core_manager_destroy(marie);
|
||||
linphone_core_manager_destroy(pauline);
|
||||
linphone_core_manager_destroy(laure);
|
||||
ms_list_free(lcs);
|
||||
}
|
||||
static void incoming_call_accepted_when_outgoing_call_in_progress(void) {
|
||||
incoming_call_accepted_when_outgoing_call_in_state(LinphoneCallOutgoingProgress);
|
||||
}
|
||||
static void incoming_call_accepted_when_outgoing_call_in_outgoing_ringing(void) {
|
||||
incoming_call_accepted_when_outgoing_call_in_state(LinphoneCallOutgoingRinging);
|
||||
}
|
||||
static void incoming_call_accepted_when_outgoing_call_in_outgoing_ringing_early_media(void) {
|
||||
incoming_call_accepted_when_outgoing_call_in_state(LinphoneCallOutgoingEarlyMedia);
|
||||
}
|
||||
|
||||
static void simple_conference_base(LinphoneCoreManager* marie, LinphoneCoreManager* pauline, LinphoneCoreManager* laure) {
|
||||
|
||||
stats initial_marie_stat;
|
||||
|
|
@ -437,7 +501,10 @@ test_t multi_call_tests[] = {
|
|||
{ "Simple call transfer", simple_call_transfer },
|
||||
{ "Unattended call transfer", unattended_call_transfer },
|
||||
{ "Unattended call transfer with error", unattended_call_transfer_with_error },
|
||||
{ "Call transfer existing call outgoing call", call_transfer_existing_call_outgoing_call }
|
||||
{ "Call transfer existing call outgoing call", call_transfer_existing_call_outgoing_call },
|
||||
{ "Incoming call accepted when outgoing call in progress",incoming_call_accepted_when_outgoing_call_in_progress},
|
||||
{ "Incoming call accepted when outgoing call in outgoing ringing",incoming_call_accepted_when_outgoing_call_in_outgoing_ringing},
|
||||
{ "Incoming call accepted when outgoing call in outgoing ringing early media",incoming_call_accepted_when_outgoing_call_in_outgoing_ringing_early_media},
|
||||
};
|
||||
|
||||
test_suite_t multi_call_test_suite = {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue