tor

The Tor anonymity network
git clone https://git.dasho.dev/tor.git
Log | Files | Refs | README | LICENSE

ratelim.c (2099B)


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