Commit 0d87a22d authored by Simon Morlat's avatar Simon Morlat
Browse files

fix bugs in Paused state management. It was possible to transition from Paused...

fix bugs in Paused state management. It was possible to transition from Paused to PausedByRemote, which actually breaks the Paused state, and eventually allows the pauser to be resumed by the paused.
parent a4594aec
......@@ -43,6 +43,9 @@ SalStreamDir sal_dir_from_call_params_dir(LinphoneMediaDirection cpdir) {
return SalStreamRecvOnly;
case LinphoneMediaDirectionSendRecv:
return SalStreamSendRecv;
case LinphoneMediaDirectionInvalid:
ms_error("LinphoneMediaDirectionInvalid shall not be used.");
return SalStreamInactive;
}
return SalStreamSendRecv;
}
......
......@@ -34,11 +34,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* Indicates for a given media the stream direction
* */
enum _LinphoneMediaDirection {
LinphoneMediaDirectionInvalid = -1,
LinphoneMediaDirectionInactive, /** No active media not supported yet*/
LinphoneMediaDirectionSendOnly, /** Send only mode*/
LinphoneMediaDirectionRecvOnly, /** recv only mode*/
LinphoneMediaDirectionSendRecv, /** send receive*/
};
/**
* Typedef for enum
......
......@@ -329,7 +329,7 @@ static void call_received(SalOp *h){
call=linphone_call_new_incoming(lc,from_addr,to_addr,h);
linphone_call_make_local_media_description(lc,call);
linphone_call_make_local_media_description(call);
sal_call_set_local_media_description(call->op,call->localdesc);
md=sal_call_get_final_media_description(call->op);
if (md){
......@@ -637,7 +637,12 @@ static void call_updated(LinphoneCore *lc, LinphoneCall *call, SalOp *op, bool_t
if (sal_media_description_has_dir(rmd,SalStreamSendRecv) || sal_media_description_has_dir(rmd,SalStreamRecvOnly)){
call_resumed(lc,call);
}else{
_linphone_core_accept_call_update(lc,call,NULL,call->state,linphone_call_state_to_string(call->state));
/*we are staying in PausedByRemote*/
linphone_core_notify_display_status(lc,_("Call is updated by remote."));
linphone_call_set_state(call, LinphoneCallUpdatedByRemote,"Call updated by remote");
if (call->defer_update == FALSE){
linphone_core_accept_call_update(lc,call,NULL);
}
}
break;
/*SIP UPDATE CASE*/
......@@ -662,12 +667,8 @@ static void call_updated(LinphoneCore *lc, LinphoneCall *call, SalOp *op, bool_t
}
break;
case LinphoneCallPaused:
if (sal_media_description_has_dir(rmd,SalStreamSendOnly) || sal_media_description_has_dir(rmd,SalStreamInactive)){
call_paused_by_remote(lc,call);
}else{
/*we'll remain in pause state but accept the offer anyway according to default parameters*/
_linphone_core_accept_call_update(lc,call,NULL,call->state,linphone_call_state_to_string(call->state));
}
/*we'll remain in pause state but accept the offer anyway according to default parameters*/
_linphone_core_accept_call_update(lc,call,NULL,call->state,linphone_call_state_to_string(call->state));
break;
case LinphoneCallUpdating:
case LinphoneCallPausing:
......@@ -702,7 +703,7 @@ static void call_updating(SalOp *op, bool_t is_update){
}
if (call->state!=LinphoneCallPaused){
/*Refresh the local description, but in paused state, we don't change anything.*/
linphone_call_make_local_media_description(lc,call);
linphone_call_make_local_media_description(call);
sal_call_set_local_media_description(call->op,call->localdesc);
}
if (rmd == NULL){
......
......@@ -582,11 +582,30 @@ static const char *linphone_call_get_public_ip_for_stream(LinphoneCall *call, in
return public_ip;
}
void linphone_call_make_local_media_description(LinphoneCore *lc, LinphoneCall *call) {
linphone_call_make_local_media_description_with_params(lc, call, call->params);
static void force_streams_dir_according_to_state(LinphoneCall *call, SalMediaDescription *md){
int i;
switch (call->state){
case LinphoneCallPausing:
case LinphoneCallPaused:
break;
default:
return;
break;
}
for (i=0; i<2; ++i){
SalStreamDescription *sd = &md->streams[i];
sd->dir = SalStreamSendOnly;
if (sd->type == SalVideo){
if (lp_config_get_int(call->core->config, "sip", "inactive_video_on_pause", 0)) {
sd->dir = SalStreamInactive;
}
}
}
}
void linphone_call_make_local_media_description_with_params(LinphoneCore *lc, LinphoneCall *call, LinphoneCallParams *params) {
void linphone_call_make_local_media_description(LinphoneCall *call) {
MSList *l;
SalMediaDescription *old_md=call->localdesc;
int i;
......@@ -595,6 +614,9 @@ void linphone_call_make_local_media_description_with_params(LinphoneCore *lc, Li
LinphoneAddress *addr;
const char *subject;
CodecConstraints codec_hints={0};
LinphoneCallParams *params = call->params;
LinphoneCore *lc = call->core;
/*multicast is only set in case of outgoing call*/
if (call->dir == LinphoneCallOutgoing && linphone_call_params_audio_multicast_enabled(params)) {
......@@ -718,6 +740,7 @@ void linphone_call_make_local_media_description_with_params(LinphoneCore *lc, Li
call->localdesc_changed=sal_media_description_equals(md,old_md);
sal_media_description_unref(old_md);
}
force_streams_dir_according_to_state(call, md);
}
static int find_port_offset(LinphoneCore *lc, int stream_index, int base_port){
......
......@@ -2768,7 +2768,7 @@ int linphone_core_start_invite(LinphoneCore *lc, LinphoneCall *call, const Linph
linphone_call_set_contact_op(call);
linphone_core_stop_dtmf_stream(lc);
linphone_call_make_local_media_description(lc,call);
linphone_call_make_local_media_description(call);
if (lc->ringstream==NULL) {
if (lc->sound_conf.play_sndcard && lc->sound_conf.capt_sndcard){
......@@ -3171,7 +3171,7 @@ int linphone_core_accept_early_media_with_params(LinphoneCore* lc, LinphoneCall*
// if parameters are passed, update the media description
if ( params ) {
linphone_call_set_new_params(call,params);
linphone_call_make_local_media_description ( lc,call );
linphone_call_make_local_media_description (call);
sal_call_set_local_media_description ( call->op,call->localdesc );
sal_op_set_sent_custom_header ( call->op,params->custom_headers );
}
......@@ -3209,7 +3209,7 @@ int linphone_core_start_update_call(LinphoneCore *lc, LinphoneCall *call){
linphone_call_fill_media_multicast_addr(call);
if (!no_user_consent) linphone_call_make_local_media_description(lc,call);
if (!no_user_consent) linphone_call_make_local_media_description(call);
#ifdef BUILD_UPNP
if(call->upnp_session != NULL) {
linphone_core_update_local_media_description_from_upnp(call->localdesc, call->upnp_session);
......@@ -3350,15 +3350,24 @@ int linphone_core_update_call(LinphoneCore *lc, LinphoneCall *call, const Linpho
* the call state notification, to deactivate the automatic answer that would just confirm the audio but reject the video.
* Then, when the user responds to dialog prompt, it becomes possible to call linphone_core_accept_call_update() to answer
* the reINVITE, with eventually video enabled in the LinphoneCallParams argument.
*
* The #LinphoneCallUpdatedByRemote notification can also arrive when receiving an INVITE without SDP. In such case, an unchanged offer is made
* in the 200Ok, and when the ACK containing the SDP answer is received, #LinphoneCallUpdatedByRemote is triggered to notify the application of possible
* changes in the media session. However in such case defering the update has no meaning since we just generating an offer.
*
* @return 0 if successful, -1 if the linphone_core_defer_call_update() was done outside a #LinphoneCallUpdatedByRemote notification, which is illegal.
* @return 0 if successful, -1 if the linphone_core_defer_call_update() was done outside a valid #LinphoneCallUpdatedByRemote notification.
**/
int linphone_core_defer_call_update(LinphoneCore *lc, LinphoneCall *call){
if (call->state==LinphoneCallUpdatedByRemote){
if (call->expect_media_in_ack){
ms_error("linphone_core_defer_call_update() is not possible during a late offer incoming reINVITE (INVITE without SDP)");
return -1;
}
call->defer_update=TRUE;
return 0;
}else{
ms_error("linphone_core_defer_call_update() not done in state LinphoneCallUpdatedByRemote");
}
ms_error("linphone_core_defer_call_update() not done in state LinphoneCallUpdatedByRemote");
return -1;
}
......@@ -3370,7 +3379,7 @@ int linphone_core_start_accept_call_update(LinphoneCore *lc, LinphoneCall *call,
return 0;
}
}
linphone_call_make_local_media_description(lc,call);
linphone_call_make_local_media_description(call);
linphone_call_update_remote_session_id_and_ver(call);
linphone_call_stop_ice_for_inactive_streams(call);
......@@ -3587,7 +3596,7 @@ int linphone_core_accept_call_with_params(LinphoneCore *lc, LinphoneCall *call,
linphone_call_set_compatible_incoming_call_parameters(call, md);
}
linphone_call_prepare_ice(call,TRUE);
linphone_call_make_local_media_description(lc,call);
linphone_call_make_local_media_description(call);
sal_call_set_local_media_description(call->op,call->localdesc);
sal_op_set_sent_custom_header(call->op,params->custom_headers);
}
......@@ -3797,10 +3806,8 @@ int linphone_core_pause_call(LinphoneCore *lc, LinphoneCall *call){
}
/* Internal version that does not play tone indication*/
int _linphone_core_pause_call(LinphoneCore *lc, LinphoneCall *call)
{
int _linphone_core_pause_call(LinphoneCore *lc, LinphoneCall *call){
const char *subject=NULL;
LinphoneCallParams *params;
if (call->state!=LinphoneCallStreamsRunning && call->state!=LinphoneCallPausedByRemote){
ms_warning("Cannot pause this call, it is not active.");
......@@ -3814,15 +3821,8 @@ int _linphone_core_pause_call(LinphoneCore *lc, LinphoneCall *call)
ms_error("No reason to pause this call, it is already paused or inactive.");
return -1;
}
params = linphone_call_params_copy(call->params);
linphone_call_params_set_audio_direction(params, LinphoneMediaDirectionSendOnly);
if (lp_config_get_int(lc->config, "sip", "inactive_video_on_pause", 0)) {
linphone_call_params_set_video_direction(params, LinphoneMediaDirectionInactive);
} else {
linphone_call_params_set_video_direction(params, LinphoneMediaDirectionSendOnly);
}
linphone_call_make_local_media_description_with_params(lc, call, params);
linphone_call_params_unref(params);
linphone_call_set_state(call, LinphoneCallPausing, "Pausing call");
linphone_call_make_local_media_description(call);
#ifdef BUILD_UPNP
if(call->upnp_session != NULL) {
linphone_core_update_local_media_description_from_upnp(call->localdesc, call->upnp_session);
......@@ -3836,7 +3836,6 @@ int _linphone_core_pause_call(LinphoneCore *lc, LinphoneCall *call)
linphone_core_notify_display_status(lc,_("Pausing the current call..."));
if (call->audiostream || call->videostream)
linphone_call_stop_media_streams (call);
linphone_call_set_state(call,LinphoneCallPausing,"Pausing call");
call->paused_by_app=FALSE;
return 0;
}
......@@ -3903,7 +3902,7 @@ int linphone_core_resume_call(LinphoneCore *lc, LinphoneCall *call){
prevents the participants to hear it while the 200OK comes back.*/
if (call->audiostream) audio_stream_play(call->audiostream, NULL);
linphone_call_make_local_media_description(lc,call);
linphone_call_make_local_media_description(call);
#ifdef BUILD_UPNP
if(call->upnp_session != NULL) {
linphone_core_update_local_media_description_from_upnp(call->localdesc, call->upnp_session);
......
......@@ -897,7 +897,7 @@ int linphone_core_set_as_current_call(LinphoneCore *lc, LinphoneCall *call);
int linphone_core_get_calls_nb(const LinphoneCore *lc);
void linphone_core_set_state(LinphoneCore *lc, LinphoneGlobalState gstate, const char *message);
void linphone_call_make_local_media_description(LinphoneCore *lc, LinphoneCall *call);
void linphone_call_make_local_media_description(LinphoneCall *call);
void linphone_call_make_local_media_description_with_params(LinphoneCore *lc, LinphoneCall *call, LinphoneCallParams *params);
void linphone_call_increment_local_media_description(LinphoneCall *call);
void linphone_call_fill_media_multicast_addr(LinphoneCall *call);
......
......@@ -160,26 +160,27 @@ static bool_t is_null_address(const char *addr){
/*check for the presence of at least one stream with requested direction */
static bool_t has_dir(const SalMediaDescription *md, SalStreamDir stream_dir){
int i;
/* we are looking for at least one stream with requested direction, inactive streams are ignored*/
for(i=0;i<md->nb_streams;++i){
const SalStreamDescription *ss=&md->streams[i];
if (!sal_stream_description_active(ss)) continue;
if (ss->dir==stream_dir) return TRUE;
if (ss->dir==stream_dir) {
return TRUE;
}
/*compatibility check for phones that only used the null address and no attributes */
if (ss->dir==SalStreamSendRecv && stream_dir==SalStreamSendOnly && (is_null_address(md->addr) || is_null_address(ss->rtp_addr)))
if (ss->dir==SalStreamSendRecv && stream_dir==SalStreamSendOnly && (is_null_address(md->addr) || is_null_address(ss->rtp_addr))){
return TRUE;
}
}
return FALSE;
}
bool_t sal_media_description_has_dir(const SalMediaDescription *md, SalStreamDir stream_dir){
if (stream_dir==SalStreamRecvOnly){
if (has_dir(md,SalStreamSendOnly) || has_dir(md,SalStreamSendRecv)) return FALSE;
else return TRUE;
return has_dir(md, SalStreamRecvOnly) && !(has_dir(md,SalStreamSendOnly) || has_dir(md,SalStreamSendRecv));
}else if (stream_dir==SalStreamSendOnly){
if (has_dir(md,SalStreamRecvOnly) || has_dir(md,SalStreamSendRecv)) return FALSE;
else return TRUE;
return has_dir(md, SalStreamSendOnly) && !(has_dir(md,SalStreamRecvOnly) || has_dir(md,SalStreamSendRecv));
}else if (stream_dir==SalStreamSendRecv){
return has_dir(md,SalStreamSendRecv);
}else{
......
......@@ -1240,6 +1240,74 @@ end:
static void call_paused_resumed(void) {
call_paused_resumed_base(FALSE);
}
static void call_paused_by_both() {
LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc");
LinphoneCoreManager* pauline = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc");
LinphoneCall* call_pauline, *call_marie;
const rtp_stats_t * stats;
MSList *lcs = NULL;
bool_t call_ok;
lcs = ms_list_append(lcs, pauline->lc);
lcs = ms_list_append(lcs, marie->lc);
BC_ASSERT_TRUE((call_ok=call(pauline,marie)));
if (!call_ok) goto end;
call_pauline = linphone_core_get_current_call(pauline->lc);
call_marie = linphone_core_get_current_call(marie->lc);
wait_for_until(pauline->lc, marie->lc, NULL, 5, 2000);
linphone_core_pause_call(pauline->lc,call_pauline);
BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallPausing,1));
BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneCallPausedByRemote,1));
BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallPaused,1));
/*stay in pause a little while in order to generate traffic*/
wait_for_until(pauline->lc, marie->lc, NULL, 5, 2000);
/*marie pauses the call also*/
linphone_core_pause_call(marie->lc, call_marie);
BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneCallPausing,1));
BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneCallPaused,1));
wait_for_until(pauline->lc, marie->lc, NULL, 5, 2000);
/*pauline must stay in paused state*/
BC_ASSERT_EQUAL(pauline->stat.number_of_LinphoneCallPaused, 1, int, "%i");
check_media_direction(pauline, call_pauline, lcs, LinphoneMediaDirectionInactive, LinphoneMediaDirectionInvalid);
check_media_direction(marie, call_marie, lcs, LinphoneMediaDirectionInactive, LinphoneMediaDirectionInvalid);
/*now pauline wants to resume*/
linphone_core_resume_call(pauline->lc, call_pauline);
BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallResuming,1));
BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallPausedByRemote,1));
/*Marie must stay in paused state*/
wait_for_until(pauline->lc, marie->lc, NULL, 5, 2000);
BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneCallPaused, 1, int, "%i");
/*now marie wants to resume also*/
linphone_core_resume_call(marie->lc, call_marie);
BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneCallResuming,1));
BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneCallStreamsRunning,2));
BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallStreamsRunning,2));
/*same here: wait a while for a bit of a traffic, we need to receive a RTCP packet*/
wait_for_until(pauline->lc, marie->lc, NULL, 5, 5000);
/*since RTCP streams are reset when call is paused/resumed, there should be no loss at all*/
stats = rtp_session_get_stats(call_pauline->sessions->rtp_session);
BC_ASSERT_EQUAL(stats->cum_packet_loss, 0, int, "%d");
end_call(marie, pauline);
end:
linphone_core_manager_destroy(marie);
linphone_core_manager_destroy(pauline);
ms_list_free(lcs);
}
#define CHECK_CURRENT_LOSS_RATE() \
rtcp_count_current = pauline->stat.number_of_rtcp_sent; \
/*wait for an RTCP packet to have an accurate cumulative lost value*/ \
......@@ -3225,48 +3293,59 @@ void check_media_direction(LinphoneCoreManager* mgr, LinphoneCall *call, MSList*
if (call) {
const LinphoneCallParams *params = linphone_call_get_current_params(call);
#ifdef VIDEO_ENABLED
int current_recv_iframe = mgr->stat.number_of_IframeDecoded;
int expected_recv_iframe=0;
int dummy = 0;
if (video_dir != LinphoneMediaDirectionInvalid){
int current_recv_iframe = mgr->stat.number_of_IframeDecoded;
int expected_recv_iframe=0;
int dummy = 0;
BC_ASSERT_EQUAL(video_dir,linphone_call_params_get_video_direction(params), int, "%d");
linphone_call_set_next_video_frame_decoded_callback(call,linphone_call_iframe_decoded_cb,mgr->lc);
linphone_call_send_vfu_request(call);
if (video_dir != LinphoneMediaDirectionInactive){
BC_ASSERT_TRUE(linphone_call_params_video_enabled(params));
}
BC_ASSERT_EQUAL(linphone_call_params_get_video_direction(params), video_dir, int, "%d");
linphone_call_set_next_video_frame_decoded_callback(call,linphone_call_iframe_decoded_cb,mgr->lc);
linphone_call_send_vfu_request(call);
wait_for_list(lcs,&dummy,1,2000); /*on some device, it may take 3 to 4s to get audio from mic*/
wait_for_list(lcs,&dummy,1,2000); /*on some device, it may take 3 to 4s to get audio from mic*/
switch (video_dir) {
case LinphoneMediaDirectionInactive:
BC_ASSERT_TRUE(linphone_call_get_video_stats(call)->upload_bandwidth<5);
case LinphoneMediaDirectionSendOnly:
expected_recv_iframe = 0;
BC_ASSERT_TRUE(linphone_call_get_video_stats(call)->download_bandwidth<5);
break;
case LinphoneMediaDirectionRecvOnly:
BC_ASSERT_TRUE(linphone_call_get_video_stats(call)->upload_bandwidth<5);
case LinphoneMediaDirectionSendRecv:
expected_recv_iframe = 1;
break;
}
BC_ASSERT_TRUE(wait_for_list(lcs, &mgr->stat.number_of_IframeDecoded,current_recv_iframe + expected_recv_iframe,3000));
#endif
BC_ASSERT_EQUAL(audio_dir,linphone_call_params_get_audio_direction(params), int, "%d");
switch (audio_dir) {
switch (video_dir) {
case LinphoneMediaDirectionInactive:
BC_ASSERT_TRUE(linphone_call_get_audio_stats(call)->upload_bandwidth<5);
BC_ASSERT_TRUE(linphone_call_get_video_stats(call)->upload_bandwidth<5);
case LinphoneMediaDirectionSendOnly:
expected_recv_iframe = 0;
BC_ASSERT_TRUE(linphone_call_get_video_stats(call)->download_bandwidth<5);
if (audio_dir == LinphoneMediaDirectionSendOnly) BC_ASSERT_TRUE(wait_for_list(lcs,mgr->stat.current_audio_upload_bandwidth,70,4000));
break;
case LinphoneMediaDirectionRecvOnly:
BC_ASSERT_TRUE(linphone_call_get_audio_stats(call)->upload_bandwidth<5);
BC_ASSERT_TRUE(linphone_call_get_video_stats(call)->upload_bandwidth<5);
case LinphoneMediaDirectionSendRecv:
BC_ASSERT_TRUE(wait_for_list(lcs,mgr->stat.current_audio_download_bandwidth,70,4000));
if (audio_dir == LinphoneMediaDirectionSendRecv) BC_ASSERT_TRUE(wait_for_list(lcs,mgr->stat.current_audio_upload_bandwidth,70,4000));
expected_recv_iframe = 1;
break;
default:
break;
}
BC_ASSERT_TRUE(wait_for_list(lcs, &mgr->stat.number_of_IframeDecoded,current_recv_iframe + expected_recv_iframe,3000));
}
#endif
if (audio_dir != LinphoneMediaDirectionInvalid){
BC_ASSERT_EQUAL(linphone_call_params_get_audio_direction(params), audio_dir, int, "%d");
switch (audio_dir) {
case LinphoneMediaDirectionInactive:
BC_ASSERT_TRUE(linphone_call_get_audio_stats(call)->upload_bandwidth<5);
case LinphoneMediaDirectionSendOnly:
BC_ASSERT_TRUE(linphone_call_get_video_stats(call)->download_bandwidth<5);
if (audio_dir == LinphoneMediaDirectionSendOnly) BC_ASSERT_TRUE(wait_for_list(lcs,mgr->stat.current_audio_upload_bandwidth,70,4000));
break;
case LinphoneMediaDirectionRecvOnly:
BC_ASSERT_TRUE(linphone_call_get_audio_stats(call)->upload_bandwidth<5);
case LinphoneMediaDirectionSendRecv:
BC_ASSERT_TRUE(wait_for_list(lcs,mgr->stat.current_audio_download_bandwidth,70,4000));
if (audio_dir == LinphoneMediaDirectionSendRecv) BC_ASSERT_TRUE(wait_for_list(lcs,mgr->stat.current_audio_upload_bandwidth,70,4000));
break;
default:
break;
}
}
}
}
......@@ -3281,11 +3360,11 @@ static void accept_call_in_send_only_base(LinphoneCoreManager* pauline, Linphone
linphone_core_enable_video(pauline->lc,TRUE,TRUE);
linphone_core_set_video_policy(pauline->lc,&pol);
linphone_core_set_video_device(pauline->lc,"Mire: Mire (synthetic moving picture)");
linphone_core_set_video_device(pauline->lc,liblinphone_tester_mire_id);
linphone_core_enable_video(marie->lc,TRUE,TRUE);
linphone_core_set_video_policy(marie->lc,&pol);
linphone_core_set_video_device(marie->lc,"Mire: Mire (synthetic moving picture)");
linphone_core_set_video_device(marie->lc,liblinphone_tester_mire_id);
linphone_call_set_next_video_frame_decoded_callback(linphone_core_invite_address(pauline->lc,marie->identity)
,linphone_call_iframe_decoded_cb
......@@ -4095,8 +4174,8 @@ static void video_call_with_re_invite_inactive_followed_by_re_invite_base(Linpho
marie = linphone_core_manager_new( "marie_rc");
pauline = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc");
linphone_core_set_avpf_mode(pauline->lc,TRUE);
linphone_core_set_video_device(pauline->lc,"Mire: Mire (synthetic moving picture)");
linphone_core_set_video_device(marie->lc,"Mire: Mire (synthetic moving picture)");
linphone_core_set_video_device(pauline->lc,liblinphone_tester_mire_id);
linphone_core_set_video_device(marie->lc,liblinphone_tester_mire_id);
linphone_core_set_avpf_mode(marie->lc,TRUE);
lcs=ms_list_append(lcs,pauline->lc);
lcs=ms_list_append(lcs,marie->lc);
......@@ -4281,13 +4360,24 @@ static void call_with_complex_late_offering(void){
LinphoneCoreManager* pauline = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc");
LinphoneCall* call_pauline;
LinphoneCall* call_marie;
LinphoneVideoPolicy vpol = {TRUE, TRUE};
bool_t call_ok;
BC_ASSERT_TRUE(call(pauline,marie));
linphone_core_enable_video(pauline->lc, TRUE, TRUE);
linphone_core_enable_video(marie->lc, TRUE, TRUE);
linphone_core_set_video_policy(pauline->lc, &vpol);
linphone_core_set_video_policy(marie->lc, &vpol);
linphone_core_set_video_device(pauline->lc,liblinphone_tester_mire_id);
linphone_core_set_video_device(marie->lc,liblinphone_tester_mire_id);
BC_ASSERT_TRUE((call_ok=call(pauline,marie)));
if (!call_ok) goto end;
call_pauline = linphone_core_get_current_call(pauline->lc);
call_marie = linphone_core_get_current_call(marie->lc);
//Invite inactive Audio/video (Marie pause Pauline)
ms_message("CONTEXT: Marie sends INVITE with SDP with all streams inactive");
params=linphone_core_create_call_params(marie->lc,call_marie);
linphone_call_params_set_audio_direction(params,LinphoneMediaDirectionInactive);
linphone_call_params_set_video_direction(params,LinphoneMediaDirectionInactive);
......@@ -4295,66 +4385,75 @@ static void call_with_complex_late_offering(void){
linphone_core_update_call(marie->lc, call_marie ,params);
linphone_call_params_destroy(params);
BC_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&marie->stat.number_of_LinphoneCallUpdating,1));
BC_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&pauline->stat.number_of_LinphoneCallPausedByRemote,1));
BC_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&marie->stat.number_of_LinphoneCallPaused,1));
BC_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&marie->stat.number_of_LinphoneCallStreamsRunning,2));
//Marie send INVITE without SDP
//Marie sends INVITE without SDP
ms_message("CONTEXT: Marie sends INVITE without SDP for setting streams in send-only mode");
linphone_core_enable_sdp_200_ack(marie->lc,TRUE);
params=linphone_core_create_call_params(marie->lc,call_marie);
linphone_call_params_set_audio_direction(params,LinphoneMediaDirectionSendOnly);
linphone_call_params_set_video_direction(params,LinphoneMediaDirectionSendOnly);
linphone_core_update_call(marie->lc, call_marie , params);
linphone_call_params_destroy(params);
//Pauline OK with sendonly
BC_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&marie->stat.number_of_LinphoneCallUpdating,1));
BC_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&marie->stat.number_of_LinphoneCallPaused,2));
BC_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&marie->stat.number_of_LinphoneCallUpdating,2));
BC_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&marie->stat.number_of_LinphoneCallStreamsRunning,3));
BC_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&pauline->stat.number_of_LinphoneCallPausedByRemote,2));
linphone_core_enable_sdp_200_ack(marie->lc,FALSE);
BC_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&pauline->stat.number_of_LinphoneCallStreamsRunning,2));
//Pauline pause Marie
ms_message("CONTEXT: Pauline pauses the call");
linphone_core_pause_call(pauline->lc,call_pauline);
BC_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&pauline->stat.number_of_LinphoneCallPausing,1));
BC_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&pauline->stat.number_of_LinphoneCallPaused,1));
BC_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&marie->stat.number_of_LinphoneCallPausedByRemote,1));
//Pauline resume Marie
wait_for_until(pauline->lc, marie->lc, NULL, 5, 5000);
ms_message("CONTEXT: Pauline resumes the call");
wait_for_until(pauline->lc, marie->lc, NULL, 5, 2000);
linphone_core_resume_call(pauline->lc,call_pauline);
BC_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&marie->stat.number_of_LinphoneCallStreamsRunning,4));
BC_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&pauline->stat.number_of_LinphoneCallResuming,1));
BC_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&pauline->stat.number_of_LinphoneCallPausedByRemote,1));
BC_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&pauline->stat.number_of_LinphoneCallPausedByRemote,3));
wait_for_until(pauline->lc, marie->lc, NULL, 0, 2000);
//Marie invite inactive Audio/Video
ms_message("CONTEXT: Marie sends INVITE with SDP with all streams inactive");
params=linphone_core_create_call_params(marie->lc,call_marie);
linphone_call_params_set_audio_direction(params,LinphoneMediaDirectionInactive);
linphone_call_params_set_video_direction(params,LinphoneMediaDirectionInactive);
linphone_core_update_call(marie->lc, call_marie,params);
BC_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&marie->stat.number_of_LinphoneCallUpdating,3));
linphone_call_params_destroy(params);
BC_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&pauline->stat.number_of_LinphoneCallStreamsRunning,3));
BC_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&marie->stat.number_of_LinphoneCallPaused,3));
BC_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&pauline->stat.number_of_LinphoneCallPausedByRemote,4));
BC_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&marie->stat.number_of_LinphoneCallStreamsRunning,5));
//Marie send INVITE without SDP
//Marie sends INVITE without SDP
ms_message("CONTEXT: Marie sends INVITE without SDP in the purpose of re-enabling streams in sendrecv mode");
linphone_core_enable_sdp_200_ack(marie->lc,TRUE);
params=linphone_core_create_call_params(marie->lc,call_marie);
linphone_call_params_set_audio_direction(params,LinphoneMediaDirectionSendRecv);
linphone_call_params_set_video_direction(params,LinphoneMediaDirectionSendRecv);
linphone_core_update_call(marie->lc, call_marie,params);
BC_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&marie->stat.number_of_LinphoneCallUpdating,3));
linphone_call_params_destroy(params);
BC_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&pauline->stat.number_of_LinphoneCallUpdatedByRemote,1));
BC_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&pauline->stat.number_of_LinphoneCallStreamsRunning,2));
BC_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&marie->stat.number_of_LinphoneCallStreamsRunning,5));
linphone_core_enable_sdp_200_ack(marie->lc,FALSE);
BC_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&pauline->stat.number_of_LinphoneCallStreamsRunning,4));
BC_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&marie->stat.number_of_LinphoneCallPaused,4));
end_call(marie,pauline);
BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &pauline->stat.number_of_LinphoneCallEnd, 1));
BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &marie->stat.number_of_LinphoneCallEnd, 1));
end:
linphone_core_manager_destroy(marie);
linphone_core_manager_destroy(pauline);
......@@ -4830,6 +4929,7 @@ test_t call_tests[] = {
{ "Call without SDP", call_with_no_sdp},
{ "Call without SDP and ACK without SDP", call_with_no_sdp_ack_without_sdp},
{ "Call paused resumed", call_paused_resumed },
{ "Call paused by both parties", call_paused_by_both },
{ "Call paused resumed with loss", call_paused_resumed_with_loss },
{ "Call paused resumed from callee", call_paused_resumed_from_callee },