static void test_rtcp_fb_attribute(void) {
	belle_sdp_rtcp_fb_attribute_t* lAttribute;

	lAttribute = BELLE_SDP_RTCP_FB_ATTRIBUTE(attribute_parse_marshall_parse_clone("a=rtcp-fb:* ack"));
	CU_ASSERT_STRING_EQUAL(belle_sdp_attribute_get_name(BELLE_SDP_ATTRIBUTE(lAttribute)), "rtcp-fb");
	CU_ASSERT_EQUAL(belle_sdp_rtcp_fb_attribute_get_id(lAttribute), -1);
	CU_ASSERT_EQUAL(belle_sdp_rtcp_fb_attribute_get_type(lAttribute), BELLE_SDP_RTCP_FB_ACK);
	CU_ASSERT_EQUAL(belle_sdp_rtcp_fb_attribute_get_param(lAttribute), BELLE_SDP_RTCP_FB_NONE);
	belle_sip_object_unref(BELLE_SIP_OBJECT(lAttribute));

	lAttribute = BELLE_SDP_RTCP_FB_ATTRIBUTE(attribute_parse_marshall_parse_clone("a=rtcp-fb:98 nack rpsi"));
	CU_ASSERT_STRING_EQUAL(belle_sdp_attribute_get_name(BELLE_SDP_ATTRIBUTE(lAttribute)), "rtcp-fb");
	CU_ASSERT_EQUAL(belle_sdp_rtcp_fb_attribute_get_id(lAttribute), 98);
	CU_ASSERT_EQUAL(belle_sdp_rtcp_fb_attribute_get_type(lAttribute), BELLE_SDP_RTCP_FB_NACK);
	CU_ASSERT_EQUAL(belle_sdp_rtcp_fb_attribute_get_param(lAttribute), BELLE_SDP_RTCP_FB_RPSI);
	belle_sip_object_unref(BELLE_SIP_OBJECT(lAttribute));

	lAttribute = BELLE_SDP_RTCP_FB_ATTRIBUTE(attribute_parse_marshall_parse_clone("a=rtcp-fb:* trr-int 3"));
	CU_ASSERT_STRING_EQUAL(belle_sdp_attribute_get_name(BELLE_SDP_ATTRIBUTE(lAttribute)), "rtcp-fb");
	CU_ASSERT_EQUAL(belle_sdp_rtcp_fb_attribute_get_id(lAttribute), -1);
	CU_ASSERT_EQUAL(belle_sdp_rtcp_fb_attribute_get_type(lAttribute), BELLE_SDP_RTCP_FB_TRR_INT);
	CU_ASSERT_EQUAL(belle_sdp_rtcp_fb_attribute_get_trr_int(lAttribute), 3);
	belle_sip_object_unref(BELLE_SIP_OBJECT(lAttribute));

	lAttribute = BELLE_SDP_RTCP_FB_ATTRIBUTE(attribute_parse_marshall_parse_clone("a=rtcp-fb:103 ccm fir"));
	CU_ASSERT_STRING_EQUAL(belle_sdp_attribute_get_name(BELLE_SDP_ATTRIBUTE(lAttribute)), "rtcp-fb");
	CU_ASSERT_EQUAL(belle_sdp_rtcp_fb_attribute_get_id(lAttribute), 103);
	CU_ASSERT_EQUAL(belle_sdp_rtcp_fb_attribute_get_type(lAttribute), BELLE_SDP_RTCP_FB_CCM);
	CU_ASSERT_EQUAL(belle_sdp_rtcp_fb_attribute_get_param(lAttribute), BELLE_SDP_RTCP_FB_FIR);
	belle_sip_object_unref(BELLE_SIP_OBJECT(lAttribute));
}
static void test_attribute_2(void) {
	belle_sdp_attribute_t* lAttribute = attribute_parse_marshall_parse_clone("a=ice-pwd:31ec21eb38b2ec6d36e8dc7b");
	CU_ASSERT_STRING_EQUAL(belle_sdp_attribute_get_name(lAttribute), "ice-pwd");
	CU_ASSERT_STRING_EQUAL(belle_sdp_attribute_get_value(lAttribute), "31ec21eb38b2ec6d36e8dc7b");
	CU_ASSERT_TRUE(belle_sdp_attribute_has_value(lAttribute));
	belle_sip_object_unref(BELLE_SIP_OBJECT(lAttribute));
}
static void test_attribute(void) {
	belle_sdp_attribute_t* lAttribute = attribute_parse_marshall_parse_clone("a=rtpmap:101 telephone-event/8000");
	CU_ASSERT_STRING_EQUAL(belle_sdp_attribute_get_name(lAttribute), "rtpmap");
	CU_ASSERT_STRING_EQUAL(belle_sdp_attribute_get_value(lAttribute), "101 telephone-event/8000");
	CU_ASSERT_TRUE(belle_sdp_attribute_has_value(lAttribute));
	belle_sip_object_unref(BELLE_SIP_OBJECT(lAttribute));
}
示例#4
0
static bool_t sdp_parse_rtcp_fb_parameters(belle_sdp_media_description_t *media_desc, SalStreamDescription *stream) {
	belle_sip_list_t *it;
	belle_sdp_attribute_t *attribute;
	belle_sdp_rtcp_fb_attribute_t *fb_attribute;
	MSList *pt_it;
	PayloadType *pt;
	int8_t pt_num;
    bool_t retval = FALSE;
    
	/* Handle rtcp-fb attributes that concern all payload types. */
	for (it = belle_sdp_media_description_get_attributes(media_desc); it != NULL; it = it->next) {
		attribute = BELLE_SDP_ATTRIBUTE(it->data);
		if (keywordcmp("rtcp-fb", belle_sdp_attribute_get_name(attribute)) == 0) {
			fb_attribute = BELLE_SDP_RTCP_FB_ATTRIBUTE(attribute);
			if (belle_sdp_rtcp_fb_attribute_get_id(fb_attribute) == -1) {
				for (pt_it = stream->payloads; pt_it != NULL; pt_it = pt_it->next) {
					pt = (PayloadType *)pt_it->data;
					apply_rtcp_fb_attribute_to_payload(fb_attribute, stream, pt);
                    retval = TRUE;
				}
			}
		}
	}

	/* Handle rtcp-fb attributes that are specefic to a payload type. */
	for (it = belle_sdp_media_description_get_attributes(media_desc); it != NULL; it = it->next) {
		attribute = BELLE_SDP_ATTRIBUTE(it->data);
		if (keywordcmp("rtcp-fb", belle_sdp_attribute_get_name(attribute)) == 0) {
			fb_attribute = BELLE_SDP_RTCP_FB_ATTRIBUTE(attribute);
			pt_num = belle_sdp_rtcp_fb_attribute_get_id(fb_attribute);
			for (pt_it = stream->payloads; pt_it != NULL; pt_it = pt_it->next) {
				pt = (PayloadType *)pt_it->data;
                retval = TRUE;
				if (payload_type_get_number(pt) == (int)pt_num) {
					apply_rtcp_fb_attribute_to_payload(fb_attribute, stream, pt);
				}
			}
		}
	}
    return retval;
}
示例#5
0
static void sdp_parse_media_crypto_parameters(belle_sdp_media_description_t *media_desc, SalStreamDescription *stream) {
	belle_sip_list_t *attribute_it;
	belle_sdp_attribute_t *attribute;
	char tmp[256], tmp2[256], parameters[256]={0};
	int valid_count = 0;
	int nb;

	memset ( &stream->crypto, 0, sizeof ( stream->crypto ) );
	for ( attribute_it=belle_sdp_media_description_get_attributes ( media_desc )
						; valid_count < SAL_CRYPTO_ALGO_MAX && attribute_it!=NULL;
			attribute_it=attribute_it->next ) {
		attribute=BELLE_SDP_ATTRIBUTE ( attribute_it->data );

		if ( keywordcmp ( "crypto",belle_sdp_attribute_get_name ( attribute ) ) ==0 && belle_sdp_attribute_get_value ( attribute ) !=NULL ) {
			nb = sscanf ( belle_sdp_attribute_get_value ( attribute ), "%d %256s inline:%256s %256s",
							&stream->crypto[valid_count].tag,
							tmp,
							tmp2, parameters );
			
			if ( nb >= 3 ) {
				MSCryptoSuite cs;
				MSCryptoSuiteNameParams np;

				np.name=tmp;
				np.params=parameters[0]!='\0' ? parameters : NULL;
				cs=ms_crypto_suite_build_from_name_params(&np);
				if (cs==MS_CRYPTO_SUITE_INVALID){
					ms_warning ( "Failed to parse crypto-algo: '%s'", tmp );
					stream->crypto[valid_count].algo = 0;
				}else{
					char *sep;
					strncpy ( stream->crypto[valid_count].master_key, tmp2, sizeof(stream->crypto[valid_count].master_key)-1 );
					sep=strchr(stream->crypto[valid_count].master_key,'|');
					if (sep) *sep='\0';
					stream->crypto[valid_count].algo = cs;
					ms_message ( "Found valid crypto line (tag:%d algo:'%s' key:'%s'",
									stream->crypto[valid_count].tag,
									tmp,
									stream->crypto[valid_count].master_key );
					valid_count++;
				}
			}else{
				ms_warning ( "sdp has a strange a= line (%s) nb=%i",belle_sdp_attribute_get_value ( attribute ),nb );
			}
		}
	}
	ms_message("Found: %d valid crypto lines", valid_count );
}
示例#6
0
static void sdp_parse_media_ice_parameters(belle_sdp_media_description_t *media_desc, SalStreamDescription *stream) {
	belle_sip_list_t *attribute_it;
	belle_sdp_attribute_t *attribute;
	const char *att_name;
	const char *value;
	int nb_ice_candidates = 0;

	for (attribute_it = belle_sdp_media_description_get_attributes(media_desc); attribute_it != NULL; attribute_it=attribute_it->next) {
		attribute=BELLE_SDP_ATTRIBUTE(attribute_it->data);
		att_name = belle_sdp_attribute_get_name(attribute);
		value = belle_sdp_attribute_get_value(attribute);

		if (	(nb_ice_candidates < sizeof (stream->ice_candidates)/sizeof(SalIceCandidate))
				&& (keywordcmp("candidate", att_name) == 0)
				&& (value != NULL)) {
			SalIceCandidate *candidate = &stream->ice_candidates[nb_ice_candidates];
			char proto[4];
			int nb = sscanf(value, "%s %u %3s %u %s %d typ %s raddr %s rport %d",
				candidate->foundation, &candidate->componentID, proto, &candidate->priority, candidate->addr, &candidate->port,
				candidate->type, candidate->raddr, &candidate->rport);
			if (strcasecmp("udp",proto)==0 && ((nb == 7) || (nb == 9))) nb_ice_candidates++;
			else memset(candidate, 0, sizeof(*candidate));
		} else if ((keywordcmp("remote-candidates", att_name) == 0) && (value != NULL)) {
			SalIceRemoteCandidate candidate;
			unsigned int componentID;
			int offset;
			const char *ptr = value;
			const char *endptr = value + strlen(ptr);
			while (3 == sscanf(ptr, "%u %s %u%n", &componentID, candidate.addr, &candidate.port, &offset)) {
				if ((componentID > 0) && (componentID <= SAL_MEDIA_DESCRIPTION_MAX_ICE_REMOTE_CANDIDATES)) {
					SalIceRemoteCandidate *remote_candidate = &stream->ice_remote_candidates[componentID - 1];
					strncpy(remote_candidate->addr, candidate.addr, sizeof(remote_candidate->addr)-1);
					remote_candidate->port = candidate.port;
				}
				ptr += offset;
				if (ptr < endptr) {
					if (ptr[offset] == ' ') ptr += 1;
				} else break;
			}
		} else if ((keywordcmp("ice-ufrag", att_name) == 0) && (value != NULL)) {
			strncpy(stream->ice_ufrag, value, sizeof(stream->ice_ufrag)-1);
		} else if ((keywordcmp("ice-pwd", att_name) == 0) && (value != NULL)) {
			strncpy(stream->ice_pwd, value, sizeof(stream->ice_pwd) -1);
		} else if (keywordcmp("ice-mismatch", att_name) == 0) {
			stream->ice_mismatch = TRUE;
		}
	}
}
示例#7
0
static void sdp_parse_media_crypto_parameters(belle_sdp_media_description_t *media_desc, SalStreamDescription *stream) {
	belle_sip_list_t *attribute_it;
	belle_sdp_attribute_t *attribute;
	char tmp[256], tmp2[256];
	int valid_count = 0;
	int nb;

	memset ( &stream->crypto, 0, sizeof ( stream->crypto ) );
	for ( attribute_it=belle_sdp_media_description_get_attributes ( media_desc )
						; valid_count < SAL_CRYPTO_ALGO_MAX && attribute_it!=NULL;
			attribute_it=attribute_it->next ) {
		attribute=BELLE_SDP_ATTRIBUTE ( attribute_it->data );

		if ( keywordcmp ( "crypto",belle_sdp_attribute_get_name ( attribute ) ) ==0 && belle_sdp_attribute_get_value ( attribute ) !=NULL ) {
			nb = sscanf ( belle_sdp_attribute_get_value ( attribute ), "%d %256s inline:%256s",
							&stream->crypto[valid_count].tag,
							tmp,
							tmp2 );
			ms_message ( "Found valid crypto line (tag:%d algo:'%s' key:'%s'",
							stream->crypto[valid_count].tag,
							tmp,
							tmp2 );
			if ( nb == 3 ) {
				if ( keywordcmp ( "AES_CM_128_HMAC_SHA1_80",tmp ) == 0 )
					stream->crypto[valid_count].algo = AES_128_SHA1_80;
				else if ( keywordcmp ( "AES_CM_128_HMAC_SHA1_32",tmp ) == 0 )
					stream->crypto[valid_count].algo = AES_128_SHA1_32;
				else {
					ms_warning ( "Failed to parse crypto-algo: '%s'", tmp );
					stream->crypto[valid_count].algo = 0;
				}
				if ( stream->crypto[valid_count].algo ) {
					strncpy ( stream->crypto[valid_count].master_key, tmp2, 41 );
					stream->crypto[valid_count].master_key[40] = '\0';
					ms_message ( "Found valid crypto line (tag:%d algo:'%s' key:'%s'",
									stream->crypto[valid_count].tag,
									tmp,
									stream->crypto[valid_count].master_key );
					valid_count++;
				}
			} else {
				ms_warning ( "sdp has a strange a= line (%s) nb=%i",belle_sdp_attribute_get_value ( attribute ),nb );
			}
		}
	}
	ms_message ( "Found: %d valid crypto lines", valid_count );
}
static void test_rtcp_xr_attribute(void) {
	belle_sdp_rtcp_xr_attribute_t* lAttribute;

	lAttribute = BELLE_SDP_RTCP_XR_ATTRIBUTE(attribute_parse_marshall_parse_clone("a=rtcp-xr"));
	CU_ASSERT_STRING_EQUAL(belle_sdp_attribute_get_name(BELLE_SDP_ATTRIBUTE(lAttribute)), "rtcp-xr");
	CU_ASSERT_TRUE(belle_sdp_rtcp_xr_attribute_has_stat_summary(lAttribute) == FALSE);
	CU_ASSERT_TRUE(belle_sdp_rtcp_xr_attribute_has_voip_metrics(lAttribute) == FALSE);
	belle_sip_object_unref(BELLE_SIP_OBJECT(lAttribute));

	lAttribute = BELLE_SDP_RTCP_XR_ATTRIBUTE(attribute_parse_marshall_parse_clone("a=rtcp-xr:rcvr-rtt=all:10"));
	CU_ASSERT_STRING_EQUAL(belle_sdp_attribute_get_name(BELLE_SDP_ATTRIBUTE(lAttribute)), "rtcp-xr");
	CU_ASSERT_STRING_EQUAL(belle_sdp_rtcp_xr_attribute_get_rcvr_rtt_mode(lAttribute), "all");
	CU_ASSERT_EQUAL(belle_sdp_rtcp_xr_attribute_get_rcvr_rtt_max_size(lAttribute), 10);
	belle_sip_object_unref(BELLE_SIP_OBJECT(lAttribute));

	lAttribute = BELLE_SDP_RTCP_XR_ATTRIBUTE(attribute_parse_marshall_parse_clone("a=rtcp-xr:stat-summary"));
	CU_ASSERT_STRING_EQUAL(belle_sdp_attribute_get_name(BELLE_SDP_ATTRIBUTE(lAttribute)), "rtcp-xr");
	CU_ASSERT_PTR_NULL(belle_sdp_rtcp_xr_attribute_get_rcvr_rtt_mode(lAttribute));
	CU_ASSERT_TRUE(belle_sdp_rtcp_xr_attribute_has_stat_summary(lAttribute) == TRUE);
	CU_ASSERT_TRUE(belle_sdp_rtcp_xr_attribute_has_voip_metrics(lAttribute) == FALSE);
	belle_sip_object_unref(BELLE_SIP_OBJECT(lAttribute));

	lAttribute = BELLE_SDP_RTCP_XR_ATTRIBUTE(attribute_parse_marshall_parse_clone("a=rtcp-xr:stat-summary=loss,jitt"));
	CU_ASSERT_STRING_EQUAL(belle_sdp_attribute_get_name(BELLE_SDP_ATTRIBUTE(lAttribute)), "rtcp-xr");
	CU_ASSERT_TRUE(belle_sdp_rtcp_xr_attribute_has_stat_summary(lAttribute) == TRUE);
	CU_ASSERT_PTR_NOT_NULL(belle_sip_list_find_custom(belle_sdp_rtcp_xr_attribute_get_stat_summary_flags(lAttribute), (belle_sip_compare_func)strcasecmp, "loss"));
	CU_ASSERT_PTR_NOT_NULL(belle_sip_list_find_custom(belle_sdp_rtcp_xr_attribute_get_stat_summary_flags(lAttribute), (belle_sip_compare_func)strcasecmp, "jitt"));
	CU_ASSERT_PTR_NULL(belle_sip_list_find_custom(belle_sdp_rtcp_xr_attribute_get_stat_summary_flags(lAttribute), (belle_sip_compare_func)strcasecmp, "HL"));
	belle_sip_object_unref(BELLE_SIP_OBJECT(lAttribute));

	lAttribute = BELLE_SDP_RTCP_XR_ATTRIBUTE(attribute_parse_marshall_parse_clone("a=rtcp-xr:voip-metrics"));
	CU_ASSERT_STRING_EQUAL(belle_sdp_attribute_get_name(BELLE_SDP_ATTRIBUTE(lAttribute)), "rtcp-xr");
	CU_ASSERT_TRUE(belle_sdp_rtcp_xr_attribute_has_stat_summary(lAttribute) == FALSE);
	CU_ASSERT_TRUE(belle_sdp_rtcp_xr_attribute_has_voip_metrics(lAttribute) == TRUE);
	belle_sip_object_unref(BELLE_SIP_OBJECT(lAttribute));

	lAttribute = BELLE_SDP_RTCP_XR_ATTRIBUTE(attribute_parse_marshall_parse_clone("a=rtcp-xr:rcvr-rtt=sender stat-summary=loss,dup,jitt,TTL voip-metrics"));
	CU_ASSERT_STRING_EQUAL(belle_sdp_attribute_get_name(BELLE_SDP_ATTRIBUTE(lAttribute)), "rtcp-xr");
	CU_ASSERT_STRING_EQUAL(belle_sdp_rtcp_xr_attribute_get_rcvr_rtt_mode(lAttribute), "sender");
	CU_ASSERT_TRUE(belle_sdp_rtcp_xr_attribute_has_stat_summary(lAttribute) == TRUE);
	CU_ASSERT_PTR_NOT_NULL(belle_sip_list_find_custom(belle_sdp_rtcp_xr_attribute_get_stat_summary_flags(lAttribute), (belle_sip_compare_func)strcasecmp, "loss"));
	CU_ASSERT_PTR_NOT_NULL(belle_sip_list_find_custom(belle_sdp_rtcp_xr_attribute_get_stat_summary_flags(lAttribute), (belle_sip_compare_func)strcasecmp, "dup"));
	CU_ASSERT_PTR_NOT_NULL(belle_sip_list_find_custom(belle_sdp_rtcp_xr_attribute_get_stat_summary_flags(lAttribute), (belle_sip_compare_func)strcasecmp, "jitt"));
	CU_ASSERT_PTR_NOT_NULL(belle_sip_list_find_custom(belle_sdp_rtcp_xr_attribute_get_stat_summary_flags(lAttribute), (belle_sip_compare_func)strcasecmp, "TTL"));
	CU_ASSERT_TRUE(belle_sdp_rtcp_xr_attribute_has_voip_metrics(lAttribute) == TRUE);
	belle_sip_object_unref(BELLE_SIP_OBJECT(lAttribute));
}
int static compare_attribute(belle_sdp_attribute_t* attr, const char* value) {
	return strcasecmp(belle_sdp_attribute_get_name(attr),"rtpmap")==0
			|| strcasecmp(belle_sdp_attribute_get_value(attr),value)==0;
}
示例#10
0
int sdp_to_media_description ( belle_sdp_session_description_t  *session_desc, SalMediaDescription *desc ) {
	/*
	typedef struct SalMediaDescription{
		int refcount;
		char addr[64];
		char username[64];
		int nstreams;
		int bandwidth;
		unsigned int session_ver;
		unsigned int session_id;
		SalStreamDescription streams[SAL_MEDIA_DESCRIPTION_MAX_STREAMS];
	} SalMediaDescription;
	 */
	belle_sdp_connection_t* cnx;
	belle_sip_list_t* media_desc_it;
	belle_sdp_media_description_t* media_desc;
	const char *mtype,*proto;
	SalStreamDescription *stream;
	belle_sdp_media_t* media;
	belle_sip_list_t* mime_params=NULL;
	belle_sip_list_t* mime_param_it=NULL;
	belle_sdp_mime_parameter_t* mime_param;
	PayloadType *pt;
	belle_sip_list_t* attribute_it;
	const belle_sdp_attribute_t* attribute;
	int valid_count = 0;
	char tmp[256], tmp2[256];
	int nb=0;
	SalStreamDir stream_dir=SalStreamSendRecv;
	const char* value;
	
	desc->n_active_streams = 0;
	desc->n_total_streams = 0;

	if ( ( cnx=belle_sdp_session_description_get_connection ( session_desc ) ) && belle_sdp_connection_get_address ( cnx ) ) {
		strncpy ( desc->addr,belle_sdp_connection_get_address ( cnx ),sizeof ( desc->addr ) );
	}
	if ( belle_sdp_session_description_get_bandwidth ( session_desc,"AS" ) >0 ) {
		desc->bandwidth=belle_sdp_session_description_get_bandwidth ( session_desc,"AS" );
	}
	/*in some very rare case, session attribute may set stream dir*/
	if ( belle_sdp_session_description_get_attribute ( session_desc,"sendrecv" ) ) {
		stream_dir=SalStreamSendRecv;
	} else if ( belle_sdp_session_description_get_attribute ( session_desc,"sendonly" ) ) {
		stream_dir=SalStreamSendOnly;
	} else if ( belle_sdp_session_description_get_attribute ( session_desc,"recvonly" ) ) {
		stream_dir=SalStreamRecvOnly;
	} else if ( belle_sdp_session_description_get_attribute ( session_desc,"inactive" ) ) {
		stream_dir=SalStreamInactive;
	}

	/* Get ICE remote ufrag and remote pwd, and ice_lite flag */
	value=belle_sdp_session_description_get_attribute_value(session_desc,"ice-ufrag");
	if (value) strncpy(desc->ice_ufrag, value, sizeof(desc->ice_ufrag));
	
	value=belle_sdp_session_description_get_attribute_value(session_desc,"ice-pwd");
	if (value) strncpy(desc->ice_pwd, value, sizeof(desc->ice_pwd));
	
	value=belle_sdp_session_description_get_attribute_value(session_desc,"ice-lite");
	if (value) desc->ice_lite = TRUE;
	
	for ( media_desc_it=belle_sdp_session_description_get_media_descriptions ( session_desc )
						; media_desc_it!=NULL
			; media_desc_it=media_desc_it->next ) {
		int nb_ice_candidates=0;
		media_desc=BELLE_SDP_MEDIA_DESCRIPTION ( media_desc_it->data );
		stream=&desc->streams[desc->n_total_streams];
		media=belle_sdp_media_description_get_media ( media_desc );

		memset ( stream,0,sizeof ( *stream ) );

		proto = belle_sdp_media_get_protocol ( media );
		stream->proto=SalProtoUnknown;
		if ( proto ) {
			if ( strcasecmp ( proto,"RTP/AVP" ) ==0 )
				stream->proto=SalProtoRtpAvp;
			else if ( strcasecmp ( proto,"RTP/SAVP" ) ==0 ) {
				stream->proto=SalProtoRtpSavp;
			}
		}
		if ( ( cnx=belle_sdp_media_description_get_connection ( media_desc ) ) && belle_sdp_connection_get_address ( cnx ) ) {
			strncpy ( stream->rtp_addr,belle_sdp_connection_get_address ( cnx ),sizeof ( stream->rtp_addr ) );
		}

		stream->rtp_port=belle_sdp_media_get_media_port ( media );

		if ( stream->rtp_port > 0 )
			desc->n_active_streams++;

		mtype = belle_sdp_media_get_media_type ( media );
		if ( strcasecmp ( "audio", mtype ) == 0 ) {
			stream->type=SalAudio;
		} else if ( strcasecmp ( "video", mtype ) == 0 ) {
			stream->type=SalVideo;
		} else {
			stream->type=SalOther;
			strncpy ( stream->typeother,mtype,sizeof ( stream->typeother )-1 );
		}

		if ( belle_sdp_media_description_get_bandwidth ( media_desc,"AS" ) >0 ) {
			stream->bandwidth=belle_sdp_media_description_get_bandwidth ( media_desc,"AS" );
		}


		if ( belle_sdp_media_description_get_attribute ( media_desc,"sendrecv" ) ) {
			stream->dir=SalStreamSendRecv;
		} else if ( belle_sdp_media_description_get_attribute ( media_desc,"sendonly" ) ) {
			stream->dir=SalStreamSendOnly;
		} else if ( belle_sdp_media_description_get_attribute ( media_desc,"recvonly" ) ) {
			stream->dir=SalStreamRecvOnly;
		} else if ( belle_sdp_media_description_get_attribute ( media_desc,"inactive" ) ) {
			stream->dir=SalStreamInactive;
		} else {
			stream->dir=stream_dir; /*takes default value if not present*/
		}

		/* for each payload type */
		mime_params=belle_sdp_media_description_build_mime_parameters ( media_desc );
		for ( mime_param_it=mime_params
							; mime_param_it!=NULL
				; mime_param_it=mime_param_it->next ) {
			mime_param=BELLE_SDP_MIME_PARAMETER ( mime_param_it->data )

					   pt=payload_type_new();
			payload_type_set_number ( pt,belle_sdp_mime_parameter_get_media_format ( mime_param ) );
			pt->clock_rate=belle_sdp_mime_parameter_get_rate ( mime_param );
			pt->mime_type=ms_strdup ( belle_sdp_mime_parameter_get_type ( mime_param ) );
			pt->channels=belle_sdp_mime_parameter_get_channel_count ( mime_param );
			payload_type_set_send_fmtp ( pt,belle_sdp_mime_parameter_get_parameters ( mime_param ) );
			stream->payloads=ms_list_append ( stream->payloads,pt );
			stream->ptime=belle_sdp_mime_parameter_get_ptime ( mime_param );
			ms_message ( "Found payload %s/%i fmtp=%s",pt->mime_type,pt->clock_rate,
						 pt->send_fmtp ? pt->send_fmtp : "" );
		}
		if ( mime_params ) belle_sip_list_free_with_data ( mime_params,belle_sip_object_unref );
		
		
		/* Get media specific RTCP attribute */
		stream->rtcp_port = stream->rtp_port + 1;
		snprintf(stream->rtcp_addr, sizeof(stream->rtcp_addr), "%s", stream->rtp_addr);
		attribute=belle_sdp_media_description_get_attribute(media_desc,"rtcp");
		if (attribute && (value=belle_sdp_attribute_get_value(attribute))!=NULL){
			char tmp[256];
			int nb = sscanf(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=rtcp line (%s) nb=%i", value, nb);
			}
		}
		
		/* read crypto lines if any */
		if ( stream->proto == SalProtoRtpSavp ) {
			valid_count=0;
			memset ( &stream->crypto, 0, sizeof ( stream->crypto ) );
			for ( attribute_it=belle_sdp_media_description_get_attributes ( media_desc )
							   ; valid_count < SAL_CRYPTO_ALGO_MAX && attribute_it!=NULL;
					attribute_it=attribute_it->next ) {
				attribute=BELLE_SDP_ATTRIBUTE ( attribute_it->data );

				if ( keywordcmp ( "crypto",belle_sdp_attribute_get_name ( attribute ) ) ==0 && belle_sdp_attribute_get_value ( attribute ) !=NULL ) {
					nb = sscanf ( belle_sdp_attribute_get_value ( attribute ), "%d %256s inline:%256s",
								  &stream->crypto[valid_count].tag,
								  tmp,
								  tmp2 );
					ms_message ( "Found valid crypto line (tag:%d algo:'%s' key:'%s'",
								 stream->crypto[valid_count].tag,
								 tmp,
								 tmp2 );
					if ( nb == 3 ) {
						if ( keywordcmp ( "AES_CM_128_HMAC_SHA1_80",tmp ) == 0 )
							stream->crypto[valid_count].algo = AES_128_SHA1_80;
						else if ( keywordcmp ( "AES_CM_128_HMAC_SHA1_32",tmp ) == 0 )
							stream->crypto[valid_count].algo = AES_128_SHA1_32;
						else {
							ms_warning ( "Failed to parse crypto-algo: '%s'", tmp );
							stream->crypto[valid_count].algo = 0;
						}
						if ( stream->crypto[valid_count].algo ) {
							strncpy ( stream->crypto[valid_count].master_key, tmp2, 41 );
							stream->crypto[valid_count].master_key[40] = '\0';
							ms_message ( "Found valid crypto line (tag:%d algo:'%s' key:'%s'",
										 stream->crypto[valid_count].tag,
										 tmp,
										 stream->crypto[valid_count].master_key );
							valid_count++;
						}
					} else {
						ms_warning ( "sdp has a strange a= line (%s) nb=%i",belle_sdp_attribute_get_value ( attribute ),nb );
					}
				}
			}
			ms_message ( "Found: %d valid crypto lines", valid_count );
		}
		
		/* Get ICE candidate attributes if any */
		for (attribute_it = belle_sdp_media_description_get_attributes(media_desc); attribute_it != NULL; attribute_it=attribute_it->next) {
			const char *att_name;
			attribute=(belle_sdp_attribute_t*)attribute_it->data;
			att_name=belle_sdp_attribute_get_name(attribute);
			value=belle_sdp_attribute_get_value(attribute);
			if ((keywordcmp("candidate", att_name) == 0) && (value != NULL)) {
				SalIceCandidate *candidate = &stream->ice_candidates[nb_ice_candidates];
				int nb = sscanf(value, "%s %u UDP %u %s %d typ %s raddr %s rport %d",
					candidate->foundation, &candidate->componentID, &candidate->priority, candidate->addr, &candidate->port,
					candidate->type, candidate->raddr, &candidate->rport);
				if ((nb == 6) || (nb == 8)) nb_ice_candidates++;
				else memset(candidate, 0, sizeof(*candidate));
			} else if ((keywordcmp("remote-candidates", att_name) == 0) && (value != NULL)) {
				SalIceRemoteCandidate candidate;
				unsigned int componentID;
				int offset;
				const char *ptr = value;
				const char *endptr=value+strlen(ptr);
				while (3 == sscanf(ptr, "%u %s %u%n", &componentID, candidate.addr, &candidate.port, &offset)) {
					if ((componentID > 0) && (componentID <= SAL_MEDIA_DESCRIPTION_MAX_ICE_REMOTE_CANDIDATES)) {
						SalIceRemoteCandidate *remote_candidate = &stream->ice_remote_candidates[componentID - 1];
						strncpy(remote_candidate->addr, candidate.addr, sizeof(remote_candidate->addr));
						remote_candidate->port = candidate.port;
					}
					ptr += offset;
					if (ptr<endptr){
						if (ptr[offset] == ' ') ptr += 1;
					}else break;
				}
			} else if ((keywordcmp("ice-ufrag", att_name) == 0) && (value != NULL)) {
				strncpy(stream->ice_ufrag, value, sizeof(stream->ice_ufrag));
			} else if ((keywordcmp("ice-pwd", att_name) == 0) && (value != NULL)) {
				strncpy(stream->ice_pwd, value, sizeof(stream->ice_pwd));
			} else if (keywordcmp("ice-mismatch", att_name) == 0) {
				stream->ice_mismatch = TRUE;
			}
		}
		desc->n_total_streams++;
	}
	return 0;
}
示例#11
0
int sdp_to_media_description ( belle_sdp_session_description_t  *session_desc, SalMediaDescription *desc ) {
	belle_sdp_connection_t* cnx;
	belle_sip_list_t* media_desc_it;
	belle_sdp_media_description_t* media_desc;
	belle_sdp_session_name_t *sname;
	belle_sip_list_t *custom_attribute_it;
	const char* value;
	SalDtlsRole session_role=SalDtlsRoleInvalid;
	int i;
	
	desc->nb_streams = 0;
	desc->dir = SalStreamSendRecv;

	if ( ( cnx=belle_sdp_session_description_get_connection ( session_desc ) ) && belle_sdp_connection_get_address ( cnx ) ) {
		strncpy ( desc->addr,belle_sdp_connection_get_address ( cnx ),sizeof ( desc->addr ) -1  );
	}
	if ( (sname=belle_sdp_session_description_get_session_name(session_desc)) && belle_sdp_session_name_get_value(sname) ){
		strncpy(desc->name,belle_sdp_session_name_get_value(sname),sizeof(desc->name) - 1);
	}
	
	if ( belle_sdp_session_description_get_bandwidth ( session_desc,"AS" ) >0 ) {
		desc->bandwidth=belle_sdp_session_description_get_bandwidth ( session_desc,"AS" );
	}
	
	/*in some very rare case, session attribute may set stream dir*/
	if ( belle_sdp_session_description_get_attribute ( session_desc,"sendrecv" ) ) {
		desc->dir=SalStreamSendRecv;
	} else if ( belle_sdp_session_description_get_attribute ( session_desc,"sendonly" ) ) {
		desc->dir=SalStreamSendOnly;
	} else if ( belle_sdp_session_description_get_attribute ( session_desc,"recvonly" ) ) {
		desc->dir=SalStreamRecvOnly;
	} else if ( belle_sdp_session_description_get_attribute ( session_desc,"inactive" ) ) {
		desc->dir=SalStreamInactive;
	}

	/*DTLS attributes can be defined at session level.*/
	value=belle_sdp_session_description_get_attribute_value(session_desc,"setup");
	if (value){
		if (strncmp(value, "actpass", 7) == 0) {
			session_role = SalDtlsRoleUnset;
		} else if (strncmp(value, "active", 6) == 0) {
			session_role = SalDtlsRoleIsClient;
		} else if (strncmp(value, "passive", 7) == 0) {
			session_role = SalDtlsRoleIsServer;
		}
	}
	value=belle_sdp_session_description_get_attribute_value(session_desc,"fingerprint");
	/*copy dtls attributes to every streams, might be overwritten stream by stream*/
	for (i=0;i<SAL_MEDIA_DESCRIPTION_MAX_STREAMS;i++) {
		if (value)
			strncpy(desc->streams[i].dtls_fingerprint, value, sizeof(desc->streams[i].dtls_fingerprint));
		desc->streams[i].dtls_role=session_role; /*set or reset value*/
	}

	/* Get ICE remote ufrag and remote pwd, and ice_lite flag */
	value=belle_sdp_session_description_get_attribute_value(session_desc,"ice-ufrag");
	if (value) strncpy(desc->ice_ufrag, value, sizeof(desc->ice_ufrag) - 1);
	
	value=belle_sdp_session_description_get_attribute_value(session_desc,"ice-pwd");
	if (value) strncpy(desc->ice_pwd, value, sizeof(desc->ice_pwd)-1);
	
	value=belle_sdp_session_description_get_attribute_value(session_desc,"ice-lite");
	if (value) desc->ice_lite = TRUE;

	/* Get session RTCP-XR attributes if any */
	sdp_parse_session_rtcp_xr_parameters(session_desc, &desc->rtcp_xr);

	/* Get the custom attributes */
	for (custom_attribute_it = belle_sdp_session_description_get_attributes(session_desc); custom_attribute_it != NULL; custom_attribute_it = custom_attribute_it->next) {
		belle_sdp_attribute_t *attr = (belle_sdp_attribute_t *)custom_attribute_it->data;
		desc->custom_sdp_attributes = sal_custom_sdp_attribute_append(desc->custom_sdp_attributes, belle_sdp_attribute_get_name(attr), belle_sdp_attribute_get_value(attr));
	}

	for ( media_desc_it=belle_sdp_session_description_get_media_descriptions ( session_desc )
						; media_desc_it!=NULL
			; media_desc_it=media_desc_it->next ) {
		if (desc->nb_streams==SAL_MEDIA_DESCRIPTION_MAX_STREAMS){
			ms_warning("Cannot convert mline at position [%i] from SDP to SalMediaDescription",desc->nb_streams);
			break;
		}
		media_desc=BELLE_SDP_MEDIA_DESCRIPTION ( media_desc_it->data );
		sdp_to_stream_description(desc, media_desc);
	}
	return 0;
}
示例#12
0
static SalStreamDescription * sdp_to_stream_description(SalMediaDescription *md, belle_sdp_media_description_t *media_desc) {
	SalStreamDescription *stream;
	belle_sdp_connection_t* cnx;
	belle_sdp_media_t* media;
	belle_sdp_attribute_t* attribute;
	belle_sip_list_t *custom_attribute_it;
	const char* value;
	const char *mtype,*proto;
    bool_t has_avpf_attributes;

	stream=&md->streams[md->nb_streams];
	media=belle_sdp_media_description_get_media ( media_desc );

	proto = belle_sdp_media_get_protocol ( media );
	stream->proto=SalProtoOther;
	if ( proto ) {
		if (strcasecmp(proto, "RTP/AVP") == 0) {
			stream->proto = SalProtoRtpAvp;
		} else if (strcasecmp(proto, "RTP/SAVP") == 0) {
			stream->proto = SalProtoRtpSavp;
		} else if (strcasecmp(proto, "RTP/AVPF") == 0) {
			stream->proto = SalProtoRtpAvpf;
		} else if (strcasecmp(proto, "RTP/SAVPF") == 0) {
			stream->proto = SalProtoRtpSavpf;
		} else if (strcasecmp(proto, "UDP/TLS/RTP/SAVP") == 0) {
			stream->proto = SalProtoUdpTlsRtpSavp;
		} else if (strcasecmp(proto, "UDP/TLS/RTP/SAVPF") == 0) {
			stream->proto = SalProtoUdpTlsRtpSavpf;
		} else {
			strncpy(stream->proto_other,proto,sizeof(stream->proto_other)-1);
		}
	}
	if ( ( cnx=belle_sdp_media_description_get_connection ( media_desc ) ) && belle_sdp_connection_get_address ( cnx ) ) {
		strncpy ( stream->rtp_addr,belle_sdp_connection_get_address ( cnx ), sizeof ( stream->rtp_addr ) -1 );
		stream->ttl=belle_sdp_connection_get_ttl(cnx);
	}

	stream->rtp_port=belle_sdp_media_get_media_port ( media );

	mtype = belle_sdp_media_get_media_type ( media );
	if ( strcasecmp ( "audio", mtype ) == 0 ) {
		stream->type=SalAudio;
	} else if ( strcasecmp ( "video", mtype ) == 0 ) {
		stream->type=SalVideo;
	} else if ( strcasecmp ( "text", mtype ) == 0 ) {
		stream->type=SalText;
	} else {
		stream->type=SalOther;
		strncpy ( stream->typeother,mtype,sizeof ( stream->typeother )-1 );
	}

	if ( belle_sdp_media_description_get_bandwidth ( media_desc,"AS" ) >0 ) {
		stream->bandwidth=belle_sdp_media_description_get_bandwidth ( media_desc,"AS" );
	}

	if ( belle_sdp_media_description_get_attribute ( media_desc,"sendrecv" ) ) {
		stream->dir=SalStreamSendRecv;
	} else if ( belle_sdp_media_description_get_attribute ( media_desc,"sendonly" ) ) {
		stream->dir=SalStreamSendOnly;
	} else if ( belle_sdp_media_description_get_attribute ( media_desc,"recvonly" ) ) {
		stream->dir=SalStreamRecvOnly;
	} else if ( belle_sdp_media_description_get_attribute ( media_desc,"inactive" ) ) {
		stream->dir=SalStreamInactive;
	} else {
		stream->dir=md->dir; /*takes default value if not present*/
	}

	stream->rtcp_mux = belle_sdp_media_description_get_attribute(media_desc, "rtcp-mux") != NULL;
	
	/* Get media payload types */
	sdp_parse_payload_types(media_desc, stream);

	/* Get media specific RTCP attribute */
	stream->rtcp_port = stream->rtp_port + 1;
	snprintf(stream->rtcp_addr, sizeof(stream->rtcp_addr), "%s", stream->rtp_addr);
	attribute=belle_sdp_media_description_get_attribute(media_desc,"rtcp");
	if (attribute && (value=belle_sdp_attribute_get_value(attribute))!=NULL){
		char tmp[256];
		int nb = sscanf(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)-1);
		} else {
			ms_warning("sdp has a strange a=rtcp line (%s) nb=%i", value, nb);
		}
	}

	/* Read DTLS specific attributes : check is some are found in the stream description otherwise copy the session description one(which are at least set to Invalid) */
	if (((stream->proto == SalProtoUdpTlsRtpSavpf) || (stream->proto == SalProtoUdpTlsRtpSavp))) {
		attribute=belle_sdp_media_description_get_attribute(media_desc,"setup");
		if (attribute && (value=belle_sdp_attribute_get_value(attribute))!=NULL){
			if (strncmp(value, "actpass", 7) == 0) {
				stream->dtls_role = SalDtlsRoleUnset;
			} else if (strncmp(value, "active", 6) == 0) {
				stream->dtls_role = SalDtlsRoleIsClient;
			} else if (strncmp(value, "passive", 7) == 0) {
				stream->dtls_role = SalDtlsRoleIsServer;
			}
		}
		if (stream->dtls_role != SalDtlsRoleInvalid && (attribute=belle_sdp_media_description_get_attribute(media_desc,"fingerprint"))) {
			strncpy(stream->dtls_fingerprint, belle_sdp_attribute_get_value(attribute),sizeof(stream->dtls_fingerprint));
		}
	}

	/* Read crypto lines if any */
	if (sal_stream_description_has_srtp(stream)) {
		sdp_parse_media_crypto_parameters(media_desc, stream);
	}

	/* Get ICE candidate attributes if any */
	sdp_parse_media_ice_parameters(media_desc, stream);
    
    has_avpf_attributes = sdp_parse_rtcp_fb_parameters(media_desc, stream);
    
	/* Get RTCP-FB attributes if any */
	if (sal_stream_description_has_avpf(stream)) {
		enable_avpf_for_stream(stream);
	}
    else if (has_avpf_attributes ){
        
        stream->implicit_rtcp_fb = TRUE;
    }

	/* Get RTCP-XR attributes if any */
	stream->rtcp_xr = md->rtcp_xr;	// Use session parameters if no stream parameters are defined
	sdp_parse_media_rtcp_xr_parameters(media_desc, &stream->rtcp_xr);

	/* Get the custom attributes */
	for (custom_attribute_it = belle_sdp_media_description_get_attributes(media_desc); custom_attribute_it != NULL; custom_attribute_it = custom_attribute_it->next) {
		belle_sdp_attribute_t *attr = (belle_sdp_attribute_t *)custom_attribute_it->data;
		stream->custom_sdp_attributes = sal_custom_sdp_attribute_append(stream->custom_sdp_attributes, belle_sdp_attribute_get_name(attr), belle_sdp_attribute_get_value(attr));
	}

	md->nb_streams++;
	return stream;
}