diff --git a/src/or/dirvote.c b/src/or/dirvote.c index 8be8a57757..2bc30231b3 100644 --- a/src/or/dirvote.c +++ b/src/or/dirvote.c @@ -1068,6 +1068,8 @@ static char *pending_consensus_body = NULL; static char *pending_consensus_signatures = NULL; /** DOCDOC */ static networkstatus_vote_t *pending_consensus = NULL; +/** DOCDOC */ +static smartlist_t *pending_consensus_signature_list = NULL; /** DOCDOC */ void @@ -1094,15 +1096,20 @@ dirvote_perform_vote(void) void dirvote_clear_pending_votes(void) { - if (!pending_vote_list) - return; - SMARTLIST_FOREACH(pending_vote_list, pending_vote_t *, v, { - cached_dir_decref(v->vote_body); - v->vote_body = NULL; - networkstatus_vote_free(v->vote); - tor_free(v); - }); - smartlist_clear(pending_vote_list); + if (pending_vote_list) { + SMARTLIST_FOREACH(pending_vote_list, pending_vote_t *, v, { + cached_dir_decref(v->vote_body); + v->vote_body = NULL; + networkstatus_vote_free(v->vote); + tor_free(v); + }); + smartlist_clear(pending_vote_list); + } + if (pending_consensus_signature_list) { + SMARTLIST_FOREACH(pending_consensus_signature_list, char *, cp, + tor_free(cp)); + smartlist_clear(pending_consensus_signature_list); + } } /** DOCDOC */ @@ -1235,12 +1242,87 @@ dirvote_compute_consensus(void) return -1; } +/** DOCDOC */ +static int +dirvote_add_signatures_to_pending_consensus( + const char *detached_signatures_body, + const char **msg_out) +{ + ns_detached_signatures_t *sigs = NULL; + int r = -1; + char *new_signatures = NULL; + size_t siglen; + + tor_assert(detached_signatures_body); + tor_assert(msg_out); + + /* Only call if we have a pending consensus right now. */ + tor_assert(pending_consensus); + tor_assert(pending_consensus_body); + tor_assert(pending_consensus_signatures); + + *msg_out = NULL; + + if (!(sigs = networkstatus_parse_detached_signatures( + detached_signatures_body, NULL))) { + *msg_out = "Couldn't parse detached signatures."; + goto err; + } + + r = networkstatus_add_detached_signatures(pending_consensus, + sigs, + &new_signatures); + if (new_signatures && (siglen = strlen(new_signatures)) && r >= 0) { + size_t siglen = strlen(new_signatures); + size_t len = strlen(pending_consensus_body); + pending_consensus_body = tor_realloc(pending_consensus_body, + len+siglen+1); + memcpy(pending_consensus_body+len, new_signatures, siglen+1); + + len = strlen(pending_consensus_signatures); + pending_consensus_signatures = tor_realloc(pending_consensus_signatures, + len+siglen+1); + memcpy(pending_consensus_signatures+len, new_signatures, siglen+1); + + log_info(LD_DIR, "Added %d new signatures to the pending consensus.", r); + } + + *msg_out = "ok"; + goto done; + err: + if (!msg_out) + *msg_out = "Unrecognized error while adding detached signatures."; + done: + tor_free(new_signatures); + if (sigs) + ns_detached_signatures_free(sigs); + return r; +} + +/** DOCDOC */ +int +dirvote_add_signatures(const char *detached_signatures_body) +{ + if (pending_consensus) { + const char *msg=NULL; + return dirvote_add_signatures_to_pending_consensus( + detached_signatures_body, &msg); + } else { + if (!pending_consensus_signature_list) + pending_consensus_signature_list = smartlist_create(); + smartlist_add(pending_consensus_signature_list, + tor_strdup(detached_signatures_body)); + return 0; + } +} + /** Release all static storage held in dirvote.c */ void dirvote_free_all(void) { dirvote_clear_pending_votes(); if (pending_vote_list) { + /* now empty as a result of clear_pending_votes. */ smartlist_free(pending_vote_list); pending_vote_list = NULL; } @@ -1250,4 +1332,9 @@ dirvote_free_all(void) networkstatus_vote_free(pending_consensus); pending_consensus = NULL; } + if (pending_consensus_signature_list) { + /* now empty as a result of clear_pending_votes. */ + smartlist_free(pending_consensus_signature_list); + pending_consensus_signature_list = NULL; + } } diff --git a/src/or/or.h b/src/or/or.h index 8b46391e7f..b4dffb2c81 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -2836,6 +2836,7 @@ void dirvote_clear_pending_votes(void); struct pending_vote_t * dirvote_add_vote(const char *vote_body, const char **msg_out); int dirvote_compute_consensus(void); +int dirvote_add_signatures(const char *detached_signatures_body); #ifdef DIRVOTE_PRIVATE int networkstatus_check_voter_signature(networkstatus_vote_t *consensus,