summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.travis.yml2
-rw-r--r--changes/bug258433
-rw-r--r--changes/feature194295
-rw-r--r--changes/ticket233546
-rw-r--r--changes/ticket25376_2576210
-rw-r--r--changes/ticket259319
-rw-r--r--changes/ticket259329
-rw-r--r--configure.ac15
-rw-r--r--doc/tor.1.txt91
-rw-r--r--src/common/aes.c4
-rw-r--r--src/common/crypto.c16
-rw-r--r--src/common/torint.h2
-rw-r--r--src/common/tortls.c19
-rw-r--r--src/or/channel.c4
-rw-r--r--src/or/circuitlist.c1
-rw-r--r--src/or/config.c95
-rw-r--r--src/or/confparse.c80
-rw-r--r--src/or/confparse.h6
-rw-r--r--src/or/connection.c1
-rw-r--r--src/or/consdiffmgr.c33
-rw-r--r--src/or/directory.c54
-rw-r--r--src/or/directory.h4
-rw-r--r--src/or/entrynodes.c16
-rw-r--r--src/or/hibernate.c10
-rw-r--r--src/or/hs_service.c28
-rw-r--r--src/or/hs_service.h1
-rw-r--r--src/or/main.c154
-rw-r--r--src/or/main.h3
-rw-r--r--src/or/or.h21
-rw-r--r--src/or/periodic.h15
-rw-r--r--src/or/rendservice.c11
-rw-r--r--src/test/geoip_dummy0
-rw-r--r--src/test/include.am1
-rw-r--r--src/test/test_dir.c127
-rw-r--r--src/test/test_entrynodes.c19
-rw-r--r--src/test/test_geoip.c84
-rw-r--r--src/test/test_options.c12
-rw-r--r--src/test/test_periodic_event.c73
-rw-r--r--src/test/test_tortls.c41
-rw-r--r--src/test/testing_common.c3
40 files changed, 716 insertions, 372 deletions
diff --git a/.travis.yml b/.travis.yml
index 18c5b5bdd5..46317ee064 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -144,8 +144,6 @@ install:
- if [[ "$RUST_OPTIONS" != "" ]]; then rustc --version; fi
- if [[ "$RUST_OPTIONS" != "" ]]; then cargo --version; fi
## If we're testing rust builds in offline-mode, then set up our vendored dependencies
- - if [[ "$RUST_OPTIONS" == "--enable-rust" ]]; then git submodule init ; fi
- - if [[ "$RUST_OPTIONS" == "--enable-rust" ]]; then git submodule update; fi
- if [[ "$TOR_RUST_DEPENDENCIES" == "true" ]]; then export TOR_RUST_DEPENDENCIES=$PWD/src/ext/rust/crates; fi
script:
diff --git a/changes/bug25843 b/changes/bug25843
new file mode 100644
index 0000000000..ddbbbef787
--- /dev/null
+++ b/changes/bug25843
@@ -0,0 +1,3 @@
+ o Minor feature (entry guards):
+ - Introduce torrc option NumPrimaryGuards for controlling the number of
+ primary guards. Closes ticket 25843. \ No newline at end of file
diff --git a/changes/feature19429 b/changes/feature19429
new file mode 100644
index 0000000000..0faa6e84e1
--- /dev/null
+++ b/changes/feature19429
@@ -0,0 +1,5 @@
+ o Minor features (compatibility):
+ - Tor now detects versions of OpenSSL 1.1.0 and later compiled with the
+ no-deprecated option, and builds correctly with them. Closes
+ tickets 19429, 19981, and 25353.
+
diff --git a/changes/ticket23354 b/changes/ticket23354
new file mode 100644
index 0000000000..f79dfd96ae
--- /dev/null
+++ b/changes/ticket23354
@@ -0,0 +1,6 @@
+ o Minor features (configuration):
+ - The "DownloadSchedule" options have been renamed to end with
+ "DownloadInitialDelay". The old names are still allowed, but will
+ produce a warning. Comma-separated lists are still permitted for
+ these options, but all values after the first are ignored (as they have
+ been since 0.2.9). Closes ticket 23354.
diff --git a/changes/ticket25376_25762 b/changes/ticket25376_25762
new file mode 100644
index 0000000000..b3ebf56d3b
--- /dev/null
+++ b/changes/ticket25376_25762
@@ -0,0 +1,10 @@
+ o Major feature (main loop, CPU usage):
+ - Previously, tor would enable at startup all possible main loop event
+ regardless if it needed them. For instance, directory authorities
+ callbacks were fired up even for client only. We have now refactored this
+ whole interface to only enable the appropriate callbacks depending on what
+ are tor roles (client only, relay, hidden service, etc.). Furthermore,
+ these events now depend on DisableNetwork or the hibernation state in
+ order to enable them. This is a big step towards reducing client CPU usage
+ by reducing the amount of wake ups the daemon does. Closes ticket 25376
+ and 25762.
diff --git a/changes/ticket25931 b/changes/ticket25931
new file mode 100644
index 0000000000..20ce761883
--- /dev/null
+++ b/changes/ticket25931
@@ -0,0 +1,9 @@
+ o Minor features (mainloop):
+ - Move responsibility for
+ rescanning the consensus cache
+ from a once-per-second callback to a callback that is only scheduled as
+ needed. Once enough items are removed from our once-per-second
+ callback, we can eliminate it entirely to conserve CPU when idle.
+ Closes ticket:
+ 25931.
+
diff --git a/changes/ticket25932 b/changes/ticket25932
new file mode 100644
index 0000000000..67f56f7cc0
--- /dev/null
+++ b/changes/ticket25932
@@ -0,0 +1,9 @@
+ o Minor features (mainloop):
+ - Move responsibility for
+ closing connections, circuits, and channels
+ from a once-per-second callback to a callback that is only scheduled as
+ needed. Once enough items are removed from our once-per-second
+ callback, we can eliminate it entirely to conserve CPU when idle.
+ Closes ticket
+ 25932.
+
diff --git a/configure.ac b/configure.ac
index 878f5a88bb..aa2617b70a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -788,9 +788,18 @@ AC_ARG_WITH(ssl-dir,
AC_MSG_NOTICE([Now, we'll look for OpenSSL >= 1.0.1])
TOR_SEARCH_LIBRARY(openssl, $tryssldir, [-lssl -lcrypto $TOR_LIB_GDI $TOR_LIB_WS32],
- [#include <openssl/ssl.h>],
- [struct ssl_method_st; const struct ssl_method_st *TLSv1_1_method(void);],
- [TLSv1_1_method();], [],
+ [#include <openssl/ssl.h>
+ char *getenv(const char *);],
+ [struct ssl_cipher_st;
+ unsigned SSL_CIPHER_get_id(const struct ssl_cipher_st *);
+ char *getenv(const char *);],
+ dnl This funny-looking test program calls getenv, so that the compiler
+ dnl will neither make code that call SSL_CIPHER_get_id(NULL) [producing
+ dnl a crash], nor optimize out the call to SSL_CIPHER_get_id().
+ dnl We look for SSL_cipher_get_id() because it is present in
+ dnl OpenSSL >=1.0.1, because it is not deprecated, and because Tor
+ dnl depends on it.
+ [if (getenv("THIS_SHOULDNT_BE_SET_X201803")) SSL_CIPHER_get_id((void *)0);], [],
[/usr/local/opt/openssl /usr/local/openssl /usr/lib/openssl /usr/local/ssl /usr/lib/ssl /usr/local /opt/openssl])
dnl XXXX check for OPENSSL_VERSION_NUMBER == SSLeay()
diff --git a/doc/tor.1.txt b/doc/tor.1.txt
index cf666e9142..9471db9362 100644
--- a/doc/tor.1.txt
+++ b/doc/tor.1.txt
@@ -1347,6 +1347,13 @@ The following options are useful only for clients (that is, if
number from the guard-n-primary-guards-to-use consensus parameter, and
default to 1 if the consensus parameter isn't set. (Default: 0)
+[[NumPrimaryGuards]] **NumPrimaryGuards** __NUM__::
+ If UseEntryGuards is set to 1, we will try to pick NUM routers for our
+ primary guard list, which is the set of routers we strongly prefer when
+ connecting to the Tor network. If NUM is 0, we try to learn the number from
+ the guard-n-primary-guards consensus parameter, and default to 3 if the
+ consensus parameter isn't set. (Default: 0)
+
[[NumDirectoryGuards]] **NumDirectoryGuards** __NUM__::
If UseEntryGuards is set to 1, we try to make sure we have at least NUM
routers to use as directory guards. If this option is set to 0, use the
@@ -1735,32 +1742,29 @@ The following options are useful only for clients (that is, if
directory authorities do not choose a value, Tor will default to 0.6.
(Default: -1)
-[[ClientBootstrapConsensusAuthorityDownloadSchedule]] **ClientBootstrapConsensusAuthorityDownloadSchedule** __N__,__N__,__...__::
- Schedule for when clients should download consensuses from authorities
+[[ClientBootstrapConsensusAuthorityDownloadInitialDelay]] **ClientBootstrapConsensusAuthorityDownloadInitialDelay** __N__::
+ Initial delay in seconds for when clients should download consensuses from authorities
if they are bootstrapping (that is, they don't have a usable, reasonably
live consensus). Only used by clients fetching from a list of fallback
directory mirrors. This schedule is advanced by (potentially concurrent)
connection attempts, unlike other schedules, which are advanced by
- connection failures. (Default: 6, 11, 3600, 10800, 25200, 54000, 111600,
- 262800)
+ connection failures. (Default: 6)
-[[ClientBootstrapConsensusFallbackDownloadSchedule]] **ClientBootstrapConsensusFallbackDownloadSchedule** __N__,__N__,__...__::
- Schedule for when clients should download consensuses from fallback
+[[ClientBootstrapConsensusFallbackDownloadInitialDelay]] **ClientBootstrapConsensusFallbackDownloadInitialDelay** __N__::
+ Initial delay in seconds for when clients should download consensuses from fallback
directory mirrors if they are bootstrapping (that is, they don't have a
usable, reasonably live consensus). Only used by clients fetching from a
list of fallback directory mirrors. This schedule is advanced by
(potentially concurrent) connection attempts, unlike other schedules,
- which are advanced by connection failures. (Default: 0, 1, 4, 11, 3600,
- 10800, 25200, 54000, 111600, 262800)
+ which are advanced by connection failures. (Default: 0)
-[[ClientBootstrapConsensusAuthorityOnlyDownloadSchedule]] **ClientBootstrapConsensusAuthorityOnlyDownloadSchedule** __N__,__N__,__...__::
- Schedule for when clients should download consensuses from authorities
+[[ClientBootstrapConsensusAuthorityOnlyDownloadInitialDelay]] **ClientBootstrapConsensusAuthorityOnlyDownloadInitialDelay** __N__::
+ Initial delay in seconds for when clients should download consensuses from authorities
if they are bootstrapping (that is, they don't have a usable, reasonably
live consensus). Only used by clients which don't have or won't fetch
from a list of fallback directory mirrors. This schedule is advanced by
(potentially concurrent) connection attempts, unlike other schedules,
- which are advanced by connection failures. (Default: 0, 3, 7, 3600,
- 10800, 25200, 54000, 111600, 262800)
+ which are advanced by connection failures. (Default: 0)
[[ClientBootstrapConsensusMaxInProgressTries]] **ClientBootstrapConsensusMaxInProgressTries** __NUM__::
Try this many simultaneous connections to download a consensus before
@@ -2891,12 +2895,9 @@ The following options are used for running a testing Tor network.
AssumeReachable 1
AuthDirMaxServersPerAddr 0
AuthDirMaxServersPerAuthAddr 0
- ClientBootstrapConsensusAuthorityDownloadSchedule 0, 2,
- 4 (for 40 seconds), 8, 16, 32, 60
- ClientBootstrapConsensusFallbackDownloadSchedule 0, 1,
- 4 (for 40 seconds), 8, 16, 32, 60
- ClientBootstrapConsensusAuthorityOnlyDownloadSchedule 0, 1,
- 4 (for 40 seconds), 8, 16, 32, 60
+ ClientBootstrapConsensusAuthorityDownloadInitialDelay 0
+ ClientBootstrapConsensusFallbackDownloadInitialDelay 0
+ ClientBootstrapConsensusAuthorityOnlyDownloadInitialDelay 0
ClientDNSRejectInternalAddresses 0
ClientRejectInternalAddresses 0
CountPrivateBandwidth 1
@@ -2911,12 +2912,12 @@ The following options are used for running a testing Tor network.
TestingV3AuthInitialDistDelay 20 seconds
TestingAuthDirTimeToLearnReachability 0 minutes
TestingEstimatedDescriptorPropagationTime 0 minutes
- TestingServerDownloadSchedule 0, 0, 0, 5, 10, 15, 20, 30, 60
- TestingClientDownloadSchedule 0, 0, 5, 10, 15, 20, 30, 60
- TestingServerConsensusDownloadSchedule 0, 0, 5, 10, 15, 20, 30, 60
- TestingClientConsensusDownloadSchedule 0, 0, 5, 10, 15, 20, 30, 60
- TestingBridgeDownloadSchedule 10, 30, 60
- TestingBridgeBootstrapDownloadSchedule 0, 0, 5, 10, 15, 20, 30, 60
+ TestingServerDownloadInitialDelay 0
+ TestingClientDownloadInitialDelay 0
+ TestingServerConsensusDownloadInitialDelay 0
+ TestingClientConsensusDownloadInitialDelay 0
+ TestingBridgeDownloadInitialDelay 10
+ TestingBridgeBootstrapDownloadInitialDelay 0
TestingClientMaxIntervalWithoutRequest 5 seconds
TestingDirConnectionMaxStall 30 seconds
TestingEnableConnBwEvent 1
@@ -2955,37 +2956,31 @@ The following options are used for running a testing Tor network.
Minimum value for the Fast flag. Overrides the ordinary minimum taken
from the consensus when TestingTorNetwork is set. (Default: 0.)
-[[TestingServerDownloadSchedule]] **TestingServerDownloadSchedule** __N__,__N__,__...__::
- Schedule for when servers should download things in general. Changing this
- requires that **TestingTorNetwork** is set. (Default: 0, 0, 0, 60, 60, 120,
- 300, 900, 2147483647)
+[[TestingServerDownloadInitialDelay]] **TestingServerDownloadInitialDelay** __N__::
+ Initial delay in seconds for when servers should download things in general. Changing this
+ requires that **TestingTorNetwork** is set. (Default: 0)
-[[TestingClientDownloadSchedule]] **TestingClientDownloadSchedule** __N__,__N__,__...__::
- Schedule for when clients should download things in general. Changing this
- requires that **TestingTorNetwork** is set. (Default: 0, 0, 60, 300, 600,
- 2147483647)
+[[TestingClientDownloadInitialDelay]] **TestingClientDownloadInitialDelay** __N__::
+ Initial delay in seconds for when clients should download things in general. Changing this
+ requires that **TestingTorNetwork** is set. (Default: 0)
-[[TestingServerConsensusDownloadSchedule]] **TestingServerConsensusDownloadSchedule** __N__,__N__,__...__::
- Schedule for when servers should download consensuses. Changing this
- requires that **TestingTorNetwork** is set. (Default: 0, 0, 60, 300, 600,
- 1800, 1800, 1800, 1800, 1800, 3600, 7200)
+[[TestingServerConsensusDownloadInitialDelay]] **TestingServerConsensusDownloadInitialDelay** __N__::
+ Initial delay in seconds for when servers should download consensuses. Changing this
+ requires that **TestingTorNetwork** is set. (Default: 0)
-[[TestingClientConsensusDownloadSchedule]] **TestingClientConsensusDownloadSchedule** __N__,__N__,__...__::
- Schedule for when clients should download consensuses. Changing this
- requires that **TestingTorNetwork** is set. (Default: 0, 0, 60, 300, 600,
- 1800, 3600, 3600, 3600, 10800, 21600, 43200)
+[[TestingClientConsensusDownloadInitialDelay]] **TestingClientConsensusDownloadInitialDelay** __N__::
+ Initial delay in seconds for when clients should download consensuses. Changing this
+ requires that **TestingTorNetwork** is set. (Default: 0)
-[[TestingBridgeDownloadSchedule]] **TestingBridgeDownloadSchedule** __N__,__N__,__...__::
- Schedule for when clients should download each bridge descriptor when they
+[[TestingBridgeDownloadInitialDelay]] **TestingBridgeDownloadInitialDelay** __N__::
+ Initial delay in seconds for when clients should download each bridge descriptor when they
know that one or more of their configured bridges are running. Changing
- this requires that **TestingTorNetwork** is set. (Default: 10800, 25200,
- 54000, 111600, 262800)
+ this requires that **TestingTorNetwork** is set. (Default: 10800)
-[[TestingBridgeBootstrapDownloadSchedule]] **TestingBridgeBootstrapDownloadSchedule** __N__,__N__,__...__::
- Schedule for when clients should download each bridge descriptor when they
+[[TestingBridgeBootstrapDownloadInitialDelay]] **TestingBridgeBootstrapDownloadInitialDelay** __N__::
+ Initial delay in seconds for when clients should download each bridge descriptor when they
have just started, or when they can not contact any of their bridges.
- Changing this requires that **TestingTorNetwork** is set. (Default: 0, 30,
- 90, 600, 3600, 10800, 25200, 54000, 111600, 262800)
+ Changing this requires that **TestingTorNetwork** is set. (Default: 0)
[[TestingClientMaxIntervalWithoutRequest]] **TestingClientMaxIntervalWithoutRequest** __N__ **seconds**|**minutes**::
When directory clients have only a few descriptors to request, they batch
diff --git a/src/common/aes.c b/src/common/aes.c
index 5d0841dfa3..95737cffcc 100644
--- a/src/common/aes.c
+++ b/src/common/aes.c
@@ -116,7 +116,11 @@ aes_cipher_free_(aes_cnt_cipher_t *cipher_)
if (!cipher_)
return;
EVP_CIPHER_CTX *cipher = (EVP_CIPHER_CTX *) cipher_;
+#if OPENSSL_VERSION_NUMBER >= OPENSSL_V_SERIES(1,1,0)
+ EVP_CIPHER_CTX_reset(cipher);
+#else
EVP_CIPHER_CTX_cleanup(cipher);
+#endif
EVP_CIPHER_CTX_free(cipher);
}
void
diff --git a/src/common/crypto.c b/src/common/crypto.c
index 9fcd17742c..c98a968757 100644
--- a/src/common/crypto.c
+++ b/src/common/crypto.c
@@ -43,6 +43,7 @@ DISABLE_GCC_WARNING(redundant-decls)
#include <openssl/dh.h>
#include <openssl/conf.h>
#include <openssl/hmac.h>
+#include <openssl/ssl.h>
ENABLE_GCC_WARNING(redundant-decls)
@@ -204,8 +205,15 @@ crypto_early_init(void)
crypto_early_initialized_ = 1;
+#if OPENSSL_VERSION_NUMBER >= OPENSSL_V_SERIES(1,1,0)
+ OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS |
+ OPENSSL_INIT_LOAD_CRYPTO_STRINGS |
+ OPENSSL_INIT_ADD_ALL_CIPHERS |
+ OPENSSL_INIT_ADD_ALL_DIGESTS, NULL);
+#else
ERR_load_crypto_strings();
OpenSSL_add_all_algorithms();
+#endif
setup_openssl_threading();
@@ -1660,11 +1668,15 @@ memwipe(void *mem, uint8_t byte, size_t sz)
int
crypto_global_cleanup(void)
{
+#if OPENSSL_VERSION_NUMBER < OPENSSL_V_SERIES(1,1,0)
EVP_cleanup();
+#endif
#ifndef NEW_THREAD_API
ERR_remove_thread_state(NULL);
#endif
+#if OPENSSL_VERSION_NUMBER < OPENSSL_V_SERIES(1,1,0)
ERR_free_strings();
+#endif
if (dh_param_p)
BN_clear_free(dh_param_p);
@@ -1676,11 +1688,15 @@ crypto_global_cleanup(void)
dh_param_p = dh_param_p_tls = dh_param_g = NULL;
#ifndef DISABLE_ENGINES
+#if OPENSSL_VERSION_NUMBER < OPENSSL_V_SERIES(1,1,0)
ENGINE_cleanup();
#endif
+#endif
CONF_modules_unload(1);
+#if OPENSSL_VERSION_NUMBER < OPENSSL_V_SERIES(1,1,0)
CRYPTO_cleanup_all_ex_data();
+#endif
crypto_openssl_free_all();
diff --git a/src/common/torint.h b/src/common/torint.h
index 0b8061d24f..fc7818fe2c 100644
--- a/src/common/torint.h
+++ b/src/common/torint.h
@@ -40,6 +40,8 @@
#include <inttypes.h>
#endif
+#include <stdbool.h>
+
#if (SIZEOF_INT8_T != 0)
#define HAVE_INT8_T
#endif
diff --git a/src/common/tortls.c b/src/common/tortls.c
index 05e29e22ff..cd236363f8 100644
--- a/src/common/tortls.c
+++ b/src/common/tortls.c
@@ -56,10 +56,25 @@ ENABLE_GCC_WARNING(redundant-decls)
#include "container.h"
#include <string.h>
+#if OPENSSL_VERSION_NUMBER >= OPENSSL_V_SERIES(1,1,0)
+#define X509_get_notBefore_const(cert) \
+ X509_get0_notBefore(cert)
+#define X509_get_notAfter_const(cert) \
+ X509_get0_notAfter(cert)
+#ifndef X509_get_notBefore
+#define X509_get_notBefore(cert) \
+ X509_getm_notBefore(cert)
+#endif
+#ifndef X509_get_notAfter
+#define X509_get_notAfter(cert) \
+ X509_getm_notAfter(cert)
+#endif
+#else /* ! OPENSSL_VERSION_NUMBER >= OPENSSL_V_SERIES(1,1,0) */
#define X509_get_notBefore_const(cert) \
((const ASN1_TIME*) X509_get_notBefore((X509 *)cert))
#define X509_get_notAfter_const(cert) \
((const ASN1_TIME*) X509_get_notAfter((X509 *)cert))
+#endif
/* Copied from or.h */
#define LEGAL_NICKNAME_CHARACTERS \
@@ -355,8 +370,12 @@ tor_tls_init(void)
check_no_tls_errors();
if (!tls_library_is_initialized) {
+#if OPENSSL_VERSION_NUMBER >= OPENSSL_V_SERIES(1,1,0)
+ OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS, NULL);
+#else
SSL_library_init();
SSL_load_error_strings();
+#endif
#if (SIZEOF_VOID_P >= 8 && \
OPENSSL_VERSION_NUMBER >= OPENSSL_V_SERIES(1,0,1))
diff --git a/src/or/channel.c b/src/or/channel.c
index 68245db497..c30e508018 100644
--- a/src/or/channel.c
+++ b/src/or/channel.c
@@ -69,6 +69,7 @@
#include "circuitmux.h"
#include "entrynodes.h"
#include "geoip.h"
+#include "main.h"
#include "nodelist.h"
#include "relay.h"
#include "rephist.h"
@@ -404,6 +405,7 @@ channel_register(channel_t *chan)
/* Put it in the finished list, creating it if necessary */
if (!finished_channels) finished_channels = smartlist_new();
smartlist_add(finished_channels, chan);
+ mainloop_schedule_postloop_cleanup();
} else {
/* Put it in the active list, creating it if necessary */
if (!active_channels) active_channels = smartlist_new();
@@ -1548,6 +1550,7 @@ channel_change_state_(channel_t *chan, channel_state_t to_state)
if (active_channels) smartlist_remove(active_channels, chan);
if (!finished_channels) finished_channels = smartlist_new();
smartlist_add(finished_channels, chan);
+ mainloop_schedule_postloop_cleanup();
}
/* Need to put on active list? */
else if (!was_active && is_active) {
@@ -1666,6 +1669,7 @@ channel_listener_change_state(channel_listener_t *chan_l,
if (active_listeners) smartlist_remove(active_listeners, chan_l);
if (!finished_listeners) finished_listeners = smartlist_new();
smartlist_add(finished_listeners, chan_l);
+ mainloop_schedule_postloop_cleanup();
}
/* Need to put on active list? */
else if (!was_active && is_active) {
diff --git a/src/or/circuitlist.c b/src/or/circuitlist.c
index 9a82713cbe..ea2f2c15c5 100644
--- a/src/or/circuitlist.c
+++ b/src/or/circuitlist.c
@@ -2067,6 +2067,7 @@ circuit_mark_for_close_, (circuit_t *circ, int reason, int line,
circuits_pending_close = smartlist_new();
smartlist_add(circuits_pending_close, circ);
+ mainloop_schedule_postloop_cleanup();
log_info(LD_GENERAL, "Circuit %u (id: %" PRIu32 ") marked for close at "
"%s:%d (orig reason: %d, new reason: %d)",
diff --git a/src/or/config.c b/src/or/config.c
index 87a3588db7..54f3930fc5 100644
--- a/src/or/config.c
+++ b/src/or/config.c
@@ -126,6 +126,11 @@ static const char unix_socket_prefix[] = "unix:";
* configuration. */
static const char unix_q_socket_prefix[] = "unix:\"";
+/** macro to help with the bulk rename of *DownloadSchedule to
+ * *DowloadInitialDelay . */
+#define DOWNLOAD_SCHEDULE(name) \
+ { #name "DownloadSchedule", #name "DownloadInitialDelay", 0, 1 }
+
/** A list of abbreviations and aliases to map command-line options, obsolete
* option names, or alternative option names, to their current values. */
static config_abbrev_t option_abbrevs_[] = {
@@ -175,6 +180,16 @@ static config_abbrev_t option_abbrevs_[] = {
{ "_HSLayer2Nodes", "HSLayer2Nodes", 0, 1 },
{ "_HSLayer3Nodes", "HSLayer3Nodes", 0, 1 },
+ DOWNLOAD_SCHEDULE(ClientBootstrapConsensusAuthority),
+ DOWNLOAD_SCHEDULE(ClientBootstrapConsensusAuthorityOnly),
+ DOWNLOAD_SCHEDULE(ClientBootstrapConsensusFallback),
+ DOWNLOAD_SCHEDULE(TestingBridge),
+ DOWNLOAD_SCHEDULE(TestingBridgeBootstrap),
+ DOWNLOAD_SCHEDULE(TestingClient),
+ DOWNLOAD_SCHEDULE(TestingClientConsensus),
+ DOWNLOAD_SCHEDULE(TestingServer),
+ DOWNLOAD_SCHEDULE(TestingServerConsensus),
+
{ NULL, NULL, 0, 0},
};
@@ -457,6 +472,7 @@ static config_var_t option_vars_[] = {
V(NumCPUs, UINT, "0"),
V(NumDirectoryGuards, UINT, "0"),
V(NumEntryGuards, UINT, "0"),
+ V(NumPrimaryGuards, UINT, "0"),
V(OfflineMasterKey, BOOL, "0"),
OBSOLETE("ORListenAddress"),
VPORT(ORPort),
@@ -599,16 +615,10 @@ static config_var_t option_vars_[] = {
VAR("__OwningControllerProcess",STRING,OwningControllerProcess, NULL),
VAR("__OwningControllerFD",INT,OwningControllerFD, "-1"),
V(MinUptimeHidServDirectoryV2, INTERVAL, "96 hours"),
- V(TestingServerDownloadSchedule, CSV_INTERVAL, "0, 0, 0, 60, 60, 120, "
- "300, 900, 2147483647"),
- V(TestingClientDownloadSchedule, CSV_INTERVAL, "0, 0, 60, 300, 600, "
- "2147483647"),
- V(TestingServerConsensusDownloadSchedule, CSV_INTERVAL, "0, 0, 60, "
- "300, 600, 1800, 1800, 1800, 1800, "
- "1800, 3600, 7200"),
- V(TestingClientConsensusDownloadSchedule, CSV_INTERVAL, "0, 0, 60, "
- "300, 600, 1800, 3600, 3600, 3600, "
- "10800, 21600, 43200"),
+ V(TestingServerDownloadInitialDelay, CSV_INTERVAL, "0"),
+ V(TestingClientDownloadInitialDelay, CSV_INTERVAL, "0"),
+ V(TestingServerConsensusDownloadInitialDelay, CSV_INTERVAL, "0"),
+ V(TestingClientConsensusDownloadInitialDelay, CSV_INTERVAL, "0"),
/* With the ClientBootstrapConsensus*Download* below:
* Clients with only authorities will try:
* - at least 3 authorities over 10 seconds, then exponentially backoff,
@@ -624,13 +634,11 @@ static config_var_t option_vars_[] = {
*
* When clients have authorities and fallbacks available, they use these
* schedules: (we stagger the times to avoid thundering herds) */
- V(ClientBootstrapConsensusAuthorityDownloadSchedule, CSV_INTERVAL,
- "6, 11, 3600, 10800, 25200, 54000, 111600, 262800" /* 3 days + 1 hour */),
- V(ClientBootstrapConsensusFallbackDownloadSchedule, CSV_INTERVAL,
- "0, 1, 4, 11, 3600, 10800, 25200, 54000, 111600, 262800"),
+ V(ClientBootstrapConsensusAuthorityDownloadInitialDelay, CSV_INTERVAL, "6"),
+ V(ClientBootstrapConsensusFallbackDownloadInitialDelay, CSV_INTERVAL, "0"),
/* When clients only have authorities available, they use this schedule: */
- V(ClientBootstrapConsensusAuthorityOnlyDownloadSchedule, CSV_INTERVAL,
- "0, 3, 7, 3600, 10800, 25200, 54000, 111600, 262800"),
+ V(ClientBootstrapConsensusAuthorityOnlyDownloadInitialDelay, CSV_INTERVAL,
+ "0"),
/* We don't want to overwhelm slow networks (or mirrors whose replies are
* blocked), but we also don't want to fail if only some mirrors are
* blackholed. Clients will try 3 directories simultaneously.
@@ -638,14 +646,12 @@ static config_var_t option_vars_[] = {
V(ClientBootstrapConsensusMaxInProgressTries, UINT, "3"),
/* When a client has any running bridges, check each bridge occasionally,
* whether or not that bridge is actually up. */
- V(TestingBridgeDownloadSchedule, CSV_INTERVAL,
- "10800, 25200, 54000, 111600, 262800"),
+ V(TestingBridgeDownloadInitialDelay, CSV_INTERVAL,"10800"),
/* When a client is just starting, or has no running bridges, check each
* bridge a few times quickly, and then try again later. These schedules
* are much longer than the other schedules, because we try each and every
* configured bridge with this schedule. */
- V(TestingBridgeBootstrapDownloadSchedule, CSV_INTERVAL,
- "0, 30, 90, 600, 3600, 10800, 25200, 54000, 111600, 262800"),
+ V(TestingBridgeBootstrapDownloadInitialDelay, CSV_INTERVAL, "0"),
V(TestingClientMaxIntervalWithoutRequest, INTERVAL, "10 minutes"),
V(TestingDirConnectionMaxStall, INTERVAL, "5 minutes"),
OBSOLETE("TestingConsensusMaxDownloadTries"),
@@ -672,12 +678,10 @@ static const config_var_t testing_tor_network_defaults[] = {
V(EnforceDistinctSubnets, BOOL, "0"),
V(AssumeReachable, BOOL, "1"),
V(AuthDirMaxServersPerAddr, UINT, "0"),
- V(ClientBootstrapConsensusAuthorityDownloadSchedule, CSV_INTERVAL,
- "0, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 16, 32, 60"),
- V(ClientBootstrapConsensusFallbackDownloadSchedule, CSV_INTERVAL,
- "0, 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 16, 32, 60"),
- V(ClientBootstrapConsensusAuthorityOnlyDownloadSchedule, CSV_INTERVAL,
- "0, 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 16, 32, 60"),
+ V(ClientBootstrapConsensusAuthorityDownloadInitialDelay, CSV_INTERVAL, "0"),
+ V(ClientBootstrapConsensusFallbackDownloadInitialDelay, CSV_INTERVAL, "0"),
+ V(ClientBootstrapConsensusAuthorityOnlyDownloadInitialDelay, CSV_INTERVAL,
+ "0"),
V(ClientDNSRejectInternalAddresses, BOOL,"0"),
V(ClientRejectInternalAddresses, BOOL, "0"),
V(CountPrivateBandwidth, BOOL, "1"),
@@ -692,17 +696,12 @@ static const config_var_t testing_tor_network_defaults[] = {
V(TestingAuthDirTimeToLearnReachability, INTERVAL, "0 minutes"),
V(TestingEstimatedDescriptorPropagationTime, INTERVAL, "0 minutes"),
V(MinUptimeHidServDirectoryV2, INTERVAL, "0 minutes"),
- V(TestingServerDownloadSchedule, CSV_INTERVAL, "0, 0, 0, 5, 10, 15, "
- "20, 30, 60"),
- V(TestingClientDownloadSchedule, CSV_INTERVAL, "0, 0, 5, 10, 15, 20, "
- "30, 60"),
- V(TestingServerConsensusDownloadSchedule, CSV_INTERVAL, "0, 0, 5, 10, "
- "15, 20, 30, 60"),
- V(TestingClientConsensusDownloadSchedule, CSV_INTERVAL, "0, 0, 5, 10, "
- "15, 20, 30, 60"),
- V(TestingBridgeDownloadSchedule, CSV_INTERVAL, "10, 30, 60"),
- V(TestingBridgeBootstrapDownloadSchedule, CSV_INTERVAL, "0, 0, 5, 10, "
- "15, 20, 30, 60"),
+ V(TestingServerDownloadInitialDelay, CSV_INTERVAL, "0"),
+ V(TestingClientDownloadInitialDelay, CSV_INTERVAL, "0"),
+ V(TestingServerConsensusDownloadInitialDelay, CSV_INTERVAL, "0"),
+ V(TestingClientConsensusDownloadInitialDelay, CSV_INTERVAL, "0"),
+ V(TestingBridgeDownloadInitialDelay, CSV_INTERVAL, "10"),
+ V(TestingBridgeBootstrapDownloadInitialDelay, CSV_INTERVAL, "0"),
V(TestingClientMaxIntervalWithoutRequest, INTERVAL, "5 seconds"),
V(TestingDirConnectionMaxStall, INTERVAL, "30 seconds"),
V(TestingEnableConnBwEvent, BOOL, "1"),
@@ -3775,6 +3774,11 @@ options_validate(or_options_t *old_options, or_options_t *options,
"http://freehaven.net/anonbib/#hs-attack06 for details.");
}
+ if (options->NumPrimaryGuards && options->NumEntryGuards &&
+ options->NumEntryGuards > options->NumPrimaryGuards) {
+ REJECT("NumEntryGuards must not be greater than NumPrimaryGuards.");
+ }
+
if (options->EntryNodes &&
routerset_is_list(options->EntryNodes) &&
(routerset_len(options->EntryNodes) == 1) &&
@@ -4373,12 +4377,12 @@ options_validate(or_options_t *old_options, or_options_t *options,
CHECK_DEFAULT(TestingV3AuthVotingStartOffset);
CHECK_DEFAULT(TestingAuthDirTimeToLearnReachability);
CHECK_DEFAULT(TestingEstimatedDescriptorPropagationTime);
- CHECK_DEFAULT(TestingServerDownloadSchedule);
- CHECK_DEFAULT(TestingClientDownloadSchedule);
- CHECK_DEFAULT(TestingServerConsensusDownloadSchedule);
- CHECK_DEFAULT(TestingClientConsensusDownloadSchedule);
- CHECK_DEFAULT(TestingBridgeDownloadSchedule);
- CHECK_DEFAULT(TestingBridgeBootstrapDownloadSchedule);
+ CHECK_DEFAULT(TestingServerDownloadInitialDelay);
+ CHECK_DEFAULT(TestingClientDownloadInitialDelay);
+ CHECK_DEFAULT(TestingServerConsensusDownloadInitialDelay);
+ CHECK_DEFAULT(TestingClientConsensusDownloadInitialDelay);
+ CHECK_DEFAULT(TestingBridgeDownloadInitialDelay);
+ CHECK_DEFAULT(TestingBridgeBootstrapDownloadInitialDelay);
CHECK_DEFAULT(TestingClientMaxIntervalWithoutRequest);
CHECK_DEFAULT(TestingDirConnectionMaxStall);
CHECK_DEFAULT(TestingAuthKeyLifetime);
@@ -8101,7 +8105,10 @@ getinfo_helper_config(control_connection_t *conn,
case CONFIG_TYPE_ISOTIME: type = "Time"; break;
case CONFIG_TYPE_ROUTERSET: type = "RouterList"; break;
case CONFIG_TYPE_CSV: type = "CommaList"; break;
- case CONFIG_TYPE_CSV_INTERVAL: type = "TimeIntervalCommaList"; break;
+ /* This type accepts more inputs than TimeInterval, but it ignores
+ * everything after the first entry, so we may as well pretend
+ * it's a TimeInterval. */
+ case CONFIG_TYPE_CSV_INTERVAL: type = "TimeInterval"; break;
case CONFIG_TYPE_LINELIST: type = "LineList"; break;
case CONFIG_TYPE_LINELIST_S: type = "Dependent"; break;
case CONFIG_TYPE_LINELIST_V: type = "Virtual"; break;
diff --git a/src/or/confparse.c b/src/or/confparse.c
index 64ed9ee6bb..6bab790945 100644
--- a/src/or/confparse.c
+++ b/src/or/confparse.c
@@ -162,8 +162,6 @@ config_assign_value(const config_format_t *fmt, void *options,
int i, ok;
const config_var_t *var;
void *lvalue;
- int *csv_int;
- smartlist_t *csv_str;
CONFIG_CHECK(fmt, options);
@@ -195,6 +193,30 @@ config_assign_value(const config_format_t *fmt, void *options,
*(int *)lvalue = i;
break;
+ case CONFIG_TYPE_CSV_INTERVAL: {
+ /* We used to have entire smartlists here. But now that all of our
+ * download schedules use exponential backoff, only the first part
+ * matters. */
+ const char *comma = strchr(c->value, ',');
+ const char *val = c->value;
+ char *tmp = NULL;
+ if (comma) {
+ tmp = tor_strndup(c->value, comma - c->value);
+ val = tmp;
+ }
+
+ i = config_parse_interval(val, &ok);
+ if (!ok) {
+ tor_asprintf(msg,
+ "Interval '%s %s' is malformed or out of bounds.",
+ c->key, c->value);
+ return -1;
+ }
+ *(int *)lvalue = i;
+ tor_free(tmp);
+ break;
+ }
+
case CONFIG_TYPE_INTERVAL: {
i = config_parse_interval(c->value, &ok);
if (!ok) {
@@ -298,36 +320,6 @@ config_assign_value(const config_format_t *fmt, void *options,
SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
break;
- case CONFIG_TYPE_CSV_INTERVAL:
- if (*(smartlist_t**)lvalue) {
- SMARTLIST_FOREACH(*(smartlist_t**)lvalue, int *, cp, tor_free(cp));
- smartlist_clear(*(smartlist_t**)lvalue);
- } else {
- *(smartlist_t**)lvalue = smartlist_new();
- }
- csv_str = smartlist_new();
- smartlist_split_string(csv_str, c->value, ",",
- SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
- SMARTLIST_FOREACH_BEGIN(csv_str, char *, str)
- {
- i = config_parse_interval(str, &ok);
- if (!ok) {
- tor_asprintf(msg,
- "Interval in '%s %s' is malformed or out of bounds.",
- c->key, c->value);
- SMARTLIST_FOREACH(csv_str, char *, cp, tor_free(cp));
- smartlist_free(csv_str);
- return -1;
- }
- csv_int = tor_malloc_zero(sizeof(int));
- *csv_int = i;
- smartlist_add(*(smartlist_t**)lvalue, csv_int);
- }
- SMARTLIST_FOREACH_END(str);
- SMARTLIST_FOREACH(csv_str, char *, cp, tor_free(cp));
- smartlist_free(csv_str);
- break;
-
case CONFIG_TYPE_LINELIST:
case CONFIG_TYPE_LINELIST_S:
{
@@ -528,7 +520,6 @@ config_get_assigned_option(const config_format_t *fmt, const void *options,
const config_var_t *var;
const void *value;
config_line_t *result;
- smartlist_t *csv_str;
tor_assert(options && key);
CONFIG_CHECK(fmt, options);
@@ -571,6 +562,7 @@ config_get_assigned_option(const config_format_t *fmt, const void *options,
break;
}
/* fall through */
+ case CONFIG_TYPE_CSV_INTERVAL:
case CONFIG_TYPE_INTERVAL:
case CONFIG_TYPE_MSEC_INTERVAL:
case CONFIG_TYPE_UINT:
@@ -611,20 +603,6 @@ config_get_assigned_option(const config_format_t *fmt, const void *options,
else
result->value = tor_strdup("");
break;
- case CONFIG_TYPE_CSV_INTERVAL:
- if (*(smartlist_t**)value) {
- csv_str = smartlist_new();
- SMARTLIST_FOREACH_BEGIN(*(smartlist_t**)value, int *, i)
- {
- smartlist_add_asprintf(csv_str, "%d", *i);
- }
- SMARTLIST_FOREACH_END(i);
- result->value = smartlist_join_strings(csv_str, ",", 0, NULL);
- SMARTLIST_FOREACH(csv_str, char *, cp, tor_free(cp));
- smartlist_free(csv_str);
- } else
- result->value = tor_strdup("");
- break;
case CONFIG_TYPE_OBSOLETE:
log_fn(LOG_INFO, LD_CONFIG,
"You asked me for the value of an obsolete config option '%s'.",
@@ -789,6 +767,7 @@ config_clear(const config_format_t *fmt, void *options,
case CONFIG_TYPE_ISOTIME:
*(time_t*)lvalue = 0;
break;
+ case CONFIG_TYPE_CSV_INTERVAL:
case CONFIG_TYPE_INTERVAL:
case CONFIG_TYPE_MSEC_INTERVAL:
case CONFIG_TYPE_UINT:
@@ -816,13 +795,6 @@ config_clear(const config_format_t *fmt, void *options,
*(smartlist_t **)lvalue = NULL;
}
break;
- case CONFIG_TYPE_CSV_INTERVAL:
- if (*(smartlist_t**)lvalue) {
- SMARTLIST_FOREACH(*(smartlist_t **)lvalue, int *, cp, tor_free(cp));
- smartlist_free(*(smartlist_t **)lvalue);
- *(smartlist_t **)lvalue = NULL;
- }
- break;
case CONFIG_TYPE_LINELIST:
case CONFIG_TYPE_LINELIST_S:
config_free_lines(*(config_line_t **)lvalue);
diff --git a/src/or/confparse.h b/src/or/confparse.h
index f1f2030343..4b4bf0adb4 100644
--- a/src/or/confparse.h
+++ b/src/or/confparse.h
@@ -28,7 +28,9 @@ typedef enum config_type_t {
* optional whitespace. */
CONFIG_TYPE_CSV_INTERVAL, /**< A list of strings, separated by commas and
* optional whitespace, representing intervals in
- * seconds, with optional units */
+ * seconds, with optional units. We allow
+ * multiple values here for legacy reasons, but
+ * ignore every value after the first. */
CONFIG_TYPE_LINELIST, /**< Uninterpreted config lines */
CONFIG_TYPE_LINELIST_S, /**< Uninterpreted, context-sensitive config lines,
* mixed with other keywords. */
@@ -62,7 +64,7 @@ typedef union {
int *AUTOBOOL;
time_t *ISOTIME;
smartlist_t **CSV;
- smartlist_t **CSV_INTERVAL;
+ int *CSV_INTERVAL;
config_line_t **LINELIST;
config_line_t **LINELIST_S;
config_line_t **LINELIST_V;
diff --git a/src/or/connection.c b/src/or/connection.c
index 389199f18e..de0f0485b0 100644
--- a/src/or/connection.c
+++ b/src/or/connection.c
@@ -3686,7 +3686,6 @@ connection_outbuf_too_full(connection_t *conn)
* This should help fix slow upload rates.
*/
static void
-
update_send_buffer_size(tor_socket_t sock)
{
#ifdef _WIN32
diff --git a/src/or/consdiffmgr.c b/src/or/consdiffmgr.c
index 02b905a520..323f4f9ca0 100644
--- a/src/or/consdiffmgr.c
+++ b/src/or/consdiffmgr.c
@@ -99,6 +99,14 @@ static const compress_method_t compress_diffs_with[] = {
#endif
};
+/**
+ * Event for rescanning the cache.
+ */
+static mainloop_event_t *consdiffmgr_rescan_ev = NULL;
+
+static void consdiffmgr_rescan_cb(mainloop_event_t *ev, void *arg);
+static void mark_cdm_cache_dirty(void);
+
/** How many different methods will we try to use for diff compression? */
STATIC unsigned
n_diff_compression_methods(void)
@@ -372,7 +380,9 @@ cdm_cache_init(void)
} else {
consdiffmgr_set_cache_flags();
}
- cdm_cache_dirty = 1;
+ consdiffmgr_rescan_ev =
+ mainloop_event_postloop_new(consdiffmgr_rescan_cb, NULL);
+ mark_cdm_cache_dirty();
cdm_cache_loaded = 0;
}
@@ -1095,6 +1105,24 @@ consdiffmgr_rescan(void)
cdm_cache_dirty = 0;
}
+/** Callback wrapper for consdiffmgr_rescan */
+static void
+consdiffmgr_rescan_cb(mainloop_event_t *ev, void *arg)
+{
+ (void)ev;
+ (void)arg;
+ consdiffmgr_rescan();
+}
+
+/** Mark the cache as dirty, and schedule a rescan event. */
+static void
+mark_cdm_cache_dirty(void)
+{
+ cdm_cache_dirty = 1;
+ tor_assert(consdiffmgr_rescan_ev);
+ mainloop_event_activate(consdiffmgr_rescan_ev);
+}
+
/**
* Helper: compare two files by their from-valid-after and valid-after labels,
* trying to sort in ascending order by from-valid-after (when present) and
@@ -1219,6 +1247,7 @@ consdiffmgr_free_all(void)
memset(latest_consensus, 0, sizeof(latest_consensus));
consensus_cache_free(cons_diff_cache);
cons_diff_cache = NULL;
+ mainloop_event_free(consdiffmgr_rescan_ev);
}
/* =====
@@ -1750,7 +1779,7 @@ consensus_compress_worker_replyfn(void *work_)
compress_consensus_with,
job->out,
"consensus");
- cdm_cache_dirty = 1;
+ mark_cdm_cache_dirty();
unsigned u;
consensus_flavor_t f = job->flavor;
diff --git a/src/or/directory.c b/src/or/directory.c
index c419b61d02..4b19999969 100644
--- a/src/or/directory.c
+++ b/src/or/directory.c
@@ -5300,84 +5300,71 @@ connection_dir_finished_connecting(dir_connection_t *conn)
/** Decide which download schedule we want to use based on descriptor type
* in <b>dls</b> and <b>options</b>.
- * Then return a list of int pointers defining download delays in seconds.
+ *
+ * Then, return the initial delay for that download schedule, in seconds.
+ *
* Helper function for download_status_increment_failure(),
* download_status_reset(), and download_status_increment_attempt(). */
-STATIC const smartlist_t *
-find_dl_schedule(const download_status_t *dls, const or_options_t *options)
+STATIC int
+find_dl_min_delay(const download_status_t *dls, const or_options_t *options)
{
+ tor_assert(dls);
+ tor_assert(options);
+
switch (dls->schedule) {
case DL_SCHED_GENERIC:
/* Any other directory document */
if (dir_server_mode(options)) {
/* A directory authority or directory mirror */
- return options->TestingServerDownloadSchedule;
+ return options->TestingServerDownloadInitialDelay;
} else {
- return options->TestingClientDownloadSchedule;
+ return options->TestingClientDownloadInitialDelay;
}
case DL_SCHED_CONSENSUS:
if (!networkstatus_consensus_can_use_multiple_directories(options)) {
/* A public relay */
- return options->TestingServerConsensusDownloadSchedule;
+ return options->TestingServerConsensusDownloadInitialDelay;
} else {
/* A client or bridge */
if (networkstatus_consensus_is_bootstrapping(time(NULL))) {
/* During bootstrapping */
if (!networkstatus_consensus_can_use_extra_fallbacks(options)) {
/* A bootstrapping client without extra fallback directories */
- return
- options->ClientBootstrapConsensusAuthorityOnlyDownloadSchedule;
+ return options->
+ ClientBootstrapConsensusAuthorityOnlyDownloadInitialDelay;
} else if (dls->want_authority) {
/* A bootstrapping client with extra fallback directories, but
* connecting to an authority */
return
- options->ClientBootstrapConsensusAuthorityDownloadSchedule;
+ options->ClientBootstrapConsensusAuthorityDownloadInitialDelay;
} else {
/* A bootstrapping client connecting to extra fallback directories
*/
return
- options->ClientBootstrapConsensusFallbackDownloadSchedule;
+ options->ClientBootstrapConsensusFallbackDownloadInitialDelay;
}
} else {
/* A client with a reasonably live consensus, with or without
* certificates */
- return options->TestingClientConsensusDownloadSchedule;
+ return options->TestingClientConsensusDownloadInitialDelay;
}
}
case DL_SCHED_BRIDGE:
if (options->UseBridges && num_bridges_usable(0) > 0) {
/* A bridge client that is sure that one or more of its bridges are
* running can afford to wait longer to update bridge descriptors. */
- return options->TestingBridgeDownloadSchedule;
+ return options->TestingBridgeDownloadInitialDelay;
} else {
/* A bridge client which might have no running bridges, must try to
* get bridge descriptors straight away. */
- return options->TestingBridgeBootstrapDownloadSchedule;
+ return options->TestingBridgeBootstrapDownloadInitialDelay;
}
default:
tor_assert(0);
}
/* Impossible, but gcc will fail with -Werror without a `return`. */
- return NULL;
-}
-
-/** Decide which minimum delay step we want to use based on
- * descriptor type in <b>dls</b> and <b>options</b>.
- * Helper function for download_status_schedule_get_delay(). */
-STATIC int
-find_dl_min_delay(download_status_t *dls, const or_options_t *options)
-{
- tor_assert(dls);
- tor_assert(options);
-
- /*
- * For now, just use the existing schedule config stuff and pick the
- * first/last entries off to get min/max delay for backoff purposes
- */
- const smartlist_t *schedule = find_dl_schedule(dls, options);
- tor_assert(schedule != NULL && smartlist_len(schedule) >= 2);
- return *(int *)(smartlist_get(schedule, 0));
+ return 0;
}
/** As next_random_exponential_delay() below, but does not compute a random
@@ -5634,10 +5621,9 @@ download_status_increment_attempt(download_status_t *dls, const char *item,
static time_t
download_status_get_initial_delay_from_now(const download_status_t *dls)
{
- const smartlist_t *schedule = find_dl_schedule(dls, get_options());
/* We use constant initial delays, even in exponential backoff
* schedules. */
- return time(NULL) + *(int *)smartlist_get(schedule, 0);
+ return time(NULL) + find_dl_min_delay(dls, get_options());
}
/** Reset <b>dls</b> so that it will be considered downloadable
diff --git a/src/or/directory.h b/src/or/directory.h
index aa4d29a5bb..5f5ff7eca6 100644
--- a/src/or/directory.h
+++ b/src/or/directory.h
@@ -259,9 +259,7 @@ STATIC char* authdir_type_to_string(dirinfo_type_t auth);
STATIC const char * dir_conn_purpose_to_string(int purpose);
STATIC int should_use_directory_guards(const or_options_t *options);
STATIC compression_level_t choose_compression_level(ssize_t n_bytes);
-STATIC const smartlist_t *find_dl_schedule(const download_status_t *dls,
- const or_options_t *options);
-STATIC int find_dl_min_delay(download_status_t *dls,
+STATIC int find_dl_min_delay(const download_status_t *dls,
const or_options_t *options);
STATIC int next_random_exponential_delay(int delay,
diff --git a/src/or/entrynodes.c b/src/or/entrynodes.c
index 96e6ccaace..2c2bf99925 100644
--- a/src/or/entrynodes.c
+++ b/src/or/entrynodes.c
@@ -432,14 +432,15 @@ get_guard_confirmed_min_lifetime(void)
STATIC int
get_n_primary_guards(void)
{
- const int n = get_options()->NumEntryGuards;
- const int n_dir = get_options()->NumDirectoryGuards;
- if (n > 5) {
- return MAX(n_dir, n + n / 2);
- } else if (n >= 1) {
- return MAX(n_dir, n * 2);
+ /* If the user has explicitly configured the number of primary guards, do
+ * what the user wishes to do */
+ const int configured_primaries = get_options()->NumPrimaryGuards;
+ if (configured_primaries) {
+ return configured_primaries;
}
+ /* otherwise check for consensus parameter and if that's not set either, just
+ * use the default value. */
return networkstatus_get_param(NULL,
"guard-n-primary-guards",
DFLT_N_PRIMARY_GUARDS, 1, INT32_MAX);
@@ -454,6 +455,9 @@ get_n_primary_guards_to_use(guard_usage_t usage)
int configured;
const char *param_name;
int param_default;
+
+ /* If the user has explicitly configured the amount of guards, use
+ that. Otherwise, fall back to the default value. */
if (usage == GUARD_USAGE_DIRGUARD) {
configured = get_options()->NumDirectoryGuards;
param_name = "guard-n-primary-dir-guards-to-use";
diff --git a/src/or/hibernate.c b/src/or/hibernate.c
index 9fed338555..c4ae63acc4 100644
--- a/src/or/hibernate.c
+++ b/src/or/hibernate.c
@@ -1111,10 +1111,18 @@ getinfo_helper_accounting(control_connection_t *conn,
static void
on_hibernate_state_change(hibernate_state_t prev_state)
{
- (void)prev_state; /* Should we do something with this? */
control_event_server_status(LOG_NOTICE,
"HIBERNATION_STATUS STATUS=%s",
hibernate_state_to_string(hibernate_state));
+
+ /* We are changing hibernation state, this can affect the main loop event
+ * list. Rescan it to update the events state. We do this whatever the new
+ * hibernation state because they can each possibly affect an event. The
+ * initial state means we are booting up so we shouldn't scan here because
+ * at this point the events in the list haven't been initialized. */
+ if (prev_state != HIBERNATE_STATE_INITIAL) {
+ rescan_periodic_events(get_options());
+ }
}
#ifdef TOR_UNIT_TESTS
diff --git a/src/or/hs_service.c b/src/or/hs_service.c
index f6c7e3cd81..7af14373d4 100644
--- a/src/or/hs_service.c
+++ b/src/or/hs_service.c
@@ -80,6 +80,7 @@ static smartlist_t *hs_service_staging_list;
* reupload if needed */
static int consider_republishing_hs_descriptors = 0;
+/* Static declaration. */
static void set_descriptor_revision_counter(hs_descriptor_t *hs_desc);
static void move_descriptors(hs_service_t *src, hs_service_t *dst);
@@ -152,6 +153,12 @@ register_service(hs_service_ht *map, hs_service_t *service)
}
/* Taking ownership of the object at this point. */
HT_INSERT(hs_service_ht, map, service);
+
+ /* If we just modified the global map, we notify. */
+ if (map == hs_service_map) {
+ hs_service_map_has_changed();
+ }
+
return 0;
}
@@ -178,6 +185,11 @@ remove_service(hs_service_ht *map, hs_service_t *service)
"while removing service %s",
escaped(service->config.directory_path));
}
+
+ /* If we just modified the global map, we notify. */
+ if (map == hs_service_map) {
+ hs_service_map_has_changed();
+ }
}
/* Set the default values for a service configuration object <b>c</b>. */
@@ -916,6 +928,11 @@ register_all_services(void)
smartlist_clear(hs_service_staging_list);
service_free_all();
hs_service_map = new_service_map;
+ /* We've just register services into the new map and now we've replaced the
+ * global map with it so we have to notify that the change happened. When
+ * registering a service, the notify is only triggered if the destination
+ * map is the global map for which in here it was not. */
+ hs_service_map_has_changed();
}
/* Write the onion address of a given service to the given filename fname_ in
@@ -2936,6 +2953,17 @@ service_add_fnames_to_list(const hs_service_t *service, smartlist_t *list)
/* Public API */
/* ========== */
+/* This is called everytime the service map (v2 or v3) changes that is if an
+ * element is added or removed. */
+void
+hs_service_map_has_changed(void)
+{
+ /* If we now have services where previously we had not, we need to enable
+ * the HS service main loop event. If we changed to having no services, we
+ * need to disable the event. */
+ rescan_periodic_events(get_options());
+}
+
/* Upload an encoded descriptor in encoded_desc of the given version. This
* descriptor is for the service identity_pk and blinded_pk used to setup the
* directory connection identifier. It is uploaded to the directory hsdir_rs
diff --git a/src/or/hs_service.h b/src/or/hs_service.h
index d163eeef28..2e27d8a899 100644
--- a/src/or/hs_service.h
+++ b/src/or/hs_service.h
@@ -260,6 +260,7 @@ void hs_service_lists_fnames_for_sandbox(smartlist_t *file_list,
int hs_service_set_conn_addr_port(const origin_circuit_t *circ,
edge_connection_t *conn);
+void hs_service_map_has_changed(void);
void hs_service_dir_info_changed(void);
void hs_service_run_scheduled_events(time_t now);
void hs_service_circuit_has_opened(origin_circuit_t *circ);
diff --git a/src/or/main.c b/src/or/main.c
index 5e9dfd6c58..797969646b 100644
--- a/src/or/main.c
+++ b/src/or/main.c
@@ -150,7 +150,6 @@ static int run_main_loop_until_done(void);
static void process_signal(int sig);
static void shutdown_did_not_work_callback(evutil_socket_t fd, short event,
void *arg) ATTR_NORETURN;
-static void rescan_periodic_events(const or_options_t *options);
/********* START VARIABLES **********/
@@ -446,6 +445,7 @@ add_connection_to_closeable_list(connection_t *conn)
tor_assert(conn->marked_for_close);
assert_connection_ok(conn, time(NULL));
smartlist_add(closeable_connection_lst, conn);
+ mainloop_schedule_postloop_cleanup();
}
/** Return 1 if conn is on the closeable list, else return 0. */
@@ -1361,56 +1361,66 @@ CALLBACK(write_stats_file);
#undef CALLBACK
/* Now we declare an array of periodic_event_item_t for each periodic event */
-#define CALLBACK(name, r) PERIODIC_EVENT(name, r)
+#define CALLBACK(name, r, f) PERIODIC_EVENT(name, r, f)
STATIC periodic_event_item_t periodic_events[] = {
/* Everyone needs to run those. */
- CALLBACK(add_entropy, PERIODIC_EVENT_ROLE_ALL),
- CALLBACK(check_expired_networkstatus, PERIODIC_EVENT_ROLE_ALL),
- CALLBACK(clean_caches, PERIODIC_EVENT_ROLE_ALL),
- CALLBACK(fetch_networkstatus, PERIODIC_EVENT_ROLE_ALL),
- CALLBACK(heartbeat, PERIODIC_EVENT_ROLE_ALL),
- CALLBACK(launch_descriptor_fetches, PERIODIC_EVENT_ROLE_ALL),
- CALLBACK(reset_padding_counts, PERIODIC_EVENT_ROLE_ALL),
- CALLBACK(retry_listeners, PERIODIC_EVENT_ROLE_ALL),
- CALLBACK(rotate_x509_certificate, PERIODIC_EVENT_ROLE_ALL),
- CALLBACK(write_stats_file, PERIODIC_EVENT_ROLE_ALL),
+ CALLBACK(add_entropy, PERIODIC_EVENT_ROLE_ALL, 0),
+ CALLBACK(check_expired_networkstatus, PERIODIC_EVENT_ROLE_ALL, 0),
+ CALLBACK(clean_caches, PERIODIC_EVENT_ROLE_ALL, 0),
+ CALLBACK(fetch_networkstatus, PERIODIC_EVENT_ROLE_ALL,
+ PERIODIC_EVENT_FLAG_NEED_NET),
+ CALLBACK(heartbeat, PERIODIC_EVENT_ROLE_ALL, 0),
+ CALLBACK(launch_descriptor_fetches, PERIODIC_EVENT_ROLE_ALL,
+ PERIODIC_EVENT_FLAG_NEED_NET),
+ CALLBACK(reset_padding_counts, PERIODIC_EVENT_ROLE_ALL, 0),
+ CALLBACK(retry_listeners, PERIODIC_EVENT_ROLE_ALL,
+ PERIODIC_EVENT_FLAG_NEED_NET),
+ CALLBACK(rotate_x509_certificate, PERIODIC_EVENT_ROLE_ALL, 0),
+ CALLBACK(write_stats_file, PERIODIC_EVENT_ROLE_ALL, 0),
/* Routers (bridge and relay) only. */
- CALLBACK(check_descriptor, PERIODIC_EVENT_ROLE_ROUTER),
- CALLBACK(check_ed_keys, PERIODIC_EVENT_ROLE_ROUTER),
- CALLBACK(check_for_reachability_bw, PERIODIC_EVENT_ROLE_ROUTER),
- CALLBACK(check_onion_keys_expiry_time, PERIODIC_EVENT_ROLE_ROUTER),
- CALLBACK(expire_old_ciruits_serverside, PERIODIC_EVENT_ROLE_ROUTER),
- CALLBACK(retry_dns, PERIODIC_EVENT_ROLE_ROUTER),
- CALLBACK(rotate_onion_key, PERIODIC_EVENT_ROLE_ROUTER),
+ CALLBACK(check_descriptor, PERIODIC_EVENT_ROLE_ROUTER,
+ PERIODIC_EVENT_FLAG_NEED_NET),
+ CALLBACK(check_ed_keys, PERIODIC_EVENT_ROLE_ROUTER, 0),
+ CALLBACK(check_for_reachability_bw, PERIODIC_EVENT_ROLE_ROUTER,
+ PERIODIC_EVENT_FLAG_NEED_NET),
+ CALLBACK(check_onion_keys_expiry_time, PERIODIC_EVENT_ROLE_ROUTER, 0),
+ CALLBACK(expire_old_ciruits_serverside, PERIODIC_EVENT_ROLE_ROUTER,
+ PERIODIC_EVENT_FLAG_NEED_NET),
+ CALLBACK(retry_dns, PERIODIC_EVENT_ROLE_ROUTER, 0),
+ CALLBACK(rotate_onion_key, PERIODIC_EVENT_ROLE_ROUTER, 0),
/* Authorities (bridge and directory) only. */
- CALLBACK(downrate_stability, PERIODIC_EVENT_ROLE_AUTHORITIES),
- CALLBACK(launch_reachability_tests, PERIODIC_EVENT_ROLE_AUTHORITIES),
- CALLBACK(save_stability, PERIODIC_EVENT_ROLE_AUTHORITIES),
+ CALLBACK(downrate_stability, PERIODIC_EVENT_ROLE_AUTHORITIES, 0),
+ CALLBACK(launch_reachability_tests, PERIODIC_EVENT_ROLE_AUTHORITIES,
+ PERIODIC_EVENT_FLAG_NEED_NET),
+ CALLBACK(save_stability, PERIODIC_EVENT_ROLE_AUTHORITIES, 0),
/* Directory authority only. */
- CALLBACK(check_authority_cert, PERIODIC_EVENT_ROLE_DIRAUTH),
+ CALLBACK(check_authority_cert, PERIODIC_EVENT_ROLE_DIRAUTH, 0),
/* Relay only. */
- CALLBACK(check_canonical_channels, PERIODIC_EVENT_ROLE_RELAY),
- CALLBACK(check_dns_honesty, PERIODIC_EVENT_ROLE_RELAY),
+ CALLBACK(check_canonical_channels, PERIODIC_EVENT_ROLE_RELAY,
+ PERIODIC_EVENT_FLAG_NEED_NET),
+ CALLBACK(check_dns_honesty, PERIODIC_EVENT_ROLE_RELAY,
+ PERIODIC_EVENT_FLAG_NEED_NET),
/* Hidden Service service only. */
- CALLBACK(hs_service, PERIODIC_EVENT_ROLE_HS_SERVICE),
+ CALLBACK(hs_service, PERIODIC_EVENT_ROLE_HS_SERVICE,
+ PERIODIC_EVENT_FLAG_NEED_NET),
/* Bridge only. */
- CALLBACK(record_bridge_stats, PERIODIC_EVENT_ROLE_BRIDGE),
+ CALLBACK(record_bridge_stats, PERIODIC_EVENT_ROLE_BRIDGE, 0),
/* Client only. */
- CALLBACK(rend_cache_failure_clean, PERIODIC_EVENT_ROLE_CLIENT),
+ CALLBACK(rend_cache_failure_clean, PERIODIC_EVENT_ROLE_CLIENT, 0),
/* Bridge Authority only. */
- CALLBACK(write_bridge_ns, PERIODIC_EVENT_ROLE_BRIDGEAUTH),
+ CALLBACK(write_bridge_ns, PERIODIC_EVENT_ROLE_BRIDGEAUTH, 0),
/* Directory server only. */
- CALLBACK(clean_consdiffmgr, PERIODIC_EVENT_ROLE_DIRSERVER),
+ CALLBACK(clean_consdiffmgr, PERIODIC_EVENT_ROLE_DIRSERVER, 0),
END_OF_PERIODIC_EVENTS
};
@@ -1542,16 +1552,29 @@ teardown_periodic_events(void)
/** Do a pass at all our periodic events, disable those we don't need anymore
* and enable those we need now using the given options. */
-static void
+void
rescan_periodic_events(const or_options_t *options)
{
tor_assert(options);
+ /* Avoid scanning the event list if we haven't initialized it yet. This is
+ * particularly useful for unit tests in order to avoid initializing main
+ * loop events everytime. */
+ if (!periodic_events_initialized) {
+ return;
+ }
+
int roles = get_my_roles(options);
for (int i = 0; periodic_events[i].name; ++i) {
periodic_event_item_t *item = &periodic_events[i];
+ /* Handle the event flags. */
+ if (net_is_disabled() &&
+ (item->flags & PERIODIC_EVENT_FLAG_NEED_NET)) {
+ continue;
+ }
+
/* Enable the event if needed. It is safe to enable an event that was
* already enabled. Same goes for disabling it. */
if (item->roles & roles) {
@@ -1604,6 +1627,30 @@ reschedule_directory_downloads(void)
periodic_event_reschedule(launch_descriptor_fetches_event);
}
+/** Mainloop callback: clean up circuits, channels, and connections
+ * that are pending close. */
+static void
+postloop_cleanup_cb(mainloop_event_t *ev, void *arg)
+{
+ (void)ev;
+ (void)arg;
+ circuit_close_all_marked();
+ close_closeable_connections();
+ channel_run_cleanup();
+ channel_listener_run_cleanup();
+}
+
+/** Event to run postloop_cleanup_cb */
+static mainloop_event_t *postloop_cleanup_ev=NULL;
+
+/** Schedule a post-loop event to clean up marked channels, connections, and
+ * circuits. */
+void
+mainloop_schedule_postloop_cleanup(void)
+{
+ mainloop_event_activate(postloop_cleanup_ev);
+}
+
#define LONGEST_TIMER_PERIOD (30 * 86400)
/** Helper: Return the number of seconds between <b>now</b> and <b>next</b>,
* clipped to the range [1 second, LONGEST_TIMER_PERIOD]. */
@@ -1702,12 +1749,6 @@ run_scheduled_events(time_t now)
circuit_expire_old_circs_as_needed(now);
}
- if (!net_is_disabled()) {
- /* This is usually redundant with circuit_build_needed_circs() above,
- * but it is very fast when there is no work to do. */
- connection_ap_attach_pending(0);
- }
-
/* 5. We do housekeeping for each connection... */
channel_update_bad_for_new_circs(NULL, 0);
int i;
@@ -1715,32 +1756,13 @@ run_scheduled_events(time_t now)
run_connection_housekeeping(i, now);
}
- /* 6. And remove any marked circuits... */
- circuit_close_all_marked();
-
- /* 8. and blow away any connections that need to die. have to do this now,
- * because if we marked a conn for close and left its socket -1, then
- * we'll pass it to poll/select and bad things will happen.
- */
- close_closeable_connections();
-
/* 8b. And if anything in our state is ready to get flushed to disk, we
* flush it. */
or_state_save(now);
- /* 8c. Do channel cleanup just like for connections */
- channel_run_cleanup();
- channel_listener_run_cleanup();
-
/* 11b. check pending unconfigured managed proxies */
if (!net_is_disabled() && pt_proxies_configuration_pending())
pt_configure_remaining_proxies();
-
- /* 12. launch diff computations. (This is free if there are none to
- * launch.) */
- if (dir_server_mode(options)) {
- consdiffmgr_rescan();
- }
}
/* Periodic callback: rotate the onion keys after the period defined by the
@@ -2616,6 +2638,20 @@ do_hup(void)
return 0;
}
+/** Initialize some mainloop_event_t objects that we require. */
+STATIC void
+initialize_mainloop_events(void)
+{
+ if (!schedule_active_linked_connections_event) {
+ schedule_active_linked_connections_event =
+ mainloop_event_postloop_new(schedule_active_linked_connections_cb, NULL);
+ }
+ if (!postloop_cleanup_ev) {
+ postloop_cleanup_ev =
+ mainloop_event_postloop_new(postloop_cleanup_cb, NULL);
+ }
+}
+
/** Tor main loop. */
int
do_main_loop(void)
@@ -2629,10 +2665,7 @@ do_main_loop(void)
initialize_periodic_events();
}
- if (!schedule_active_linked_connections_event) {
- schedule_active_linked_connections_event =
- mainloop_event_postloop_new(schedule_active_linked_connections_cb, NULL);
- }
+ initialize_mainloop_events();
/* initialize dns resolve map, spawn workers if needed */
if (dns_init() < 0) {
@@ -3517,6 +3550,7 @@ tor_free_all(int postfork)
tor_event_free(initialize_periodic_events_event);
mainloop_event_free(directory_all_unreachable_cb_event);
mainloop_event_free(schedule_active_linked_connections_event);
+ mainloop_event_free(postloop_cleanup_ev);
#ifdef HAVE_SYSTEMD_209
periodic_timer_free(systemd_watchdog_timer);
diff --git a/src/or/main.h b/src/or/main.h
index 0e3de7d4be..2447339fb5 100644
--- a/src/or/main.h
+++ b/src/or/main.h
@@ -61,6 +61,8 @@ void dns_servers_relaunch_checks(void);
void reset_all_main_loop_timers(void);
void reschedule_descriptor_update_check(void);
void reschedule_directory_downloads(void);
+void mainloop_schedule_postloop_cleanup(void);
+void rescan_periodic_events(const or_options_t *options);
MOCK_DECL(long,get_uptime,(void));
MOCK_DECL(void,reset_uptime,(void));
@@ -96,6 +98,7 @@ extern token_bucket_rw_t global_relayed_bucket;
#ifdef MAIN_PRIVATE
STATIC void init_connection_lists(void);
+STATIC void initialize_mainloop_events(void);
STATIC void close_closeable_connections(void);
STATIC void initialize_periodic_events(void);
STATIC void teardown_periodic_events(void);
diff --git a/src/or/or.h b/src/or/or.h
index e27f25197b..006c2ec7d4 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -57,7 +57,6 @@
#ifdef HAVE_TIME_H
#include <time.h>
#endif
-#include <stdbool.h>
#ifdef _WIN32
#include <winsock2.h>
@@ -4149,6 +4148,8 @@ typedef struct {
int NumDirectoryGuards; /**< How many dir guards do we try to establish?
* If 0, use value from NumEntryGuards. */
+ int NumPrimaryGuards; /**< How many primary guards do we want? */
+
int RephistTrackTime; /**< How many seconds do we keep rephist info? */
/** Should we always fetch our dir info on the mirror schedule (which
* means directly from the authorities) no matter our other config? */
@@ -4317,19 +4318,19 @@ typedef struct {
/** Schedule for when servers should download things in general. Only
* altered on testing networks. */
- smartlist_t *TestingServerDownloadSchedule;
+ int TestingServerDownloadInitialDelay;
/** Schedule for when clients should download things in general. Only
* altered on testing networks. */
- smartlist_t *TestingClientDownloadSchedule;
+ int TestingClientDownloadInitialDelay;
/** Schedule for when servers should download consensuses. Only altered
* on testing networks. */
- smartlist_t *TestingServerConsensusDownloadSchedule;
+ int TestingServerConsensusDownloadInitialDelay;
/** Schedule for when clients should download consensuses. Only altered
* on testing networks. */
- smartlist_t *TestingClientConsensusDownloadSchedule;
+ int TestingClientConsensusDownloadInitialDelay;
/** Schedule for when clients should download consensuses from authorities
* if they are bootstrapping (that is, they don't have a usable, reasonably
@@ -4339,7 +4340,7 @@ typedef struct {
* This schedule is incremented by (potentially concurrent) connection
* attempts, unlike other schedules, which are incremented by connection
* failures. Only altered on testing networks. */
- smartlist_t *ClientBootstrapConsensusAuthorityDownloadSchedule;
+ int ClientBootstrapConsensusAuthorityDownloadInitialDelay;
/** Schedule for when clients should download consensuses from fallback
* directory mirrors if they are bootstrapping (that is, they don't have a
@@ -4349,7 +4350,7 @@ typedef struct {
* This schedule is incremented by (potentially concurrent) connection
* attempts, unlike other schedules, which are incremented by connection
* failures. Only altered on testing networks. */
- smartlist_t *ClientBootstrapConsensusFallbackDownloadSchedule;
+ int ClientBootstrapConsensusFallbackDownloadInitialDelay;
/** Schedule for when clients should download consensuses from authorities
* if they are bootstrapping (that is, they don't have a usable, reasonably
@@ -4359,15 +4360,15 @@ typedef struct {
* This schedule is incremented by (potentially concurrent) connection
* attempts, unlike other schedules, which are incremented by connection
* failures. Only altered on testing networks. */
- smartlist_t *ClientBootstrapConsensusAuthorityOnlyDownloadSchedule;
+ int ClientBootstrapConsensusAuthorityOnlyDownloadInitialDelay;
/** Schedule for when clients should download bridge descriptors. Only
* altered on testing networks. */
- smartlist_t *TestingBridgeDownloadSchedule;
+ int TestingBridgeDownloadInitialDelay;
/** Schedule for when clients should download bridge descriptors when they
* have no running bridges. Only altered on testing networks. */
- smartlist_t *TestingBridgeBootstrapDownloadSchedule;
+ int TestingBridgeBootstrapDownloadInitialDelay;
/** When directory clients have only a few descriptors to request, they
* batch them until they have more, or until this amount of time has
diff --git a/src/or/periodic.h b/src/or/periodic.h
index cc0ab86bd8..e8208b2475 100644
--- a/src/or/periodic.h
+++ b/src/or/periodic.h
@@ -30,6 +30,15 @@
(PERIODIC_EVENT_ROLE_AUTHORITIES | PERIODIC_EVENT_ROLE_CLIENT | \
PERIODIC_EVENT_ROLE_HS_SERVICE | PERIODIC_EVENT_ROLE_ROUTER)
+/*
+ * Event flags which can change the behavior of an event.
+ */
+
+/* Indicate that the event needs the network meaning that if we are in
+ * DisableNetwork or hibernation mode, the event won't be enabled. This obey
+ * the net_is_disabled() check. */
+#define PERIODIC_EVENT_FLAG_NEED_NET (1U << 0)
+
/** Callback function for a periodic event to take action. The return value
* influences the next time the function will get called. Return
* PERIODIC_EVENT_NO_UPDATE to not update <b>last_action_time</b> and be polled
@@ -50,13 +59,15 @@ typedef struct periodic_event_item_t {
/* Bitmask of roles define above for which this event applies. */
uint32_t roles;
+ /* Bitmask of flags which can change the behavior of the event. */
+ uint32_t flags;
/* Indicate that this event has been enabled that is scheduled. */
unsigned int enabled : 1;
} periodic_event_item_t;
/** events will get their interval from first execution */
-#define PERIODIC_EVENT(fn, r) { fn##_callback, 0, NULL, #fn, r, 0 }
-#define END_OF_PERIODIC_EVENTS { NULL, 0, NULL, NULL, 0, 0 }
+#define PERIODIC_EVENT(fn, r, f) { fn##_callback, 0, NULL, #fn, r, f, 0 }
+#define END_OF_PERIODIC_EVENTS { NULL, 0, NULL, NULL, 0, 0, 0 }
/* Return true iff the given event was setup before thus is enabled to be
* scheduled. */
diff --git a/src/or/rendservice.c b/src/or/rendservice.c
index 1a93c36433..afaeabe5dc 100644
--- a/src/or/rendservice.c
+++ b/src/or/rendservice.c
@@ -348,6 +348,13 @@ rend_add_service(smartlist_t *service_list, rend_service_t *service)
/* The service passed all the checks */
tor_assert(s_list);
smartlist_add(s_list, service);
+
+ /* Notify that our global service list has changed only if this new service
+ * went into our global list. If not, when we move service from the staging
+ * list to the new list, a notify is triggered. */
+ if (s_list == rend_service_list) {
+ hs_service_map_has_changed();
+ }
return 0;
}
@@ -609,6 +616,8 @@ rend_service_prune_list_impl_(void)
circuit_mark_for_close(TO_CIRCUIT(ocirc), END_CIRC_REASON_FINISHED);
}
smartlist_free(surviving_services);
+ /* Notify that our global service list has changed. */
+ hs_service_map_has_changed();
}
/* Try to prune our main service list using the temporary one that we just
@@ -958,6 +967,8 @@ rend_service_del_ephemeral(const char *service_id)
}
} SMARTLIST_FOREACH_END(circ);
smartlist_remove(rend_service_list, s);
+ /* Notify that we just removed a service from our global list. */
+ hs_service_map_has_changed();
rend_service_free(s);
log_debug(LD_CONFIG, "Removed ephemeral Onion Service: %s", service_id);
diff --git a/src/test/geoip_dummy b/src/test/geoip_dummy
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/src/test/geoip_dummy
diff --git a/src/test/include.am b/src/test/include.am
index b59517a135..eb61d74893 100644
--- a/src/test/include.am
+++ b/src/test/include.am
@@ -343,6 +343,7 @@ src_test_test_bt_cl_CPPFLAGS= $(src_test_AM_CPPFLAGS) $(TEST_CPPFLAGS)
EXTRA_DIST += \
src/test/bt_test.py \
+ src/test/geoip_dummy \
src/test/ntor_ref.py \
src/test/hs_ntor_ref.py \
src/test/hs_build_address.py \
diff --git a/src/test/test_dir.c b/src/test/test_dir.c
index df5ae2d594..957f646de9 100644
--- a/src/test/test_dir.c
+++ b/src/test/test_dir.c
@@ -4065,34 +4065,19 @@ test_dir_download_status_increment(void *arg)
DL_WANT_ANY_DIRSERVER,
DL_SCHED_INCREMENT_ATTEMPT,
0, 0 };
- int no_delay = 0;
- int delay0 = -1;
- int delay1 = -1;
- int delay2 = -1;
- smartlist_t *schedule = smartlist_new();
- smartlist_t *schedule_no_initial_delay = smartlist_new();
or_options_t test_options;
time_t current_time = time(NULL);
- /* Provide some values for the schedules */
- delay0 = 10;
- delay1 = 99;
- delay2 = 20;
-
- /* Make the schedules */
- smartlist_add(schedule, (void *)&delay0);
- smartlist_add(schedule, (void *)&delay1);
- smartlist_add(schedule, (void *)&delay2);
-
- smartlist_add(schedule_no_initial_delay, (void *)&no_delay);
- smartlist_add(schedule_no_initial_delay, (void *)&delay1);
- smartlist_add(schedule_no_initial_delay, (void *)&delay2);
+ const int delay0 = 10;
+ const int no_delay = 0;
+ const int schedule = 10;
+ const int schedule_no_initial_delay = 0;
/* Put it in the options */
mock_options = &test_options;
reset_options(mock_options, &mock_get_options_calls);
- mock_options->TestingBridgeBootstrapDownloadSchedule = schedule;
- mock_options->TestingClientDownloadSchedule = schedule;
+ mock_options->TestingBridgeBootstrapDownloadInitialDelay = schedule;
+ mock_options->TestingClientDownloadInitialDelay = schedule;
MOCK(get_options, mock_get_options);
@@ -4100,13 +4085,13 @@ test_dir_download_status_increment(void *arg)
* whether or not it was reset before being used */
/* regression test for 17750: no initial delay */
- mock_options->TestingClientDownloadSchedule = schedule_no_initial_delay;
+ mock_options->TestingClientDownloadInitialDelay = schedule_no_initial_delay;
mock_get_options_calls = 0;
/* we really want to test that it's equal to time(NULL) + delay0, but that's
* an unrealiable test, because time(NULL) might change. */
/* regression test for 17750: exponential, no initial delay */
- mock_options->TestingClientDownloadSchedule = schedule_no_initial_delay;
+ mock_options->TestingClientDownloadInitialDelay = schedule_no_initial_delay;
mock_get_options_calls = 0;
/* we really want to test that it's equal to time(NULL) + delay0, but that's
* an unrealiable test, because time(NULL) might change. */
@@ -4119,7 +4104,7 @@ test_dir_download_status_increment(void *arg)
tt_int_op(mock_get_options_calls, OP_GE, 1);
/* regression test for 17750: exponential, initial delay */
- mock_options->TestingClientDownloadSchedule = schedule;
+ mock_options->TestingClientDownloadInitialDelay = schedule;
mock_get_options_calls = 0;
/* we really want to test that it's equal to time(NULL) + delay0, but that's
* an unrealiable test, because time(NULL) might change. */
@@ -4132,9 +4117,6 @@ test_dir_download_status_increment(void *arg)
tt_int_op(mock_get_options_calls, OP_GE, 1);
done:
- /* the pointers in schedule are allocated on the stack */
- smartlist_free(schedule);
- smartlist_free(schedule_no_initial_delay);
UNMOCK(get_options);
mock_options = NULL;
mock_get_options_calls = 0;
@@ -5452,7 +5434,7 @@ mock_num_bridges_usable(int use_maybe_reachable)
* fallbacks.
*/
static void
-test_dir_find_dl_schedule(void* data)
+test_dir_find_dl_min_delay(void* data)
{
const char *str = (const char *)data;
@@ -5485,44 +5467,45 @@ test_dir_find_dl_schedule(void* data)
mock_num_bridges_usable);
download_status_t dls;
- smartlist_t server, client, server_cons, client_cons;
- smartlist_t client_boot_auth_only_cons, client_boot_auth_cons;
- smartlist_t client_boot_fallback_cons, bridge, bridge_bootstrap;
+
+ const int server=10, client=20, server_cons=30, client_cons=40;
+ const int client_boot_auth_only_cons=50, client_boot_auth_cons=60;
+ const int client_boot_fallback_cons=70, bridge=80, bridge_bootstrap=90;
mock_options = tor_malloc(sizeof(or_options_t));
reset_options(mock_options, &mock_get_options_calls);
MOCK(get_options, mock_get_options);
- mock_options->TestingServerDownloadSchedule = &server;
- mock_options->TestingClientDownloadSchedule = &client;
- mock_options->TestingServerConsensusDownloadSchedule = &server_cons;
- mock_options->TestingClientConsensusDownloadSchedule = &client_cons;
- mock_options->ClientBootstrapConsensusAuthorityOnlyDownloadSchedule =
- &client_boot_auth_only_cons;
- mock_options->ClientBootstrapConsensusAuthorityDownloadSchedule =
- &client_boot_auth_cons;
- mock_options->ClientBootstrapConsensusFallbackDownloadSchedule =
- &client_boot_fallback_cons;
- mock_options->TestingBridgeDownloadSchedule = &bridge;
- mock_options->TestingBridgeBootstrapDownloadSchedule = &bridge_bootstrap;
+ mock_options->TestingServerDownloadInitialDelay = server;
+ mock_options->TestingClientDownloadInitialDelay = client;
+ mock_options->TestingServerConsensusDownloadInitialDelay = server_cons;
+ mock_options->TestingClientConsensusDownloadInitialDelay = client_cons;
+ mock_options->ClientBootstrapConsensusAuthorityOnlyDownloadInitialDelay =
+ client_boot_auth_only_cons;
+ mock_options->ClientBootstrapConsensusAuthorityDownloadInitialDelay =
+ client_boot_auth_cons;
+ mock_options->ClientBootstrapConsensusFallbackDownloadInitialDelay =
+ client_boot_fallback_cons;
+ mock_options->TestingBridgeDownloadInitialDelay = bridge;
+ mock_options->TestingBridgeBootstrapDownloadInitialDelay = bridge_bootstrap;
dls.schedule = DL_SCHED_GENERIC;
/* client */
mock_options->ClientOnly = 1;
- tt_ptr_op(find_dl_schedule(&dls, mock_options), OP_EQ, &client);
+ tt_int_op(find_dl_min_delay(&dls, mock_options), OP_EQ, client);
mock_options->ClientOnly = 0;
/* dir mode */
mock_options->DirPort_set = 1;
mock_options->DirCache = 1;
- tt_ptr_op(find_dl_schedule(&dls, mock_options), OP_EQ, &server);
+ tt_int_op(find_dl_min_delay(&dls, mock_options), OP_EQ, server);
mock_options->DirPort_set = 0;
mock_options->DirCache = 0;
dls.schedule = DL_SCHED_CONSENSUS;
/* public server mode */
mock_options->ORPort_set = 1;
- tt_ptr_op(find_dl_schedule(&dls, mock_options), OP_EQ, &server_cons);
+ tt_int_op(find_dl_min_delay(&dls, mock_options), OP_EQ, server_cons);
mock_options->ORPort_set = 0;
/* client and bridge modes */
@@ -5531,30 +5514,30 @@ test_dir_find_dl_schedule(void* data)
dls.want_authority = 1;
/* client */
mock_options->ClientOnly = 1;
- tt_ptr_op(find_dl_schedule(&dls, mock_options), OP_EQ,
- &client_boot_auth_cons);
+ tt_int_op(find_dl_min_delay(&dls, mock_options), OP_EQ,
+ client_boot_auth_cons);
mock_options->ClientOnly = 0;
/* bridge relay */
mock_options->ORPort_set = 1;
mock_options->BridgeRelay = 1;
- tt_ptr_op(find_dl_schedule(&dls, mock_options), OP_EQ,
- &client_boot_auth_cons);
+ tt_int_op(find_dl_min_delay(&dls, mock_options), OP_EQ,
+ client_boot_auth_cons);
mock_options->ORPort_set = 0;
mock_options->BridgeRelay = 0;
dls.want_authority = 0;
/* client */
mock_options->ClientOnly = 1;
- tt_ptr_op(find_dl_schedule(&dls, mock_options), OP_EQ,
- &client_boot_fallback_cons);
+ tt_int_op(find_dl_min_delay(&dls, mock_options), OP_EQ,
+ client_boot_fallback_cons);
mock_options->ClientOnly = 0;
/* bridge relay */
mock_options->ORPort_set = 1;
mock_options->BridgeRelay = 1;
- tt_ptr_op(find_dl_schedule(&dls, mock_options), OP_EQ,
- &client_boot_fallback_cons);
+ tt_int_op(find_dl_min_delay(&dls, mock_options), OP_EQ,
+ client_boot_fallback_cons);
mock_options->ORPort_set = 0;
mock_options->BridgeRelay = 0;
@@ -5562,30 +5545,30 @@ test_dir_find_dl_schedule(void* data)
/* dls.want_authority is ignored */
/* client */
mock_options->ClientOnly = 1;
- tt_ptr_op(find_dl_schedule(&dls, mock_options), OP_EQ,
- &client_boot_auth_only_cons);
+ tt_int_op(find_dl_min_delay(&dls, mock_options), OP_EQ,
+ client_boot_auth_only_cons);
mock_options->ClientOnly = 0;
/* bridge relay */
mock_options->ORPort_set = 1;
mock_options->BridgeRelay = 1;
- tt_ptr_op(find_dl_schedule(&dls, mock_options), OP_EQ,
- &client_boot_auth_only_cons);
+ tt_int_op(find_dl_min_delay(&dls, mock_options), OP_EQ,
+ client_boot_auth_only_cons);
mock_options->ORPort_set = 0;
mock_options->BridgeRelay = 0;
}
} else {
/* client */
mock_options->ClientOnly = 1;
- tt_ptr_op(find_dl_schedule(&dls, mock_options), OP_EQ,
- &client_cons);
+ tt_int_op(find_dl_min_delay(&dls, mock_options), OP_EQ,
+ client_cons);
mock_options->ClientOnly = 0;
/* bridge relay */
mock_options->ORPort_set = 1;
mock_options->BridgeRelay = 1;
- tt_ptr_op(find_dl_schedule(&dls, mock_options), OP_EQ,
- &client_cons);
+ tt_int_op(find_dl_min_delay(&dls, mock_options), OP_EQ,
+ client_cons);
mock_options->ORPort_set = 0;
mock_options->BridgeRelay = 0;
}
@@ -5595,9 +5578,9 @@ test_dir_find_dl_schedule(void* data)
mock_options->ClientOnly = 1;
mock_options->UseBridges = 1;
if (num_bridges_usable(0) > 0) {
- tt_ptr_op(find_dl_schedule(&dls, mock_options), OP_EQ, &bridge);
+ tt_int_op(find_dl_min_delay(&dls, mock_options), OP_EQ, bridge);
} else {
- tt_ptr_op(find_dl_schedule(&dls, mock_options), OP_EQ, &bridge_bootstrap);
+ tt_int_op(find_dl_min_delay(&dls, mock_options), OP_EQ, bridge_bootstrap);
}
done:
@@ -5871,14 +5854,14 @@ struct testcase_t dir_tests[] = {
DIR(dump_unparseable_descriptors, 0),
DIR(populate_dump_desc_fifo, 0),
DIR(populate_dump_desc_fifo_2, 0),
- DIR_ARG(find_dl_schedule, TT_FORK, "bfd"),
- DIR_ARG(find_dl_schedule, TT_FORK, "bad"),
- DIR_ARG(find_dl_schedule, TT_FORK, "cfd"),
- DIR_ARG(find_dl_schedule, TT_FORK, "cad"),
- DIR_ARG(find_dl_schedule, TT_FORK, "bfr"),
- DIR_ARG(find_dl_schedule, TT_FORK, "bar"),
- DIR_ARG(find_dl_schedule, TT_FORK, "cfr"),
- DIR_ARG(find_dl_schedule, TT_FORK, "car"),
+ DIR_ARG(find_dl_min_delay, TT_FORK, "bfd"),
+ DIR_ARG(find_dl_min_delay, TT_FORK, "bad"),
+ DIR_ARG(find_dl_min_delay, TT_FORK, "cfd"),
+ DIR_ARG(find_dl_min_delay, TT_FORK, "cad"),
+ DIR_ARG(find_dl_min_delay, TT_FORK, "bfr"),
+ DIR_ARG(find_dl_min_delay, TT_FORK, "bar"),
+ DIR_ARG(find_dl_min_delay, TT_FORK, "cfr"),
+ DIR_ARG(find_dl_min_delay, TT_FORK, "car"),
DIR(assumed_flags, 0),
DIR(networkstatus_compute_bw_weights_v10, 0),
DIR(platform_str, 0),
diff --git a/src/test/test_entrynodes.c b/src/test/test_entrynodes.c
index 92a860360d..f55e9f0173 100644
--- a/src/test/test_entrynodes.c
+++ b/src/test/test_entrynodes.c
@@ -2679,6 +2679,23 @@ test_enty_guard_should_expire_waiting(void *arg)
tor_free(fake_state);
}
+/** Test that the number of primary guards can be controlled using torrc */
+static void
+test_entry_guard_number_of_primaries(void *arg)
+{
+ (void) arg;
+
+ /* Get default value */
+ tt_int_op(get_n_primary_guards(), OP_EQ, DFLT_N_PRIMARY_GUARDS);
+
+ /* Set number of primaries using torrc */
+ get_options_mutable()->NumPrimaryGuards = 42;
+ tt_int_op(get_n_primary_guards(), OP_EQ, 42);
+
+ done:
+ ;
+}
+
static void
mock_directory_initiate_request(directory_request_t *req)
{
@@ -2826,6 +2843,8 @@ struct testcase_t entrynodes_tests[] = {
test_entry_guard_parse_from_state_broken, TT_FORK, NULL, NULL },
{ "get_guard_selection_by_name",
test_entry_guard_get_guard_selection_by_name, TT_FORK, NULL, NULL },
+ { "number_of_primaries",
+ test_entry_guard_number_of_primaries, TT_FORK, NULL, NULL },
BFN_TEST(choose_selection_initial),
BFN_TEST(add_single_guard),
BFN_TEST(node_filter),
diff --git a/src/test/test_geoip.c b/src/test/test_geoip.c
index 20f6114dc0..0711a113eb 100644
--- a/src/test/test_geoip.c
+++ b/src/test/test_geoip.c
@@ -444,6 +444,86 @@ test_geoip_load_file(void *arg)
tor_free(dhex);
}
+static void
+test_geoip6_load_file(void *arg)
+{
+ (void)arg;
+ struct in6_addr iaddr6;
+ char *contents = NULL;
+ char *dhex = NULL;
+
+ /* A nonexistant filename should fail. */
+ tt_int_op(-1, OP_EQ,
+ geoip_load_file(AF_INET6, "/you/did/not/put/a/file/here/I/hope"));
+
+ /* Any lookup attempt should say "-1" because we have no info */
+ tor_inet_pton(AF_INET6, "2001:4860:4860::8888", &iaddr6);
+ tt_int_op(-1, OP_EQ, geoip_get_country_by_ipv6(&iaddr6));
+
+ /* Load geiop6 file */
+ const char FNAME6[] = SRCDIR "/src/config/geoip6";
+ tt_int_op(0, OP_EQ, geoip_load_file(AF_INET6, FNAME6));
+
+ /* Check that we loaded some countries; this will fail if there are ever
+ * fewer than 50 countries in the world. */
+ tt_int_op(geoip_get_n_countries(), OP_GE, 50);
+
+ /* Let's see where 2001:4860:4860::8888 (google dns) is. */
+ const char *caddr6 = "2001:4860:4860::8888";
+ tor_inet_pton(AF_INET6, caddr6, &iaddr6);
+ int country6 = geoip_get_country_by_ipv6(&iaddr6);
+ tt_int_op(country6, OP_GE, 1);
+
+ const char *cc6 = geoip_get_country_name(country6);
+ tt_int_op(strlen(cc6), OP_EQ, 2);
+
+ /* The digest should be set.... */
+ tt_str_op("0000000000000000000000000000000000000000", OP_NE,
+ geoip_db_digest(AF_INET6));
+
+ /* And it should be set correctly */
+ contents = read_file_to_str(FNAME6, RFTS_BIN, NULL);
+ uint8_t d[DIGEST_LEN];
+ crypto_digest((char*)d, contents, strlen(contents));
+ dhex = tor_strdup(hex_str((char*)d, DIGEST_LEN));
+ tt_str_op(dhex, OP_EQ, geoip_db_digest(AF_INET6));
+
+ /* Make sure geoip_free_all() works. */
+ geoip_free_all();
+ tt_int_op(1, OP_EQ, geoip_get_n_countries());
+ tt_str_op("??", OP_EQ, geoip_get_country_name(0));
+ tor_inet_pton(AF_INET6, "::1:2:3:4", &iaddr6);
+ tt_int_op(-1, OP_EQ, geoip_get_country_by_ipv6(&iaddr6));
+ tt_str_op("0000000000000000000000000000000000000000", OP_EQ,
+ geoip_db_digest(AF_INET6));
+
+ done:
+ tor_free(contents);
+ tor_free(dhex);
+}
+
+static void
+test_geoip_load_2nd_file(void *arg)
+{
+ (void)arg;
+
+ /* Load 1st geoip file */
+ const char FNAME[] = SRCDIR "/src/config/geoip";
+ tt_int_op(0, OP_EQ, geoip_load_file(AF_INET, FNAME));
+
+ /* Load 2nd geoip (empty) file */
+ /* It has to be the same IP address family */
+ const char FNAME2[] = SRCDIR "/src/test/geoip_dummy";
+ tt_int_op(0, OP_EQ, geoip_load_file(AF_INET, FNAME2));
+
+ /* Check that there is no geoip information for 8.8.8.8, */
+ /* since loading the empty 2nd file should have delete it. */
+ int country = geoip_get_country_by_ipv4(0x08080808);
+ tt_int_op(country, OP_EQ, 0);
+
+ done: ;
+}
+
#define ENT(name) \
{ #name, test_ ## name , 0, NULL, NULL }
#define FORK(name) \
@@ -459,6 +539,10 @@ struct testcase_t geoip_tests[] = {
{ "geoip", test_geoip, TT_FORK, NULL, NULL },
{ "geoip_with_pt", test_geoip_with_pt, TT_FORK, NULL, NULL },
{ "load_file", test_geoip_load_file, TT_FORK|SKIP_ON_WINDOWS, NULL, NULL },
+ { "load_file6", test_geoip6_load_file, TT_FORK | SKIP_ON_WINDOWS,
+ NULL, NULL },
+ { "load_2nd_file", test_geoip_load_2nd_file, TT_FORK | SKIP_ON_WINDOWS,
+ NULL, NULL },
END_OF_TESTCASES
};
diff --git a/src/test/test_options.c b/src/test/test_options.c
index 9974ed2575..65564f324c 100644
--- a/src/test/test_options.c
+++ b/src/test/test_options.c
@@ -2067,12 +2067,12 @@ test_options_validate__testing(void *ignored)
ENSURE_DEFAULT(TestingV3AuthVotingStartOffset, 3000);
ENSURE_DEFAULT(TestingAuthDirTimeToLearnReachability, 3000);
ENSURE_DEFAULT(TestingEstimatedDescriptorPropagationTime, 3000);
- ENSURE_DEFAULT(TestingServerDownloadSchedule, 3000);
- ENSURE_DEFAULT(TestingClientDownloadSchedule, 3000);
- ENSURE_DEFAULT(TestingServerConsensusDownloadSchedule, 3000);
- ENSURE_DEFAULT(TestingClientConsensusDownloadSchedule, 3000);
- ENSURE_DEFAULT(TestingBridgeDownloadSchedule, 3000);
- ENSURE_DEFAULT(TestingBridgeBootstrapDownloadSchedule, 3000);
+ ENSURE_DEFAULT(TestingServerDownloadInitialDelay, 3000);
+ ENSURE_DEFAULT(TestingClientDownloadInitialDelay, 3000);
+ ENSURE_DEFAULT(TestingServerConsensusDownloadInitialDelay, 3000);
+ ENSURE_DEFAULT(TestingClientConsensusDownloadInitialDelay, 3000);
+ ENSURE_DEFAULT(TestingBridgeDownloadInitialDelay, 3000);
+ ENSURE_DEFAULT(TestingBridgeBootstrapDownloadInitialDelay, 3000);
ENSURE_DEFAULT(TestingClientMaxIntervalWithoutRequest, 3000);
ENSURE_DEFAULT(TestingDirConnectionMaxStall, 3000);
ENSURE_DEFAULT(TestingAuthKeyLifetime, 3000);
diff --git a/src/test/test_periodic_event.c b/src/test/test_periodic_event.c
index 1a9f4351ea..74e799360e 100644
--- a/src/test/test_periodic_event.c
+++ b/src/test/test_periodic_event.c
@@ -16,6 +16,7 @@
#include "or.h"
#include "config.h"
+#include "hibernate.h"
#include "hs_service.h"
#include "main.h"
#include "periodic.h"
@@ -68,12 +69,15 @@ test_pe_initialize(void *arg)
static void
test_pe_launch(void *arg)
{
- hs_service_t service;
+ hs_service_t service, *to_remove = NULL;
or_options_t *options;
(void) arg;
hs_init();
+ /* We need to put tor in hibernation live state so the events requiring
+ * network gets enabled. */
+ consider_hibernation(time(NULL));
/* Hack: We'll set a dumb fn() of each events so they don't get called when
* dispatching them. We just want to test the state of the callbacks, not
@@ -148,8 +152,11 @@ test_pe_launch(void *arg)
options->V3AuthoritativeDir = 1; options->BridgeAuthoritativeDir = 1;
register_dummy_hidden_service(&service);
periodic_events_on_new_options(options);
- /* Remove it now so the hs_free_all() doesn't try to free stack memory. */
- remove_service(get_hs_service_map(), &service);
+ /* Note down the reference because we need to remove this service from the
+ * global list before the hs_free_all() call so it doesn't try to free
+ * memory on the stack. Furthermore, we can't remove it now else it will
+ * trigger a rescan of the event disabling the HS service event. */
+ to_remove = &service;
for (int i = 0; periodic_events[i].name; ++i) {
periodic_event_item_t *item = &periodic_events[i];
@@ -157,6 +164,9 @@ test_pe_launch(void *arg)
}
done:
+ if (to_remove) {
+ remove_service(get_hs_service_map(), to_remove);
+ }
hs_free_all();
}
@@ -243,6 +253,62 @@ test_pe_get_roles(void *arg)
hs_free_all();
}
+static void
+test_pe_hs_service(void *arg)
+{
+ hs_service_t service, *to_remove = NULL;
+
+ (void) arg;
+
+ hs_init();
+ /* We need to put tor in hibernation live state so the events requiring
+ * network gets enabled. */
+ consider_hibernation(time(NULL));
+ /* Initialize the events so we can enable them */
+ initialize_periodic_events();
+
+ /* Hack: We'll set a dumb fn() of each events so they don't get called when
+ * dispatching them. We just want to test the state of the callbacks, not
+ * the whole code path. */
+ for (int i = 0; periodic_events[i].name; ++i) {
+ periodic_event_item_t *item = &periodic_events[i];
+ item->fn = dumb_event_fn;
+ }
+
+ /* This should trigger a rescan of the list and enable the HS service
+ * events. */
+ register_dummy_hidden_service(&service);
+ /* Note down the reference because we need to remove this service from the
+ * global list before the hs_free_all() call so it doesn't try to free
+ * memory on the stack. Furthermore, we can't remove it now else it will
+ * trigger a rescan of the event disabling the HS service event. */
+ to_remove = &service;
+
+ for (int i = 0; periodic_events[i].name; ++i) {
+ periodic_event_item_t *item = &periodic_events[i];
+ if (item->roles & PERIODIC_EVENT_ROLE_HS_SERVICE) {
+ tt_int_op(periodic_event_is_enabled(item), OP_EQ, 1);
+ }
+ }
+ to_remove = NULL;
+
+ /* Remove the service from the global map, it should trigger a rescan and
+ * disable the HS service events. */
+ remove_service(get_hs_service_map(), &service);
+ for (int i = 0; periodic_events[i].name; ++i) {
+ periodic_event_item_t *item = &periodic_events[i];
+ if (item->roles & PERIODIC_EVENT_ROLE_HS_SERVICE) {
+ tt_int_op(periodic_event_is_enabled(item), OP_EQ, 0);
+ }
+ }
+
+ done:
+ if (to_remove) {
+ remove_service(get_hs_service_map(), to_remove);
+ }
+ hs_free_all();
+}
+
#define PE_TEST(name) \
{ #name, test_pe_## name , TT_FORK, NULL, NULL }
@@ -250,6 +316,7 @@ struct testcase_t periodic_event_tests[] = {
PE_TEST(initialize),
PE_TEST(launch),
PE_TEST(get_roles),
+ PE_TEST(hs_service),
END_OF_TESTCASES
};
diff --git a/src/test/test_tortls.c b/src/test/test_tortls.c
index 29f7cc9c37..ef1be139a6 100644
--- a/src/test/test_tortls.c
+++ b/src/test/test_tortls.c
@@ -203,6 +203,17 @@ test_tortls_tor_tls_get_error(void *data)
}
static void
+library_init(void)
+{
+#if OPENSSL_VERSION_NUMBER >= OPENSSL_V_SERIES(1,1,0)
+ OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS, NULL);
+#else
+ SSL_library_init();
+ SSL_load_error_strings();
+#endif
+}
+
+static void
test_tortls_get_state_description(void *ignored)
{
(void)ignored;
@@ -210,9 +221,7 @@ test_tortls_get_state_description(void *ignored)
char *buf;
SSL_CTX *ctx;
- SSL_library_init();
- SSL_load_error_strings();
-
+ library_init();
ctx = SSL_CTX_new(SSLv23_method());
buf = tor_malloc_zero(1000);
@@ -274,8 +283,7 @@ test_tortls_get_by_ssl(void *ignored)
SSL_CTX *ctx;
SSL *ssl;
- SSL_library_init();
- SSL_load_error_strings();
+ library_init();
tor_tls_allocate_tor_tls_object_ex_data_index();
ctx = SSL_CTX_new(SSLv23_method());
@@ -322,8 +330,7 @@ test_tortls_log_one_error(void *ignored)
SSL_CTX *ctx;
SSL *ssl = NULL;
- SSL_library_init();
- SSL_load_error_strings();
+ library_init();
ctx = SSL_CTX_new(SSLv23_method());
tls = tor_malloc_zero(sizeof(tor_tls_t));
@@ -415,8 +422,7 @@ test_tortls_get_error(void *ignored)
int ret;
SSL_CTX *ctx;
- SSL_library_init();
- SSL_load_error_strings();
+ library_init();
ctx = SSL_CTX_new(SSLv23_method());
setup_capture_of_logs(LOG_INFO);
@@ -792,8 +798,8 @@ test_tortls_classify_client_ciphers(void *ignored)
STACK_OF(SSL_CIPHER) *ciphers;
SSL_CIPHER *tmp_cipher;
- SSL_library_init();
- SSL_load_error_strings();
+ library_init();
+
tor_tls_allocate_tor_tls_object_ex_data_index();
tls = tor_malloc_zero(sizeof(tor_tls_t));
@@ -897,8 +903,7 @@ test_tortls_client_is_using_v2_ciphers(void *ignored)
SSL_SESSION *sess;
STACK_OF(SSL_CIPHER) *ciphers;
- SSL_library_init();
- SSL_load_error_strings();
+ library_init();
ctx = SSL_CTX_new(TLSv1_method());
ssl = SSL_new(ctx);
@@ -1541,8 +1546,8 @@ test_tortls_session_secret_cb(void *ignored)
STACK_OF(SSL_CIPHER) *ciphers = NULL;
SSL_CIPHER *one;
- SSL_library_init();
- SSL_load_error_strings();
+ library_init();
+
tor_tls_allocate_tor_tls_object_ex_data_index();
tls = tor_malloc_zero(sizeof(tor_tls_t));
@@ -1733,8 +1738,7 @@ test_tortls_find_cipher_by_id(void *ignored)
fixed_cipher2 = tor_malloc_zero(sizeof(SSL_CIPHER));
fixed_cipher2->id = 0xC00A;
- SSL_library_init();
- SSL_load_error_strings();
+ library_init();
ctx = SSL_CTX_new(m);
ssl = SSL_new(ctx);
@@ -1825,8 +1829,7 @@ test_tortls_server_info_callback(void *ignored)
SSL_CTX *ctx;
SSL *ssl;
- SSL_library_init();
- SSL_load_error_strings();
+ library_init();
ctx = SSL_CTX_new(TLSv1_method());
ssl = SSL_new(ctx);
diff --git a/src/test/testing_common.c b/src/test/testing_common.c
index b9b36d96d0..312c07471d 100644
--- a/src/test/testing_common.c
+++ b/src/test/testing_common.c
@@ -8,6 +8,7 @@
* \brief Common pieces to implement unit tests.
**/
+#define MAIN_PRIVATE
#include "orconfig.h"
#include "or.h"
#include "control.h"
@@ -16,6 +17,7 @@
#include "backtrace.h"
#include "test.h"
#include "channelpadding.h"
+#include "main.h"
#include <stdio.h>
#ifdef HAVE_FCNTL_H
@@ -290,6 +292,7 @@ main(int c, const char **v)
}
rep_hist_init();
setup_directory();
+ initialize_mainloop_events();
options_init(options);
options->DataDirectory = tor_strdup(temp_dir);
tor_asprintf(&options->KeyDirectory, "%s"PATH_SEPARATOR"keys",