diff --git a/daemon/call.c b/daemon/call.c index 918ff3303..d0599f7ce 100644 --- a/daemon/call.c +++ b/daemon/call.c @@ -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); diff --git a/daemon/codec.c b/daemon/codec.c index d0034d83c..b8c32691f 100644 --- a/daemon/codec.c +++ b/daemon/codec.c @@ -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; diff --git a/include/call.h b/include/call.h index 0653620fd..2c0d64456 100644 --- a/include/call.h +++ b/include/call.h @@ -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; diff --git a/include/codec.h b/include/codec.h index 2103ba76f..076128dab 100644 --- a/include/codec.h +++ b/include/codec.h @@ -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); diff --git a/t/auto-daemon-tests.pl b/t/auto-daemon-tests.pl index 434af6135..005ace76e 100755 --- a/t/auto-daemon-tests.pl +++ b/t/auto-daemon-tests.pl @@ -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);