|  | @@ -2388,22 +2388,23 @@ connection_bucket_init(void)
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -/** Refill a single <b>bucket</b> called <b>name</b> with bandwidth rate
 | 
	
		
			
				|  |  | - * <b>rate</b> and bandwidth burst <b>burst</b>, assuming that
 | 
	
		
			
				|  |  | - * <b>seconds_elapsed</b> seconds have passed since the last call.
 | 
	
		
			
				|  |  | - **/
 | 
	
		
			
				|  |  | +/** Refill a single <b>bucket</b> called <b>name</b> with bandwidth rate per
 | 
	
		
			
				|  |  | + * second <b>rate</b> and bandwidth burst <b>burst</b>, assuming that
 | 
	
		
			
				|  |  | + * <b>milliseconds_elapsed</b> milliseconds have passed since the last
 | 
	
		
			
				|  |  | + * call. */
 | 
	
		
			
				|  |  |  static void
 | 
	
		
			
				|  |  |  connection_bucket_refill_helper(int *bucket, int rate, int burst,
 | 
	
		
			
				|  |  | -                                int seconds_elapsed, const char *name)
 | 
	
		
			
				|  |  | +                                int milliseconds_elapsed,
 | 
	
		
			
				|  |  | +                                const char *name)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  |    int starting_bucket = *bucket;
 | 
	
		
			
				|  |  | -  if (starting_bucket < burst && seconds_elapsed) {
 | 
	
		
			
				|  |  | -    if (((burst - starting_bucket)/seconds_elapsed) < rate) {
 | 
	
		
			
				|  |  | +  if (starting_bucket < burst && milliseconds_elapsed > 0) {
 | 
	
		
			
				|  |  | +    int64_t incr = (((int64_t)rate) * milliseconds_elapsed) / 1000;
 | 
	
		
			
				|  |  | +    if ((burst - starting_bucket) < incr) {
 | 
	
		
			
				|  |  |        *bucket = burst;  /* We would overflow the bucket; just set it to
 | 
	
		
			
				|  |  |                           * the maximum. */
 | 
	
		
			
				|  |  |      } else {
 | 
	
		
			
				|  |  | -      int incr = rate*seconds_elapsed;
 | 
	
		
			
				|  |  | -      *bucket += incr;
 | 
	
		
			
				|  |  | +      *bucket += (int)incr;
 | 
	
		
			
				|  |  |        if (*bucket > burst || *bucket < starting_bucket) {
 | 
	
		
			
				|  |  |          /* If we overflow the burst, or underflow our starting bucket,
 | 
	
		
			
				|  |  |           * cap the bucket value to burst. */
 | 
	
	
		
			
				|  | @@ -2416,41 +2417,46 @@ connection_bucket_refill_helper(int *bucket, int rate, int burst,
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -/** A second has rolled over; increment buckets appropriately. */
 | 
	
		
			
				|  |  | +/** Time has passed; increment buckets appropriately. */
 | 
	
		
			
				|  |  |  void
 | 
	
		
			
				|  |  | -connection_bucket_refill(int seconds_elapsed, time_t now)
 | 
	
		
			
				|  |  | +connection_bucket_refill(int milliseconds_elapsed, time_t now)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  |    const or_options_t *options = get_options();
 | 
	
		
			
				|  |  |    smartlist_t *conns = get_connection_array();
 | 
	
		
			
				|  |  | -  int relayrate, relayburst;
 | 
	
		
			
				|  |  | +  int bandwidthrate, bandwidthburst, relayrate, relayburst;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  bandwidthrate = (int)options->BandwidthRate;
 | 
	
		
			
				|  |  | +  bandwidthburst = (int)options->BandwidthBurst;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    if (options->RelayBandwidthRate) {
 | 
	
		
			
				|  |  |      relayrate = (int)options->RelayBandwidthRate;
 | 
	
		
			
				|  |  |      relayburst = (int)options->RelayBandwidthBurst;
 | 
	
		
			
				|  |  |    } else {
 | 
	
		
			
				|  |  | -    relayrate = (int)options->BandwidthRate;
 | 
	
		
			
				|  |  | -    relayburst = (int)options->BandwidthBurst;
 | 
	
		
			
				|  |  | +    relayrate = bandwidthrate;
 | 
	
		
			
				|  |  | +    relayburst = bandwidthburst;
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  tor_assert(seconds_elapsed >= 0);
 | 
	
		
			
				|  |  | +  tor_assert(milliseconds_elapsed >= 0);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    write_buckets_empty_last_second =
 | 
	
		
			
				|  |  |      global_relayed_write_bucket <= 0 || global_write_bucket <= 0;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    /* refill the global buckets */
 | 
	
		
			
				|  |  |    connection_bucket_refill_helper(&global_read_bucket,
 | 
	
		
			
				|  |  | -                                  (int)options->BandwidthRate,
 | 
	
		
			
				|  |  | -                                  (int)options->BandwidthBurst,
 | 
	
		
			
				|  |  | -                                  seconds_elapsed, "global_read_bucket");
 | 
	
		
			
				|  |  | +                                  bandwidthrate, bandwidthburst,
 | 
	
		
			
				|  |  | +                                  milliseconds_elapsed,
 | 
	
		
			
				|  |  | +                                  "global_read_bucket");
 | 
	
		
			
				|  |  |    connection_bucket_refill_helper(&global_write_bucket,
 | 
	
		
			
				|  |  | -                                  (int)options->BandwidthRate,
 | 
	
		
			
				|  |  | -                                  (int)options->BandwidthBurst,
 | 
	
		
			
				|  |  | -                                  seconds_elapsed, "global_write_bucket");
 | 
	
		
			
				|  |  | +                                  bandwidthrate, bandwidthburst,
 | 
	
		
			
				|  |  | +                                  milliseconds_elapsed,
 | 
	
		
			
				|  |  | +                                  "global_write_bucket");
 | 
	
		
			
				|  |  |    connection_bucket_refill_helper(&global_relayed_read_bucket,
 | 
	
		
			
				|  |  | -                                  relayrate, relayburst, seconds_elapsed,
 | 
	
		
			
				|  |  | +                                  relayrate, relayburst,
 | 
	
		
			
				|  |  | +                                  milliseconds_elapsed,
 | 
	
		
			
				|  |  |                                    "global_relayed_read_bucket");
 | 
	
		
			
				|  |  |    connection_bucket_refill_helper(&global_relayed_write_bucket,
 | 
	
		
			
				|  |  | -                                  relayrate, relayburst, seconds_elapsed,
 | 
	
		
			
				|  |  | +                                  relayrate, relayburst,
 | 
	
		
			
				|  |  | +                                  milliseconds_elapsed,
 | 
	
		
			
				|  |  |                                    "global_relayed_write_bucket");
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    /* refill the per-connection buckets */
 | 
	
	
		
			
				|  | @@ -2458,18 +2464,20 @@ connection_bucket_refill(int seconds_elapsed, time_t now)
 | 
	
		
			
				|  |  |    {
 | 
	
		
			
				|  |  |      if (connection_speaks_cells(conn)) {
 | 
	
		
			
				|  |  |        or_connection_t *or_conn = TO_OR_CONN(conn);
 | 
	
		
			
				|  |  | +      int orbandwidthrate = or_conn->bandwidthrate;
 | 
	
		
			
				|  |  | +      int orbandwidthburst = or_conn->bandwidthburst;
 | 
	
		
			
				|  |  |        if (connection_bucket_should_increase(or_conn->read_bucket, or_conn)) {
 | 
	
		
			
				|  |  |          connection_bucket_refill_helper(&or_conn->read_bucket,
 | 
	
		
			
				|  |  | -                                        or_conn->bandwidthrate,
 | 
	
		
			
				|  |  | -                                        or_conn->bandwidthburst,
 | 
	
		
			
				|  |  | -                                        seconds_elapsed,
 | 
	
		
			
				|  |  | +                                        orbandwidthrate,
 | 
	
		
			
				|  |  | +                                        orbandwidthburst,
 | 
	
		
			
				|  |  | +                                        milliseconds_elapsed,
 | 
	
		
			
				|  |  |                                          "or_conn->read_bucket");
 | 
	
		
			
				|  |  |        }
 | 
	
		
			
				|  |  |        if (connection_bucket_should_increase(or_conn->write_bucket, or_conn)) {
 | 
	
		
			
				|  |  |          connection_bucket_refill_helper(&or_conn->write_bucket,
 | 
	
		
			
				|  |  | -                                        or_conn->bandwidthrate,
 | 
	
		
			
				|  |  | -                                        or_conn->bandwidthburst,
 | 
	
		
			
				|  |  | -                                        seconds_elapsed,
 | 
	
		
			
				|  |  | +                                        orbandwidthrate,
 | 
	
		
			
				|  |  | +                                        orbandwidthburst,
 | 
	
		
			
				|  |  | +                                        milliseconds_elapsed,
 | 
	
		
			
				|  |  |                                          "or_conn->write_bucket");
 | 
	
		
			
				|  |  |        }
 | 
	
		
			
				|  |  |      }
 | 
	
	
		
			
				|  | @@ -2553,7 +2561,10 @@ connection_bucket_init(void)
 | 
	
		
			
				|  |  |      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);
 |