MT#61802 retain offered codecs across answers

The `answer` processing empties out the list of codecs and leaves only
those that were accepted in the answer. Side effect of this is that if
another answer with a different list of codecs comes through, them the
codec-accept function is missing the original list of offered codecs and
can yield an incorrect result.

Fix this by storing a copy of the offered codecs at the end of the
`offer` processing, and then restore this list at the beginning of each
`answer` message.

Change-Id: I3c714e80689f3c5689637cc7d1eb2f203c292a15
pull/1897/head
Richard Fuchs 4 months ago
parent acc30ec0fa
commit 34e007defc

@ -664,6 +664,7 @@ struct call_media *call_media_new(call_t *call) {
med = uid_slice_alloc0(med, &call->medias.q);
med->call = call;
codec_store_init(&med->codecs, med);
codec_store_init(&med->offered_codecs, med);
med->media_subscribers_ht = subscription_ht_new();
med->media_subscriptions_ht = subscription_ht_new();
mutex_init(&med->dtmf_lock);
@ -2507,6 +2508,9 @@ static void codecs_offer(struct call_media *media, struct call_media *other_medi
codec_handlers_update(media, other_media, .flags = flags, .sp = sp,
.allow_asymmetric = !!(flags->allow_asymmetric_codecs),
.reset_transcoding = true);
// keep a copy of the final list of what was offered
codec_store_copy(&other_media->offered_codecs, &other_media->codecs);
}
__attribute__((nonnull(1, 2, 3, 4)))
@ -2537,6 +2541,9 @@ static void codecs_answer(struct call_media *media, struct call_media *other_med
codec_store_offer(&other_media->codecs, &flags->codec_offer, &sp->codecs);
codec_store_check_empty(&other_media->codecs, &sp->codecs, flags);
// restore list of originally offered codecs
codec_store_copy(&media->codecs, &media->offered_codecs);
// update callee side codec handlers again (second pass after the offer) as we
// might need to update some handlers, e.g. when supplemental codecs have been
// rejected
@ -4093,6 +4100,7 @@ void call_media_free(struct call_media **mdp) {
t_queue_clear(&md->streams);
t_queue_clear(&md->endpoint_maps);
codec_store_cleanup(&md->codecs);
codec_store_cleanup(&md->offered_codecs);
codec_handlers_free(md);
codec_handler_free(&md->t38_handler);
t38_gateway_put(&md->t38_gateway);

@ -5248,6 +5248,30 @@ void __codec_store_populate(struct codec_store *dst, struct codec_store *src, st
codec_store_cleanup(&orig_dst);
}
void codec_store_copy(struct codec_store *dst, struct codec_store *src) {
codec_store_init(dst, src->media);
for (__auto_type l = src->codec_prefs.head; l; l = l->next) {
rtp_payload_type *pt = l->data;
codec_store_add_end(dst, pt);
if (l == src->supp_link)
dst->supp_link = dst->codec_prefs.tail;
}
dst->strip_full = src->strip_full;
dst->strip_all = src->strip_all;
#ifdef WITH_TRANSCODING
dst->tracker->all_touched = src->tracker->all_touched;
GHashTableIter iter;
g_hash_table_iter_init(&iter, src->tracker->touched);
void *key;
while (g_hash_table_iter_next(&iter, &key, NULL))
g_hash_table_insert(dst->tracker->touched, key, (void *) 0x1);
#endif
}
void codec_store_strip(struct codec_store *cs, str_q *strip, str_case_ht except) {
for (__auto_type l = strip->head; l; l = l->next) {
str *codec = l->data;

@ -504,6 +504,7 @@ struct call_media {
endpoint_map_q endpoint_maps;
struct codec_store codecs;
struct codec_store offered_codecs;
sdp_attr_q generic_attributes; /* sdp_attr_new() */
sdp_attr_q all_attributes; /* sdp_attr_new() */
sdp_attr_print_f *sdp_attr_print;

@ -136,6 +136,7 @@ void __codec_store_populate_reuse(struct codec_store *, struct codec_store *, st
#define codec_store_populate_reuse(dst, src, ...) \
__codec_store_populate_reuse(dst, src, (struct codec_store_args) {__VA_ARGS__})
__attribute__((nonnull(1, 2)))
void codec_store_copy(struct codec_store *, struct codec_store *);
void codec_store_add_raw(struct codec_store *cs, rtp_payload_type *pt);
__attribute__((nonnull(1, 2)))
void codec_store_strip(struct codec_store *, str_q *strip, str_case_ht except);

@ -83,6 +83,133 @@ sub stun_succ {
new_call;
offer('double answer codec change', { }, <<SDP);
v=0
o=- 1545997027 1 IN IP4 198.51.100.23
s=tester
c=IN IP4 198.51.100.35
t=0 0
m=audio 3000 RTP/AVP 0 8 9
---------------------------------------------
v=0
o=- 1545997027 1 IN IP4 198.51.100.23
s=tester
t=0 0
m=audio PORT RTP/AVP 0 8 9
c=IN IP4 203.0.113.1
a=rtpmap:0 PCMU/8000
a=rtpmap:8 PCMA/8000
a=rtpmap:9 G722/8000
a=sendrecv
a=rtcp:PORT
SDP
answer('double answer codec change', { }, <<SDP);
v=0
o=- 1545997027 1 IN IP4 198.51.100.23
s=tester
c=IN IP4 198.51.100.35
t=0 0
m=audio 3000 RTP/AVP 0
---------------------------------------------
v=0
o=- 1545997027 1 IN IP4 198.51.100.23
s=tester
t=0 0
m=audio PORT RTP/AVP 0
c=IN IP4 203.0.113.1
a=rtpmap:0 PCMU/8000
a=sendrecv
a=rtcp:PORT
SDP
answer('double answer codec change', { }, <<SDP);
v=0
o=- 1545997027 1 IN IP4 198.51.100.23
s=tester
c=IN IP4 198.51.100.35
t=0 0
m=audio 3000 RTP/AVP 8
---------------------------------------------
v=0
o=- 1545997027 1 IN IP4 198.51.100.23
s=tester
t=0 0
m=audio PORT RTP/AVP 8
c=IN IP4 203.0.113.1
a=rtpmap:8 PCMA/8000
a=sendrecv
a=rtcp:PORT
SDP
new_call;
offer('double answer codec change with new to-tag', { }, <<SDP);
v=0
o=- 1545997027 1 IN IP4 198.51.100.23
s=tester
c=IN IP4 198.51.100.35
t=0 0
m=audio 3000 RTP/AVP 0 8 9
---------------------------------------------
v=0
o=- 1545997027 1 IN IP4 198.51.100.23
s=tester
t=0 0
m=audio PORT RTP/AVP 0 8 9
c=IN IP4 203.0.113.1
a=rtpmap:0 PCMU/8000
a=rtpmap:8 PCMA/8000
a=rtpmap:9 G722/8000
a=sendrecv
a=rtcp:PORT
SDP
answer('double answer codec change with new to-tag', { }, <<SDP);
v=0
o=- 1545997027 1 IN IP4 198.51.100.23
s=tester
c=IN IP4 198.51.100.35
t=0 0
m=audio 3000 RTP/AVP 0
---------------------------------------------
v=0
o=- 1545997027 1 IN IP4 198.51.100.23
s=tester
t=0 0
m=audio PORT RTP/AVP 0
c=IN IP4 203.0.113.1
a=rtpmap:0 PCMU/8000
a=sendrecv
a=rtcp:PORT
SDP
new_tt;
answer('double answer codec change with new to-tag', { }, <<SDP);
v=0
o=- 1545997027 1 IN IP4 198.51.100.23
s=tester
c=IN IP4 198.51.100.35
t=0 0
m=audio 3000 RTP/AVP 8
---------------------------------------------
v=0
o=- 1545997027 1 IN IP4 198.51.100.23
s=tester
t=0 0
m=audio PORT RTP/AVP 8
c=IN IP4 203.0.113.1
a=rtpmap:8 PCMA/8000
a=sendrecv
a=rtcp:PORT
SDP
($sock_a, $sock_b) = new_call([qw(198.51.100.65 3000)], [qw(198.51.100.65 3002)]);
($port_a) = offer('opus<>opus+DTMF', { }, <<SDP);

Loading…
Cancel
Save