ratelim.c 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960
  1. /* Copyright (c) 2003-2004, Roger Dingledine
  2. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
  3. * Copyright (c) 2007-2018, The Tor Project, Inc. */
  4. /* See LICENSE for licensing information */
  5. /**
  6. * \file ratelim.c
  7. * \brief Summarize similar messages that would otherwise flood the logs.
  8. **/
  9. #include "lib/log/ratelim.h"
  10. #include "lib/malloc/malloc.h"
  11. #include "lib/string/printf.h"
  12. /** If the rate-limiter <b>lim</b> is ready at <b>now</b>, return the number
  13. * of calls to rate_limit_is_ready (including this one!) since the last time
  14. * rate_limit_is_ready returned nonzero. Otherwise return 0.
  15. * If the call number hits <b>RATELIM_TOOMANY</b> limit, drop a warning
  16. * about this event and stop counting. */
  17. static int
  18. rate_limit_is_ready(ratelim_t *lim, time_t now)
  19. {
  20. if (lim->rate + lim->last_allowed <= now) {
  21. int res = lim->n_calls_since_last_time + 1;
  22. lim->last_allowed = now;
  23. lim->n_calls_since_last_time = 0;
  24. return res;
  25. } else {
  26. if (lim->n_calls_since_last_time <= RATELIM_TOOMANY) {
  27. ++lim->n_calls_since_last_time;
  28. }
  29. return 0;
  30. }
  31. }
  32. /** If the rate-limiter <b>lim</b> is ready at <b>now</b>, return a newly
  33. * allocated string indicating how many messages were suppressed, suitable to
  34. * append to a log message. Otherwise return NULL. */
  35. char *
  36. rate_limit_log(ratelim_t *lim, time_t now)
  37. {
  38. int n;
  39. if ((n = rate_limit_is_ready(lim, now))) {
  40. if (n == 1) {
  41. return tor_strdup("");
  42. } else {
  43. char *cp=NULL;
  44. const char *opt_over = (n >= RATELIM_TOOMANY) ? "over " : "";
  45. /* XXXX this is not exactly correct: the messages could have occurred
  46. * any time between the old value of lim->allowed and now. */
  47. tor_asprintf(&cp,
  48. " [%s%d similar message(s) suppressed in last %d seconds]",
  49. opt_over, n-1, lim->rate);
  50. return cp;
  51. }
  52. } else {
  53. return NULL;
  54. }
  55. }