[tor-commits] [tor/master] Lower dir fetch retry schedules in testing networks.

nickm at torproject.org nickm at torproject.org
Tue May 28 15:03:19 UTC 2013


commit 1293835440dd4debf6fbfc66e755d9b9384aa362
Author: Karsten Loesing <karsten.loesing at gmx.net>
Date:   Thu May 16 12:08:48 2013 +0200

    Lower dir fetch retry schedules in testing networks.
    
    Also lower maximum interval without directory requests, and raise
    maximum download tries.
    
    Implements #6752.
---
 changes/bug6752        |    5 ++
 doc/tor.1.txt          |   61 ++++++++++++++++++
 src/common/container.c |   19 ++++++
 src/common/container.h |    1 +
 src/or/config.c        |  163 ++++++++++++++++++++++++++++++++++++++++++++----
 src/or/confparse.c     |   56 +++++++++++++++++
 src/or/confparse.h     |    3 +
 src/or/directory.c     |   80 +++++++-----------------
 src/or/main.c          |    8 +--
 src/or/microdesc.c     |    2 +-
 src/or/networkstatus.c |    4 +-
 src/or/or.h            |   53 +++++++++++++---
 src/or/routerlist.c    |   19 ++----
 13 files changed, 375 insertions(+), 99 deletions(-)

diff --git a/changes/bug6752 b/changes/bug6752
new file mode 100644
index 0000000..8d620d5
--- /dev/null
+++ b/changes/bug6752
@@ -0,0 +1,5 @@
+ o Minor features:
+   - Lower directory fetch retry schedules and maximum interval without
+     directory requests, and raise maximum download tries in testing
+     networks. Implements #6752.
+
diff --git a/doc/tor.1.txt b/doc/tor.1.txt
index 0a6f8f5..5785b38 100644
--- a/doc/tor.1.txt
+++ b/doc/tor.1.txt
@@ -2005,6 +2005,17 @@ 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 60, 30, 30, 60
+       TestingClientMaxIntervalWithoutRequest 5 seconds
+       TestingDirConnectionMaxStall 30 seconds
+       TestingConsensusMaxDownloadTries 80
+       TestingDescriptorMaxDownloadTries 80
+       TestingMicrodescMaxDownloadTries 80
+       TestingCertMaxDownloadTries 80
 
 **TestingV3AuthInitialVotingInterval** __N__ **minutes**|**hours**::
     Like V3AuthVotingInterval, but for initial voting interval before the first
@@ -2035,6 +2046,56 @@ 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** __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)
+
+**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)
+
+**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)
+
+**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)
+
+**TestingBridgeDownloadSchedule** __N__,__N__,__...__::
+    Schedule for when clients should download bridge descriptors. Changing this
+    requires that **TestingTorNetwork** is set. (Default: 3600, 900, 900, 3600)
+
+**TestingClientMaxIntervalWithoutRequest** __N__ **seconds**|**minutes**::
+    When directory clients have only a few descriptors to request, they batch
+    them until they have more, or until this amount of time has passed.
+    Changing this requires that **TestingTorNetwork** is set. (Default: 10
+    minutes)
+
+**TestingDirConnectionMaxStall** __N__ **seconds**|**minutes**::
+    Let a directory connection stall this long before expiring it.
+    Changing this requires that **TestingTorNetwork** is set. (Default:
+    5 minutes)
+
+**TestingConsensusMaxDownloadTries** __NUM__::
+    Try this often to download a consensus before giving up. Changing
+    this requires that **TestingTorNetwork** is set. (Default: 8)
+
+**TestingDescriptorMaxDownloadTries** __NUM__::
+    Try this often to download a router descriptor before giving up.
+    Changing this requires that **TestingTorNetwork** is set. (Default: 8)
+
+**TestingMicrodescMaxDownloadTries** __NUM__::
+    Try this often to download a microdesc descriptor before giving up.
+    Changing this requires that **TestingTorNetwork** is set. (Default: 8)
+
+**TestingCertMaxDownloadTries** __NUM__::
+    Try this often to download a v3 authority certificate before giving up.
+    Changing this requires that **TestingTorNetwork** is set. (Default: 8)
 
 SIGNALS
 -------
diff --git a/src/common/container.c b/src/common/container.c
index eec497a..03c65b7 100644
--- a/src/common/container.c
+++ b/src/common/container.c
@@ -243,6 +243,25 @@ smartlist_strings_eq(const smartlist_t *sl1, const smartlist_t *sl2)
   return 1;
 }
 
