Bug 17592: Clean up connection timeout logic.

This unifies CircuitIdleTimeout and PredictedCircsRelevanceTime into a single
option, and randomizes it.

It also gives us control over the default value as well as relay-to-relay
connection lifespan through the consensus.

Conflicts:
	src/or/circuituse.c
	src/or/config.c
	src/or/main.c
	src/test/testing_common.c
This commit is contained in:
Mike Perry 2017-02-21 21:28:00 -05:00 committed by Nick Mathewson
parent b0e92634d8
commit d5a151a067
13 changed files with 339 additions and 71 deletions

13
changes/bug17592 Normal file
View File

@ -0,0 +1,13 @@
o Minor bugfixes (connection lifespan)
- Allow more control over how long TLS connections are kept open: unify
CircuitIdleTimeout and PredictedPortsRelevanceTime into a single option
called CircuitsAvailableTimeout. Also, allow the consensus to control
the default values for both this preference, as well as the lifespan
of relay-to-relay connections. Fixes bug #17592.
- Increase the intial circuit build timeout testing frequency, to help
ensure that ReducedConnectionPadding clients finish learning a timeout
before their orconn would expire. The initial testing rate was set back
in the days of TAP and before the Tor Browser updater, when we had to be
much more careful about new clients making lots of circuits. With this
change, a circuit build time is learned in about 15-20 minutes, instead
of ~100-120 minutes.

View File

@ -666,8 +666,8 @@ GENERAL OPTIONS
[[PredictedPortsRelevanceTime]] **PredictedPortsRelevanceTime** __NUM__::
Set how long, after the client has made an anonymized connection to a
given port, we will try to make sure that we build circuits to
exits that support that port. The maximum value for this option is 1
hour. (Default: 1 hour)
exits that support that port. This option is deprecated. Please use
CircuitsAvailableTimeout instead.
[[RunAsDaemon]] **RunAsDaemon** **0**|**1**::
If 1, Tor forks and daemonizes to the background. This option has no effect
@ -809,13 +809,19 @@ The following options are useful only for clients (that is, if
LearnCircuitBuildTimeout is 0, this value is the only value used.
(Default: 60 seconds)
[[CircuitsAvailableTimeout]] **CircuitsAvailableTimeout** __NUM__::
Tor will attempt to keep at least one open, unused circuit available for
this amount of time. This option governs how long idle circuits are kept
open, as well as the amount of time Tor will keep a circuit open to each
of the recently used ports. This way when the Tor client is entirely
idle, it can expire all of its circuits, and then expire its TLS
connections. Note that the actual timeout value is uniformly randomized
from the specified value to twice that amount. (Default: 30 minutes;
Max: 24 hours)
[[CircuitIdleTimeout]] **CircuitIdleTimeout** __NUM__::
If we have kept a clean (never used) circuit around for NUM seconds, then
close it. This way when the Tor client is entirely idle, it can expire all
of its circuits, and then expire its TLS connections. Also, if we end up
making a circuit that is not useful for exiting any of the requests we're
receiving, it won't forever take up a slot in the circuit list. (Default: 1
hour)
close it. This option is deprecated. Use CircuitsAvailableTimeout instead.
[[CircuitStreamTimeout]] **CircuitStreamTimeout** __NUM__::
If non-zero, this option overrides our internal timeout schedule for how

View File

