(0x100 - component_id));
}
-static guint32
+static guint16
nice_candidate_ice_local_preference_full (guint direction_preference,
- guint other_preference)
+ guint turn_preference, guint other_preference)
{
- return (0x2000 * direction_preference +
- other_preference);
+ /*
+ * bits 0- 5: other_preference (ip local preference)
+ * 6- 8: turn_preference
+ * 9-12: <unused>
+ * 13-15: direction_preference
+ */
+ g_assert_cmpuint (other_preference, <, NICE_CANDIDATE_MAX_LOCAL_ADDRESSES);
+ g_assert_cmpuint (turn_preference, <, NICE_CANDIDATE_MAX_TURN_SERVERS);
+ g_assert_cmpuint (direction_preference, <, 8);
+
+ return (direction_preference << 13) +
+ (turn_preference << 6) +
+ other_preference;
}
-static guint8
+static guint
nice_candidate_ip_local_preference (const NiceCandidate *candidate)
{
- guint8 preference = 0;
+ guint preference = 0;
gchar ip_string[INET6_ADDRSTRLEN];
GList/*<owned gchar*>*/ *ips = NULL;
GList/*<unowned gchar*>*/ *iter;
ips = nice_interfaces_get_local_ips (TRUE);
for (iter = ips; iter; iter = g_list_next (iter)) {
- if (g_strcmp0 (ip_string, iter->data) == 0) {
+ /* Strip the IPv6 link-local scope string */
+ gchar **tokens = g_strsplit (iter->data, "%", 2);
+ gboolean match = (g_strcmp0 (ip_string, tokens[0]) == 0);
+ g_strfreev (tokens);
+ if (match)
break;
- }
++preference;
}
static guint16
nice_candidate_ice_local_preference (const NiceCandidate *candidate)
{
- guint direction_preference;
+ guint direction_preference = 0;
+ guint turn_preference = 0;
switch (candidate->transport)
{
break;
case NICE_CANDIDATE_TRANSPORT_UDP:
default:
- return 1;
+ direction_preference = 1;
break;
}
+ /* Relay candidates are assigned a unique local preference at
+ * creation time.
+ */
+ if (candidate->type == NICE_CANDIDATE_TYPE_RELAYED) {
+ g_assert (candidate->turn);
+ turn_preference = candidate->turn->preference;
+ }
+
return nice_candidate_ice_local_preference_full (direction_preference,
- nice_candidate_ip_local_preference (candidate));
+ turn_preference, nice_candidate_ip_local_preference (candidate));
}
-static guint32
+static guint16
nice_candidate_ms_ice_local_preference_full (guint transport_preference,
- guint direction_preference, guint other_preference)
+ guint direction_preference, guint turn_preference, guint other_preference)
{
- return 0x1000 * transport_preference +
- 0x200 * direction_preference +
- 0x1 * other_preference;
+ /*
+ * bits 0- 5: other_preference (ip local preference)
+ * 6- 8: turn_preference
+ * 9-11: direction_preference
+ * 12-15: transport_preference
+ */
+ g_assert_cmpuint (other_preference, <, NICE_CANDIDATE_MAX_LOCAL_ADDRESSES);
+ g_assert_cmpuint (turn_preference, <, NICE_CANDIDATE_MAX_TURN_SERVERS);
+ g_assert_cmpuint (direction_preference, <, 8);
+ g_assert_cmpuint (transport_preference, <, 16);
+
+ return (transport_preference << 12) +
+ (direction_preference << 9) +
+ (turn_preference << 6) +
+ other_preference;
}
static guint32
nice_candidate_ms_ice_local_preference (const NiceCandidate *candidate)
{
- guint8 transport_preference = 0;
- guint8 direction_preference = 0;
+ guint transport_preference = 0;
+ guint direction_preference = 0;
+ guint turn_preference = 0;
switch (candidate->transport)
{
break;
}
+ /* Relay candidates are assigned a unique local preference at
+ * creation time.
+ */
+ if (candidate->type == NICE_CANDIDATE_TYPE_RELAYED) {
+ g_assert (candidate->turn);
+ turn_preference = candidate->turn->preference;
+ }
+
return nice_candidate_ms_ice_local_preference_full(transport_preference,
- direction_preference, nice_candidate_ip_local_preference (candidate));
+ direction_preference, turn_preference,
+ nice_candidate_ip_local_preference (candidate));
}
static guint8
return (one << thirtytwo) * min + 2 * max + (o_prio > a_prio ? 1 : 0);
}
+void
+nice_candidate_pair_priority_to_string (guint64 prio, gchar *string)
+{
+ g_snprintf (string, NICE_CANDIDATE_PAIR_PRIORITY_MAX_SIZE,
+ "%08" G_GINT64_MODIFIER "x:%08" G_GINT64_MODIFIER "x:%" G_GUINT64_FORMAT,
+ prio >> 32, (prio >> 1) & 0x7fffffff, prio & 1);
+}
+
/*
* Copies a candidate
*/