Commit e8aef044 authored by jehan's avatar jehan
Browse files

Allows incoming call to be accepted even if an outgoing call is in progress....

Allows incoming call to be accepted even if an outgoing call is in progress. In such case, outgoing call is automatically canceled.
parent 705384eb
......@@ -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 = {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment