|
|
|
|
@ -2881,12 +2881,35 @@ static void media_set_siprec_label(struct call_media *other_media, struct call_m
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
__attribute__((nonnull(1)))
|
|
|
|
|
static unsigned int media_extmap_id(struct call_media *media) {
|
|
|
|
|
static unsigned int media_bundle_extmap_id(struct call_media *media) {
|
|
|
|
|
__auto_type ml = media->monologue;
|
|
|
|
|
|
|
|
|
|
// XXX slow search?
|
|
|
|
|
for (unsigned int i = 1; i < 255; i++) {
|
|
|
|
|
if (!media->extmap_ops->lookup(media, i))
|
|
|
|
|
if (media->extmap_ops->lookup(media, i))
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
// used by any other media in the bundle?
|
|
|
|
|
bool good = true;
|
|
|
|
|
// XXX even worse search
|
|
|
|
|
for (unsigned int j = 0; j < ml->medias->len; j++) {
|
|
|
|
|
__auto_type bundle_media = ml->medias->pdata[j];
|
|
|
|
|
if (!bundle_media)
|
|
|
|
|
continue;
|
|
|
|
|
if (bundle_media == media)
|
|
|
|
|
continue;
|
|
|
|
|
if (bundle_media->bundle != media->bundle)
|
|
|
|
|
continue;
|
|
|
|
|
if (bundle_media->extmap_ops->lookup(bundle_media, i)) {
|
|
|
|
|
good = false;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (good)
|
|
|
|
|
return i;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return -1u;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -2958,7 +2981,8 @@ static void media_init_extmap(struct call_media *media, struct rtp_extension *ex
|
|
|
|
|
|
|
|
|
|
t_hash_table_insert(media->extmap_ht, GUINT_TO_POINTER(ext->id), ext);
|
|
|
|
|
|
|
|
|
|
ext->handler = rtp_extension_get_handler(&ext->name);
|
|
|
|
|
if (!ext->handler.set)
|
|
|
|
|
ext->handler = rtp_extension_get_handler(&ext->name);
|
|
|
|
|
|
|
|
|
|
if (ext->id > 0 && ext->id <= 14)
|
|
|
|
|
media->extmap_a[ext->id - 1] = ext;
|
|
|
|
|
@ -3531,6 +3555,73 @@ static void monologue_bundle_set_sinks(struct call_monologue *ml) {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// see if any other media in a bundle has the extension already
|
|
|
|
|
static struct rtp_extension *monologue_ext_any_bundle(struct call_media *media, unsigned int id) {
|
|
|
|
|
__auto_type ml = media->monologue;
|
|
|
|
|
__auto_type bundle = media->bundle;
|
|
|
|
|
// XXX bit silly to do this in a loop
|
|
|
|
|
for (unsigned int i = 0; i < ml->medias->len; i++) {
|
|
|
|
|
__auto_type bundle_media = ml->medias->pdata[i];
|
|
|
|
|
if (!bundle_media)
|
|
|
|
|
continue;
|
|
|
|
|
if (bundle_media->bundle != bundle)
|
|
|
|
|
continue;
|
|
|
|
|
if (bundle_media->extmap_id[id])
|
|
|
|
|
return bundle_media->extmap_id[id];
|
|
|
|
|
}
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
__attribute__((nonnull(1)))
|
|
|
|
|
static void monologue_bundle_mid(struct call_monologue *ml) {
|
|
|
|
|
for (unsigned int i = 0; i < ml->medias->len; i++) {
|
|
|
|
|
__auto_type media = ml->medias->pdata[i];
|
|
|
|
|
if (!media)
|
|
|
|
|
continue;
|
|
|
|
|
if (!media->bundle)
|
|
|
|
|
continue;
|
|
|
|
|
if (media->extmap_id[RTP_EXT_MID])
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
struct rtp_extension *new_ext;
|
|
|
|
|
|
|
|
|
|
__auto_type ext = monologue_ext_any_bundle(media, RTP_EXT_MID);
|
|
|
|
|
if (ext) {
|
|
|
|
|
__auto_type ext_exist = media->extmap_ops->lookup(media, ext->id);
|
|
|
|
|
if (ext_exist) {
|
|
|
|
|
// XXX ideally we would support extension renumbering here
|
|
|
|
|
ilog(LOG_WARN, "RTP header extension collision for MID (%u vs "
|
|
|
|
|
"%u/'" STR_FORMAT "'), removing it in favour of MID",
|
|
|
|
|
ext->id, ext_exist->id, STR_FMT(&ext_exist->name));
|
|
|
|
|
t_hash_table_remove(media->extmap_ht, GUINT_TO_POINTER(ext_exist->id));
|
|
|
|
|
if (ext_exist->id <= 14)
|
|
|
|
|
media->extmap_a[ext_exist->id] = NULL;
|
|
|
|
|
t_queue_remove(&media->extmap, ext_exist); // XXX also not ideal
|
|
|
|
|
rtp_extension_free(ext_exist);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
new_ext = g_new(struct rtp_extension, 1);
|
|
|
|
|
*new_ext = *ext;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
unsigned int id = media_bundle_extmap_id(media);
|
|
|
|
|
if (id == -1u) {
|
|
|
|
|
ilog(LOG_WARN, "Out of IDs for RTP header extension");
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
new_ext = g_new(struct rtp_extension, 1);
|
|
|
|
|
*new_ext = media_rtp_ext_mid;
|
|
|
|
|
new_ext->id = id;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
new_ext->synthetic = true;
|
|
|
|
|
new_ext->accepted = true;
|
|
|
|
|
t_queue_push_tail(&media->extmap, new_ext);
|
|
|
|
|
media_init_extmap(media, new_ext);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
__attribute__((nonnull(1, 2)))
|
|
|
|
|
static void monologue_bundle_offer(struct call_monologue *ml, sdp_ng_flags *flags) {
|
|
|
|
|
if (!flags->bundle_offer || flags->opmode != OP_OFFER)
|
|
|
|
|
@ -3570,27 +3661,11 @@ static void monologue_bundle_offer(struct call_monologue *ml, sdp_ng_flags *flag
|
|
|
|
|
// set bundle group
|
|
|
|
|
media->bundle = bundle;
|
|
|
|
|
|
|
|
|
|
// offer MID header extension
|
|
|
|
|
if (!media->extmap_id[RTP_EXT_MID]) {
|
|
|
|
|
unsigned int id = media_extmap_id(media);
|
|
|
|
|
if (id == -1u)
|
|
|
|
|
ilog(LOG_WARN, "Out of IDs for RTP header extension");
|
|
|
|
|
else {
|
|
|
|
|
__auto_type ext = g_new0(struct rtp_extension, 1);
|
|
|
|
|
// XXX string duplication and duplicate lookup via init_extmap -> get_handler
|
|
|
|
|
ext->name = STR("urn:ietf:params:rtp-hdrext:sdes:mid");
|
|
|
|
|
ext->id = id;
|
|
|
|
|
ext->synthetic = true;
|
|
|
|
|
t_queue_push_tail(&media->extmap, ext);
|
|
|
|
|
media_init_extmap(media, ext);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
track_bundle_media_pt(media, exclude_pt);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
monologue_bundle_check_consistency(ml);
|
|
|
|
|
monologue_bundle_check_heads(ml);
|
|
|
|
|
// make sure MID is offered for all medias in a bundle
|
|
|
|
|
monologue_bundle_mid(ml);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
__attribute__((nonnull(1, 2)))
|
|
|
|
|
@ -3885,6 +3960,7 @@ int monologue_offer_answer(struct call_monologue *monologues[2], sdp_streams_q *
|
|
|
|
|
monologue_bundle_accept(sender_ml, flags);
|
|
|
|
|
monologue_bundle_offer(receiver_ml, flags);
|
|
|
|
|
monologue_bundle_check_consistency(receiver_ml);
|
|
|
|
|
monologue_bundle_check_heads(receiver_ml);
|
|
|
|
|
monologue_bundle_set_fds(receiver_ml);
|
|
|
|
|
monologue_bundle_set_sinks(sender_ml);
|
|
|
|
|
monologue_bundle_set_sinks(receiver_ml);
|
|
|
|
|
|