static void test_overflow(void){ belle_sdp_session_description_t* sdp; belle_sip_list_t *mds; belle_sdp_media_description_t *vmd; int i; const size_t orig_buffsize=1024; size_t buffsize=orig_buffsize; char *buffer=belle_sip_malloc0(buffsize); size_t offset=0; sdp=belle_sdp_session_description_parse(big_sdp); CU_ASSERT_PTR_NOT_NULL(sdp); mds=belle_sdp_session_description_get_media_descriptions(sdp); CU_ASSERT_PTR_NOT_NULL(mds); CU_ASSERT_PTR_NOT_NULL(mds->next); vmd=(belle_sdp_media_description_t*)mds->next->data; for(i=0;i<16;i++){ belle_sdp_media_description_add_attribute(vmd,belle_sdp_attribute_create("candidate","2 1 UDP 1694498815 82.65.223.97 9078 typ srflx raddr 192.168.0.2 rport 9078")); } CU_ASSERT_EQUAL(belle_sip_object_marshal(BELLE_SIP_OBJECT(sdp),buffer,buffsize,&offset),BELLE_SIP_BUFFER_OVERFLOW); belle_sip_message("marshal size is %i",(int)offset); CU_ASSERT_TRUE(offset==buffsize); belle_sip_object_unref(sdp); belle_sip_free(buffer); }
void belle_sip_multipart_body_handler_add_part(belle_sip_multipart_body_handler_t *obj, belle_sip_body_handler_t *part){ obj->base.expected_size+=part->expected_size+strlen(obj->boundary) + 4; /* add the separator length to the body length as each part start with a separator. 4 is for "--" and "\r\n" */ if (part->headers != NULL) { /* there is a declared header for this part, add its length to the expected total length */ size_t headerStringBufferSize = DEFAULT_HEADER_STRING_SIZE; size_t offset = 0; belle_sip_list_t *headerList = part->headers; part->headerStringBuffer = (char *)belle_sip_malloc(DEFAULT_HEADER_STRING_SIZE); while (headerList != NULL) { size_t offsetBackup=offset; /* we must backup the offset as it will be messed up by the marshal function in case of failure */ belle_sip_error_code returnCode = belle_sip_object_marshal(headerList->data, part->headerStringBuffer, headerStringBufferSize-5, &offset); /* -5 to leave room for carriage returns */ if (returnCode == BELLE_SIP_BUFFER_OVERFLOW) { /* increase buffer size */ offset=offsetBackup; /* restore the offset, no data were written to the buffer */ headerStringBufferSize+=DEFAULT_HEADER_STRING_SIZE; part->headerStringBuffer = (char *)belle_sip_realloc(part->headerStringBuffer, headerStringBufferSize); } else if (returnCode == BELLE_SIP_OK) { /* add the carriage return chars */ part->headerStringBuffer[offset++]='\r'; part->headerStringBuffer[offset++]='\n'; headerList = belle_sip_list_next(headerList); } } part->headerStringBuffer[offset++]='\r'; part->headerStringBuffer[offset++]='\n'; obj->base.expected_size += offset; part->headerStringBuffer[offset++]='\0'; /* null terminate the buffer in order to be able to get it length later using strlen */ } obj->parts=belle_sip_list_append(obj->parts,belle_sip_object_ref(part)); }
static char * belle_sip_object_to_alloc_string(belle_sip_object_t *obj, int size_hint){ char *buf=belle_sip_malloc(size_hint); size_t offset=0; belle_sip_error_code error = belle_sip_object_marshal(obj,buf,size_hint-1,&offset); obj->vptr->tostring_bufsize_hint=size_hint; if (error==BELLE_SIP_BUFFER_OVERFLOW){ belle_sip_message("belle_sip_object_to_alloc_string(): hint buffer was too short while doing to_string() for %s, retrying", obj->vptr->type_name); belle_sip_free(buf); return belle_sip_object_to_alloc_string(obj,2*size_hint); } buf=belle_sip_realloc(buf,offset+1); buf[offset]='\0'; return buf; }
char* belle_sip_object_to_string(void* _obj) { belle_sip_object_t *obj=BELLE_SIP_OBJECT(_obj); if (obj->vptr->tostring_bufsize_hint!=0){ return belle_sip_object_to_alloc_string(obj,obj->vptr->tostring_bufsize_hint); }else{ char buff[BELLE_SIP_MAX_TO_STRING_SIZE]; size_t offset=0; belle_sip_error_code error = belle_sip_object_marshal(obj,buff,sizeof(buff),&offset); if (error==BELLE_SIP_BUFFER_OVERFLOW){ belle_sip_message("belle_sip_object_to_string(): temporary buffer is too short while doing to_string() for %s, retrying", obj->vptr->type_name); return belle_sip_object_to_alloc_string(obj,get_hint_size(2*offset)); } buff[offset]='\0'; obj->vptr->tostring_bufsize_hint=get_hint_size(2*offset); return belle_sip_strdup(buff); } }
char *sal_address_as_string_uri_only(const SalAddress *addr){ belle_sip_header_address_t* header_addr = BELLE_SIP_HEADER_ADDRESS(addr); belle_sip_uri_t* sip_uri = belle_sip_header_address_get_uri(header_addr); belle_generic_uri_t* absolute_uri = belle_sip_header_address_get_absolute_uri(header_addr); char tmp[1024]={0}; size_t off=0; belle_sip_object_t* uri; if (sip_uri) { uri=(belle_sip_object_t*)sip_uri; } else if (absolute_uri) { uri=(belle_sip_object_t*)absolute_uri; } else { ms_error("Cannot generate string for addr [%p] with null uri",addr); return NULL; } belle_sip_object_marshal(uri,tmp,sizeof(tmp),&off); return ms_strdup(tmp); }
static int set_sdp(belle_sip_message_t *msg,belle_sdp_session_description_t* session_desc) { belle_sip_header_content_type_t* content_type ; belle_sip_header_content_length_t* content_length; belle_sip_error_code error = BELLE_SIP_BUFFER_OVERFLOW; size_t length = 0; if (session_desc) { size_t bufLen = 2048; size_t hardlimit = 16*1024; /* 16k SDP limit seems reasonable */ char* buff = belle_sip_malloc(bufLen); content_type = belle_sip_header_content_type_create("application","sdp"); /* try to marshal the description. This could go higher than 2k so we iterate */ while( error != BELLE_SIP_OK && bufLen <= hardlimit && buff != NULL){ error = belle_sip_object_marshal(BELLE_SIP_OBJECT(session_desc),buff,bufLen,&length); if( error != BELLE_SIP_OK ){ bufLen *= 2; length = 0; buff = belle_sip_realloc(buff,bufLen); } } /* give up if hard limit reached */ if (error != BELLE_SIP_OK || buff == NULL) { ms_error("Buffer too small (%d) or not enough memory, giving up SDP", (int)bufLen); return -1; } content_length = belle_sip_header_content_length_create(length); belle_sip_message_add_header(msg,BELLE_SIP_HEADER(content_type)); belle_sip_message_add_header(msg,BELLE_SIP_HEADER(content_length)); belle_sip_message_assign_body(msg,buff,length); return 0; } else { return -1; } }
static int set_sdp(belle_sip_message_t *msg,belle_sdp_session_description_t* session_desc) { belle_sip_header_content_type_t* content_type ; belle_sip_header_content_length_t* content_length; belle_sip_error_code error = BELLE_SIP_OK; size_t length = 0; char buff[2048]; if (session_desc) { content_type = belle_sip_header_content_type_create("application","sdp"); error = belle_sip_object_marshal(BELLE_SIP_OBJECT(session_desc),buff,sizeof(buff),&length); if (error != BELLE_SIP_OK) { ms_error("Buffer too small or sdp too big"); return -1; } content_length= belle_sip_header_content_length_create(length); belle_sip_message_add_header(msg,BELLE_SIP_HEADER(content_type)); belle_sip_message_add_header(msg,BELLE_SIP_HEADER(content_length)); belle_sip_message_set_body(msg,buff,length); return 0; } else { return -1; } }
static void stream_description_to_sdp ( belle_sdp_session_description_t *session_desc, const SalMediaDescription *md, const SalStreamDescription *stream ) { belle_sdp_mime_parameter_t* mime_param; belle_sdp_media_description_t* media_desc; int j; MSList* pt_it; PayloadType* pt; char buffer[1024]; char* dir=NULL; const char *rtp_addr; const char *rtcp_addr; int rtp_port; int rtcp_port; bool_t different_rtp_and_rtcp_addr; rtp_addr=stream->rtp_addr; rtcp_addr=stream->rtcp_addr; rtp_port=stream->rtp_port; rtcp_port=stream->rtcp_port; media_desc = belle_sdp_media_description_create ( sal_stream_description_get_type_as_string(stream) ,stream->rtp_port ,1 ,sal_media_proto_to_string ( stream->proto ) ,NULL ); if (stream->payloads) { for ( pt_it=stream->payloads; pt_it!=NULL; pt_it=pt_it->next ) { pt= ( PayloadType* ) pt_it->data; mime_param= belle_sdp_mime_parameter_create ( pt->mime_type , payload_type_get_number ( pt ) , pt->clock_rate ,stream->type==SalAudio?1:-1 ); belle_sdp_mime_parameter_set_parameters ( mime_param,pt->recv_fmtp ); if ( stream->ptime>0 ) { belle_sdp_mime_parameter_set_ptime ( mime_param,stream->ptime ); } belle_sdp_media_description_append_values_from_mime_parameter ( media_desc,mime_param ); belle_sip_object_unref ( mime_param ); } } else { /* to comply with SDP we cannot have an empty payload type number list */ /* as it happens only when mline is declined with a zero port, it does not matter to put whatever codec*/ belle_sip_list_t* format = belle_sip_list_append(NULL,0); belle_sdp_media_set_media_formats(belle_sdp_media_description_get_media(media_desc),format); } /*only add a c= line within the stream description if address are differents*/ if (rtp_addr[0]!='\0' && strcmp(rtp_addr,md->addr)!=0){ bool_t inet6; if (strchr(rtp_addr,':')!=NULL){ inet6=TRUE; }else inet6=FALSE; belle_sdp_media_description_set_connection(media_desc,belle_sdp_connection_create("IN", inet6 ? "IP6" : "IP4", rtp_addr)); } if ( stream->bandwidth>0 ) belle_sdp_media_description_set_bandwidth ( media_desc,"AS",stream->bandwidth ); if ( stream->proto == SalProtoRtpSavp ) { /* add crypto lines */ for ( j=0; j<SAL_CRYPTO_ALGO_MAX; j++ ) { switch ( stream->crypto[j].algo ) { case AES_128_SHA1_80: snprintf ( buffer, sizeof ( buffer ), "%d %s inline:%s", stream->crypto[j].tag, "AES_CM_128_HMAC_SHA1_80", stream->crypto[j].master_key ); belle_sdp_media_description_add_attribute ( media_desc,belle_sdp_attribute_create ( "crypto",buffer ) ); break; case AES_128_SHA1_32: snprintf ( buffer, sizeof ( buffer ), "%d %s inline:%s", stream->crypto[j].tag, "AES_CM_128_HMAC_SHA1_32", stream->crypto[j].master_key ); belle_sdp_media_description_add_attribute ( media_desc,belle_sdp_attribute_create ( "crypto",buffer ) ); break; case AES_128_NO_AUTH: ms_warning ( "Unsupported crypto suite: AES_128_NO_AUTH" ); break; case NO_CIPHER_SHA1_80: ms_warning ( "Unsupported crypto suite: NO_CIPHER_SHA1_80" ); break; default: j = SAL_CRYPTO_ALGO_MAX; /* no break */ } } } switch ( stream->dir ) { case SalStreamSendRecv: /*dir="sendrecv";*/ dir=NULL; break; case SalStreamRecvOnly: dir="recvonly"; break; case SalStreamSendOnly: dir="sendonly"; break; case SalStreamInactive: dir="inactive"; break; } if ( dir ) belle_sdp_media_description_add_attribute ( media_desc,belle_sdp_attribute_create ( dir,NULL ) ); 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) { snprintf(buffer, sizeof(buffer), "%u IN IP4 %s", rtcp_port, rtcp_addr); } else { snprintf(buffer, sizeof(buffer), "%u",rtcp_port); } belle_sdp_media_description_add_attribute(media_desc,belle_sdp_attribute_create ("rtcp",buffer)); } } if (stream->ice_completed == TRUE) { belle_sdp_media_description_add_attribute(media_desc,belle_sdp_attribute_create ("nortpproxy","yes")); } if (stream->ice_mismatch == TRUE) { belle_sdp_media_description_add_attribute(media_desc,belle_sdp_attribute_create ("ice-mismatch",NULL)); } else { if (rtp_port != 0) { if (stream->ice_pwd[0] != '\0') belle_sdp_media_description_add_attribute(media_desc,belle_sdp_attribute_create ("ice-pwd",stream->ice_pwd)); if (stream->ice_ufrag[0] != '\0') belle_sdp_media_description_add_attribute(media_desc,belle_sdp_attribute_create ("ice-ufrag",stream->ice_ufrag)); add_ice_candidates(media_desc,stream); add_ice_remote_candidates(media_desc,stream); } } if (stream->rtcp_xr.enabled == TRUE) { char sastr[1024] = {0}; char mastr[1024] = {0}; size_t saoff = 0; size_t maoff = 0; const belle_sdp_attribute_t *session_attribute = belle_sdp_session_description_get_attribute(session_desc, "rtcp-xr"); belle_sdp_attribute_t *media_attribute; if (session_attribute != NULL) { belle_sip_object_marshal((belle_sip_object_t*)session_attribute, sastr, sizeof(sastr), &saoff); } media_attribute = create_rtcp_xr_attribute(&stream->rtcp_xr); if (media_attribute != NULL) { belle_sip_object_marshal((belle_sip_object_t*)media_attribute, mastr, sizeof(mastr), &maoff); } if (strcmp(sastr, mastr) != 0) { belle_sdp_media_description_add_attribute(media_desc, media_attribute); } else { belle_sip_object_unref((belle_sip_object_t*)media_attribute); } } belle_sdp_session_description_add_media_description(session_desc, media_desc); }
static void _send_message(belle_sip_channel_t *obj){ char buffer[belle_sip_network_buffer_size]; size_t len=0; belle_sip_error_code error=BELLE_SIP_OK; belle_sip_message_t *msg=obj->cur_out_message; belle_sip_body_handler_t *bh=belle_sip_message_get_body_handler(msg); size_t body_len=bh ? belle_sip_body_handler_get_size(bh) : 0; int sendret; size_t off; int ret; if (obj->ewouldblock_buffer){ sendret=send_buffer(obj,(const char*)obj->ewouldblock_buffer+obj->ewouldblock_offset,obj->ewouldblock_size-obj->ewouldblock_offset); if (sendret>0){ obj->ewouldblock_offset+=sendret; if (obj->ewouldblock_offset==obj->ewouldblock_size){ free_ewouldblock_buffer(obj); } return; /*we prefer poll again to be sure we can write*/ }else if (belle_sip_error_code_is_would_block(-sendret)) { /*we got an ewouldblock again. Nothing to do, we'll be called later in order to retry*/ return; }else {/*error or disconnection case*/ goto done; } } if (obj->out_state==OUTPUT_STREAM_SENDING_HEADERS){ BELLE_SIP_INVOKE_LISTENERS_ARG1_ARG2(obj->listeners,belle_sip_channel_listener_t,on_sending,obj,msg); check_content_length(msg,body_len); error=belle_sip_object_marshal((belle_sip_object_t*)msg,buffer,sizeof(buffer)-1,&len); if (error!=BELLE_SIP_OK) { belle_sip_error("channel [%p] _send_message: marshaling failed.",obj); goto done; } /*send the headers and eventually the body if it fits in our buffer*/ if (bh){ size_t max_body_len=sizeof(buffer)-1-len; if (body_len>0 && body_len<=max_body_len){ /*if size is known and fits into our buffer, send together with headers*/ belle_sip_body_handler_begin_transfer(bh); do{ max_body_len=sizeof(buffer)-1-len; ret=belle_sip_body_handler_send_chunk(bh,msg,(uint8_t*)buffer+len,&max_body_len); len+=max_body_len; }while(ret==BELLE_SIP_CONTINUE); belle_sip_body_handler_end_transfer(bh); }else{ if (body_len==0){ belle_sip_fatal("Sending bodies whose size is not known must be done in chunked mode, which is not supported yet."); } belle_sip_body_handler_begin_transfer(bh); obj->out_state=OUTPUT_STREAM_SENDING_BODY; } } off=0; do{ sendret=send_buffer(obj,buffer+off,len-off); if (sendret>0){ off+=sendret; if (off==len){ break; } }else if (belle_sip_error_code_is_would_block(-sendret)) { handle_ewouldblock(obj,buffer+off,len-off); return; }else {/*error or disconnection case*/ goto done; } }while(1); } if (obj->out_state==OUTPUT_STREAM_SENDING_BODY){ do{ size_t chunk_len=sizeof(buffer)-1; ret=belle_sip_body_handler_send_chunk(bh,msg,(uint8_t*)buffer,&chunk_len); if (chunk_len!=0){ off=0; do{ sendret=send_buffer(obj,buffer+off,chunk_len-off); if (sendret>0){ off+=sendret; if (off==chunk_len){ break; } }else if (belle_sip_error_code_is_would_block(-sendret)) { handle_ewouldblock(obj,buffer+off,chunk_len-off); return; }else {/*error or disconnection case*/ goto done; } }while(1); } }while(ret==BELLE_SIP_CONTINUE); belle_sip_body_handler_end_transfer(bh); } done: /*we get ready to send another message*/ belle_sip_source_set_events((belle_sip_source_t*)obj,BELLE_SIP_EVENT_READ|BELLE_SIP_EVENT_ERROR); free_ewouldblock_buffer(obj); obj->out_state=OUTPUT_STREAM_IDLE; belle_sip_object_unref(obj->cur_out_message); obj->cur_out_message=NULL; }
static void stream_description_to_sdp ( belle_sdp_session_description_t *session_desc, const SalMediaDescription *md, const SalStreamDescription *stream ) { belle_sdp_mime_parameter_t* mime_param; belle_sdp_media_description_t* media_desc; int j; MSList* pt_it; PayloadType* pt; char buffer[1024]; char* dir=NULL; const char *rtp_addr; const char *rtcp_addr; int rtp_port; int rtcp_port; bool_t different_rtp_and_rtcp_addr; rtp_addr=stream->rtp_addr; rtcp_addr=stream->rtcp_addr; rtp_port=stream->rtp_port; rtcp_port=stream->rtcp_port; media_desc = belle_sdp_media_description_create ( sal_stream_description_get_type_as_string(stream) ,stream->rtp_port ,1 ,sal_media_proto_to_string ( stream->proto ) ,NULL ); if (stream->payloads) { for ( pt_it=stream->payloads; pt_it!=NULL; pt_it=pt_it->next ) { pt= ( PayloadType* ) pt_it->data; mime_param= belle_sdp_mime_parameter_create ( pt->mime_type , payload_type_get_number ( pt ) , pt->clock_rate , pt->channels>0 ? pt->channels : -1 ); belle_sdp_mime_parameter_set_parameters ( mime_param,pt->recv_fmtp ); if ( stream->ptime>0 ) { belle_sdp_mime_parameter_set_ptime ( mime_param,stream->ptime ); } belle_sdp_media_description_append_values_from_mime_parameter ( media_desc,mime_param ); belle_sip_object_unref ( mime_param ); } } else { /* to comply with SDP we cannot have an empty payload type number list */ /* as it happens only when mline is declined with a zero port, it does not matter to put whatever codec*/ belle_sip_list_t* format = belle_sip_list_append(NULL,0); belle_sdp_media_set_media_formats(belle_sdp_media_description_get_media(media_desc),format); } /*only add a c= line within the stream description if address are differents*/ if (rtp_addr[0]!='\0' && strcmp(rtp_addr,md->addr)!=0){ bool_t inet6; belle_sdp_connection_t *connection; if (strchr(rtp_addr,':')!=NULL){ inet6=TRUE; }else inet6=FALSE; connection = belle_sdp_connection_create("IN", inet6 ? "IP6" : "IP4", rtp_addr); if (ms_is_multicast(rtp_addr)) { /*remove session cline in case of multicast*/ belle_sdp_session_description_set_connection(session_desc,NULL); if (inet6 == FALSE) belle_sdp_connection_set_ttl(connection,stream->ttl); } belle_sdp_media_description_set_connection(media_desc,connection); } if ( stream->bandwidth>0 ) belle_sdp_media_description_set_bandwidth ( media_desc,"AS",stream->bandwidth ); if ((stream->proto == SalProtoRtpSavpf) || (stream->proto == SalProtoRtpSavp)) { /* add crypto lines */ for ( j=0; j<SAL_CRYPTO_ALGO_MAX; j++ ) { MSCryptoSuiteNameParams desc; if (ms_crypto_suite_to_name_params(stream->crypto[j].algo,&desc)==0){ if (desc.params) snprintf ( buffer, sizeof ( buffer )-1, "%d %s inline:%s %s", stream->crypto[j].tag, desc.name, stream->crypto[j].master_key,desc.params); else snprintf ( buffer, sizeof ( buffer )-1, "%d %s inline:%s", stream->crypto[j].tag, desc.name, stream->crypto[j].master_key ); belle_sdp_media_description_add_attribute( media_desc,belle_sdp_attribute_create ("crypto", buffer)); }else break; } } /* insert DTLS session attribute if needed */ if ((stream->proto == SalProtoUdpTlsRtpSavpf) || (stream->proto == SalProtoUdpTlsRtpSavp)) { char* ssrc_attribute = ms_strdup_printf("%u cname:%s",htonl(stream->rtp_ssrc),stream->rtcp_cname); if ((stream->dtls_role != SalDtlsRoleInvalid) && (strlen(stream->dtls_fingerprint)>0)) { switch(stream->dtls_role) { case SalDtlsRoleIsClient: belle_sdp_media_description_add_attribute(media_desc, belle_sdp_attribute_create("setup","active")); break; case SalDtlsRoleIsServer: belle_sdp_media_description_add_attribute(media_desc, belle_sdp_attribute_create("setup","passive")); break; case SalDtlsRoleUnset: default: belle_sdp_media_description_add_attribute(media_desc, belle_sdp_attribute_create("setup","actpass")); break; } belle_sdp_media_description_add_attribute(media_desc, belle_sdp_attribute_create("fingerprint",stream->dtls_fingerprint)); } belle_sdp_media_description_add_attribute(media_desc, belle_sdp_attribute_create("ssrc",ssrc_attribute)); /* truc de Jehan a virer? */ ms_free(ssrc_attribute); } switch ( stream->dir ) { case SalStreamSendRecv: /*dir="sendrecv";*/ dir=NULL; break; case SalStreamRecvOnly: dir="recvonly"; break; case SalStreamSendOnly: dir="sendonly"; break; case SalStreamInactive: dir="inactive"; break; } if ( dir ) belle_sdp_media_description_add_attribute ( media_desc,belle_sdp_attribute_create ( dir,NULL ) ); 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) { snprintf(buffer, sizeof(buffer), "%u IN IP4 %s", rtcp_port, rtcp_addr); } else { snprintf(buffer, sizeof(buffer), "%u",rtcp_port); } belle_sdp_media_description_add_attribute(media_desc,belle_sdp_attribute_create ("rtcp",buffer)); } } if (stream->ice_completed == TRUE) { belle_sdp_media_description_add_attribute(media_desc,belle_sdp_attribute_create ("nortpproxy","yes")); } if (stream->ice_mismatch == TRUE) { belle_sdp_media_description_add_attribute(media_desc,belle_sdp_attribute_create ("ice-mismatch",NULL)); } else { if (rtp_port != 0) { if (stream->ice_pwd[0] != '\0') belle_sdp_media_description_add_attribute(media_desc,belle_sdp_attribute_create ("ice-pwd",stream->ice_pwd)); if (stream->ice_ufrag[0] != '\0') belle_sdp_media_description_add_attribute(media_desc,belle_sdp_attribute_create ("ice-ufrag",stream->ice_ufrag)); add_ice_candidates(media_desc,stream); add_ice_remote_candidates(media_desc,stream); } } if ((rtp_port != 0) && ((stream->proto == SalProtoRtpAvpf) || (stream->proto == SalProtoRtpSavpf))) { add_rtcp_fb_attributes(media_desc, md, stream); } if ((rtp_port != 0) && (stream->rtcp_xr.enabled == TRUE)) { char sastr[1024] = {0}; char mastr[1024] = {0}; size_t saoff = 0; size_t maoff = 0; const belle_sdp_attribute_t *session_attribute = belle_sdp_session_description_get_attribute(session_desc, "rtcp-xr"); belle_sdp_attribute_t *media_attribute; if (session_attribute != NULL) { belle_sip_object_marshal((belle_sip_object_t*)session_attribute, sastr, sizeof(sastr), &saoff); } media_attribute = create_rtcp_xr_attribute(&stream->rtcp_xr); if (media_attribute != NULL) { belle_sip_object_marshal((belle_sip_object_t*)media_attribute, mastr, sizeof(mastr), &maoff); } if (strcmp(sastr, mastr) != 0) { belle_sdp_media_description_add_attribute(media_desc, media_attribute); } else { belle_sip_object_unref((belle_sip_object_t*)media_attribute); } } /* * rfc5576 * 4.1. The "ssrc" Media Attribute * <ssrc-id> is the synchronization source (SSRC) ID of the * source being described, interpreted as a 32-bit unsigned integer in * network byte order and represented in decimal.*/ belle_sdp_session_description_add_media_description(session_desc, media_desc); }
char *sal_address_as_string(const SalAddress *addr){ char tmp[1024]={0}; size_t off=0; belle_sip_object_marshal((belle_sip_object_t*)addr,tmp,sizeof(tmp),&off); return ms_strdup(tmp); }