|
|
|
|
@ -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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|