]> sjero.net Git - linphone/commitdiff
Defer ringing when ICE is activated to be able to gather local candidates.
authorGhislain MARY <ghislain.mary@belledonne-communications.com>
Tue, 31 Jul 2012 15:14:15 +0000 (17:14 +0200)
committerGhislain MARY <ghislain.mary@belledonne-communications.com>
Wed, 1 Aug 2012 07:29:19 +0000 (09:29 +0200)
coreapi/callbacks.c
coreapi/linphonecall.c
coreapi/linphonecore.c
coreapi/linphonecore.h

index 8ec8f39b17eec081b951025fbaa389ae732ec699..cd3290aa63f5431ecae05eda1443b5212cbdb321 100644 (file)
@@ -140,16 +140,10 @@ static bool_t already_a_call_pending(LinphoneCore *lc){
 
 static void call_received(SalOp *h){
        LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(h));
-       char *barmesg;
        LinphoneCall *call;
        const char *from,*to;
-       char *tmp;
-       LinphoneAddress *from_parsed;
        LinphoneAddress *from_addr, *to_addr;
-       SalMediaDescription *md;
-       bool_t propose_early_media=lp_config_get_int(lc->config,"sip","incoming_calls_early_media",FALSE);
        bool_t prevent_colliding_calls=lp_config_get_int(lc->config,"sip","prevent_colliding_calls",TRUE);
-       const char *ringback_tone=linphone_core_get_remote_ringback_tone (lc);
        
        /* first check if we can answer successfully to this invite */
        if (lc->presence_mode==LinphoneStatusBusy ||
@@ -188,72 +182,18 @@ static void call_received(SalOp *h){
        
        call=linphone_call_new_incoming(lc,from_addr,to_addr,h);
        sal_call_set_local_media_description(h,call->localdesc);
-       md=sal_call_get_final_media_description(h);
-
-       if (md && sal_media_description_empty(md)){
-               sal_call_decline(h,SalReasonMedia,NULL);
-               linphone_call_unref(call);
-               return;
-       }
        
        /* the call is acceptable so we can now add it to our list */
        linphone_core_add_call(lc,call);
-       
-       from_parsed=linphone_address_new(sal_op_get_from(h));
-       linphone_address_clean(from_parsed);
-       tmp=linphone_address_as_string(from_parsed);
-       linphone_address_destroy(from_parsed);
-       barmesg=ortp_strdup_printf("%s %s%s",tmp,_("is contacting you"),
-           (sal_call_autoanswer_asked(h)) ?_(" and asked autoanswer."):_("."));
-       if (lc->vtable.show) lc->vtable.show(lc);
-       if (lc->vtable.display_status) 
-           lc->vtable.display_status(lc,barmesg);
-
-       /* play the ring if this is the only call*/
-       if (ms_list_size(lc->calls)==1){
-               lc->current_call=call;
-               if (lc->ringstream && lc->dmfs_playing_start_time!=0){
-                       ring_stop(lc->ringstream);
-                       lc->ringstream=NULL;
-                       lc->dmfs_playing_start_time=0;
-               }
-               if (lc->sound_conf.ring_sndcard!=NULL){
-                       if(lc->ringstream==NULL && lc->sound_conf.local_ring){
-                               MSSndCard *ringcard=lc->sound_conf.lsd_card ?lc->sound_conf.lsd_card : lc->sound_conf.ring_sndcard;
-                               ms_message("Starting local ring...");
-                               lc->ringstream=ring_start(lc->sound_conf.local_ring,2000,ringcard);
-                       }
-                       else
-                       {
-                               ms_message("the local ring is already started");
-                       }
-               }
-       }else{
-               /* else play a tone within the context of the current call */
-               call->ringing_beep=TRUE;
-               linphone_core_play_tone(lc);
-       }
-
-       
        linphone_call_ref(call); /*prevent the call from being destroyed while we are notifying, if the user declines within the state callback */
-       linphone_call_set_state(call,LinphoneCallIncomingReceived,"Incoming call");
-       
-       if (call->state==LinphoneCallIncomingReceived){
-               sal_call_notify_ringing(h,propose_early_media || ringback_tone!=NULL);
 
-               if (propose_early_media || ringback_tone!=NULL){
-                       linphone_call_set_state(call,LinphoneCallIncomingEarlyMedia,"Incoming call early media");
-                       md=sal_call_get_final_media_description(h);
-                       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);
-               }
+       if (linphone_core_get_firewall_policy(lc) == LinphonePolicyUseIce) {
+               /* Defer ringing until the end of the ICE candidates gathering process. */
+               ms_message("Defer ringing to gather ICE candidates");
+               return;
        }
-       linphone_call_unref(call);
 
-       ms_free(barmesg);
-       ms_free(tmp);
+       linphone_core_notify_incoming_call(lc,call);
 }
 
 static void call_ringing(SalOp *h){
index 75518a143e18030d4dc5871326fa8d8c585578c8..e2948f597d819eb6837fab1bcd8ee025f6ab2178 100644 (file)
@@ -390,7 +390,14 @@ LinphoneCall * linphone_call_new_incoming(LinphoneCore *lc, LinphoneAddress *fro
        call->camera_active=call->params.has_video;
        switch (linphone_core_get_firewall_policy(call->core)) {
                case LinphonePolicyUseIce:
-                       linphone_core_gather_ice_candidates(call->core, call);
+                       linphone_call_init_media_streams(call);
+                       linphone_call_start_media_streams_for_ice_gathering(call);
+                       if (linphone_core_gather_ice_candidates(call->core,call)<0) {
+                               /* Ice candidates gathering failed, proceed with the call anyway. */
+                               ice_session_destroy(sal_op_get_ice_session(call->op));
+                               sal_op_set_ice_session(call->op, NULL);
+                               linphone_call_stop_media_streams(call);
+                       }
                        break;
                case LinphonePolicyUseStun:
                        linphone_core_run_stun_tests(call->core,call);
@@ -1469,6 +1476,7 @@ void linphone_call_stop_media_streams(LinphoneCall *call){
                rtp_session_unregister_event_queue(call->audiostream->session,call->audiostream_app_evq);
                ortp_ev_queue_flush(call->audiostream_app_evq);
                ortp_ev_queue_destroy(call->audiostream_app_evq);
+               call->audiostream_app_evq=NULL;
 
                if (call->audiostream->ec){
                        const char *state_str=NULL;
@@ -1690,98 +1698,110 @@ void linphone_call_background_tasks(LinphoneCall *call, bool_t one_second_elapse
        }
 #ifdef VIDEO_ENABLED
        if (call->videostream!=NULL) {
+               OrtpEvent *ev;
+
                // Beware that the application queue should not depend on treatments fron the
                // mediastreamer queue.
                video_stream_iterate(call->videostream);
 
-               if (call->videostream_app_evq){
-                       OrtpEvent *ev;
-                       while (NULL != (ev=ortp_ev_queue_get(call->videostream_app_evq))){
-                               OrtpEventType evt=ortp_event_get_type(ev);
-                               OrtpEventData *evd=ortp_event_get_data(ev);
-                               if (evt == ORTP_EVENT_ZRTP_ENCRYPTION_CHANGED){
-                                       linphone_call_videostream_encryption_changed(call, evd->info.zrtp_stream_encrypted);
-                               } else if (evt == ORTP_EVENT_RTCP_PACKET_RECEIVED) {
-                                       call->stats[LINPHONE_CALL_STATS_VIDEO].round_trip_delay = rtp_session_get_round_trip_propagation(call->videostream->session);
-                                       if(call->stats[LINPHONE_CALL_STATS_VIDEO].received_rtcp != NULL)
-                                               freemsg(call->stats[LINPHONE_CALL_STATS_VIDEO].received_rtcp);
-                                       call->stats[LINPHONE_CALL_STATS_VIDEO].received_rtcp = evd->packet;
-                                       evd->packet = NULL;
-                                       if (lc->vtable.call_stats_updated)
-                                               lc->vtable.call_stats_updated(lc, call, &call->stats[LINPHONE_CALL_STATS_VIDEO]);
-                               } else if (evt == ORTP_EVENT_RTCP_PACKET_EMITTED) {
-                                       memcpy(&call->stats[LINPHONE_CALL_STATS_VIDEO].jitter_stats, rtp_session_get_jitter_stats(call->videostream->session), sizeof(jitter_stats_t));
-                                       if(call->stats[LINPHONE_CALL_STATS_VIDEO].sent_rtcp != NULL)
-                                               freemsg(call->stats[LINPHONE_CALL_STATS_VIDEO].sent_rtcp);
-                                       call->stats[LINPHONE_CALL_STATS_VIDEO].sent_rtcp = evd->packet;
-                                       evd->packet = NULL;
-                                       if (lc->vtable.call_stats_updated)
-                                               lc->vtable.call_stats_updated(lc, call, &call->stats[LINPHONE_CALL_STATS_VIDEO]);
-                               } else if (evt == ORTP_EVENT_ICE_SESSION_PROCESSING_FINISHED) {
-                                       if (ice_session_role(sal_op_get_ice_session(call->op)) == IR_Controlling) {
-                                               linphone_core_update_call(lc, call, &call->current_params);
-                                       }
-                               } else if (evt == ORTP_EVENT_ICE_GATHERING_FINISHED) {
-                                       if (call->state==LinphoneCallOutgoingInit) {
-                                               linphone_call_stop_media_streams(call);
-                                               if (evd->info.ice_processing_successful==FALSE) {
-                                                       ice_session_destroy(sal_op_get_ice_session(call->op));
-                                                       sal_op_set_ice_session(call->op, NULL);
-                                               }
-                                               linphone_core_start_invite(call->core,call,NULL);
-                                       }
+               while (call->videostream_app_evq && (NULL != (ev=ortp_ev_queue_get(call->videostream_app_evq)))){
+                       OrtpEventType evt=ortp_event_get_type(ev);
+                       OrtpEventData *evd=ortp_event_get_data(ev);
+                       if (evt == ORTP_EVENT_ZRTP_ENCRYPTION_CHANGED){
+                               linphone_call_videostream_encryption_changed(call, evd->info.zrtp_stream_encrypted);
+                       } else if (evt == ORTP_EVENT_RTCP_PACKET_RECEIVED) {
+                               call->stats[LINPHONE_CALL_STATS_VIDEO].round_trip_delay = rtp_session_get_round_trip_propagation(call->videostream->session);
+                               if(call->stats[LINPHONE_CALL_STATS_VIDEO].received_rtcp != NULL)
+                                       freemsg(call->stats[LINPHONE_CALL_STATS_VIDEO].received_rtcp);
+                               call->stats[LINPHONE_CALL_STATS_VIDEO].received_rtcp = evd->packet;
+                               evd->packet = NULL;
+                               if (lc->vtable.call_stats_updated)
+                                       lc->vtable.call_stats_updated(lc, call, &call->stats[LINPHONE_CALL_STATS_VIDEO]);
+                       } else if (evt == ORTP_EVENT_RTCP_PACKET_EMITTED) {
+                               memcpy(&call->stats[LINPHONE_CALL_STATS_VIDEO].jitter_stats, rtp_session_get_jitter_stats(call->videostream->session), sizeof(jitter_stats_t));
+                               if(call->stats[LINPHONE_CALL_STATS_VIDEO].sent_rtcp != NULL)
+                                       freemsg(call->stats[LINPHONE_CALL_STATS_VIDEO].sent_rtcp);
+                               call->stats[LINPHONE_CALL_STATS_VIDEO].sent_rtcp = evd->packet;
+                               evd->packet = NULL;
+                               if (lc->vtable.call_stats_updated)
+                                       lc->vtable.call_stats_updated(lc, call, &call->stats[LINPHONE_CALL_STATS_VIDEO]);
+                       } else if (evt == ORTP_EVENT_ICE_SESSION_PROCESSING_FINISHED) {
+                               if (ice_session_role(sal_op_get_ice_session(call->op)) == IR_Controlling) {
+                                       linphone_core_update_call(lc, call, &call->current_params);
+                               }
+                       } else if (evt == ORTP_EVENT_ICE_GATHERING_FINISHED) {
+                               IceSession *ice_session = sal_op_get_ice_session(call->op);
+                               linphone_call_stop_media_streams(call);
+                               if (evd->info.ice_processing_successful==TRUE) {
+                                       ice_session_compute_candidates_foundations(ice_session);
+                                       ice_session_eliminate_redundant_candidates(ice_session);
+                                       ice_session_choose_default_candidates(ice_session);
+                               } else {
+                                       ice_session_destroy(ice_session);
+                                       sal_op_set_ice_session(call->op, NULL);
+                               }
+                               if (call->state==LinphoneCallOutgoingInit) {
+                                       linphone_core_start_invite(call->core,call,NULL);
+                               } else {
+                                       linphone_core_notify_incoming_call(call->core,call);
                                }
-                               ortp_event_destroy(ev);
                        }
+                       ortp_event_destroy(ev);
                }
        }
 #endif
        if (call->audiostream!=NULL) {
+               OrtpEvent *ev;
+
                // Beware that the application queue should not depend on treatments fron the
                // mediastreamer queue.
                audio_stream_iterate(call->audiostream);
 
-               if (call->audiostream_app_evq){
-                       OrtpEvent *ev;
-                       while (NULL != (ev=ortp_ev_queue_get(call->audiostream_app_evq))){
-                               OrtpEventType evt=ortp_event_get_type(ev);
-                               OrtpEventData *evd=ortp_event_get_data(ev);
-                               if (evt == ORTP_EVENT_ZRTP_ENCRYPTION_CHANGED){
-                                       linphone_call_audiostream_encryption_changed(call, evd->info.zrtp_stream_encrypted);
-                               } else if (evt == ORTP_EVENT_ZRTP_SAS_READY) {
-                                       linphone_call_audiostream_auth_token_ready(call, evd->info.zrtp_sas.sas, evd->info.zrtp_sas.verified);
-                               } else if (evt == ORTP_EVENT_RTCP_PACKET_RECEIVED) {
-                                       call->stats[LINPHONE_CALL_STATS_AUDIO].round_trip_delay = rtp_session_get_round_trip_propagation(call->audiostream->session);
-                                       if(call->stats[LINPHONE_CALL_STATS_AUDIO].received_rtcp != NULL)
-                                               freemsg(call->stats[LINPHONE_CALL_STATS_AUDIO].received_rtcp);
-                                       call->stats[LINPHONE_CALL_STATS_AUDIO].received_rtcp = evd->packet;
-                                       evd->packet = NULL;
-                                       if (lc->vtable.call_stats_updated)
-                                               lc->vtable.call_stats_updated(lc, call, &call->stats[LINPHONE_CALL_STATS_AUDIO]);
-                               } else if (evt == ORTP_EVENT_RTCP_PACKET_EMITTED) {
-                                       memcpy(&call->stats[LINPHONE_CALL_STATS_AUDIO].jitter_stats, rtp_session_get_jitter_stats(call->audiostream->session), sizeof(jitter_stats_t));
-                                       if(call->stats[LINPHONE_CALL_STATS_AUDIO].sent_rtcp != NULL)
-                                               freemsg(call->stats[LINPHONE_CALL_STATS_AUDIO].sent_rtcp);
-                                       call->stats[LINPHONE_CALL_STATS_AUDIO].sent_rtcp = evd->packet;
-                                       evd->packet = NULL;
-                                       if (lc->vtable.call_stats_updated)
-                                               lc->vtable.call_stats_updated(lc, call, &call->stats[LINPHONE_CALL_STATS_AUDIO]);
-                               } else if (evt == ORTP_EVENT_ICE_SESSION_PROCESSING_FINISHED) {
-                                       if (ice_session_role(sal_op_get_ice_session(call->op)) == IR_Controlling) {
-                                               linphone_core_update_call(lc, call, &call->current_params);
-                                       }
-                               } else if (evt == ORTP_EVENT_ICE_GATHERING_FINISHED) {
-                                       if (call->state==LinphoneCallOutgoingInit) {
-                                               linphone_call_stop_media_streams(call);
-                                               if (evd->info.ice_processing_successful==FALSE) {
-                                                       ice_session_destroy(sal_op_get_ice_session(call->op));
-                                                       sal_op_set_ice_session(call->op, NULL);
-                                               }
-                                               linphone_core_start_invite(call->core,call,NULL);
-                                       }
+               while (call->audiostream_app_evq && (NULL != (ev=ortp_ev_queue_get(call->audiostream_app_evq)))){
+                       OrtpEventType evt=ortp_event_get_type(ev);
+                       OrtpEventData *evd=ortp_event_get_data(ev);
+                       if (evt == ORTP_EVENT_ZRTP_ENCRYPTION_CHANGED){
+                               linphone_call_audiostream_encryption_changed(call, evd->info.zrtp_stream_encrypted);
+                       } else if (evt == ORTP_EVENT_ZRTP_SAS_READY) {
+                               linphone_call_audiostream_auth_token_ready(call, evd->info.zrtp_sas.sas, evd->info.zrtp_sas.verified);
+                       } else if (evt == ORTP_EVENT_RTCP_PACKET_RECEIVED) {
+                               call->stats[LINPHONE_CALL_STATS_AUDIO].round_trip_delay = rtp_session_get_round_trip_propagation(call->audiostream->session);
+                               if(call->stats[LINPHONE_CALL_STATS_AUDIO].received_rtcp != NULL)
+                                       freemsg(call->stats[LINPHONE_CALL_STATS_AUDIO].received_rtcp);
+                               call->stats[LINPHONE_CALL_STATS_AUDIO].received_rtcp = evd->packet;
+                               evd->packet = NULL;
+                               if (lc->vtable.call_stats_updated)
+                                       lc->vtable.call_stats_updated(lc, call, &call->stats[LINPHONE_CALL_STATS_AUDIO]);
+                       } else if (evt == ORTP_EVENT_RTCP_PACKET_EMITTED) {
+                               memcpy(&call->stats[LINPHONE_CALL_STATS_AUDIO].jitter_stats, rtp_session_get_jitter_stats(call->audiostream->session), sizeof(jitter_stats_t));
+                               if(call->stats[LINPHONE_CALL_STATS_AUDIO].sent_rtcp != NULL)
+                                       freemsg(call->stats[LINPHONE_CALL_STATS_AUDIO].sent_rtcp);
+                               call->stats[LINPHONE_CALL_STATS_AUDIO].sent_rtcp = evd->packet;
+                               evd->packet = NULL;
+                               if (lc->vtable.call_stats_updated)
+                                       lc->vtable.call_stats_updated(lc, call, &call->stats[LINPHONE_CALL_STATS_AUDIO]);
+                       } else if (evt == ORTP_EVENT_ICE_SESSION_PROCESSING_FINISHED) {
+                               if (ice_session_role(sal_op_get_ice_session(call->op)) == IR_Controlling) {
+                                       linphone_core_update_call(lc, call, &call->current_params);
+                               }
+                       } else if (evt == ORTP_EVENT_ICE_GATHERING_FINISHED) {
+                               IceSession *ice_session = sal_op_get_ice_session(call->op);
+                               linphone_call_stop_media_streams(call);
+                               if (evd->info.ice_processing_successful==TRUE) {
+                                       ice_session_compute_candidates_foundations(ice_session);
+                                       ice_session_eliminate_redundant_candidates(ice_session);
+                                       ice_session_choose_default_candidates(ice_session);
+                               } else {
+                                       ice_session_destroy(sal_op_get_ice_session(call->op));
+                                       sal_op_set_ice_session(call->op, NULL);
+                               }
+                               if (call->state==LinphoneCallOutgoingInit) {
+                                       linphone_core_start_invite(call->core,call,NULL);
+                               } else {
+                                       linphone_core_notify_incoming_call(call->core,call);
                                }
-                               ortp_event_destroy(ev);
                        }
+                       ortp_event_destroy(ev);
                }
        }
        if (call->state==LinphoneCallStreamsRunning && one_second_elapsed && call->audiostream!=NULL && disconnect_timeout>0 )
index 060259a4829680066804813c1a4f7b4ef0ff35c0..73ef52c3f44ba3e808aaa4a20e38de8778446c4c 100644 (file)
@@ -2373,6 +2373,78 @@ bool_t linphone_core_inc_invite_pending(LinphoneCore*lc){
        return FALSE;
 }
 
+void linphone_core_notify_incoming_call(LinphoneCore *lc, LinphoneCall *call){
+       char *barmesg;
+       char *tmp;
+       LinphoneAddress *from_parsed;
+       SalMediaDescription *md;
+       bool_t propose_early_media=lp_config_get_int(lc->config,"sip","incoming_calls_early_media",FALSE);
+       const char *ringback_tone=linphone_core_get_remote_ringback_tone (lc);
+
+       /* Regenerate final media description to include all ICE candidates. */
+       md=sal_call_get_final_media_description(call->op);
+
+       if (md && sal_media_description_empty(md)){
+               sal_call_decline(call->op,SalReasonMedia,NULL);
+               linphone_call_unref(call);
+               return;
+       }
+
+       from_parsed=linphone_address_new(sal_op_get_from(call->op));
+       linphone_address_clean(from_parsed);
+       tmp=linphone_address_as_string(from_parsed);
+       linphone_address_destroy(from_parsed);
+       barmesg=ortp_strdup_printf("%s %s%s",tmp,_("is contacting you"),
+           (sal_call_autoanswer_asked(call->op)) ?_(" and asked autoanswer."):_("."));
+       if (lc->vtable.show) lc->vtable.show(lc);
+       if (lc->vtable.display_status)
+           lc->vtable.display_status(lc,barmesg);
+
+       /* play the ring if this is the only call*/
+       if (ms_list_size(lc->calls)==1){
+               lc->current_call=call;
+               if (lc->ringstream && lc->dmfs_playing_start_time!=0){
+                       ring_stop(lc->ringstream);
+                       lc->ringstream=NULL;
+                       lc->dmfs_playing_start_time=0;
+               }
+               if (lc->sound_conf.ring_sndcard!=NULL){
+                       if(lc->ringstream==NULL && lc->sound_conf.local_ring){
+                               MSSndCard *ringcard=lc->sound_conf.lsd_card ?lc->sound_conf.lsd_card : lc->sound_conf.ring_sndcard;
+                               ms_message("Starting local ring...");
+                               lc->ringstream=ring_start(lc->sound_conf.local_ring,2000,ringcard);
+                       }
+                       else
+                       {
+                               ms_message("the local ring is already started");
+                       }
+               }
+       }else{
+               /* else play a tone within the context of the current call */
+               call->ringing_beep=TRUE;
+               linphone_core_play_tone(lc);
+       }
+
+       linphone_call_set_state(call,LinphoneCallIncomingReceived,"Incoming call");
+
+       if (call->state==LinphoneCallIncomingReceived){
+               sal_call_notify_ringing(call->op,propose_early_media || ringback_tone!=NULL);
+
+               if (propose_early_media || ringback_tone!=NULL){
+                       linphone_call_set_state(call,LinphoneCallIncomingEarlyMedia,"Incoming call early media");
+                       md=sal_call_get_final_media_description(call->op);
+                       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);
+               }
+       }
+       linphone_call_unref(call);
+
+       ms_free(barmesg);
+       ms_free(tmp);
+}
+
 /**
  * @ingroup call_control
  * Updates a running call according to supplied call parameters or parameters changed in the LinphoneCore.
index 10f6108c9ba3102c108199700454312b3988839f..67e887c609734902c6892773c5b0585a80d001fb 100644 (file)
@@ -783,6 +783,8 @@ int linphone_core_transfer_call_to_another(LinphoneCore *lc, LinphoneCall *call,
 
 bool_t linphone_core_inc_invite_pending(LinphoneCore*lc);
 
+void linphone_core_notify_incoming_call(LinphoneCore *lc, LinphoneCall *call);
+
 bool_t linphone_core_in_call(const LinphoneCore *lc);
 
 LinphoneCall *linphone_core_get_current_call(const LinphoneCore *lc);