|
|
|
@ -93,8 +93,17 @@ const char * const ice_type_strings[] = {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static unsigned int frag_key_hash(const void *A);
|
|
|
|
|
static int frag_key_eq(const void *A, const void *B);
|
|
|
|
|
static void fragment_key_free(struct fragment_key *);
|
|
|
|
|
|
|
|
|
|
TYPED_GQUEUE(fragment, struct sdp_fragment)
|
|
|
|
|
TYPED_GHASHTABLE(fragments_ht, struct fragment_key, fragment_q, frag_key_hash, frag_key_eq,
|
|
|
|
|
fragment_key_free, NULL)
|
|
|
|
|
TYPED_GHASHTABLE_LOOKUP_INSERT(fragments_ht, fragment_key_free, fragment_q_new)
|
|
|
|
|
|
|
|
|
|
static mutex_t sdp_fragments_lock;
|
|
|
|
|
static GHashTable *sdp_fragments;
|
|
|
|
|
static fragments_ht sdp_fragments;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -147,8 +156,7 @@ static void fragment_free(struct sdp_fragment *frag) {
|
|
|
|
|
obj_put(frag->ngbuf);
|
|
|
|
|
g_slice_free1(sizeof(*frag), frag);
|
|
|
|
|
}
|
|
|
|
|
static void fragment_key_free(void *p) {
|
|
|
|
|
struct fragment_key *k = p;
|
|
|
|
|
static void fragment_key_free(struct fragment_key *k) {
|
|
|
|
|
g_free(k->call_id.s);
|
|
|
|
|
g_free(k->from_tag.s);
|
|
|
|
|
g_slice_free1(sizeof(*k), k);
|
|
|
|
@ -170,8 +178,8 @@ static void queue_sdp_fragment(ng_buffer *ngbuf, sdp_streams_q *streams, sdp_ng_
|
|
|
|
|
ZERO(*flags);
|
|
|
|
|
|
|
|
|
|
mutex_lock(&sdp_fragments_lock);
|
|
|
|
|
GQueue *frags = g_hash_table_lookup_queue_new(sdp_fragments, k, fragment_key_free);
|
|
|
|
|
g_queue_push_tail(frags, frag);
|
|
|
|
|
fragment_q *frags = fragments_ht_lookup_insert(sdp_fragments, k);
|
|
|
|
|
t_queue_push_tail(frags, frag);
|
|
|
|
|
mutex_unlock(&sdp_fragments_lock);
|
|
|
|
|
}
|
|
|
|
|
bool trickle_ice_update(ng_buffer *ngbuf, struct call *call, sdp_ng_flags *flags,
|
|
|
|
@ -201,11 +209,11 @@ void dequeue_sdp_fragments(struct call_monologue *monologue) {
|
|
|
|
|
k.call_id = monologue->call->callid;
|
|
|
|
|
k.from_tag = monologue->tag;
|
|
|
|
|
|
|
|
|
|
GQueue *frags = NULL;
|
|
|
|
|
fragment_q *frags = NULL;
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
LOCK(&sdp_fragments_lock);
|
|
|
|
|
g_hash_table_steal_extended(sdp_fragments, &k, NULL, (void **) &frags);
|
|
|
|
|
t_hash_table_steal_extended(sdp_fragments, &k, NULL, &frags);
|
|
|
|
|
if (!frags)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
@ -213,7 +221,7 @@ void dequeue_sdp_fragments(struct call_monologue *monologue) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct sdp_fragment *frag;
|
|
|
|
|
while ((frag = g_queue_pop_head(frags))) {
|
|
|
|
|
while ((frag = t_queue_pop_head(frags))) {
|
|
|
|
|
if (timeval_diff(&rtpe_now, &frag->received) > MAX_FRAG_AGE)
|
|
|
|
|
goto next;
|
|
|
|
|
|
|
|
|
@ -226,30 +234,28 @@ next:
|
|
|
|
|
fragment_free(frag);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
g_queue_free(frags);
|
|
|
|
|
t_queue_free(frags);
|
|
|
|
|
}
|
|
|
|
|
static gboolean fragment_check_cleanup(void *k, void *v, void *p) {
|
|
|
|
|
static gboolean fragment_check_cleanup(struct fragment_key *key, fragment_q *frags, void *p) {
|
|
|
|
|
bool all = GPOINTER_TO_INT(p);
|
|
|
|
|
struct fragment_key *key = k;
|
|
|
|
|
GQueue *frags = v;
|
|
|
|
|
if (!key || !frags)
|
|
|
|
|
return TRUE;
|
|
|
|
|
while (frags->length) {
|
|
|
|
|
struct sdp_fragment *frag = frags->head->data;
|
|
|
|
|
if (!all && timeval_diff(&rtpe_now, &frag->received) <= MAX_FRAG_AGE)
|
|
|
|
|
break;
|
|
|
|
|
g_queue_pop_head(frags);
|
|
|
|
|
t_queue_pop_head(frags);
|
|
|
|
|
fragment_free(frag);
|
|
|
|
|
}
|
|
|
|
|
if (!frags->length) {
|
|
|
|
|
g_queue_free(frags);
|
|
|
|
|
t_queue_free(frags);
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
static void fragments_cleanup(bool all) {
|
|
|
|
|
mutex_lock(&sdp_fragments_lock);
|
|
|
|
|
g_hash_table_foreach_remove(sdp_fragments, fragment_check_cleanup, GINT_TO_POINTER(all));
|
|
|
|
|
t_hash_table_foreach_remove(sdp_fragments, fragment_check_cleanup, GINT_TO_POINTER(all));
|
|
|
|
|
mutex_unlock(&sdp_fragments_lock);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -751,7 +757,7 @@ void ice_init(void) {
|
|
|
|
|
random_string((void *) &tie_breaker, sizeof(tie_breaker));
|
|
|
|
|
timerthread_init(&ice_agents_timer_thread, ice_agents_timer_run);
|
|
|
|
|
|
|
|
|
|
sdp_fragments = g_hash_table_new_full(frag_key_hash, frag_key_eq, fragment_key_free, NULL);
|
|
|
|
|
sdp_fragments = fragments_ht_new();
|
|
|
|
|
mutex_init(&sdp_fragments_lock);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -759,8 +765,7 @@ void ice_free(void) {
|
|
|
|
|
timerthread_free(&ice_agents_timer_thread);
|
|
|
|
|
|
|
|
|
|
fragments_cleanup(true);
|
|
|
|
|
g_hash_table_destroy(sdp_fragments);
|
|
|
|
|
sdp_fragments = NULL;
|
|
|
|
|
t_hash_table_destroy_ptr(&sdp_fragments);
|
|
|
|
|
mutex_destroy(&sdp_fragments_lock);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|