Add a function to check for support for "protocol X or later"

Also, add unit tests for this new function and for the regular
"does this list include support for protocol X" code.
This commit is contained in:
Nick Mathewson 2017-09-11 09:50:31 -04:00
parent 67a5d4cb60
commit 362bc880b1
3 changed files with 69 additions and 0 deletions

View File

@ -280,6 +280,42 @@ protocol_list_supports_protocol(const char *list, protocol_type_t tp,
return contains;
}
/**
* Return true iff "list" encodes a protocol list that includes support for
* the indicated protocol and version, or some later version.
*/
int
protocol_list_supports_protocol_or_later(const char *list,
protocol_type_t tp,
uint32_t version)
{
/* NOTE: This is a pretty inefficient implementation. If it ever shows
* up in profiles, we should memoize it.
*/
smartlist_t *protocols = parse_protocol_list(list);
if (!protocols) {
return 0;
}
const char *pr_name = protocol_type_to_str(tp);
int contains = 0;
SMARTLIST_FOREACH_BEGIN(protocols, proto_entry_t *, proto) {
if (strcasecmp(proto->name, pr_name))
continue;
SMARTLIST_FOREACH_BEGIN(proto->ranges, const proto_range_t *, range) {
if (range->high >= version) {
contains = 1;
goto found;
}
} SMARTLIST_FOREACH_END(range);
} SMARTLIST_FOREACH_END(proto);
found:
SMARTLIST_FOREACH(protocols, proto_entry_t *, ent, proto_entry_free(ent));
smartlist_free(protocols);
return contains;
}
/** Return the canonical string containing the list of protocols
* that we support. */
const char *

View File

@ -47,6 +47,9 @@ char *protover_compute_vote(const smartlist_t *list_of_proto_strings,
const char *protover_compute_for_old_tor(const char *version);
int protocol_list_supports_protocol(const char *list, protocol_type_t tp,
uint32_t version);
int protocol_list_supports_protocol_or_later(const char *list,
protocol_type_t tp,
uint32_t version);
void protover_free_all(void);

View File

@ -182,6 +182,35 @@ test_protover_all_supported(void *arg)
tor_free(msg);
}
static void
test_protover_supports_version(void *arg)
{
(void)arg;
tt_assert(protocol_list_supports_protocol("Link=3-6", PRT_LINK, 3));
tt_assert(protocol_list_supports_protocol("Link=3-6", PRT_LINK, 6));
tt_assert(!protocol_list_supports_protocol("Link=3-6", PRT_LINK, 7));
tt_assert(!protocol_list_supports_protocol("Link=3-6", PRT_LINKAUTH, 3));
tt_assert(!protocol_list_supports_protocol("Link=4-6 LinkAuth=3",
PRT_LINKAUTH, 2));
tt_assert(protocol_list_supports_protocol("Link=4-6 LinkAuth=3",
PRT_LINKAUTH, 3));
tt_assert(!protocol_list_supports_protocol("Link=4-6 LinkAuth=3",
PRT_LINKAUTH, 4));
tt_assert(!protocol_list_supports_protocol_or_later("Link=4-6 LinkAuth=3",
PRT_LINKAUTH, 4));
tt_assert(protocol_list_supports_protocol_or_later("Link=4-6 LinkAuth=3",
PRT_LINKAUTH, 3));
tt_assert(protocol_list_supports_protocol_or_later("Link=4-6 LinkAuth=3",
PRT_LINKAUTH, 2));
tt_assert(!protocol_list_supports_protocol_or_later("Link=4-6 LinkAuth=3",
PRT_DESC, 2));
done:
;
}
#define PV_TEST(name, flags) \
{ #name, test_protover_ ##name, (flags), NULL, NULL }
@ -190,6 +219,7 @@ struct testcase_t protover_tests[] = {
PV_TEST(parse_fail, 0),
PV_TEST(vote, 0),
PV_TEST(all_supported, 0),
PV_TEST(supports_version, 0),
END_OF_TESTCASES
};