Commit b957318f authored by Simon Morlat's avatar Simon Morlat

implement defered ICE response to reINVITE, as defined by RFC.

This produces when the Controlled side hasn't finished yet with its check list processing, while the controlling side has finished and has sent a reINVITE with remote-candidates.
In this case of the 200Ok of the reINVITE must be delayed to the point where the controlled side finishes its check list processing.
parent d981a246
......@@ -688,6 +688,13 @@ static void call_paused_by_remote(LinphoneCore *lc, LinphoneCall *call){
static void call_updated_by_remote(LinphoneCore *lc, LinphoneCall *call){
linphone_core_notify_display_status(lc,_("Call is updated by remote."));
linphone_call_set_state(call, LinphoneCallUpdatedByRemote,"Call updated by remote");
if (call->ice_session && check_ice_reinvite_needs_defered_response(call)){
call->defer_update = TRUE;
ms_message("LinphoneCall [%p]: Ice reinvite received, but one or more check list are not completed. Response will be sent later, once ICE has completed.", call);
call->incoming_ice_reinvite_pending = TRUE;
if (call->defer_update == FALSE){
if (call->state == LinphoneCallUpdatedByRemote){
linphone_call_accept_update(call, NULL);
......@@ -4660,7 +4660,7 @@ static void handle_ice_events(LinphoneCall *call, OrtpEvent *ev){
switch (ice_session_state(call->ice_session)) {
case IS_Completed:
case IS_Failed:
/* At least one ICE session has succeeded, so perform a call update. */
/* At least one ICE check list has succeeded, so perform a call update. */
if (ice_session_has_completed_check_list(call->ice_session) == TRUE) {
const LinphoneCallParams *current_param = linphone_call_get_current_params(call);
if (ice_session_role(call->ice_session) == IR_Controlling && current_param->update_call_when_ice_completed ) {
......@@ -4668,6 +4668,9 @@ static void handle_ice_events(LinphoneCall *call, OrtpEvent *ev){
params->internal_call_update = TRUE;
linphone_call_update(call, params);
}else if (ice_session_role(call->ice_session) == IR_Controlled && call->incoming_ice_reinvite_pending){
linphone_call_accept_update(call, NULL);
call->incoming_ice_reinvite_pending = FALSE;
......@@ -813,6 +813,7 @@ void linphone_call_stop_ice_for_inactive_streams(LinphoneCall *call, SalMediaDes
void _update_local_media_description_from_ice(SalMediaDescription *desc, IceSession *session, bool_t use_nortpproxy) {
IceCandidate *rtp_candidate = NULL;
IceCandidate *rtcp_candidate = NULL;
......@@ -1684,6 +1685,38 @@ static bool_t _check_for_ice_restart_and_set_remote_credentials(IceSession *ice_
return ice_restarted;
/*the purpose of this function is to detect a situation where a check list is still running while a reINVITE
with remote-candidates is received*/
bool_t check_ice_reinvite_needs_defered_response(LinphoneCall *call){
SalMediaDescription *md = sal_call_get_remote_media_description(call->op);
int i,j;
IceCheckList *cl;
if (ice_session_state(call->ice_session) != IS_Running ) return FALSE;
for (i = 0; i < md->nb_streams; i++) {
SalStreamDescription *stream = &md->streams[i];
cl = ice_session_check_list(call->ice_session, i);
if (cl==NULL) continue;
if (stream->ice_mismatch == TRUE) {
return FALSE;
if (stream->rtp_port == 0) {
if (ice_check_list_state(cl) != ICL_Running) continue;
const SalIceRemoteCandidate *remote_candidate = &stream->ice_remote_candidates[j];
if (remote_candidate->addr[0] != '\0') return TRUE;
return FALSE;
static void _create_ice_check_lists_and_parse_ice_attributes(LinphoneCall *call, const SalMediaDescription *md, bool_t ice_restarted) {
const SalStreamDescription *stream;
IceCheckList *cl = NULL;
......@@ -405,6 +405,7 @@ struct _LinphoneCall{
bool_t reinvite_on_cancel_response_requested;
bool_t non_op_error; /*set when the LinphoneErrorInfo was set at higher level than sal*/
bool_t incoming_ice_reinvite_pending;
bctbx_list_t *callbacks; /* A list of LinphoneCallCbs object */
LinphoneCallCbs *current_cbs; /* The current LinphoneCallCbs object used to call a callback */
......@@ -1996,6 +1997,7 @@ char *linphone_presence_model_to_xml(LinphonePresenceModel *model) ;
#define LINPHONE_SQLITE3_VFS "sqlite3bctbx_vfs"
void linphone_call_check_ice_session(LinphoneCall *call, IceRole role, bool_t is_reinvite);
bool_t check_ice_reinvite_needs_defered_response(LinphoneCall *call);
bool_t linphone_call_state_is_early(LinphoneCallState state);
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