mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-11 05:33:47 +01:00
Expose consensus download statuses on the control port
This commit is contained in:
parent
703254a832
commit
8cf9fe5ba6
176
src/or/control.c
176
src/or/control.c
@ -190,6 +190,8 @@ static void set_cached_network_liveness(int liveness);
|
||||
|
||||
static void flush_queued_events_cb(evutil_socket_t fd, short what, void *arg);
|
||||
|
||||
static char * download_status_to_string(const download_status_t *dl);
|
||||
|
||||
/** Given a control event code for a message event, return the corresponding
|
||||
* log severity. */
|
||||
static inline int
|
||||
@ -2051,6 +2053,166 @@ getinfo_helper_dir(control_connection_t *control_conn,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Turn a download_status_t into a human-readable description in a newly
|
||||
* allocated string. */
|
||||
|
||||
static char *
|
||||
download_status_to_string(const download_status_t *dl)
|
||||
{
|
||||
char *rv = NULL, *tmp;
|
||||
char tbuf[ISO_TIME_LEN+1];
|
||||
const char *schedule_str, *want_authority_str;
|
||||
const char *increment_on_str, *backoff_str;
|
||||
|
||||
if (dl) {
|
||||
/* Get some substrings of the eventual output ready */
|
||||
format_iso_time(tbuf, dl->next_attempt_at);
|
||||
|
||||
switch (dl->schedule) {
|
||||
case DL_SCHED_GENERIC:
|
||||
schedule_str = "DL_SCHED_GENERIC";
|
||||
break;
|
||||
case DL_SCHED_CONSENSUS:
|
||||
schedule_str = "DL_SCHED_CONSENSUS";
|
||||
break;
|
||||
case DL_SCHED_BRIDGE:
|
||||
schedule_str = "DL_SCHED_BRIDGE";
|
||||
break;
|
||||
default:
|
||||
schedule_str = "unknown";
|
||||
break;
|
||||
}
|
||||
|
||||
switch (dl->want_authority) {
|
||||
case DL_WANT_ANY_DIRSERVER:
|
||||
want_authority_str = "DL_WANT_ANY_DIRSERVER";
|
||||
break;
|
||||
case DL_WANT_AUTHORITY:
|
||||
want_authority_str = "DL_WANT_AUTHORITY";
|
||||
break;
|
||||
default:
|
||||
want_authority_str = "unknown";
|
||||
break;
|
||||
}
|
||||
|
||||
switch (dl->increment_on) {
|
||||
case DL_SCHED_INCREMENT_FAILURE:
|
||||
increment_on_str = "DL_SCHED_INCREMENT_FAILURE";
|
||||
break;
|
||||
case DL_SCHED_INCREMENT_ATTEMPT:
|
||||
increment_on_str = "DL_SCHED_INCREMENT_ATTEMPT";
|
||||
break;
|
||||
default:
|
||||
increment_on_str = "unknown";
|
||||
break;
|
||||
}
|
||||
|
||||
switch (dl->backoff) {
|
||||
case DL_SCHED_DETERMINISTIC:
|
||||
backoff_str = "DL_SCHED_DETERMINISTIC";
|
||||
break;
|
||||
case DL_SCHED_RANDOM_EXPONENTIAL:
|
||||
backoff_str = "DL_SCHED_RANDOM_EXPONENTIAL";
|
||||
break;
|
||||
default:
|
||||
backoff_str = "unknown";
|
||||
break;
|
||||
}
|
||||
|
||||
/* Now assemble them */
|
||||
tor_asprintf(&tmp,
|
||||
"next-attempt-at %s\n"
|
||||
"n-download-failures %u\n"
|
||||
"n-download-attempts %u\n"
|
||||
"schedule %s\n"
|
||||
"want-authority %s\n"
|
||||
"increment-on %s\n"
|
||||
"backoff %s\n",
|
||||
tbuf,
|
||||
dl->n_download_failures,
|
||||
dl->n_download_attempts,
|
||||
schedule_str,
|
||||
want_authority_str,
|
||||
increment_on_str,
|
||||
backoff_str);
|
||||
|
||||
if (dl->backoff == DL_SCHED_RANDOM_EXPONENTIAL) {
|
||||
/* Additional fields become relevant in random-exponential mode */
|
||||
tor_asprintf(&rv,
|
||||
"%s"
|
||||
"last-backoff-position %u\n"
|
||||
"last-delay-used %d\n",
|
||||
tmp,
|
||||
dl->last_backoff_position,
|
||||
dl->last_delay_used);
|
||||
tor_free(tmp);
|
||||
} else {
|
||||
/* That was it */
|
||||
rv = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
/** Implementation helper for GETINFO: knows the answers for questions about
|
||||
* download status information. */
|
||||
static int
|
||||
getinfo_helper_downloads(control_connection_t *control_conn,
|
||||
const char *question, char **answer,
|
||||
const char **errmsg)
|
||||
{
|
||||
const char *flavor;
|
||||
download_status_t *dl_to_emit = NULL;
|
||||
|
||||
/* Assert args are sane */
|
||||
tor_assert(control_conn != NULL);
|
||||
tor_assert(question != NULL);
|
||||
tor_assert(answer != NULL);
|
||||
tor_assert(errmsg != NULL);
|
||||
|
||||
/* We check for this later to see if we should supply a default */
|
||||
*errmsg = NULL;
|
||||
|
||||
/* Are we after networkstatus downloads? */
|
||||
if (!strcmpstart(question, "downloads/networkstatus/")) {
|
||||
flavor = question + strlen("downloads/networkstatus/");
|
||||
/*
|
||||
* We get the one for the current bootstrapped status by default, or
|
||||
* take an extra /bootstrap or /running suffix
|
||||
*/
|
||||
if (strcmp(flavor, "ns") == 0) {
|
||||
dl_to_emit = networkstatus_get_dl_status_by_flavor(FLAV_NS);
|
||||
} else if (strcmp(flavor, "ns/bootstrap") == 0) {
|
||||
dl_to_emit = networkstatus_get_dl_status_by_flavor_bootstrap(FLAV_NS);
|
||||
} else if (strcmp(flavor, "ns/running") == 0 ) {
|
||||
dl_to_emit = networkstatus_get_dl_status_by_flavor_running(FLAV_NS);
|
||||
} else if (strcmp(flavor, "microdesc") == 0) {
|
||||
dl_to_emit = networkstatus_get_dl_status_by_flavor(FLAV_MICRODESC);
|
||||
} else if (strcmp(flavor, "microdesc/bootstrap") == 0) {
|
||||
dl_to_emit =
|
||||
networkstatus_get_dl_status_by_flavor_bootstrap(FLAV_MICRODESC);
|
||||
} else if (strcmp(flavor, "microdesc/running") == 0) {
|
||||
dl_to_emit =
|
||||
networkstatus_get_dl_status_by_flavor_running(FLAV_MICRODESC);
|
||||
} else {
|
||||
*errmsg = "Unknown flavor";
|
||||
}
|
||||
}
|
||||
|
||||
if (dl_to_emit) {
|
||||
*answer = download_status_to_string(dl_to_emit);
|
||||
|
||||
return 0;
|
||||
} else {
|
||||
if (!(*errmsg)) {
|
||||
*errmsg = "Unknown error";
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/** Allocate and return a description of <b>circ</b>'s current status,
|
||||
* including its path (if any). */
|
||||
static char *
|
||||
@ -2490,6 +2652,20 @@ static const getinfo_item_t getinfo_items[] = {
|
||||
DOC("config/defaults",
|
||||
"List of default values for configuration options. "
|
||||
"See also config/names"),
|
||||
PREFIX("downloads/networkstatus/", downloads,
|
||||
"Download statuses for networkstatus objects"),
|
||||
DOC("downloads/networkstatus/ns",
|
||||
"Download status for current-mode networkstatus download"),
|
||||
DOC("downloads/networkstatus/ns/bootstrap",
|
||||
"Download status for bootstrap-time networkstatus download"),
|
||||
DOC("downloads/networkstatus/ns/running",
|
||||
"Download status for run-time networkstatus download"),
|
||||
DOC("downloads/networkstatus/microdesc",
|
||||
"Download status for current-mode microdesc download"),
|
||||
DOC("downloads/networkstatus/microdesc/bootstrap",
|
||||
"Download status for bootstrap-time microdesc download"),
|
||||
DOC("downloads/networkstatus/microdesc/running",
|
||||
"Download status for run-time microdesc download"),
|
||||
ITEM("info/names", misc,
|
||||
"List of GETINFO options, types, and documentation."),
|
||||
ITEM("events/names", misc,
|
||||
|
@ -1179,6 +1179,52 @@ consensus_is_waiting_for_certs(void)
|
||||
? 1 : 0;
|
||||
}
|
||||
|
||||
/** Look up the currently active (depending on bootstrap status) download
|
||||
* status for this consensus flavor and return a pointer to it.
|
||||
*/
|
||||
download_status_t *
|
||||
networkstatus_get_dl_status_by_flavor(consensus_flavor_t flavor)
|
||||
{
|
||||
download_status_t *dl = NULL;
|
||||
const int we_are_bootstrapping =
|
||||
networkstatus_consensus_is_bootstrapping(time(NULL));
|
||||
|
||||
if (flavor <= N_CONSENSUS_FLAVORS) {
|
||||
dl = &((we_are_bootstrapping ?
|
||||
consensus_bootstrap_dl_status : consensus_dl_status)[flavor]);
|
||||
}
|
||||
|
||||
return dl;
|
||||
}
|
||||
|
||||
/** Look up the bootstrap download status for this consensus flavor
|
||||
* and return a pointer to it. */
|
||||
download_status_t *
|
||||
networkstatus_get_dl_status_by_flavor_bootstrap(consensus_flavor_t flavor)
|
||||
{
|
||||
download_status_t *dl = NULL;
|
||||
|
||||
if (flavor <= N_CONSENSUS_FLAVORS) {
|
||||
dl = &(consensus_bootstrap_dl_status[flavor]);
|
||||
}
|
||||
|
||||
return dl;
|
||||
}
|
||||
|
||||
/** Look up the running (non-bootstrap) download status for this consensus
|
||||
* flavor and return a pointer to it. */
|
||||
download_status_t *
|
||||
networkstatus_get_dl_status_by_flavor_running(consensus_flavor_t flavor)
|
||||
{
|
||||
download_status_t *dl = NULL;
|
||||
|
||||
if (flavor <= N_CONSENSUS_FLAVORS) {
|
||||
dl = &(consensus_dl_status[flavor]);
|
||||
}
|
||||
|
||||
return dl;
|
||||
}
|
||||
|
||||
/** Return the most recent consensus that we have downloaded, or NULL if we
|
||||
* don't have one. */
|
||||
networkstatus_t *
|
||||
|
@ -38,6 +38,13 @@ routerstatus_t *networkstatus_vote_find_mutable_entry(networkstatus_t *ns,
|
||||
int networkstatus_vote_find_entry_idx(networkstatus_t *ns,
|
||||
const char *digest, int *found_out);
|
||||
|
||||
download_status_t * networkstatus_get_dl_status_by_flavor(
|
||||
consensus_flavor_t flavor);
|
||||
download_status_t * networkstatus_get_dl_status_by_flavor_bootstrap(
|
||||
consensus_flavor_t flavor);
|
||||
download_status_t * networkstatus_get_dl_status_by_flavor_running(
|
||||
consensus_flavor_t flavor);
|
||||
|
||||
MOCK_DECL(download_status_t *,router_get_dl_status_by_descriptor_digest,
|
||||
(const char *d));
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user