Commit 8bb210c5 authored by Fabrice Bellet's avatar Fabrice Bellet

stun timer: make properties for stun timer tunables

Three STUN binding request properties should be customisable. RFC 5245
describes the retransmission timer of the STUN transaction 'RTO', and
RFC 5389 describes the number of retransmissions to send until a
response is received 'Rc'. The third property is the 'RTO' when
a reliable connection is used.

RFC 5389 introduces a supplementary property 'Rm' as a multiplier used
to compute the final timeout RTO * Rm. However, this property is not
added in libnice, because this would require breaking the public API for
STUN. Currently, our STUN implementation hardcodes a division by two for
this final timeout.

Differential Revision: https://phabricator.freedesktop.org/D1109
parent 80c61369
......@@ -106,7 +106,6 @@ nice_input_message_iter_compare (const NiceInputMessageIter *a,
#define NICE_AGENT_TIMER_TA_DEFAULT 20 /* timer Ta, msecs (impl. defined) */
#define NICE_AGENT_TIMER_TR_DEFAULT 25000 /* timer Tr, msecs (impl. defined) */
#define NICE_AGENT_TIMER_TR_MIN 15000 /* timer Tr, msecs (ICE ID-19) */
#define NICE_AGENT_MAX_CONNECTIVITY_CHECKS_DEFAULT 100 /* see spec 5.7.3 (ID-19) */
......@@ -132,6 +131,9 @@ struct _NiceAgent
guint timer_ta; /* property: timer Ta */
guint max_conn_checks; /* property: max connectivity checks */
gboolean force_relay; /* property: force relay */
guint stun_max_retransmissions; /* property: stun max retransmissions, Rc */
guint stun_initial_timeout; /* property: stun initial timeout, RTO */
guint stun_reliable_timeout; /* property: stun reliable timeout */
GSList *local_addresses; /* list of NiceAddresses for local
interfaces */
......
......@@ -113,6 +113,9 @@ enum
PROP_BYTESTREAM_TCP,
PROP_KEEPALIVE_CONNCHECK,
PROP_FORCE_RELAY,
PROP_STUN_MAX_RETRANSMISSIONS,
PROP_STUN_INITIAL_TIMEOUT,
PROP_STUN_RELIABLE_TIMEOUT,
};
......@@ -708,6 +711,76 @@ nice_agent_class_init (NiceAgentClass *klass)
FALSE,
G_PARAM_READWRITE));
/**
* NiceAgent:stun-max-retransmissions
*
* The maximum number of retransmissions of the STUN binding requests
* used in the gathering stage, to find our local candidates, and used
* in the connection check stage, to test the validity of each
* constructed pair. This property is described as 'Rc' in the RFC
* 5389, with a default value of 7. The timeout of each STUN request
* is doubled for each retransmission, so the choice of this value has
* a direct impact on the time needed to move from the CONNECTED state
* to the READY state, and on the time needed to complete the GATHERING
* state.
*
* Since: UNRELEASED
*/
g_object_class_install_property (gobject_class, PROP_STUN_MAX_RETRANSMISSIONS,
g_param_spec_uint (
"stun-max-retransmissions",
"STUN Max Retransmissions",
"Maximum number of STUN binding requests retransmissions "
"described as 'Rc' in the STUN specification.",
1, 99,
STUN_TIMER_DEFAULT_MAX_RETRANSMISSIONS,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
/**
* NiceAgent:stun-initial-timeout
*
* The initial timeout (msecs) of the STUN binding requests
* used in the gathering stage, to find our local candidates.
* This property is described as 'RTO' in the RFC 5389 and RFC 5245.
* This timeout is doubled for each retransmission, until
* #NiceAgent:stun-max-retransmissions have been done,
* with an exception for the last restransmission, where the timeout is
* divided by two instead (RFC 5389 indicates that a customisable
* multiplier 'Rm' to 'RTO' should be used).
*
* Since: UNRELEASED
*/
g_object_class_install_property (gobject_class, PROP_STUN_INITIAL_TIMEOUT,
g_param_spec_uint (
"stun-initial-timeout",
"STUN Initial Timeout",
"STUN timeout in msecs of the initial binding requests used in the "
"gathering state, described as 'RTO' in the ICE specification.",
20, 9999,
STUN_TIMER_DEFAULT_TIMEOUT,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
/**
* NiceAgent:stun-reliable-timeout
*
* The initial timeout of the STUN binding requests used
* for a reliable timer.
*
* Since: UNRELEASED
*/
g_object_class_install_property (gobject_class, PROP_STUN_RELIABLE_TIMEOUT,
g_param_spec_uint (
"stun-reliable-timeout",
"STUN Reliable Timeout",
"STUN timeout in msecs of the initial binding requests used for "
"a reliable timer.",
20, 99999,
STUN_TIMER_DEFAULT_RELIABLE_TIMEOUT,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
/* install signals */
/**
......@@ -1187,6 +1260,18 @@ nice_agent_get_property (
g_value_set_boolean (value, agent->force_relay);
break;
case PROP_STUN_MAX_RETRANSMISSIONS:
g_value_set_uint (value, agent->stun_max_retransmissions);
break;
case PROP_STUN_INITIAL_TIMEOUT:
g_value_set_uint (value, agent->stun_initial_timeout);
break;
case PROP_STUN_RELIABLE_TIMEOUT:
g_value_set_uint (value, agent->stun_reliable_timeout);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
}
......@@ -1374,6 +1459,18 @@ nice_agent_set_property (
agent->force_relay = g_value_get_boolean (value);
break;
case PROP_STUN_MAX_RETRANSMISSIONS:
agent->stun_max_retransmissions = g_value_get_uint (value);
break;
case PROP_STUN_INITIAL_TIMEOUT:
agent->stun_initial_timeout = g_value_get_uint (value);
break;
case PROP_STUN_RELIABLE_TIMEOUT:
agent->stun_reliable_timeout = g_value_get_uint (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
}
......
......@@ -888,8 +888,9 @@ static gboolean priv_conn_keepalive_tick_unlocked (NiceAgent *agent)
agent, buf_len, p->keepalive.stun_message.buffer);
if (buf_len > 0) {
stun_timer_start (&p->keepalive.timer, STUN_TIMER_DEFAULT_TIMEOUT,
STUN_TIMER_DEFAULT_MAX_RETRANSMISSIONS);
stun_timer_start (&p->keepalive.timer,
agent->stun_initial_timeout,
agent->stun_max_retransmissions);
agent->media_after_tick = FALSE;
......@@ -1116,8 +1117,9 @@ static void priv_turn_allocate_refresh_tick_unlocked (CandidateRefresh *cand)
}
if (buffer_len > 0) {
stun_timer_start (&cand->timer, STUN_TIMER_DEFAULT_TIMEOUT,
STUN_TIMER_DEFAULT_MAX_RETRANSMISSIONS);
stun_timer_start (&cand->timer,
cand->agent->stun_initial_timeout,
cand->agent->stun_max_retransmissions);
/* send the refresh */
agent_socket_send (cand->nicesock, &cand->server,
......@@ -2171,11 +2173,11 @@ int conn_check_send (NiceAgent *agent, CandidateCheckPair *pair)
if (buffer_len > 0) {
if (nice_socket_is_reliable(pair->sockptr)) {
stun_timer_start_reliable(&pair->timer, STUN_TIMER_DEFAULT_RELIABLE_TIMEOUT);
stun_timer_start_reliable(&pair->timer, agent->stun_reliable_timeout);
} else {
stun_timer_start (&pair->timer,
priv_compute_conncheck_timer (agent),
STUN_TIMER_DEFAULT_MAX_RETRANSMISSIONS);
agent->stun_max_retransmissions);
}
/* TCP-ACTIVE candidate must create a new socket before sending
......@@ -2340,7 +2342,7 @@ static gboolean priv_schedule_triggered_check (NiceAgent *agent, NiceStream *str
if (!nice_socket_is_reliable (p->sockptr) && !p->timer_restarted) {
stun_timer_start (&p->timer,
priv_compute_conncheck_timer (agent),
STUN_TIMER_DEFAULT_MAX_RETRANSMISSIONS);
agent->stun_max_retransmissions);
p->timer_restarted = TRUE;
}
}
......
......@@ -1072,11 +1072,11 @@ static gboolean priv_discovery_tick_unlocked (gpointer pointer)
if (buffer_len > 0) {
if (nice_socket_is_reliable (cand->nicesock)) {
stun_timer_start_reliable (&cand->timer,
STUN_TIMER_DEFAULT_RELIABLE_TIMEOUT);
stun_timer_start_reliable (&cand->timer, agent->stun_reliable_timeout);
} else {
stun_timer_start (&cand->timer, 200,
STUN_TIMER_DEFAULT_MAX_RETRANSMISSIONS);
stun_timer_start (&cand->timer,
agent->stun_initial_timeout,
agent->stun_max_retransmissions);
}
/* send the conncheck */
......
......@@ -132,7 +132,11 @@ struct stun_timer_s {
* The default intial timeout to use for the timer
* RFC recommendds 500, but it's ridiculous, 50ms is known to work in most
* cases as it is also what is used by SIP style VoIP when sending A-Law and
* mu-Law audio, so 200ms should be hyper safe.
* mu-Law audio, so 200ms should be hyper safe. With an initial timeout
* of 200ms, a default of 7 transmissions, the last timeout will be
* 16 * 200ms, and we expect to receive a response from the stun server
* before (1 + 2 + 4 + 8 + 16 + 32 + 16) * 200ms = 15200 ms after the initial
* stun request has been sent.
*/
#define STUN_TIMER_DEFAULT_TIMEOUT 200
......
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