From e16b90b88a76fb82702ae26c54834aca6c591d64 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Tue, 18 Jun 2019 19:16:57 -0400 Subject: [PATCH] Partially port routerset to being a full-fledged config type again. --- src/app/config/confparse.c | 27 +++----------- src/feature/nodelist/routerset.c | 62 ++++++++++++++++++++++++++++++++ src/feature/nodelist/routerset.h | 3 ++ 3 files changed, 70 insertions(+), 22 deletions(-) diff --git a/src/app/config/confparse.c b/src/app/config/confparse.c index bc2ab24e4f..a02aa26e82 100644 --- a/src/app/config/confparse.c +++ b/src/app/config/confparse.c @@ -175,18 +175,8 @@ config_assign_value(const config_format_t *fmt, void *options, if (var->type == CONFIG_TYPE_ROUTERSET) { // XXXX make the backend extensible so that we don't have to - // XXXX handle ROUTERSET specially. - - if (*(routerset_t**)lvalue) { - routerset_free(*(routerset_t**)lvalue); - } - *(routerset_t**)lvalue = routerset_new(); - if (routerset_parse(*(routerset_t**)lvalue, c->value, c->key)<0) { - tor_asprintf(msg, "Invalid exit list '%s' for option '%s'", - c->value, c->key); - return -1; - } - return 0; + // XXXX special-case this type. + return typed_var_kvassign_ex(lvalue, c, msg, &routerset_type_defn); } return typed_var_kvassign(lvalue, c, msg, var->type); @@ -377,10 +367,8 @@ config_get_assigned_option(const config_format_t *fmt, const void *options, if (var->type == CONFIG_TYPE_ROUTERSET) { // XXXX make the backend extensible so that we don't have to - // XXXX handle ROUTERSET specially. - result = tor_malloc_zero(sizeof(config_line_t)); - result->key = tor_strdup(var->name); - result->value = routerset_to_string(*(routerset_t**)value); + // XXXX special-case this type. + result = typed_var_kvencode_ex(var->name, value, &routerset_type_defn); } else { result = typed_var_kvencode(var->name, value, var->type); } @@ -512,12 +500,7 @@ config_clear(const config_format_t *fmt, void *options, void *lvalue = STRUCT_VAR_P(options, var->var_offset); (void)fmt; /* unused */ if (var->type == CONFIG_TYPE_ROUTERSET) { - // XXXX make the backend extensible so that we don't have to - // XXXX handle ROUTERSET specially. - if (*(routerset_t**)lvalue) { - routerset_free(*(routerset_t**)lvalue); - *(routerset_t**)lvalue = NULL; - } + typed_var_free_ex(lvalue, &routerset_type_defn); return; } diff --git a/src/feature/nodelist/routerset.c b/src/feature/nodelist/routerset.c index e801fd81b1..ad42e8e101 100644 --- a/src/feature/nodelist/routerset.c +++ b/src/feature/nodelist/routerset.c @@ -34,6 +34,9 @@ n * Copyright (c) 2001-2004, Roger Dingledine. #include "feature/nodelist/nickname.h" #include "feature/nodelist/nodelist.h" #include "feature/nodelist/routerset.h" +#include "lib/conf/conftypes.h" +#include "lib/confmgt/typedvar.h" +#include "lib/encoding/confline.h" #include "lib/geoip/geoip.h" #include "core/or/addr_policy_st.h" @@ -41,6 +44,7 @@ n * Copyright (c) 2001-2004, Roger Dingledine. #include "feature/nodelist/node_st.h" #include "feature/nodelist/routerinfo_st.h" #include "feature/nodelist/routerstatus_st.h" +#include "lib/confmgt/var_type_def_st.h" /** Return a new empty routerset. */ routerset_t * @@ -461,3 +465,61 @@ routerset_free_(routerset_t *routerset) bitarray_free(routerset->countries); tor_free(routerset); } + +static int +routerset_kv_parse(void *target, const config_line_t *line, char **errmsg, + const void *params) +{ + (void)params; + routerset_t **p = (routerset_t**)target; + routerset_free(*p); // clear the old value, if any. + routerset_t *rs = routerset_new(); + if (routerset_parse(rs, line->value, line->key) < 0) { + routerset_free(rs); + *errmsg = tor_strdup("Invalid router list."); + return -1; + } else { + *p = rs; + return 0; + } +} + +static char * +routerset_encode(const void *value, const void *params) +{ + (void)params; + const routerset_t **p = (const routerset_t**)value; + return routerset_to_string(*p); +} + +static void +routerset_clear(void *value, const void *params) +{ + (void)params; + routerset_t **p = (routerset_t**)value; + routerset_free(*p); // sets *p to NULL. +} + +static int +routerset_copy(void *dest, const void *src, const void *params) +{ + (void)params; + routerset_t **output = (routerset_t**)dest; + const routerset_t *input = *(routerset_t**)src; + routerset_free(*output); // sets *output to NULL + *output = routerset_new(); + routerset_union(*output, input); + return 0; +} + +static const var_type_fns_t routerset_type_fns = { + .kv_parse = routerset_kv_parse, + .encode = routerset_encode, + .clear = routerset_clear, + .copy = routerset_copy +}; + +const var_type_def_t routerset_type_defn = { + .name = "RouterList", + .fns = &routerset_type_fns +}; diff --git a/src/feature/nodelist/routerset.h b/src/feature/nodelist/routerset.h index ca8b6fed93..9d184c9852 100644 --- a/src/feature/nodelist/routerset.h +++ b/src/feature/nodelist/routerset.h @@ -44,6 +44,9 @@ void routerset_free_(routerset_t *routerset); #define routerset_free(rs) FREE_AND_NULL(routerset_t, routerset_free_, (rs)) int routerset_len(const routerset_t *set); +struct var_type_def_t; +extern const struct var_type_def_t routerset_type_defn; + #ifdef ROUTERSET_PRIVATE #include "lib/container/bitarray.h"