]> sjero.net Git - linphone/commitdiff
Keep the total number of streams and the number of active streams in the media descri...
authorGhislain MARY <ghislain.mary@belledonne-communications.com>
Tue, 22 Jan 2013 10:39:05 +0000 (11:39 +0100)
committerGhislain MARY <ghislain.mary@belledonne-communications.com>
Wed, 23 Jan 2013 11:25:08 +0000 (12:25 +0100)
This is to respect section 8 of RFC 3264 ("Modifying the Session"). The
number of streams in the SDP MUST NOT decrease.

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

index 7985f36588295d2f4d5ea4cd8e974f60a2899f3c..784c1f1bdc838b300f6eb3d505620a0014cda5f1 100644 (file)
@@ -41,14 +41,14 @@ void linphone_core_update_streams_destinations(LinphoneCore *lc, LinphoneCall *c
        char *rtp_addr, *rtcp_addr;
        int i;
 
-       for (i = 0; i < old_md->nstreams; i++) {
+       for (i = 0; i < old_md->n_active_streams; i++) {
                if (old_md->streams[i].type == SalAudio) {
                        old_audiodesc = &old_md->streams[i];
                } else if (old_md->streams[i].type == SalVideo) {
                        old_videodesc = &old_md->streams[i];
                }
        }
-       for (i = 0; i < new_md->nstreams; i++) {
+       for (i = 0; i < new_md->n_active_streams; i++) {
                if (new_md->streams[i].type == SalAudio) {
                        new_audiodesc = &new_md->streams[i];
                } else if (new_md->streams[i].type == SalVideo) {
@@ -591,7 +591,7 @@ static void call_failure(SalOp *op, SalError error, SalReason sr, const char *de
                                        if (call->state==LinphoneCallOutgoingInit || call->state==LinphoneCallOutgoingProgress){
                                                /* clear SRTP local params */
                                                call->params.media_encryption = LinphoneMediaEncryptionNone;
-                                               for(i=0; i<call->localdesc->nstreams; i++) {
+                                               for(i=0; i<call->localdesc->n_active_streams; i++) {
                                                        call->localdesc->streams[i].proto = SalProtoRtpAvp;
                                                        memset(call->localdesc->streams[i].crypto, 0, sizeof(call->localdesc->streams[i].crypto));
                                                }
index 6ef8e0c553a4a188f4096827238b9d4279ca5f30..d918057e9981b55ba8e56d58f1a4b80a98230a2e 100644 (file)
@@ -173,9 +173,10 @@ void linphone_call_set_authentication_token_verified(LinphoneCall *call, bool_t
        propagate_encryption_changed(call);
 }
 
-static MSList *make_codec_list(LinphoneCore *lc, const MSList *codecs, int bandwidth_limit,int* max_sample_rate){
+static MSList *make_codec_list(LinphoneCore *lc, const MSList *codecs, int bandwidth_limit,int* max_sample_rate, int nb_codecs_limit){
        MSList *l=NULL;
        const MSList *it;
+       int nb = 0;
        if (max_sample_rate) *max_sample_rate=0;
        for(it=codecs;it!=NULL;it=it->next){
                PayloadType *pt=(PayloadType*)it->data;
@@ -186,26 +187,30 @@ static MSList *make_codec_list(LinphoneCore *lc, const MSList *codecs, int bandw
                        }
                        if (linphone_core_check_payload_type_usability(lc,pt)){
                                l=ms_list_append(l,payload_type_clone(pt));
+                               nb++;
                                if (max_sample_rate && payload_type_get_rate(pt)>*max_sample_rate) *max_sample_rate=payload_type_get_rate(pt);
                        }
                }
+               if ((nb_codecs_limit > 0) && (nb >= nb_codecs_limit)) break;
        }
        return l;
 }
 
 static void update_media_description_from_stun(SalMediaDescription *md, const StunCandidate *ac, const StunCandidate *vc){
-       if (ac->port!=0){
-               strcpy(md->streams[0].rtp_addr,ac->addr);
-               md->streams[0].rtp_port=ac->port;
-               if ((ac->addr[0]!='\0' && vc->addr[0]!='\0' && strcmp(ac->addr,vc->addr)==0) || md->nstreams==1){
-                       strcpy(md->addr,ac->addr);
+       int i;
+       for (i = 0; i < md->n_active_streams; i++) {
+               if ((md->streams[i].type == SalAudio) && (ac->port != 0)) {
+                       strcpy(md->streams[0].rtp_addr,ac->addr);
+                       md->streams[0].rtp_port=ac->port;
+                       if ((ac->addr[0]!='\0' && vc->addr[0]!='\0' && strcmp(ac->addr,vc->addr)==0) || md->n_active_streams==1){
+                               strcpy(md->addr,ac->addr);
+                       }
+               }
+               if ((md->streams[i].type == SalVideo) && (vc->port != 0)) {
+                       strcpy(md->streams[1].rtp_addr,vc->addr);
+                       md->streams[1].rtp_port=vc->port;
                }
        }
-       if (vc->port!=0){
-               strcpy(md->streams[1].rtp_addr,vc->addr);
-               md->streams[1].rtp_port=vc->port;
-       }
-       
 }
 
 void linphone_call_make_local_media_description(LinphoneCore *lc, LinphoneCall *call){
@@ -218,12 +223,13 @@ void linphone_call_make_local_media_description(LinphoneCore *lc, LinphoneCall *
        const char *username=linphone_address_get_username (addr);
        SalMediaDescription *md=sal_media_description_new();
        bool_t keep_srtp_keys=lp_config_get_int(lc->config,"sip","keep_srtp_keys",0);
-       
+
        linphone_core_adapt_to_network(lc,call->ping_time,&call->params);
 
        md->session_id=(old_md ? old_md->session_id : (rand() & 0xfff));
        md->session_ver=(old_md ? (old_md->session_ver+1) : (rand() & 0xfff));
-       md->nstreams=1;
+       md->n_total_streams=(old_md ? old_md->n_total_streams : 1);
+       md->n_active_streams=1;
        strncpy(md->addr,call->localip,sizeof(md->addr));
        strncpy(md->username,username,sizeof(md->username));
        
@@ -243,22 +249,35 @@ void linphone_call_make_local_media_description(LinphoneCore *lc, LinphoneCall *
                md->streams[0].ptime=call->params.down_ptime;
        else
                md->streams[0].ptime=linphone_core_get_download_ptime(lc);
-       l=make_codec_list(lc,lc->codecs_conf.audio_codecs,call->params.audio_bw,&md->streams[0].max_rate);
+       l=make_codec_list(lc,lc->codecs_conf.audio_codecs,call->params.audio_bw,&md->streams[0].max_rate,-1);
        pt=payload_type_clone(rtp_profile_get_payload_from_mime(lc->default_profile,"telephone-event"));
        l=ms_list_append(l,pt);
        md->streams[0].payloads=l;
 
        if (call->params.has_video){
-               md->nstreams++;
+               md->n_active_streams++;
                md->streams[1].rtp_port=call->video_port;
                md->streams[1].rtcp_port=call->video_port+1;
                md->streams[1].proto=md->streams[0].proto;
                md->streams[1].type=SalVideo;
-               l=make_codec_list(lc,lc->codecs_conf.video_codecs,0,NULL);
+               l=make_codec_list(lc,lc->codecs_conf.video_codecs,0,NULL,-1);
                md->streams[1].payloads=l;
        }
-       
-       for(i=0; i<md->nstreams; i++) {
+       if (md->n_total_streams < md->n_active_streams)
+               md->n_total_streams = md->n_active_streams;
+
+       /* Deactivate inactive streams. */
+       for (i = md->n_active_streams; i < md->n_total_streams; i++) {
+               md->streams[i].rtp_port = 0;
+               md->streams[i].rtcp_port = 0;
+               md->streams[i].proto = SalProtoRtpAvp;
+               md->streams[i].type = old_md->streams[i].type;
+               md->streams[i].dir = SalStreamInactive;
+               l = make_codec_list(lc, lc->codecs_conf.video_codecs, 0, NULL, 1);
+               md->streams[i].payloads = l;
+       }
+
+       for(i=0; i<md->n_active_streams; i++) {
                if (md->streams[i].proto == SalProtoRtpSavp) {
                        if (keep_srtp_keys && old_md && old_md->streams[i].proto==SalProtoRtpSavp){
                                int j;
index 1ed5ef62f82631ae476f4ae977c120b8a6b27e34..20788eb1646218337663901d24765786e74a85fd 100644 (file)
@@ -2576,7 +2576,7 @@ bool_t linphone_core_inc_invite_pending(LinphoneCore*lc){
 bool_t linphone_core_incompatible_security(LinphoneCore *lc, SalMediaDescription *md){
        if (linphone_core_is_media_encryption_mandatory(lc) && linphone_core_get_media_encryption(lc)==LinphoneMediaEncryptionSRTP){
                int i;
-               for(i=0;i<md->nstreams;i++){
+               for(i=0;i<md->n_active_streams;i++){
                        SalStreamDescription *sd=&md->streams[i];
                        if (sd->proto!=SalProtoRtpSavp){
                                return TRUE;
index 53f0d65cfb6d8115b31ed6f54b1a06e71cf9dabb..b8041c433d77ae4a04483d554a8a8d1c6636a683 100644 (file)
@@ -734,7 +734,7 @@ void linphone_core_update_local_media_description_from_ice(SalMediaDescription *
        }
        strncpy(desc->ice_pwd, ice_session_local_pwd(session), sizeof(desc->ice_pwd));
        strncpy(desc->ice_ufrag, ice_session_local_ufrag(session), sizeof(desc->ice_ufrag));
-       for (i = 0; i < desc->nstreams; i++) {
+       for (i = 0; i < desc->n_active_streams; i++) {
                SalStreamDescription *stream = &desc->streams[i];
                IceCheckList *cl = ice_session_check_list(session, i);
                nb_candidates = 0;
@@ -838,7 +838,7 @@ void linphone_core_update_ice_from_remote_media_description(LinphoneCall *call,
                        ice_session_restart(call->ice_session);
                        ice_restarted = TRUE;
                } else {
-                       for (i = 0; i < md->nstreams; i++) {
+                       for (i = 0; i < md->n_total_streams; i++) {
                                const SalStreamDescription *stream = &md->streams[i];
                                IceCheckList *cl = ice_session_check_list(call->ice_session, i);
                                if (cl && (strcmp(stream->rtp_addr, "0.0.0.0") == 0)) {
@@ -857,7 +857,7 @@ void linphone_core_update_ice_from_remote_media_description(LinphoneCall *call,
                        }
                        ice_session_set_remote_credentials(call->ice_session, md->ice_ufrag, md->ice_pwd);
                }
-               for (i = 0; i < md->nstreams; i++) {
+               for (i = 0; i < md->n_total_streams; i++) {
                        const SalStreamDescription *stream = &md->streams[i];
                        IceCheckList *cl = ice_session_check_list(call->ice_session, i);
                        if (cl && (stream->ice_pwd[0] != '\0') && (stream->ice_ufrag[0] != '\0')) {
@@ -873,7 +873,7 @@ void linphone_core_update_ice_from_remote_media_description(LinphoneCall *call,
                }
 
                /* Create ICE check lists if needed and parse ICE attributes. */
-               for (i = 0; i < md->nstreams; i++) {
+               for (i = 0; i < md->n_total_streams; i++) {
                        const SalStreamDescription *stream = &md->streams[i];
                        IceCheckList *cl = ice_session_check_list(call->ice_session, i);
                        if (cl == NULL) {
@@ -930,7 +930,7 @@ void linphone_core_update_ice_from_remote_media_description(LinphoneCall *call,
                                }
                        }
                }
-               for (i = ice_session_nb_check_lists(call->ice_session); i > md->nstreams; i--) {
+               for (i = ice_session_nb_check_lists(call->ice_session); i > md->n_active_streams; i--) {
                        ice_session_remove_check_list(call->ice_session, ice_session_check_list(call->ice_session, i - 1));
                }
                ice_session_check_mismatch(call->ice_session);
@@ -948,8 +948,8 @@ bool_t linphone_core_media_description_contains_video_stream(const SalMediaDescr
 {
        int i;
 
-       for (i = 0; i < md->nstreams; i++) {
-               if ((md->streams[i].type == SalVideo) && (md->streams[i].rtp_port != 0))
+       for (i = 0; i < md->n_active_streams; i++) {
+               if (md->streams[i].type == SalVideo)
                        return TRUE;
        }
        return FALSE;
index 541a1eee3623b252b47d6a5438553d72e83226f1..ab38f76366997f3665fd59dbc4fdb2c90208529e 100644 (file)
@@ -19,6 +19,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
 #include "sal.h"
 #include "offeranswer.h"
+#include "private.h"
 
 static bool_t only_telephone_event(const MSList *l){
        for(;l!=NULL;l=l->next){
@@ -267,22 +268,23 @@ static void initiate_incoming(const SalStreamDescription *local_cap,
  * and the returned response (remote).
 **/
 int offer_answer_initiate_outgoing(const SalMediaDescription *local_offer,
-                                                                       const SalMediaDescription *remote_answer,
-                                                       SalMediaDescription *result){
-       int i,j;
-    
+                                       const SalMediaDescription *remote_answer,
+                                       SalMediaDescription *result){
+       int i,j;
+
        const SalStreamDescription *ls,*rs;
-       for(i=0,j=0;i<local_offer->nstreams;++i){
+       for(i=0,j=0;i<local_offer->n_total_streams;++i){
                ms_message("Processing for stream %i",i);
                ls=&local_offer->streams[i];
                rs=sal_media_description_find_stream((SalMediaDescription*)remote_answer,ls->proto,ls->type);
-       if (rs) {
+               if (rs) {
                        initiate_outgoing(ls,rs,&result->streams[j]);
                        ++j;
                }
                else ms_warning("No matching stream for %i",i);
        }
-       result->nstreams=j;
+       result->n_active_streams=j;
+       result->n_total_streams=local_offer->n_total_streams;
        result->bandwidth=remote_answer->bandwidth;
        strcpy(result->addr,remote_answer->addr);
        return 0;
@@ -294,12 +296,13 @@ int offer_answer_initiate_outgoing(const SalMediaDescription *local_offer,
  * The returned media description is an answer and should be sent to the offerer.
 **/
 int offer_answer_initiate_incoming(const SalMediaDescription *local_capabilities,
-                                               const SalMediaDescription *remote_offer,
-                                       SalMediaDescription *result, bool_t one_matching_codec){
+                                       const SalMediaDescription *remote_offer,
+                                       SalMediaDescription *result, bool_t one_matching_codec){
        int i;
        const SalStreamDescription *ls=NULL,*rs;
-                                                       
-       for(i=0;i<remote_offer->nstreams;++i){
+
+       result->n_active_streams=0;
+       for(i=0;i<remote_offer->n_total_streams;++i){
                rs=&remote_offer->streams[i];
                if (rs->proto!=SalProtoUnknown){
                        ls=sal_media_description_find_stream((SalMediaDescription*)local_capabilities,rs->proto,rs->type);
@@ -310,6 +313,7 @@ int offer_answer_initiate_incoming(const SalMediaDescription *local_capabilities
                }else ms_warning("Unknown protocol for mline %i, declining",i);
                if (ls){
                        initiate_incoming(ls,rs,&result->streams[i],one_matching_codec);
+                       result->n_active_streams++;
                }
                else {
                        /* create an inactive stream for the answer, as there where no matching stream a local capability */
@@ -322,7 +326,7 @@ int offer_answer_initiate_incoming(const SalMediaDescription *local_capabilities
                        }
                }
        }
-       result->nstreams=i;
+       result->n_total_streams=i;
        strcpy(result->username, local_capabilities->username);
        strcpy(result->addr,local_capabilities->addr);
        result->bandwidth=local_capabilities->bandwidth;
index 2b09212aa02e79f3468aa54d8f6bbcbfaff90484..05d03499d85e327a6dc813bca746757815c193b5 100644 (file)
@@ -76,7 +76,7 @@ void sal_media_description_unref(SalMediaDescription *md){
 SalStreamDescription *sal_media_description_find_stream(SalMediaDescription *md,
     SalMediaProto proto, SalStreamType type){
        int i;
-       for(i=0;i<md->nstreams;++i){
+       for(i=0;i<md->n_active_streams;++i){
                SalStreamDescription *ss=&md->streams[i];
                if (ss->proto==proto && ss->type==type) return ss;
        }
@@ -84,17 +84,13 @@ SalStreamDescription *sal_media_description_find_stream(SalMediaDescription *md,
 }
 
 bool_t sal_media_description_empty(const SalMediaDescription *md){
-       int i;
-       for(i=0;i<md->nstreams;++i){
-               const SalStreamDescription *ss=&md->streams[i];
-               if (ss->rtp_port!=0) return FALSE;
-       }
+       if (md->n_active_streams > 0) return FALSE;
        return TRUE;
 }
 
 void sal_media_description_set_dir(SalMediaDescription *md, SalStreamDir stream_dir){
        int i;
-       for(i=0;i<md->nstreams;++i){
+       for(i=0;i<md->n_active_streams;++i){
                SalStreamDescription *ss=&md->streams[i];
                ss->dir=stream_dir;
        }
@@ -110,7 +106,7 @@ static bool_t has_dir(const SalMediaDescription *md, SalStreamDir stream_dir){
        int i;
 
        /* we are looking for at least one stream with requested direction, inactive streams are ignored*/
-       for(i=0;i<md->nstreams;++i){
+       for(i=0;i<md->n_active_streams;++i){
                const SalStreamDescription *ss=&md->streams[i];
                if (ss->dir==stream_dir) return TRUE;
                /*compatibility check for phones that only used the null address and no attributes */
@@ -224,9 +220,9 @@ int sal_media_description_equals(const SalMediaDescription *md1, const SalMediaD
        int i;
 
        if (strcmp(md1->addr, md2->addr) != 0) result |= SAL_MEDIA_DESCRIPTION_NETWORK_CHANGED;
-       if (md1->nstreams != md2->nstreams) result |= SAL_MEDIA_DESCRIPTION_CODEC_CHANGED;
+       if (md1->n_total_streams != md2->n_total_streams) result |= SAL_MEDIA_DESCRIPTION_CODEC_CHANGED;
        if (md1->bandwidth != md2->bandwidth) result |= SAL_MEDIA_DESCRIPTION_CODEC_CHANGED;
-       for(i = 0; i < md1->nstreams; ++i){
+       for(i = 0; i < md1->n_total_streams; ++i){
                result |= sal_stream_description_equals(&md1->streams[i], &md2->streams[i]);
        }
        return result;
index ba6daa2211ad2b7abd9ee3808f77beb9cbb917fd..6baae97ae8b20fb6941e3245077232fb5bc2b46b 100644 (file)
@@ -178,7 +178,8 @@ typedef struct SalMediaDescription{
        int refcount;
        char addr[64];
        char username[64];
-       int nstreams;
+       int n_active_streams;
+       int n_total_streams;
        int bandwidth;
        unsigned int session_ver;
        unsigned int session_id;
index d8332621d539d1302aa805a43007504ccadbb4ba..1cbecb638c8452677d82e88c39509b072c398401 100644 (file)
@@ -589,18 +589,15 @@ static void sdp_process(SalOp *h){
                strcpy(h->result->addr,h->base.remote_media->addr);
                h->result->bandwidth=h->base.remote_media->bandwidth;
                
-               for(i=0;i<h->result->nstreams;++i){
-                       if (h->result->streams[i].rtp_port>0){
-                               strcpy(h->result->streams[i].rtp_addr,h->base.remote_media->streams[i].rtp_addr);
-                               strcpy(h->result->streams[i].rtcp_addr,h->base.remote_media->streams[i].rtcp_addr);
-                               h->result->streams[i].ptime=h->base.remote_media->streams[i].ptime;
-                               h->result->streams[i].bandwidth=h->base.remote_media->streams[i].bandwidth;
-                               h->result->streams[i].rtp_port=h->base.remote_media->streams[i].rtp_port;
-                               h->result->streams[i].rtcp_port=h->base.remote_media->streams[i].rtcp_port;
-                               
-                               if (h->result->streams[i].proto == SalProtoRtpSavp) {
-                                       h->result->streams[i].crypto[0] = h->base.remote_media->streams[i].crypto[0]; 
-                               }
+               for(i=0;i<h->result->n_active_streams;++i){
+                       strcpy(h->result->streams[i].rtp_addr,h->base.remote_media->streams[i].rtp_addr);
+                       strcpy(h->result->streams[i].rtcp_addr,h->base.remote_media->streams[i].rtcp_addr);
+                       h->result->streams[i].ptime=h->base.remote_media->streams[i].ptime;
+                       h->result->streams[i].bandwidth=h->base.remote_media->streams[i].bandwidth;
+                       h->result->streams[i].rtp_port=h->base.remote_media->streams[i].rtp_port;
+                       h->result->streams[i].rtcp_port=h->base.remote_media->streams[i].rtcp_port;
+                       if (h->result->streams[i].proto == SalProtoRtpSavp) {
+                               h->result->streams[i].crypto[0] = h->base.remote_media->streams[i].crypto[0];
                        }
                }
        }
index 4aad1486388839b9b8c9c6210981291d0501f6e1..9297077e66dafc25cefa4826fe94c7aaa02c23be 100644 (file)
@@ -394,7 +394,7 @@ static void add_line(sdp_message_t *msg, int lineno, const SalStreamDescription
 sdp_message_t *media_description_to_sdp(const SalMediaDescription *desc){
        int i;
        sdp_message_t *msg=create_generic_sdp(desc);
-       for(i=0;i<desc->nstreams;++i){
+       for(i=0;i<desc->n_total_streams;++i){
                add_line(msg,i,&desc->streams[i]);
        }
        return msg;
@@ -463,6 +463,8 @@ int sdp_to_media_description(sdp_message_t *msg, SalMediaDescription *desc){
                }
        }
 
+       desc->n_active_streams = 0;
+
        /* for each m= line */
        for (i=0; !sdp_message_endof_media (msg, i) && i<SAL_MEDIA_DESCRIPTION_MAX_STREAMS; i++)
        {
@@ -486,6 +488,8 @@ int sdp_to_media_description(sdp_message_t *msg, SalMediaDescription *desc){
                        strncpy(stream->rtp_addr,rtp_addr,sizeof(stream->rtp_addr));
                if (rtp_port)
                        stream->rtp_port=atoi(rtp_port);
+               if (stream->rtp_port > 0)
+                       desc->n_active_streams++;
                
                stream->ptime=_sdp_message_get_a_ptime(msg,i);
                if (strcasecmp("audio", mtype) == 0){
@@ -609,6 +613,6 @@ int sdp_to_media_description(sdp_message_t *msg, SalMediaDescription *desc){
                        }
                }
        }
-       desc->nstreams=i;
+       desc->n_total_streams=i;
        return 0;
 }