@ -446,6 +446,111 @@ channelpadding_compute_time_until_pad_for_netflow(channel_t *chan)
return CHANNELPADDING_TIME_LATER;
}
/**
* Returns a randomized value for channel idle timeout in seconds.
* The channel idle timeout governs how quickly we close a channel
* after its last circuit has disappeared.
*
* There are three classes of channels:
* 1. Client+non-canonical. These live for 3-4.5 minutes
* 2. relay to relay. These live for 45-75 min by default
* 3. Reduced padding clients. These live for 1.5-2.25 minutes.
*
* Also allows the default relay-to-relay value to be controlled by the
* consensus.
*/
unsigned int
channelpadding_get_channel_idle_timeout(const channel_t *chan,
int is_canonical)
{
const or_options_t *options = get_options();
unsigned int timeout;
/* Non-canonical and client channels only last for 3-4.5 min when idle */
if (!is_canonical || !public_server_mode(options) ||
chan->is_client ||
!connection_or_digest_is_known_relay(chan->identity_digest)) {
#define CONNTIMEOUT_CLIENTS_BASE 180 // 3 to 4.5 min
timeout = CONNTIMEOUT_CLIENTS_BASE
+ crypto_rand_int(CONNTIMEOUT_CLIENTS_BASE/2);
} else { // Canonical relay-to-relay channels
// 45..75min or consensus +/- 25%
#define CONNTIMEOUT_RELAYS_DFLT (60*60) // 1 hour
#define CONNTIMEOUT_RELAYS_MIN 60
#define CONNTIMEOUT_RELAYS_MAX (7*24*60*60) // 1 week
timeout = networkstatus_get_param(NULL, "nf_conntimeout_relays",
CONNTIMEOUT_RELAYS_DFLT,
CONNTIMEOUT_RELAYS_MIN,
CONNTIMEOUT_RELAYS_MAX);
timeout = 3*timeout/4 + crypto_rand_int(timeout/2);
}
/* If ReducedConnectionPadding is set, we want to halve the duration of
* the channel idle timeout, since reducing the additional time that
* a channel stays open will reduce the total overhead for making
* new channels. This reduction in overhead/channel expense
* is important for mobile users. The option cannot be set by relays.
*
* We also don't reduce any values for timeout that the user explicitly
* set.
*/
if (options->ReducedConnectionPadding
&& !options->CircuitsAvailableTimeout) {
timeout /= 2;
}
return timeout;
}
/**
* This function controls how long we keep idle circuits open,
* and how long we build predicted circuits. This behavior is under
* the control of channelpadding because circuit availability is the
* dominant factor in channel lifespan, which influences total padding
* overhead.
*
* Returns a randomized number of seconds in a range from
* CircuitsAvailableTimeout to 2*CircuitsAvailableTimeout. This value is halved
* if ReducedConnectionPadding is set. The default value of
* CircuitsAvailableTimeout can be controlled by the consensus.
*/
int
channelpadding_get_circuits_available_timeout(void)
{
const or_options_t *options = get_options();
int timeout = options->CircuitsAvailableTimeout;
if (!timeout) {
#define CIRCTIMEOUT_CLIENTS_DFLT (30*60) // 30 minutes
#define CIRCTIMEOUT_CLIENTS_MIN 60
#define CIRCTIMEOUT_CLIENTS_MAX (24*60*60) // 24 hours
timeout = networkstatus_get_param(NULL, "nf_conntimeout_clients",
CIRCTIMEOUT_CLIENTS_DFLT,
CIRCTIMEOUT_CLIENTS_MIN,
CIRCTIMEOUT_CLIENTS_MAX);
/* If ReducedConnectionPadding is set, we want to halve the duration of
* the channel idle timeout, since reducing the additional time that
* a channel stays open will reduce the total overhead for making
* new connections. This reduction in overhead/connection expense
* is important for mobile users. The option cannot be set by relays.
*
* We also don't reduce any values for timeout that the user explicitly
* set.
*/
if (options->ReducedConnectionPadding) {
// half the value to 15..30min by default
timeout /= 2;
}
}
// 30..60min by default
timeout = timeout + crypto_rand_int(timeout);
return timeout;
}
/**
* Calling this function on a channel causes it to tell the other side
* not to send padding, and disables sending padding from this side as well.

View File

@ -78,6 +78,7 @@
#include "rephist.h"
#include "routerlist.h"
#include "routerset.h"
#include "channelpadding.h"
#include "ht.h"
@ -814,6 +815,11 @@ init_circuit_base(circuit_t *circ)
circ->global_circuitlist_idx = smartlist_len(circuit_get_global_list()) - 1;
}
/** If we haven't yet decided on a good timeout value for circuit
* building, we close idle circuits aggressively so we can get more
* data points. */
#define IDLE_TIMEOUT_WHILE_LEARNING (1*60)
/** Allocate space for a new circuit, initializing with <b>p_circ_id</b>
* and <b>p_conn</b>. Add it to the global circuit list.
*/
@ -841,6 +847,41 @@ origin_circuit_new(void)
circuit_build_times_update_last_circ(get_circuit_build_times_mutable());
if (! circuit_build_times_disabled(get_options()) &&
circuit_build_times_needs_circuits(get_circuit_build_times())) {
/* Circuits should be shorter lived if we need more of them
* for learning a good build timeout */
circ->circuit_idle_timeout = IDLE_TIMEOUT_WHILE_LEARNING;
} else {
// This should always be larger than the current port prediction time
// remaining, or else we'll end up with the case where a circuit times out
// and another one is built, effectively doubling the timeout window.
//
// We also randomize it by up to 5% more (ie 5% of 0 to 3600 seconds,
// depending on how much circuit prediction time is remaining) so that
// we don't close a bunch of unused circuits all at the same time.
int prediction_time_remaining =
predicted_ports_prediction_time_remaining(time(NULL));
circ->circuit_idle_timeout = prediction_time_remaining+1+
crypto_rand_int(1+prediction_time_remaining/20);
if (circ->circuit_idle_timeout <= 0) {
log_warn(LD_BUG,
"Circuit chose a negative idle timeout of %d based on "
"%d seconds of predictive building remaining.",
circ->circuit_idle_timeout,
prediction_time_remaining);
circ->circuit_idle_timeout = IDLE_TIMEOUT_WHILE_LEARNING;
}
log_info(LD_CIRC,
"Circuit " U64_FORMAT " chose an idle timeout of %d based on "
"%d seconds of predictive building remaining.",
U64_PRINTF_ARG(circ->global_identifier),
circ->circuit_idle_timeout,
prediction_time_remaining);
}
return circ;
}

