diff --git a/coreapi/bellesip_sal/sal_op_call.c b/coreapi/bellesip_sal/sal_op_call.c index 5474540ea..bdbae06ec 100644 --- a/coreapi/bellesip_sal/sal_op_call.c +++ b/coreapi/bellesip_sal/sal_op_call.c @@ -66,7 +66,7 @@ static void sdp_process(SalOp *h){ /*for backward compatibility purpose*/ if(h->cnx_ip_to_0000_if_sendonly_enabled && sal_media_description_has_dir(h->result,SalStreamSendOnly)) { set_addr_to_0000(h->result->addr); - for(i=0;iresult->nb_streams;++i){ + for(i=0;iresult->streams[i].dir == SalStreamSendOnly) set_addr_to_0000(h->result->streams[i].rtp_addr); set_addr_to_0000(h->result->streams[i].rtcp_addr); @@ -78,7 +78,7 @@ 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;iresult->nb_streams;++i){ + for(i=0;iresult->streams[i].rtp_port!=0){ /*if stream was accepted*/ strcpy(h->result->streams[i].rtp_addr,h->base.remote_media->streams[i].rtp_addr); diff --git a/coreapi/bellesip_sal/sal_sdp.c b/coreapi/bellesip_sal/sal_sdp.c index ec84ccfe4..940ee7438 100644 --- a/coreapi/bellesip_sal/sal_sdp.c +++ b/coreapi/bellesip_sal/sal_sdp.c @@ -416,7 +416,8 @@ belle_sdp_session_description_t * media_description_to_sdp ( const SalMediaDescr belle_sdp_session_description_add_attribute(session_desc, create_rtcp_xr_attribute(&desc->rtcp_xr)); } - for ( i=0; inb_streams; i++ ) { + for ( i=0; istreams[i])) continue; stream_description_to_sdp(session_desc, desc, &desc->streams[i]); } return session_desc; diff --git a/coreapi/call_params.c b/coreapi/call_params.c index 5f73a7d07..1f22ad4fd 100644 --- a/coreapi/call_params.c +++ b/coreapi/call_params.c @@ -266,7 +266,7 @@ LinphoneCallParams * linphone_call_params_new(void) { LinphoneCallParams *cp=belle_sip_object_new(LinphoneCallParams); cp->audio_dir=LinphoneMediaDirectionSendRecv; cp->video_dir=LinphoneMediaDirectionSendRecv; - cp->realtimetext_enabled=TRUE; /*fixme*/ + cp->realtimetext_enabled = FALSE; return cp; } diff --git a/coreapi/callbacks.c b/coreapi/callbacks.c index f58c2a77f..54394b719 100644 --- a/coreapi/callbacks.c +++ b/coreapi/callbacks.c @@ -49,7 +49,7 @@ void linphone_core_update_streams_destinations(LinphoneCore *lc, LinphoneCall *c char *rtp_addr, *rtcp_addr; int i; - for (i = 0; i < new_md->nb_streams; i++) { + for (i = 0; i < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; i++) { if (!sal_stream_description_active(&new_md->streams[i])) continue; if (new_md->streams[i].type == SalAudio) { new_audiodesc = &new_md->streams[i]; @@ -188,8 +188,9 @@ void linphone_core_update_streams(LinphoneCore *lc, LinphoneCall *call, SalMedia linphone_call_stop_media_streams (call); if (md_changed & SAL_MEDIA_DESCRIPTION_NETWORK_XXXCAST_CHANGED){ ms_message("Media ip type has changed, destroying sessions context on call [%p]",call); - ms_media_stream_sessions_uninit(&call->sessions[0]); - ms_media_stream_sessions_uninit(&call->sessions[1]); + ms_media_stream_sessions_uninit(&call->sessions[call->main_audio_stream_index]); + ms_media_stream_sessions_uninit(&call->sessions[call->main_video_stream_index]); + if (call->params->realtimetext_enabled) ms_media_stream_sessions_uninit(&call->sessions[call->main_text_stream_index]); } linphone_call_init_media_streams (call); } @@ -368,7 +369,7 @@ static void try_early_media_forking(LinphoneCall *call, SalMediaDescription *md) SalStreamDescription *ref_stream,*new_stream; ms_message("Early media response received from another branch, checking if media can be forked to this new destination."); - for (i=0;inb_streams;++i){ + for (i=0;istreams[i])) continue; ref_stream=&cur_md->streams[i]; new_stream=&md->streams[i]; diff --git a/coreapi/linphonecall.c b/coreapi/linphonecall.c index f1a284d24..82e71db9e 100644 --- a/coreapi/linphonecall.c +++ b/coreapi/linphonecall.c @@ -408,7 +408,7 @@ static MSList *make_codec_list(LinphoneCore *lc, CodecConstraints * hints, SalSt static void update_media_description_from_stun(SalMediaDescription *md, const StunCandidate *ac, const StunCandidate *vc, const StunCandidate *tc){ int i; - for (i = 0; i < md->nb_streams; i++) { + for (i = 0; i < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; i++) { if (!sal_stream_description_active(&md->streams[i])) continue; if ((md->streams[i].type == SalAudio) && (ac->port != 0)) { strcpy(md->streams[i].rtp_addr,ac->addr); @@ -453,7 +453,7 @@ static int setup_encryption_key(SalSrtpCryptoAlgo *crypto, MSCryptoSuite suite, } static void setup_dtls_keys(LinphoneCall *call, SalMediaDescription *md){ int i; - for(i=0; inb_streams; i++) { + for(i=0; istreams[i])) continue; /* if media encryption is set to DTLS check presence of fingerprint in the call which shall have been set at stream init but it may have failed when retrieving certificate resulting in no fingerprint present and then DTLS not usable */ if (sal_stream_description_has_dtls(&md->streams[i]) == TRUE) { @@ -473,7 +473,7 @@ static void setup_encryption_keys(LinphoneCall *call, SalMediaDescription *md){ SalMediaDescription *old_md=call->localdesc; bool_t keep_srtp_keys=lp_config_get_int(lc->config,"sip","keep_srtp_keys",1); - for(i=0; inb_streams; i++) { + for(i=0; istreams[i])) continue; if (sal_stream_description_has_srtp(&md->streams[i]) == TRUE) { if (keep_srtp_keys && old_md && (sal_stream_description_active(&old_md->streams[i]) == TRUE) && (sal_stream_description_has_srtp(&old_md->streams[i]) == TRUE)) { @@ -499,7 +499,7 @@ static void setup_rtcp_fb(LinphoneCall *call, SalMediaDescription *md) { LinphoneCore *lc = call->core; int i; - for (i = 0; i < md->nb_streams; i++) { + for (i = 0; i < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; i++) { if (!sal_stream_description_active(&md->streams[i])) continue; md->streams[i].rtcp_fb.generic_nack_enabled = lp_config_get_int(lc->config, "rtp", "rtcp_fb_generic_nack_enabled", 0); md->streams[i].rtcp_fb.tmmbr_enabled = lp_config_get_int(lc->config, "rtp", "rtcp_fb_tmmbr_enabled", 0); @@ -537,7 +537,7 @@ static void setup_rtcp_xr(LinphoneCall *call, SalMediaDescription *md) { } md->rtcp_xr.voip_metrics_enabled = lp_config_get_int(lc->config, "rtp", "rtcp_xr_voip_metrics_enabled", 1); } - for (i = 0; i < md->nb_streams; i++) { + for (i = 0; i < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; i++) { if (!sal_stream_description_active(&md->streams[i])) continue; memcpy(&md->streams[i].rtcp_xr, &md->rtcp_xr, sizeof(md->streams[i].rtcp_xr)); } @@ -563,7 +563,7 @@ void linphone_call_update_local_media_description_from_ice_or_upnp(LinphoneCall static void transfer_already_assigned_payload_types(SalMediaDescription *old, SalMediaDescription *md){ int i; - for(i=0;inb_streams;++i){ + for(i=0;istreams[i].already_assigned_payloads=old->streams[i].already_assigned_payloads; old->streams[i].already_assigned_payloads=NULL; } @@ -601,12 +601,14 @@ static void force_streams_dir_according_to_state(LinphoneCall *call, SalMediaDes break; } - for (i=0; inb_streams; ++i){ + for (i=0; istreams[i]; - sd->dir = SalStreamSendOnly; - if (sd->type == SalVideo){ - if (lp_config_get_int(call->core->config, "sip", "inactive_video_on_pause", 0)) { - sd->dir = SalStreamInactive; + if (sd->dir != SalStreamInactive) { + sd->dir = SalStreamSendOnly; + if (sd->type == SalVideo){ + if (lp_config_get_int(call->core->config, "sip", "inactive_video_on_pause", 0)) { + sd->dir = SalStreamInactive; + } } } } @@ -747,17 +749,20 @@ void linphone_call_make_local_media_description(LinphoneCall *call) { md->nb_streams = nb_active_streams; /* Deactivate inactive streams. */ - for (i = nb_active_streams; i < md->nb_streams; i++) { - md->streams[i].rtp_port = 0; - md->streams[i].rtcp_port = 0; - md->streams[i].proto = call->biggestdesc->streams[i].proto; - md->streams[i].type = call->biggestdesc->streams[i].type; - md->streams[i].dir = SalStreamInactive; - codec_hints.bandwidth_limit=0; - codec_hints.max_codecs=1; - codec_hints.previously_used=NULL; - l = make_codec_list(lc, &codec_hints, SalVideo, lc->codecs_conf.video_codecs); - md->streams[i].payloads = l; + for (i = 0; i < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; i++) { + if (md->streams[i].dir == SalStreamInactive) { + md->streams[i].rtp_port = 0; + md->streams[i].rtcp_port = 0; + if (call->biggestdesc && i < call->biggestdesc->nb_streams) { + md->streams[i].proto = call->biggestdesc->streams[i].proto; + md->streams[i].type = call->biggestdesc->streams[i].type; + } + codec_hints.bandwidth_limit=0; + codec_hints.max_codecs=1; + codec_hints.previously_used=NULL; + l = make_codec_list(lc, &codec_hints, SalVideo, lc->codecs_conf.video_codecs); + md->streams[i].payloads = l; + } } setup_encryption_keys(call,md); setup_dtls_keys(call,md); @@ -876,8 +881,10 @@ static void linphone_call_init_common(LinphoneCall *call, LinphoneAddress *from, linphone_core_get_video_port_range(call->core, &min_port, &max_port); port_config_set(call,call->main_video_stream_index,min_port,max_port); - linphone_core_get_text_port_range(call->core, &min_port, &max_port); - port_config_set(call,call->main_text_stream_index,min_port,max_port); + if (call->params->realtimetext_enabled) { + linphone_core_get_text_port_range(call->core, &min_port, &max_port); + port_config_set(call,call->main_text_stream_index,min_port,max_port); + } linphone_call_init_stats(&call->stats[LINPHONE_CALL_STATS_AUDIO], LINPHONE_CALL_STATS_AUDIO); linphone_call_init_stats(&call->stats[LINPHONE_CALL_STATS_VIDEO], LINPHONE_CALL_STATS_VIDEO); @@ -1015,14 +1022,14 @@ LinphoneCall * linphone_call_new_outgoing(struct _LinphoneCore *lc, LinphoneAddr call->main_audio_stream_index = LINPHONE_CALL_STATS_AUDIO; call->main_video_stream_index = LINPHONE_CALL_STATS_VIDEO; - call->main_text_stream_index = LINPHONE_CALL_STATS_TEXT; + call->main_text_stream_index = params->realtimetext_enabled ? LINPHONE_CALL_STATS_TEXT : -1; call->dir=LinphoneCallOutgoing; call->core=lc; linphone_call_outgoing_select_ip_version(call,to,cfg); linphone_call_get_local_ip(call, to); - linphone_call_init_common(call, from, to); call->params = linphone_call_params_copy(params); + linphone_call_init_common(call, from, to); linphone_call_fill_media_multicast_addr(call); @@ -1087,9 +1094,9 @@ LinphoneCall * linphone_call_new_incoming(LinphoneCore *lc, LinphoneAddress *fro LinphoneFirewallPolicy fpol; int i; - call->main_audio_stream_index = LINPHONE_CALL_STATS_AUDIO; - call->main_video_stream_index = LINPHONE_CALL_STATS_VIDEO; - call->main_text_stream_index = LINPHONE_CALL_STATS_TEXT; + call->main_audio_stream_index = -1; + call->main_video_stream_index = -1; + call->main_text_stream_index = -1; call->dir=LinphoneCallIncoming; sal_op_set_user_pointer(op,call); @@ -1122,8 +1129,8 @@ LinphoneCall * linphone_call_new_incoming(LinphoneCore *lc, LinphoneAddress *fro linphone_address_clean(from); linphone_call_get_local_ip(call, from); - linphone_call_init_common(call, from, to); call->params = linphone_call_params_new(); + linphone_call_init_common(call, from, to); call->log->call_id=ms_strdup(sal_op_get_call_id(op)); /*must be known at that time*/ call->dest_proxy = linphone_core_lookup_known_proxy(call->core, to); linphone_core_init_default_params(lc, call->params); @@ -1143,21 +1150,28 @@ LinphoneCall * linphone_call_new_incoming(LinphoneCore *lc, LinphoneAddress *fro linphone_call_set_compatible_incoming_call_parameters(call, md); /* set multicast role & address if any*/ if (!sal_call_is_offerer(op)){ - for (i=0;inb_streams;i++){ + for (i = 0; i < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; i++) { + if (md->streams[i].dir == SalStreamInactive) { + continue; + } + if (md->streams[i].rtp_addr[0]!='\0' && ms_is_multicast(md->streams[i].rtp_addr)){ md->streams[i].multicast_role = SalMulticastReceiver; strncpy(call->media_ports[i].multicast_ip,md->streams[i].rtp_addr,sizeof(call->media_ports[i].multicast_ip)); - - if (sal_stream_description_active(&md->streams[i])) { - if (md->streams[i].type == SalAudio) { - call->main_audio_stream_index = i; - } else if (md->streams[i].type == SalVideo) { - call->main_video_stream_index = i; - } else if (md->streams[i].type == SalText) { - call->main_text_stream_index = i; - } - } } + + if (sal_stream_description_active(&md->streams[i])) { + if (md->streams[i].type == SalAudio) { + call->main_audio_stream_index = i; + ms_message("audio stream index updated: %i", i); + } else if (md->streams[i].type == SalVideo) { + call->main_video_stream_index = i; + ms_message("video stream index updated: %i", i); + } else if (md->streams[i].type == SalText) { + call->main_text_stream_index = i; + ms_message("text stream index updated: %i", i); + } + } } } } @@ -1220,12 +1234,12 @@ void linphone_call_free_media_resources(LinphoneCall *call){ linphone_call_stop_media_streams(call); ms_media_stream_sessions_uninit(&call->sessions[call->main_audio_stream_index]); ms_media_stream_sessions_uninit(&call->sessions[call->main_video_stream_index]); - ms_media_stream_sessions_uninit(&call->sessions[call->main_text_stream_index]); + if (call->params->realtimetext_enabled) ms_media_stream_sessions_uninit(&call->sessions[call->main_text_stream_index]); linphone_call_delete_upnp_session(call); linphone_call_delete_ice_session(call); - linphone_call_stats_uninit(&call->stats[call->main_audio_stream_index]); - linphone_call_stats_uninit(&call->stats[call->main_video_stream_index]); - linphone_call_stats_uninit(&call->stats[call->main_text_stream_index]); + linphone_call_stats_uninit(&call->stats[LINPHONE_CALL_STATS_AUDIO]); + linphone_call_stats_uninit(&call->stats[LINPHONE_CALL_STATS_VIDEO]); + linphone_call_stats_uninit(&call->stats[LINPHONE_CALL_STATS_TEXT]); } /* @@ -2255,7 +2269,7 @@ void linphone_call_init_text_stream(LinphoneCall *call){ LinphoneCore *lc=call->core; char* cname; - if (call->textstream != NULL) return; + if (call->textstream != NULL || !call->params->realtimetext_enabled) return; if (call->sessions[call->main_text_stream_index].rtp_session == NULL) { SalMulticastRole multicast_role = linphone_call_get_multicast_role(call, SalText); SalMediaDescription *remotedesc = NULL; @@ -3356,7 +3370,7 @@ static void linphone_call_stop_text_stream(LinphoneCall *call) { } void linphone_call_stop_media_streams(LinphoneCall *call){ - if (call->audiostream || call->videostream) { + if (call->audiostream || call->videostream || call->textstream) { if (call->audiostream && call->videostream) audio_stream_unlink_video(call->audiostream, call->videostream); linphone_call_stop_audio_stream(call); @@ -4048,8 +4062,9 @@ void linphone_call_handle_stream_events(LinphoneCall *call, int stream_index){ OrtpEventType evt=ortp_event_get_type(ev); OrtpEventData *evd=ortp_event_get_data(ev); - linphone_call_stats_fill(&call->stats[stream_index],ms,ev); - linphone_call_notify_stats_updated(call,stream_index); + int stats_index = stream_index == call->main_audio_stream_index ? LINPHONE_CALL_STATS_AUDIO : (stream_index == call->main_video_stream_index ? LINPHONE_CALL_STATS_VIDEO : LINPHONE_CALL_STATS_TEXT); + linphone_call_stats_fill(&call->stats[stats_index],ms,ev); + linphone_call_notify_stats_updated(call,stats_index); if (evt == ORTP_EVENT_ZRTP_ENCRYPTION_CHANGED){ if (ms->type==MSAudio) diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index 1c8504b63..c9a50638c 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -2831,8 +2831,9 @@ int linphone_core_proceed_with_invite_if_ready(LinphoneCore *lc, LinphoneCall *c int linphone_core_restart_invite(LinphoneCore *lc, LinphoneCall *call){ linphone_call_create_op(call); linphone_call_stop_media_streams(call); - ms_media_stream_sessions_uninit(&call->sessions[0]); - ms_media_stream_sessions_uninit(&call->sessions[1]); + ms_media_stream_sessions_uninit(&call->sessions[call->main_audio_stream_index]); + ms_media_stream_sessions_uninit(&call->sessions[call->main_video_stream_index]); + if (call->params->realtimetext_enabled) ms_media_stream_sessions_uninit(&call->sessions[call->main_text_stream_index]); linphone_call_init_media_streams(call); return linphone_core_start_invite(lc,call, NULL); } @@ -6157,6 +6158,11 @@ void rtp_config_uninit(LinphoneCore *lc) } else { lp_config_set_range(lc->config, "rtp", "video_rtp_port", config->video_rtp_min_port, config->video_rtp_max_port); } + if (config->text_rtp_min_port == config->text_rtp_max_port) { + lp_config_set_int(lc->config, "rtp", "text_rtp_port", config->text_rtp_min_port); + } else { + lp_config_set_range(lc->config, "rtp", "text_rtp_port", config->text_rtp_min_port, config->text_rtp_max_port); + } lp_config_set_int(lc->config,"rtp","audio_jitt_comp",config->audio_jitt_comp); lp_config_set_int(lc->config,"rtp","video_jitt_comp",config->video_jitt_comp); lp_config_set_int(lc->config,"rtp","nortp_timeout",config->nortp_timeout); diff --git a/coreapi/misc.c b/coreapi/misc.c index 8fcd4c546..6cad3002b 100644 --- a/coreapi/misc.c +++ b/coreapi/misc.c @@ -409,22 +409,23 @@ int linphone_core_run_stun_tests(LinphoneCore *lc, LinphoneCall *call){ const char *server=linphone_core_get_stun_server(lc); StunCandidate *ac=&call->ac; StunCandidate *vc=&call->vc; + StunCandidate *tc=&call->tc; if (lc->sip_conf.ipv6_enabled){ ms_warning("stun support is not implemented for ipv6"); return -1; } - if (call->media_ports[0].rtp_port==-1){ + if (call->media_ports[call->main_audio_stream_index].rtp_port==-1){ ms_warning("Stun-only support not available for system random port"); return -1; } if (server!=NULL){ const struct addrinfo *ai=linphone_core_get_stun_server_addrinfo(lc); - ortp_socket_t sock1=-1, sock2=-1; + ortp_socket_t sock1=-1, sock2=-1, sock3=-1; int loops=0; bool_t video_enabled=linphone_core_video_enabled(lc); - bool_t got_audio,got_video; - bool_t cone_audio=FALSE,cone_video=FALSE; + bool_t got_audio,got_video,got_text; + bool_t cone_audio=FALSE,cone_video=FALSE,cone_text=FALSE; struct timeval init,cur; double elapsed; int ret=0; @@ -436,14 +437,19 @@ int linphone_core_run_stun_tests(LinphoneCore *lc, LinphoneCall *call){ linphone_core_notify_display_status(lc,_("Stun lookup in progress...")); /*create the two audio and video RTP sockets, and send STUN message to our stun server */ - sock1=create_socket(call->media_ports[0].rtp_port); + sock1=create_socket(call->media_ports[call->main_audio_stream_index].rtp_port); if (sock1==-1) return -1; if (video_enabled){ - sock2=create_socket(call->media_ports[1].rtp_port); + sock2=create_socket(call->media_ports[call->main_video_stream_index].rtp_port); if (sock2==-1) return -1; } + if (call->params->realtimetext_enabled) { + sock3=create_socket(call->media_ports[call->main_text_stream_index].rtp_port); + if (sock3==-1) return -1; + } got_audio=FALSE; got_video=FALSE; + got_text=FALSE; ortp_gettimeofday(&init,NULL); do{ @@ -456,6 +462,10 @@ int linphone_core_run_stun_tests(LinphoneCore *lc, LinphoneCall *call){ sendStunRequest(sock2,ai->ai_addr,ai->ai_addrlen,22,TRUE); sendStunRequest(sock2,ai->ai_addr,ai->ai_addrlen,2,FALSE); } + if (sock3!=-1){ + sendStunRequest(sock3,ai->ai_addr,ai->ai_addrlen,33,TRUE); + sendStunRequest(sock3,ai->ai_addr,ai->ai_addrlen,3,FALSE); + } } ms_usleep(10000); @@ -477,6 +487,15 @@ int linphone_core_run_stun_tests(LinphoneCore *lc, LinphoneCall *call){ cone_video=TRUE; got_video=TRUE; } + if (recvStunResponse(sock3,tc->addr, + &tc->port,&id)>0){ + ms_message("STUN test result: local text port maps to %s:%i", + tc->addr, + tc->port); + if (id==33) + cone_text=TRUE; + got_text=TRUE; + } ortp_gettimeofday(&cur,NULL); elapsed=((cur.tv_sec-init.tv_sec)*1000.0) + ((cur.tv_usec-init.tv_usec)/1000.0); if (elapsed>2000) { @@ -485,7 +504,7 @@ int linphone_core_run_stun_tests(LinphoneCore *lc, LinphoneCall *call){ break; } loops++; - }while(!(got_audio && (got_video||sock2==-1) ) ); + }while(!(got_audio && (got_video||sock2==-1) && (got_text||sock3==-1) ) ); if (ret==0) ret=(int)elapsed; if (!got_audio){ ms_error("No stun server response for audio port."); @@ -503,8 +522,18 @@ int linphone_core_run_stun_tests(LinphoneCore *lc, LinphoneCall *call){ } } } + if (sock3!=-1){ + if (!got_text){ + ms_error("No stun server response for text port."); + }else{ + if (!cone_text) { + ms_message("NAT is symmetric for text port."); + } + } + } close_socket(sock1); if (sock2!=-1) close_socket(sock2); + if (sock3!=-1) close_socket(sock3); return ret; } return -1; @@ -622,14 +651,14 @@ int linphone_core_gather_ice_candidates(LinphoneCore *lc, LinphoneCall *call) return -1; } if ((ice_check_list_state(audio_check_list) != ICL_Completed) && (ice_check_list_candidates_gathered(audio_check_list) == FALSE)) { - ice_add_local_candidate(audio_check_list, "host", local_addr, call->media_ports[0].rtp_port, 1, NULL); - ice_add_local_candidate(audio_check_list, "host", local_addr, call->media_ports[0].rtcp_port, 2, NULL); + ice_add_local_candidate(audio_check_list, "host", local_addr, call->media_ports[call->main_audio_stream_index].rtp_port, 1, NULL); + ice_add_local_candidate(audio_check_list, "host", local_addr, call->media_ports[call->main_audio_stream_index].rtcp_port, 2, NULL); call->stats[LINPHONE_CALL_STATS_AUDIO].ice_state = LinphoneIceStateInProgress; } if (linphone_core_video_enabled(lc) && (video_check_list != NULL) && (ice_check_list_state(video_check_list) != ICL_Completed) && (ice_check_list_candidates_gathered(video_check_list) == FALSE)) { - ice_add_local_candidate(video_check_list, "host", local_addr, call->media_ports[1].rtp_port, 1, NULL); - ice_add_local_candidate(video_check_list, "host", local_addr, call->media_ports[1].rtcp_port, 2, NULL); + ice_add_local_candidate(video_check_list, "host", local_addr, call->media_ports[call->main_video_stream_index].rtp_port, 1, NULL); + ice_add_local_candidate(video_check_list, "host", local_addr, call->media_ports[call->main_video_stream_index].rtcp_port, 2, NULL); call->stats[LINPHONE_CALL_STATS_VIDEO].ice_state = LinphoneIceStateInProgress; } @@ -759,7 +788,7 @@ void _update_local_media_description_from_ice(SalMediaDescription *desc, IceSess } 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->nb_streams; i++) { + for (i = 0; i < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; i++) { SalStreamDescription *stream = &desc->streams[i]; IceCheckList *cl = ice_session_check_list(session, i); nb_candidates = 0; @@ -866,9 +895,10 @@ void linphone_call_update_ice_from_remote_media_description(LinphoneCall *call, ice_params_found=TRUE; } else { int i; - for (i = 0; i < md->nb_streams; i++) { + for (i = 0; i < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; i++) { const SalStreamDescription *stream = &md->streams[i]; IceCheckList *cl = ice_session_check_list(call->ice_session, i); + if (!sal_stream_description_active(stream)) continue; if (cl) { if ((stream->ice_pwd[0] != '\0') && (stream->ice_ufrag[0] != '\0')) { ice_params_found=TRUE; @@ -887,9 +917,10 @@ void linphone_call_update_ice_from_remote_media_description(LinphoneCall *call, ice_session_restart(call->ice_session); ice_restarted = TRUE; } else { - for (i = 0; i < md->nb_streams; i++) { + for (i = 0; i < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; i++) { const SalStreamDescription *stream = &md->streams[i]; IceCheckList *cl = ice_session_check_list(call->ice_session, i); + if (!sal_stream_description_active(stream)) continue; if (cl && (strcmp(stream->rtp_addr, "0.0.0.0") == 0)) { ice_session_restart(call->ice_session); ice_restarted = TRUE; @@ -906,9 +937,10 @@ void linphone_call_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->nb_streams; i++) { + for (i = 0; i < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; i++) { const SalStreamDescription *stream = &md->streams[i]; IceCheckList *cl = ice_session_check_list(call->ice_session, i); + if (!sal_stream_description_active(stream)) continue; if (cl && (stream->ice_pwd[0] != '\0') && (stream->ice_ufrag[0] != '\0')) { if (ice_check_list_remote_credentials_changed(cl, stream->ice_ufrag, stream->ice_pwd)) { if (ice_restarted == FALSE @@ -925,9 +957,10 @@ void linphone_call_update_ice_from_remote_media_description(LinphoneCall *call, } /* Create ICE check lists if needed and parse ICE attributes. */ - for (i = 0; i < md->nb_streams; i++) { + for (i = 0; i < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; i++) { const SalStreamDescription *stream = &md->streams[i]; IceCheckList *cl = ice_session_check_list(call->ice_session, i); + if (!sal_stream_description_active(stream)) continue; /* if ((cl == NULL) && (i < md->n_active_streams)) { cl = ice_check_list_new(); @@ -986,7 +1019,7 @@ void linphone_call_update_ice_from_remote_media_description(LinphoneCall *call, } } } - for (i = 0; i < md->nb_streams; i++) { + for (i = 0; i < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; i++) { IceCheckList * cl = ice_session_check_list(call->ice_session, i); if (!sal_stream_description_active(&md->streams[i]) && (cl != NULL)) { ice_session_remove_check_list_from_idx(call->ice_session, i); @@ -1007,7 +1040,7 @@ void linphone_call_update_ice_from_remote_media_description(LinphoneCall *call, bool_t linphone_core_media_description_contains_video_stream(const SalMediaDescription *md){ int i; - for (i = 0; md && i < md->nb_streams; i++) { + for (i = 0; md && i < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; i++) { if (md->streams[i].type == SalVideo && md->streams[i].rtp_port!=0) return TRUE; } diff --git a/coreapi/offeranswer.c b/coreapi/offeranswer.c index 0b0edb931..f36f002a7 100644 --- a/coreapi/offeranswer.c +++ b/coreapi/offeranswer.c @@ -493,9 +493,10 @@ int offer_answer_initiate_outgoing(const SalMediaDescription *local_offer, int i,j; const SalStreamDescription *ls,*rs; - for(i=0,j=0;inb_streams;++i){ - ms_message("Processing for stream %i",i); + for(i=0,j=0;istreams[i]; + if (!sal_stream_description_active(ls)) continue; + ms_message("Processing for stream %i",i); rs=sal_media_description_find_stream((SalMediaDescription*)remote_answer,ls->proto,ls->type); if (rs) { initiate_outgoing(ls,rs,&result->streams[j]); @@ -522,7 +523,7 @@ int offer_answer_initiate_outgoing(const SalMediaDescription *local_offer, static bool_t local_stream_not_already_used(const SalMediaDescription *result, const SalStreamDescription *stream){ int i; - for(i=0;inb_streams;++i){ + for(i=0;istreams[i]; if (strcmp(ss->name,stream->name)==0){ ms_message("video stream already used in answer"); @@ -544,7 +545,7 @@ static bool_t proto_compatible(SalMediaProto local, SalMediaProto remote) { static const SalStreamDescription *find_local_matching_stream(const SalMediaDescription *result, const SalMediaDescription *local_capabilities, const SalStreamDescription *remote_stream){ int i; - for(i=0;inb_streams;++i){ + for(i=0;istreams[i]; if (!sal_stream_description_active(ss)) continue; if (ss->type==remote_stream->type && proto_compatible(ss->proto,remote_stream->proto) @@ -564,8 +565,9 @@ int offer_answer_initiate_incoming(const SalMediaDescription *local_capabilities int i; const SalStreamDescription *ls=NULL,*rs; - for(i=0;inb_streams;++i){ + for(i=0;istreams[i]; + if (!sal_stream_description_active(rs)) continue; if (rs->proto!=SalProtoOther){ ls=find_local_matching_stream(result,local_capabilities,rs); }else ms_warning("Unknown protocol for mline %i, declining",i); diff --git a/coreapi/quality_reporting.c b/coreapi/quality_reporting.c index 4df8a2e0e..58e47310b 100644 --- a/coreapi/quality_reporting.c +++ b/coreapi/quality_reporting.c @@ -390,8 +390,8 @@ static int send_report(LinphoneCall* call, reporting_session_report_t * report, static const SalStreamDescription * get_media_stream_for_desc(const SalMediaDescription * smd, SalStreamType sal_stream_type) { int count; if (smd != NULL) { - for (count = 0; count < smd->nb_streams; ++count) { - if (smd->streams[count].type == sal_stream_type) { + for (count = 0; count < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; ++count) { + if (sal_stream_description_active(&smd->streams[count]) && smd->streams[count].type == sal_stream_type) { return &smd->streams[count]; } } diff --git a/coreapi/sal.c b/coreapi/sal.c index ba8108eae..78d1af051 100644 --- a/coreapi/sal.c +++ b/coreapi/sal.c @@ -55,7 +55,11 @@ SalTransport sal_transport_parse(const char* param) { SalMediaDescription *sal_media_description_new(){ SalMediaDescription *md=ms_new0(SalMediaDescription,1); + int i; md->refcount=1; + for(i=0;istreams[i].dir=SalStreamInactive; + } return md; } @@ -85,7 +89,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;inb_streams;++i){ + for(i=0;istreams[i]; if (!sal_stream_description_active(ss)) continue; if (ss->proto==proto && ss->type==type) return ss; @@ -96,7 +100,7 @@ SalStreamDescription *sal_media_description_find_stream(SalMediaDescription *md, unsigned int sal_media_description_nb_active_streams_of_type(SalMediaDescription *md, SalStreamType type) { unsigned int i; unsigned int nb = 0; - for (i = 0; i < md->nb_streams; ++i) { + for (i = 0; i < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; ++i) { if (!sal_stream_description_active(&md->streams[i])) continue; if (md->streams[i].type == type) nb++; } @@ -105,7 +109,7 @@ unsigned int sal_media_description_nb_active_streams_of_type(SalMediaDescription SalStreamDescription * sal_media_description_get_active_stream_of_type(SalMediaDescription *md, SalStreamType type, unsigned int idx) { unsigned int i; - for (i = 0; i < md->nb_streams; ++i) { + for (i = 0; i < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; ++i) { if (!sal_stream_description_active(&md->streams[i])) continue; if (md->streams[i].type == type) { if (idx-- == 0) return &md->streams[i]; @@ -137,7 +141,7 @@ bool_t sal_media_description_empty(const SalMediaDescription *md){ void sal_media_description_set_dir(SalMediaDescription *md, SalStreamDir stream_dir){ int i; - for(i=0;inb_streams;++i){ + for(i=0;istreams[i]; if (!sal_stream_description_active(ss)) continue; ss->dir=stream_dir; @@ -147,7 +151,7 @@ void sal_media_description_set_dir(SalMediaDescription *md, SalStreamDir stream_ int sal_media_description_get_nb_active_streams(const SalMediaDescription *md) { int i; int nb = 0; - for (i = 0; i < md->nb_streams; i++) { + for (i = 0; i < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; i++) { if (sal_stream_description_active(&md->streams[i])) nb++; } return nb; @@ -162,7 +166,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;inb_streams;++i){ + for(i=0;istreams[i]; if (!sal_stream_description_active(ss)) continue; if (ss->dir==stream_dir) { @@ -211,7 +215,7 @@ bool_t sal_stream_description_has_dtls(const SalStreamDescription *sd) { bool_t sal_media_description_has_avpf(const SalMediaDescription *md) { int i; if (md->nb_streams == 0) return FALSE; - for (i = 0; i < md->nb_streams; i++) { + for (i = 0; i < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; i++) { if (!sal_stream_description_active(&md->streams[i])) continue; if (sal_stream_description_has_avpf(&md->streams[i]) != TRUE) return FALSE; } @@ -221,7 +225,7 @@ bool_t sal_media_description_has_avpf(const SalMediaDescription *md) { bool_t sal_media_description_has_srtp(const SalMediaDescription *md) { int i; if (md->nb_streams == 0) return FALSE; - for (i = 0; i < md->nb_streams; i++) { + for (i = 0; i < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; i++) { if (!sal_stream_description_active(&md->streams[i])) continue; if (sal_stream_description_has_srtp(&md->streams[i]) != TRUE) return FALSE; } @@ -231,7 +235,7 @@ bool_t sal_media_description_has_srtp(const SalMediaDescription *md) { bool_t sal_media_description_has_dtls(const SalMediaDescription *md) { int i; if (md->nb_streams == 0) return FALSE; - for (i = 0; i < md->nb_streams; i++) { + for (i = 0; i < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; i++) { if (!sal_stream_description_active(&md->streams[i])) continue; if (sal_stream_description_has_dtls(&md->streams[i]) != TRUE) return FALSE; } @@ -336,7 +340,8 @@ int sal_media_description_equals(const SalMediaDescription *md1, const SalMediaD result |= SAL_MEDIA_DESCRIPTION_NETWORK_XXXCAST_CHANGED; if (md1->nb_streams != md2->nb_streams) result |= SAL_MEDIA_DESCRIPTION_STREAMS_CHANGED; if (md1->bandwidth != md2->bandwidth) result |= SAL_MEDIA_DESCRIPTION_CODEC_CHANGED; - for(i = 0; i < md1->nb_streams; ++i){ + for(i = 0; i < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; ++i){ + if (!sal_stream_description_active(&md1->streams[i]) || !sal_stream_description_active(&md2->streams[i])) continue; result |= sal_stream_description_equals(&md1->streams[i], &md2->streams[i]); } return result; diff --git a/coreapi/upnp.c b/coreapi/upnp.c index 68b82e2ed..72257ac60 100644 --- a/coreapi/upnp.c +++ b/coreapi/upnp.c @@ -698,19 +698,19 @@ int linphone_core_update_upnp_audio_video(LinphoneCall *call, bool_t audio, bool * Audio part */ linphone_upnp_update_port_binding(lupnp, &call->upnp_session->audio->rtp, - UPNP_IGD_IP_PROTOCOL_UDP, (audio)? call->media_ports[0].rtp_port:0, UPNP_CALL_RETRY_DELAY); + UPNP_IGD_IP_PROTOCOL_UDP, (audio)? call->media_ports[call->main_audio_stream_index].rtp_port:0, UPNP_CALL_RETRY_DELAY); linphone_upnp_update_port_binding(lupnp, &call->upnp_session->audio->rtcp, - UPNP_IGD_IP_PROTOCOL_UDP, (audio)? call->media_ports[0].rtcp_port:0, UPNP_CALL_RETRY_DELAY); + UPNP_IGD_IP_PROTOCOL_UDP, (audio)? call->media_ports[call->main_audio_stream_index].rtcp_port:0, UPNP_CALL_RETRY_DELAY); /* * Video part */ linphone_upnp_update_port_binding(lupnp, &call->upnp_session->video->rtp, - UPNP_IGD_IP_PROTOCOL_UDP, (video)? call->media_ports[1].rtp_port:0, UPNP_CALL_RETRY_DELAY); + UPNP_IGD_IP_PROTOCOL_UDP, (video)? call->media_ports[call->main_video_stream_index].rtp_port:0, UPNP_CALL_RETRY_DELAY); linphone_upnp_update_port_binding(lupnp, &call->upnp_session->video->rtcp, - UPNP_IGD_IP_PROTOCOL_UDP, (video)? call->media_ports[1].rtcp_port:0, UPNP_CALL_RETRY_DELAY); + UPNP_IGD_IP_PROTOCOL_UDP, (video)? call->media_ports[call->main_video_stream_index].rtcp_port:0, UPNP_CALL_RETRY_DELAY); } ms_mutex_unlock(&lupnp->mutex); @@ -731,8 +731,9 @@ int linphone_core_update_upnp_from_remote_media_description(LinphoneCall *call, int i; const SalStreamDescription *stream; - for (i = 0; i < md->nb_streams; i++) { + for (i = 0; i < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; i++) { stream = &md->streams[i]; + if (!sal_stream_description_active(stream)) continue; if(stream->type == SalAudio) { audio = TRUE; } else if(stream->type == SalVideo) { @@ -1060,7 +1061,7 @@ int linphone_core_update_local_media_description_from_upnp(SalMediaDescription * SalStreamDescription *stream; UpnpStream *upnpStream; - for (i = 0; i < desc->nb_streams; i++) { + for (i = 0; i < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; i++) { stream = &desc->streams[i]; if (!sal_stream_description_active(stream)) continue; upnpStream = NULL;