From 55cb3fa3ed9cf344004adf26c386adc20a0078df Mon Sep 17 00:00:00 2001 From: Ghislain MARY Date: Mon, 23 Jul 2012 13:37:10 +0200 Subject: [PATCH] Parse the rtcp attribute in the SDP if present. --- coreapi/linphonecall.c | 32 +++++++++++----------- coreapi/offeranswer.c | 24 ++++++++--------- coreapi/sal.c | 8 +++--- coreapi/sal.h | 6 +++-- coreapi/sal_eXosip2.c | 6 ++--- coreapi/sal_eXosip2_sdp.c | 57 +++++++++++++++++++++++++-------------- 6 files changed, 76 insertions(+), 57 deletions(-) diff --git a/coreapi/linphonecall.c b/coreapi/linphonecall.c index 1ca85fa53..825e56797 100644 --- a/coreapi/linphonecall.c +++ b/coreapi/linphonecall.c @@ -211,8 +211,8 @@ static SalMediaDescription *_create_local_media_description(LinphoneCore *lc, Li md->bandwidth=linphone_core_get_download_bandwidth(lc); /*set audio capabilities */ - strncpy(md->streams[0].addr,call->localip,sizeof(md->streams[0].addr)); - md->streams[0].port=call->audio_port; + strncpy(md->streams[0].rtp_addr,call->localip,sizeof(md->streams[0].rtp_addr)); + md->streams[0].rtp_port=call->audio_port; md->streams[0].proto=(call->params.media_encryption == LinphoneMediaEncryptionSRTP) ? SalProtoRtpSavp : SalProtoRtpAvp; md->streams[0].type=SalAudio; @@ -226,7 +226,7 @@ static SalMediaDescription *_create_local_media_description(LinphoneCore *lc, Li if (call->params.has_video){ md->nstreams++; - md->streams[1].port=call->video_port; + md->streams[1].rtp_port=call->video_port; 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); @@ -607,7 +607,7 @@ const LinphoneCallParams * linphone_call_get_current_params(const LinphoneCall * } static bool_t is_video_active(const SalStreamDescription *sd){ - return sd->port!=0 && sd->dir!=SalStreamInactive; + return sd->rtp_port!=0 && sd->dir!=SalStreamInactive; } /** @@ -930,7 +930,7 @@ void linphone_call_init_media_streams(LinphoneCall *call){ AudioStream *audiostream; IceSession *ice_session = sal_op_get_ice_session(call->op); - call->audiostream=audiostream=audio_stream_new(md->streams[0].port,linphone_core_ipv6_enabled(lc)); + call->audiostream=audiostream=audio_stream_new(md->streams[0].rtp_port,linphone_core_ipv6_enabled(lc)); if (linphone_core_echo_limiter_enabled(lc)){ const char *type=lp_config_get_string(lc->config,"sound","el_type","mic"); if (strcasecmp(type,"mic")==0) @@ -971,9 +971,9 @@ void linphone_call_init_media_streams(LinphoneCall *call){ #ifdef VIDEO_ENABLED - if ((lc->video_conf.display || lc->video_conf.capture) && md->streams[1].port>0){ + 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); - call->videostream=video_stream_new(md->streams[1].port,linphone_core_ipv6_enabled(lc)); + call->videostream=video_stream_new(md->streams[1].rtp_port,linphone_core_ipv6_enabled(lc)); video_stream_enable_display_filter_auto_rotate(call->videostream, lp_config_get_int(lc->config,"video","display_filter_auto_rotate",0)); if (video_recv_buf_size>0) rtp_session_set_recv_buf_size(call->videostream->session,video_recv_buf_size); @@ -1189,7 +1189,7 @@ static void linphone_call_start_audio_stream(LinphoneCall *call, const char *cna stream=sal_media_description_find_stream(call->resultdesc, SalProtoRtpAvp,SalAudio); - if (stream && stream->dir!=SalStreamInactive && stream->port!=0){ + if (stream && stream->dir!=SalStreamInactive && stream->rtp_port!=0){ MSSndCard *playcard=lc->sound_conf.lsd_card ? lc->sound_conf.lsd_card : lc->sound_conf.play_sndcard; MSSndCard *captcard=lc->sound_conf.capt_sndcard; @@ -1208,7 +1208,7 @@ static void linphone_call_start_audio_stream(LinphoneCall *call, const char *cna } /*Replace soundcard filters by inactive file players or recorders when placed in recvonly or sendonly mode*/ - if (stream->port==0 || stream->dir==SalStreamRecvOnly){ + if (stream->rtp_port==0 || stream->dir==SalStreamRecvOnly){ captcard=NULL; playfile=NULL; }else if (stream->dir==SalStreamSendOnly){ @@ -1242,9 +1242,9 @@ static void linphone_call_start_audio_stream(LinphoneCall *call, const char *cna audio_stream_start_full( call->audiostream, call->audio_profile, - stream->addr[0]!='\0' ? stream->addr : call->resultdesc->addr, - stream->port, - linphone_core_rtcp_enabled(lc) ? (stream->port+1) : 0, + stream->rtp_addr[0]!='\0' ? stream->rtp_addr : call->resultdesc->addr, + stream->rtp_port, + linphone_core_rtcp_enabled(lc) ? (stream->rtp_port+1) : 0, used_pt, jitt_comp, playfile, @@ -1312,8 +1312,8 @@ static void linphone_call_start_video_stream(LinphoneCall *call, const char *cna lc->previewstream=NULL; } - if (vstream!=NULL && vstream->dir!=SalStreamInactive && vstream->port!=0) { - const char *addr=vstream->addr[0]!='\0' ? vstream->addr : call->resultdesc->addr; + if (vstream!=NULL && vstream->dir!=SalStreamInactive && vstream->rtp_port!=0) { + const char *addr=vstream->rtp_addr[0]!='\0' ? vstream->rtp_addr : call->resultdesc->addr; call->video_profile=make_profile(call,call->resultdesc,vstream,&used_pt); if (used_pt!=-1){ call->current_params.video_codec = rtp_profile_get_payload(call->video_profile, used_pt); @@ -1359,8 +1359,8 @@ static void linphone_call_start_video_stream(LinphoneCall *call, const char *cna ms_message("%s lc rotation:%d\n", __FUNCTION__, lc->device_rotation); video_stream_set_device_rotation(call->videostream, lc->device_rotation); video_stream_start(call->videostream, - call->video_profile, addr, vstream->port, - linphone_core_rtcp_enabled(lc) ? (vstream->port+1) : 0, + call->video_profile, addr, vstream->rtp_port, + linphone_core_rtcp_enabled(lc) ? (vstream->rtp_port+1) : 0, used_pt, lc->rtp_conf.audio_jitt_comp, cam); video_stream_set_rtcp_information(call->videostream, cname,LINPHONE_RTCP_SDES_TOOL); } diff --git a/coreapi/offeranswer.c b/coreapi/offeranswer.c index 5a2b4f527..62782921c 100644 --- a/coreapi/offeranswer.c +++ b/coreapi/offeranswer.c @@ -203,25 +203,25 @@ static SalStreamDir compute_dir_incoming(SalStreamDir local, SalStreamDir offere static void initiate_outgoing(const SalStreamDescription *local_offer, const SalStreamDescription *remote_answer, SalStreamDescription *result){ - if (remote_answer->port!=0) + if (remote_answer->rtp_port!=0) result->payloads=match_payloads(local_offer->payloads,remote_answer->payloads,TRUE,FALSE); result->proto=remote_answer->proto; result->type=local_offer->type; result->dir=compute_dir_outgoing(local_offer->dir,remote_answer->dir); if (result->payloads && !only_telephone_event(result->payloads)){ - strcpy(result->addr,remote_answer->addr); - result->port=remote_answer->port; + strcpy(result->rtp_addr,remote_answer->rtp_addr); + result->rtp_port=remote_answer->rtp_port; result->bandwidth=remote_answer->bandwidth; result->ptime=remote_answer->ptime; }else{ - result->port=0; + result->rtp_port=0; } if (result->proto == SalProtoRtpSavp) { /* verify crypto algo */ memset(result->crypto, 0, sizeof(result->crypto)); if (!match_crypto_algo(local_offer->crypto, remote_answer->crypto, &result->crypto[0], &result->crypto_local_tag, FALSE)) - result->port = 0; + result->rtp_port = 0; } } @@ -233,20 +233,20 @@ static void initiate_incoming(const SalStreamDescription *local_cap, result->proto=remote_offer->proto; result->type=local_cap->type; result->dir=compute_dir_incoming(local_cap->dir,remote_offer->dir); - if (result->payloads && !only_telephone_event(result->payloads) && (remote_offer->port!=0 || remote_offer->port==SalStreamSendOnly)){ - strcpy(result->addr,local_cap->addr); + if (result->payloads && !only_telephone_event(result->payloads) && (remote_offer->rtp_port!=0 || remote_offer->rtp_port==SalStreamSendOnly)){ + strcpy(result->rtp_addr,local_cap->rtp_addr); memcpy(result->candidates,local_cap->candidates,sizeof(result->candidates)); - result->port=local_cap->port; + result->rtp_port=local_cap->rtp_port; result->bandwidth=local_cap->bandwidth; - result->ptime=local_cap->ptime; + result->ptime=local_cap->ptime; }else{ - result->port=0; + result->rtp_port=0; } if (result->proto == SalProtoRtpSavp) { /* select crypto algo */ memset(result->crypto, 0, sizeof(result->crypto)); if (!match_crypto_algo(local_cap->crypto, remote_offer->crypto, &result->crypto[0], &result->crypto_local_tag, TRUE)) - result->port = 0; + result->rtp_port = 0; } } @@ -303,7 +303,7 @@ int offer_answer_initiate_incoming(const SalMediaDescription *local_capabilities else { /* create an inactive stream for the answer, as there where no matching stream a local capability */ result->streams[i].dir=SalStreamInactive; - result->streams[i].port=0; + result->streams[i].rtp_port=0; result->streams[i].type=rs->type; result->streams[i].proto=rs->proto; if (rs->type==SalOther){ diff --git a/coreapi/sal.c b/coreapi/sal.c index 37e56fade..de812c4fb 100644 --- a/coreapi/sal.c +++ b/coreapi/sal.c @@ -87,7 +87,7 @@ bool_t sal_media_description_empty(const SalMediaDescription *md){ int i; for(i=0;instreams;++i){ const SalStreamDescription *ss=&md->streams[i]; - if (ss->port!=0) return FALSE; + if (ss->rtp_port!=0) return FALSE; } return TRUE; } @@ -114,7 +114,7 @@ static bool_t has_dir(const SalMediaDescription *md, SalStreamDir stream_dir){ 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 */ - if (ss->dir==SalStreamSendRecv && stream_dir==SalStreamSendOnly && (is_null_address(md->addr) || is_null_address(ss->addr))) + if (ss->dir==SalStreamSendRecv && stream_dir==SalStreamSendOnly && (is_null_address(md->addr) || is_null_address(ss->rtp_addr))) return TRUE; } return FALSE; @@ -180,8 +180,8 @@ static bool_t payload_list_equals(const MSList *l1, const MSList *l2){ bool_t sal_stream_description_equals(const SalStreamDescription *sd1, const SalStreamDescription *sd2){ if (sd1->proto!=sd2->proto) return FALSE; if (sd1->type!=sd2->type) return FALSE; - if (strcmp(sd1->addr,sd2->addr)!=0) return FALSE; - if (sd1->port!=sd2->port) return FALSE; + if (strcmp(sd1->rtp_addr,sd2->rtp_addr)!=0) return FALSE; + if (sd1->rtp_port!=sd2->rtp_port) return FALSE; if (!payload_list_equals(sd1->payloads,sd2->payloads)) return FALSE; if (sd1->bandwidth!=sd2->bandwidth) return FALSE; if (sd1->ptime!=sd2->ptime) return FALSE; diff --git a/coreapi/sal.h b/coreapi/sal.h index 8782226b8..8a51fa4a4 100644 --- a/coreapi/sal.h +++ b/coreapi/sal.h @@ -126,8 +126,10 @@ typedef struct SalStreamDescription{ SalMediaProto proto; SalStreamType type; char typeother[32]; - char addr[64]; - int port; + char rtp_addr[64]; + char rtcp_addr[64]; + int rtp_port; + int rtcp_port; MSList *payloads; //result->bandwidth=h->base.remote_media->bandwidth; for(i=0;iresult->nstreams;++i){ - if (h->result->streams[i].port>0){ - strcpy(h->result->streams[i].addr,h->base.remote_media->streams[i].addr); + if (h->result->streams[i].rtp_port>0){ + strcpy(h->result->streams[i].rtp_addr,h->base.remote_media->streams[i].rtp_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].port=h->base.remote_media->streams[i].port; + h->result->streams[i].rtp_port=h->base.remote_media->streams[i].rtp_port; if (h->result->streams[i].proto == SalProtoRtpSavp) { h->result->streams[i].crypto[0] = h->base.remote_media->streams[i].crypto[0]; diff --git a/coreapi/sal_eXosip2_sdp.c b/coreapi/sal_eXosip2_sdp.c index 4101a818e..7cf668ca1 100644 --- a/coreapi/sal_eXosip2_sdp.c +++ b/coreapi/sal_eXosip2_sdp.c @@ -130,7 +130,7 @@ static sdp_message_t *create_generic_sdp(const SalMediaDescription *desc, const int inet6; char sessid[16]; char sessver[16]; - const char *addr = desc->addr; + const char *rtp_addr = desc->addr; snprintf(sessid,16,"%i",desc->session_id); snprintf(sessver,16,"%i",desc->session_ver); @@ -146,17 +146,17 @@ static sdp_message_t *create_generic_sdp(const SalMediaDescription *desc, const 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), &addr, NULL, NULL, NULL); + 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), &addr, NULL, NULL, NULL); + 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, osip_strdup ("IN"), inet6 ? osip_strdup ("IP6") : osip_strdup ("IP4"), - osip_strdup (addr), NULL, NULL); + osip_strdup (rtp_addr), NULL, NULL); } else { @@ -262,9 +262,9 @@ static void add_line(sdp_message_t *msg, int lineno, const SalStreamDescription mt=desc->typeother; break; } - rtp_addr=rtcp_addr=desc->addr; - rtp_port=desc->port; - rtcp_port=desc->port+1; + rtp_addr=rtcp_addr=desc->rtp_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); @@ -418,21 +418,21 @@ static int payload_type_fill_from_rtpmap(PayloadType *pt, const char *rtpmap){ int sdp_to_media_description(sdp_message_t *msg, SalMediaDescription *desc, IceSession **ice_session){ int i,j; - const char *mtype,*proto,*port,*addr,*number; + const char *mtype,*proto,*rtp_port,*rtp_addr,*number; const char *ice_ufrag, *ice_pwd; 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; - - addr=sdp_message_c_addr_get (msg, -1, 0); - if (addr) - strncpy(desc->addr,addr,sizeof(desc->addr)); + + rtp_addr=sdp_message_c_addr_get (msg, -1, 0); + if (rtp_addr) + strncpy(desc->addr,rtp_addr,sizeof(desc->addr)); for(j=0;(sbw=sdp_message_bandwidth_get(msg,-1,j))!=NULL;++j){ if (strcasecmp(sbw->b_bwtype,"AS")==0) desc->bandwidth=atoi(sbw->b_bandwidth); } - + /* for each m= line */ for (i=0; !sdp_message_endof_media (msg, i) && iproto=SalProtoUnknown; if (proto){ if (strcasecmp(proto,"RTP/AVP")==0) @@ -450,11 +450,11 @@ int sdp_to_media_description(sdp_message_t *msg, SalMediaDescription *desc, IceS stream->proto=SalProtoRtpSavp; } } - addr = sdp_message_c_addr_get (msg, i, 0); - if (addr != NULL) - strncpy(stream->addr,addr,sizeof(stream->addr)); - if (port) - stream->port=atoi(port); + rtp_addr = sdp_message_c_addr_get (msg, i, 0); + if (rtp_addr != NULL) + strncpy(stream->rtp_addr,rtp_addr,sizeof(stream->rtp_addr)); + if (rtp_port) + stream->rtp_port=atoi(rtp_port); stream->ptime=_sdp_message_get_a_ptime(msg,i); if (strcasecmp("audio", mtype) == 0){ @@ -489,7 +489,24 @@ int sdp_to_media_description(sdp_message_t *msg, SalMediaDescription *desc, IceS pt->send_fmtp ? pt->send_fmtp : ""); } } - + + /* Get media specific RTCP attribute */ + stream->rtcp_port = stream->rtp_port + 1; + snprintf(stream->rtcp_addr, sizeof(stream->rtcp_addr), stream->rtp_addr); + for (j = 0; ((attr = sdp_message_attribute_get(msg, i, j)) != NULL); j++) { + if ((keywordcmp("rtcp", attr->a_att_field) == 0) && (attr->a_att_value != NULL)) { + char tmp[256]; + int nb = sscanf(attr->a_att_value, "%d IN IP4 %s", &stream->rtcp_port, tmp); + if (nb == 1) { + /* SDP rtcp attribute only contains the port */ + } else if (nb == 2) { + strncpy(stream->rtcp_addr, tmp, sizeof(stream->rtcp_addr)); + } else { + ms_warning("sdp has a strange a= line (%s) nb=%i", attr->a_att_value, nb); + } + } + } + /* read crypto lines if any */ if (stream->proto == SalProtoRtpSavp) { int k, valid_count = 0;