+/** Return true iff the two lists contain the same ints in the same order,
+ * or if they are both NULL. */
+int
+smartlist_ints_eq(const smartlist_t *sl1, const smartlist_t *sl2)
+{
+  if (sl1 == NULL)
+    return sl2 == NULL;
+  if (sl2 == NULL)
+    return 0;
+  if (smartlist_len(sl1) != smartlist_len(sl2))
+    return 0;
+  SMARTLIST_FOREACH(sl1, int *, cp1, {
+      int *cp2 = smartlist_get(sl2, cp1_sl_idx);
+      if (*cp1 != *cp2)
+        return 0;
+    });
+  return 1;
+}
+
 /** Return true iff <b>sl</b> has some element E such that
  * tor_memeq(E,<b>element</b>,DIGEST_LEN)
  */
diff --git a/src/common/container.h b/src/common/container.h
index 1a68b8f..1bcc540 100644
--- a/src/common/container.h
+++ b/src/common/container.h
@@ -42,6 +42,7 @@ int smartlist_contains_string_case(const smartlist_t *sl, const char *element);
 int smartlist_contains_int_as_string(const smartlist_t *sl, int num);
 int smartlist_strings_eq(const smartlist_t *sl1, const smartlist_t *sl2);
 int smartlist_contains_digest(const smartlist_t *sl, const char *element);
+int smartlist_ints_eq(const smartlist_t *sl1, const smartlist_t *sl2);
 int smartlist_overlap(const smartlist_t *sl1, const smartlist_t *sl2);
 void smartlist_intersect(smartlist_t *sl1, const smartlist_t *sl2);
 void smartlist_subtract(smartlist_t *sl1, const smartlist_t *sl2);
diff --git a/src/or/config.c b/src/or/config.c
index 8ca89b6..5809937 100644
--- a/src/or/config.c
+++ b/src/or/config.c
@@ -433,6 +433,23 @@ static config_var_t option_vars_[] = {
   VAR("__OwningControllerProcess",STRING,OwningControllerProcess, NULL),
   V(MinUptimeHidServDirectoryV2, INTERVAL, "25 hours"),
   V(VoteOnHidServDirectoriesV2,  BOOL,     "1"),
+  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(TestingBridgeDownloadSchedule, CSV_INTERVAL, "3600, 900, 900, 3600"),
+  V(TestingClientMaxIntervalWithoutRequest, INTERVAL, "10 minutes"),
+  V(TestingDirConnectionMaxStall, INTERVAL, "5 minutes"),
+  V(TestingConsensusMaxDownloadTries, UINT, "8"),
+  V(TestingDescriptorMaxDownloadTries, UINT, "8"),
+  V(TestingMicrodescMaxDownloadTries, UINT, "8"),
+  V(TestingCertMaxDownloadTries, UINT, "8"),
   VAR("___UsingTestNetworkDefaults", BOOL, UsingTestNetworkDefaults_, "0"),
 
   { NULL, CONFIG_TYPE_OBSOLETE, 0, NULL }
@@ -461,6 +478,21 @@ 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, "60, 30, 30, 60"),
+  V(TestingClientMaxIntervalWithoutRequest, INTERVAL, "5 seconds"),
+  V(TestingDirConnectionMaxStall, INTERVAL, "30 seconds"),
+  V(TestingConsensusMaxDownloadTries, UINT, "80"),
+  V(TestingDescriptorMaxDownloadTries, UINT, "80"),
+  V(TestingMicrodescMaxDownloadTries, UINT, "80"),
+  V(TestingCertMaxDownloadTries, UINT, "80"),
   VAR("___UsingTestNetworkDefaults", BOOL, UsingTestNetworkDefaults_, "1"),
 
   { NULL, CONFIG_TYPE_OBSOLETE, 0, NULL }
@@ -475,6 +507,7 @@ static char *get_windows_conf_root(void);
 #endif
 static int options_validate(or_options_t *old_options,
                             or_options_t *options,
+                            or_options_t *default_options,
                             int from_setconf, char **msg);
 static int options_act_reversible(const or_options_t *old_options, char **msg);
 static int options_act(const or_options_t *old_options);
@@ -1851,7 +1884,8 @@ options_trial_assign(config_line_t *list, int use_defaults,
     return r;
   }
 
-  if (options_validate(get_options_mutable(), trial_options, 1, msg) < 0) {
+  if (options_validate(get_options_mutable(), trial_options,
+                       global_default_options, 1, msg) < 0) {
     config_free(&options_format, trial_options);
     return SETOPT_ERR_PARSE; /*XXX make this a separate return value. */
   }
@@ -2295,7 +2329,7 @@ compute_publishserverdescriptor(or_options_t *options)
  */
 static int
 options_validate(or_options_t *old_options, or_options_t *options,
-                 int from_setconf, char **msg)
+                 or_options_t *default_options, int from_setconf, char **msg)
 {
   int i;
   config_line_t *cl;
@@ -3177,11 +3211,8 @@ options_validate(or_options_t *old_options, or_options_t *options,
              "ignore you.");
   }
 
