|
|
|
@ -59,7 +59,7 @@ static struct ice_candidate_pair *__pair_lookup(struct ice_agent *, struct ice_c |
|
|
|
const struct local_intf *ifa); |
|
|
|
static void __recalc_pair_prios(struct ice_agent *ag); |
|
|
|
static void __role_change(struct ice_agent *ag, int new_controlling); |
|
|
|
static void __get_complete_components(GQueue *out, struct ice_agent *ag, GTree *t, unsigned int); |
|
|
|
static void __get_complete_components(candidate_pair_q *out, struct ice_agent *ag, GTree *t, unsigned int); |
|
|
|
static void __agent_schedule(struct ice_agent *ag, unsigned long); |
|
|
|
static void __agent_schedule_abs(struct ice_agent *ag, const struct timeval *tv); |
|
|
|
static void __agent_deschedule(struct ice_agent *ag); |
|
|
|
@ -303,8 +303,8 @@ static void __new_stun_transaction(struct ice_candidate_pair *pair) { |
|
|
|
|
|
|
|
/* agent must be locked */ |
|
|
|
static void __all_pairs_list(struct ice_agent *ag) { |
|
|
|
g_queue_clear(&ag->all_pairs_list); |
|
|
|
g_tree_get_values(&ag->all_pairs_list, ag->all_pairs); |
|
|
|
t_queue_clear(&ag->all_pairs_list); |
|
|
|
g_tree_get_values(&ag->all_pairs_list.q, ag->all_pairs); |
|
|
|
} |
|
|
|
|
|
|
|
static void __tree_coll_callback(void *oo, void *nn) { |
|
|
|
@ -334,7 +334,7 @@ static struct ice_candidate_pair *__pair_candidate(struct stream_fd *sfd, struct |
|
|
|
__do_ice_pair_priority(pair); |
|
|
|
__new_stun_transaction(pair); |
|
|
|
|
|
|
|
g_queue_push_tail(&ag->candidate_pairs, pair); |
|
|
|
t_queue_push_tail(&ag->candidate_pairs, pair); |
|
|
|
g_hash_table_insert(ag->pair_hash, pair, pair); |
|
|
|
g_tree_insert_coll(ag->all_pairs, pair, pair, __tree_coll_callback); |
|
|
|
|
|
|
|
@ -490,14 +490,13 @@ void ice_restart(struct ice_agent *ag) { |
|
|
|
|
|
|
|
/* called with the call lock held in W, hence agent doesn't need to be locked */ |
|
|
|
void ice_update(struct ice_agent *ag, struct stream_params *sp, bool allow_reset) { |
|
|
|
GList *l; |
|
|
|
struct ice_candidate *cand, *dup; |
|
|
|
struct call_media *media; |
|
|
|
struct call *call; |
|
|
|
int recalc = 0; |
|
|
|
unsigned int comps; |
|
|
|
struct packet_stream *components[MAX_COMPONENTS], *ps; |
|
|
|
GQueue *candidates; |
|
|
|
candidate_q *candidates; |
|
|
|
struct stream_fd *sfd; |
|
|
|
|
|
|
|
if (!ag) |
|
|
|
@ -533,13 +532,13 @@ void ice_update(struct ice_agent *ag, struct stream_params *sp, bool allow_reset |
|
|
|
/* get our component streams */ |
|
|
|
ZERO(components); |
|
|
|
comps = 0; |
|
|
|
for (l = media->streams.head; l; l = l->next) |
|
|
|
for (GList *l = media->streams.head; l; l = l->next) |
|
|
|
components[comps++] = l->data; |
|
|
|
if (comps == 2 && (MEDIA_ISSET(media, RTCP_MUX) || !proto_is_rtp(media->protocol))) |
|
|
|
components[1] = NULL; |
|
|
|
|
|
|
|
comps = 0; |
|
|
|
for (l = candidates->head; l; l = l->next) { |
|
|
|
for (__auto_type l = candidates->head; l; l = l->next) { |
|
|
|
if (ag->remote_candidates.length >= MAX_ICE_CANDIDATES) { |
|
|
|
ilogs(ice, LOG_WARNING, "Maxmimum number of ICE candidates exceeded"); |
|
|
|
break; |
|
|
|
@ -598,7 +597,7 @@ void ice_update(struct ice_agent *ag, struct stream_params *sp, bool allow_reset |
|
|
|
__copy_cand(call, dup, cand); |
|
|
|
g_hash_table_insert(ag->candidate_hash, dup, dup); |
|
|
|
g_hash_table_insert(ag->cand_prio_hash, GUINT_TO_POINTER(dup->priority), dup); |
|
|
|
g_queue_push_tail(&ag->remote_candidates, dup); |
|
|
|
t_queue_push_tail(&ag->remote_candidates, dup); |
|
|
|
} |
|
|
|
|
|
|
|
g_hash_table_insert(ag->foundation_hash, dup, dup); |
|
|
|
@ -641,17 +640,17 @@ pair: |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static void ice_candidate_free(void *p) { |
|
|
|
g_slice_free1(sizeof(struct ice_candidate), p); |
|
|
|
static void ice_candidate_free(struct ice_candidate *p) { |
|
|
|
g_slice_free1(sizeof(*p), p); |
|
|
|
} |
|
|
|
void ice_candidates_free(GQueue *q) { |
|
|
|
g_queue_clear_full(q, ice_candidate_free); |
|
|
|
void ice_candidates_free(candidate_q *q) { |
|
|
|
t_queue_clear_full(q, ice_candidate_free); |
|
|
|
} |
|
|
|
static void ice_candidate_pair_free(void *p) { |
|
|
|
static void ice_candidate_pair_free(struct ice_candidate_pair *p) { |
|
|
|
g_slice_free1(sizeof(struct ice_candidate_pair), p); |
|
|
|
} |
|
|
|
static void ice_candidate_pairs_free(GQueue *q) { |
|
|
|
g_queue_clear_full(q, ice_candidate_pair_free); |
|
|
|
static void ice_candidate_pairs_free(candidate_pair_q *q) { |
|
|
|
t_queue_clear_full(q, ice_candidate_pair_free); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@ -679,14 +678,14 @@ static void __ice_agent_free_components(struct ice_agent *ag) { |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
g_queue_clear(&ag->triggered); |
|
|
|
t_queue_clear(&ag->triggered); |
|
|
|
g_hash_table_destroy(ag->candidate_hash); |
|
|
|
g_hash_table_destroy(ag->cand_prio_hash); |
|
|
|
g_hash_table_destroy(ag->pair_hash); |
|
|
|
g_hash_table_destroy(ag->transaction_hash); |
|
|
|
g_hash_table_destroy(ag->foundation_hash); |
|
|
|
g_tree_destroy(ag->all_pairs); |
|
|
|
g_queue_clear(&ag->all_pairs_list); |
|
|
|
t_queue_clear(&ag->all_pairs_list); |
|
|
|
g_tree_destroy(ag->nominated_pairs); |
|
|
|
g_tree_destroy(ag->succeeded_pairs); |
|
|
|
g_tree_destroy(ag->valid_pairs); |
|
|
|
@ -835,20 +834,19 @@ static int __component_find(const void *a, const void *b) { |
|
|
|
static struct ice_candidate_pair *__get_pair_by_component(GTree *t, unsigned int component) { |
|
|
|
return g_tree_find_first(t, __component_find, GUINT_TO_POINTER(component)); |
|
|
|
} |
|
|
|
static void __get_pairs_by_component(GQueue *out, GTree *t, unsigned int component) { |
|
|
|
g_tree_find_all(out, t, __component_find, GUINT_TO_POINTER(component)); |
|
|
|
static void __get_pairs_by_component(candidate_pair_q *out, GTree *t, unsigned int component) { |
|
|
|
g_tree_find_all(&out->q, t, __component_find, GUINT_TO_POINTER(component)); |
|
|
|
} |
|
|
|
|
|
|
|
static void __get_complete_succeeded_pairs(GQueue *out, struct ice_agent *ag) { |
|
|
|
static void __get_complete_succeeded_pairs(candidate_pair_q *out, struct ice_agent *ag) { |
|
|
|
__get_complete_components(out, ag, ag->succeeded_pairs, ICE_PAIR_SUCCEEDED); |
|
|
|
} |
|
|
|
static void __get_complete_valid_pairs(GQueue *out, struct ice_agent *ag) { |
|
|
|
static void __get_complete_valid_pairs(candidate_pair_q *out, struct ice_agent *ag) { |
|
|
|
__get_complete_components(out, ag, ag->valid_pairs, ICE_PAIR_VALID); |
|
|
|
} |
|
|
|
|
|
|
|
static void __nominate_pairs(struct ice_agent *ag) { |
|
|
|
GQueue complete; |
|
|
|
GList *l; |
|
|
|
candidate_pair_q complete; |
|
|
|
struct ice_candidate_pair *pair; |
|
|
|
|
|
|
|
ilogs(ice, LOG_DEBUG, "Start nominating ICE pairs"); |
|
|
|
@ -858,22 +856,21 @@ static void __nominate_pairs(struct ice_agent *ag) { |
|
|
|
|
|
|
|
__get_complete_succeeded_pairs(&complete, ag); |
|
|
|
|
|
|
|
for (l = complete.head; l; l = l->next) { |
|
|
|
for (__auto_type l = complete.head; l; l = l->next) { |
|
|
|
pair = l->data; |
|
|
|
ilogs(ice, LOG_DEBUG, "Nominating ICE pair "PAIR_FORMAT, PAIR_FMT(pair)); |
|
|
|
PAIR_CLEAR(pair, IN_PROGRESS); |
|
|
|
PAIR_SET2(pair, NOMINATED, TO_USE); |
|
|
|
pair->retransmits = 0; |
|
|
|
__new_stun_transaction(pair); |
|
|
|
g_queue_push_tail(&ag->triggered, pair); |
|
|
|
t_queue_push_tail(&ag->triggered, pair); |
|
|
|
} |
|
|
|
|
|
|
|
g_queue_clear(&complete); |
|
|
|
t_queue_clear(&complete); |
|
|
|
} |
|
|
|
|
|
|
|
/* call must be locked R or W, agent must not be locked */ |
|
|
|
static void __do_ice_checks(struct ice_agent *ag) { |
|
|
|
GList *l; |
|
|
|
struct ice_candidate_pair *pair, *highest = NULL, *frozen = NULL, *valid; |
|
|
|
struct stream_fd *sfd; |
|
|
|
GQueue retransmits = G_QUEUE_INIT; |
|
|
|
@ -903,7 +900,7 @@ static void __do_ice_checks(struct ice_agent *ag) { |
|
|
|
} |
|
|
|
|
|
|
|
/* triggered checks are preferred */ |
|
|
|
pair = g_queue_pop_head(&ag->triggered); |
|
|
|
pair = t_queue_pop_head(&ag->triggered); |
|
|
|
if (pair) { |
|
|
|
__DBG("running triggered check on " PAIR_FORMAT, PAIR_FMT(pair)); |
|
|
|
PAIR_CLEAR(pair, TRIGGERED); |
|
|
|
@ -912,7 +909,7 @@ static void __do_ice_checks(struct ice_agent *ag) { |
|
|
|
} |
|
|
|
|
|
|
|
/* find the highest-priority non-frozen non-in-progress pair */ |
|
|
|
for (l = ag->all_pairs_list.head; l; l = l->next) { |
|
|
|
for (__auto_type l = ag->all_pairs_list.head; l; l = l->next) { |
|
|
|
pair = l->data; |
|
|
|
|
|
|
|
__DBG("considering checking " PAIR_FORMAT, PAIR_FMT(pair)); |
|
|
|
@ -1084,7 +1081,7 @@ static struct ice_candidate_pair *__learned_candidate(struct ice_agent *ag, stru |
|
|
|
goto pair; |
|
|
|
} |
|
|
|
|
|
|
|
g_queue_push_tail(&ag->remote_candidates, cand); |
|
|
|
t_queue_push_tail(&ag->remote_candidates, cand); |
|
|
|
g_hash_table_insert(ag->candidate_hash, cand, cand); |
|
|
|
g_hash_table_insert(ag->cand_prio_hash, GUINT_TO_POINTER(cand->priority), cand); |
|
|
|
g_hash_table_insert(ag->foundation_hash, cand, cand); |
|
|
|
@ -1109,7 +1106,7 @@ static void __trigger_check(struct ice_candidate_pair *pair) { |
|
|
|
if (PAIR_CLEAR(pair, FAILED)) |
|
|
|
PAIR_CLEAR(pair, IN_PROGRESS); |
|
|
|
if (ag->triggered.length < 4 * MAX_ICE_CANDIDATES && !PAIR_SET(pair, TRIGGERED)) |
|
|
|
g_queue_push_tail(&ag->triggered, pair); |
|
|
|
t_queue_push_tail(&ag->triggered, pair); |
|
|
|
mutex_unlock(&ag->lock); |
|
|
|
|
|
|
|
__agent_schedule(ag, 0); |
|
|
|
@ -1119,7 +1116,6 @@ static void __trigger_check(struct ice_candidate_pair *pair) { |
|
|
|
/* also regenerates all_pairs_list */ |
|
|
|
static void __recalc_pair_prios(struct ice_agent *ag) { |
|
|
|
struct ice_candidate_pair *pair; |
|
|
|
GList *l; |
|
|
|
GQueue nominated, valid, succ, all; |
|
|
|
|
|
|
|
ilogs(ice, LOG_DEBUG, "Recalculating all ICE pair priorities"); |
|
|
|
@ -1129,7 +1125,7 @@ static void __recalc_pair_prios(struct ice_agent *ag) { |
|
|
|
g_tree_find_remove_all(&valid, ag->valid_pairs); |
|
|
|
g_tree_find_remove_all(&all, ag->all_pairs); |
|
|
|
|
|
|
|
for (l = ag->candidate_pairs.head; l; l = l->next) { |
|
|
|
for (__auto_type l = ag->candidate_pairs.head; l; l = l->next) { |
|
|
|
pair = l->data; |
|
|
|
__do_ice_pair_priority(pair); |
|
|
|
/* this changes the packets, so we must keep these from being seen as retransmits */ |
|
|
|
@ -1162,22 +1158,21 @@ static void __role_change(struct ice_agent *ag, int new_controlling) { |
|
|
|
} |
|
|
|
|
|
|
|
/* initializes "out" */ |
|
|
|
static void __get_complete_components(GQueue *out, struct ice_agent *ag, GTree *t, unsigned int flag) { |
|
|
|
GQueue compo1 = G_QUEUE_INIT; |
|
|
|
GList *l; |
|
|
|
static void __get_complete_components(candidate_pair_q *out, struct ice_agent *ag, GTree *t, unsigned int flag) { |
|
|
|
candidate_pair_q compo1 = TYPED_GQUEUE_INIT; |
|
|
|
struct ice_candidate_pair *pair1, *pairX; |
|
|
|
struct ice_candidate *cand; |
|
|
|
unsigned int i; |
|
|
|
|
|
|
|
__get_pairs_by_component(&compo1, t, 1); |
|
|
|
|
|
|
|
g_queue_init(out); |
|
|
|
t_queue_init(out); |
|
|
|
|
|
|
|
for (l = compo1.head; l; l = l->next) { |
|
|
|
for (__auto_type l = compo1.head; l; l = l->next) { |
|
|
|
pair1 = l->data; |
|
|
|
|
|
|
|
g_queue_clear(out); |
|
|
|
g_queue_push_tail(out, pair1); |
|
|
|
t_queue_clear(out); |
|
|
|
t_queue_push_tail(out, pair1); |
|
|
|
|
|
|
|
for (i = 2; i <= ag->active_components; i++) { |
|
|
|
cand = __foundation_lookup(ag, &pair1->remote_candidate->foundation, i); |
|
|
|
@ -1188,7 +1183,7 @@ static void __get_complete_components(GQueue *out, struct ice_agent *ag, GTree * |
|
|
|
goto next_foundation; |
|
|
|
if (!bf_isset(&pairX->pair_flags, flag)) |
|
|
|
goto next_foundation; |
|
|
|
g_queue_push_tail(out, pairX); |
|
|
|
t_queue_push_tail(out, pairX); |
|
|
|
} |
|
|
|
goto found; |
|
|
|
|
|
|
|
@ -1197,18 +1192,19 @@ next_foundation: |
|
|
|
} |
|
|
|
|
|
|
|
/* nothing found */ |
|
|
|
g_queue_clear(out); |
|
|
|
t_queue_clear(out); |
|
|
|
|
|
|
|
found: |
|
|
|
g_queue_clear(&compo1); |
|
|
|
t_queue_clear(&compo1); |
|
|
|
} |
|
|
|
|
|
|
|
/* call(W) or call(R)+agent must be locked - no in_lock or out_lock must be held */ |
|
|
|
static int __check_valid(struct ice_agent *ag) { |
|
|
|
struct call_media *media; |
|
|
|
struct packet_stream *ps; |
|
|
|
GList *l, *k; |
|
|
|
GQueue all_compos; |
|
|
|
GList *l; |
|
|
|
candidate_pair_list *k; |
|
|
|
candidate_pair_q all_compos; |
|
|
|
struct ice_candidate_pair *pair; |
|
|
|
// const struct local_intf *ifa; |
|
|
|
struct stream_fd *sfd; |
|
|
|
@ -1272,7 +1268,7 @@ static int __check_valid(struct ice_agent *ag) { |
|
|
|
|
|
|
|
call_media_unkernelize(media, "ICE negotiation event"); |
|
|
|
|
|
|
|
g_queue_clear(&all_compos); |
|
|
|
t_queue_clear(&all_compos); |
|
|
|
return 1; |
|
|
|
} |
|
|
|
|
|
|
|
@ -1375,7 +1371,7 @@ err: |
|
|
|
|
|
|
|
|
|
|
|
static int __check_succeeded_complete(struct ice_agent *ag) { |
|
|
|
GQueue complete; |
|
|
|
candidate_pair_q complete; |
|
|
|
int ret; |
|
|
|
|
|
|
|
__get_complete_succeeded_pairs(&complete, ag); |
|
|
|
@ -1388,7 +1384,7 @@ static int __check_succeeded_complete(struct ice_agent *ag) { |
|
|
|
ilogs(ice, LOG_DEBUG, "No succeeded ICE pairs with all components yet"); |
|
|
|
ret = 0; |
|
|
|
} |
|
|
|
g_queue_clear(&complete); |
|
|
|
t_queue_clear(&complete); |
|
|
|
return ret; |
|
|
|
} |
|
|
|
|
|
|
|
@ -1567,21 +1563,20 @@ void ice_foundation(str *s) { |
|
|
|
random_ice_string(s->s, ICE_FOUNDATION_LENGTH); |
|
|
|
} |
|
|
|
|
|
|
|
void ice_remote_candidates(GQueue *out, struct ice_agent *ag) { |
|
|
|
GQueue all_compos; |
|
|
|
GList *l; |
|
|
|
void ice_remote_candidates(candidate_q *out, struct ice_agent *ag) { |
|
|
|
candidate_pair_q all_compos; |
|
|
|
struct ice_candidate_pair *pair; |
|
|
|
|
|
|
|
g_queue_init(out); |
|
|
|
t_queue_init(out); |
|
|
|
|
|
|
|
mutex_lock(&ag->lock); |
|
|
|
__get_complete_valid_pairs(&all_compos, ag); |
|
|
|
mutex_unlock(&ag->lock); |
|
|
|
|
|
|
|
for (l = all_compos.head; l; l = l->next) { |
|
|
|
for (__auto_type l = all_compos.head; l; l = l->next) { |
|
|
|
pair = l->data; |
|
|
|
g_queue_push_tail(out, pair->remote_candidate); |
|
|
|
t_queue_push_tail(out, pair->remote_candidate); |
|
|
|
} |
|
|
|
|
|
|
|
g_queue_clear(&all_compos); |
|
|
|
t_queue_clear(&all_compos); |
|
|
|
} |