diff options
-rw-r--r-- | agent/agent.c | 42 | ||||
-rw-r--r-- | agent/conncheck.c | 168 | ||||
-rw-r--r-- | agent/conncheck.h | 1 |
3 files changed, 66 insertions, 145 deletions
diff --git a/agent/agent.c b/agent/agent.c index 0773c53..49fc371 100644 --- a/agent/agent.c +++ b/agent/agent.c @@ -3300,6 +3300,28 @@ nice_agent_add_local_address (NiceAgent *agent, NiceAddress *addr) return TRUE; } +/* Recompute foundations of all candidate pairs from a given stream + * having a specific remote candidate + */ +static void priv_update_pair_foundations (NiceAgent *agent, + guint stream_id, NiceCandidate *remote) +{ + NiceStream *stream = agent_find_stream (agent, stream_id); + if (stream) { + GSList *i; + for (i = stream->conncheck_list; i; i = i->next) { + CandidateCheckPair *pair = i->data; + if (pair->remote == remote) { + g_snprintf (pair->foundation, + NICE_CANDIDATE_PAIR_MAX_FOUNDATION, "%s:%s", + pair->local->foundation, pair->remote->foundation); + nice_debug ("Agent %p : Updating pair %p foundation to '%s'", + agent, pair, pair->foundation); + } + } + } +} + static gboolean priv_add_remote_candidate ( NiceAgent *agent, guint stream_id, @@ -3331,8 +3353,7 @@ static gboolean priv_add_remote_candidate ( /* If it was a discovered remote peer reflexive candidate, then it should * be updated according to RFC 5245 section 7.2.1.3 */ - if (candidate && candidate->type == NICE_CANDIDATE_TYPE_PEER_REFLEXIVE && - candidate->priority == priority) { + if (candidate && candidate->type == NICE_CANDIDATE_TYPE_PEER_REFLEXIVE) { nice_debug ("Agent %p : Updating existing peer-rfx remote candidate to %s", agent, _cand_type_to_sdp (type)); candidate->type = type; @@ -3375,6 +3396,13 @@ static gboolean priv_add_remote_candidate ( g_free (candidate->password); candidate->password = g_strdup (password); } + + /* since the type of the existing candidate may have changed, + * the pairs priority and foundation related to this candidate need + * to be recomputed. + */ + recalculate_pair_priorities (agent); + priv_update_pair_foundations (agent, stream_id, candidate); } else { /* case 2: add a new candidate */ @@ -3429,12 +3457,14 @@ static gboolean priv_add_remote_candidate ( if (foundation) g_strlcpy (candidate->foundation, foundation, NICE_CANDIDATE_MAX_FOUNDATION); - } - if (conn_check_add_for_candidate (agent, stream_id, component, candidate) < 0) { - goto errors; + /* We only create a pair when a candidate is new, and not when + * updating an existing one. + */ + if (conn_check_add_for_candidate (agent, stream_id, + component, candidate) < 0) + goto errors; } - return TRUE; errors: diff --git a/agent/conncheck.c b/agent/conncheck.c index 38a90cd..11ef9c9 100644 --- a/agent/conncheck.c +++ b/agent/conncheck.c @@ -1691,34 +1691,6 @@ gint conn_check_compare (const CandidateCheckPair *a, const CandidateCheckPair * } /* - * Preprocesses a new connectivity check by going through list - * of a any stored early incoming connectivity checks from - * the remote peer. If a matching incoming check has been already - * received, update the state of the new outgoing check 'pair'. - * - * @param agent context pointer - * @param stream which stream (of the agent) - * @param component pointer to component object to which 'pair'has been added - * @param pair newly added connectivity check - */ -static void priv_preprocess_conn_check_pending_data (NiceAgent *agent, NiceStream *stream, NiceComponent *component, CandidateCheckPair *pair) -{ - GSList *i; - for (i = component->incoming_checks; i; i = i->next) { - IncomingCheck *icheck = i->data; - if (nice_address_equal (&icheck->from, &pair->remote->addr) && - icheck->local_socket == pair->sockptr) { - nice_debug ("Agent %p : Updating check %p with stored early-icheck %p, %p/%u/%u (agent/stream/component).", agent, pair, icheck, agent, stream->id, component->id); - priv_schedule_triggered_check (agent, stream, component, - icheck->local_socket, pair->remote); - if (icheck->use_candidate) - priv_mark_pair_nominated (agent, stream, component, pair->local, pair->remote); - } - } -} - - -/* * Handle any processing steps for connectivity checks after * remote credentials have been set. This function handles * the special case where answerer has sent us connectivity @@ -1728,126 +1700,39 @@ static void priv_preprocess_conn_check_pending_data (NiceAgent *agent, NiceStrea */ void conn_check_remote_credentials_set(NiceAgent *agent, NiceStream *stream) { - GSList *j, *k, *l, *m, *n, *o; + GSList *j, *k, *l, *m; - for (j = stream->conncheck_list; j ; j = j->next) { - CandidateCheckPair *pair = j->data; - NiceComponent *component = - nice_stream_find_component_by_id (stream, pair->component_id); - gboolean match = FALSE; - - /* performn delayed processing of spec steps section 7.2.1.4, - and section 7.2.1.5 */ - priv_preprocess_conn_check_pending_data (agent, stream, component, pair); + for (j = stream->components; j ; j = j->next) { + NiceComponent *component = j->data; for (k = component->incoming_checks; k; k = k->next) { IncomingCheck *icheck = k->data; /* sect 7.2.1.3., "Learning Peer Reflexive Candidates", has to * be handled separately */ for (l = component->remote_candidates; l; l = l->next) { - NiceCandidate *cand = l->data; - if (nice_address_equal (&icheck->from, &cand->addr)) { - match = TRUE; - break; - } - } - if (match != TRUE) { - /* note: we have gotten an incoming connectivity check from - * an address that is not a known remote candidate */ - - NiceCandidate *local_candidate = NULL; - NiceCandidate *remote_candidate = NULL; - - if (agent->compatibility == NICE_COMPATIBILITY_GOOGLE || - agent->compatibility == NICE_COMPATIBILITY_MSN || - agent->compatibility == NICE_COMPATIBILITY_OC2007) { - /* We need to find which local candidate was used */ - uint8_t uname[NICE_STREAM_MAX_UNAME]; - guint uname_len; - - nice_debug ("Agent %p: We have a peer-reflexive candidate in a " - "stored pending check", agent); - - for (m = component->remote_candidates; - m != NULL && remote_candidate == NULL; m = m->next) { - for (n = component->local_candidates; n; n = n->next) { - NiceCandidate *rcand = m->data; - NiceCandidate *lcand = n->data; - - uname_len = priv_create_username (agent, stream, - component->id, rcand, lcand, - uname, sizeof (uname), TRUE); - - stun_debug ("pending check, comparing usernames of len %d and %d, equal=%d", - icheck->username_len, uname_len, - icheck->username && uname_len == icheck->username_len && - memcmp (uname, icheck->username, icheck->username_len) == 0); - stun_debug_bytes (" first username: ", - icheck->username, - icheck->username? icheck->username_len : 0); - stun_debug_bytes (" second username: ", uname, uname_len); - - if (icheck->username && - uname_len == icheck->username_len && - memcmp (uname, icheck->username, icheck->username_len) == 0) { - local_candidate = lcand; - remote_candidate = rcand; - break; - } - } - } - } else { - for (l = component->local_candidates; l; l = l->next) { - NiceCandidate *cand = l->data; + NiceCandidate *rcand = l->data; + NiceCandidate *lcand = NULL; + if (nice_address_equal (&rcand->addr, &icheck->from)) { + for (m = component->local_candidates; m; m = m->next) { + NiceCandidate *cand = m->data; if (nice_address_equal (&cand->addr, &icheck->local_socket->addr)) { - local_candidate = cand; + lcand = cand; break; } } - } - - if (agent->compatibility == NICE_COMPATIBILITY_GOOGLE && - local_candidate == NULL) { - /* if we couldn't match the username, then the matching remote - * candidate hasn't been received yet.. we must wait */ - nice_debug ("Agent %p : Username check failed. pending check has " - "to wait to be processed", agent); - } else { - NiceCandidate *candidate; - - nice_debug ("Agent %p : Discovered peer reflexive from early i-check", - agent); - candidate = - discovery_learn_remote_peer_reflexive_candidate (agent, - stream, - component, - icheck->priority, - &icheck->from, - icheck->local_socket, - local_candidate, remote_candidate); - if (candidate) { - if (local_candidate && - local_candidate->transport == NICE_CANDIDATE_TRANSPORT_TCP_PASSIVE) - priv_conn_check_add_for_candidate_pair_matched (agent, - stream->id, component, local_candidate, candidate, NICE_CHECK_DISCOVERED); - else - conn_check_add_for_candidate (agent, stream->id, component, candidate); - - priv_schedule_triggered_check (agent, stream, component, - icheck->local_socket, candidate); - if (icheck->use_candidate) - priv_mark_pair_nominated (agent, stream, component, local_candidate, candidate); - } + g_assert (lcand != NULL); + priv_schedule_triggered_check (agent, stream, component, + icheck->local_socket, rcand); + if (icheck->use_candidate) + priv_mark_pair_nominated (agent, stream, component, + lcand, rcand); + break; } } } - } - - /* Once we process the pending checks, we should free them to avoid - * reprocessing them again if a dribble-mode set_remote_candidates - * is called */ - for (o = stream->components; o; o = o->next) { - NiceComponent *component = o->data; + /* Once we process the pending checks, we should free them to avoid + * reprocessing them again if a dribble-mode set_remote_candidates + * is called */ g_slist_free_full (component->incoming_checks, (GDestroyNotify) incoming_check_free); component->incoming_checks = NULL; @@ -2964,8 +2849,8 @@ static gboolean priv_schedule_triggered_check (NiceAgent *agent, NiceStream *str if (i) { nice_debug ("Agent %p : Adding a triggered check to conn.check list (local=%p).", agent, local); - p = priv_add_new_check_pair (agent, stream->id, component, - local, remote_cand, NICE_CHECK_WAITING); + p = priv_conn_check_add_for_candidate_pair_matched (agent, stream->id, + component, local, remote_cand, NICE_CHECK_WAITING); priv_add_pair_to_triggered_check_queue (agent, p); return TRUE; } @@ -3018,7 +2903,12 @@ static void priv_reply_to_conn_check (NiceAgent *agent, NiceStream *stream, ms_ice2_legacy_conncheck_send(msg, sockptr, toaddr); } - if (rcand) { + /* We react to this stun request when we have the remote credentials. + * When credentials are not yet known, this request is stored + * in incoming_checks for later processing when returning from this + * function. + */ + if (rcand && stream->remote_ufrag[0]) { priv_schedule_triggered_check (agent, stream, component, sockptr, rcand); if (use_candidate) priv_mark_pair_nominated (agent, stream, component, lcand, rcand); @@ -3114,7 +3004,7 @@ static CandidateCheckPair *priv_add_peer_reflexive_pair (NiceAgent *agent, guint * Recalculates priorities of all candidate pairs. This * is required after a conflict in ICE roles. */ -static void priv_recalculate_pair_priorities (NiceAgent *agent) +void recalculate_pair_priorities (NiceAgent *agent) { GSList *i, *j; @@ -3143,7 +3033,7 @@ static void priv_check_for_role_conflict (NiceAgent *agent, gboolean control) agent->controlling_mode = control; /* the pair priorities depend on the roles, so recalculation * is needed */ - priv_recalculate_pair_priorities (agent); + recalculate_pair_priorities (agent); } else nice_debug ("Agent %p : Role conflict, staying with role \"%s\".", diff --git a/agent/conncheck.h b/agent/conncheck.h index e16dc67..8cfe2d6 100644 --- a/agent/conncheck.h +++ b/agent/conncheck.h @@ -119,5 +119,6 @@ conn_check_prune_socket (NiceAgent *agent, NiceStream *stream, NiceComponent *co NiceSocket *sock); guint32 ensure_unique_priority (NiceComponent *component, guint32 priority); +void recalculate_pair_priorities (NiceAgent *agent); #endif /*_NICE_CONNCHECK_H */ |