mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-11 05:33:47 +01:00
Add a function to canonicalize nodefamilies per prop298
This is the same as the regular canonical nodefamily format, except that unrecognized elements are preserved.
This commit is contained in:
parent
0e9a963b6b
commit
d29e3a02d5
@ -93,12 +93,46 @@ nodefamily_parse(const char *s, const uint8_t *rsa_id_self,
|
||||
{
|
||||
smartlist_t *sl = smartlist_new();
|
||||
smartlist_split_string(sl, s, NULL, SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
|
||||
nodefamily_t *result = nodefamily_from_members(sl, rsa_id_self, flags);
|
||||
nodefamily_t *result = nodefamily_from_members(sl, rsa_id_self, flags, NULL);
|
||||
SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp));
|
||||
smartlist_free(sl);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Canonicalize the family list <b>s</b>, returning a newly allocated string.
|
||||
*
|
||||
* The canonicalization rules are fully specified in dir-spec.txt, but,
|
||||
* briefly: $hexid entries are put in caps, $hexid[=~]foo entries are
|
||||
* truncated, nicknames are put into lowercase, unrecognized entries are left
|
||||
* alone, and everything is sorted.
|
||||
**/
|
||||
char *
|
||||
nodefamily_canonicalize(const char *s, const uint8_t *rsa_id_self,
|
||||
unsigned flags)
|
||||
{
|
||||
smartlist_t *sl = smartlist_new();
|
||||
smartlist_t *result_members = smartlist_new();
|
||||
smartlist_split_string(sl, s, NULL, SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
|
||||
nodefamily_t *nf = nodefamily_from_members(sl, rsa_id_self, flags,
|
||||
result_members);
|
||||
|
||||
char *formatted = nodefamily_format(nf);
|
||||
smartlist_split_string(result_members, formatted, NULL,
|
||||
SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
|
||||
smartlist_sort_strings(result_members);
|
||||
char *combined = smartlist_join_strings(result_members, " ", 0, NULL);
|
||||
|
||||
nodefamily_free(nf);
|
||||
SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp));
|
||||
smartlist_free(sl);
|
||||
SMARTLIST_FOREACH(result_members, char *, cp, tor_free(cp));
|
||||
smartlist_free(result_members);
|
||||
tor_free(formatted);
|
||||
|
||||
return combined;
|
||||
}
|
||||
|
||||
/**
|
||||
* qsort helper for encoded nodefamily elements.
|
||||
**/
|
||||
@ -117,11 +151,15 @@ compare_members(const void *a, const void *b)
|
||||
* family declaration if it is not there already.
|
||||
*
|
||||
* The <b>flags</b> element is interpreted as in nodefamily_parse().
|
||||
*
|
||||
* If <b>unrecognized</b> is provided, fill it copies of any unrecognized
|
||||
* members. (Note that malformed $hexids are not considered unrecognized.)
|
||||
**/
|
||||
nodefamily_t *
|
||||
nodefamily_from_members(const smartlist_t *members,
|
||||
const uint8_t *rsa_id_self,
|
||||
unsigned flags)
|
||||
unsigned flags,
|
||||
smartlist_t *unrecognized_out)
|
||||
{
|
||||
const int n_self = rsa_id_self ? 1 : 0;
|
||||
int n_bad_elements = 0;
|
||||
@ -146,6 +184,9 @@ nodefamily_from_members(const smartlist_t *members,
|
||||
ptr[0] = NODEFAMILY_BY_RSA_ID;
|
||||
memcpy(ptr+1, digest_buf, DIGEST_LEN);
|
||||
}
|
||||
} else {
|
||||
if (unrecognized_out)
|
||||
smartlist_add_strdup(unrecognized_out, cp);
|
||||
}
|
||||
|
||||
if (bad_element) {
|
||||
|
@ -27,7 +27,8 @@ nodefamily_t *nodefamily_parse(const char *s,
|
||||
unsigned flags);
|
||||
nodefamily_t *nodefamily_from_members(const struct smartlist_t *members,
|
||||
const uint8_t *rsa_id_self,
|
||||
unsigned flags);
|
||||
unsigned flags,
|
||||
smartlist_t *unrecognized_out);
|
||||
void nodefamily_free_(nodefamily_t *family);
|
||||
#define nodefamily_free(family) \
|
||||
FREE_AND_NULL(nodefamily_t, nodefamily_free_, (family))
|
||||
@ -41,6 +42,8 @@ bool nodefamily_contains_node(const nodefamily_t *family,
|
||||
void nodefamily_add_nodes_to_smartlist(const nodefamily_t *family,
|
||||
struct smartlist_t *out);
|
||||
char *nodefamily_format(const nodefamily_t *family);
|
||||
char *nodefamily_canonicalize(const char *s, const uint8_t *rsa_id_self,
|
||||
unsigned flags);
|
||||
|
||||
void nodefamily_free_all(void);
|
||||
|
||||
|
@ -610,6 +610,36 @@ test_nodelist_node_nodefamily(void *arg)
|
||||
smartlist_free(nodes);
|
||||
}
|
||||
|
||||
static void
|
||||
test_nodelist_nodefamily_canonicalize(void *arg)
|
||||
{
|
||||
(void)arg;
|
||||
char *c = NULL;
|
||||
|
||||
c = nodefamily_canonicalize("", NULL, 0);
|
||||
tt_str_op(c, OP_EQ, "");
|
||||
tor_free(c);
|
||||
|
||||
uint8_t own_id[20];
|
||||
memset(own_id, 0, sizeof(own_id));
|
||||
c = nodefamily_canonicalize(
|
||||
"alice BOB caroL %potrzebie !!!@#@# "
|
||||
"$bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb=fred "
|
||||
"ffffffffffffffffffffffffffffffffffffffff "
|
||||
"$cccccccccccccccccccccccccccccccccccccccc ", own_id, 0);
|
||||
tt_str_op(c, OP_EQ,
|
||||
"!!!@#@# "
|
||||
"$0000000000000000000000000000000000000000 "
|
||||
"$BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB "
|
||||
"$CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC "
|
||||
"$FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF "
|
||||
"%potrzebie "
|
||||
"alice bob carol");
|
||||
|
||||
done:
|
||||
tor_free(c);
|
||||
}
|
||||
|
||||
#define NODE(name, flags) \
|
||||
{ #name, test_nodelist_##name, (flags), NULL, NULL }
|
||||
|
||||
@ -623,5 +653,6 @@ struct testcase_t nodelist_tests[] = {
|
||||
NODE(nodefamily_lookup, TT_FORK),
|
||||
NODE(nickname_matches, 0),
|
||||
NODE(node_nodefamily, TT_FORK),
|
||||
NODE(nodefamily_canonicalize, 0),
|
||||
END_OF_TESTCASES
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user