diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index c2ff6a028..fa290f411 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -3012,6 +3012,47 @@ void linphone_core_notify_incoming_call(LinphoneCore *lc, LinphoneCall *call){ ms_free(tmp); } +int linphone_core_accept_early_media_with_params(LinphoneCore* lc, LinphoneCall* call, bool_t early_media, LinphoneCallParams* params) { + if (call->state==LinphoneCallIncomingReceived){ + SalMediaDescription* md; + + /*try to be best-effort in giving real local or routable contact address for 100Rel case*/ + linphone_call_set_contact_op(call); + + // if parameters are passed, update the media description + if ( params ) { + md = sal_call_get_remote_media_description ( call->op ); + _linphone_call_params_copy ( &call->params,params ); + + // There might not be a md if the INVITE was lacking an SDP + // In this case we use the parameters as is. + if ( md ) call->params.has_video &= linphone_core_media_description_contains_video_stream ( md ); + + linphone_call_make_local_media_description ( lc,call ); + sal_call_set_local_media_description ( call->op,call->localdesc ); + sal_op_set_sent_custom_header ( call->op,params->custom_headers ); + } + + sal_call_notify_ringing(call->op,early_media); + + if (early_media){ + linphone_call_set_state(call,LinphoneCallIncomingEarlyMedia,"Incoming call early media"); + md=sal_call_get_final_media_description(call->op); + if (md) linphone_core_update_streams(lc,call,md); + } + if (sal_call_get_replaces(call->op)!=NULL && lp_config_get_int(lc->config,"sip","auto_answer_replacing_calls",1)){ + linphone_core_accept_call(lc,call); + } + return 0; + } + + return -1; +} + +int linphone_core_accept_early_media(LinphoneCore* lc, LinphoneCall* call, bool_t early_media){ + return linphone_core_accept_early_media_with_params(lc, call, early_media, NULL); +} + int linphone_core_start_update_call(LinphoneCore *lc, LinphoneCall *call){ const char *subject; diff --git a/coreapi/linphonecore.h b/coreapi/linphonecore.h index 291748312..a98e29be0 100644 --- a/coreapi/linphonecore.h +++ b/coreapi/linphonecore.h @@ -1404,6 +1404,10 @@ LINPHONE_PUBLIC int linphone_core_accept_call(LinphoneCore *lc, LinphoneCall *ca LINPHONE_PUBLIC int linphone_core_accept_call_with_params(LinphoneCore *lc, LinphoneCall *call, const LinphoneCallParams *params); +LINPHONE_PUBLIC int linphone_core_accept_early_media_with_params(LinphoneCore* lc, LinphoneCall* call, bool_t early_media, LinphoneCallParams* params); + +LINPHONE_PUBLIC int linphone_core_accept_early_media(LinphoneCore* lc, LinphoneCall* call, bool_t early_media); + LINPHONE_PUBLIC int linphone_core_terminate_call(LinphoneCore *lc, LinphoneCall *call); /** diff --git a/tester/call_tester.c b/tester/call_tester.c index 6c8710dba..8e4f80771 100644 --- a/tester/call_tester.c +++ b/tester/call_tester.c @@ -1080,6 +1080,54 @@ static void early_media_call(void) { linphone_core_manager_destroy(pauline); } +static void early_media_call_with_ringing(void){ + + LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc"); + LinphoneCoreManager* pauline = linphone_core_manager_new("pauline_rc"); + MSList* lcs = NULL; + LinphoneCall* marie_call; + + lcs = ms_list_append(lcs,marie->lc); + lcs = ms_list_append(lcs,pauline->lc); + /* + Marie calls Pauline, and after the call has rung, transitions to an early_media session + */ + + marie_call = linphone_core_invite_address(marie->lc, pauline->identity); + + CU_ASSERT_TRUE(wait_for_list(lcs, &pauline->stat.number_of_LinphoneCallIncomingReceived,1,1000)); + CU_ASSERT_TRUE(wait_for_list(lcs, &marie->stat.number_of_LinphoneCallOutgoingRinging,1,1000)); + + + /* send a 183 to initiate the early media */ + + linphone_core_accept_early_media(pauline->lc, linphone_core_get_current_call(pauline->lc), TRUE); + + CU_ASSERT_TRUE( wait_for_list(lcs, &pauline->stat.number_of_LinphoneCallIncomingEarlyMedia,1,2000) ); + CU_ASSERT_TRUE( wait_for_list(lcs, &marie->stat.number_of_LinphoneCallOutgoingEarlyMedia,1,2000) ); + + liblinphone_tester_check_rtcp(marie, pauline); + + linphone_core_accept_call(pauline->lc, linphone_core_get_current_call(pauline->lc)); + + CU_ASSERT_TRUE(wait_for_list(lcs, &marie->stat.number_of_LinphoneCallStreamsRunning, 1,1000)); + + CU_ASSERT_EQUAL(marie_call, linphone_core_get_current_call(marie->lc)); + + liblinphone_tester_check_rtcp(marie, pauline); + + linphone_core_terminate_all_calls(pauline->lc); + + CU_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneCallEnd,1,1000)); + CU_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneCallEnd,1,1000)); + + + ms_list_free(lcs); + + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); +} + static void simple_call_transfer(void) { LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc"); @@ -1548,6 +1596,7 @@ test_t call_tests[] = { { "Call with media relay", call_with_media_relay}, { "Simple call compatibility mode", simple_call_compatibility_mode }, { "Early-media call", early_media_call }, + { "Early-media call with ringing", early_media_call_with_ringing }, { "Call terminated by caller", call_terminated_by_caller }, { "Call without SDP", call_with_no_sdp}, { "Call paused resumed", call_paused_resumed },