-  /*XXXX checking for defaults manually like this is a bit fragile.*/
-
-  /* Keep changes to hard-coded values synchronous to man page and default
-   * values table. */
-  if (options->TestingV3AuthInitialVotingInterval != 30*60 &&
+  if (default_options->TestingV3AuthInitialVotingInterval !=
+              options->TestingV3AuthInitialVotingInterval &&
       !options->TestingTorNetwork && !options->UsingTestNetworkDefaults_) {
     REJECT("TestingV3AuthInitialVotingInterval may only be changed in testing "
            "Tor networks!");
@@ -3192,16 +3223,17 @@ options_validate(or_options_t *old_options, or_options_t *options,
            "30 minutes.");
   }
 
-  if (options->TestingV3AuthInitialVoteDelay != 5*60 &&
+  if (default_options->TestingV3AuthInitialVoteDelay !=
+              options->TestingV3AuthInitialVoteDelay &&
       !options->TestingTorNetwork && !options->UsingTestNetworkDefaults_) {
-
     REJECT("TestingV3AuthInitialVoteDelay may only be changed in testing "
            "Tor networks!");
   } else if (options->TestingV3AuthInitialVoteDelay < MIN_VOTE_SECONDS) {
     REJECT("TestingV3AuthInitialVoteDelay is way too low.");
   }
 
-  if (options->TestingV3AuthInitialDistDelay != 5*60 &&
+  if (default_options->TestingV3AuthInitialDistDelay !=
+              options->TestingV3AuthInitialDistDelay &&
       !options->TestingTorNetwork && !options->UsingTestNetworkDefaults_) {
     REJECT("TestingV3AuthInitialDistDelay may only be changed in testing "
            "Tor networks!");
@@ -3216,7 +3248,8 @@ options_validate(or_options_t *old_options, or_options_t *options,
            "must be less than half TestingV3AuthInitialVotingInterval");
   }
 
-  if (options->TestingAuthDirTimeToLearnReachability != 30*60 &&
+  if (default_options->TestingAuthDirTimeToLearnReachability !=
+              options->TestingAuthDirTimeToLearnReachability &&
       !options->TestingTorNetwork && !options->UsingTestNetworkDefaults_) {
     REJECT("TestingAuthDirTimeToLearnReachability may only be changed in "
            "testing Tor networks!");
@@ -3226,7 +3259,8 @@ options_validate(or_options_t *old_options, or_options_t *options,
     COMPLAIN("TestingAuthDirTimeToLearnReachability is insanely high.");
   }
 
-  if (options->TestingEstimatedDescriptorPropagationTime != 10*60 &&
+  if (default_options->TestingEstimatedDescriptorPropagationTime !=
+              options->TestingEstimatedDescriptorPropagationTime &&
       !options->TestingTorNetwork && !options->UsingTestNetworkDefaults_) {
     REJECT("TestingEstimatedDescriptorPropagationTime may only be changed in "
            "testing Tor networks!");
@@ -3236,6 +3270,107 @@ options_validate(or_options_t *old_options, or_options_t *options,
     COMPLAIN("TestingEstimatedDescriptorPropagationTime is insanely high.");
   }
 
+  if (!smartlist_ints_eq(options->TestingServerDownloadSchedule,
+                 default_options->TestingServerDownloadSchedule) &&
+      !options->TestingTorNetwork && !options->UsingTestNetworkDefaults_) {
+    REJECT("TestingServerDownloadSchedule may only be changed in testing "
+           "Tor networks!");
+  }
+
+  if (!smartlist_ints_eq(options->TestingClientDownloadSchedule,
+                 default_options->TestingClientDownloadSchedule) &&
+      !options->TestingTorNetwork && !options->UsingTestNetworkDefaults_) {
+    REJECT("TestingClientDownloadSchedule may only be changed in testing "
+           "Tor networks!");
+  }
+
+  if (!smartlist_ints_eq(options->TestingServerConsensusDownloadSchedule,
+                 default_options->TestingServerConsensusDownloadSchedule) &&
+      !options->TestingTorNetwork && !options->UsingTestNetworkDefaults_) {
+    REJECT("TestingServerConsensusDownloadSchedule may only be changed "
+           "in testing Tor networks!");
+  }
+
+  if (!smartlist_ints_eq(options->TestingClientConsensusDownloadSchedule,
+                 default_options->TestingClientConsensusDownloadSchedule) &&
+      !options->TestingTorNetwork && !options->UsingTestNetworkDefaults_) {
+    REJECT("TestingClientConsensusDownloadSchedule may only be changed "
+           "in testing Tor networks!");
+  }
+
+  if (!smartlist_ints_eq(options->TestingBridgeDownloadSchedule,
+                 default_options->TestingBridgeDownloadSchedule) &&
+      !options->TestingTorNetwork && !options->UsingTestNetworkDefaults_) {
+    REJECT("TestingBridgeDownloadSchedule may only be changed in testing "
+           "Tor networks!");
+  }
+
+  if (default_options->TestingClientMaxIntervalWithoutRequest !=
+              options->TestingClientMaxIntervalWithoutRequest &&
+      !options->TestingTorNetwork && !options->UsingTestNetworkDefaults_) {
+    REJECT("TestingClientMaxIntervalWithoutRequest may only be changed "
+           "in testing Tor networks!");
+  } else if (options->TestingClientMaxIntervalWithoutRequest < 1) {
+    REJECT("TestingClientMaxIntervalWithoutRequest is way too low.");
+  } else if (options->TestingClientMaxIntervalWithoutRequest > 3600) {
+    COMPLAIN("TestingClientMaxIntervalWithoutRequest is insanely high.");
+  }
+
+  if (default_options->TestingDirConnectionMaxStall !=
+              options->TestingDirConnectionMaxStall &&
+      !options->TestingTorNetwork && !options->UsingTestNetworkDefaults_) {
+    REJECT("TestingDirConnectionMaxStall may only be changed in testing "
+           "Tor networks!");
+  } else if (options->TestingDirConnectionMaxStall < 5) {
+    REJECT("TestingDirConnectionMaxStall is way too low.");
+  } else if (options->TestingDirConnectionMaxStall > 3600) {
+    COMPLAIN("TestingDirConnectionMaxStall is insanely high.");
+  }
+
+  if (default_options->TestingConsensusMaxDownloadTries !=
+              options->TestingConsensusMaxDownloadTries &&
+      !options->TestingTorNetwork && !options->UsingTestNetworkDefaults_) {
+    REJECT("TestingConsensusMaxDownloadTries may only be changed in "
+           "testing Tor networks!");
+  } else if (options->TestingConsensusMaxDownloadTries < 2) {
+    REJECT("TestingConsensusMaxDownloadTries must be greater than 1.");
+  } else if (options->TestingConsensusMaxDownloadTries > 800) {
+    COMPLAIN("TestingConsensusMaxDownloadTries is insanely high.");
+  }
+
+  if (default_options->TestingDescriptorMaxDownloadTries !=
+              options->TestingDescriptorMaxDownloadTries &&
+      !options->TestingTorNetwork && !options->UsingTestNetworkDefaults_) {
+    REJECT("TestingDescriptorMaxDownloadTries may only be changed in "
+           "testing Tor networks!");
+  } else if (options->TestingDescriptorMaxDownloadTries < 2) {
+    REJECT("TestingDescriptorMaxDownloadTries must be greater than 1.");
+  } else if (options->TestingDescriptorMaxDownloadTries > 800) {
+    COMPLAIN("TestingDescriptorMaxDownloadTries is insanely high.");
+  }
+
+  if (default_options->TestingMicrodescMaxDownloadTries !=
+              options->TestingMicrodescMaxDownloadTries &&
+      !options->TestingTorNetwork && !options->UsingTestNetworkDefaults_) {
+    REJECT("TestingMicrodescMaxDownloadTries may only be changed in "
+           "testing Tor networks!");
+  } else if (options->TestingMicrodescMaxDownloadTries < 2) {
+    REJECT("TestingMicrodescMaxDownloadTries must be greater than 1.");
+  } else if (options->TestingMicrodescMaxDownloadTries > 800) {
+    COMPLAIN("TestingMicrodescMaxDownloadTries is insanely high.");
+  }
+
+  if (default_options->TestingCertMaxDownloadTries !=
+              options->TestingCertMaxDownloadTries &&
+      !options->TestingTorNetwork && !options->UsingTestNetworkDefaults_) {
+    REJECT("TestingCertMaxDownloadTries may only be changed in testing "
+           "Tor networks!");
+  } else if (options->TestingCertMaxDownloadTries < 2) {
+    REJECT("TestingCertMaxDownloadTries must be greater than 1.");
+  } else if (options->TestingCertMaxDownloadTries > 800) {
+    COMPLAIN("TestingCertMaxDownloadTries is insanely high.");
+  }
+
   if (options->TestingTorNetwork) {
     log_warn(LD_CONFIG, "TestingTorNetwork is set. This will make your node "
                         "almost unusable in the public Tor network, and is "
@@ -3850,7 +3985,8 @@ options_init_from_string(const char *cf_defaults, const char *cf,
   }
 
   /* Validate newoptions */
-  if (options_validate(oldoptions, newoptions, 0, msg) < 0) {
+  if (options_validate(oldoptions, newoptions, newdefaultoptions,
+                       0, msg) < 0) {
     err = SETOPT_ERR_PARSE; /*XXX make this a separate return value.*/
     goto err;
   }
@@ -6050,6 +6186,7 @@ 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;
         case CONFIG_TYPE_LINELIST: type = "LineList"; break;
         case CONFIG_TYPE_LINELIST_S: type = "Dependant"; break;
         case CONFIG_TYPE_LINELIST_V: type = "Virtual"; break;
diff --git a/src/or/confparse.c b/src/or/confparse.c
index 8863d92..8607f58 100644
--- a/src/or/confparse.c
+++ b/src/or/confparse.c
@@ -223,6 +223,8 @@ 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);
 
@@ -357,6 +359,36 @@ 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_clear(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_clear(csv_str);
+    break;
+
   case CONFIG_TYPE_LINELIST:
   case CONFIG_TYPE_LINELIST_S:
     {
@@ -555,6 +587,8 @@ 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;
+  char *s;
   tor_assert(options && key);
 
   CONFIG_CHECK(fmt, options);
@@ -637,6 +671,21 @@ 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)
+          {
+            tor_asprintf(&s, "%d", *i);
+            smartlist_add(csv_str, s);
+          }
+        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'.",
@@ -826,6 +875,13 @@ 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 1b987f3..d82e109 100644
--- a/src/or/confparse.h
+++ b/src/or/confparse.h
@@ -26,6 +26,9 @@ typedef enum config_type_t {
   CONFIG_TYPE_ISOTIME,      /**< An ISO-formatted time relative to UTC. */
   CONFIG_TYPE_CSV,          /**< A list of strings, separated by commas and
                               * optional whitespace. */
+  CONFIG_TYPE_CSV_INTERVAL, /**< A list of strings, separated by commas and
+                              * optional whitespace, representing intervals in
+                              * seconds, with optional units */
   CONFIG_TYPE_LINELIST,     /**< Uninterpreted config lines */
   CONFIG_TYPE_LINELIST_S,   /**< Uninterpreted, context-sensitive config lines,
                              * mixed with other keywords. */
diff --git a/src/or/directory.c b/src/or/directory.c
index b4381ac..caf8a55 100644
--- a/src/or/directory.c
+++ b/src/or/directory.c
@@ -3723,57 +3723,25 @@ dir_networkstatus_download_failed(smartlist_t *failed, int status_code)
   } SMARTLIST_FOREACH_END(fp);
 }
 
-/** Schedule for when servers should download things in general. */
-static const int server_dl_schedule[] = {
-  0, 0, 0, 60, 60, 60*2, 60*5, 60*15, INT_MAX
-};
-/** Schedule for when clients should download things in general. */
-static const int client_dl_schedule[] = {
-  0, 0, 60, 60*5, 60*10, INT_MAX
-};
-/** Schedule for when servers should download consensuses. */
-static const int server_consensus_dl_schedule[] = {
-  0, 0, 60, 60*5, 60*10, 60*30, 60*30, 60*30, 60*30, 60*30, 60*60, 60*60*2
-};
-/** Schedule for when clients should download consensuses. */
-static const int client_consensus_dl_schedule[] = {
-  0, 0, 60, 60*5, 60*10, 60*30, 60*60, 60*60, 60*60, 60*60*3, 60*60*6, 60*60*12
-};
-/** Schedule for when clients should download bridge descriptors. */
-static const int bridge_dl_schedule[] = {
-  60*60, 15*60, 15*60, 60*60
-};
-
 /** Decide which download schedule we want to use, and then return a
  * pointer to it along with a pointer to its length. Helper function for
  * download_status_increment_failure() and download_status_reset(). */
-static void
-find_dl_schedule_and_len(download_status_t *dls, int server,
-                         const int **schedule, size_t *schedule_len)
+static smartlist_t *
+find_dl_schedule_and_len(download_status_t *dls, int server)
 {
   switch (dls->schedule) {
     case DL_SCHED_GENERIC:
-      if (server) {
-        *schedule = server_dl_schedule;
-        *schedule_len = sizeof(server_dl_schedule)/sizeof(int);
-      } else {
-        *schedule = client_dl_schedule;
-        *schedule_len = sizeof(client_dl_schedule)/sizeof(int);
-      }
-      break;
+      if (server)
+        return get_options()->TestingServerDownloadSchedule;
+      else
+        return get_options()->TestingClientDownloadSchedule;
     case DL_SCHED_CONSENSUS:
-      if (server) {
-        *schedule = server_consensus_dl_schedule;
-        *schedule_len = sizeof(server_consensus_dl_schedule)/sizeof(int);
-      } else {
-        *schedule = client_consensus_dl_schedule;
-        *schedule_len = sizeof(client_consensus_dl_schedule)/sizeof(int);
-      }
-      break;
+      if (server)
+        return get_options()->TestingServerConsensusDownloadSchedule;
+      else
+        return get_options()->TestingClientConsensusDownloadSchedule;
     case DL_SCHED_BRIDGE:
-      *schedule = bridge_dl_schedule;
-      *schedule_len = sizeof(bridge_dl_schedule)/sizeof(int);
-      break;
+      return get_options()->TestingBridgeDownloadSchedule;
     default:
       tor_assert(0);
   }
@@ -3787,8 +3755,7 @@ time_t
 download_status_increment_failure(download_status_t *dls, int status_code,
                                   const char *item, int server, time_t now)
 {
-  const int *schedule;
-  size_t schedule_len;
+  smartlist_t *schedule;
   int increment;
   tor_assert(dls);
   if (status_code != 503 || server) {
@@ -3796,14 +3763,14 @@ download_status_increment_failure(download_status_t *dls, int status_code,
       ++dls->n_download_failures;
   }
 
-  find_dl_schedule_and_len(dls, server, &schedule, &schedule_len);
+  schedule = find_dl_schedule_and_len(dls, server);
 
-  if (dls->n_download_failures < schedule_len)
-    increment = schedule[dls->n_download_failures];
+  if (dls->n_download_failures < smartlist_len(schedule))
+    increment = *(int *)smartlist_get(schedule, dls->n_download_failures);
   else if (dls->n_download_failures == IMPOSSIBLE_TO_DOWNLOAD)
     increment = INT_MAX;
   else
-    increment = schedule[schedule_len-1];
+    increment = *(int *)smartlist_get(schedule, smartlist_len(schedule) - 1);
 
   if (increment < INT_MAX)
     dls->next_attempt_at = now+increment;
@@ -3836,14 +3803,11 @@ download_status_increment_failure(download_status_t *dls, int status_code,
 void
 download_status_reset(download_status_t *dls)
 {
-  const int *schedule;
-  size_t schedule_len;
-
-  find_dl_schedule_and_len(dls, get_options()->DirPort_set,
-                           &schedule, &schedule_len);
+  smartlist_t *schedule = find_dl_schedule_and_len(
+                          dls, get_options()->DirPort_set);
 
   dls->n_download_failures = 0;
-  dls->next_attempt_at = time(NULL) + schedule[0];
+  dls->next_attempt_at = time(NULL) + *(int *)smartlist_get(schedule, 0);
 }
 
 /** Return the number of failures on <b>dls</b> since the last success (if
@@ -3888,7 +3852,8 @@ dir_routerdesc_download_failed(smartlist_t *failed, int status_code,
     } else {
       dls = router_get_dl_status_by_descriptor_digest(digest);
     }
-    if (!dls || dls->n_download_failures >= MAX_ROUTERDESC_DOWNLOAD_FAILURES)
+    if (!dls || dls->n_download_failures >=
+                get_options()->TestingDescriptorMaxDownloadTries)
       continue;
     download_status_increment_failure(dls, status_code, cp, server, now);
   } SMARTLIST_FOREACH_END(cp);
@@ -3919,7 +3884,8 @@ dir_microdesc_download_failed(smartlist_t *failed,
     if (!rs)
       continue;
     dls = &rs->dl_status;
-    if (dls->n_download_failures >= MAX_MICRODESC_DOWNLOAD_FAILURES)
+    if (dls->n_download_failures >=
+        get_options()->TestingMicrodescMaxDownloadTries)
       continue;
     {
       char buf[BASE64_DIGEST256_LEN+1];
diff --git a/src/or/main.c b/src/or/main.c
index fd8b6cf..90ffba3 100644
--- a/src/or/main.c
+++ b/src/or/main.c
@@ -155,8 +155,6 @@ int can_complete_circuit=0;
 /** How often do we 'forgive' undownloadable router descriptors and attempt
  * to download them again? */
 #define DESCRIPTOR_FAILURE_RESET_INTERVAL (60*60)
-/** How long do we let a directory connection stall before expiring it? */
-#define DIR_CONN_MAX_STALL (5*60)
 
 /** Decides our behavior when no logs are configured/before any
  * logs have been configured.  For 0, we log notice to stdout as normal.
@@ -1028,9 +1026,11 @@ run_connection_housekeeping(int i, time_t now)
    * if a server or received if a client) for 5 min */
   if (conn->type == CONN_TYPE_DIR &&
       ((DIR_CONN_IS_SERVER(conn) &&
-        conn->timestamp_lastwritten + DIR_CONN_MAX_STALL < now) ||
+        conn->timestamp_lastwritten
+            + options->TestingDirConnectionMaxStall < now) ||
        (!DIR_CONN_IS_SERVER(conn) &&
-        conn->timestamp_lastread + DIR_CONN_MAX_STALL < now))) {
+        conn->timestamp_lastread
+            + options->TestingDirConnectionMaxStall < now))) {
     log_info(LD_DIR,"Expiring wedged directory conn (fd %d, purpose %d)",
              (int)conn->s, conn->purpose);
     /* This check is temporary; it's to let us know whether we should consider
diff --git a/src/or/microdesc.c b/src/or/microdesc.c
index f81501c..143825b 100644
--- a/src/or/microdesc.c
+++ b/src/or/microdesc.c
@@ -662,7 +662,7 @@ microdesc_list_missing_digest256(networkstatus_t *ns, microdesc_cache_t *cache,
       continue;
     if (downloadable_only &&
         !download_status_is_ready(&rs->dl_status, now,
-                                  MAX_MICRODESC_DOWNLOAD_FAILURES))
+                  get_options()->TestingMicrodescMaxDownloadTries))
       continue;
     if (skip && digestmap_get(skip, rs->descriptor_digest))
       continue;
diff --git a/src/or/networkstatus.c b/src/or/networkstatus.c
index 8715841..3f995a9 100644
--- a/src/or/networkstatus.c
+++ b/src/or/networkstatus.c
@@ -1203,8 +1203,6 @@ we_want_to_fetch_flavor(const or_options_t *options, int flavor)
   return flavor == usable_consensus_flavor();
 }
 
-/** How many times will we try to fetch a consensus before we give up? */
-#define CONSENSUS_NETWORKSTATUS_MAX_DL_TRIES 8
 /** How long will we hang onto a possibly live consensus for which we're
  * fetching certs before we check whether there is a better one? */
 #define DELAY_WHILE_FETCHING_CERTS (20*60)
@@ -1238,7 +1236,7 @@ update_consensus_networkstatus_downloads(time_t now)
     resource = networkstatus_get_flavor_name(i);
 
     if (!download_status_is_ready(&consensus_dl_status[i], now,
-                                  CONSENSUS_NETWORKSTATUS_MAX_DL_TRIES))
+                             options->TestingConsensusMaxDownloadTries))
       continue; /* We failed downloading a consensus too recently. */
     if (connection_dir_get_by_purpose_and_resource(
                                 DIR_PURPOSE_FETCH_CONSENSUS, resource))
diff --git a/src/or/or.h b/src/or/or.h
index 7b6c65f..bfb1a43 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -2279,14 +2279,6 @@ typedef struct node_t {
 
 } node_t;
 
-/** How many times will we try to download a router's descriptor before giving
- * up? */
-#define MAX_ROUTERDESC_DOWNLOAD_FAILURES 8
-
-/** How many times will we try to download a microdescriptor before giving
- * up? */
-#define MAX_MICRODESC_DOWNLOAD_FAILURES 8
-
 /** Contents of a v2 (non-consensus, non-vote) network status object. */
 typedef struct networkstatus_v2_t {
   /** When did we receive the network-status document? */
@@ -3915,6 +3907,51 @@ typedef struct {
    * networks. */
   int TestingEstimatedDescriptorPropagationTime;
 
+  /** Schedule for when servers should download things in general.  Only
+   * altered on testing networks. */
+  smartlist_t *TestingServerDownloadSchedule;
+
+  /** Schedule for when clients should download things in general.  Only
+   * altered on testing networks. */
+  smartlist_t *TestingClientDownloadSchedule;
+
+  /** Schedule for when servers should download consensuses.  Only altered
+   * on testing networks. */
+  smartlist_t *TestingServerConsensusDownloadSchedule;
+
+  /** Schedule for when clients should download consensuses.  Only altered
+   * on testing networks. */
+  smartlist_t *TestingClientConsensusDownloadSchedule;
+
+  /** Schedule for when clients should download bridge descriptors.  Only
+   * altered on testing networks. */
+  smartlist_t *TestingBridgeDownloadSchedule;
+
+  /** When directory clients have only a few descriptors to request, they
+   * batch them until they have more, or until this amount of time has
+   * passed.  Only altered on testing networks. */
+  int TestingClientMaxIntervalWithoutRequest;
+
+  /** How long do we let a directory connection stall before expiring
+   * it?  Only altered on testing networks. */
+  int TestingDirConnectionMaxStall;
+
+  /** How many times will we try to fetch a consensus before we give
+   * up?  Only altered on testing networks. */
+  int TestingConsensusMaxDownloadTries;
+
+  /** How many times will we try to download a router's descriptor before
+   * giving up?  Only altered on testing networks. */
+  int TestingDescriptorMaxDownloadTries;
+
+  /** How many times will we try to download a microdescriptor before
+   * giving up?  Only altered on testing networks. */
+  int TestingMicrodescMaxDownloadTries;
+
+  /** How many times will we try to fetch a certificate before giving
+   * up?  Only altered on testing networks. */
+  int TestingCertMaxDownloadTries;
+
   /** If true, we take part in a testing network. Change the defaults of a
    * couple of other configuration options and allow to change the values
    * of certain configuration options. */
diff --git a/src/or/routerlist.c b/src/or/routerlist.c
index e98c126..a145ba7 100644
--- a/src/or/routerlist.c
+++ b/src/or/routerlist.c
@@ -629,9 +629,6 @@ authority_cert_dl_looks_uncertain(const char *id_digest)
   return n_failures >= N_AUTH_CERT_DL_FAILURES_TO_BUG_USER;
 }
 
-/** How many times will we try to fetch a certificate before giving up? */
-#define MAX_CERT_DL_FAILURES 8
-
 /** Try to download any v3 authority certificates that we may be missing.  If
  * <b>status</b> is provided, try to get all the ones that were used to sign
  * <b>status</b>.  Additionally, try to have a non-expired certificate for
@@ -703,7 +700,7 @@ authority_certs_fetch_missing(networkstatus_t *status, time_t now)
     } SMARTLIST_FOREACH_END(cert);
     if (!found &&
         download_status_is_ready(&(cl->dl_status_by_id), now,
-                                 MAX_CERT_DL_FAILURES) &&
+                                 get_options()->TestingCertMaxDownloadTries) &&
         !digestmap_get(pending_id, ds->v3_identity_digest)) {
       log_info(LD_DIR,
                "No current certificate known for authority %s "
@@ -765,7 +762,7 @@ authority_certs_fetch_missing(networkstatus_t *status, time_t now)
         }
         if (download_status_is_ready_by_sk_in_cl(
               cl, sig->signing_key_digest,
-              now, MAX_CERT_DL_FAILURES) &&
+              now, get_options()->TestingCertMaxDownloadTries) &&
             !fp_pair_map_get_by_digests(pending_cert,
                                         voter->identity_digest,
                                         sig->signing_key_digest)) {
@@ -4450,12 +4447,8 @@ initiate_descriptor_downloads(const routerstatus_t *source,
  * try to split our requests into at least this many requests. */
 #define MIN_REQUESTS 3
 /** If we want fewer than this many descriptors, wait until we
- * want more, or until MAX_CLIENT_INTERVAL_WITHOUT_REQUEST has
- * passed. */
+ * want more, or until TestingClientMaxIntervalWithoutRequest has passed. */
 #define MAX_DL_TO_DELAY 16
-/** When directory clients have only a few servers to request, they batch
- * them until they have more, or until this amount of time has passed. */
-#define MAX_CLIENT_INTERVAL_WITHOUT_REQUEST (10*60)
 
 /** Given a <b>purpose</b> (FETCH_MICRODESC or FETCH_SERVERDESC) and a list of
  * router descriptor digests or microdescriptor digest256s in
@@ -4487,7 +4480,7 @@ launch_descriptor_downloads(int purpose,
       should_delay = 0;
     } else {
       should_delay = (last_descriptor_download_attempted +
-                      MAX_CLIENT_INTERVAL_WITHOUT_REQUEST) > now;
+                      options->TestingClientMaxIntervalWithoutRequest) > now;
       if (!should_delay && n_downloadable) {
         if (last_descriptor_download_attempted) {
           log_info(LD_DIR,
@@ -4760,7 +4753,7 @@ update_consensus_router_descriptor_downloads(time_t now, int is_vote,
         continue; /* We have an in-progress download. */
       }
       if (!download_status_is_ready(&rs->dl_status, now,
-                                    MAX_ROUTERDESC_DOWNLOAD_FAILURES)) {
+                          options->TestingDescriptorMaxDownloadTries)) {
         ++n_delayed; /* Not ready for retry. */
         continue;
       }
@@ -4920,7 +4913,7 @@ update_extrainfo_downloads(time_t now)
         continue;
       }
       if (!download_status_is_ready(&sd->ei_dl_status, now,
-                                    MAX_ROUTERDESC_DOWNLOAD_FAILURES)) {
+                          options->TestingDescriptorMaxDownloadTries)) {
         ++n_delay;
         continue;
       }





More information about the tor-commits mailing list