]> sjero.net Git - linphone/commitdiff
Redesign ICE integration to prevent Sal from depending on ICE.
authorGhislain MARY <ghislain.mary@belledonne-communications.com>
Fri, 3 Aug 2012 08:53:49 +0000 (10:53 +0200)
committerGhislain MARY <ghislain.mary@belledonne-communications.com>
Mon, 6 Aug 2012 09:16:16 +0000 (11:16 +0200)
 - Move the ICE session from the Sal Op to the LinphoneCall.
 - Do not access directly to the ICE session to generate the SDP from
   the media description or to generate the media description from the
   SDP. Instead include ICE attributes in the media description.

coreapi/callbacks.c
coreapi/linphonecall.c
coreapi/linphonecore.c
coreapi/misc.c
coreapi/private.h
coreapi/sal.c
coreapi/sal.h
coreapi/sal_eXosip2.c
coreapi/sal_eXosip2.h
coreapi/sal_eXosip2_sdp.c

index dd17650f565e7aec03723f2fa4b065373f6671c3..63327de66dad777ab968f49f98c3db9f54bc13cc 100644 (file)
@@ -187,7 +187,7 @@ static void call_received(SalOp *h){
        linphone_core_add_call(lc,call);
        linphone_call_ref(call); /*prevent the call from being destroyed while we are notifying, if the user declines within the state callback */
 
-       if ((linphone_core_get_firewall_policy(lc) == LinphonePolicyUseIce) && sal_op_get_ice_session(call->op)) {
+       if ((linphone_core_get_firewall_policy(lc) == LinphonePolicyUseIce) && (call->ice_session != NULL)) {
                /* Defer ringing until the end of the ICE candidates gathering process. */
                ms_message("Defer ringing to gather ICE candidates");
                return;
@@ -254,7 +254,6 @@ static void call_ringing(SalOp *h){
 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);
-       IceSession *ice_session=sal_op_get_ice_session(op);
        SalMediaDescription *md;
        
        if (call==NULL){
@@ -262,7 +261,7 @@ static void call_accepted(SalOp *op){
                return ;
        }
 
-       if (ice_session == NULL) {
+       if (call->ice_session == NULL) {
                /* Ensure the ICE check list pointers for the call streams are resetted to prevent crashes */
                if (call->audiostream != NULL) call->audiostream->ice_check_list = NULL;
                if (call->videostream != NULL) call->videostream->ice_check_list = NULL;
index d8fcb12c9b4ca8ffc75bba3a95f8315e80d9ac1c..4a06a7873be51378bd3e8c1adea65f5dc5e11d51 100644 (file)
@@ -201,7 +201,6 @@ static SalMediaDescription *_create_local_media_description(LinphoneCore *lc, Li
        LinphoneAddress *addr=linphone_address_new(me);
        const char *username=linphone_address_get_username (addr);
        SalMediaDescription *md=sal_media_description_new();
-       IceSession *ice_session=sal_op_get_ice_session(call->op);
 
        md->session_id=session_id;
        md->session_ver=session_ver;
@@ -249,8 +248,8 @@ static SalMediaDescription *_create_local_media_description(LinphoneCore *lc, Li
                        md->streams[i].crypto[2].algo = 0;
                }
                if ((call->dir == LinphoneCallOutgoing) && (linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseIce)
-                       && (ice_session != NULL) && (ice_session_check_list(ice_session, i) == NULL)) {
-                       ice_session_add_check_list(ice_session, ice_check_list_new());
+                       && (call->ice_session != NULL) && (ice_session_check_list(call->ice_session, i) == NULL)) {
+                       ice_session_add_check_list(call->ice_session, ice_check_list_new());
                }
        }
        
@@ -346,8 +345,8 @@ LinphoneCall * linphone_call_new_outgoing(struct _LinphoneCore *lc, LinphoneAddr
        linphone_call_init_common(call,from,to);
        call->params=*params;
        if (linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseIce) {
-               sal_op_set_ice_session(call->op, ice_session_new());
-               ice_session_set_role(sal_op_get_ice_session(call->op), IR_Controlling);
+               call->ice_session = ice_session_new();
+               ice_session_set_role(call->ice_session, IR_Controlling);
        }
        call->localdesc=create_local_media_description (lc,call);
        call->camera_active=params->has_video;
@@ -403,9 +402,7 @@ LinphoneCall * linphone_call_new_incoming(LinphoneCore *lc, LinphoneAddress *fro
                        linphone_core_run_stun_tests(call->core,call);
                        /* No break to also destroy ice session in this case. */
                default:
-                       if (sal_op_get_ice_session(call->op) != NULL) {
-                               linphone_call_delete_ice_session(call);
-                       }
+                       linphone_call_delete_ice_session(call);
                        break;
        }
        discover_mtu(lc,linphone_address_get_domain(from));
@@ -552,11 +549,10 @@ void linphone_call_enable_video(LinphoneCall *call, bool_t enabled)
 {
        LinphoneCore *lc=linphone_call_get_core(call);
        LinphoneCallParams *params=linphone_call_params_copy(linphone_call_get_current_params(call));
-       IceSession *ice_session=sal_op_get_ice_session(call->op);
 
        linphone_call_params_enable_video(params, enabled);
        if (enabled == TRUE) {
-               if (ice_session != NULL) {
+               if (call->ice_session != NULL) {
                        /* Defer call update until the ICE candidates gathering process has finished. */
                        ms_message("Defer call update to gather ICE candidates");
                        call->params = *params;
@@ -572,8 +568,8 @@ void linphone_call_enable_video(LinphoneCall *call, bool_t enabled)
                        }
                }
        } else {
-               if ((ice_session != NULL) && (call->videostream != NULL)) {
-                       ice_session_remove_check_list(ice_session, call->videostream->ice_check_list);
+               if ((call->ice_session != NULL) && (call->videostream != NULL)) {
+                       ice_session_remove_check_list(call->ice_session, call->videostream->ice_check_list);
                        call->videostream->ice_check_list = NULL;
                }
                if (linphone_call_get_state(call) == LinphoneCallUpdatedByRemote) {
@@ -610,6 +606,9 @@ static void linphone_call_destroy(LinphoneCall *obj)
        if (obj->auth_token) {
                ms_free(obj->auth_token);
        }
+       if (obj->ice_session) {
+               ice_session_destroy(obj->ice_session);
+       }
 
        ms_free(obj);
 }
@@ -971,7 +970,6 @@ void linphone_call_init_audio_stream(LinphoneCall *call){
        LinphoneCore *lc=call->core;
        SalMediaDescription *md=call->localdesc;
        AudioStream *audiostream;
-       IceSession *ice_session = sal_op_get_ice_session(call->op);
 
        call->audiostream=audiostream=audio_stream_new(md->streams[0].rtp_port,md->streams[0].rtcp_port,linphone_core_ipv6_enabled(lc));
        if (linphone_core_echo_limiter_enabled(lc)){
@@ -1004,9 +1002,9 @@ void linphone_call_init_audio_stream(LinphoneCall *call){
                RtpTransport *artcp=lc->rtptf->audio_rtcp_func(lc->rtptf->audio_rtcp_func_data, call->audio_port+1);
                rtp_session_set_transports(audiostream->session,artp,artcp);
        }
-       if ((linphone_core_get_firewall_policy(lc) == LinphonePolicyUseIce) && (ice_session != NULL)){
+       if ((linphone_core_get_firewall_policy(lc) == LinphonePolicyUseIce) && (call->ice_session != NULL)){
                rtp_session_set_pktinfo(audiostream->session, TRUE);
-               audiostream->ice_check_list = ice_session_check_list(ice_session, 0);
+               audiostream->ice_check_list = ice_session_check_list(call->ice_session, 0);
                ice_check_list_set_rtp_session(audiostream->ice_check_list, audiostream->session);
        }
 
@@ -1018,7 +1016,6 @@ void linphone_call_init_video_stream(LinphoneCall *call){
 #ifdef VIDEO_ENABLED
        LinphoneCore *lc=call->core;
        SalMediaDescription *md=call->localdesc;
-       IceSession *ice_session = sal_op_get_ice_session(call->op);
 
        if ((lc->video_conf.display || lc->video_conf.capture) && md->streams[1].rtp_port>0){
                int video_recv_buf_size=lp_config_get_int(lc->config,"video","recv_buf_size",0);
@@ -1034,9 +1031,9 @@ void linphone_call_init_video_stream(LinphoneCall *call){
                        RtpTransport *vrtcp=lc->rtptf->video_rtcp_func(lc->rtptf->video_rtcp_func_data, call->video_port+1);
                        rtp_session_set_transports(call->videostream->session,vrtp,vrtcp);
                }
-               if ((linphone_core_get_firewall_policy(lc) == LinphonePolicyUseIce) && (ice_session != NULL) && (ice_session_check_list(ice_session, 1))){
+               if ((linphone_core_get_firewall_policy(lc) == LinphonePolicyUseIce) && (call->ice_session != NULL) && (ice_session_check_list(call->ice_session, 1))){
                        rtp_session_set_pktinfo(call->videostream->session, TRUE);
-                       call->videostream->ice_check_list = ice_session_check_list(ice_session, 1);
+                       call->videostream->ice_check_list = ice_session_check_list(call->ice_session, 1);
                        ice_check_list_set_rtp_session(call->videostream->ice_check_list, call->videostream->session);
                }
                call->videostream_app_evq = ortp_ev_queue_new();
@@ -1495,8 +1492,8 @@ void linphone_call_start_media_streams(LinphoneCall *call, bool_t all_inputs_mut
        /*also reflect the change if the "wished" params, in order to avoid to propose SAVP or video again
         * further in the call, for example during pause,resume, conferencing reINVITEs*/
        linphone_call_fix_call_parameters(call);
-       if ((sal_op_get_ice_session(call->op) != NULL) && (ice_session_state(sal_op_get_ice_session(call->op)) != IS_Completed)) {
-               ice_session_start_connectivity_checks(sal_op_get_ice_session(call->op));
+       if ((call->ice_session != NULL) && (ice_session_state(call->ice_session) != IS_Completed)) {
+               ice_session_start_connectivity_checks(call->ice_session);
        }
 
        goto end;
@@ -1513,10 +1510,9 @@ void linphone_call_start_media_streams_for_ice_gathering(LinphoneCall *call){
 }
 
 void linphone_call_delete_ice_session(LinphoneCall *call){
-       IceSession *ice_session = sal_op_get_ice_session(call->op);
-       if (ice_session != NULL) {
-               ice_session_destroy(ice_session);
-               sal_op_set_ice_session(call->op, NULL);
+       if (call->ice_session != NULL) {
+               ice_session_destroy(call->ice_session);
+               call->ice_session = NULL;
                if (call->audiostream != NULL) call->audiostream->ice_check_list = NULL;
                if (call->videostream != NULL) call->videostream->ice_check_list = NULL;
        }
@@ -1739,19 +1735,18 @@ static void handle_ice_events(LinphoneCall *call, OrtpEvent *ev){
        OrtpEventData *evd=ortp_event_get_data(ev);
 
        if (evt == ORTP_EVENT_ICE_SESSION_PROCESSING_FINISHED) {
-               if (ice_session_role(sal_op_get_ice_session(call->op)) == IR_Controlling) {
+               if (ice_session_role(call->ice_session) == IR_Controlling) {
                        linphone_core_update_call(call->core, call, &call->current_params);
                }
        } else if (evt == ORTP_EVENT_ICE_GATHERING_FINISHED) {
-               IceSession *ice_session = sal_op_get_ice_session(call->op);
                LinphoneCallParams *params;
                switch (call->state) {
                        case LinphoneCallStreamsRunning:
                        case LinphoneCallUpdatedByRemote:
                                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);
+                                       ice_session_compute_candidates_foundations(call->ice_session);
+                                       ice_session_eliminate_redundant_candidates(call->ice_session);
+                                       ice_session_choose_default_candidates(call->ice_session);
                                }
                                params = linphone_call_params_copy(linphone_call_get_current_params(call));
                                linphone_call_params_enable_video(params, TRUE);
@@ -1766,9 +1761,9 @@ static void handle_ice_events(LinphoneCall *call, OrtpEvent *ev){
                        default:
                                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);
+                                       ice_session_compute_candidates_foundations(call->ice_session);
+                                       ice_session_eliminate_redundant_candidates(call->ice_session);
+                                       ice_session_choose_default_candidates(call->ice_session);
                                } else {
                                        linphone_call_delete_ice_session(call);
                                }
@@ -1808,7 +1803,7 @@ void linphone_call_background_tasks(LinphoneCall *call, bool_t one_second_elapse
                OrtpEvent *ev;
 
                /* Ensure there is no dangling ICE check list. */
-               if (sal_op_get_ice_session(call->op) == NULL) call->videostream->ice_check_list = NULL;
+               if (call->ice_session == NULL) call->videostream->ice_check_list = NULL;
 
                // Beware that the application queue should not depend on treatments fron the
                // mediastreamer queue.
@@ -1846,7 +1841,7 @@ void linphone_call_background_tasks(LinphoneCall *call, bool_t one_second_elapse
                OrtpEvent *ev;
 
                /* Ensure there is no dangling ICE check list. */
-               if (sal_op_get_ice_session(call->op) == NULL) call->audiostream->ice_check_list = NULL;
+               if (call->ice_session == NULL) call->audiostream->ice_check_list = NULL;
 
                // Beware that the application queue should not depend on treatments fron the
                // mediastreamer queue.
index 921e1800ee81a19d21945c5b6a4a4d524f1bd2d8..6f08e92600c8a2c6d9211a7453979dcaa434af9c 100644 (file)
@@ -1852,7 +1852,7 @@ void linphone_core_iterate(LinphoneCore *lc){
                linphone_call_background_tasks(call,one_second_elapsed);
                if (call->state==LinphoneCallOutgoingInit && (curtime-call->start_time>=2)){
                        /*start the call even if the OPTIONS reply did not arrive*/
-                       if (sal_op_get_ice_session(call->op) != NULL) {
+                       if (call->ice_session != NULL) {
                                /* ICE candidates gathering has not finished yet, proceed with the call without ICE anyway. */
                                linphone_call_delete_ice_session(call);
                                linphone_call_stop_media_streams(call);
index 0e4be8e111c94cfeac0a33a245010afe3b28a365..a59aca8862238c10a18344559031bfa889c8397c 100644 (file)
@@ -569,12 +569,11 @@ int linphone_core_gather_ice_candidates(LinphoneCore *lc, LinphoneCall *call)
        socklen_t ss_len;
        IceCheckList *audio_check_list;
        IceCheckList *video_check_list;
-       IceSession *ice_session = sal_op_get_ice_session(call->op);
        const char *server = linphone_core_get_stun_server(lc);
 
-       if ((server == NULL) || (ice_session == NULL)) return -1;
-       audio_check_list = ice_session_check_list(ice_session, 0);
-       video_check_list = ice_session_check_list(ice_session, 1);
+       if ((server == NULL) || (call->ice_session == NULL)) return -1;
+       audio_check_list = ice_session_check_list(call->ice_session, 0);
+       video_check_list = ice_session_check_list(call->ice_session, 1);
        if (audio_check_list == NULL) return -1;
 
        if (lc->sip_conf.ipv6_enabled){
@@ -602,7 +601,7 @@ int linphone_core_gather_ice_candidates(LinphoneCore *lc, LinphoneCall *call)
        }
 
        /* Gather local srflx candidates. */
-       ice_session_gather_candidates(ice_session, ss, ss_len);
+       ice_session_gather_candidates(call->ice_session, ss, ss_len);
        return 0;
 }
 
index 61d1d4179a0919f04ead75b1486deebb11be2048..bc65e946e8ca7598799f0803b2e97503b70039bf 100644 (file)
@@ -136,6 +136,7 @@ struct _LinphoneCall
        bool_t was_automatically_paused;
        CallCallbackObj nextVideoFrameDecoded;
        LinphoneCallStats stats[2];
+       IceSession *ice_session;
 };
 
 
index 5b592b8d36ccdb312709001605607d2ef7eb1e60..a7bb00e3e816d32c01433e75eef7d16c4be10af7 100644 (file)
@@ -234,10 +234,6 @@ void sal_op_set_user_pointer(SalOp *op, void *up){
        ((SalOpBase*)op)->user_pointer=up;
 }
 
-void sal_op_set_ice_session(SalOp *op, IceSession *ice_session){
-       ((SalOpBase*)op)->ice_session=ice_session;
-}
-
 Sal *sal_op_get_sal(const SalOp *op){
        return ((SalOpBase*)op)->root;
 }
@@ -266,10 +262,6 @@ void *sal_op_get_user_pointer(const SalOp *op){
        return ((SalOpBase*)op)->user_pointer;
 }
 
-IceSession *sal_op_get_ice_session(const SalOp *op){
-       return ((SalOpBase*)op)->ice_session;
-}
-
 const char *sal_op_get_proxy(const SalOp *op){
        return ((SalOpBase*)op)->route;
 }
@@ -318,8 +310,6 @@ void __sal_op_free(SalOp *op){
                sal_media_description_unref(b->local_media);
        if (b->remote_media)
                sal_media_description_unref(b->remote_media);
-       if (b->ice_session)
-               ice_session_destroy(b->ice_session);
        ms_free(op);
 }
 
index 8a51fa4a4a4fa409ebabb0904242b6b35072b200..dfb5604721450967b2755792ee19d600036cd893 100644 (file)
@@ -27,7 +27,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 #define sal_h
 
 #include "mediastreamer2/mscommon.h"
-#include "mediastreamer2/ice.h"
 #include "ortp/ortp_srtp.h"
 
 /*Dirty hack, keep in sync with mediastreamer2/include/mediastream.h */
@@ -113,6 +112,33 @@ typedef struct SalEndpointCandidate{
 
 #define SAL_ENDPOINT_CANDIDATE_MAX 2
 
+#define SAL_MEDIA_DESCRIPTION_MAX_ICE_ADDR_LEN 64
+#define SAL_MEDIA_DESCRIPTION_MAX_ICE_FOUNDATION_LEN 32
+#define SAL_MEDIA_DESCRIPTION_MAX_ICE_TYPE_LEN 6
+
+typedef struct SalIceCandidate {
+       char addr[SAL_MEDIA_DESCRIPTION_MAX_ICE_ADDR_LEN];
+       char raddr[SAL_MEDIA_DESCRIPTION_MAX_ICE_ADDR_LEN];
+       char foundation[SAL_MEDIA_DESCRIPTION_MAX_ICE_FOUNDATION_LEN];
+       char type[SAL_MEDIA_DESCRIPTION_MAX_ICE_TYPE_LEN];
+       unsigned int componentID;
+       unsigned int priority;
+       int port;
+       int rport;
+} SalIceCandidate;
+
+#define SAL_MEDIA_DESCRIPTION_MAX_ICE_CANDIDATES 10
+
+typedef struct SalIceRemoteCandidate {
+       char addr[SAL_MEDIA_DESCRIPTION_MAX_ICE_ADDR_LEN];
+       int port;
+} SalIceRemoteCandidate;
+
+#define SAL_MEDIA_DESCRIPTION_MAX_ICE_REMOTE_CANDIDATES 2
+
+#define SAL_MEDIA_DESCRIPTION_MAX_ICE_UFRAG_LEN 256
+#define SAL_MEDIA_DESCRIPTION_MAX_ICE_PWD_LEN 256
+
 typedef struct SalSrtpCryptoAlgo {
        unsigned int tag;
        enum ortp_srtp_crypto_suite_t algo;
@@ -138,6 +164,11 @@ typedef struct SalStreamDescription{
        SalSrtpCryptoAlgo crypto[SAL_CRYPTO_ALGO_MAX];
        unsigned int crypto_local_tag;
        int max_rate;
+       SalIceCandidate ice_candidates[SAL_MEDIA_DESCRIPTION_MAX_ICE_CANDIDATES];
+       SalIceRemoteCandidate ice_remote_candidates[SAL_MEDIA_DESCRIPTION_MAX_ICE_REMOTE_CANDIDATES];
+       char ice_ufrag[SAL_MEDIA_DESCRIPTION_MAX_ICE_UFRAG_LEN];
+       char ice_pwd[SAL_MEDIA_DESCRIPTION_MAX_ICE_PWD_LEN];
+       bool_t ice_mismatch;
 } SalStreamDescription;
 
 #define SAL_MEDIA_DESCRIPTION_MAX_STREAMS 4
@@ -151,10 +182,13 @@ typedef struct SalMediaDescription{
        unsigned int session_ver;
        unsigned int session_id;
        SalStreamDescription streams[SAL_MEDIA_DESCRIPTION_MAX_STREAMS];
+       char ice_ufrag[SAL_MEDIA_DESCRIPTION_MAX_ICE_UFRAG_LEN];
+       char ice_pwd[SAL_MEDIA_DESCRIPTION_MAX_ICE_PWD_LEN];
+       bool_t ice_lite;
+       bool_t ice_completed;
 } SalMediaDescription;
 
 #define SAL_MEDIA_DESCRIPTION_MAX_MESSAGE_ATTRIBUTES 5
-#define SAL_MEDIA_DESCRIPTION_MAX_ICE_CANDIDATES 10
 
 SalMediaDescription *sal_media_description_new();
 void sal_media_description_ref(SalMediaDescription *md);
@@ -177,7 +211,6 @@ typedef struct SalOpBase{
        char *remote_ua;
        SalMediaDescription *local_media;
        SalMediaDescription *remote_media;
-       IceSession *ice_session;
        void *user_pointer;
 } SalOpBase;
 
@@ -322,7 +355,6 @@ void sal_op_release(SalOp *h);
 void sal_op_authenticate(SalOp *h, const SalAuthInfo *info);
 void sal_op_cancel_authentication(SalOp *h);
 void sal_op_set_user_pointer(SalOp *h, void *up);
-void sal_op_set_ice_session(SalOp *h, IceSession *ice_session);
 int sal_op_get_auth_requested(SalOp *h, const char **realm, const char **username);
 const char *sal_op_get_from(const SalOp *op);
 const char *sal_op_get_to(const SalOp *op);
@@ -334,7 +366,6 @@ const char *sal_op_get_network_origin(const SalOp *op);
 /*returns far-end "User-Agent" string */
 const char *sal_op_get_remote_ua(const SalOp *op);
 void *sal_op_get_user_pointer(const SalOp *op);
-IceSession *sal_op_get_ice_session(const SalOp *op);
 
 /*Call API*/
 int sal_call_set_local_media_description(SalOp *h, SalMediaDescription *desc);
index 42f11eca095333ac7838be1e6eb166e9867a0afb..a9f3559b670062d3272f956c33e491e515fe6bf0 100644 (file)
@@ -502,8 +502,8 @@ static void set_sdp(osip_message_t *sip,sdp_message_t *msg){
        osip_free(sdp);
 }
 
-static void set_sdp_from_desc(osip_message_t *sip, const SalMediaDescription *desc, const IceSession *ice_session){
-       sdp_message_t *msg=media_description_to_sdp(desc, ice_session);
+static void set_sdp_from_desc(osip_message_t *sip, const SalMediaDescription *desc){
+       sdp_message_t *msg=media_description_to_sdp(desc);
        if (msg==NULL) {
                ms_error("Fail to print sdp message !");
                return;
@@ -526,7 +526,7 @@ static void sdp_process(SalOp *h){
                        sdp_message_free(h->sdp_answer);
                }
                offer_answer_initiate_incoming(h->base.local_media,h->base.remote_media,h->result,h->base.root->one_matching_codec);
-               h->sdp_answer=media_description_to_sdp(h->result, sal_op_get_ice_session(h));
+               h->sdp_answer=media_description_to_sdp(h->result);
                /*once we have generated the SDP answer, we modify the result description for processing by the upper layer.
                 It should contains media parameters constraint from the remote offer, not our response*/
                strcpy(h->result->addr,h->base.remote_media->addr);
@@ -600,7 +600,7 @@ int sal_call(SalOp *h, const char *from, const char *to){
        }
        if (h->base.local_media){
                h->sdp_offering=TRUE;
-               set_sdp_from_desc(invite,h->base.local_media,sal_op_get_ice_session(h));
+               set_sdp_from_desc(invite,h->base.local_media);
        }else h->sdp_offering=FALSE;
        if (h->replaces){
                osip_message_set_header(invite,"Replaces",h->replaces);
@@ -668,7 +668,7 @@ int sal_call_accept(SalOp * h){
        if (h->base.local_media){
                /*this is the case where we received an invite without SDP*/
                if (h->sdp_offering) {
-                       set_sdp_from_desc(msg,h->base.local_media,sal_op_get_ice_session(h));
+                       set_sdp_from_desc(msg,h->base.local_media);
                }else{
                        if (h->sdp_answer==NULL) sdp_process(h);
                        if (h->sdp_answer){
@@ -990,7 +990,6 @@ static void inc_new_call(Sal *sal, eXosip_event_t *ev){
        osip_call_info_t *call_info;
        char *tmp;
        sdp_message_t *sdp=eXosip_get_sdp_info(ev->request);
-       IceSession *ice_session;
 
        set_network_origin(op,ev->request);
        set_remote_ua(op,ev->request);
@@ -999,9 +998,7 @@ static void inc_new_call(Sal *sal, eXosip_event_t *ev){
        if (sdp){
                op->sdp_offering=FALSE;
                op->base.remote_media=sal_media_description_new();
-               ice_session=sal_op_get_ice_session(op);
-               sdp_to_media_description(sdp,op->base.remote_media,&ice_session);
-               sal_op_set_ice_session(op,ice_session);
+               sdp_to_media_description(sdp,op->base.remote_media);
                sdp_message_free(sdp);
        }else op->sdp_offering=TRUE;
 
@@ -1037,7 +1034,6 @@ static void inc_new_call(Sal *sal, eXosip_event_t *ev){
 static void handle_reinvite(Sal *sal,  eXosip_event_t *ev){
        SalOp *op=find_op(sal,ev);
        sdp_message_t *sdp;
-       IceSession *ice_session;
 
        if (op==NULL) {
                ms_warning("Reinvite for non-existing operation !");
@@ -1057,9 +1053,7 @@ static void handle_reinvite(Sal *sal,  eXosip_event_t *ev){
        if (sdp){
                op->sdp_offering=FALSE;
                op->base.remote_media=sal_media_description_new();
-               ice_session=sal_op_get_ice_session(op);
-               sdp_to_media_description(sdp,op->base.remote_media,&ice_session);
-               sal_op_set_ice_session(op,ice_session);
+               sdp_to_media_description(sdp,op->base.remote_media);
                sdp_message_free(sdp);
                
        }else {
@@ -1071,7 +1065,6 @@ static void handle_reinvite(Sal *sal,  eXosip_event_t *ev){
 static void handle_ack(Sal *sal,  eXosip_event_t *ev){
        SalOp *op=find_op(sal,ev);
        sdp_message_t *sdp;
-       IceSession *ice_session;
 
        if (op==NULL) {
                ms_warning("ack for non-existing call !");
@@ -1088,9 +1081,7 @@ static void handle_ack(Sal *sal,  eXosip_event_t *ev){
                        if (op->base.remote_media)
                                sal_media_description_unref(op->base.remote_media);
                        op->base.remote_media=sal_media_description_new();
-                       ice_session=sal_op_get_ice_session(op);
-                       sdp_to_media_description(sdp,op->base.remote_media,&ice_session);
-                       sal_op_set_ice_session(op,ice_session);
+                       sdp_to_media_description(sdp,op->base.remote_media);
                        sdp_process(op);
                        sdp_message_free(sdp);
                }
@@ -1150,16 +1141,13 @@ static int call_proceeding(Sal *sal, eXosip_event_t *ev){
 static void call_ringing(Sal *sal, eXosip_event_t *ev){
        sdp_message_t *sdp;
        SalOp *op=find_op(sal,ev);
-       IceSession *ice_session;
        if (call_proceeding(sal, ev)==-1) return;
 
        set_remote_ua(op,ev->response);
        sdp=eXosip_get_sdp_info(ev->response);
        if (sdp){
                op->base.remote_media=sal_media_description_new();
-               ice_session=sal_op_get_ice_session(op);
-               sdp_to_media_description(sdp,op->base.remote_media,&ice_session);
-               sal_op_set_ice_session(op,ice_session);
+               sdp_to_media_description(sdp,op->base.remote_media);
                sdp_message_free(sdp);
                if (op->base.local_media) sdp_process(op);
        }
@@ -1171,7 +1159,6 @@ static void call_accepted(Sal *sal, eXosip_event_t *ev){
        osip_message_t *msg=NULL;
        SalOp *op=find_op(sal,ev);
        const char *contact;
-       IceSession *ice_session;
        
        if (op==NULL || op->terminated==TRUE) {
                ms_warning("This call has been already terminated.");
@@ -1187,9 +1174,7 @@ static void call_accepted(Sal *sal, eXosip_event_t *ev){
        sdp=eXosip_get_sdp_info(ev->response);
        if (sdp){
                op->base.remote_media=sal_media_description_new();
-               ice_session=sal_op_get_ice_session(op);
-               sdp_to_media_description(sdp,op->base.remote_media,&ice_session);
-               sal_op_set_ice_session(op,ice_session);
+               sdp_to_media_description(sdp,op->base.remote_media);
                sdp_message_free(sdp);
                if (op->base.local_media) sdp_process(op);
        }
@@ -2427,7 +2412,7 @@ int sal_call_update(SalOp *h, const char *subject){
        }
        if (h->base.local_media){
                h->sdp_offering=TRUE;
-               set_sdp_from_desc(reinvite,h->base.local_media,sal_op_get_ice_session(h));
+               set_sdp_from_desc(reinvite,h->base.local_media);
        }else h->sdp_offering=FALSE;
        eXosip_lock();
        err = eXosip_call_send_request(h->did, reinvite);
index e3264f74de5fca0d69bc2932441adffea96034fc..ccc95d56a76f30d758999e2527a57176c030084d 100644 (file)
@@ -25,8 +25,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
 
 
-sdp_message_t *media_description_to_sdp(const SalMediaDescription *sal, const IceSession *ice_session);
-int sdp_to_media_description(sdp_message_t *sdp, SalMediaDescription *desc, IceSession **ice_session);
+sdp_message_t *media_description_to_sdp(const SalMediaDescription *sal);
+int sdp_to_media_description(sdp_message_t *sdp, SalMediaDescription *desc);
 
 struct Sal{
        SalCallbacks callbacks;
index 1cd88cad71c728843b0d3481a6171de8494d35c9..e03e65bae95864c4aa1db4b8816eadc1aea334dd 100644 (file)
@@ -124,7 +124,7 @@ static int _sdp_message_get_mline_dir(sdp_message_t *sdp, int mline){
        return SalStreamSendRecv;
 }
 
-static sdp_message_t *create_generic_sdp(const SalMediaDescription *desc, const IceSession *ice_session)
+static sdp_message_t *create_generic_sdp(const SalMediaDescription *desc)
 {
        sdp_message_t *local;
        int inet6;
@@ -144,14 +144,6 @@ static sdp_message_t *create_generic_sdp(const SalMediaDescription *desc, const
                          osip_strdup ("IN"), inet6 ? osip_strdup("IP6") : osip_strdup ("IP4"),
                          osip_strdup (desc->addr));
        sdp_message_s_name_set (local, osip_strdup ("Talk"));
-       if ((ice_session != NULL) && (ice_session_check_list(ice_session, 0) != NULL)) {
-               if (ice_session_state(ice_session) == IS_Completed) {
-                       ice_check_list_nominated_valid_local_candidate(ice_session_check_list(ice_session, 0), &rtp_addr, NULL, NULL, NULL);
-               }
-               else {
-                       ice_check_list_default_local_candidate(ice_session_check_list(ice_session, 0), &rtp_addr, NULL, NULL, NULL);
-               }
-       }
        if(!sal_media_description_has_dir (desc,SalStreamSendOnly))
        {
                sdp_message_c_connection_add (local, -1,
@@ -167,23 +159,9 @@ static sdp_message_t *create_generic_sdp(const SalMediaDescription *desc, const
        sdp_message_t_time_descr_add (local, osip_strdup ("0"), osip_strdup ("0"));
        if (desc->bandwidth>0) sdp_message_b_bandwidth_add (local, -1, osip_strdup ("AS"),
                        int_2char(desc->bandwidth));
-       if ((ice_session != NULL) && (ice_session_check_list(ice_session, 0) != NULL)) {
-               char buffer[512];
-               switch (ice_session_state(ice_session)) {
-                       case IS_Completed:
-                               sdp_message_a_attribute_add(local, -1, osip_strdup("nortpproxy"), osip_strdup("yes"));
-                               /* No break to also include the ice-ufrag and ice-pwd attributes when ICE session is completed. */
-                       case IS_Running:
-                       case IS_Stopped:
-                               snprintf(buffer, sizeof(buffer), "%s", ice_session_local_pwd(ice_session));
-                               sdp_message_a_attribute_add(local, -1, osip_strdup("ice-pwd"), osip_strdup(buffer));
-                               snprintf(buffer, sizeof(buffer), "%s", ice_session_local_ufrag(ice_session));
-                               sdp_message_a_attribute_add(local, -1, osip_strdup("ice-ufrag"), osip_strdup(buffer));
-                               break;
-                       default:
-                               break;
-               }
-       }
+       if (desc->ice_completed == TRUE) sdp_message_a_attribute_add(local, -1, osip_strdup("nortpproxy"), osip_strdup("yes"));
+       if (desc->ice_pwd[0] != '\0') sdp_message_a_attribute_add(local, -1, osip_strdup("ice-pwd"), osip_strdup(desc->ice_pwd));
+       if (desc->ice_ufrag[0] != '\0') sdp_message_a_attribute_add(local, -1, osip_strdup("ice-ufrag"), osip_strdup(desc->ice_ufrag));
 
        return local;
 }
@@ -224,83 +202,57 @@ static void add_payload(sdp_message_t *msg, int line, const PayloadType *pt, boo
        }
 }
 
-static void add_candidate_attribute(sdp_message_t *msg, int lineno, const IceCandidate *candidate)
+static void add_ice_candidates(sdp_message_t *msg, int lineno, const SalStreamDescription *desc)
 {
        char buffer[1024];
+       const SalIceCandidate *candidate;
        int nb;
+       int i;
 
-       nb = snprintf(buffer, sizeof(buffer), "%s %d UDP %d %s %d typ %s",
-               candidate->foundation, candidate->componentID, candidate->priority, candidate->taddr.ip, candidate->taddr.port, ice_candidate_type(candidate));
-       if (nb < 0) {
-               ms_error("Cannot add ICE candidate attribute!");
-               return;
-       }
-       if (candidate->type != ICT_HostCandidate) {
-               nb = snprintf(buffer + nb, sizeof(buffer) - nb, " raddr %s rport %d", candidate->base->taddr.ip, candidate->base->taddr.port);
+       for (i = 0; i < SAL_MEDIA_DESCRIPTION_MAX_ICE_CANDIDATES; i++) {
+               candidate = &desc->ice_candidates[i];
+               if ((candidate->addr[0] == '\0') || (candidate->port == 0)) break;
+               nb = snprintf(buffer, sizeof(buffer), "%s %u UDP %u %s %d typ %s",
+                       candidate->foundation, candidate->componentID, candidate->priority, candidate->addr, candidate->port, candidate->type);
                if (nb < 0) {
                        ms_error("Cannot add ICE candidate attribute!");
                        return;
                }
-       }
-       sdp_message_a_attribute_add(msg, lineno, osip_strdup("candidate"), osip_strdup(buffer));
-}
-
-static void add_ice_candidates(sdp_message_t *msg, int lineno, const IceCheckList *ice_cl, const char *rtp_addr, int rtp_port, const char *rtcp_addr, int rtcp_port)
-{
-       const IceCandidate *candidate;
-       int i;
-
-       if ((ice_check_list_state(ice_cl) == ICL_Failed) && ice_check_list_is_mismatch(ice_cl)) {
-               sdp_message_a_attribute_add(msg, lineno, osip_strdup("ice-mismatch"), NULL);
-               return;
-       }
-       for (i = 0; i < ms_list_size(ice_cl->local_candidates); i++) {
-               candidate = ms_list_nth_data(ice_cl->local_candidates, i);
-               switch (ice_check_list_state(ice_cl)) {
-                       case ICL_Running:
-                               add_candidate_attribute(msg, lineno, candidate);
-                               break;
-                       case ICL_Completed:
-                               /* Only include the candidates matching the default destination for each component of the stream as specified in RFC5245 section 9.1.2.2. */
-                               if (((candidate->taddr.port == rtp_port) && (strlen(candidate->taddr.ip) == strlen(rtp_addr)) && (strcmp(candidate->taddr.ip, rtp_addr) == 0))
-                                       || ((candidate->taddr.port == rtcp_port) && (strlen(candidate->taddr.ip) == strlen(rtcp_addr)) && (strcmp(candidate->taddr.ip, rtcp_addr) == 0))) {
-                                       add_candidate_attribute(msg, lineno, candidate);
-                               }
-                               break;
-                       default:
-                               break;
+               if (candidate->raddr[0] != '\0') {
+                       nb = snprintf(buffer + nb, sizeof(buffer) - nb, " raddr %s rport %d", candidate->raddr, candidate->rport);
+                       if (nb < 0) {
+                               ms_error("Cannot add ICE candidate attribute!");
+                               return;
+                       }
                }
+               sdp_message_a_attribute_add(msg, lineno, osip_strdup("candidate"), osip_strdup(buffer));
        }
 }
 
-static void add_ice_remote_candidates(sdp_message_t *msg, int lineno, const IceCheckList *ice_cl)
+static void add_ice_remote_candidates(sdp_message_t *msg, int lineno, const SalStreamDescription *desc)
 {
        char buffer[1024];
-       const char *rtp_addr = NULL;
-       const char *rtcp_addr = NULL;
-       int rtp_port;
-       int rtcp_port;
-       int nb;
+       char *ptr = buffer;
+       const SalIceRemoteCandidate *candidate;
+       int offset = 0;
+       int i;
 
-       if ((ice_session_role(ice_cl->session) == IR_Controlling) && (ice_check_list_state(ice_cl) == ICL_Completed)) {
-               ice_check_list_nominated_valid_remote_candidate(ice_cl, &rtp_addr, &rtp_port, &rtcp_addr, &rtcp_port);
-               nb = snprintf(buffer, sizeof(buffer), "1 %s %d", rtp_addr, rtp_port);
-               if (nb < 0) {
-                       ms_error("Cannot add ICE remote-candidates attribute!");
-                       return;
-               }
-               if (rtcp_addr != NULL) {
-                       nb = snprintf(buffer + nb, sizeof(buffer) - nb, " 2 %s %d", rtcp_addr, rtcp_port);
-                       if (nb < 0) {
+       buffer[0] = '\0';
+       for (i = 0; i < SAL_MEDIA_DESCRIPTION_MAX_ICE_REMOTE_CANDIDATES; i++) {
+               candidate = &desc->ice_remote_candidates[i];
+               if ((candidate->addr[0] != '\0') && (candidate->port != 0)) {
+                       offset = snprintf(ptr, buffer + sizeof(buffer) - ptr, "%s%d %s %d", (i > 0) ? " " : "", i + 1, candidate->addr, candidate->port);
+                       if (offset < 0) {
                                ms_error("Cannot add ICE remote-candidates attribute!");
                                return;
                        }
+                       ptr += offset;
                }
-               sdp_message_a_attribute_add(msg, lineno, osip_strdup("remote-candidates"), osip_strdup(buffer));
        }
+       if (buffer[0] != '\0') sdp_message_a_attribute_add(msg, lineno, osip_strdup("remote-candidates"), osip_strdup(buffer));
 }
 
-static void add_line(sdp_message_t *msg, int lineno, const SalStreamDescription *desc, const IceCheckList *ice_cl){
+static void add_line(sdp_message_t *msg, int lineno, const SalStreamDescription *desc){
        const char *mt=NULL;
        const MSList *elem;
        const char *rtp_addr;
@@ -309,6 +261,7 @@ static void add_line(sdp_message_t *msg, int lineno, const SalStreamDescription
        int rtp_port;
        int rtcp_port;
        bool_t strip_well_known_rtpmaps;
+       bool_t different_rtp_and_rtcp_addr;
        
        switch (desc->type) {
        case SalAudio:
@@ -321,16 +274,11 @@ static void add_line(sdp_message_t *msg, int lineno, const SalStreamDescription
                mt=desc->typeother;
                break;
        }
-       rtp_addr=rtcp_addr=desc->rtp_addr;
+       rtp_addr=desc->rtp_addr;
+       rtcp_addr=desc->rtcp_addr;
        rtp_port=desc->rtp_port;
        rtcp_port=desc->rtcp_port;
-       if (ice_cl != NULL) {
-               if (ice_check_list_state(ice_cl) == ICL_Completed) {
-                       ice_check_list_nominated_valid_local_candidate(ice_cl, &rtp_addr, &rtp_port, &rtcp_addr, &rtcp_port);
-               } else {
-                       ice_check_list_default_local_candidate(ice_cl, &rtp_addr, &rtp_port, &rtcp_addr, &rtcp_port);
-               }
-       } else if (desc->candidates[0].addr[0]!='\0'){
+       if (desc->candidates[0].addr[0]!='\0'){
                rtp_addr=desc->candidates[0].addr;
                rtp_port=desc->candidates[0].port;
        }
@@ -417,28 +365,34 @@ static void add_line(sdp_message_t *msg, int lineno, const SalStreamDescription
                        break;
        }
        if (dir) sdp_message_a_attribute_add (msg, lineno, osip_strdup (dir),NULL);
-       if (ice_cl != NULL) {
-               if (strcmp(rtp_addr, rtcp_addr) != 0) {
-                       char buffer[1024];
-                       snprintf(buffer, sizeof(buffer), "%u IN IP4 %s", rtcp_port, rtcp_addr);
-                       sdp_message_a_attribute_add(msg, lineno, osip_strdup("rtcp"), osip_strdup(buffer));
-               } else {
-                       sdp_message_a_attribute_add(msg, lineno, osip_strdup("rtcp"), int_2char(rtcp_port));
+       if (rtp_port != 0) {
+               different_rtp_and_rtcp_addr = (rtcp_addr[0] != '\0') && (strcmp(rtp_addr, rtcp_addr) != 0);
+               if ((rtcp_port != (rtp_port + 1)) || (different_rtp_and_rtcp_addr == TRUE)) {
+                       if (different_rtp_and_rtcp_addr == TRUE) {
+                               char buffer[1024];
+                               snprintf(buffer, sizeof(buffer), "%u IN IP4 %s", rtcp_port, rtcp_addr);
+                               sdp_message_a_attribute_add(msg, lineno, osip_strdup("rtcp"), osip_strdup(buffer));
+                       } else {
+                               sdp_message_a_attribute_add(msg, lineno, osip_strdup("rtcp"), int_2char(rtcp_port));
+                       }
                }
-               add_ice_candidates(msg, lineno, ice_cl, rtp_addr, rtp_port, rtcp_addr, rtcp_port);
-               add_ice_remote_candidates(msg, lineno, ice_cl);
+       }
+       if (desc->ice_mismatch == TRUE) {
+               sdp_message_a_attribute_add(msg, lineno, osip_strdup("ice-mismatch"), NULL);
+       } else {
+               if (desc->ice_pwd[0] != '\0') sdp_message_a_attribute_add(msg, lineno, osip_strdup("ice-pwd"), osip_strdup(desc->ice_pwd));
+               if (desc->ice_ufrag[0] != '\0') sdp_message_a_attribute_add(msg, lineno, osip_strdup("ice-ufrag"), osip_strdup(desc->ice_ufrag));
+               add_ice_candidates(msg, lineno, desc);
+               add_ice_remote_candidates(msg, lineno, desc);
        }
 }
 
 
-sdp_message_t *media_description_to_sdp(const SalMediaDescription *desc, const IceSession *ice_session){
-       IceCheckList *ice_cl = NULL;
+sdp_message_t *media_description_to_sdp(const SalMediaDescription *desc){
        int i;
-       sdp_message_t *msg=create_generic_sdp(desc, ice_session);
+       sdp_message_t *msg=create_generic_sdp(desc);
        for(i=0;i<desc->nstreams;++i){
-               if (ice_session != NULL) ice_cl = ice_session_check_list(ice_session, i);
-               else ice_cl = NULL;
-               add_line(msg,i,&desc->streams[i], ice_cl);
+               add_line(msg,i,&desc->streams[i]);
        }
        return msg;
 }
@@ -474,15 +428,12 @@ static int payload_type_fill_from_rtpmap(PayloadType *pt, const char *rtpmap){
        return 0;
 }
 
-int sdp_to_media_description(sdp_message_t *msg, SalMediaDescription *desc, IceSession **ice_session){
+int sdp_to_media_description(sdp_message_t *msg, SalMediaDescription *desc){
        int i,j;
        const char *mtype,*proto,*rtp_port,*rtp_addr,*number;
-       const char *ice_ufrag, *ice_pwd, *ice_remote_candidates=NULL;
        sdp_bandwidth_t *sbw=NULL;
        sdp_attribute_t *attr;
-       int media_attribute_nb;
-       bool_t ice_session_just_created = FALSE;
-       bool_t ice_lite = FALSE;
+       int nb_ice_candidates;
 
        rtp_addr=sdp_message_c_addr_get (msg, -1, 0);
        if (rtp_addr)
@@ -491,10 +442,22 @@ int sdp_to_media_description(sdp_message_t *msg, SalMediaDescription *desc, IceS
                if (strcasecmp(sbw->b_bwtype,"AS")==0) desc->bandwidth=atoi(sbw->b_bandwidth);
        }
 
+       /* Get ICE remote ufrag and remote pwd, and ice_lite flag */
+       for (i = 0; (i < SAL_MEDIA_DESCRIPTION_MAX_MESSAGE_ATTRIBUTES) && ((attr = sdp_message_attribute_get(msg, -1, i)) != NULL); i++) {
+               if ((keywordcmp("ice-ufrag", attr->a_att_field) == 0) && (attr->a_att_value != NULL)) {
+                       strncpy(desc->ice_ufrag, attr->a_att_value, sizeof(desc->ice_ufrag));
+               } else if ((keywordcmp("ice-pwd", attr->a_att_field) == 0) && (attr->a_att_value != NULL)) {
+                       strncpy(desc->ice_pwd, attr->a_att_value, sizeof(desc->ice_pwd));
+               } else if (keywordcmp("ice-lite", attr->a_att_field) == 0) {
+                       desc->ice_lite = TRUE;
+               }
+       }
+
        /* for each m= line */
        for (i=0; !sdp_message_endof_media (msg, i) && i<SAL_MEDIA_DESCRIPTION_MAX_STREAMS; i++)
        {
                SalStreamDescription *stream=&desc->streams[i];
+               nb_ice_candidates = 0;
                
                memset(stream,0,sizeof(*stream));
                mtype = sdp_message_m_media_get(msg, i);
@@ -527,7 +490,6 @@ int sdp_to_media_description(sdp_message_t *msg, SalMediaDescription *desc, IceS
                        if (strcasecmp(sbw->b_bwtype,"AS")==0) stream->bandwidth=atoi(sbw->b_bandwidth);
                }
                stream->dir=_sdp_message_get_mline_dir(msg,i);
-               media_attribute_nb = 0;
                /* for each payload type */
                for (j=0;((number=sdp_message_m_payload_get (msg, i,j)) != NULL); j++){
                        const char *rtpmap,*fmtp;
@@ -536,11 +498,9 @@ int sdp_to_media_description(sdp_message_t *msg, SalMediaDescription *desc, IceS
                        payload_type_set_number(pt,ptn);
                        /* get the rtpmap associated to this codec, if any */
                        rtpmap=sdp_message_a_attr_value_get_with_pt(msg, i,ptn,"rtpmap");
-                       if (rtpmap != NULL) media_attribute_nb++;
                        if (payload_type_fill_from_rtpmap(pt,rtpmap)==0){
                                /* get the fmtp, if any */
                                fmtp=sdp_message_a_attr_value_get_with_pt(msg, i, ptn,"fmtp");
-                               if (fmtp != NULL) media_attribute_nb++;
                                payload_type_set_send_fmtp(pt,fmtp);
                                stream->payloads=ms_list_append(stream->payloads,pt);
                                ms_message("Found payload %s/%i fmtp=%s",pt->mime_type,pt->clock_rate,
@@ -608,121 +568,37 @@ int sdp_to_media_description(sdp_message_t *msg, SalMediaDescription *desc, IceS
                }
 
                /* Get ICE candidate attributes if any */
-               ice_ufrag = ice_pwd = NULL;
-               for (j = 0; (j < SAL_MEDIA_DESCRIPTION_MAX_ICE_CANDIDATES) && ((attr = sdp_message_attribute_get(msg, i, media_attribute_nb + j)) != NULL); j++) {
+               for (j = 0; (attr = sdp_message_attribute_get(msg, i, j)) != NULL; j++) {
                        if ((keywordcmp("candidate", attr->a_att_field) == 0) && (attr->a_att_value != NULL)) {
-                               char ip[64];
-                               char foundation[32];
-                               char type[6];
-                               unsigned int priority;
+                               SalIceCandidate *candidate = &stream->ice_candidates[nb_ice_candidates];
+                               int nb = sscanf(attr->a_att_value, "%s %u UDP %u %s %d typ %s raddr %s rport %d",
+                                       candidate->foundation, &candidate->componentID, &candidate->priority, candidate->addr, &candidate->port,
+                                       candidate->type, candidate->raddr, &candidate->rport);
+                               if ((nb == 6) || (nb == 8)) nb_ice_candidates++;
+                               else memset(candidate, 0, sizeof(*candidate));
+                       } else if ((keywordcmp("remote-candidates", attr->a_att_field) == 0) && (attr->a_att_value != NULL)) {
+                               SalIceRemoteCandidate candidate;
                                unsigned int componentID;
-                               unsigned int port;
-                               int nb;
-
-                               /* Allocate the ICE session if it has not been done yet. */
-                               if (*ice_session == NULL) {
-                                       *ice_session = ice_session_new();
-                                       ice_session_just_created = TRUE;
-                               }
-                               /* Allocate the ICE check list if it has not been done yet. */
-                               if (ice_session_check_list(*ice_session, i) == NULL) {
-                                       ice_session_add_check_list(*ice_session, ice_check_list_new());
-                               }
-                               nb = sscanf(attr->a_att_value, "%s %u UDP %u %s %u typ %s",
-                                       foundation, &componentID, &priority, ip, &port, type);
-                               if (nb == 6) {
-                                       char *default_ip = desc->addr;
-                                       unsigned int default_port = stream->rtp_port;
-                                       bool_t is_default_candidate = FALSE;
-                                       if (componentID == 1) {
-                                               if ((stream->rtp_addr == NULL) || (stream->rtp_addr[0] == '\0')) default_ip = desc->addr;
-                                               else default_ip = stream->rtp_addr;
-                                               default_port = stream->rtp_port;
-                                       } else if (componentID == 2) {
-                                               if ((stream->rtcp_addr == NULL) || (stream->rtcp_addr[0] == '\0')) default_ip = desc->addr;
-                                               else default_ip = stream->rtcp_addr;
-                                               default_port = stream->rtcp_port;
+                               int offset;
+                               char *ptr = attr->a_att_value;
+                               while (3 == sscanf(ptr, "%u %s %u%n", &componentID, candidate.addr, &candidate.port, &offset)) {
+                                       if ((componentID > 0) && (componentID <= SAL_MEDIA_DESCRIPTION_MAX_ICE_REMOTE_CANDIDATES)) {
+                                               SalIceRemoteCandidate *remote_candidate = &stream->ice_remote_candidates[componentID - 1];
+                                               strncpy(remote_candidate->addr, candidate.addr, sizeof(remote_candidate->addr));
+                                               remote_candidate->port = candidate.port;
                                        }
-                                       if ((port == default_port) && (strlen(ip) == strlen(default_ip)) && (strcmp(ip, default_ip) == 0)) is_default_candidate = TRUE;
-                                       ice_add_remote_candidate(ice_session_check_list(*ice_session, i), type, ip, port, componentID, priority, foundation, is_default_candidate);
+                                       ptr += offset;
+                                       if (ptr[offset] == ' ') ptr += 1;
                                }
-                       } else if ((keywordcmp("remote-candidates", attr->a_att_field) == 0) && (attr->a_att_value != NULL)) {
-                               ice_remote_candidates = attr->a_att_value;
                        } else if ((keywordcmp("ice-ufrag", attr->a_att_field) == 0) && (attr->a_att_value != NULL)) {
-                               ice_ufrag = attr->a_att_value;
+                               strncpy(stream->ice_ufrag, attr->a_att_value, sizeof(stream->ice_ufrag));
                        } else if ((keywordcmp("ice-pwd", attr->a_att_field) == 0) && (attr->a_att_value != NULL)) {
-                               ice_pwd = attr->a_att_value;
+                               strncpy(stream->ice_pwd, attr->a_att_value, sizeof(stream->ice_pwd));
                        } else if (keywordcmp("ice-mismatch", attr->a_att_field) == 0) {
-                               ice_check_list_set_state(ice_session_check_list(*ice_session, i), ICL_Failed);
+                               stream->ice_mismatch = TRUE;
                        }
                }
-               if ((*ice_session != NULL) && ice_session_check_list(*ice_session, i)) {
-                       if (ice_remote_candidates != NULL) {
-                               char ip[64];
-                               unsigned int port;
-                               unsigned int componentID;
-                               int offset;
-
-                               while (3 == sscanf(ice_remote_candidates, "%u %s %u%n", &componentID, ip, &port, &offset)) {
-                                       if (componentID == 1) {
-                                               if ((stream->rtp_addr == NULL) || (stream->rtp_addr[0] == '\0')) rtp_addr = desc->addr;
-                                               else rtp_addr = stream->rtp_addr;
-                                               ice_add_losing_pair(ice_session_check_list(*ice_session, i), componentID, ip, port, rtp_addr, stream->rtp_port);
-                                       } else if (componentID == 2) {
-                                               if ((stream->rtcp_addr == NULL) || (stream->rtcp_addr[0] == '\0')) rtp_addr = desc->addr;
-                                               else rtp_addr = stream->rtcp_addr;
-                                               ice_add_losing_pair(ice_session_check_list(*ice_session, i), componentID, ip, port, rtp_addr, stream->rtcp_port);
-                                       }
-                                       ice_remote_candidates += offset;
-                                       if (ice_remote_candidates[offset] == ' ') ice_remote_candidates += 1;
-                               }
-                       }
-                       if ((ice_ufrag != NULL) && (ice_pwd != NULL)) {
-                               ice_check_list_set_remote_credentials(ice_session_check_list(*ice_session, i), ice_ufrag, ice_pwd);
-                       }
-                       if (stream->rtp_port == 0) {
-                               /* This stream has been deactivated by the peer, delete the check list. */
-                               ice_session_remove_check_list(*ice_session, ice_session_check_list(*ice_session, i));
-                       }
-                       ice_dump_candidates(ice_session_check_list(*ice_session, i));
-               }
        }
        desc->nstreams=i;
-
-       /* Get ICE remote ufrag and remote pwd */
-       ice_ufrag = ice_pwd = NULL;
-       for (i = 0; (i < SAL_MEDIA_DESCRIPTION_MAX_MESSAGE_ATTRIBUTES) && ((attr = sdp_message_attribute_get(msg, -1, i)) != NULL); i++) {
-               if ((keywordcmp("ice-ufrag", attr->a_att_field) == 0) && (attr->a_att_value != NULL)) {
-                       ice_ufrag = attr->a_att_value;
-               } else if ((keywordcmp("ice-pwd", attr->a_att_field) == 0) && (attr->a_att_value != NULL)) {
-                       ice_pwd = attr->a_att_value;
-               } else if (keywordcmp("ice-lite", attr->a_att_field) == 0) {
-                       ice_lite = TRUE;
-               }
-       }
-       if (*ice_session != NULL) {
-               int nb_check_lists;
-               if (ice_session_just_created == TRUE) {
-                       if (ice_lite == TRUE) {
-                               ice_session_set_role(*ice_session, IR_Controlling);
-                       } else {
-                               ice_session_set_role(*ice_session, IR_Controlled);
-                       }
-                       ice_session_check_mismatch(*ice_session);
-               }
-               while ((nb_check_lists = ice_session_nb_check_lists(*ice_session)) > desc->nstreams) {
-                       ice_session_remove_check_list(*ice_session, ice_session_check_list(*ice_session, nb_check_lists - 1));
-               }
-               if ((ice_ufrag != NULL) && (ice_pwd != NULL)) {
-                       ice_session_set_remote_credentials(*ice_session, ice_ufrag, ice_pwd);
-                       ice_dump_session(*ice_session);
-               }
-               if (((ice_session_just_created == FALSE) && ((ice_ufrag == NULL) || (ice_pwd == NULL)))
-                       || (ice_session_state(*ice_session) == IS_Failed)) {
-                       /* We started with ICE activated but the peer apparently do not support ICE, so stop using it. */
-                       ice_session_destroy(*ice_session);
-                       *ice_session = NULL;
-               }
-       }
        return 0;
 }