|
@@ -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);
|
|
|
+
|
|
|
|
|
|
* log severity. */
|
|
|
static inline int
|
|
@@ -2051,6 +2053,166 @@ getinfo_helper_dir(control_connection_t *control_conn,
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+ * 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) {
|
|
|
+
|
|
|
+ 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;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ 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) {
|
|
|
+
|
|
|
+ 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 {
|
|
|
+
|
|
|
+ rv = tmp;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return rv;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+ * 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;
|
|
|
+
|
|
|
+
|
|
|
+ tor_assert(control_conn != NULL);
|
|
|
+ tor_assert(question != NULL);
|
|
|
+ tor_assert(answer != NULL);
|
|
|
+ tor_assert(errmsg != NULL);
|
|
|
+
|
|
|
+
|
|
|
+ *errmsg = NULL;
|
|
|
+
|
|
|
+
|
|
|
+ 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;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
|
|
|
* 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,
|