diff options
-rw-r--r-- | agent/agent-priv.h | 1 | ||||
-rw-r--r-- | agent/agent.c | 29 | ||||
-rw-r--r-- | agent/agent.h | 3 | ||||
-rw-r--r-- | agent/conncheck.c | 59 | ||||
-rw-r--r-- | stun/stunmessage.h | 8 |
5 files changed, 98 insertions, 2 deletions
diff --git a/agent/agent-priv.h b/agent/agent-priv.h index a38aa23..91f73a3 100644 --- a/agent/agent-priv.h +++ b/agent/agent-priv.h @@ -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 */ diff --git a/agent/agent.c b/agent/agent.c index 59028ce..86bf37a 100644 --- a/agent/agent.c +++ b/agent/agent.c @@ -119,6 +119,7 @@ enum PROP_STUN_RELIABLE_TIMEOUT, PROP_NOMINATION_MODE, PROP_ICE_TRICKLE, + PROP_SUPPORT_RENOMINATION, }; @@ -466,6 +467,24 @@ nice_agent_class_init (NiceAgentClass *klass) 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: * * The proxy server IP used to bypass a proxy firewall @@ -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); diff --git a/agent/agent.h b/agent/agent.h index 2ad700c..688d784 100644 --- a/agent/agent.h +++ b/agent/agent.h @@ -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; /** diff --git a/agent/conncheck.c b/agent/conncheck.c index 06ba940..f8acfd6 100644 --- a/agent/conncheck.c +++ b/agent/conncheck.c @@ -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; } diff --git a/stun/stunmessage.h b/stun/stunmessage.h index 26ee12d..0ac9977 100644 --- a/stun/stunmessage.h +++ b/stun/stunmessage.h @@ -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; |