summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFabrice Bellet <fabrice@bellet.info>2019-07-12 14:06:13 +0000
committerOlivier CrĂȘte <olivier.crete@ocrete.ca>2019-07-12 14:06:13 +0000
commit85a5c0a053aa32d987558803653de905c523cf9f (patch)
treee08fbb80467b6774b41c4b75e254644ad792763a
parentbd4b47813844aa0e68e9074b3ac516c383ca8bab (diff)
downloadlibnice-85a5c0a053aa32d987558803653de905c523cf9f.tar.gz
conncheck: avoid transport association mismatch
In some rare cases, the same address and port number may match two remotes candidates, a tcp and an udp one, and lead to buggy pair construction with incompatible transport. This supplementary check prevents this problem. The matching test is not aimed to be exhaustive but just a way to discard obviously broken associations, and fallback to accept everything else (because socket type has a great diversity, with socket types based on other sockets types). It should fix #81, where such bogus transport association has been reported (tcp-pass:udp).
-rw-r--r--agent/conncheck.c37
1 files changed, 35 insertions, 2 deletions
diff --git a/agent/conncheck.c b/agent/conncheck.c
index e139ead..a979f3f 100644
--- a/agent/conncheck.c
+++ b/agent/conncheck.c
@@ -1855,6 +1855,35 @@ gint conn_check_compare (const CandidateCheckPair *a, const CandidateCheckPair *
return 0;
}
+static gboolean
+priv_match_remote_candidate_transport_and_socket_type (NiceAgent *agent,
+ NiceCandidate *candidate, NiceSocket *socket)
+{
+ gboolean ret = TRUE;
+ g_assert (socket);
+ g_assert (candidate);
+
+ /* Detect some obvious incompatibilites.
+ *
+ * In rare situations, tcp and udp candidate may have the same
+ * couple (address, port), they must be identified by their
+ * matching transport.
+ */
+ if (socket->type == NICE_SOCKET_TYPE_UDP_BSD &&
+ candidate->transport == NICE_CANDIDATE_TRANSPORT_TCP_ACTIVE)
+ ret = FALSE;
+ if (socket->type == NICE_SOCKET_TYPE_TCP_BSD &&
+ candidate->transport == NICE_CANDIDATE_TRANSPORT_UDP)
+ ret = FALSE;
+
+ nice_debug_verbose ("Agent %p : socket/candidate compat: %s and %s: %s",
+ agent, priv_socket_type_to_string (socket->type),
+ priv_candidate_transport_to_string (candidate->transport),
+ ret ? "yes" : "no");
+
+ return ret;
+}
+
void
conn_check_remote_candidates_set(NiceAgent *agent, NiceStream *stream,
NiceComponent *component)
@@ -1883,7 +1912,9 @@ conn_check_remote_candidates_set(NiceAgent *agent, NiceStream *stream,
NiceCandidate *rcand = l->data;
NiceCandidate *lcand = NULL;
- if (nice_address_equal (&rcand->addr, &icheck->from)) {
+ if (nice_address_equal (&rcand->addr, &icheck->from) &&
+ priv_match_remote_candidate_transport_and_socket_type
+ (agent, rcand, icheck->local_socket)) {
for (m = component->local_candidates; m; m = m->next) {
NiceCandidate *cand = m->data;
NiceAddress *addr;
@@ -4461,7 +4492,9 @@ gboolean conn_check_handle_inbound_stun (NiceAgent *agent, NiceStream *stream,
for (i = component->remote_candidates; i; i = i->next) {
NiceCandidate *cand = i->data;
- if (nice_address_equal (from, &cand->addr)) {
+ if (nice_address_equal (from, &cand->addr) &&
+ priv_match_remote_candidate_transport_and_socket_type
+ (agent, cand, nicesock)) {
remote_candidate = cand;
break;
}