Loading src/feature/nodelist/nodefamily.c +43 −2 Original line number Diff line number Diff line Loading @@ -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. **/ Loading @@ -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; Loading @@ -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) { Loading src/feature/nodelist/nodefamily.h +4 −1 Original line number Diff line number Diff line Loading @@ -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)) Loading @@ -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); Loading src/test/test_nodelist.c +31 −0 Original line number Diff line number Diff line Loading @@ -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 } Loading @@ -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
src/feature/nodelist/nodefamily.c +43 −2 Original line number Diff line number Diff line Loading @@ -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. **/ Loading @@ -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; Loading @@ -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) { Loading
src/feature/nodelist/nodefamily.h +4 −1 Original line number Diff line number Diff line Loading @@ -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)) Loading @@ -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); Loading
src/test/test_nodelist.c +31 −0 Original line number Diff line number Diff line Loading @@ -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 } Loading @@ -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 };