View File

@ -1383,11 +1383,6 @@ circuit_detach_stream(circuit_t *circ, edge_connection_t *conn)
tor_fragile_assert();
}
/** If we haven't yet decided on a good timeout value for circuit
* building, we close idles circuits aggressively so we can get more
* data points. */
#define IDLE_TIMEOUT_WHILE_LEARNING (10*60)
/** Find each circuit that has been unused for too long, or dirty
* for too long and has no streams on it: mark it for close.
*/
@ -1397,21 +1392,15 @@ circuit_expire_old_circuits_clientside(void)
struct timeval cutoff, now;
tor_gettimeofday(&now);
cutoff = now;
last_expired_clientside_circuits = now.tv_sec;
if (! circuit_build_times_disabled(get_options()) &&
circuit_build_times_needs_circuits(get_circuit_build_times())) {
/* Circuits should be shorter lived if we need more of them
* for learning a good build timeout */
cutoff.tv_sec -= IDLE_TIMEOUT_WHILE_LEARNING;
} else {
cutoff.tv_sec -= get_options()->CircuitIdleTimeout;
}
SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, circ) {
if (circ->marked_for_close || !CIRCUIT_IS_ORIGIN(circ))
continue;
cutoff = now;
cutoff.tv_sec -= TO_ORIGIN_CIRCUIT(circ)->circuit_idle_timeout;
/* If the circuit has been dirty for too long, and there are no streams
* on it, mark it for close.
*/
@ -1437,8 +1426,10 @@ circuit_expire_old_circuits_clientside(void)
(circ->purpose >= CIRCUIT_PURPOSE_C_INTRODUCING &&
circ->purpose <= CIRCUIT_PURPOSE_C_REND_READY_INTRO_ACKED) ||
circ->purpose == CIRCUIT_PURPOSE_S_CONNECT_REND) {
log_debug(LD_CIRC,
"Closing circuit that has been unused for %ld msec.",
log_info(LD_CIRC,
"Closing circuit "U64_FORMAT
" that has been unused for %ld msec.",
U64_PRINTF_ARG(TO_ORIGIN_CIRCUIT(circ)->global_identifier),
tv_mdiff(&circ->timestamp_began, &now));
circuit_mark_for_close(circ, END_CIRC_REASON_FINISHED);
} else if (!TO_ORIGIN_CIRCUIT(circ)->is_ancient) {

View File

@ -245,7 +245,8 @@ static config_var_t option_vars_[] = {
V(PaddingStatistics, BOOL, "1"),
V(LearnCircuitBuildTimeout, BOOL, "1"),
V(CircuitBuildTimeout, INTERVAL, "0"),
V(CircuitIdleTimeout, INTERVAL, "1 hour"),
OBSOLETE("CircuitIdleTimeout"),
V(CircuitsAvailableTimeout, INTERVAL, "0"),
V(CircuitStreamTimeout, INTERVAL, "0"),
V(CircuitPriorityHalflife, DOUBLE, "-100.0"), /*negative:'Use default'*/
V(ClientDNSRejectInternalAddresses, BOOL,"1"),
@ -402,7 +403,7 @@ static config_var_t option_vars_[] = {
V(NATDListenAddress, LINELIST, NULL),
VPORT(NATDPort),
V(Nickname, STRING, NULL),
V(PredictedPortsRelevanceTime, INTERVAL, "1 hour"),
OBSOLETE("PredictedPortsRelevanceTime"),
V(WarnUnsafeSocks, BOOL, "1"),
VAR("NodeFamily", LINELIST, NodeFamilies, NULL),
V(NumCPUs, UINT, "0"),
@ -2812,10 +2813,10 @@ compute_publishserverdescriptor(or_options_t *options)
#define MIN_REND_POST_PERIOD (10*60)
#define MIN_REND_POST_PERIOD_TESTING (5)
/** Highest allowable value for PredictedPortsRelevanceTime; if this is
* too high, our selection of exits will decrease for an extended
* period of time to an uncomfortable level .*/
#define MAX_PREDICTED_CIRCS_RELEVANCE (60*60)
/** Higest allowable value for CircuitsAvailableTimeout.
* If this is too large, client connections will stay open for too long,
* incurring extra padding overhead. */
#define MAX_CIRCS_AVAILABLE_TIME (24*60*60)
/** Highest allowable value for RendPostPeriod. */
#define MAX_DIR_PERIOD (MIN_ONION_KEY_LIFETIME/2)
@ -3461,17 +3462,17 @@ options_validate(or_options_t *old_options, or_options_t *options,
options->RendPostPeriod = MAX_DIR_PERIOD;
}
if (options->PredictedPortsRelevanceTime >
MAX_PREDICTED_CIRCS_RELEVANCE) {
log_warn(LD_CONFIG, "PredictedPortsRelevanceTime is too large; "
"clipping to %ds.", MAX_PREDICTED_CIRCS_RELEVANCE);
options->PredictedPortsRelevanceTime = MAX_PREDICTED_CIRCS_RELEVANCE;
}
/* Check the Single Onion Service options */
if (options_validate_single_onion(options, msg) < 0)
return -1;
if (options->CircuitsAvailableTimeout > MAX_CIRCS_AVAILABLE_TIME) {
// options_t is immutable for new code (the above code is older),
// so just make the user fix the value themselves rather than
// silently keep a shadow value lower than what they asked for.
REJECT("CircuitsAvailableTimeout is too large. Max is 24 hours.");
}
#ifdef ENABLE_TOR2WEB_MODE
if (options->Tor2webMode && options->UseEntryGuards) {
/* tor2web mode clients do not (and should not) use entry guards

View File

@ -815,24 +815,6 @@ connection_or_update_token_buckets(smartlist_t *conns,
});
}
/** How long do we wait before killing non-canonical OR connections with no
* circuits? In Tor versions up to 0.2.1.25 and 0.2.2.12-alpha, we waited 15
* minutes before cancelling these connections, which caused fast relays to
* accrue many many idle connections. Hopefully 3-4.5 minutes is low enough
* that it kills most idle connections, without being so low that we cause
* clients to bounce on and off.
*
* For canonical connections, the limit is higher, at 15-22.5 minutes.
*
* For each OR connection, we randomly add up to 50% extra to its idle_timeout
* field, to avoid exposing when exactly the last circuit closed. Since we're
* storing idle_timeout in a uint16_t, don't let these values get higher than
* 12 hours or so without revising connection_or_set_canonical and/or expanding
* idle_timeout.
*/
#define IDLE_OR_CONN_TIMEOUT_NONCANONICAL 180
#define IDLE_OR_CONN_TIMEOUT_CANONICAL 900
/* Mark <b>or_conn</b> as canonical if <b>is_canonical</b> is set, and
* non-canonical otherwise. Adjust idle_timeout accordingly.
*/
@ -840,9 +822,6 @@ void
connection_or_set_canonical(or_connection_t *or_conn,
int is_canonical)
{
const unsigned int timeout_base = is_canonical ?
IDLE_OR_CONN_TIMEOUT_CANONICAL : IDLE_OR_CONN_TIMEOUT_NONCANONICAL;
if (bool_eq(is_canonical, or_conn->is_canonical) &&
or_conn->idle_timeout != 0) {
/* Don't recalculate an existing idle_timeout unless the canonical
@ -851,7 +830,14 @@ connection_or_set_canonical(or_connection_t *or_conn,
}
or_conn->is_canonical = !! is_canonical; /* force to a 1-bit boolean */
or_conn->idle_timeout = timeout_base + crypto_rand_int(timeout_base / 2);
or_conn->idle_timeout = channelpadding_get_channel_idle_timeout(
TLS_CHAN_TO_BASE(or_conn->chan), is_canonical);
log_info(LD_CIRC,
"Channel " U64_FORMAT " chose an idle timeout of %d.",
or_conn->chan ?
U64_PRINTF_ARG(TLS_CHAN_TO_BASE(or_conn->chan)->global_identifier):0,
or_conn->idle_timeout);
}
/** If we don't necessarily know the router we're connecting to, but we

View File

@ -1096,8 +1096,9 @@ run_connection_housekeeping(int i, time_t now)
} else if (!have_any_circuits &&
now - or_conn->idle_timeout >=
chan->timestamp_last_had_circuits) {
log_info(LD_OR,"Expiring non-used OR connection to fd %d (%s:%d) "
"[no circuits for %d; timeout %d; %scanonical].",
log_info(LD_OR,"Expiring non-used OR connection "U64_FORMAT" to fd %d "
"(%s:%d) [no circuits for %d; timeout %d; %scanonical].",
U64_PRINTF_ARG(chan->global_identifier),
(int)conn->s, conn->address, conn->port,
(int)(now - chan->timestamp_last_had_circuits),
or_conn->idle_timeout,
@ -3019,6 +3020,9 @@ tor_init(int argc, char *argv[])
/* The options are now initialised */
const or_options_t *options = get_options();
/* Initialize predicted ports list after loading options */
predicted_ports_init();
#ifndef _WIN32
if (geteuid()==0)
log_warn(LD_GENERAL,"You are running Tor as root. You don't need to, "

View File

@ -3301,6 +3301,13 @@ typedef struct origin_circuit_t {
* adjust_exit_policy_from_exitpolicy_failure.
*/
smartlist_t *prepend_policy;
/** How long do we wait before closing this circuit if it remains
* completely idle after it was built, in seconds? This value
* is randomized on a per-circuit basis from CircuitsAvailableTimoeut
* to 2*CircuitsAvailableTimoeut. */
int circuit_idle_timeout;
} origin_circuit_t;
struct onion_queue_t;
@ -3882,6 +3889,8 @@ typedef struct {
* adaptive algorithm learns a new value. */
int CircuitIdleTimeout; /**< Cull open clean circuits that were born
* at least this many seconds ago. */
int CircuitsAvailableTimeout; /**< Try to have an open circuit for at
least this long after last activity */
int CircuitStreamTimeout; /**< If non-zero, detach streams from circuits
* and try a new circuit if the stream has been
* waiting for this many seconds. If zero, use
@ -4826,7 +4835,7 @@ typedef uint32_t build_time_t;
double circuit_build_times_quantile_cutoff(void);
/** How often in seconds should we build a test circuit */
#define CBT_DEFAULT_TEST_FREQUENCY 60
#define CBT_DEFAULT_TEST_FREQUENCY 10
#define CBT_MIN_TEST_FREQUENCY 1
#define CBT_MAX_TEST_FREQUENCY INT32_MAX

View File

@ -84,12 +84,13 @@
#include "router.h"
#include "routerlist.h"
#include "ht.h"
#include "channelpadding.h"
#include "channelpadding.h"
#include "connection_or.h"
static void bw_arrays_init(void);
static void predicted_ports_init(void);
static void predicted_ports_alloc(void);
/** Total number of bytes currently allocated in fields used by rephist.c. */
uint64_t rephist_total_alloc=0;
@ -305,7 +306,7 @@ rep_hist_init(void)
{
history_map = digestmap_new();
bw_arrays_init();
predicted_ports_init();
predicted_ports_alloc();
}
/** Helper: note that we are no longer connected to the router with history
@ -1799,6 +1800,36 @@ typedef struct predicted_port_t {
/** A list of port numbers that have been used recently. */
static smartlist_t *predicted_ports_list=NULL;
/** How long do we keep predicting circuits? */
static int prediction_timeout=0;
/** When was the last time we added a prediction entry (HS or port) */
static time_t last_prediction_add_time=0;
/**
* How much time left until we stop predicting circuits?
*/
int
predicted_ports_prediction_time_remaining(time_t now)
{
time_t idle_delta = now - last_prediction_add_time;
/* Protect against overflow of return value. This can happen if the clock
* jumps backwards in time. Update the last prediction time (aka last
* active time) to prevent it. This update is preferable to using monotonic
* time because it prevents clock jumps into the past from simply causing
* very long idle timeouts while the monotonic time stands still. */
if (last_prediction_add_time > now) {
last_prediction_add_time = now;
idle_delta = 0;
}
/* Protect against underflow of the return value. This can happen for very
* large periods of inactivity/system sleep. */
if (idle_delta > prediction_timeout)
return 0;
return prediction_timeout - idle_delta;
}
/** We just got an application request for a connection with
* port <b>port</b>. Remember it for the future, so we can keep
@ -1808,21 +1839,40 @@ static void
add_predicted_port(time_t now, uint16_t port)
{
predicted_port_t *pp = tor_malloc(sizeof(predicted_port_t));
// If the list is empty, re-randomize predicted ports lifetime
if (!any_predicted_circuits(now)) {
prediction_timeout = channelpadding_get_circuits_available_timeout();
}
last_prediction_add_time = now;
log_info(LD_CIRC,
"New port prediction added. Will continue predictive circ building "
"for %d more seconds.",
predicted_ports_prediction_time_remaining(now));
pp->port = port;
pp->time = now;
rephist_total_alloc += sizeof(*pp);
smartlist_add(predicted_ports_list, pp);
}
/** Initialize whatever memory and structs are needed for predicting
/**
* Allocate whatever memory and structs are needed for predicting
* which ports will be used. Also seed it with port 80, so we'll build
* circuits on start-up.
*/
static void
predicted_ports_init(void)
predicted_ports_alloc(void)
{
predicted_ports_list = smartlist_new();
add_predicted_port(time(NULL), 80); /* add one to kickstart us */
}
void
predicted_ports_init(void)
{
add_predicted_port(time(NULL), 443); // Add a port to get us started
}
/** Free whatever memory is needed for predicting which ports will
@ -1853,6 +1903,12 @@ rep_hist_note_used_port(time_t now, uint16_t port)
SMARTLIST_FOREACH_BEGIN(predicted_ports_list, predicted_port_t *, pp) {
if (pp->port == port) {
pp->time = now;
last_prediction_add_time = now;
log_info(LD_CIRC,
"New port prediction added. Will continue predictive circ "
"building for %d more seconds.",
predicted_ports_prediction_time_remaining(now));
return;
}
} SMARTLIST_FOREACH_END(pp);
@ -1869,8 +1925,8 @@ rep_hist_get_predicted_ports(time_t now)
int predicted_circs_relevance_time;
smartlist_t *out = smartlist_new();
tor_assert(predicted_ports_list);
// XXX: Change this if ReducedConnectionPadding is set.
predicted_circs_relevance_time = get_options()->PredictedPortsRelevanceTime;
predicted_circs_relevance_time = prediction_timeout;
/* clean out obsolete entries */
SMARTLIST_FOREACH_BEGIN(predicted_ports_list, predicted_port_t *, pp) {
@ -1930,6 +1986,18 @@ static time_t predicted_internal_capacity_time = 0;
void
rep_hist_note_used_internal(time_t now, int need_uptime, int need_capacity)
{
// If the list is empty, re-randomize predicted ports lifetime
if (!any_predicted_circuits(now)) {
prediction_timeout = channelpadding_get_circuits_available_timeout();
}
last_prediction_add_time = now;
log_info(LD_CIRC,
"New port prediction added. Will continue predictive circ building "
"for %d more seconds.",
predicted_ports_prediction_time_remaining(now));
predicted_internal_time = now;
if (need_uptime)
predicted_internal_uptime_time = now;
@ -1943,7 +2011,8 @@ rep_hist_get_predicted_internal(time_t now, int *need_uptime,
int *need_capacity)
{
int predicted_circs_relevance_time;
predicted_circs_relevance_time = get_options()->PredictedPortsRelevanceTime;
predicted_circs_relevance_time = prediction_timeout;
if (!predicted_internal_time) { /* initialize it */
predicted_internal_time = now;
@ -1965,7 +2034,7 @@ int
any_predicted_circuits(time_t now)
{
int predicted_circs_relevance_time;
predicted_circs_relevance_time = get_options()->PredictedPortsRelevanceTime;
predicted_circs_relevance_time = prediction_timeout;
return smartlist_len(predicted_ports_list) ||
predicted_internal_time + predicted_circs_relevance_time >= now;

View File

@ -48,6 +48,7 @@ double rep_hist_get_weighted_fractional_uptime(const char *id, time_t when);
long rep_hist_get_weighted_time_known(const char *id, time_t when);
int rep_hist_have_measured_enough_stability(void);
void predicted_ports_init(void);
void rep_hist_note_used_port(time_t now, uint16_t port);
smartlist_t *rep_hist_get_predicted_ports(time_t now);
void rep_hist_remove_predicted_ports(const smartlist_t *rmv_ports);
@ -59,6 +60,7 @@ int rep_hist_get_predicted_internal(time_t now, int *need_uptime,
int any_predicted_circuits(time_t now);
int rep_hist_circbuilding_dormant(time_t now);
int predicted_ports_prediction_time_remaining(time_t now);
void note_crypto_pk_op(pk_op_t operation);
void dump_pk_ops(int severity);

View File

@ -359,6 +359,7 @@ test_channelpadding_consensus(void *arg)
* consensus defaults
* 4. Relay-to-relay padding can be enabled/disabled in consensus
* 5. Can enable/disable padding before actually using a connection
* 6. Can we control circ and TLS conn lifetime from the consensus?
*/
channel_t *chan;
routerstatus_t *relay = tor_malloc_zero(sizeof(routerstatus_t));
@ -491,6 +492,43 @@ test_channelpadding_consensus(void *arg)
tt_int_op(decision, OP_EQ, CHANNELPADDING_WONTPAD);
tt_assert(!chan->pending_padding_callback);
/* Test 6: Can we control circ and TLS conn lifetime from the consensus? */
val = channelpadding_get_channel_idle_timeout(NULL, 0);
tt_int_op(val, OP_GE, 180);
tt_int_op(val, OP_LE, 180+90);
val = channelpadding_get_channel_idle_timeout(chan, 0);
tt_int_op(val, OP_GE, 180);
tt_int_op(val, OP_LE, 180+90);
options->ReducedConnectionPadding = 1;
val = channelpadding_get_channel_idle_timeout(chan, 0);
tt_int_op(val, OP_GE, 180/2);
tt_int_op(val, OP_LE, (180+90)/2);
options->ReducedConnectionPadding = 0;
options->ORPort_set = 1;
smartlist_add(current_md_consensus->net_params,
(void*)"nf_conntimeout_relays=600");
val = channelpadding_get_channel_idle_timeout(chan, 1);
tt_int_op(val, OP_GE, 450);
tt_int_op(val, OP_LE, 750);
val = channelpadding_get_circuits_available_timeout();
tt_int_op(val, OP_GE, 30*60);
tt_int_op(val, OP_LE, 30*60*2);
options->ReducedConnectionPadding = 1;
smartlist_add(current_md_consensus->net_params,
(void*)"nf_conntimeout_clients=600");
val = channelpadding_get_circuits_available_timeout();
tt_int_op(val, OP_GE, 600/2);
tt_int_op(val, OP_LE, 600*2/2);
options->ReducedConnectionPadding = 0;
options->CircuitsAvailableTimeout = 24*60*60;
val = channelpadding_get_circuits_available_timeout();
tt_int_op(val, OP_GE, 24*60*60);
tt_int_op(val, OP_LE, 24*60*60*2);
done:
free_fake_channeltls((channel_tls_t*)chan);
smartlist_free(connection_array);

View File

@ -304,10 +304,13 @@ main(int c, const char **v)
tor_free(errmsg);
return 1;
}
tor_set_failed_assertion_callback(an_assertion_failed);
init_pregenerated_keys();
predicted_ports_init();
atexit(remove_directory);
int have_failed = (tinytest_main(c, v, testgroups) != 0);