diff --git a/daemon/call.c b/daemon/call.c index 3dd2ae758..2dfdb342d 100644 --- a/daemon/call.c +++ b/daemon/call.c @@ -2430,10 +2430,9 @@ int monologue_offer_answer(struct call_monologue *dialogue[2], GQueue *streams, SHARED_FLAG_ICE | SHARED_FLAG_TRICKLE_ICE | SHARED_FLAG_ICE_LITE_PEER | SHARED_FLAG_RTCP_FB); - // steal the entire queue of offered crypto params + // duplicate the entire queue of offered crypto params crypto_params_sdes_queue_clear(&other_media->sdes_in); - other_media->sdes_in = sp->sdes_params; - g_queue_init(&sp->sdes_params); + crypto_params_sdes_queue_copy(&other_media->sdes_in, &sp->sdes_params); if (other_media->sdes_in.length) { MEDIA_SET(other_media, SDES); @@ -3025,9 +3024,12 @@ static void __call_free(void *p) { g_hash_table_destroy(m->other_tags); g_hash_table_destroy(m->branches); g_hash_table_destroy(m->media_ids); - if (m->last_sdp) - g_string_free(m->last_sdp, TRUE); free_ssrc_hash(&m->ssrc_hash); + if (m->last_out_sdp) + g_string_free(m->last_out_sdp, TRUE); + str_free_dup(&m->last_in_sdp); + sdp_free(&m->last_in_sdp_parsed); + sdp_streams_free(&m->last_in_sdp_streams); g_slice_free1(sizeof(*m), m); } diff --git a/daemon/call_interfaces.c b/daemon/call_interfaces.c index 78eb14dcf..7122eadfe 100644 --- a/daemon/call_interfaces.c +++ b/daemon/call_interfaces.c @@ -1320,11 +1320,28 @@ static void fragments_cleanup(int all) { mutex_unlock(&sdp_fragments_lock); } + +static void save_last_sdp(struct call_monologue *ml, str *sdp, GQueue *parsed, GQueue *streams) { + str_free_dup(&ml->last_in_sdp); + ml->last_in_sdp = *sdp; + *sdp = STR_NULL; + + sdp_free(&ml->last_in_sdp_parsed); + ml->last_in_sdp_parsed = *parsed; + g_queue_init(parsed); + + sdp_streams_free(&ml->last_in_sdp_streams); + ml->last_in_sdp_streams = *streams; + g_queue_init(streams); +} + + static const char *call_offer_answer_ng(struct ng_buffer *ngbuf, bencode_item_t *input, bencode_item_t *output, enum call_opmode opmode, const char* addr, const endpoint_t *sin) { const char *errstr; + AUTO_CLEANUP(str sdp, str_free_dup) = STR_NULL; AUTO_CLEANUP(GQueue parsed, sdp_free) = G_QUEUE_INIT; AUTO_CLEANUP(GQueue streams, sdp_streams_free) = G_QUEUE_INIT; struct call *call; @@ -1347,13 +1364,15 @@ static const char *call_offer_answer_ng(struct ng_buffer *ngbuf, bencode_item_t str_swap(&flags.to_tag, &flags.from_tag); } + str_init_dup_str(&sdp, &flags.sdp); + errstr = "Failed to parse SDP"; - if (sdp_parse(&flags.sdp, &parsed, &flags)) + if (sdp_parse(&sdp, &parsed, &flags)) goto out; if (flags.loop_protect && sdp_is_duplicate(&parsed)) { ilog(LOG_INFO, "Ignoring message as SDP has already been processed by us"); - bencode_dictionary_add_str(output, "sdp", &flags.sdp); + bencode_dictionary_add_str(output, "sdp", &sdp); errstr = NULL; goto out; } @@ -1420,7 +1439,7 @@ static const char *call_offer_answer_ng(struct ng_buffer *ngbuf, bencode_item_t dialogue[0]->tagtype = TO_TAG; } - chopper = sdp_chopper_new(&flags.sdp); + chopper = sdp_chopper_new(&sdp); bencode_buffer_destroy_add(output->buffer, (free_func_t) sdp_chopper_destroy, chopper); detect_setup_recording(call, &flags.record_call_str, &flags.metadata); @@ -1451,11 +1470,12 @@ static const char *call_offer_answer_ng(struct ng_buffer *ngbuf, bencode_item_t do_dequeue = 0; } - // streams and flags are invalid after here + if (!ret) + save_last_sdp(dialogue[0], &sdp, &parsed, &streams); struct recording *recording = call->recording; if (recording != NULL) { - meta_write_sdp_before(recording, &flags.sdp, dialogue[0], opmode); + meta_write_sdp_before(recording, &sdp, dialogue[0], opmode); meta_write_sdp_after(recording, chopper->output, dialogue[0], opmode); diff --git a/daemon/sdp.c b/daemon/sdp.c index 73ba0e242..b91a45b51 100644 --- a/daemon/sdp.c +++ b/daemon/sdp.c @@ -2446,17 +2446,17 @@ static void sdp_version_check(struct sdp_chopper *chop, GQueue *sessions, struct // first update all versions to match our single version sdp_version_replace(chop, sessions, monologue); // then check if we need to change - if (!monologue->last_sdp) + if (!monologue->last_out_sdp) goto dup; - if (g_string_equal(monologue->last_sdp, chop->output)) + if (g_string_equal(monologue->last_out_sdp, chop->output)) return; // mismatch detected. increment version, update again, and store copy monologue->sdp_version++; sdp_version_replace(chop, sessions, monologue); - g_string_free(monologue->last_sdp, TRUE); + g_string_free(monologue->last_out_sdp, TRUE); dup: - monologue->last_sdp = g_string_new_len(chop->output->str, chop->output->len); + monologue->last_out_sdp = g_string_new_len(chop->output->str, chop->output->len); } diff --git a/include/call.h b/include/call.h index 9f6866312..f26368fb2 100644 --- a/include/call.h +++ b/include/call.h @@ -403,7 +403,10 @@ struct call_monologue { GHashTable *media_ids; struct media_player *player; unsigned long long sdp_version; - GString *last_sdp; + str last_in_sdp; + GQueue last_in_sdp_parsed; + GQueue last_in_sdp_streams; + GString *last_out_sdp; char *sdp_username; char *sdp_session_name; struct ssrc_hash *ssrc_hash; diff --git a/include/crypto.h b/include/crypto.h index 5a60e6631..44cc3f46b 100644 --- a/include/crypto.h +++ b/include/crypto.h @@ -207,6 +207,15 @@ INLINE void crypto_params_sdes_free(struct crypto_params_sdes *cps) { INLINE void crypto_params_sdes_queue_clear(GQueue *q) { g_queue_clear_full(q, (GDestroyNotify) crypto_params_sdes_free); } +INLINE void crypto_params_sdes_queue_copy(GQueue *dst, const GQueue *src) { + for (const GList *l = src->head; l; l = l->next) { + struct crypto_params_sdes *cps = l->data; + struct crypto_params_sdes *cpy = g_slice_alloc(sizeof(*cpy)); + *cpy = *cps; + crypto_params_copy(&cpy->params, &cps->params, 1); + g_queue_push_tail(dst, cpy); + } +} #include "main.h"