|
|
|
@ -317,8 +317,9 @@ void ice_update(struct ice_agent *ag, struct stream_params *sp) { |
|
|
|
int recalc = 0; |
|
|
|
unsigned int comps; |
|
|
|
struct packet_stream *components[MAX_COMPONENTS], *ps; |
|
|
|
GQueue *candidates; |
|
|
|
|
|
|
|
if (!ag || !sp) |
|
|
|
if (!ag) |
|
|
|
return; |
|
|
|
|
|
|
|
media = ag->media; |
|
|
|
@ -326,19 +327,25 @@ void ice_update(struct ice_agent *ag, struct stream_params *sp) { |
|
|
|
|
|
|
|
__role_change(ag, MEDIA_ISSET(media, ICE_CONTROLLING)); |
|
|
|
|
|
|
|
/* check for ICE restarts */ |
|
|
|
if (ag->ufrag[0].s && sp->ice_ufrag.s && str_cmp_str(&ag->ufrag[0], &sp->ice_ufrag)) |
|
|
|
__ice_restart(ag); |
|
|
|
else if (ag->pwd[0].s && sp->ice_pwd.s && str_cmp_str(&ag->pwd[0], &sp->ice_pwd)) |
|
|
|
__ice_restart(ag); |
|
|
|
else if (ag->local_interface != media->interface) |
|
|
|
__ice_restart(ag); |
|
|
|
|
|
|
|
/* update remote info */ |
|
|
|
if (sp->ice_ufrag.s) |
|
|
|
call_str_cpy(call, &ag->ufrag[0], &sp->ice_ufrag); |
|
|
|
if (sp->ice_pwd.s) |
|
|
|
call_str_cpy(call, &ag->pwd[0], &sp->ice_pwd); |
|
|
|
if (sp) { |
|
|
|
/* check for ICE restarts */ |
|
|
|
if (ag->ufrag[0].s && sp->ice_ufrag.s && str_cmp_str(&ag->ufrag[0], &sp->ice_ufrag)) |
|
|
|
__ice_restart(ag); |
|
|
|
else if (ag->pwd[0].s && sp->ice_pwd.s && str_cmp_str(&ag->pwd[0], &sp->ice_pwd)) |
|
|
|
__ice_restart(ag); |
|
|
|
else if (ag->local_interface != media->interface) |
|
|
|
__ice_restart(ag); |
|
|
|
|
|
|
|
/* update remote info */ |
|
|
|
if (sp->ice_ufrag.s) |
|
|
|
call_str_cpy(call, &ag->ufrag[0], &sp->ice_ufrag); |
|
|
|
if (sp->ice_pwd.s) |
|
|
|
call_str_cpy(call, &ag->pwd[0], &sp->ice_pwd); |
|
|
|
|
|
|
|
candidates = &sp->ice_candidates; |
|
|
|
} |
|
|
|
else /* this is a dummy update in case rtcp-mux has changed */ |
|
|
|
candidates = &ag->remote_candidates; |
|
|
|
|
|
|
|
/* get our component streams */ |
|
|
|
ZERO(components); |
|
|
|
@ -349,7 +356,7 @@ void ice_update(struct ice_agent *ag, struct stream_params *sp) { |
|
|
|
components[1] = NULL; |
|
|
|
|
|
|
|
comps = 0; |
|
|
|
for (l = sp->ice_candidates.head; l; l = l->next) { |
|
|
|
for (l = candidates->head; l; l = l->next) { |
|
|
|
if (ag->remote_candidates.length >= MAX_ICE_CANDIDATES) { |
|
|
|
ilog(LOG_WARNING, "Maxmimum number of ICE candidates exceeded"); |
|
|
|
break; |
|
|
|
@ -360,15 +367,16 @@ void ice_update(struct ice_agent *ag, struct stream_params *sp) { |
|
|
|
/* skip invalid */ |
|
|
|
if (!cand->component_id || cand->component_id > G_N_ELEMENTS(components)) |
|
|
|
continue; |
|
|
|
/* skip if we don't have a candidate of our own */ |
|
|
|
ps = components[cand->component_id - 1]; |
|
|
|
if (!ps) |
|
|
|
continue; |
|
|
|
|
|
|
|
comps = MAX(comps, cand->component_id); |
|
|
|
if (ps) /* only count active components */ |
|
|
|
comps = MAX(comps, cand->component_id); |
|
|
|
|
|
|
|
/* check for duplicates */ |
|
|
|
dup = g_hash_table_lookup(ag->candidate_hash, cand); |
|
|
|
if (!sp && dup) /* this isn't a real update, so only check pairings */ |
|
|
|
goto pair; |
|
|
|
|
|
|
|
/* check for duplicates */ |
|
|
|
if (dup) { |
|
|
|
/* if this is peer reflexive, we've learned it through STUN. |
|
|
|
* otherwise it's simply one we've seen before. */ |
|
|
|
@ -410,6 +418,9 @@ void ice_update(struct ice_agent *ag, struct stream_params *sp) { |
|
|
|
|
|
|
|
g_hash_table_insert(ag->foundation_hash, dup, dup); |
|
|
|
|
|
|
|
pair: |
|
|
|
if (!ps) |
|
|
|
continue; |
|
|
|
for (k = ag->local_interface->list.head; k; k = k->next) { |
|
|
|
/* skip duplicates here also */ |
|
|
|
if (__pair_lookup(ag, dup, k->data)) |
|
|
|
@ -1088,8 +1099,10 @@ int ice_request(struct packet_stream *ps, struct sockaddr_in6 *src, struct in6_a |
|
|
|
|
|
|
|
g_tree_insert(ag->nominated_pairs, pair, pair); |
|
|
|
|
|
|
|
if (PAIR_ISSET(pair, SUCCEEDED)) |
|
|
|
if (PAIR_ISSET(pair, SUCCEEDED)) { |
|
|
|
PAIR_SET(pair, VALID); |
|
|
|
g_tree_insert(ag->valid_pairs, pair, pair); |
|
|
|
} |
|
|
|
|
|
|
|
if (!AGENT_ISSET(ag, CONTROLLING)) |
|
|
|
ret = __check_valid(ag); |
|
|
|
@ -1129,7 +1142,7 @@ static int __check_succeeded_complete(struct ice_agent *ag) { |
|
|
|
int ice_response(struct packet_stream *ps, struct sockaddr_in6 *src, struct in6_addr *dst, |
|
|
|
struct stun_attrs *attrs, u_int32_t transaction[3]) |
|
|
|
{ |
|
|
|
struct ice_candidate_pair *pair; |
|
|
|
struct ice_candidate_pair *pair, *opair; |
|
|
|
struct ice_agent *ag; |
|
|
|
struct call_media *media = ps->media; |
|
|
|
const char *err; |
|
|
|
@ -1222,20 +1235,21 @@ int ice_response(struct packet_stream *ps, struct sockaddr_in6 *src, struct in6_ |
|
|
|
cand = __foundation_lookup(ag, &pair->remote_candidate->foundation, component); |
|
|
|
if (!cand) |
|
|
|
continue; |
|
|
|
pair = __pair_lookup(ag, cand, ifa); |
|
|
|
if (!pair) |
|
|
|
opair = __pair_lookup(ag, cand, ifa); |
|
|
|
if (!opair) |
|
|
|
continue; |
|
|
|
|
|
|
|
if (PAIR_ISSET(pair, FAILED)) |
|
|
|
if (PAIR_ISSET(opair, FAILED)) |
|
|
|
continue; |
|
|
|
if (!PAIR_CLEAR(pair, FROZEN)) |
|
|
|
if (!PAIR_CLEAR(opair, FROZEN)) |
|
|
|
continue; |
|
|
|
|
|
|
|
ilog(LOG_DEBUG, "Unfreezing related ICE pair "PAIR_FORMAT, PAIR_FMT(pair)); |
|
|
|
ilog(LOG_DEBUG, "Unfreezing related ICE pair "PAIR_FORMAT, PAIR_FMT(opair)); |
|
|
|
} |
|
|
|
|
|
|
|
/* if this was previously nominated by the peer, it's now valid */ |
|
|
|
if (PAIR_ISSET(pair, NOMINATED)) { |
|
|
|
PAIR_SET(pair, VALID); |
|
|
|
g_tree_insert(ag->valid_pairs, pair, pair); |
|
|
|
|
|
|
|
if (!AGENT_ISSET(ag, CONTROLLING)) |
|
|
|
|