]> sjero.net Git - linphone/blobdiff - coreapi/linphonecall.c
Merge branch 'upnp'
[linphone] / coreapi / linphonecall.c
index eece911b49f5788314640d6bdbe64e5885fd074c..11be247c237bd5a5bf7f8576e8f6b1616e80d239 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;
@@ -1699,18 +1718,20 @@ void linphone_call_update_crypto_parameters(LinphoneCall *call, SalMediaDescript
        new_stream = sal_media_description_find_stream(new_md, SalProtoRtpSavp, SalAudio);
        if (old_stream && new_stream) {
                const SalStreamDescription *local_st_desc = sal_media_description_find_stream(call->localdesc, SalProtoRtpSavp, SalAudio);
-               int crypto_idx = find_crypto_index_from_tag(local_st_desc->crypto, new_stream->crypto_local_tag);
-               if (crypto_idx >= 0) {
-                       audio_stream_enable_srtp(call->audiostream, new_stream->crypto[0].algo, local_st_desc->crypto[crypto_idx].master_key, new_stream->crypto[0].master_key);
-                       call->audiostream_encrypted = TRUE;
-               } else {
-                       ms_warning("Failed to find local crypto algo with tag: %d", new_stream->crypto_local_tag);
-                       call->audiostream_encrypted = FALSE;
-               }
-               for (i = 0; i < SAL_CRYPTO_ALGO_MAX; i++) {
-                       old_stream->crypto[i].tag = new_stream->crypto[i].tag;
-                       old_stream->crypto[i].algo = new_stream->crypto[i].algo;
-                       strncpy(old_stream->crypto[i].master_key, new_stream->crypto[i].master_key, sizeof(old_stream->crypto[i].master_key) - 1);
+               if (local_st_desc) {
+                       int crypto_idx = find_crypto_index_from_tag(local_st_desc->crypto, new_stream->crypto_local_tag);
+                       if (crypto_idx >= 0) {
+                               audio_stream_enable_srtp(call->audiostream, new_stream->crypto[0].algo, local_st_desc->crypto[crypto_idx].master_key, new_stream->crypto[0].master_key);
+                               call->audiostream_encrypted = TRUE;
+                       } else {
+                               ms_warning("Failed to find local crypto algo with tag: %d", new_stream->crypto_local_tag);
+                               call->audiostream_encrypted = FALSE;
+                       }
+                       for (i = 0; i < SAL_CRYPTO_ALGO_MAX; i++) {
+                               old_stream->crypto[i].tag = new_stream->crypto[i].tag;
+                               old_stream->crypto[i].algo = new_stream->crypto[i].algo;
+                               strncpy(old_stream->crypto[i].master_key, new_stream->crypto[i].master_key, sizeof(old_stream->crypto[i].master_key) - 1);
+                       }
                }
        }
 
@@ -1719,23 +1740,33 @@ void linphone_call_update_crypto_parameters(LinphoneCall *call, SalMediaDescript
        new_stream = sal_media_description_find_stream(new_md, SalProtoRtpSavp, SalVideo);
        if (old_stream && new_stream) {
                const SalStreamDescription *local_st_desc = sal_media_description_find_stream(call->localdesc, SalProtoRtpSavp, SalVideo);
-               int crypto_idx = find_crypto_index_from_tag(local_st_desc->crypto, new_stream->crypto_local_tag);
-               if (crypto_idx >= 0) {
-                       video_stream_enable_strp(call->videostream, new_stream->crypto[0].algo, local_st_desc->crypto[crypto_idx].master_key, new_stream->crypto[0].master_key);
-                       call->videostream_encrypted = TRUE;
-               } else {
-                       ms_warning("Failed to find local crypto algo with tag: %d", new_stream->crypto_local_tag);
-                       call->videostream_encrypted = FALSE;
-               }
-               for (i = 0; i < SAL_CRYPTO_ALGO_MAX; i++) {
-                       old_stream->crypto[i].tag = new_stream->crypto[i].tag;
-                       old_stream->crypto[i].algo = new_stream->crypto[i].algo;
-                       strncpy(old_stream->crypto[i].master_key, new_stream->crypto[i].master_key, sizeof(old_stream->crypto[i].master_key) - 1);
+               if (local_st_desc) {
+                       int crypto_idx = find_crypto_index_from_tag(local_st_desc->crypto, new_stream->crypto_local_tag);
+                       if (crypto_idx >= 0) {
+                               video_stream_enable_strp(call->videostream, new_stream->crypto[0].algo, local_st_desc->crypto[crypto_idx].master_key, new_stream->crypto[0].master_key);
+                               call->videostream_encrypted = TRUE;
+                       } else {
+                               ms_warning("Failed to find local crypto algo with tag: %d", new_stream->crypto_local_tag);
+                               call->videostream_encrypted = FALSE;
+                       }
+                       for (i = 0; i < SAL_CRYPTO_ALGO_MAX; i++) {
+                               old_stream->crypto[i].tag = new_stream->crypto[i].tag;
+                               old_stream->crypto[i].algo = new_stream->crypto[i].algo;
+                               strncpy(old_stream->crypto[i].master_key, new_stream->crypto[i].master_key, sizeof(old_stream->crypto[i].master_key) - 1);
+                       }
                }
        }
 #endif
 }
 
+void linphone_call_update_remote_session_id_and_ver(LinphoneCall *call) {
+       SalMediaDescription *remote_desc = sal_call_get_remote_media_description(call->op);
+       if (remote_desc) {
+               call->remote_session_id = remote_desc->session_id;
+               call->remote_session_ver = remote_desc->session_ver;
+       }
+}
+
 void linphone_call_delete_ice_session(LinphoneCall *call){
        if (call->ice_session != NULL) {
                ice_session_destroy(call->ice_session);