Commit 1faae8c8 authored by Andrey Skryabin's avatar Andrey Skryabin Committed by Olivier Crête

conncheck: NOMINATION STUN attribute support

Attribute is proposed here: https://tools.ietf.org/html/draft-thatcher-ice-renomination-00
WebRTC supports this attribute: controlling side provides attribute value increased by one each time selected pair is changed:
https://chromium.googlesource.com/external/webrtc/+/3c7d599750405bc734e1d5adbf1b54265b725a9d/p2p/base/p2ptransportchannel.cc#1821
parent 62cbfbd5
......@@ -156,6 +156,7 @@ struct _NiceAgent
guint stun_initial_timeout; /* property: stun initial timeout, RTO */
guint stun_reliable_timeout; /* property: stun reliable timeout */
NiceNominationMode nomination_mode; /* property: Nomination mode */
gboolean support_renomination; /* property: support RENOMINATION STUN attribute */
GSList *local_addresses; /* list of NiceAddresses for local
interfaces */
......
......@@ -119,6 +119,7 @@ enum
PROP_STUN_RELIABLE_TIMEOUT,
PROP_NOMINATION_MODE,
PROP_ICE_TRICKLE,
PROP_SUPPORT_RENOMINATION,
};
......@@ -465,6 +466,24 @@ nice_agent_class_init (NiceAgentClass *klass)
NICE_TYPE_NOMINATION_MODE, NICE_NOMINATION_MODE_AGGRESSIVE,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
/**
* NiceAgent:support-renomination:
*
* Support RENOMINATION STUN attribute proposed here:
* https://tools.ietf.org/html/draft-thatcher-ice-renomination-00 As
* soon as RENOMINATION attribute is received from remote
* candidate's address, corresponding candidates pair gets
* selected. This is specific to Google Chrome/libWebRTC.
*/
g_object_class_install_property (gobject_class, PROP_SUPPORT_RENOMINATION,
g_param_spec_boolean (
"support-renomination",
"Support RENOMINATION STUN attribute",
"As soon as RENOMINATION attribute is received from remote candidate's address, "
"corresponding candidates pair gets selected.",
FALSE,
G_PARAM_READWRITE));
/**
* NiceAgent:proxy-ip:
*
......@@ -1183,6 +1202,7 @@ nice_agent_init (NiceAgent *agent)
agent->saved_controlling_mode = TRUE;
agent->max_conn_checks = NICE_AGENT_MAX_CONNECTIVITY_CHECKS_DEFAULT;
agent->nomination_mode = NICE_NOMINATION_MODE_AGGRESSIVE;
agent->support_renomination = FALSE;
agent->discovery_list = NULL;
agent->discovery_unsched_items = 0;
......@@ -1246,6 +1266,7 @@ nice_agent_new_full (GMainContext *ctx,
NICE_NOMINATION_MODE_REGULAR : NICE_NOMINATION_MODE_AGGRESSIVE,
"full-mode", (flags & NICE_AGENT_OPTION_LITE_MODE) ? FALSE : TRUE,
"ice-trickle", (flags & NICE_AGENT_OPTION_ICE_TRICKLE) ? TRUE : FALSE,
"support-renomination", (flags & NICE_AGENT_OPTION_SUPPORT_RENOMINATION) ? TRUE : FALSE,
NULL);
return agent;
......@@ -1302,6 +1323,10 @@ nice_agent_get_property (
g_value_set_enum (value, agent->nomination_mode);
break;
case PROP_SUPPORT_RENOMINATION:
g_value_set_boolean (value, agent->support_renomination);
break;
case PROP_PROXY_IP:
g_value_set_string (value, agent->proxy_ip);
break;
......@@ -1514,6 +1539,10 @@ nice_agent_set_property (
agent->nomination_mode = g_value_get_enum (value);
break;
case PROP_SUPPORT_RENOMINATION:
agent->support_renomination = g_value_get_boolean (value);
break;
case PROP_PROXY_IP:
g_free (agent->proxy_ip);
agent->proxy_ip = g_value_dup_string (value);
......
......@@ -405,6 +405,8 @@ typedef enum
* @NICE_AGENT_OPTION_RELIABLE: Enables reliable mode, possibly using PseudoTCP, * see nice_agent_new_reliable().
* @NICE_AGENT_OPTION_LITE_MODE: Enable lite mode
* @NICE_AGENT_OPTION_ICE_TRICKLE: Enable ICE trickle mode
* @NICE_AGENT_OPTION_SUPPORT_RENOMINATION: Enable renomination triggered by NOMINATION STUN attribute
* proposed here: https://tools.ietf.org/html/draft-thatcher-ice-renomination-00
*
* These are options that can be passed to nice_agent_new_full(). They set
* various properties on the agent. Not including them sets the property to
......@@ -417,6 +419,7 @@ typedef enum {
NICE_AGENT_OPTION_RELIABLE = 1 << 1,
NICE_AGENT_OPTION_LITE_MODE = 1 << 2,
NICE_AGENT_OPTION_ICE_TRICKLE = 1 << 3,
NICE_AGENT_OPTION_SUPPORT_RENOMINATION = 1 << 4,
} NiceAgentOption;
/**
......
......@@ -3913,6 +3913,62 @@ static bool conncheck_stun_validater (StunAgent *agent,
return FALSE;
}
/*
* handle RENOMINATION stun attribute
* @return TRUE if nomination changed. FALSE otherwise
*/
static gboolean conn_check_handle_renomination (NiceAgent *agent, NiceStream *stream,
NiceComponent *component, StunMessage *req,
NiceCandidate *remote_candidate, NiceCandidate *local_candidate)
{
GSList *lst;
if (!agent->controlling_mode && NICE_AGENT_IS_COMPATIBLE_WITH_RFC5245_OR_OC2007R2 (agent) &&
agent->support_renomination && remote_candidate && local_candidate)
{
uint32_t nom_value = 0;
uint16_t nom_len = 0;
const void *value = stun_message_find (req, STUN_ATTRIBUTE_NOMINATION, &nom_len);
if (nom_len == 0) {
return FALSE;
}
if (nom_len == 4) {
memcpy (&nom_value, value, 4);
nom_value = ntohl (nom_value);
} else {
nice_debug ("Agent %p : received NOMINATION attr with incorrect octet length %u, expected 4 bytes",
agent, nom_len);
return FALSE;
}
if (nice_debug_is_enabled ()) {
gchar remote_str[INET6_ADDRSTRLEN];
nice_address_to_string(&remote_candidate->addr, remote_str);
nice_debug ("Agent %p : received NOMINATION attr for remote candidate [%s]:%u, value is %u",
agent, remote_str, nice_address_get_port (&remote_candidate->addr), nom_value);
}
/*
* If another pair is SELECTED, change this pair's priority to be greater than
* selected pair's priority so this pair gets SELECTED!
*/
if (component->selected_pair.priority &&
component->selected_pair.remote && component->selected_pair.remote != remote_candidate &&
component->selected_pair.local && component->selected_pair.local != local_candidate) {
for (lst = stream->conncheck_list; lst; lst = lst->next) {
CandidateCheckPair *pair = lst->data;
if (pair->local == local_candidate && pair->remote == remote_candidate) {
if (pair->valid) {
pair->priority = component->selected_pair.priority + 1;
}
break;
}
}
}
priv_mark_pair_nominated (agent, stream, component, local_candidate, remote_candidate);
return TRUE;
}
return FALSE;
}
/*
* Processing an incoming STUN message.
......@@ -4278,6 +4334,9 @@ gboolean conn_check_handle_inbound_stun (NiceAgent *agent, NiceStream *stream,
"probably a keepalive.", agent);
}
/* RENOMINATION attribute support */
conn_check_handle_renomination(agent, stream, component, &req, local_candidate, remote_candidate);
return TRUE;
}
......
......@@ -230,6 +230,8 @@ typedef enum
* attribute as defined by [MS-ICE2]
* @STUN_ATTRIBUTE_MS_IMPLEMENTATION_VERSION: The IMPLEMENTATION-VERSION
* optional attribute as defined by [MS-ICE2]
* @STUN_ATTRIBUTE_NOMINATION: The NOMINATION attribute as defined by
* draft-thatcher-ice-renomination-00 and deployed in Google Chrome
*
* Known STUN attribute types as defined by various RFCs and drafts
*/
......@@ -309,8 +311,10 @@ typedef enum
/* 0x8051-0x8053 */ /* reserved */
STUN_ATTRIBUTE_CANDIDATE_IDENTIFIER=0x8054, /* MS-ICE2 */
/* 0x8055-0x806F */ /* reserved */
STUN_ATTRIBUTE_MS_IMPLEMENTATION_VERSION=0x8070 /* MS-ICE2 */
/* 0x8071-0xFFFF */ /* reserved */
STUN_ATTRIBUTE_MS_IMPLEMENTATION_VERSION=0x8070, /* MS-ICE2 */
/* 0x8071-0xC000 */ /* reserved */
STUN_ATTRIBUTE_NOMINATION=0xC001 /* https://tools.ietf.org/html/draft-thatcher-ice-renomination-00 */
/* 0xC002-0xFFFF */ /* reserved */
} StunAttribute;
......
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