aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--changes/bug1638912
-rw-r--r--changes/bug165394
-rw-r--r--changes/decouple_dir_all_unreachable4
-rw-r--r--changes/move_formatting_functions3
-rw-r--r--src/common/container.c6
-rw-r--r--src/common/container.h6
-rw-r--r--src/or/dirvote.c2
-rw-r--r--src/or/main.c44
-rw-r--r--src/or/routerlist.c2
-rw-r--r--src/test/test_containers.c153
10 files changed, 218 insertions, 18 deletions
diff --git a/changes/bug16389 b/changes/bug16389
new file mode 100644
index 0000000000..b7eb35034a
--- /dev/null
+++ b/changes/bug16389
@@ -0,0 +1,12 @@
+ o Hidden Service Enhancement
+ Client now uses an introduction point failure cache to know when to
+ fetch or keep a descriptor in their cache.
+
+ When fetching a descriptor, for every introduction points in it, we look
+ them up in the failure cache to know if we keep the descriptor or not.
+ For this to work, everytime an introduction points is discarded (ex:
+ receiving a NACK), we note it down in our introduction cache. If all
+ introduction points for an onion service are in our failure cache, we
+ discard the descriptor and fetch a new one.
+
+ See rendcache.c for a detailed explanation of the cache's behavior.
diff --git a/changes/bug16539 b/changes/bug16539
new file mode 100644
index 0000000000..8a0b6d251c
--- /dev/null
+++ b/changes/bug16539
@@ -0,0 +1,4 @@
+ o Minor bugfixes (Ed25519):
+ - Fix a memory leak when reading router descriptors with
+ expired Ed25519 certificate. Fixes bug 16539; bugfix on 0.2.7.2-alpha.
+
diff --git a/changes/decouple_dir_all_unreachable b/changes/decouple_dir_all_unreachable
new file mode 100644
index 0000000000..1e57b3dfbd
--- /dev/null
+++ b/changes/decouple_dir_all_unreachable
@@ -0,0 +1,4 @@
+ o Code simplification and refactoring:
+ - Simply the control graph further by deferring the inner body of
+ directory_all_unreachable() into a callback. Closes ticket
+ 16762. \ No newline at end of file
diff --git a/changes/move_formatting_functions b/changes/move_formatting_functions
new file mode 100644
index 0000000000..4ad5806f23
--- /dev/null
+++ b/changes/move_formatting_functions
@@ -0,0 +1,3 @@
+ o Code simplification and refactoring:
+ - Move some format-parsing functions out of crypto.c and
+ crypto_curve25519.c into crypto_format.c and/or util_format.c.
diff --git a/src/common/container.c b/src/common/container.c
index 082afb51ee..636dfb6c57 100644
--- a/src/common/container.c
+++ b/src/common/container.c
@@ -742,7 +742,7 @@ smartlist_sort_strings(smartlist_t *sl)
}
/** Return the most frequent string in the sorted list <b>sl</b> */
-char *
+const char *
smartlist_get_most_frequent_string(smartlist_t *sl)
{
return smartlist_get_most_frequent(sl, compare_string_ptrs_);
@@ -752,7 +752,7 @@ smartlist_get_most_frequent_string(smartlist_t *sl)
* If <b>count_out</b> is provided, set <b>count_out</b> to the
* number of times that string appears.
*/
-char *
+const char *
smartlist_get_most_frequent_string_(smartlist_t *sl, int *count_out)
{
return smartlist_get_most_frequent_(sl, compare_string_ptrs_, count_out);
@@ -1020,7 +1020,7 @@ smartlist_sort_digests256(smartlist_t *sl)
/** Return the most frequent member of the sorted list of DIGEST256_LEN
* digests in <b>sl</b> */
-char *
+const uint8_t *
smartlist_get_most_frequent_digest256(smartlist_t *sl)
{
return smartlist_get_most_frequent(sl, compare_digests256_);
diff --git a/src/common/container.h b/src/common/container.h
index 2a6ba01e62..5abd8b48d9 100644
--- a/src/common/container.h
+++ b/src/common/container.h
@@ -109,9 +109,9 @@ void smartlist_sort_digests(smartlist_t *sl);
void smartlist_sort_digests256(smartlist_t *sl);
void smartlist_sort_pointers(smartlist_t *sl);
-char *smartlist_get_most_frequent_string(smartlist_t *sl);
-char *smartlist_get_most_frequent_string_(smartlist_t *sl, int *count_out);
-char *smartlist_get_most_frequent_digest256(smartlist_t *sl);
+const char *smartlist_get_most_frequent_string(smartlist_t *sl);
+const char *smartlist_get_most_frequent_string_(smartlist_t *sl, int *count_out);
+const uint8_t *smartlist_get_most_frequent_digest256(smartlist_t *sl);
void smartlist_uniq_strings(smartlist_t *sl);
void smartlist_uniq_digests(smartlist_t *sl);
diff --git a/src/or/dirvote.c b/src/or/dirvote.c
index 0f3b77fe28..d8e6ee2229 100644
--- a/src/or/dirvote.c
+++ b/src/or/dirvote.c
@@ -478,7 +478,7 @@ compute_routerstatus_consensus(smartlist_t *votes, int consensus_method,
if (microdesc_digest256_out) {
smartlist_t *digests = smartlist_new();
- const char *best_microdesc_digest;
+ const uint8_t *best_microdesc_digest;
SMARTLIST_FOREACH_BEGIN(votes, vote_routerstatus_t *, rs) {
char d[DIGEST256_LEN];
if (compare_vote_rs(rs, most))
diff --git a/src/or/main.c b/src/or/main.c
index c6dcd2ae95..092014f7fa 100644
--- a/src/or/main.c
+++ b/src/or/main.c
@@ -982,19 +982,18 @@ conn_close_if_marked(int i)
return 1;
}
-/** We've just tried every dirserver we know about, and none of
- * them were reachable. Assume the network is down. Change state
- * so next time an application connection arrives we'll delay it
- * and try another directory fetch. Kill off all the circuit_wait
- * streams that are waiting now, since they will all timeout anyway.
+/** Implementation for directory_all_unreachable. This is done in a callback,
+ * since otherwise it would complicate Tor's control-flow graph beyond all
+ * reason.
*/
-void
-directory_all_unreachable(time_t now)
+static void
+directory_all_unreachable_cb(evutil_socket_t fd, short event, void *arg)
{
- connection_t *conn;
- (void)now;
+ (void)fd;
+ (void)event;
+ (void)arg;
- stats_n_seconds_working=0; /* reset it */
+ connection_t *conn;
while ((conn = connection_get_by_type_state(CONN_TYPE_AP,
AP_CONN_STATE_CIRCUIT_WAIT))) {
@@ -1010,6 +1009,31 @@ directory_all_unreachable(time_t now)
control_event_general_status(LOG_ERR, "DIR_ALL_UNREACHABLE");
}
+static struct event *directory_all_unreachable_cb_event = NULL;
+
+/** We've just tried every dirserver we know about, and none of
+ * them were reachable. Assume the network is down. Change state
+ * so next time an application connection arrives we'll delay it
+ * and try another directory fetch. Kill off all the circuit_wait
+ * streams that are waiting now, since they will all timeout anyway.
+ */
+void
+directory_all_unreachable(time_t now)
+{
+ (void)now;
+
+ stats_n_seconds_working=0; /* reset it */
+
+ if (!directory_all_unreachable_cb_event) {
+ directory_all_unreachable_cb_event =
+ tor_event_new(tor_libevent_get_base(),
+ -1, EV_READ, directory_all_unreachable_cb, NULL);
+ tor_assert(directory_all_unreachable_cb_event);
+ }
+
+ event_active(directory_all_unreachable_cb_event, EV_READ, 1);
+}
+
/** This function is called whenever we successfully pull down some new
* network statuses or server descriptors. */
void
diff --git a/src/or/routerlist.c b/src/or/routerlist.c
index dc48862201..aebbd480d2 100644
--- a/src/or/routerlist.c
+++ b/src/or/routerlist.c
@@ -3295,6 +3295,8 @@ router_add_to_routerlist(routerinfo_t *router, const char **msg,
/* Make sure that it isn't expired. */
if (router->cert_expiration_time < approx_time()) {
+ routerinfo_free(router);
+ *msg = "Some certs on this router are expired.";
return ROUTER_CERTS_EXPIRED;
}
diff --git a/src/test/test_containers.c b/src/test/test_containers.c
index 2ae81bf18d..eb98cc80b4 100644
--- a/src/test/test_containers.c
+++ b/src/test/test_containers.c
@@ -887,7 +887,7 @@ static void
test_container_order_functions(void *arg)
{
int lst[25], n = 0;
- unsigned int lst_2[25];
+ uint32_t lst_2[25];
// int a=12,b=24,c=25,d=60,e=77;
#define median() median_int(lst, n)
@@ -933,6 +933,31 @@ test_container_order_functions(void *arg)
#undef third_quartile
+ double dbls[] = { 1.0, 10.0, 100.0, 1e4, 1e5, 1e6 };
+ tt_assert(1.0 == median_double(dbls, 1));
+ tt_assert(1.0 == median_double(dbls, 2));
+ tt_assert(10.0 == median_double(dbls, 3));
+ tt_assert(10.0 == median_double(dbls, 4));
+ tt_assert(100.0 == median_double(dbls, 5));
+ tt_assert(100.0 == median_double(dbls, 6));
+
+ time_t times[] = { 5, 10, 20, 25, 15 };
+
+ tt_assert(5 == median_time(times, 1));
+ tt_assert(5 == median_time(times, 2));
+ tt_assert(10 == median_time(times, 3));
+ tt_assert(10 == median_time(times, 4));
+ tt_assert(15 == median_time(times, 5));
+
+ int32_t int32s[] = { -5, -10, -50, 100 };
+ tt_int_op(-5, ==, median_int32(int32s, 1));
+ tt_int_op(-10, ==, median_int32(int32s, 2));
+ tt_int_op(-10, ==, median_int32(int32s, 3));
+ tt_int_op(-10, ==, median_int32(int32s, 4));
+
+ long longs[] = { -30, 30, 100, -100, 7 };
+ tt_int_op(7, ==, find_nth_long(longs, 5, 2));
+
done:
;
}
@@ -1078,6 +1103,129 @@ test_container_fp_pair_map(void *arg)
tor_free(v105);
}
+static void
+test_container_smartlist_most_frequent(void *arg)
+{
+ (void) arg;
+ smartlist_t *sl = smartlist_new();
+
+ int count = -1;
+ const char *cp;
+
+ cp = smartlist_get_most_frequent_string_(sl, &count);
+ tt_int_op(count, ==, 0);
+ tt_ptr_op(cp, ==, NULL);
+
+ /* String must be sorted before we call get_most_frequent */
+ smartlist_split_string(sl, "abc:def:ghi", ":", 0, 0);
+
+ cp = smartlist_get_most_frequent_string_(sl, &count);
+ tt_int_op(count, ==, 1);
+ tt_str_op(cp, ==, "ghi"); /* Ties broken in favor of later element */
+
+ smartlist_split_string(sl, "def:ghi", ":", 0, 0);
+ smartlist_sort_strings(sl);
+
+ cp = smartlist_get_most_frequent_string_(sl, &count);
+ tt_int_op(count, ==, 2);
+ tt_ptr_op(cp, !=, NULL);
+ tt_str_op(cp, ==, "ghi"); /* Ties broken in favor of later element */
+
+ smartlist_split_string(sl, "def:abc:qwop", ":", 0, 0);
+ smartlist_sort_strings(sl);
+
+ cp = smartlist_get_most_frequent_string_(sl, &count);
+ tt_int_op(count, ==, 3);
+ tt_ptr_op(cp, !=, NULL);
+ tt_str_op(cp, ==, "def"); /* No tie */
+
+ done:
+ SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp));
+ smartlist_free(sl);
+}
+
+static void
+test_container_smartlist_sort_ptrs(void *arg)
+{
+ (void)arg;
+ int array[10];
+ int *arrayptrs[11];
+ smartlist_t *sl = smartlist_new();
+ unsigned i=0, j;
+
+ for (j = 0; j < ARRAY_LENGTH(array); ++j) {
+ smartlist_add(sl, &array[j]);
+ arrayptrs[i++] = &array[j];
+ if (j == 5) {
+ smartlist_add(sl, &array[j]);
+ arrayptrs[i++] = &array[j];
+ }
+ }
+
+ for (i = 0; i < 10; ++i) {
+ smartlist_shuffle(sl);
+ smartlist_sort_pointers(sl);
+ for (j = 0; j < ARRAY_LENGTH(arrayptrs); ++j) {
+ tt_ptr_op(smartlist_get(sl, j), ==, arrayptrs[j]);
+ }
+ }
+
+ done:
+ smartlist_free(sl);
+}
+
+static void
+test_container_smartlist_strings_eq(void *arg)
+{
+ (void)arg;
+ smartlist_t *sl1 = smartlist_new();
+ smartlist_t *sl2 = smartlist_new();
+#define EQ_SHOULD_SAY(s1,s2,val) \
+ do { \
+ SMARTLIST_FOREACH(sl1, char *, cp, tor_free(cp)); \
+ SMARTLIST_FOREACH(sl2, char *, cp, tor_free(cp)); \
+ smartlist_clear(sl1); \
+ smartlist_clear(sl2); \
+ smartlist_split_string(sl1, (s1), ":", 0, 0); \
+ smartlist_split_string(sl2, (s2), ":", 0, 0); \
+ tt_int_op((val), OP_EQ, smartlist_strings_eq(sl1, sl2)); \
+ } while (0)
+
+ /* Both NULL, so equal */
+ tt_int_op(1, ==, smartlist_strings_eq(NULL, NULL));
+
+ /* One NULL, not equal. */
+ tt_int_op(0, ==, smartlist_strings_eq(NULL, sl1));
+ tt_int_op(0, ==, smartlist_strings_eq(sl1, NULL));
+
+ /* Both empty, both equal. */
+ EQ_SHOULD_SAY("", "", 1);
+
+ /* One empty, not equal */
+ EQ_SHOULD_SAY("", "ab", 0);
+ EQ_SHOULD_SAY("", "xy:z", 0);
+ EQ_SHOULD_SAY("abc", "", 0);
+ EQ_SHOULD_SAY("abc:cd", "", 0);
+
+ /* Different lengths, not equal. */
+ EQ_SHOULD_SAY("hello:world", "hello", 0);
+ EQ_SHOULD_SAY("hello", "hello:friends", 0);
+
+ /* Same lengths, not equal */
+ EQ_SHOULD_SAY("Hello:world", "goodbye:world", 0);
+ EQ_SHOULD_SAY("Hello:world", "Hello:stars", 0);
+
+ /* Actually equal */
+ EQ_SHOULD_SAY("ABC", "ABC", 1);
+ EQ_SHOULD_SAY(" ab : cd : e", " ab : cd : e", 1);
+
+ done:
+ SMARTLIST_FOREACH(sl1, char *, cp, tor_free(cp));
+ SMARTLIST_FOREACH(sl2, char *, cp, tor_free(cp));
+ smartlist_free(sl1);
+ smartlist_free(sl2);
+}
+
#define CONTAINER_LEGACY(name) \
{ #name, test_container_ ## name , 0, NULL, NULL }
@@ -1099,6 +1247,9 @@ struct testcase_t container_tests[] = {
CONTAINER_LEGACY(order_functions),
CONTAINER(di_map, 0),
CONTAINER_LEGACY(fp_pair_map),
+ CONTAINER(smartlist_most_frequent, 0),
+ CONTAINER(smartlist_sort_ptrs, 0),
+ CONTAINER(smartlist_strings_eq, 0),
END_OF_TESTCASES
};