|
@@ -3651,6 +3651,87 @@ dirvote_format_microdesc_vote_line(char *out_buf, size_t out_buf_len,
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
+/** Array of start and end of consensus methods used for supported
|
|
|
+ microdescriptor formats. */
|
|
|
+static const struct consensus_method_range_t {
|
|
|
+ int low;
|
|
|
+ int high;
|
|
|
+} microdesc_consensus_methods[] = {
|
|
|
+ {MIN_METHOD_FOR_MICRODESC, MIN_METHOD_FOR_A_LINES - 1},
|
|
|
+ {MIN_METHOD_FOR_A_LINES, MIN_METHOD_FOR_P6_LINES - 1},
|
|
|
+ {MIN_METHOD_FOR_P6_LINES, MIN_METHOD_FOR_NTOR_KEY - 1},
|
|
|
+ {MIN_METHOD_FOR_NTOR_KEY, MAX_SUPPORTED_CONSENSUS_METHOD},
|
|
|
+ {-1, -1}
|
|
|
+};
|
|
|
+
|
|
|
+/** Helper type used when generating the microdescriptor lines in a directory
|
|
|
+ * vote. */
|
|
|
+typedef struct microdesc_vote_line_t {
|
|
|
+ int low;
|
|
|
+ int high;
|
|
|
+ microdesc_t *md;
|
|
|
+ struct microdesc_vote_line_t *next;
|
|
|
+} microdesc_vote_line_t;
|
|
|
+
|
|
|
+/** Generate and return a linked list of all the lines that should appear to
|
|
|
+ * describe a router's microdescriptor versions in a directory vote.
|
|
|
+ * Add the generated microdescriptors to <b>microdescriptors_out</b>. */
|
|
|
+vote_microdesc_hash_t *
|
|
|
+dirvote_format_all_microdesc_vote_lines(const routerinfo_t *ri, time_t now,
|
|
|
+ smartlist_t *microdescriptors_out)
|
|
|
+{
|
|
|
+ const struct consensus_method_range_t *cmr;
|
|
|
+ microdesc_vote_line_t *entries = NULL, *ep;
|
|
|
+ vote_microdesc_hash_t *result = NULL;
|
|
|
+
|
|
|
+ /* Generate the microdescriptors. */
|
|
|
+ for (cmr = microdesc_consensus_methods;
|
|
|
+ cmr->low != -1 && cmr->high != -1;
|
|
|
+ cmr++) {
|
|
|
+ microdesc_t *md = dirvote_create_microdescriptor(ri, cmr->low);
|
|
|
+ if (md) {
|
|
|
+ microdesc_vote_line_t *e =
|
|
|
+ tor_malloc_zero(sizeof(microdesc_vote_line_t));
|
|
|
+ e->md = md;
|
|
|
+ e->low = cmr->low;
|
|
|
+ e->high = cmr->high;
|
|
|
+ e->next = entries;
|
|
|
+ entries = e;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /* Compress adjacent identical ones */
|
|
|
+ for (ep = entries; ep; ep = ep->next) {
|
|
|
+ while (ep->next &&
|
|
|
+ fast_memeq(ep->md->digest, ep->next->md->digest, DIGEST256_LEN) &&
|
|
|
+ ep->low == ep->next->high + 1) {
|
|
|
+ microdesc_vote_line_t *next = ep->next;
|
|
|
+ ep->low = next->low;
|
|
|
+ microdesc_free(next->md);
|
|
|
+ ep->next = next->next;
|
|
|
+ tor_free(next);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /* Format them into vote_microdesc_hash_t, and add to microdescriptors_out.*/
|
|
|
+ while ((ep = entries)) {
|
|
|
+ char buf[128];
|
|
|
+ vote_microdesc_hash_t *h;
|
|
|
+ dirvote_format_microdesc_vote_line(buf, sizeof(buf), ep->md,
|
|
|
+ ep->low, ep->high);
|
|
|
+ h = tor_malloc_zero(sizeof(vote_microdesc_hash_t));
|
|
|
+ h->microdesc_hash_line = tor_strdup(buf);
|
|
|
+ h->next = result;
|
|
|
+ result = h;
|
|
|
+ ep->md->last_listed = now;
|
|
|
+ smartlist_add(microdescriptors_out, ep->md);
|
|
|
+ entries = ep->next;
|
|
|
+ tor_free(ep);
|
|
|
+ }
|
|
|
+
|
|
|
+ return result;
|
|
|
+}
|
|
|
+
|
|
|
/** If <b>vrs</b> has a hash made for the consensus method <b>method</b> with
|
|
|
* the digest algorithm <b>alg</b>, decode it and copy it into
|
|
|
* <b>digest256_out</b> and return 0. Otherwise return -1. */
|