|
|
|
@ -66,6 +66,7 @@ enum attr_id { |
|
|
|
ATTR_TLS_ID, |
|
|
|
ATTR_END_OF_CANDIDATES, |
|
|
|
ATTR_MOH_ATTR_NAME, |
|
|
|
ATTR_EXTMAP, |
|
|
|
}; |
|
|
|
// make sure g_direct_hash can be used |
|
|
|
static_assert(sizeof(void *) >= sizeof(enum attr_id), "sizeof enum attr_id wrong"); |
|
|
|
@ -255,9 +256,15 @@ struct attribute_t38faxudpecdepth { |
|
|
|
int maxred; |
|
|
|
}; |
|
|
|
|
|
|
|
struct attribute_extmap { |
|
|
|
str id_str; |
|
|
|
str ext; |
|
|
|
|
|
|
|
int id; |
|
|
|
}; |
|
|
|
|
|
|
|
enum attribute_other { |
|
|
|
ATTR_OTHER_UNKNOWN = 0, |
|
|
|
ATTR_OTHER_EXTMAP, |
|
|
|
}; |
|
|
|
|
|
|
|
struct sdp_attribute { |
|
|
|
@ -283,6 +290,7 @@ struct sdp_attribute { |
|
|
|
int i; |
|
|
|
struct attribute_t38faxudpecdepth t38faxudpecdepth; |
|
|
|
struct attribute_t38faxratemanagement t38faxratemanagement; |
|
|
|
struct attribute_extmap extmap; |
|
|
|
enum attribute_other other; |
|
|
|
}; |
|
|
|
}; |
|
|
|
@ -1147,6 +1155,22 @@ static bool parse_attribute_t38faxudpecdepth(struct sdp_attribute *output) { |
|
|
|
return true; |
|
|
|
} |
|
|
|
|
|
|
|
static bool parse_attribute_extmap(struct sdp_attribute *output) { |
|
|
|
output->attr = ATTR_EXTMAP; |
|
|
|
|
|
|
|
PARSE_INIT; |
|
|
|
EXTRACT_TOKEN(extmap.id_str); |
|
|
|
EXTRACT_TOKEN(extmap.ext); |
|
|
|
|
|
|
|
output->extmap.id = str_to_i(&output->extmap.id_str, 0); |
|
|
|
// RFC 8285, valid range: 1-14, 15 reserved, 16-255, 256 appbits (not supported), |
|
|
|
// 256-4095 invalid, 4096-4351 remap (not supported) |
|
|
|
if (output->extmap.id <= 0 || output->extmap.id == 15 || output->extmap.id >= 256) |
|
|
|
return false; |
|
|
|
|
|
|
|
return true; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static bool parse_attribute(struct sdp_attribute *a) { |
|
|
|
a->strs.name = a->strs.line_value; |
|
|
|
@ -1194,7 +1218,7 @@ static bool parse_attribute(struct sdp_attribute *a) { |
|
|
|
ret = parse_attribute_crypto(a); |
|
|
|
break; |
|
|
|
case CSH_LOOKUP("extmap"): |
|
|
|
a->other = ATTR_OTHER_EXTMAP; |
|
|
|
ret = parse_attribute_extmap(a); |
|
|
|
break; |
|
|
|
case CSH_LOOKUP("rtpmap"): |
|
|
|
ret = parse_attribute_rtpmap(a); |
|
|
|
@ -1750,6 +1774,7 @@ static void sp_free(struct stream_params *s) { |
|
|
|
crypto_params_sdes_queue_clear(&s->sdes_params); |
|
|
|
t_queue_clear_full(&s->generic_attributes, sdp_attr_free); |
|
|
|
t_queue_clear_full(&s->all_attributes, sdp_attr_free); |
|
|
|
t_queue_clear_full(&s->extmap, rtp_extension_free); |
|
|
|
g_free(s); |
|
|
|
} |
|
|
|
|
|
|
|
@ -2078,6 +2103,18 @@ bool sdp_streams(const sdp_sessions_q *sessions, sdp_streams_q *streams, sdp_ng_ |
|
|
|
|
|
|
|
__sdp_t38(sp, media); |
|
|
|
|
|
|
|
// a=extmap |
|
|
|
attrs = attr_list_get_by_id(&media->attributes, ATTR_EXTMAP); |
|
|
|
if (!attrs) |
|
|
|
attrs = attr_list_get_by_id(&session->attributes, ATTR_EXTMAP); |
|
|
|
for (__auto_type ll = attrs ? attrs->head : NULL; ll; ll = ll->next) { |
|
|
|
attr = ll->data; |
|
|
|
__auto_type ext = g_new0(struct rtp_extension, 1); |
|
|
|
ext->id = attr->extmap.id; |
|
|
|
ext->name = attr->extmap.ext; |
|
|
|
t_queue_push_tail(&sp->extmap, ext); |
|
|
|
} |
|
|
|
|
|
|
|
/* determine RTCP endpoint */ |
|
|
|
|
|
|
|
if (attr_get_by_id(&media->attributes, ATTR_RTCP_MUX)) |
|
|
|
@ -2188,8 +2225,6 @@ void sdp_insert_media_attributes(GString *gs, struct call_media *media, struct c |
|
|
|
return; |
|
|
|
for (__auto_type l = source_media->generic_attributes.head; l; l = l->next) { |
|
|
|
__auto_type s = l->data; |
|
|
|
if (s->other == ATTR_OTHER_EXTMAP && flags->strip_extmap && !MEDIA_ISSET(source_media, PASSTHRU)) |
|
|
|
continue; |
|
|
|
append_gen_attr_to_gstring(gs, &s->strs.name, &s->strs.value, flags, source_media->type_id); |
|
|
|
} |
|
|
|
} |
|
|
|
@ -2203,8 +2238,6 @@ void sdp_insert_monologue_attributes(GString *gs, struct call_monologue *ml, con |
|
|
|
|
|
|
|
for (__auto_type l = source_ml->generic_attributes.head; l; l = l->next) { |
|
|
|
__auto_type s = l->data; |
|
|
|
if (s->other == ATTR_OTHER_EXTMAP && flags->strip_extmap) |
|
|
|
continue; |
|
|
|
append_gen_attr_to_gstring(gs, &s->strs.name, &s->strs.value, flags, MT_UNKNOWN); |
|
|
|
} |
|
|
|
} |
|
|
|
@ -2219,6 +2252,19 @@ void sdp_insert_all_attributes(GString *s, struct call_media *media, struct sdp_ |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
static void sdp_print_extmap(GString *s, struct call_media *source_media, const sdp_ng_flags *flags) { |
|
|
|
if (!source_media) |
|
|
|
return; |
|
|
|
if (flags->strip_extmap && !MEDIA_ISSET(source_media, PASSTHRU)) |
|
|
|
return; |
|
|
|
|
|
|
|
for (__auto_type l = source_media->extmap.head; l; l = l->next) { |
|
|
|
__auto_type ext = l->data; |
|
|
|
sdp_append_attr(s, flags, source_media->type_id, |
|
|
|
"extmap", "%u " STR_FORMAT, ext->id, STR_FMT(&ext->name)); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
static bool insert_ice_address(const struct sdp_state *state, stream_fd *sfd, const sdp_ng_flags *flags) { |
|
|
|
if (!is_addr_unspecified(&flags->media_address)) |
|
|
|
sockaddr_print_gstring(state->s, &flags->media_address); |
|
|
|
@ -2806,6 +2852,8 @@ static void print_sdp_media_section(GString *s, struct call_media *media, |
|
|
|
if (proto_is_rtp(media->protocol)) |
|
|
|
insert_codec_parameters(s, media, flags); |
|
|
|
|
|
|
|
sdp_print_extmap(s, source_media, flags); |
|
|
|
|
|
|
|
/* all unknown type attributes will be added here */ |
|
|
|
media->sdp_attr_print(s, media, source_media, flags); |
|
|
|
|
|
|
|
|