diff --git a/daemon/call_interfaces.c b/daemon/call_interfaces.c index 35e9fb6f8..8a1187a48 100644 --- a/daemon/call_interfaces.c +++ b/daemon/call_interfaces.c @@ -2061,8 +2061,6 @@ static const char *call_offer_answer_ng(struct ng_buffer *ngbuf, bencode_item_t call->drop_traffic = 0; } - bool do_dequeue = true; - ret = monologue_offer_answer(dialogue, &streams, &flags); if (!ret) ret = sdp_replace(chopper, &parsed, dialogue[1], &flags); @@ -2078,8 +2076,7 @@ static const char *call_offer_answer_ng(struct ng_buffer *ngbuf, bencode_item_t recording_response(recording, output); } - if (do_dequeue) - dequeue_sdp_fragments(dialogue[0]); + dequeue_sdp_fragments(dialogue[0]); rwlock_unlock_w(&call->master_lock); diff --git a/daemon/janus.c b/daemon/janus.c index d6aedad8f..6abacf0ad 100644 --- a/daemon/janus.c +++ b/daemon/janus.c @@ -1553,51 +1553,49 @@ const char *janus_trickle(JsonReader *reader, struct janus_session *session, uin if (!ml) return "Handle not found in room"; - // find our media section - struct call_media *media = NULL; + // set up "streams" structures to use an trickle ICE update. these must be + // allocated in case of delayed trickle ICE updates. it's using a refcounted + // ng_buffer as storage. + + *successp = "ack"; + + // top-level structures first, with auto cleanup + AUTO_CLEANUP(GQueue streams, sdp_streams_free) = G_QUEUE_INIT; + AUTO_CLEANUP(struct ng_buffer *ngbuf, ng_buffer_auto_release) = ng_buffer_new(NULL); + + // then the contained structures, and add them in + struct stream_params *sp = g_slice_alloc0(sizeof(*sp)); + g_queue_push_tail(&streams, sp); + struct ice_candidate *cand = g_slice_alloc0(sizeof(*cand)); + g_queue_push_tail(&sp->ice_candidates, cand); + + // populate and allocate a=mid if (sdp_mid) { - str sdp_mid_str = STR_CONST_INIT_LEN((char *) sdp_mid, strlen(sdp_mid)); - media = g_hash_table_lookup(ml->media_ids, &sdp_mid_str); + sp->media_id.len = strlen(sdp_mid); + sp->media_id.s = bencode_strdup(&ngbuf->buffer, sdp_mid); } - if (!media && sdp_m_line >= 0 && ml->medias->len > sdp_m_line) - media = ml->medias->pdata[sdp_m_line]; + + // allocate and parse candidate + str cand_str = STR_CONST_INIT_LEN(bencode_strdup(&ngbuf->buffer, candidate), strlen(candidate)); + str_shift_cmp(&cand_str, "candidate:"); // skip prefix + if (!cand_str.len) // end of candidates + return NULL; *retcode = 466; - if (!media) - return "No matching media"; - if (!media->ice_agent) - return "Media is not ICE-enabled"; + int ret = sdp_parse_candidate(cand, &cand_str); + if (ret < 0) + return "Failed to parse trickle candidate"; + if (ret > 0) + return NULL; // unsupported candidate type, accept and ignore it - // parse candidate - str cand_str = STR_CONST_INIT_LEN((char *) candidate, strlen(candidate)); - str_shift_cmp(&cand_str, "candidate:"); // skip prefix - if (!cand_str.len) { - // end of candidates - } - else { - struct ice_candidate cand; - *retcode = 466; - int ret = sdp_parse_candidate(&cand, &cand_str); - if (ret < 0) - return "Failed to parse trickle candidate"; - - if (ret == 0) { - // do the actual ICE update - struct stream_params sp = { - .ice_ufrag = cand.ufrag, - .index = media->index, - }; - if (!sp.ice_ufrag.len && ufrag) - str_init(&sp.ice_ufrag, (char *) ufrag); - g_queue_push_tail(&sp.ice_candidates, &cand); - - ice_update(media->ice_agent, &sp, false); - - g_queue_clear(&sp.ice_candidates); - } - } + // ufrag can be given in-line or separately + sp->ice_ufrag = cand->ufrag; + if (!sp->ice_ufrag.len && ufrag) + str_init_len(&sp->ice_ufrag, bencode_strdup(&ngbuf->buffer, ufrag), strlen(ufrag)); + + // finally do the update + ice_update_media_streams(ml, &streams); - *successp = "ack"; return NULL; }