dlstatus.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422
  1. /* Copyright (c) 2001-2004, Roger Dingledine.
  2. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
  3. * Copyright (c) 2007-2019, The Tor Project, Inc. */
  4. /* See LICENSE for licensing information */
  5. #define DLSTATUS_PRIVATE
  6. #include "core/or/or.h"
  7. #include "app/config/config.h"
  8. #include "feature/client/entrynodes.h"
  9. #include "feature/dirclient/dlstatus.h"
  10. #include "feature/nodelist/networkstatus.h"
  11. #include "feature/relay/routermode.h"
  12. #include "lib/crypt_ops/crypto_rand.h"
  13. #include "feature/dirclient/download_status_st.h"
  14. /** Decide which download schedule we want to use based on descriptor type
  15. * in <b>dls</b> and <b>options</b>.
  16. *
  17. * Then, return the initial delay for that download schedule, in seconds.
  18. *
  19. * Helper function for download_status_increment_failure(),
  20. * download_status_reset(), and download_status_increment_attempt(). */
  21. STATIC int
  22. find_dl_min_delay(const download_status_t *dls, const or_options_t *options)
  23. {
  24. tor_assert(dls);
  25. tor_assert(options);
  26. switch (dls->schedule) {
  27. case DL_SCHED_GENERIC:
  28. /* Any other directory document */
  29. if (dir_server_mode(options)) {
  30. /* A directory authority or directory mirror */
  31. return options->TestingServerDownloadInitialDelay;
  32. } else {
  33. return options->TestingClientDownloadInitialDelay;
  34. }
  35. case DL_SCHED_CONSENSUS:
  36. if (!networkstatus_consensus_can_use_multiple_directories(options)) {
  37. /* A public relay */
  38. return options->TestingServerConsensusDownloadInitialDelay;
  39. } else {
  40. /* A client or bridge */
  41. if (networkstatus_consensus_is_bootstrapping(time(NULL))) {
  42. /* During bootstrapping */
  43. if (!networkstatus_consensus_can_use_extra_fallbacks(options)) {
  44. /* A bootstrapping client without extra fallback directories */
  45. return options->
  46. ClientBootstrapConsensusAuthorityOnlyDownloadInitialDelay;
  47. } else if (dls->want_authority) {
  48. /* A bootstrapping client with extra fallback directories, but
  49. * connecting to an authority */
  50. return
  51. options->ClientBootstrapConsensusAuthorityDownloadInitialDelay;
  52. } else {
  53. /* A bootstrapping client connecting to extra fallback directories
  54. */
  55. return
  56. options->ClientBootstrapConsensusFallbackDownloadInitialDelay;
  57. }
  58. } else {
  59. /* A client with a reasonably live consensus, with or without
  60. * certificates */
  61. return options->TestingClientConsensusDownloadInitialDelay;
  62. }
  63. }
  64. case DL_SCHED_BRIDGE:
  65. if (options->UseBridges && num_bridges_usable(0) > 0) {
  66. /* A bridge client that is sure that one or more of its bridges are
  67. * running can afford to wait longer to update bridge descriptors. */
  68. return options->TestingBridgeDownloadInitialDelay;
  69. } else {
  70. /* A bridge client which might have no running bridges, must try to
  71. * get bridge descriptors straight away. */
  72. return options->TestingBridgeBootstrapDownloadInitialDelay;
  73. }
  74. default:
  75. tor_assert(0);
  76. }
  77. /* Impossible, but gcc will fail with -Werror without a `return`. */
  78. return 0;
  79. }
  80. /** As next_random_exponential_delay() below, but does not compute a random
  81. * value. Instead, compute the range of values that
  82. * next_random_exponential_delay() should use when computing its random value.
  83. * Store the low bound into *<b>low_bound_out</b>, and the high bound into
  84. * *<b>high_bound_out</b>. Guarantees that the low bound is strictly less
  85. * than the high bound. */
  86. STATIC void
  87. next_random_exponential_delay_range(int *low_bound_out,
  88. int *high_bound_out,
  89. int delay,
  90. int base_delay)
  91. {
  92. // This is the "decorrelated jitter" approach, from
  93. // https://www.awsarchitectureblog.com/2015/03/backoff.html
  94. // The formula is
  95. // sleep = min(cap, random_between(base, sleep * 3))
  96. const int delay_times_3 = delay < INT_MAX/3 ? delay * 3 : INT_MAX;
  97. *low_bound_out = base_delay;
  98. if (delay_times_3 > base_delay) {
  99. *high_bound_out = delay_times_3;
  100. } else {
  101. *high_bound_out = base_delay+1;
  102. }
  103. }
  104. /** Advance one delay step. The algorithm will generate a random delay,
  105. * such that each failure is possibly (random) longer than the ones before.
  106. *
  107. * We then clamp that value to be no larger than max_delay, and return it.
  108. *
  109. * The <b>base_delay</b> parameter is lowest possible delay time (can't be
  110. * zero); the <b>backoff_position</b> parameter is the number of times we've
  111. * generated a delay; and the <b>delay</b> argument is the most recently used
  112. * delay.
  113. */
  114. STATIC int
  115. next_random_exponential_delay(int delay,
  116. int base_delay)
  117. {
  118. /* Check preconditions */
  119. if (BUG(delay < 0))
  120. delay = 0;
  121. if (base_delay < 1)
  122. base_delay = 1;
  123. int low_bound=0, high_bound=INT_MAX;
  124. next_random_exponential_delay_range(&low_bound, &high_bound,
  125. delay, base_delay);
  126. return crypto_rand_int_range(low_bound, high_bound);
  127. }
  128. /** Find the current delay for dls based on min_delay.
  129. *
  130. * This function sets dls->next_attempt_at based on now, and returns the delay.
  131. * Helper for download_status_increment_failure and
  132. * download_status_increment_attempt. */
  133. STATIC int
  134. download_status_schedule_get_delay(download_status_t *dls,
  135. int min_delay,
  136. time_t now)
  137. {
  138. tor_assert(dls);
  139. /* If we're using random exponential backoff, we do need min/max delay */
  140. tor_assert(min_delay >= 0);
  141. int delay = INT_MAX;
  142. uint8_t dls_schedule_position = (dls->increment_on
  143. == DL_SCHED_INCREMENT_ATTEMPT
  144. ? dls->n_download_attempts
  145. : dls->n_download_failures);
  146. /* Check if we missed a reset somehow */
  147. IF_BUG_ONCE(dls->last_backoff_position > dls_schedule_position) {
  148. dls->last_backoff_position = 0;
  149. dls->last_delay_used = 0;
  150. }
  151. if (dls_schedule_position > 0) {
  152. delay = dls->last_delay_used;
  153. while (dls->last_backoff_position < dls_schedule_position) {
  154. /* Do one increment step */
  155. delay = next_random_exponential_delay(delay, min_delay);
  156. /* Update our position */
  157. ++(dls->last_backoff_position);
  158. }
  159. } else {
  160. /* If we're just starting out, use the minimum delay */
  161. delay = min_delay;
  162. }
  163. /* Clamp it within min/max if we have them */
  164. if (min_delay >= 0 && delay < min_delay) delay = min_delay;
  165. /* Store it for next time */
  166. dls->last_backoff_position = dls_schedule_position;
  167. dls->last_delay_used = delay;
  168. /* A negative delay makes no sense. Knowing that delay is
  169. * non-negative allows us to safely do the wrapping check below. */
  170. tor_assert(delay >= 0);
  171. /* Avoid now+delay overflowing TIME_MAX, by comparing with a subtraction
  172. * that won't overflow (since delay is non-negative). */
  173. if (delay < INT_MAX && now <= TIME_MAX - delay) {
  174. dls->next_attempt_at = now+delay;
  175. } else {
  176. dls->next_attempt_at = TIME_MAX;
  177. }
  178. return delay;
  179. }
  180. /* Log a debug message about item, which increments on increment_action, has
  181. * incremented dls_n_download_increments times. The message varies based on
  182. * was_schedule_incremented (if not, not_incremented_response is logged), and
  183. * the values of increment, dls_next_attempt_at, and now.
  184. * Helper for download_status_increment_failure and
  185. * download_status_increment_attempt. */
  186. static void
  187. download_status_log_helper(const char *item, int was_schedule_incremented,
  188. const char *increment_action,
  189. const char *not_incremented_response,
  190. uint8_t dls_n_download_increments, int increment,
  191. time_t dls_next_attempt_at, time_t now)
  192. {
  193. if (item) {
  194. if (!was_schedule_incremented)
  195. log_debug(LD_DIR, "%s %s %d time(s); I'll try again %s.",
  196. item, increment_action, (int)dls_n_download_increments,
  197. not_incremented_response);
  198. else if (increment == 0)
  199. log_debug(LD_DIR, "%s %s %d time(s); I'll try again immediately.",
  200. item, increment_action, (int)dls_n_download_increments);
  201. else if (dls_next_attempt_at < TIME_MAX)
  202. log_debug(LD_DIR, "%s %s %d time(s); I'll try again in %d seconds.",
  203. item, increment_action, (int)dls_n_download_increments,
  204. (int)(dls_next_attempt_at-now));
  205. else
  206. log_debug(LD_DIR, "%s %s %d time(s); Giving up for a while.",
  207. item, increment_action, (int)dls_n_download_increments);
  208. }
  209. }
  210. /** Determine when a failed download attempt should be retried.
  211. * Called when an attempt to download <b>dls</b> has failed with HTTP status
  212. * <b>status_code</b>. Increment the failure count (if the code indicates a
  213. * real failure, or if we're a server) and set <b>dls</b>-\>next_attempt_at to
  214. * an appropriate time in the future and return it.
  215. * If <b>dls->increment_on</b> is DL_SCHED_INCREMENT_ATTEMPT, increment the
  216. * failure count, and return a time in the far future for the next attempt (to
  217. * avoid an immediate retry). */
  218. time_t
  219. download_status_increment_failure(download_status_t *dls, int status_code,
  220. const char *item, int server, time_t now)
  221. {
  222. (void) status_code; // XXXX no longer used.
  223. (void) server; // XXXX no longer used.
  224. int increment = -1;
  225. int min_delay = 0;
  226. tor_assert(dls);
  227. /* dls wasn't reset before it was used */
  228. if (dls->next_attempt_at == 0) {
  229. download_status_reset(dls);
  230. }
  231. /* count the failure */
  232. if (dls->n_download_failures < IMPOSSIBLE_TO_DOWNLOAD-1) {
  233. ++dls->n_download_failures;
  234. }
  235. if (dls->increment_on == DL_SCHED_INCREMENT_FAILURE) {
  236. /* We don't find out that a failure-based schedule has attempted a
  237. * connection until that connection fails.
  238. * We'll never find out about successful connections, but this doesn't
  239. * matter, because schedules are reset after a successful download.
  240. */
  241. if (dls->n_download_attempts < IMPOSSIBLE_TO_DOWNLOAD-1)
  242. ++dls->n_download_attempts;
  243. /* only return a failure retry time if this schedule increments on failures
  244. */
  245. min_delay = find_dl_min_delay(dls, get_options());
  246. increment = download_status_schedule_get_delay(dls, min_delay, now);
  247. }
  248. download_status_log_helper(item, !dls->increment_on, "failed",
  249. "concurrently", dls->n_download_failures,
  250. increment,
  251. download_status_get_next_attempt_at(dls),
  252. now);
  253. if (dls->increment_on == DL_SCHED_INCREMENT_ATTEMPT) {
  254. /* stop this schedule retrying on failure, it will launch concurrent
  255. * connections instead */
  256. return TIME_MAX;
  257. } else {
  258. return download_status_get_next_attempt_at(dls);
  259. }
  260. }
  261. /** Determine when the next download attempt should be made when using an
  262. * attempt-based (potentially concurrent) download schedule.
  263. * Called when an attempt to download <b>dls</b> is being initiated.
  264. * Increment the attempt count and set <b>dls</b>-\>next_attempt_at to an
  265. * appropriate time in the future and return it.
  266. * If <b>dls->increment_on</b> is DL_SCHED_INCREMENT_FAILURE, don't increment
  267. * the attempts, and return a time in the far future (to avoid launching a
  268. * concurrent attempt). */
  269. time_t
  270. download_status_increment_attempt(download_status_t *dls, const char *item,
  271. time_t now)
  272. {
  273. int delay = -1;
  274. int min_delay = 0;
  275. tor_assert(dls);
  276. /* dls wasn't reset before it was used */
  277. if (dls->next_attempt_at == 0) {
  278. download_status_reset(dls);
  279. }
  280. if (dls->increment_on == DL_SCHED_INCREMENT_FAILURE) {
  281. /* this schedule should retry on failure, and not launch any concurrent
  282. attempts */
  283. log_warn(LD_BUG, "Tried to launch an attempt-based connection on a "
  284. "failure-based schedule.");
  285. return TIME_MAX;
  286. }
  287. if (dls->n_download_attempts < IMPOSSIBLE_TO_DOWNLOAD-1)
  288. ++dls->n_download_attempts;
  289. min_delay = find_dl_min_delay(dls, get_options());
  290. delay = download_status_schedule_get_delay(dls, min_delay, now);
  291. download_status_log_helper(item, dls->increment_on, "attempted",
  292. "on failure", dls->n_download_attempts,
  293. delay, download_status_get_next_attempt_at(dls),
  294. now);
  295. return download_status_get_next_attempt_at(dls);
  296. }
  297. static time_t
  298. download_status_get_initial_delay_from_now(const download_status_t *dls)
  299. {
  300. /* We use constant initial delays, even in exponential backoff
  301. * schedules. */
  302. return time(NULL) + find_dl_min_delay(dls, get_options());
  303. }
  304. /** Reset <b>dls</b> so that it will be considered downloadable
  305. * immediately, and/or to show that we don't need it anymore.
  306. *
  307. * Must be called to initialise a download schedule, otherwise the zeroth item
  308. * in the schedule will never be used.
  309. *
  310. * (We find the zeroth element of the download schedule, and set
  311. * next_attempt_at to be the appropriate offset from 'now'. In most
  312. * cases this means setting it to 'now', so the item will be immediately
  313. * downloadable; when using authorities with fallbacks, there is a few seconds'
  314. * delay.) */
  315. void
  316. download_status_reset(download_status_t *dls)
  317. {
  318. if (dls->n_download_failures == IMPOSSIBLE_TO_DOWNLOAD
  319. || dls->n_download_attempts == IMPOSSIBLE_TO_DOWNLOAD)
  320. return; /* Don't reset this. */
  321. dls->n_download_failures = 0;
  322. dls->n_download_attempts = 0;
  323. dls->next_attempt_at = download_status_get_initial_delay_from_now(dls);
  324. dls->last_backoff_position = 0;
  325. dls->last_delay_used = 0;
  326. /* Don't reset dls->want_authority or dls->increment_on */
  327. }
  328. /** Return true iff, as of <b>now</b>, the resource tracked by <b>dls</b> is
  329. * ready to get its download reattempted. */
  330. int
  331. download_status_is_ready(download_status_t *dls, time_t now)
  332. {
  333. /* dls wasn't reset before it was used */
  334. if (dls->next_attempt_at == 0) {
  335. download_status_reset(dls);
  336. }
  337. return download_status_get_next_attempt_at(dls) <= now;
  338. }
  339. /** Mark <b>dl</b> as never downloadable. */
  340. void
  341. download_status_mark_impossible(download_status_t *dl)
  342. {
  343. dl->n_download_failures = IMPOSSIBLE_TO_DOWNLOAD;
  344. dl->n_download_attempts = IMPOSSIBLE_TO_DOWNLOAD;
  345. }
  346. /** Return the number of failures on <b>dls</b> since the last success (if
  347. * any). */
  348. int
  349. download_status_get_n_failures(const download_status_t *dls)
  350. {
  351. return dls->n_download_failures;
  352. }
  353. /** Return the number of attempts to download <b>dls</b> since the last success
  354. * (if any). This can differ from download_status_get_n_failures() due to
  355. * outstanding concurrent attempts. */
  356. int
  357. download_status_get_n_attempts(const download_status_t *dls)
  358. {
  359. return dls->n_download_attempts;
  360. }
  361. /** Return the next time to attempt to download <b>dls</b>. */
  362. time_t
  363. download_status_get_next_attempt_at(const download_status_t *dls)
  364. {
  365. /* dls wasn't reset before it was used */
  366. if (dls->next_attempt_at == 0) {
  367. /* so give the answer we would have given if it had been */
  368. return download_status_get_initial_delay_from_now(dls);
  369. }
  370. return dls->next_attempt_at;
  371. }