NUM must be between 1 and 1000, inclusive. Note that the configured
bandwidth limits are still expressed in bytes per second: this
option only affects the frequency with which Tor checks to see whether
- previously exhausted connections may read again. This option is
- if Tor was built with Libevent's bufferevents enabled. (Default: 10 msec.)
+ previously exhausted connections may read again. (Default: 10 msec.)
**TrackHostExits** __host__,__.domain__,__...__::
For each value in the comma separated list, Tor will track recent
#ifdef USE_BUFFEREVENTS
static int using_iocp_bufferevents = 0;
+static void tor_libevent_set_tick_timeout(int msec_per_tick);
int
tor_libevent_using_iocp_bufferevents(void)
"You have a *VERY* old version of libevent. It is likely to be buggy; "
"please build Tor with a more recent version.");
#endif
+
+#ifdef USE_BUFFEREVENTS
+ tor_libevent_set_tick_timeout(torcfg->msec_per_tick);
+#endif
}
/** Return the current Libevent event base that we're set up to use. */
/**
* Return a special timeout to be passed whenever libevent's O(1) timeout
* implementation should be used. Only use this when the timer is supposed
- * to fire after 1 / TOR_LIBEVENT_TICKS_PER_SECOND seconds have passed.
+ * to fire after msec_per_tick ticks have elapsed.
*/
const struct timeval *
tor_libevent_get_one_tick_timeout(void)
{
- if (PREDICT_UNLIKELY(one_tick == NULL)) {
- struct event_base *base = tor_libevent_get_base();
- struct timeval tv;
- if (TOR_LIBEVENT_TICKS_PER_SECOND == 1) {
- tv.tv_sec = 1;
- tv.tv_usec = 0;
- } else {
- tv.tv_sec = 0;
- tv.tv_usec = 1000000 / TOR_LIBEVENT_TICKS_PER_SECOND;
- }
- one_tick = event_base_init_common_timeout(base, &tv);
- }
+ tor_assert(one_tick);
return one_tick;
}
+/** Initialize the common timeout that we'll use to refill the buckets every
+ * time a tick elapses. */
+static void
+tor_libevent_set_tick_timeout(int msec_per_tick)
+{
+ struct event_base *base = tor_libevent_get_base();
+ struct timeval tv;
+
+ tor_assert(! one_tick);
+ tv.tv_sec = msec_per_tick / 1000;
+ tv.tv_usec = (msec_per_tick % 1000) * 1000;
+ one_tick = event_base_init_common_timeout(base, &tv);
+}
+
static struct bufferevent *
tor_get_root_bufferevent(struct bufferevent *bev)
{
typedef struct tor_libevent_cfg {
int disable_iocp;
int num_cpus;
+ int msec_per_tick;
} tor_libevent_cfg;
void tor_libevent_initialize(tor_libevent_cfg *cfg);
const char *tor_libevent_get_version_str(void);
#ifdef USE_BUFFEREVENTS
-#define TOR_LIBEVENT_TICKS_PER_SECOND 3
const struct timeval *tor_libevent_get_one_tick_timeout(void);
int tor_libevent_using_iocp_bufferevents(void);
int tor_set_bufferevent_rate_limit(struct bufferevent *bev,
memset(&cfg, 0, sizeof(cfg));
cfg.disable_iocp = options->DisableIOCP;
cfg.num_cpus = get_num_cpus(options);
+ cfg.msec_per_tick = options->TokenBucketRefillInterval;
tor_libevent_initialize(&cfg);
burst = options->BandwidthBurst;
}
- rate /= TOR_LIBEVENT_TICKS_PER_SECOND;
+ /* This can't overflow, since TokenBucketRefillInterval <= 1000,
+ * and rate started out less than INT32_MAX. */
+ rate = (rate * options->TokenBucketRefillInterval) / 1000;
+
bucket_cfg = ev_token_bucket_cfg_new((uint32_t)rate, (uint32_t)burst,
(uint32_t)rate, (uint32_t)burst,
tick);
{
const struct timeval *tick = tor_libevent_get_one_tick_timeout();
struct ev_token_bucket_cfg *cfg, *old_cfg;
- int rate_per_tick = rate / TOR_LIBEVENT_TICKS_PER_SECOND;
+ int64_t rate64 = (((int64_t)rate) * options->TokenBucketRefillInterval)
+ / 1000;
+ /* This can't overflow, since TokenBucketRefillInterval <= 1000,
+ * and rate started out less than INT_MAX. */
+ int rate_per_tick = (int) rate64;
+
cfg = ev_token_bucket_cfg_new(rate_per_tick, burst, rate_per_tick,
burst, tick);
old_cfg = conn->bucket_cfg;