|  | @@ -26,12 +26,10 @@
 | 
	
		
			
				|  |  |  #include "app/config/confparse.h"
 | 
	
		
			
				|  |  |  #include "feature/nodelist/routerset.h"
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +#include "lib/confmgt/unitparse.h"
 | 
	
		
			
				|  |  |  #include "lib/container/bitarray.h"
 | 
	
		
			
				|  |  |  #include "lib/encoding/confline.h"
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -static uint64_t config_parse_memunit(const char *s, int *ok);
 | 
	
		
			
				|  |  | -static int config_parse_msec_interval(const char *s, int *ok);
 | 
	
		
			
				|  |  | -static int config_parse_interval(const char *s, int *ok);
 | 
	
		
			
				|  |  |  static void config_reset(const config_format_t *fmt, void *options,
 | 
	
		
			
				|  |  |                           const config_var_t *var, int use_defaults);
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -1014,193 +1012,3 @@ config_dump(const config_format_t *fmt, const void *default_options,
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |    return result;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -/** Mapping from a unit name to a multiplier for converting that unit into a
 | 
	
		
			
				|  |  | - * base unit.  Used by config_parse_unit. */
 | 
	
		
			
				|  |  | -struct unit_table_t {
 | 
	
		
			
				|  |  | -  const char *unit; /**< The name of the unit */
 | 
	
		
			
				|  |  | -  uint64_t multiplier; /**< How many of the base unit appear in this unit */
 | 
	
		
			
				|  |  | -};
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -/** Table to map the names of memory units to the number of bytes they
 | 
	
		
			
				|  |  | - * contain. */
 | 
	
		
			
				|  |  | -static struct unit_table_t memory_units[] = {
 | 
	
		
			
				|  |  | -  { "",          1 },
 | 
	
		
			
				|  |  | -  { "b",         1<< 0 },
 | 
	
		
			
				|  |  | -  { "byte",      1<< 0 },
 | 
	
		
			
				|  |  | -  { "bytes",     1<< 0 },
 | 
	
		
			
				|  |  | -  { "kb",        1<<10 },
 | 
	
		
			
				|  |  | -  { "kbyte",     1<<10 },
 | 
	
		
			
				|  |  | -  { "kbytes",    1<<10 },
 | 
	
		
			
				|  |  | -  { "kilobyte",  1<<10 },
 | 
	
		
			
				|  |  | -  { "kilobytes", 1<<10 },
 | 
	
		
			
				|  |  | -  { "kilobits",  1<<7  },
 | 
	
		
			
				|  |  | -  { "kilobit",   1<<7  },
 | 
	
		
			
				|  |  | -  { "kbits",     1<<7  },
 | 
	
		
			
				|  |  | -  { "kbit",      1<<7  },
 | 
	
		
			
				|  |  | -  { "m",         1<<20 },
 | 
	
		
			
				|  |  | -  { "mb",        1<<20 },
 | 
	
		
			
				|  |  | -  { "mbyte",     1<<20 },
 | 
	
		
			
				|  |  | -  { "mbytes",    1<<20 },
 | 
	
		
			
				|  |  | -  { "megabyte",  1<<20 },
 | 
	
		
			
				|  |  | -  { "megabytes", 1<<20 },
 | 
	
		
			
				|  |  | -  { "megabits",  1<<17 },
 | 
	
		
			
				|  |  | -  { "megabit",   1<<17 },
 | 
	
		
			
				|  |  | -  { "mbits",     1<<17 },
 | 
	
		
			
				|  |  | -  { "mbit",      1<<17 },
 | 
	
		
			
				|  |  | -  { "gb",        1<<30 },
 | 
	
		
			
				|  |  | -  { "gbyte",     1<<30 },
 | 
	
		
			
				|  |  | -  { "gbytes",    1<<30 },
 | 
	
		
			
				|  |  | -  { "gigabyte",  1<<30 },
 | 
	
		
			
				|  |  | -  { "gigabytes", 1<<30 },
 | 
	
		
			
				|  |  | -  { "gigabits",  1<<27 },
 | 
	
		
			
				|  |  | -  { "gigabit",   1<<27 },
 | 
	
		
			
				|  |  | -  { "gbits",     1<<27 },
 | 
	
		
			
				|  |  | -  { "gbit",      1<<27 },
 | 
	
		
			
				|  |  | -  { "tb",        UINT64_C(1)<<40 },
 | 
	
		
			
				|  |  | -  { "tbyte",     UINT64_C(1)<<40 },
 | 
	
		
			
				|  |  | -  { "tbytes",    UINT64_C(1)<<40 },
 | 
	
		
			
				|  |  | -  { "terabyte",  UINT64_C(1)<<40 },
 | 
	
		
			
				|  |  | -  { "terabytes", UINT64_C(1)<<40 },
 | 
	
		
			
				|  |  | -  { "terabits",  UINT64_C(1)<<37 },
 | 
	
		
			
				|  |  | -  { "terabit",   UINT64_C(1)<<37 },
 | 
	
		
			
				|  |  | -  { "tbits",     UINT64_C(1)<<37 },
 | 
	
		
			
				|  |  | -  { "tbit",      UINT64_C(1)<<37 },
 | 
	
		
			
				|  |  | -  { NULL, 0 },
 | 
	
		
			
				|  |  | -};
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -/** Table to map the names of time units to the number of seconds they
 | 
	
		
			
				|  |  | - * contain. */
 | 
	
		
			
				|  |  | -static struct unit_table_t time_units[] = {
 | 
	
		
			
				|  |  | -  { "",         1 },
 | 
	
		
			
				|  |  | -  { "second",   1 },
 | 
	
		
			
				|  |  | -  { "seconds",  1 },
 | 
	
		
			
				|  |  | -  { "minute",   60 },
 | 
	
		
			
				|  |  | -  { "minutes",  60 },
 | 
	
		
			
				|  |  | -  { "hour",     60*60 },
 | 
	
		
			
				|  |  | -  { "hours",    60*60 },
 | 
	
		
			
				|  |  | -  { "day",      24*60*60 },
 | 
	
		
			
				|  |  | -  { "days",     24*60*60 },
 | 
	
		
			
				|  |  | -  { "week",     7*24*60*60 },
 | 
	
		
			
				|  |  | -  { "weeks",    7*24*60*60 },
 | 
	
		
			
				|  |  | -  { "month",    2629728, }, /* about 30.437 days */
 | 
	
		
			
				|  |  | -  { "months",   2629728, },
 | 
	
		
			
				|  |  | -  { NULL, 0 },
 | 
	
		
			
				|  |  | -};
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -/** Table to map the names of time units to the number of milliseconds
 | 
	
		
			
				|  |  | - * they contain. */
 | 
	
		
			
				|  |  | -static struct unit_table_t time_msec_units[] = {
 | 
	
		
			
				|  |  | -  { "",         1 },
 | 
	
		
			
				|  |  | -  { "msec",     1 },
 | 
	
		
			
				|  |  | -  { "millisecond", 1 },
 | 
	
		
			
				|  |  | -  { "milliseconds", 1 },
 | 
	
		
			
				|  |  | -  { "second",   1000 },
 | 
	
		
			
				|  |  | -  { "seconds",  1000 },
 | 
	
		
			
				|  |  | -  { "minute",   60*1000 },
 | 
	
		
			
				|  |  | -  { "minutes",  60*1000 },
 | 
	
		
			
				|  |  | -  { "hour",     60*60*1000 },
 | 
	
		
			
				|  |  | -  { "hours",    60*60*1000 },
 | 
	
		
			
				|  |  | -  { "day",      24*60*60*1000 },
 | 
	
		
			
				|  |  | -  { "days",     24*60*60*1000 },
 | 
	
		
			
				|  |  | -  { "week",     7*24*60*60*1000 },
 | 
	
		
			
				|  |  | -  { "weeks",    7*24*60*60*1000 },
 | 
	
		
			
				|  |  | -  { NULL, 0 },
 | 
	
		
			
				|  |  | -};
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -/** Parse a string <b>val</b> containing a number, zero or more
 | 
	
		
			
				|  |  | - * spaces, and an optional unit string.  If the unit appears in the
 | 
	
		
			
				|  |  | - * table <b>u</b>, then multiply the number by the unit multiplier.
 | 
	
		
			
				|  |  | - * On success, set *<b>ok</b> to 1 and return this product.
 | 
	
		
			
				|  |  | - * Otherwise, set *<b>ok</b> to 0.
 | 
	
		
			
				|  |  | - */
 | 
	
		
			
				|  |  | -static uint64_t
 | 
	
		
			
				|  |  | -config_parse_units(const char *val, struct unit_table_t *u, int *ok)
 | 
	
		
			
				|  |  | -{
 | 
	
		
			
				|  |  | -  uint64_t v = 0;
 | 
	
		
			
				|  |  | -  double d = 0;
 | 
	
		
			
				|  |  | -  int use_float = 0;
 | 
	
		
			
				|  |  | -  char *cp;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  tor_assert(ok);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  v = tor_parse_uint64(val, 10, 0, UINT64_MAX, ok, &cp);
 | 
	
		
			
				|  |  | -  if (!*ok || (cp && *cp == '.')) {
 | 
	
		
			
				|  |  | -    d = tor_parse_double(val, 0, (double)UINT64_MAX, ok, &cp);
 | 
	
		
			
				|  |  | -    if (!*ok)
 | 
	
		
			
				|  |  | -      goto done;
 | 
	
		
			
				|  |  | -    use_float = 1;
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  if (!cp) {
 | 
	
		
			
				|  |  | -    *ok = 1;
 | 
	
		
			
				|  |  | -    v = use_float ? ((uint64_t)d) :  v;
 | 
	
		
			
				|  |  | -    goto done;
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  cp = (char*) eat_whitespace(cp);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  for ( ;u->unit;++u) {
 | 
	
		
			
				|  |  | -    if (!strcasecmp(u->unit, cp)) {
 | 
	
		
			
				|  |  | -      if (use_float)
 | 
	
		
			
				|  |  | -        v = (uint64_t)(u->multiplier * d);
 | 
	
		
			
				|  |  | -      else
 | 
	
		
			
				|  |  | -        v *= u->multiplier;
 | 
	
		
			
				|  |  | -      *ok = 1;
 | 
	
		
			
				|  |  | -      goto done;
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -  log_warn(LD_CONFIG, "Unknown unit '%s'.", cp);
 | 
	
		
			
				|  |  | -  *ok = 0;
 | 
	
		
			
				|  |  | - done:
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  if (*ok)
 | 
	
		
			
				|  |  | -    return v;
 | 
	
		
			
				|  |  | -  else
 | 
	
		
			
				|  |  | -    return 0;
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -/** Parse a string in the format "number unit", where unit is a unit of
 | 
	
		
			
				|  |  | - * information (byte, KB, M, etc).  On success, set *<b>ok</b> to true
 | 
	
		
			
				|  |  | - * and return the number of bytes specified.  Otherwise, set
 | 
	
		
			
				|  |  | - * *<b>ok</b> to false and return 0. */
 | 
	
		
			
				|  |  | -static uint64_t
 | 
	
		
			
				|  |  | -config_parse_memunit(const char *s, int *ok)
 | 
	
		
			
				|  |  | -{
 | 
	
		
			
				|  |  | -  uint64_t u = config_parse_units(s, memory_units, ok);
 | 
	
		
			
				|  |  | -  return u;
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -/** Parse a string in the format "number unit", where unit is a unit of
 | 
	
		
			
				|  |  | - * time in milliseconds.  On success, set *<b>ok</b> to true and return
 | 
	
		
			
				|  |  | - * the number of milliseconds in the provided interval.  Otherwise, set
 | 
	
		
			
				|  |  | - * *<b>ok</b> to 0 and return -1. */
 | 
	
		
			
				|  |  | -static int
 | 
	
		
			
				|  |  | -config_parse_msec_interval(const char *s, int *ok)
 | 
	
		
			
				|  |  | -{
 | 
	
		
			
				|  |  | -  uint64_t r;
 | 
	
		
			
				|  |  | -  r = config_parse_units(s, time_msec_units, ok);
 | 
	
		
			
				|  |  | -  if (r > INT_MAX) {
 | 
	
		
			
				|  |  | -    log_warn(LD_CONFIG, "Msec interval '%s' is too long", s);
 | 
	
		
			
				|  |  | -    *ok = 0;
 | 
	
		
			
				|  |  | -    return -1;
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -  return (int)r;
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -/** Parse a string in the format "number unit", where unit is a unit of time.
 | 
	
		
			
				|  |  | - * On success, set *<b>ok</b> to true and return the number of seconds in
 | 
	
		
			
				|  |  | - * the provided interval.  Otherwise, set *<b>ok</b> to 0 and return -1.
 | 
	
		
			
				|  |  | - */
 | 
	
		
			
				|  |  | -static int
 | 
	
		
			
				|  |  | -config_parse_interval(const char *s, int *ok)
 | 
	
		
			
				|  |  | -{
 | 
	
		
			
				|  |  | -  uint64_t r;
 | 
	
		
			
				|  |  | -  r = config_parse_units(s, time_units, ok);
 | 
	
		
			
				|  |  | -  if (r > INT_MAX) {
 | 
	
		
			
				|  |  | -    log_warn(LD_CONFIG, "Interval '%s' is too long", s);
 | 
	
		
			
				|  |  | -    *ok = 0;
 | 
	
		
			
				|  |  | -    return -1;
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -  return (int)r;
 | 
	
		
			
				|  |  | -}
 |