Commit 59ce41df authored by Miguel París Díaz's avatar Miguel París Díaz Committed by Olivier Crête

conncheck: consider answer received when remote credentials are set

Consider that the answer is received when remote credentials
are set instead of when a remote candidate is set,
which could not happen or could cause more delay for the
connection establishment.

Ported to git master by Olivier Crête

Differential Revision: https://phabricator.freedesktop.org/D1704
parent a4bacb2f
...@@ -3240,6 +3240,8 @@ nice_agent_set_remote_credentials ( ...@@ -3240,6 +3240,8 @@ nice_agent_set_remote_credentials (
g_strlcpy (stream->remote_ufrag, ufrag, NICE_STREAM_MAX_UFRAG); g_strlcpy (stream->remote_ufrag, ufrag, NICE_STREAM_MAX_UFRAG);
g_strlcpy (stream->remote_password, pwd, NICE_STREAM_MAX_PWD); g_strlcpy (stream->remote_password, pwd, NICE_STREAM_MAX_PWD);
conn_check_remote_credentials_set(agent, stream);
ret = TRUE; ret = TRUE;
goto done; goto done;
} }
...@@ -3342,8 +3344,6 @@ _set_remote_candidates_locked (NiceAgent *agent, NiceStream *stream, ...@@ -3342,8 +3344,6 @@ _set_remote_candidates_locked (NiceAgent *agent, NiceStream *stream,
} }
} }
conn_check_remote_candidates_set(agent, stream, component);
if (added > 0) { if (added > 0) {
conn_check_schedule_next (agent); conn_check_schedule_next (agent);
} }
......
...@@ -1243,124 +1243,124 @@ static GSList *prune_cancelled_conn_check (GSList *conncheck_list) ...@@ -1243,124 +1243,124 @@ static GSList *prune_cancelled_conn_check (GSList *conncheck_list)
/* /*
* Handle any processing steps for connectivity checks after * Handle any processing steps for connectivity checks after
* remote candidates have been set. This function handles * remote credentials have been set. This function handles
* the special case where answerer has sent us connectivity * the special case where answerer has sent us connectivity
* checks before the answer (containing candidate information), * checks before the answer (containing credentials information),
* reaches us. The special case is documented in sect 7.2 * reaches us. The special case is documented in sect 7.2
* if ICE spec (ID-19). * if ICE spec (ID-19).
*/ */
void conn_check_remote_candidates_set(NiceAgent *agent, NiceStream *stream, NiceComponent *component) void conn_check_remote_credentials_set(NiceAgent *agent, NiceStream *stream)
{ {
GSList *j, *k, *l, *m, *n; GSList *j, *k, *l, *m, *n, *o;
for (j = stream->conncheck_list; j ; j = j->next) { for (j = stream->conncheck_list; j ; j = j->next) {
CandidateCheckPair *pair = j->data; CandidateCheckPair *pair = j->data;
if (pair->component_id == component->id) { NiceComponent *component =
gboolean match = FALSE; 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 */ /* performn delayed processing of spec steps section 7.2.1.4,
priv_preprocess_conn_check_pending_data (agent, stream, component, pair); and section 7.2.1.5 */
priv_preprocess_conn_check_pending_data (agent, stream, component, pair);
for (k = component->incoming_checks; k; k = k->next) {
IncomingCheck *icheck = k->data; for (k = component->incoming_checks; k; k = k->next) {
/* sect 7.2.1.3., "Learning Peer Reflexive Candidates", has to IncomingCheck *icheck = k->data;
* be handled separately */ /* sect 7.2.1.3., "Learning Peer Reflexive Candidates", has to
for (l = component->remote_candidates; l; l = l->next) { * be handled separately */
NiceCandidate *cand = l->data; for (l = component->remote_candidates; l; l = l->next) {
if (nice_address_equal (&icheck->from, &cand->addr)) { NiceCandidate *cand = l->data;
match = TRUE; if (nice_address_equal (&icheck->from, &cand->addr)) {
break; match = TRUE;
} break;
} }
if (match != TRUE) { }
/* note: we have gotten an incoming connectivity check from if (match != TRUE) {
* an address that is not a known remote candidate */ /* 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; NiceCandidate *local_candidate = NULL;
NiceCandidate *remote_candidate = NULL;
if (agent->compatibility == NICE_COMPATIBILITY_GOOGLE ||
agent->compatibility == NICE_COMPATIBILITY_MSN || if (agent->compatibility == NICE_COMPATIBILITY_GOOGLE ||
agent->compatibility == NICE_COMPATIBILITY_OC2007) { agent->compatibility == NICE_COMPATIBILITY_MSN ||
/* We need to find which local candidate was used */ agent->compatibility == NICE_COMPATIBILITY_OC2007) {
uint8_t uname[NICE_STREAM_MAX_UNAME]; /* We need to find which local candidate was used */
guint uname_len; 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); 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 (m = component->remote_candidates;
for (n = component->local_candidates; n; n = n->next) { m != NULL && remote_candidate == NULL; m = m->next) {
NiceCandidate *rcand = m->data; for (n = component->local_candidates; n; n = n->next) {
NiceCandidate *lcand = n->data; NiceCandidate *rcand = m->data;
NiceCandidate *lcand = n->data;
uname_len = priv_create_username (agent, stream,
component->id, rcand, lcand, uname_len = priv_create_username (agent, stream,
uname, sizeof (uname), TRUE); 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, stun_debug ("pending check, comparing usernames of len %d and %d, equal=%d",
icheck->username && uname_len == icheck->username_len && icheck->username_len, uname_len,
memcmp (uname, icheck->username, icheck->username_len) == 0); icheck->username && uname_len == icheck->username_len &&
stun_debug_bytes (" first username: ", memcmp (uname, icheck->username, icheck->username_len) == 0);
icheck->username, stun_debug_bytes (" first username: ",
icheck->username? icheck->username_len : 0); icheck->username,
stun_debug_bytes (" second username: ", uname, uname_len); icheck->username? icheck->username_len : 0);
stun_debug_bytes (" second username: ", uname, uname_len);
if (icheck->username &&
uname_len == icheck->username_len && if (icheck->username &&
memcmp (uname, icheck->username, icheck->username_len) == 0) { uname_len == icheck->username_len &&
local_candidate = lcand; memcmp (uname, icheck->username, icheck->username_len) == 0) {
remote_candidate = rcand; local_candidate = lcand;
break; remote_candidate = rcand;
}
}
}
} else {
for (l = component->local_candidates; l; l = l->next) {
NiceCandidate *cand = l->data;
if (nice_address_equal (&cand->addr, &icheck->local_socket->addr)) {
local_candidate = cand;
break; break;
} }
} }
} }
} else {
if (agent->compatibility == NICE_COMPATIBILITY_GOOGLE && for (l = component->local_candidates; l; l = l->next) {
local_candidate == NULL) { NiceCandidate *cand = l->data;
/* if we couldn't match the username, then the matching remote if (nice_address_equal (&cand->addr, &icheck->local_socket->addr)) {
* candidate hasn't been received yet.. we must wait */ local_candidate = cand;
nice_debug ("Agent %p : Username check failed. pending check has " break;
"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);
if (icheck->use_candidate)
priv_mark_pair_nominated (agent, stream, component, local_candidate, candidate);
priv_schedule_triggered_check (agent, stream, component, icheck->local_socket, candidate, icheck->use_candidate);
} }
} }
} }
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);
if (icheck->use_candidate)
priv_mark_pair_nominated (agent, stream, component, local_candidate, candidate);
priv_schedule_triggered_check (agent, stream, component, icheck->local_socket, candidate, icheck->use_candidate);
}
}
} }
} }
} }
...@@ -1368,9 +1368,12 @@ void conn_check_remote_candidates_set(NiceAgent *agent, NiceStream *stream, Nice ...@@ -1368,9 +1368,12 @@ void conn_check_remote_candidates_set(NiceAgent *agent, NiceStream *stream, Nice
/* Once we process the pending checks, we should free them to avoid /* Once we process the pending checks, we should free them to avoid
* reprocessing them again if a dribble-mode set_remote_candidates * reprocessing them again if a dribble-mode set_remote_candidates
* is called */ * is called */
g_slist_free_full (component->incoming_checks, for (o = stream->components; o; o = o->next) {
(GDestroyNotify) incoming_check_free); NiceComponent *component = o->data;
component->incoming_checks = NULL; g_slist_free_full (component->incoming_checks,
(GDestroyNotify) incoming_check_free);
component->incoming_checks = NULL;
}
stream->conncheck_list = stream->conncheck_list =
prune_cancelled_conn_check (stream->conncheck_list); prune_cancelled_conn_check (stream->conncheck_list);
...@@ -3628,14 +3631,14 @@ gboolean conn_check_handle_inbound_stun (NiceAgent *agent, NiceStream *stream, ...@@ -3628,14 +3631,14 @@ gboolean conn_check_handle_inbound_stun (NiceAgent *agent, NiceStream *stream,
if (stream->initial_binding_request_received != TRUE) if (stream->initial_binding_request_received != TRUE)
agent_signal_initial_binding_request_received (agent, stream); agent_signal_initial_binding_request_received (agent, stream);
if (component->remote_candidates && remote_candidate == NULL) { if (remote_candidate == NULL) {
nice_debug ("Agent %p : No matching remote candidate for incoming check ->" nice_debug ("Agent %p : No matching remote candidate for incoming check ->"
"peer-reflexive candidate.", agent); "peer-reflexive candidate.", agent);
remote_candidate = discovery_learn_remote_peer_reflexive_candidate ( remote_candidate = discovery_learn_remote_peer_reflexive_candidate (
agent, stream, component, priority, from, nicesock, agent, stream, component, priority, from, nicesock,
local_candidate, local_candidate,
remote_candidate2 ? remote_candidate2 : remote_candidate); remote_candidate2 ? remote_candidate2 : remote_candidate);
if(remote_candidate) { if(remote_candidate && stream->remote_ufrag != NULL) {
if (local_candidate && if (local_candidate &&
local_candidate->transport == NICE_CANDIDATE_TRANSPORT_TCP_PASSIVE) { local_candidate->transport == NICE_CANDIDATE_TRANSPORT_TCP_PASSIVE) {
CandidateCheckPair *pair; CandidateCheckPair *pair;
...@@ -3654,10 +3657,10 @@ gboolean conn_check_handle_inbound_stun (NiceAgent *agent, NiceStream *stream, ...@@ -3654,10 +3657,10 @@ gboolean conn_check_handle_inbound_stun (NiceAgent *agent, NiceStream *stream,
priv_reply_to_conn_check (agent, stream, component, local_candidate, priv_reply_to_conn_check (agent, stream, component, local_candidate,
remote_candidate, from, nicesock, rbuf_len, &msg, use_candidate); remote_candidate, from, nicesock, rbuf_len, &msg, use_candidate);
if (component->remote_candidates == NULL) { if (stream->remote_ufrag == NULL) {
/* case: We've got a valid binding request to a local candidate /* case: We've got a valid binding request to a local candidate
* but we do not yet know remote credentials nor * but we do not yet know remote credentials.
* candidates. As per sect 7.2 of ICE (ID-19), we send a reply * As per sect 7.2 of ICE (ID-19), we send a reply
* immediately but postpone all other processing until * immediately but postpone all other processing until
* we get information about the remote candidates */ * we get information about the remote candidates */
......
...@@ -105,7 +105,7 @@ int conn_check_send (NiceAgent *agent, CandidateCheckPair *pair); ...@@ -105,7 +105,7 @@ int conn_check_send (NiceAgent *agent, CandidateCheckPair *pair);
void conn_check_prune_stream (NiceAgent *agent, NiceStream *stream); void conn_check_prune_stream (NiceAgent *agent, NiceStream *stream);
gboolean conn_check_handle_inbound_stun (NiceAgent *agent, NiceStream *stream, NiceComponent *component, NiceSocket *udp_socket, const NiceAddress *from, gchar *buf, guint len); gboolean conn_check_handle_inbound_stun (NiceAgent *agent, NiceStream *stream, NiceComponent *component, NiceSocket *udp_socket, const NiceAddress *from, gchar *buf, guint len);
gint conn_check_compare (const CandidateCheckPair *a, const CandidateCheckPair *b); gint conn_check_compare (const CandidateCheckPair *a, const CandidateCheckPair *b);
void conn_check_remote_candidates_set(NiceAgent *agent, NiceStream *stream, NiceComponent *component); void conn_check_remote_credentials_set(NiceAgent *agent, NiceStream *stream);
NiceCandidateTransport conn_check_match_transport (NiceCandidateTransport transport); NiceCandidateTransport conn_check_match_transport (NiceCandidateTransport transport);
void void
conn_check_prune_socket (NiceAgent *agent, NiceStream *stream, NiceComponent *component, conn_check_prune_socket (NiceAgent *agent, NiceStream *stream, NiceComponent *component,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment