|
|
|
|
@ -100,12 +100,14 @@ struct sdp_connection {
|
|
|
|
|
|
|
|
|
|
TYPED_GQUEUE(attributes, struct sdp_attribute)
|
|
|
|
|
TYPED_GHASHTABLE(attr_id_ht, enum attr_id, struct sdp_attribute, g_int_hash, g_int_equal, NULL, NULL)
|
|
|
|
|
TYPED_GHASHTABLE(attr_list_ht, enum attr_id, attributes_q, g_int_hash, g_int_equal, NULL, g_queue_free)
|
|
|
|
|
TYPED_GHASHTABLE_LOOKUP_INSERT(attr_list_ht, NULL, attributes_q_new)
|
|
|
|
|
|
|
|
|
|
struct sdp_attributes {
|
|
|
|
|
attributes_q list;
|
|
|
|
|
/* GHashTable *name_hash; */
|
|
|
|
|
/* GHashTable *name_lists_hash; */
|
|
|
|
|
GHashTable *id_lists_hash;
|
|
|
|
|
attr_list_ht id_lists_hash;
|
|
|
|
|
attr_id_ht id_hash;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
@ -377,8 +379,8 @@ static void append_attr_int_to_gstring(GString *s, char * value, const int * add
|
|
|
|
|
INLINE struct sdp_attribute *attr_get_by_id(struct sdp_attributes *a, enum attr_id id) {
|
|
|
|
|
return t_hash_table_lookup(a->id_hash, &id);
|
|
|
|
|
}
|
|
|
|
|
INLINE GQueue *attr_list_get_by_id(struct sdp_attributes *a, enum attr_id id) {
|
|
|
|
|
return g_hash_table_lookup(a->id_lists_hash, &id);
|
|
|
|
|
INLINE attributes_q *attr_list_get_by_id(struct sdp_attributes *a, enum attr_id id) {
|
|
|
|
|
return t_hash_table_lookup(a->id_lists_hash, &id);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static struct sdp_attribute *attr_get_by_id_m_s(struct sdp_media *m, enum attr_id id) {
|
|
|
|
|
@ -508,8 +510,7 @@ static void attrs_init(struct sdp_attributes *a) {
|
|
|
|
|
a->id_hash = attr_id_ht_new();
|
|
|
|
|
/* a->name_lists_hash = g_hash_table_new_full(str_hash, str_equal,
|
|
|
|
|
NULL, (GDestroyNotify) g_queue_free); */
|
|
|
|
|
a->id_lists_hash = g_hash_table_new_full(g_int_hash, g_int_equal,
|
|
|
|
|
NULL, (GDestroyNotify) g_queue_free);
|
|
|
|
|
a->id_lists_hash = attr_list_ht_new();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void attr_insert(struct sdp_attributes *attrs, struct sdp_attribute *attr) {
|
|
|
|
|
@ -518,10 +519,9 @@ static void attr_insert(struct sdp_attributes *attrs, struct sdp_attribute *attr
|
|
|
|
|
if (!t_hash_table_lookup(attrs->id_hash, &attr->attr))
|
|
|
|
|
t_hash_table_insert(attrs->id_hash, &attr->attr, attr);
|
|
|
|
|
|
|
|
|
|
GQueue *attr_queue = g_hash_table_lookup_queue_new(attrs->id_lists_hash, &attr->attr,
|
|
|
|
|
NULL);
|
|
|
|
|
attributes_q *attr_queue = attr_list_ht_lookup_insert(attrs->id_lists_hash, &attr->attr);
|
|
|
|
|
|
|
|
|
|
g_queue_push_tail(attr_queue, attr);
|
|
|
|
|
t_queue_push_tail(attr_queue, attr);
|
|
|
|
|
|
|
|
|
|
/* g_hash_table_insert(attrs->name_hash, &attr->name, attr); */
|
|
|
|
|
/* if (attr->key.s)
|
|
|
|
|
@ -1407,7 +1407,7 @@ static void free_attributes(struct sdp_attributes *a) {
|
|
|
|
|
/* g_hash_table_destroy(a->name_hash); */
|
|
|
|
|
t_hash_table_destroy(a->id_hash);
|
|
|
|
|
/* g_hash_table_destroy(a->name_lists_hash); */
|
|
|
|
|
g_hash_table_destroy(a->id_lists_hash);
|
|
|
|
|
t_hash_table_destroy(a->id_lists_hash);
|
|
|
|
|
t_queue_clear_full(&a->list, attr_free);
|
|
|
|
|
}
|
|
|
|
|
static void media_free(struct sdp_media *media) {
|
|
|
|
|
@ -1456,8 +1456,6 @@ static int fill_endpoint(struct endpoint *ep, const struct sdp_media *media, sdp
|
|
|
|
|
static int __rtp_payload_types(struct stream_params *sp, struct sdp_media *media)
|
|
|
|
|
{
|
|
|
|
|
GHashTable *ht_rtpmap, *ht_fmtp, *ht_rtcp_fb;
|
|
|
|
|
GQueue *q;
|
|
|
|
|
GList *ql;
|
|
|
|
|
struct sdp_attribute *attr;
|
|
|
|
|
int ret = 0;
|
|
|
|
|
|
|
|
|
|
@ -1466,8 +1464,8 @@ static int __rtp_payload_types(struct stream_params *sp, struct sdp_media *media
|
|
|
|
|
|
|
|
|
|
/* first go through a=rtpmap and build a hash table of attrs */
|
|
|
|
|
ht_rtpmap = g_hash_table_new(g_int_hash, g_int_equal);
|
|
|
|
|
q = attr_list_get_by_id(&media->attributes, ATTR_RTPMAP);
|
|
|
|
|
for (ql = q ? q->head : NULL; ql; ql = ql->next) {
|
|
|
|
|
attributes_q *q = attr_list_get_by_id(&media->attributes, ATTR_RTPMAP);
|
|
|
|
|
for (__auto_type ql = q ? q->head : NULL; ql; ql = ql->next) {
|
|
|
|
|
struct rtp_payload_type *pt;
|
|
|
|
|
attr = ql->data;
|
|
|
|
|
pt = &attr->rtpmap.rtp_pt;
|
|
|
|
|
@ -1476,14 +1474,14 @@ static int __rtp_payload_types(struct stream_params *sp, struct sdp_media *media
|
|
|
|
|
// do the same for a=fmtp
|
|
|
|
|
ht_fmtp = g_hash_table_new(g_int_hash, g_int_equal);
|
|
|
|
|
q = attr_list_get_by_id(&media->attributes, ATTR_FMTP);
|
|
|
|
|
for (ql = q ? q->head : NULL; ql; ql = ql->next) {
|
|
|
|
|
for (__auto_type ql = q ? q->head : NULL; ql; ql = ql->next) {
|
|
|
|
|
attr = ql->data;
|
|
|
|
|
g_hash_table_insert(ht_fmtp, &attr->fmtp.payload_type, &attr->fmtp.format_parms_str);
|
|
|
|
|
}
|
|
|
|
|
// do the same for a=rtcp-fb
|
|
|
|
|
ht_rtcp_fb = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, (GDestroyNotify) g_queue_free);
|
|
|
|
|
q = attr_list_get_by_id(&media->attributes, ATTR_RTCP_FB);
|
|
|
|
|
for (ql = q ? q->head : NULL; ql; ql = ql->next) {
|
|
|
|
|
for (__auto_type ql = q ? q->head : NULL; ql; ql = ql->next) {
|
|
|
|
|
attr = ql->data;
|
|
|
|
|
if (attr->rtcp_fb.payload_type == -1)
|
|
|
|
|
continue;
|
|
|
|
|
@ -1492,7 +1490,7 @@ static int __rtp_payload_types(struct stream_params *sp, struct sdp_media *media
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* then go through the format list and associate */
|
|
|
|
|
for (ql = media->format_list.head; ql; ql = ql->next) {
|
|
|
|
|
for (GList *ql = media->format_list.head; ql; ql = ql->next) {
|
|
|
|
|
char *ep;
|
|
|
|
|
str *s;
|
|
|
|
|
unsigned int i;
|
|
|
|
|
@ -1556,8 +1554,6 @@ static void __sdp_ice(struct stream_params *sp, struct sdp_media *media) {
|
|
|
|
|
struct sdp_attribute *attr;
|
|
|
|
|
struct attribute_candidate *ac;
|
|
|
|
|
struct ice_candidate *cand;
|
|
|
|
|
GQueue *q;
|
|
|
|
|
GList *ql;
|
|
|
|
|
|
|
|
|
|
attr = attr_get_by_id_m_s(media, ATTR_ICE_UFRAG);
|
|
|
|
|
if (!attr)
|
|
|
|
|
@ -1566,11 +1562,11 @@ static void __sdp_ice(struct stream_params *sp, struct sdp_media *media) {
|
|
|
|
|
|
|
|
|
|
SP_SET(sp, ICE);
|
|
|
|
|
|
|
|
|
|
q = attr_list_get_by_id(&media->attributes, ATTR_CANDIDATE);
|
|
|
|
|
attributes_q *q = attr_list_get_by_id(&media->attributes, ATTR_CANDIDATE);
|
|
|
|
|
if (!q)
|
|
|
|
|
goto no_cand;
|
|
|
|
|
|
|
|
|
|
for (ql = q->head; ql; ql = ql->next) {
|
|
|
|
|
for (__auto_type ql = q->head; ql; ql = ql->next) {
|
|
|
|
|
attr = ql->data;
|
|
|
|
|
ac = &attr->candidate;
|
|
|
|
|
if (!ac->parsed)
|
|
|
|
|
@ -1751,7 +1747,6 @@ int sdp_streams(const sdp_sessions_q *sessions, sdp_streams_q *streams, sdp_ng_f
|
|
|
|
|
const char *errstr;
|
|
|
|
|
unsigned int num = 0;
|
|
|
|
|
struct sdp_attribute *attr;
|
|
|
|
|
GQueue *attrs;
|
|
|
|
|
|
|
|
|
|
for (__auto_type l = sessions->head; l; l = l->next) {
|
|
|
|
|
session = l->data;
|
|
|
|
|
@ -1798,11 +1793,11 @@ int sdp_streams(const sdp_sessions_q *sessions, sdp_streams_q *streams, sdp_ng_f
|
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
|
|
/* a=crypto */
|
|
|
|
|
attrs = attr_list_get_by_id(&media->attributes, ATTR_CRYPTO);
|
|
|
|
|
for (GList *ll = attrs ? attrs->head : NULL; ll; ll = ll->next) {
|
|
|
|
|
attributes_q *attrs = attr_list_get_by_id(&media->attributes, ATTR_CRYPTO);
|
|
|
|
|
for (__auto_type ll = attrs ? attrs->head : NULL; ll; ll = ll->next) {
|
|
|
|
|
attr = ll->data;
|
|
|
|
|
struct crypto_params_sdes *cps = g_slice_alloc0(sizeof(*cps));
|
|
|
|
|
g_queue_push_tail(&sp->sdes_params, cps);
|
|
|
|
|
t_queue_push_tail(&sp->sdes_params, cps);
|
|
|
|
|
|
|
|
|
|
cps->params.crypto_suite = attr->crypto.crypto_suite;
|
|
|
|
|
cps->params.mki_len = attr->crypto.mki_len;
|
|
|
|
|
@ -1830,7 +1825,7 @@ int sdp_streams(const sdp_sessions_q *sessions, sdp_streams_q *streams, sdp_ng_f
|
|
|
|
|
{
|
|
|
|
|
/* a=ssrc-group */
|
|
|
|
|
attrs = attr_list_get_by_id(&media->attributes, ATTR_SSRC_GROUP);
|
|
|
|
|
for (GList *ll = attrs ? attrs->head : NULL; ll; ll = ll->next) {
|
|
|
|
|
for (__auto_type ll = attrs ? attrs->head : NULL; ll; ll = ll->next) {
|
|
|
|
|
attr = ll->data;
|
|
|
|
|
str * ret = str_dup(&attr->line_value);
|
|
|
|
|
g_queue_push_tail(&sp->attributes, ret);
|
|
|
|
|
@ -1838,7 +1833,7 @@ int sdp_streams(const sdp_sessions_q *sessions, sdp_streams_q *streams, sdp_ng_f
|
|
|
|
|
|
|
|
|
|
/* a=ssrc */
|
|
|
|
|
attrs = attr_list_get_by_id(&media->attributes, ATTR_SSRC);
|
|
|
|
|
for (GList *ll = attrs ? attrs->head : NULL; ll; ll = ll->next) {
|
|
|
|
|
for (__auto_type ll = attrs ? attrs->head : NULL; ll; ll = ll->next) {
|
|
|
|
|
attr = ll->data;
|
|
|
|
|
str * ret = str_dup(&attr->line_value);
|
|
|
|
|
g_queue_push_tail(&sp->attributes, ret);
|
|
|
|
|
@ -1846,7 +1841,7 @@ int sdp_streams(const sdp_sessions_q *sessions, sdp_streams_q *streams, sdp_ng_f
|
|
|
|
|
|
|
|
|
|
/* a=msid */
|
|
|
|
|
attrs = attr_list_get_by_id(&media->attributes, ATTR_MSID);
|
|
|
|
|
for (GList *ll = attrs ? attrs->head : NULL; ll; ll = ll->next) {
|
|
|
|
|
for (__auto_type ll = attrs ? attrs->head : NULL; ll; ll = ll->next) {
|
|
|
|
|
attr = ll->data;
|
|
|
|
|
str * ret = str_dup(&attr->line_value);
|
|
|
|
|
g_queue_push_tail(&sp->attributes, ret);
|
|
|
|
|
@ -1855,7 +1850,7 @@ int sdp_streams(const sdp_sessions_q *sessions, sdp_streams_q *streams, sdp_ng_f
|
|
|
|
|
/* a=extmap */
|
|
|
|
|
if (!flags->strip_extmap) {
|
|
|
|
|
attrs = attr_list_get_by_id(&media->attributes, ATTR_EXTMAP);
|
|
|
|
|
for (GList *ll = attrs ? attrs->head : NULL; ll; ll = ll->next) {
|
|
|
|
|
for (__auto_type ll = attrs ? attrs->head : NULL; ll; ll = ll->next) {
|
|
|
|
|
attr = ll->data;
|
|
|
|
|
str * ret = str_dup(&attr->line_value);
|
|
|
|
|
g_queue_push_tail(&sp->attributes, ret);
|
|
|
|
|
@ -1864,7 +1859,7 @@ int sdp_streams(const sdp_sessions_q *sessions, sdp_streams_q *streams, sdp_ng_f
|
|
|
|
|
|
|
|
|
|
/* ATTR_OTHER (unknown types) */
|
|
|
|
|
attrs = attr_list_get_by_id(&media->attributes, ATTR_OTHER);
|
|
|
|
|
for (GList *ll = attrs ? attrs->head : NULL; ll; ll = ll->next) {
|
|
|
|
|
for (__auto_type ll = attrs ? attrs->head : NULL; ll; ll = ll->next) {
|
|
|
|
|
attr = ll->data;
|
|
|
|
|
str * ret = str_dup(&attr->line_value);
|
|
|
|
|
g_queue_push_tail(&sp->attributes, ret);
|
|
|
|
|
@ -2582,10 +2577,8 @@ strip_with_subst:
|
|
|
|
|
static void new_priority(struct sdp_media *media, enum ice_candidate_type type, unsigned int *tprefp,
|
|
|
|
|
unsigned int *lprefp)
|
|
|
|
|
{
|
|
|
|
|
GQueue *cands;
|
|
|
|
|
unsigned int lpref, tpref;
|
|
|
|
|
uint32_t prio;
|
|
|
|
|
GList *l;
|
|
|
|
|
struct sdp_attribute *a;
|
|
|
|
|
struct attribute_candidate *c;
|
|
|
|
|
|
|
|
|
|
@ -2593,11 +2586,11 @@ static void new_priority(struct sdp_media *media, enum ice_candidate_type type,
|
|
|
|
|
tpref = ice_type_preference(type);
|
|
|
|
|
prio = ice_priority_pref(tpref, lpref, 1);
|
|
|
|
|
|
|
|
|
|
cands = attr_list_get_by_id(&media->attributes, ATTR_CANDIDATE);
|
|
|
|
|
attributes_q *cands = attr_list_get_by_id(&media->attributes, ATTR_CANDIDATE);
|
|
|
|
|
if (!cands)
|
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
|
|
for (l = cands->head; l; l = l->next) {
|
|
|
|
|
for (__auto_type l = cands->head; l; l = l->next) {
|
|
|
|
|
a = l->data;
|
|
|
|
|
c = &a->candidate;
|
|
|
|
|
if (c->cand_parsed.priority <= prio && c->cand_parsed.type == type
|
|
|
|
|
@ -2862,7 +2855,7 @@ static void insert_crypto1(GString *s, struct call_media *media, struct crypto_p
|
|
|
|
|
static void insert_crypto(GString *s, struct call_media *media, sdp_ng_flags *flags) {
|
|
|
|
|
if (!media->protocol || !media->protocol->srtp)
|
|
|
|
|
return;
|
|
|
|
|
for (GList *l = media->sdes_out.head; l; l = l->next)
|
|
|
|
|
for (__auto_type l = media->sdes_out.head; l; l = l->next)
|
|
|
|
|
insert_crypto1(s, media, l->data, flags);
|
|
|
|
|
}
|
|
|
|
|
static void insert_rtcp_attr(GString *s, struct packet_stream *ps, sdp_ng_flags *flags,
|
|
|
|
|
@ -3057,9 +3050,9 @@ struct packet_stream *print_rtcp(GString *s, struct call_media *media, GList *rt
|
|
|
|
|
void sdp_copy_session_attributes(struct call_monologue * src, struct call_monologue * dst) {
|
|
|
|
|
struct sdp_attribute *attr;
|
|
|
|
|
struct sdp_session *src_session = src->last_in_sdp_parsed.head->data;
|
|
|
|
|
GQueue *src_attributes = attr_list_get_by_id(&src_session->attributes, ATTR_OTHER);
|
|
|
|
|
attributes_q *src_attributes = attr_list_get_by_id(&src_session->attributes, ATTR_OTHER);
|
|
|
|
|
g_queue_clear_full(&dst->sdp_attributes, free);
|
|
|
|
|
for (GList *ll = src_attributes ? src_attributes->head : NULL; ll; ll = ll->next) {
|
|
|
|
|
for (__auto_type ll = src_attributes ? src_attributes->head : NULL; ll; ll = ll->next) {
|
|
|
|
|
attr = ll->data;
|
|
|
|
|
str * ret = str_dup(&attr->line_value);
|
|
|
|
|
g_queue_push_tail(&dst->sdp_attributes, ret);
|
|
|
|
|
@ -3510,10 +3503,10 @@ err:
|
|
|
|
|
int sdp_is_duplicate(sdp_sessions_q *sessions) {
|
|
|
|
|
for (__auto_type l = sessions->head; l; l = l->next) {
|
|
|
|
|
struct sdp_session *s = l->data;
|
|
|
|
|
GQueue *attr_list = attr_list_get_by_id(&s->attributes, ATTR_RTPENGINE);
|
|
|
|
|
attributes_q *attr_list = attr_list_get_by_id(&s->attributes, ATTR_RTPENGINE);
|
|
|
|
|
if (!attr_list)
|
|
|
|
|
return 0;
|
|
|
|
|
for (GList *ql = attr_list->head; ql; ql = ql->next) {
|
|
|
|
|
for (__auto_type ql = attr_list->head; ql; ql = ql->next) {
|
|
|
|
|
struct sdp_attribute *attr = ql->data;
|
|
|
|
|
if (!str_cmp_str(&attr->value, &rtpe_instance_id))
|
|
|
|
|
goto next;
|
|
|
|
|
|