From ed2385ce289c124d05ac4e1fa94560cf4573b494 Mon Sep 17 00:00:00 2001 From: Simon Morlat Date: Wed, 2 Sep 2015 17:30:02 +0200 Subject: [PATCH] Refactoring of states, handling of media direction, late offering and so on. Almost working except one test. --- coreapi/bellesip_sal/sal_impl.h | 8 +- coreapi/bellesip_sal/sal_op_call.c | 41 +-- coreapi/callbacks.c | 384 ++++++++++++++--------------- coreapi/linphonecall.c | 85 ++++--- coreapi/linphonecore.c | 53 +--- coreapi/misc.c | 46 ++++ coreapi/private.h | 17 +- tester/call_tester.c | 16 +- 8 files changed, 334 insertions(+), 316 deletions(-) diff --git a/coreapi/bellesip_sal/sal_impl.h b/coreapi/bellesip_sal/sal_impl.h index eae0c6bb3..b75be9156 100644 --- a/coreapi/bellesip_sal/sal_impl.h +++ b/coreapi/bellesip_sal/sal_impl.h @@ -93,7 +93,6 @@ struct SalOp{ belle_sip_header_referred_by_t *referred_by; SalMediaDescription *result; belle_sdp_session_description_t *sdp_answer; - bool_t supports_session_timers; SalOpState state; SalOpDir dir; belle_sip_refresher_t* refresher; @@ -101,14 +100,15 @@ struct SalOp{ SalOpType type; SalPrivacyMask privacy; belle_sip_header_t *event; /*used by SalOpSubscribe kinds*/ + SalOpSDPHandling sdp_handling; + int auth_requests; /*number of auth requested for this op*/ + bool_t cnx_ip_to_0000_if_sendonly_enabled; bool_t auto_answer_asked; bool_t sdp_offering; bool_t call_released; bool_t manual_refresher; bool_t has_auth_pending; - SalOpSDPHandling sdp_handling; - int auth_requests; /*number of auth requested for this op*/ - bool_t cnx_ip_to_0000_if_sendonly_enabled; /*for */ + bool_t supports_session_timers; }; diff --git a/coreapi/bellesip_sal/sal_op_call.c b/coreapi/bellesip_sal/sal_op_call.c index f6e7087bb..5474540ea 100644 --- a/coreapi/bellesip_sal/sal_op_call.c +++ b/coreapi/bellesip_sal/sal_op_call.c @@ -302,10 +302,10 @@ static void call_process_response(void *op_base, const belle_sip_response_event_ && (header_content_type = belle_sip_message_get_header_by_type(req,belle_sip_header_content_type_t)) && strcmp("application",belle_sip_header_content_type_get_type(header_content_type))==0 && strcmp("media_control+xml",belle_sip_header_content_type_get_subtype(header_content_type))==0) { - unsigned int retry_in =1000*((float)rand()/RAND_MAX); - belle_sip_source_t *s=sal_create_timer(op->base.root,vfu_retry,sal_op_ref(op), retry_in, "vfu request retry"); - ms_message("Rejected vfu request on op [%p], just retry in [%ui] ms",op,retry_in); - belle_sip_object_unref(s); + unsigned int retry_in =1000*((float)rand()/RAND_MAX); + belle_sip_source_t *s=sal_create_timer(op->base.root,vfu_retry,sal_op_ref(op), retry_in, "vfu request retry"); + ms_message("Rejected vfu request on op [%p], just retry in [%ui] ms",op,retry_in); + belle_sip_object_unref(s); }else { /*ignoring*/ } @@ -323,7 +323,7 @@ static void call_process_response(void *op_base, const belle_sip_response_event_ } break; case BELLE_SIP_DIALOG_TERMINATED: { - if (code >= 300){ + if (strcmp("INVITE",method)==0 && code >= 300){ call_set_error(op,response); } } @@ -578,22 +578,27 @@ static void process_request_event(void *op_base, const belle_sip_request_event_t case BELLE_SIP_DIALOG_CONFIRMED: /*great ACK received*/ if (strcmp("ACK",method)==0) { - if (op->sdp_offering){ - SalReason reason; - if (extract_sdp(op,BELLE_SIP_MESSAGE(req),&sdp,&reason)==0){ - if (sdp){ - if (op->base.remote_media) - sal_media_description_unref(op->base.remote_media); - op->base.remote_media=sal_media_description_new(); - sdp_to_media_description(sdp,op->base.remote_media); - sdp_process(op); - belle_sip_object_unref(sdp); - }else{ - ms_warning("SDP expected in ACK but not found."); + if (!op->pending_client_trans || + !belle_sip_transaction_state_is_transient(belle_sip_transaction_get_state((belle_sip_transaction_t*)op->pending_client_trans))){ + if (op->sdp_offering){ + SalReason reason; + if (extract_sdp(op,BELLE_SIP_MESSAGE(req),&sdp,&reason)==0){ + if (sdp){ + if (op->base.remote_media) + sal_media_description_unref(op->base.remote_media); + op->base.remote_media=sal_media_description_new(); + sdp_to_media_description(sdp,op->base.remote_media); + sdp_process(op); + belle_sip_object_unref(sdp); + }else{ + ms_warning("SDP expected in ACK but not found."); + } } } + op->base.root->callbacks.call_ack(op); + }else{ + ms_message("Ignored received ack since a new client transaction has been started since."); } - op->base.root->callbacks.call_ack(op); } else if(strcmp("BYE",method)==0) { resp=sal_op_create_response_from_request(op,req,200); belle_sip_server_transaction_send_response(server_transaction,resp); diff --git a/coreapi/callbacks.c b/coreapi/callbacks.c index 03611b2cf..015f10615 100644 --- a/coreapi/callbacks.c +++ b/coreapi/callbacks.c @@ -117,10 +117,8 @@ void linphone_call_update_frozen_payloads(LinphoneCall *call, SalMediaDescriptio } } -void linphone_core_update_streams(LinphoneCore *lc, LinphoneCall *call, SalMediaDescription *new_md){ +void linphone_core_update_streams(LinphoneCore *lc, LinphoneCall *call, SalMediaDescription *new_md, LinphoneCallState target_state){ SalMediaDescription *oldmd=call->resultdesc; - bool_t all_muted=FALSE; - bool_t send_ringbacktone=FALSE; int md_changed=0; @@ -144,7 +142,6 @@ void linphone_core_update_streams(LinphoneCore *lc, LinphoneCall *call, SalMedia call->biggestdesc=sal_media_description_ref(sal_call_get_remote_media_description(call->op)); } sal_media_description_ref(new_md); - call->expect_media_in_ack=FALSE; call->resultdesc=new_md; if ((call->audiostream && call->audiostream->ms.state==MSStreamStarted) || (call->videostream && call->videostream->ms.state==MSStreamStarted)){ clear_early_media_destinations(call); @@ -201,25 +198,11 @@ void linphone_core_update_streams(LinphoneCore *lc, LinphoneCall *call, SalMedia /*this happens after pausing the call locally. The streams are destroyed and then we wait the 200Ok to recreate them*/ linphone_call_init_media_streams (call); } - if (call->state==LinphoneCallIncomingEarlyMedia && linphone_core_get_remote_ringback_tone (lc)!=NULL){ - send_ringbacktone=TRUE; - } - if ((call->state==LinphoneCallIncomingEarlyMedia || call->state==LinphoneCallOutgoingEarlyMedia) && !call->params->real_early_media){ - all_muted=TRUE; - } + if (call->params->real_early_media && call->state==LinphoneCallOutgoingEarlyMedia){ prepare_early_media_forking(call); } -#ifdef VIDEO_ENABLED - if (call->state==LinphoneCallPausing) { - /*change cam to noweb cam*/ - call->cam = get_nowebcam_device(); - } else if (call->state != LinphoneCallPaused) { - /*restaure web cam*/ - call->cam = lc->video_conf.device; - } -#endif /*VIDEO*/ - linphone_call_start_media_streams(call,all_muted,send_ringbacktone); + linphone_call_start_media_streams(call, target_state); if (call->state==LinphoneCallPausing && call->paused_by_app && ms_list_size(lc->calls)==1){ linphone_core_play_named_tone(lc,LinphoneToneCallOnHold); } @@ -476,7 +459,7 @@ static void call_ringing(SalOp *h){ linphone_call_set_state(call,LinphoneCallOutgoingEarlyMedia,"Early media"); linphone_core_stop_ringing(lc); ms_message("Doing early media..."); - linphone_core_update_streams(lc,call,md); + linphone_core_update_streams(lc,call,md, call->state); if ((linphone_call_params_get_audio_direction(linphone_call_get_current_params(call)) == LinphoneMediaDirectionInactive) && call->audiostream) { if (lc->ringstream != NULL) return; /* Already ringing! */ start_remote_ring(lc, call); @@ -484,21 +467,35 @@ static void call_ringing(SalOp *h){ } } -/* - * could be reach : - * - when the call is accepted - * - when a request is accepted (pause, resume) - */ -static void call_accepted(SalOp *op){ - LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op)); - LinphoneCall *call=(LinphoneCall*)sal_op_get_user_pointer(op); - SalMediaDescription *md, *rmd; - bool_t update_state=TRUE; +static void start_pending_refer(LinphoneCall *call){ + linphone_core_start_refered_call(call->core, call,NULL); +} - if (call == NULL){ - ms_warning("No call to accept."); - return ; +static void process_call_accepted(LinphoneCore *lc, LinphoneCall *call, SalOp *op){ + SalMediaDescription *md, *rmd; + LinphoneCallState next_state = LinphoneCallIdle; + const char *next_state_str = NULL; + LinphoneTaskList tl; + + switch (call->state){/*immediately notify the connected state, even if errors occur after*/ + case LinphoneCallOutgoingProgress: + case LinphoneCallOutgoingRinging: + case LinphoneCallOutgoingEarlyMedia: + /*immediately notify the connected state*/ + linphone_call_set_state(call,LinphoneCallConnected,"Connected"); + { + char *tmp=linphone_call_get_remote_address_as_string (call); + char *msg=ms_strdup_printf(_("Call answered by %s"),tmp); + linphone_core_notify_display_status(lc,msg); + ms_free(tmp); + ms_free(msg); + } + break; + default: + break; } + + linphone_task_list_init(&tl); rmd=sal_call_get_remote_media_description(op); /*set privacy*/ call->current_params->privacy=(LinphonePrivacyMask)sal_op_get_privacy(call->op); @@ -517,128 +514,108 @@ static void call_accepted(SalOp *op){ #endif //BUILD_UPNP md=sal_call_get_final_media_description(op); - - switch (call->state){ - case LinphoneCallOutgoingProgress: - case LinphoneCallOutgoingRinging: - case LinphoneCallOutgoingEarlyMedia: - linphone_call_set_state(call,LinphoneCallConnected,"Connected"); - if (call->referer) linphone_core_notify_refer_state(lc,call->referer,call); - break; - case LinphoneCallEarlyUpdating: - linphone_call_set_state(call,call->prevstate,"Early update accepted"); - update_state=FALSE; - break; - default: - break; + if (md == NULL && call->prevstate == LinphoneCallOutgoingEarlyMedia && call->resultdesc != NULL){ + ms_message("Using early media SDP since none was received with the 200 OK"); + md = call->resultdesc; } - - if( (call->prevstate == LinphoneCallOutgoingEarlyMedia) && (md == NULL || sal_media_description_empty(md)) ){ - /* media description is null or empty because no SDP was received in the 200 OK, we can possibly use the early-media SDP. */ - if( call->resultdesc != NULL){ - ms_message("Using early media SDP since none were received with the 200 OK"); - md = call->resultdesc; - } + if (md && (sal_media_description_empty(md) || linphone_core_incompatible_security(lc,md))){ + md = NULL; } - - if (md && !sal_media_description_empty(md) && !linphone_core_incompatible_security(lc,md)){ - linphone_call_update_remote_session_id_and_ver(call); - linphone_core_update_ice_state_in_call_stats(call); - if (sal_media_description_has_dir(md,SalStreamSendOnly) || - sal_media_description_has_dir(md,SalStreamInactive)){ - { - char *tmp=linphone_call_get_remote_address_as_string (call); - char *msg=ms_strdup_printf(_("Call with %s is paused."),tmp); - linphone_core_notify_display_status(lc,msg); - ms_free(tmp); - ms_free(msg); - } - linphone_core_update_streams (lc,call,md); - if (update_state) linphone_call_set_state(call,LinphoneCallPaused,"Call paused"); - if (call->refer_pending) - linphone_core_start_refered_call(lc,call,NULL); - }else if (sal_media_description_has_dir(md,SalStreamRecvOnly)){ - /*we are put on hold when the call is initially accepted */ - { - char *tmp=linphone_call_get_remote_address_as_string (call); - char *msg=ms_strdup_printf(_("Call answered by %s - on hold."),tmp); - linphone_core_notify_display_status(lc,msg); - ms_free(tmp); - ms_free(msg); - } - linphone_core_update_streams (lc,call,md); - if (update_state) linphone_call_set_state(call,LinphoneCallPausedByRemote,"Call paused by remote"); - }else{ - if (call->state!=LinphoneCallUpdating){ - if (call->state==LinphoneCallResuming){ - linphone_core_notify_display_status(lc,_("Call resumed.")); + if (md){ /*there is a valid SDP in the response, either offer or answer, and we're able to start/update the streams*/ + switch (call->state){ + case LinphoneCallResuming: + linphone_core_notify_display_status(lc,_("Call resumed.")); + /*intentionally no break*/ + case LinphoneCallConnected: + if (call->referer) linphone_core_notify_refer_state(lc,call->referer,call); + /*intentionally no break*/ + case LinphoneCallUpdating: + case LinphoneCallUpdatedByRemote: + if (!sal_media_description_has_dir(call->localdesc, SalStreamInactive) && + (sal_media_description_has_dir(md,SalStreamRecvOnly) || + sal_media_description_has_dir(md,SalStreamInactive))){ + next_state = LinphoneCallPausedByRemote; + next_state_str = "Call paused by remote"; }else{ - { - char *tmp=linphone_call_get_remote_address_as_string (call); - char *msg=ms_strdup_printf(_("Call answered by %s."),tmp); - linphone_core_notify_display_status(lc,msg); - ms_free(tmp); - ms_free(msg); - } + if (!call->current_params->in_conference) + lc->current_call=call; + next_state = LinphoneCallStreamsRunning; + next_state_str = "Streams running"; } - } - linphone_core_update_streams(lc,call,md); - linphone_call_fix_call_parameters(call); - if (!call->current_params->in_conference) - lc->current_call=call; - if (update_state) linphone_call_set_state(call, LinphoneCallStreamsRunning, "Streams running"); + break; + case LinphoneCallEarlyUpdating: + next_state_str = "Early update accepted"; + next_state = call->prevstate; + break; + case LinphoneCallPausing: + /*when we entered the pausing state, we always reach the paused state whatever the content of the remote SDP is. + Our streams are all send-only (with music), soundcard and camera are never used*/ + next_state = LinphoneCallPaused; + next_state_str = "Call paused"; + if (call->refer_pending) + linphone_task_list_add(&tl, (LinphoneCoreIterateHook)start_pending_refer, call); + break; + default: + ms_error("call_accepted(): don't know what to do in state [%s]", linphone_call_state_to_string(call->state)); + break; } - }else{ + + if (next_state != LinphoneCallIdle){ + linphone_call_update_remote_session_id_and_ver(call); + linphone_core_update_ice_state_in_call_stats(call); + linphone_core_update_streams(lc, call, md, next_state); + linphone_call_fix_call_parameters(call); + linphone_call_set_state(call, next_state, next_state_str); + }else{ + ms_error("BUG: next_state is not set in call_accepted(), current state is %s", linphone_call_state_to_string(call->state)); + } + }else{ /*invalid or no SDP*/ switch (call->prevstate){ - /*send a bye only in case of outgoing state*/ + /*send a bye only in case of early states*/ case LinphoneCallOutgoingInit: case LinphoneCallOutgoingProgress: case LinphoneCallOutgoingRinging: case LinphoneCallOutgoingEarlyMedia: - ms_error("Incompatible SDP offer received in 200 OK, need to abort the call"); + case LinphoneCallIncomingReceived: + case LinphoneCallIncomingEarlyMedia: + ms_error("Incompatible SDP answer received, need to abort the call"); linphone_core_abort_call(lc,call,_("Incompatible, check codecs or security settings...")); break; /*otherwise we are able to resume previous state*/ default: - ms_message("Incompatible SDP offer received in 200 OK, restoring previous state[%s]",linphone_call_state_to_string(call->prevstate)); + ms_message("Incompatible SDP answer received, restoring previous state [%s]",linphone_call_state_to_string(call->prevstate)); linphone_call_set_state(call,call->prevstate,_("Incompatible media parameters.")); break; } } + linphone_task_list_run(&tl); + linphone_task_list_free(&tl); } -static void call_ack(SalOp *op){ +/* + * could be reach : + * - when the call is accepted + * - when a request is accepted (pause, resume) + */ +static void call_accepted(SalOp *op){ LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op)); LinphoneCall *call=(LinphoneCall*)sal_op_get_user_pointer(op); - if (call==NULL){ - ms_warning("No call to be ACK'd"); + + if (call == NULL){ + ms_warning("call_accepted: call does no longer exist."); return ; } - if (call->expect_media_in_ack){ - SalMediaDescription *md=sal_call_get_final_media_description(op); - if (md && !sal_media_description_empty(md)){ - linphone_core_update_streams(lc,call,md); - linphone_call_set_state (call,LinphoneCallStreamsRunning,"Connected (streams running)"); - }else{ - /*send a bye*/ - ms_error("Incompatible SDP response received in ACK, need to abort the call"); - linphone_core_abort_call(lc,call,"No codec intersection"); - return; - } - } + process_call_accepted(lc, call, op); } static void call_resumed(LinphoneCore *lc, LinphoneCall *call){ - /*when we are resumed, increment session id, because sdp is changed (a=recvonly disapears)*/ - linphone_call_increment_local_media_description(call); linphone_core_notify_display_status(lc,_("We have been resumed.")); _linphone_core_accept_call_update(lc,call,NULL,LinphoneCallStreamsRunning,"Connected (streams running)"); } static void call_paused_by_remote(LinphoneCore *lc, LinphoneCall *call){ LinphoneCallParams *params; - /*when we are paused, increment session id, because sdp is changed (a=recvonly appears)*/ - linphone_call_increment_local_media_description(call); + /* we are being paused */ linphone_core_notify_display_status(lc,_("We are paused by other party.")); params = linphone_call_params_copy(call->params); @@ -649,100 +626,47 @@ static void call_paused_by_remote(LinphoneCore *lc, LinphoneCall *call){ linphone_call_params_unref(params); } -static void call_updated_by_remote(LinphoneCore *lc, LinphoneCall *call, bool_t is_update){ - /*first check if media capabilities are compatible*/ - SalMediaDescription *md; - SalMediaDescription *rmd=sal_call_get_remote_media_description(call->op); - SalMediaDescription *prev_result_desc=call->resultdesc; - - if (rmd!=NULL){ - if (call->state!=LinphoneCallPaused){ - /*in paused state, we must stay in paused state.*/ - linphone_call_make_local_media_description(lc,call); - sal_call_set_local_media_description(call->op,call->localdesc); - } - md=sal_call_get_final_media_description(call->op); - if (md && (sal_media_description_empty(md) || linphone_core_incompatible_security(lc,md))){ - sal_call_decline(call->op,SalReasonNotAcceptable,NULL); - return; - } - if (is_update && prev_result_desc && md){ - int diff=sal_media_description_equals(prev_result_desc,md); - if (diff & (SAL_MEDIA_DESCRIPTION_CRYPTO_POLICY_CHANGED|SAL_MEDIA_DESCRIPTION_STREAMS_CHANGED)){ - ms_warning("Cannot accept this update, it is changing parameters that require user approval"); - sal_call_decline(call->op,SalReasonNotAcceptable,NULL); /*FIXME should send 504 Cannot change the session parameters without prompting the user"*/ - return; - } - } - } - - if ( call->state == LinphoneCallStreamsRunning) { - /*reINVITE and in-dialogs UPDATE go here*/ - linphone_core_notify_display_status(lc,_("Call is updated by remote.")); - call->defer_update = lp_config_get_int(lc->config, "sip", "defer_update_default", FALSE); - linphone_call_set_state(call, LinphoneCallUpdatedByRemote,"Call updated by remote"); - if (call->defer_update==FALSE){ - linphone_core_accept_call_update(lc,call,NULL); - } - if (rmd==NULL){ - call->expect_media_in_ack=TRUE; - } - - } else if( call->state == LinphoneCallPausedByRemote ){ - /* FIXME: the comment below is meaningless. */ - /* Case where no SDP is present and we were paused by remote. - * We send back an ACK with our SDP and expect the remote to send its own. - * No state change here until an answer is received. */ - call->defer_update = lp_config_get_int(lc->config, "sip", "defer_update_default", FALSE); - if (call->defer_update==FALSE){ - _linphone_core_accept_call_update(lc,call,NULL,call->state,linphone_call_state_to_string(call->state)); - } - if (rmd==NULL){ - call->expect_media_in_ack=TRUE; - } - } else if (is_update){ /*SIP UPDATE case, can occur in early states*/ - linphone_call_set_state(call, LinphoneCallEarlyUpdatedByRemote, "EarlyUpdatedByRemote"); - _linphone_core_accept_call_update(lc,call,NULL,call->prevstate,linphone_call_state_to_string(call->prevstate)); - } -} - /* this callback is called when an incoming re-INVITE/ SIP UPDATE modifies the session*/ -static void call_updating(SalOp *op, bool_t is_update){ - LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op)); - LinphoneCall *call=(LinphoneCall*)sal_op_get_user_pointer(op); +static void call_updated(LinphoneCore *lc, LinphoneCall *call, SalOp *op, bool_t is_update){ SalMediaDescription *rmd=sal_call_get_remote_media_description(op); - - if (rmd==NULL){ - /* case of a reINVITE or UPDATE without SDP */ - call_updated_by_remote(lc,call,is_update); - return; - } - + + call->defer_update = lp_config_get_int(lc->config, "sip", "defer_update_default", FALSE); + switch(call->state){ case LinphoneCallPausedByRemote: if (sal_media_description_has_dir(rmd,SalStreamSendRecv) || sal_media_description_has_dir(rmd,SalStreamRecvOnly)){ call_resumed(lc,call); - }else call_updated_by_remote(lc,call,is_update); + }else{ + _linphone_core_accept_call_update(lc,call,NULL,call->state,linphone_call_state_to_string(call->state)); + } break; /*SIP UPDATE CASE*/ case LinphoneCallOutgoingRinging: case LinphoneCallOutgoingEarlyMedia: case LinphoneCallIncomingEarlyMedia: - if (is_update) call_updated_by_remote(lc,call,is_update); + if (is_update) { + linphone_call_set_state(call, LinphoneCallEarlyUpdatedByRemote, "EarlyUpdatedByRemote"); + _linphone_core_accept_call_update(lc,call,NULL,call->prevstate,linphone_call_state_to_string(call->prevstate)); + } break; case LinphoneCallStreamsRunning: case LinphoneCallConnected: if (sal_media_description_has_dir(rmd,SalStreamSendOnly) || sal_media_description_has_dir(rmd,SalStreamInactive)){ call_paused_by_remote(lc,call); }else{ - call_updated_by_remote(lc,call,is_update); + 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; case LinphoneCallPaused: if (sal_media_description_has_dir(rmd,SalStreamSendOnly) || sal_media_description_has_dir(rmd,SalStreamInactive)){ call_paused_by_remote(lc,call); }else{ - call_updated_by_remote(lc,call,is_update); + /*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: @@ -766,6 +690,71 @@ static void call_updating(SalOp *op, bool_t is_update){ } } +/* this callback is called when an incoming re-INVITE/ SIP UPDATE modifies the session*/ +static void call_updating(SalOp *op, bool_t is_update){ + LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op)); + LinphoneCall *call=(LinphoneCall*)sal_op_get_user_pointer(op); + SalMediaDescription *rmd=sal_call_get_remote_media_description(op); + + if (!call) { + ms_error("call_updating(): call doesn't exist anymore"); + return ; + } + 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); + sal_call_set_local_media_description(call->op,call->localdesc); + } + if (rmd == NULL){ + /* case of a reINVITE or UPDATE without SDP */ + call->expect_media_in_ack = TRUE; + sal_call_accept(op); /*respond with an offer*/ + /*don't do anything else in this case, wait for the ACK to receive to notify the app*/ + }else { + SalMediaDescription *md; + SalMediaDescription *prev_result_desc=call->resultdesc; + + call->expect_media_in_ack = FALSE; + + md=sal_call_get_final_media_description(call->op); + if (md && (sal_media_description_empty(md) || linphone_core_incompatible_security(lc,md))){ + sal_call_decline(call->op,SalReasonNotAcceptable,NULL); + return; + } + if (is_update && prev_result_desc && md){ + int diff=sal_media_description_equals(prev_result_desc,md); + if (diff & (SAL_MEDIA_DESCRIPTION_CRYPTO_POLICY_CHANGED|SAL_MEDIA_DESCRIPTION_STREAMS_CHANGED)){ + ms_warning("Cannot accept this update, it is changing parameters that require user approval"); + sal_call_decline(call->op,SalReasonNotAcceptable,NULL); /*FIXME should send 504 Cannot change the session parameters without prompting the user"*/ + return; + } + } + call_updated(lc, call, op, is_update); + } +} + + +static void call_ack(SalOp *op){ + LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op)); + LinphoneCall *call=(LinphoneCall*)sal_op_get_user_pointer(op); + + if (call == NULL){ + ms_warning("call_ack(): no call for which an ack is expected"); + return; + } + if (call->expect_media_in_ack){ + switch(call->state){ + case LinphoneCallStreamsRunning: + case LinphoneCallPausedByRemote: + linphone_call_set_state(call, LinphoneCallUpdatedByRemote, "UpdatedByRemote"); + break; + default: + break; + } + process_call_accepted(lc, call, op); + } +} + static void call_terminated(SalOp *op, const char *from){ LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op)); LinphoneCall *call=(LinphoneCall*)sal_op_get_user_pointer(op); @@ -922,16 +911,11 @@ static void call_failure(SalOp *op){ msg=_("Incompatible media parameters."); linphone_core_notify_display_status(lc,msg); break; - case SalReasonRequestPending: - /*restore previous state, the application will decide to resubmit the action if relevant*/ - linphone_call_set_state(call,call->prevstate,msg); - return; - break; default: linphone_core_notify_display_status(lc,_("Call failed.")); } - /*some call error are not fatal*/ + /*some call errors are not fatal*/ switch (call->state) { case LinphoneCallUpdating: case LinphoneCallPausing: diff --git a/coreapi/linphonecall.c b/coreapi/linphonecall.c index 1c60558c9..d4c9f43d5 100644 --- a/coreapi/linphonecall.c +++ b/coreapi/linphonecall.c @@ -43,11 +43,15 @@ static const char *EC_STATE_STORE = ".linphone.ecstate"; static void linphone_call_stats_uninit(LinphoneCallStats *stats); static void linphone_call_get_local_ip(LinphoneCall *call, const LinphoneAddress *remote_addr); -#ifdef VIDEO_ENABLED + MSWebCam *get_nowebcam_device(){ +#ifdef VIDEO_ENABLED return ms_web_cam_manager_get_cam(ms_web_cam_manager_get(),"StaticImage: Static picture"); -} +#else + return NULL; #endif +} + static bool_t generate_b64_crypto_key(int key_length, char* key_out, size_t key_out_size) { int b64_size; @@ -818,9 +822,6 @@ static void linphone_call_init_common(LinphoneCall *call, LinphoneAddress *from, linphone_call_init_stats(&call->stats[LINPHONE_CALL_STATS_AUDIO], LINPHONE_CALL_STATS_AUDIO); linphone_call_init_stats(&call->stats[LINPHONE_CALL_STATS_VIDEO], LINPHONE_CALL_STATS_VIDEO); -#ifdef VIDEO_ENABLED - call->cam = call->core->video_conf.device; -#endif } void linphone_call_init_stats(LinphoneCallStats *stats, int type) { @@ -948,6 +949,7 @@ void linphone_call_fill_media_multicast_addr(LinphoneCall *call) { } else call->media_ports[1].multicast_ip[0]='\0'; } + LinphoneCall * linphone_call_new_outgoing(struct _LinphoneCore *lc, LinphoneAddress *from, LinphoneAddress *to, const LinphoneCallParams *params, LinphoneProxyConfig *cfg){ LinphoneCall *call = belle_sip_object_new(LinphoneCall); @@ -955,7 +957,7 @@ LinphoneCall * linphone_call_new_outgoing(struct _LinphoneCore *lc, LinphoneAddr call->core=lc; linphone_call_outgoing_select_ip_version(call,to,cfg); linphone_call_get_local_ip(call, to); - linphone_call_init_common(call,from,to); + linphone_call_init_common(call, from, to); call->params = linphone_call_params_copy(params); linphone_call_fill_media_multicast_addr(call); @@ -1260,7 +1262,7 @@ void linphone_call_set_state(LinphoneCall *call, LinphoneCallState cstate, const call->prevstate=call->state; if (call->state==LinphoneCallEnd || call->state==LinphoneCallError){ if (cstate!=LinphoneCallReleased){ - ms_warning("Spurious call state change from %s to %s, ignored." ,linphone_call_state_to_string(call->state) + ms_fatal("Spurious call state change from %s to %s, ignored." ,linphone_call_state_to_string(call->state) ,linphone_call_state_to_string(cstate)); return; } @@ -2547,9 +2549,8 @@ static RtpSession * create_audio_rtp_io_session(LinphoneCall *call) { return rtp_session; } -static void linphone_call_start_audio_stream(LinphoneCall *call, bool_t muted, bool_t send_ringbacktone, bool_t use_arc){ +static void linphone_call_start_audio_stream(LinphoneCall *call, LinphoneCallState next_state, bool_t use_arc){ LinphoneCore *lc=call->core; - LpConfig* conf; int used_pt=-1; char rtcp_tool[128]={0}; const SalStreamDescription *stream; @@ -2586,26 +2587,24 @@ static void linphone_call_start_audio_stream(LinphoneCall *call, bool_t muted, b if (captcard==NULL) { ms_warning("No card defined for capture !"); } - /*Replace soundcard filters by inactive file players or recorders - when placed in recvonly or sendonly mode*/ + /*Don't use file or soundcard capture when placed in recv-only mode*/ if (stream->rtp_port==0 || stream->dir==SalStreamRecvOnly || (stream->multicast_role == SalMulticastReceiver && is_multicast)){ captcard=NULL; playfile=NULL; - }else if (stream->dir==SalStreamSendOnly){ + } + if (next_state == LinphoneCallPaused){ + /*in paused state, we never use soundcard*/ playcard=NULL; - /*jehan: why capture card should be null in this case ? Not very good to only rely on stream dir to detect paused state. - * It can also be a simple call in one way audio*/ captcard=NULL; recfile=NULL; /*And we will eventually play "playfile" if set by the user*/ } - if (send_ringbacktone){ - conf = linphone_core_get_config(lc); + if (call->playing_ringbacktone){ captcard=NULL; playfile=NULL;/* it is setup later*/ - if( conf && lp_config_get_int(conf,"sound","send_ringback_without_playback", 0) == 1){ + if (lp_config_get_int(lc->config,"sound","send_ringback_without_playback", 0) == 1){ playcard = NULL; recfile = NULL; } @@ -2629,7 +2628,7 @@ static void linphone_call_start_audio_stream(LinphoneCall *call, bool_t muted, b if (captcard && stream->max_rate>0) ms_snd_card_set_preferred_sample_rate(captcard, stream->max_rate); audio_stream_enable_adaptive_bitrate_control(call->audiostream,use_arc); media_stream_set_adaptive_bitrate_algorithm(&call->audiostream->ms, - ms_qos_analyzer_algorithm_from_string(linphone_core_get_adaptive_rate_algorithm(lc))); + ms_qos_analyzer_algorithm_from_string(linphone_core_get_adaptive_rate_algorithm(lc))); audio_stream_enable_adaptive_jittcomp(call->audiostream, linphone_core_audio_adaptive_jittcomp_enabled(lc)); rtp_session_set_jitter_compensation(call->audiostream->ms.sessions.rtp_session,linphone_core_get_audio_jittcomp(lc)); if (!call->params->in_conference && call->params->record_file){ @@ -2686,22 +2685,22 @@ static void linphone_call_start_audio_stream(LinphoneCall *call, bool_t muted, b used_pt, &io ); - post_configure_audio_streams(call, muted && !send_ringbacktone); + post_configure_audio_streams(call, (call->all_muted || call->audio_muted) && !call->playing_ringbacktone); } ms_media_stream_sessions_set_encryption_mandatory(&call->audiostream->ms.sessions,linphone_core_is_media_encryption_mandatory(call->core)); - if (stream->dir==SalStreamSendOnly && playfile!=NULL){ + if (next_state == LinphoneCallPaused && captcard == NULL && playfile != NULL){ int pause_time=500; ms_filter_call_method(call->audiostream->soundread,MS_FILE_PLAYER_LOOP,&pause_time); } - if (send_ringbacktone){ + if (call->playing_ringbacktone){ setup_ring_player(lc,call); } if (call->params->in_conference){ /*transform the graph to connect it to the conference filter */ - mute=stream->dir==SalStreamRecvOnly; + mute = stream->dir==SalStreamRecvOnly; linphone_call_add_to_conf(call, mute); } call->current_params->in_conference=call->params->in_conference; @@ -2737,7 +2736,7 @@ static RtpSession * create_video_rtp_io_session(LinphoneCall *call) { } #endif -static void linphone_call_start_video_stream(LinphoneCall *call, bool_t all_inputs_muted){ +static void linphone_call_start_video_stream(LinphoneCall *call, LinphoneCallState next_state){ #ifdef VIDEO_ENABLED LinphoneCore *lc=call->core; int used_pt=-1; @@ -2810,11 +2809,7 @@ static void linphone_call_start_video_stream(LinphoneCall *call, bool_t all_inpu /*either inactive or incompatible with local capabilities*/ is_inactive=TRUE; } - if (all_inputs_muted){ - cam=get_nowebcam_device(); - } else { - cam = linphone_call_get_video_device(call); - } + cam = linphone_call_get_video_device(call); if (!is_inactive){ if (sal_stream_description_has_srtp(vstream) == TRUE) { int crypto_idx = find_crypto_index_from_tag(local_st_desc->crypto, vstream->crypto_local_tag); @@ -2934,13 +2929,29 @@ static void setZrtpCryptoTypesParameters(MSZrtpParams *params, LinphoneCore *lc) params->keyAgreementsCount = linphone_core_get_zrtp_key_agreement_suites(lc, params->keyAgreements); } -void linphone_call_start_media_streams(LinphoneCall *call, bool_t all_inputs_muted, bool_t send_ringbacktone){ +void linphone_call_start_media_streams(LinphoneCall *call, LinphoneCallState next_state){ LinphoneCore *lc=call->core; - bool_t use_arc=linphone_core_adaptive_rate_control_enabled(lc); + bool_t use_arc = linphone_core_adaptive_rate_control_enabled(lc); #ifdef VIDEO_ENABLED const SalStreamDescription *vstream=sal_media_description_find_best_stream(call->resultdesc,SalVideo); #endif + switch (next_state){ + case LinphoneCallIncomingEarlyMedia: + if (linphone_core_get_remote_ringback_tone(lc)){ + call->playing_ringbacktone = TRUE; + } + case LinphoneCallOutgoingEarlyMedia: + if (!call->params->real_early_media){ + call->all_muted = TRUE; + } + break; + default: + call->playing_ringbacktone = FALSE; + call->all_muted = FALSE; + break; + } + call->current_params->audio_codec = NULL; call->current_params->video_codec = NULL; @@ -2958,18 +2969,16 @@ void linphone_call_start_media_streams(LinphoneCall *call, bool_t all_inputs_mut call, linphone_core_get_upload_bandwidth(lc),linphone_core_get_download_bandwidth(lc)); if (call->audiostream!=NULL) { - linphone_call_start_audio_stream(call,all_inputs_muted||call->audio_muted,send_ringbacktone,use_arc); + linphone_call_start_audio_stream(call, next_state, use_arc); } else { ms_warning("DTLS no audio stream!"); } call->current_params->has_video=FALSE; if (call->videostream!=NULL) { if (call->audiostream) audio_stream_link_video(call->audiostream,call->videostream); - linphone_call_start_video_stream(call,all_inputs_muted); + linphone_call_start_video_stream(call, next_state); } - call->all_muted=all_inputs_muted; - call->playing_ringbacktone=send_ringbacktone; call->up_bw=linphone_core_get_upload_bandwidth(lc); /*might be moved in audio/video stream_start*/ @@ -4141,14 +4150,14 @@ void linphone_call_set_native_video_window_id(LinphoneCall *call, void *id) { } #endif } -#ifdef VIDEO_ENABLED + MSWebCam *linphone_call_get_video_device(const LinphoneCall *call) { - if (call->camera_enabled==FALSE) + if (call->all_muted || call->camera_enabled == FALSE) return get_nowebcam_device(); else - return call->cam; + return call->core->video_conf.device; } -#endif + void linphone_call_set_audio_route(LinphoneCall *call, LinphoneAudioRoute route) { if (call != NULL && call->audiostream != NULL){ diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index 9db9e82bf..19bb7b5a1 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -100,7 +100,6 @@ static ortp_mutex_t liblinphone_log_collection_mutex; static bool_t liblinphone_serialize_logs = FALSE; static void set_network_reachable(LinphoneCore* lc,bool_t isReachable, time_t curtime); static void linphone_core_run_hooks(LinphoneCore *lc); -static void linphone_core_free_hooks(LinphoneCore *lc); #include "enum.h" #include "contact_providers_priv.h" @@ -1590,7 +1589,7 @@ static void linphone_core_init(LinphoneCore * lc, const LinphoneCoreVTable *vtab lc->config=lp_config_ref(config); lc->data=userdata; lc->ringstream_autorelease=TRUE; - + linphone_task_list_init(&lc->hooks); memcpy(local_vtable,vtable,sizeof(LinphoneCoreVTable)); _linphone_core_add_listener(lc, local_vtable, TRUE); @@ -3177,11 +3176,11 @@ int linphone_core_accept_early_media_with_params(LinphoneCore* lc, LinphoneCall* sal_op_set_sent_custom_header ( call->op,params->custom_headers ); } - sal_call_notify_ringing(call->op,TRUE); + sal_call_notify_ringing(call->op, TRUE); 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 (md) linphone_core_update_streams(lc, call, md, call->state); return 0; }else{ ms_error("Bad state %s for linphone_core_accept_early_media_with_params()", linphone_call_state_to_string(call->state)); @@ -3273,6 +3272,7 @@ int linphone_core_update_call(LinphoneCore *lc, LinphoneCall *call, const Linpho break; case LinphoneCallStreamsRunning: case LinphoneCallPaused: + case LinphoneCallPausedByRemote: nextstate=LinphoneCallUpdating; break; default: @@ -3329,7 +3329,7 @@ int linphone_core_update_call(LinphoneCore *lc, LinphoneCall *call, const Linpho video_stream_set_sent_video_size(call->videostream,linphone_core_get_preferred_video_size(lc)); video_stream_set_fps(call->videostream, linphone_core_get_preferred_framerate(lc)); if (call->camera_enabled && call->videostream->cam!=lc->video_conf.device){ - video_stream_change_camera(call->videostream,call->cam = lc->video_conf.device); + video_stream_change_camera(call->videostream, lc->video_conf.device); }else video_stream_update_video_params(call->videostream); } #endif @@ -3378,7 +3378,7 @@ int linphone_core_start_accept_call_update(LinphoneCore *lc, LinphoneCall *call, sal_call_accept(call->op); md=sal_call_get_final_media_description(call->op); if (md && !sal_media_description_empty(md)){ - linphone_core_update_streams (lc,call,md); + linphone_core_update_streams(lc, call, md, next_state); linphone_call_fix_call_parameters(call); } linphone_call_set_state(call,next_state,state_info); @@ -3613,7 +3613,7 @@ int linphone_core_accept_call_with_params(LinphoneCore *lc, LinphoneCall *call, linphone_call_set_state(call,LinphoneCallConnected,"Connected"); new_md=sal_call_get_final_media_description(call->op); if (new_md){ - linphone_core_update_streams(lc, call, new_md); + linphone_core_update_streams(lc, call, new_md, LinphoneCallStreamsRunning); linphone_call_fix_call_parameters(call); linphone_call_set_state(call,LinphoneCallStreamsRunning,"Connected (streams running)"); }else call->expect_media_in_ack=TRUE; @@ -6096,7 +6096,7 @@ LpConfig * linphone_core_create_lp_config(LinphoneCore *lc, const char *filename static void linphone_core_uninit(LinphoneCore *lc) { - linphone_core_free_hooks(lc); + linphone_task_list_free(&lc->hooks); lc->video_conf.show_local = FALSE; while(lc->calls) @@ -6558,47 +6558,18 @@ void linphone_core_set_max_calls(LinphoneCore *lc, int max) { lc->max_calls=max; } -typedef struct Hook{ - LinphoneCoreIterateHook fun; - void *data; -}Hook; - -static Hook *hook_new(LinphoneCoreIterateHook hook, void *hook_data){ - Hook *h=ms_new0(Hook,1); - h->fun=hook; - h->data=hook_data; - return h; -} - -static void hook_invoke(Hook *h){ - h->fun(h->data); -} void linphone_core_add_iterate_hook(LinphoneCore *lc, LinphoneCoreIterateHook hook, void *hook_data){ - lc->hooks=ms_list_append(lc->hooks,hook_new(hook,hook_data)); + linphone_task_list_add(&lc->hooks, hook, hook_data); } static void linphone_core_run_hooks(LinphoneCore *lc){ - ms_list_for_each(lc->hooks,(void (*)(void*))hook_invoke); -} - -static void linphone_core_free_hooks(LinphoneCore *lc){ - ms_list_for_each(lc->hooks,(void (*)(void*))ms_free); - ms_list_free(lc->hooks); - lc->hooks=NULL; + linphone_task_list_run(&lc->hooks); } void linphone_core_remove_iterate_hook(LinphoneCore *lc, LinphoneCoreIterateHook hook, void *hook_data){ - MSList *elem; - for(elem=lc->hooks;elem!=NULL;elem=elem->next){ - Hook *h=(Hook*)elem->data; - if (h->fun==hook && h->data==hook_data){ - lc->hooks = ms_list_remove_link(lc->hooks,elem); - ms_free(h); - return; - } - } - ms_error("linphone_core_remove_iterate_hook(): No such hook found."); + linphone_task_list_remove(&lc->hooks, hook, hook_data); + } void linphone_core_set_zrtp_secrets_file(LinphoneCore *lc, const char* file){ diff --git a/coreapi/misc.c b/coreapi/misc.c index d94b170e3..60465887d 100644 --- a/coreapi/misc.c +++ b/coreapi/misc.c @@ -1788,3 +1788,49 @@ const char *linphone_tunnel_mode_to_string(LinphoneTunnelMode mode) { return "invalid"; } + +typedef struct Hook{ + LinphoneCoreIterateHook fun; + void *data; +}Hook; + +void linphone_task_list_init(LinphoneTaskList *t){ + t->hooks = NULL; +} + +static Hook *hook_new(LinphoneCoreIterateHook hook, void *hook_data){ + Hook *h=ms_new0(Hook,1); + h->fun=hook; + h->data=hook_data; + return h; +} + +static void hook_invoke(Hook *h){ + h->fun(h->data); +} + +void linphone_task_list_add(LinphoneTaskList *t, LinphoneCoreIterateHook hook, void *hook_data){ + t->hooks = ms_list_append(t->hooks,hook_new(hook,hook_data)); +} + +void linphone_task_list_remove(LinphoneTaskList *t, LinphoneCoreIterateHook hook, void *hook_data){ + MSList *elem; + for(elem=t->hooks;elem!=NULL;elem=elem->next){ + Hook *h=(Hook*)elem->data; + if (h->fun==hook && h->data==hook_data){ + t->hooks = ms_list_remove_link(t->hooks,elem); + ms_free(h); + return; + } + } + ms_error("linphone_task_list_remove(): No such hook found."); +} + +void linphone_task_list_run(LinphoneTaskList *t){ + ms_list_for_each(t->hooks,(void (*)(void*))hook_invoke); +} + +void linphone_task_list_free(LinphoneTaskList *t){ + t->hooks = ms_list_free_with_data(t->hooks, (void (*)(void*))ms_free); +} + diff --git a/coreapi/private.h b/coreapi/private.h index 12fd5b4c4..da3290788 100644 --- a/coreapi/private.h +++ b/coreapi/private.h @@ -295,7 +295,6 @@ struct _LinphoneCall{ belle_sip_source_t *dtmfs_timer; /*DTMF timer needed to send a DTMF sequence*/ char *dtls_certificate_fingerprint; /**> This fingerprint is computed during stream init and is stored in call to be used when making local media description */ - MSWebCam *cam; /*webcam use for this call*/ bool_t refer_pending; bool_t expect_media_in_ack; bool_t audio_muted; @@ -450,7 +449,7 @@ void linphone_call_fix_call_parameters(LinphoneCall *call); void linphone_call_init_audio_stream(LinphoneCall *call); void linphone_call_init_video_stream(LinphoneCall *call); void linphone_call_init_media_streams(LinphoneCall *call); -void linphone_call_start_media_streams(LinphoneCall *call, bool_t all_inputs_muted, bool_t send_ringbacktone); +void linphone_call_start_media_streams(LinphoneCall *call, LinphoneCallState target_state); void linphone_call_start_media_streams_for_ice_gathering(LinphoneCall *call); void linphone_call_stop_media_streams(LinphoneCall *call); void linphone_call_delete_ice_session(LinphoneCall *call); @@ -757,6 +756,16 @@ const char *linphone_core_get_tone_file(const LinphoneCore *lc, LinphoneToneID i int _linphone_core_accept_call_update(LinphoneCore *lc, LinphoneCall *call, const LinphoneCallParams *params, LinphoneCallState next_state, const char *state_info); typedef struct _LinphoneConference LinphoneConference; +typedef struct _LinphoneTaskList{ + MSList *hooks; +}LinphoneTaskList; + +void linphone_task_list_init(LinphoneTaskList *t); +void linphone_task_list_add(LinphoneTaskList *t, LinphoneCoreIterateHook hook, void *hook_data); +void linphone_task_list_remove(LinphoneTaskList *t, LinphoneCoreIterateHook hook, void *hook_data); +void linphone_task_list_run(LinphoneTaskList *t); +void linphone_task_list_free(LinphoneTaskList *t); + struct _LinphoneCore { MSList* vtable_refs; @@ -804,7 +813,7 @@ struct _LinphoneCore void *preview_window_id; time_t netup_time; /*time when network went reachable */ struct _EcCalibrator *ecc; - MSList *hooks; + LinphoneTaskList hooks; /*tasks periodically executed in linphone_core_iterate()*/ LinphoneConference conf_ctx; char* zrtp_secrets_cache; char* user_certificates_path; @@ -892,7 +901,7 @@ void linphone_call_make_local_media_description(LinphoneCore *lc, LinphoneCall * 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); -void linphone_core_update_streams(LinphoneCore *lc, LinphoneCall *call, SalMediaDescription *new_md); +void linphone_core_update_streams(LinphoneCore *lc, LinphoneCall *call, SalMediaDescription *new_md, LinphoneCallState target_state); bool_t linphone_core_is_payload_type_usable_for_bandwidth(LinphoneCore *lc, const PayloadType *pt, int bandwidth_limit); diff --git a/tester/call_tester.c b/tester/call_tester.c index 7b9eb36c5..a9ed2e494 100644 --- a/tester/call_tester.c +++ b/tester/call_tester.c @@ -288,9 +288,9 @@ bool_t call_with_params2(LinphoneCoreManager* caller_mgr BC_ASSERT_TRUE(wait_for(callee_mgr->lc,caller_mgr->lc,&callee_mgr->stat.number_of_LinphoneCallConnected,initial_callee.number_of_LinphoneCallConnected+1)); BC_ASSERT_TRUE(wait_for(callee_mgr->lc,caller_mgr->lc,&caller_mgr->stat.number_of_LinphoneCallConnected,initial_callee.number_of_LinphoneCallConnected+1)); - result = wait_for(callee_mgr->lc,caller_mgr->lc,&caller_mgr->stat.number_of_LinphoneCallStreamsRunning,initial_caller.number_of_LinphoneCallStreamsRunning+1) + result = wait_for_until(callee_mgr->lc,caller_mgr->lc,&caller_mgr->stat.number_of_LinphoneCallStreamsRunning,initial_caller.number_of_LinphoneCallStreamsRunning+1, 2000) && - wait_for(callee_mgr->lc,caller_mgr->lc,&callee_mgr->stat.number_of_LinphoneCallStreamsRunning,initial_callee.number_of_LinphoneCallStreamsRunning+1); + wait_for_until(callee_mgr->lc,caller_mgr->lc,&callee_mgr->stat.number_of_LinphoneCallStreamsRunning,initial_callee.number_of_LinphoneCallStreamsRunning+1, 2000); if (linphone_core_get_media_encryption(caller_mgr->lc) != LinphoneMediaEncryptionNone || linphone_core_get_media_encryption(callee_mgr->lc) != LinphoneMediaEncryptionNone) { @@ -4112,7 +4112,7 @@ static void video_call_with_re_invite_inactive_followed_by_re_invite_base(Linpho 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,&marie->stat.number_of_LinphoneCallPaused,1)); + BC_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&marie->stat.number_of_LinphoneCallStreamsRunning,2)); BC_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&pauline->stat.number_of_LinphoneCallPausedByRemote,1)); check_media_direction(marie,linphone_core_get_current_call(marie->lc),lcs,LinphoneMediaDirectionInactive,LinphoneMediaDirectionInactive); @@ -4122,19 +4122,13 @@ static void video_call_with_re_invite_inactive_followed_by_re_invite_base(Linpho linphone_core_enable_sdp_200_ack(marie->lc,TRUE); } - /* - currently update call cannot be used in paused state, might not be good. params=linphone_core_create_call_params(marie->lc,linphone_core_get_current_call(marie->lc)); linphone_call_params_set_audio_direction(params,LinphoneMediaDirectionSendRecv); linphone_call_params_set_video_direction(params,LinphoneMediaDirectionSendRecv); linphone_core_update_call(marie->lc,linphone_core_get_current_call(marie->lc),params); linphone_call_params_destroy(params); - */ - - linphone_core_resume_call(marie->lc,linphone_core_get_current_call(marie->lc)); - - BC_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&marie->stat.number_of_LinphoneCallResuming,1)); - BC_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&marie->stat.number_of_LinphoneCallStreamsRunning,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_LinphoneCallStreamsRunning,2)); check_media_direction(marie,linphone_core_get_current_call(marie->lc),lcs,LinphoneMediaDirectionSendRecv,LinphoneMediaDirectionSendRecv);