diff --git a/changes/bug3327 b/changes/bug3327 index 32a8b9cd02..454eb3156c 100644 --- a/changes/bug3327 +++ b/changes/bug3327 @@ -6,3 +6,9 @@ to re-publish itself because it has done so too recently, even though the authorities decided not to list its recent-enough descriptor. Fix for bug 3327. + + o Minor features: + - Relays now include a reason for regenerating their descriptors + an HTTP header when uploading to the authorities. This will + make it easier to debug descriptor-upload issues in the future. + diff --git a/src/or/directory.c b/src/or/directory.c index 6055ae38dd..f56a63c08c 100644 --- a/src/or/directory.c +++ b/src/or/directory.c @@ -1228,12 +1228,18 @@ directory_send_command(dir_connection_t *conn, httpcommand = "GET"; tor_asprintf(&url, "/tor/micro/%s", resource); break; - case DIR_PURPOSE_UPLOAD_DIR: + case DIR_PURPOSE_UPLOAD_DIR: { + const char *why = router_get_descriptor_gen_reason(); tor_assert(!resource); tor_assert(payload); httpcommand = "POST"; url = tor_strdup("/tor/"); + if (why) { + tor_asprintf(&header, "X-Desc-Gen-Reason: %s\r\n", why); + smartlist_add(headers, header); + } break; + } case DIR_PURPOSE_UPLOAD_VOTE: tor_assert(!resource); tor_assert(payload); diff --git a/src/or/router.c b/src/or/router.c index ccaa1398fd..07a65999bd 100644 --- a/src/or/router.c +++ b/src/or/router.c @@ -1220,9 +1220,14 @@ router_get_advertised_dir_port(const or_options_t *options, uint16_t dirport) static routerinfo_t *desc_routerinfo = NULL; /** My extrainfo */ static extrainfo_t *desc_extrainfo = NULL; +/** Why did we most recently decide to regenerate our descriptor? Used to + * tell the authorities why we're sending it to them. */ +static const char *desc_gen_reason = NULL; /** Since when has our descriptor been "clean"? 0 if we need to regenerate it * now. */ static time_t desc_clean_since = 0; +/** Why did we mark the descriptor dirty? */ +static const char *desc_dirty_reason = NULL; /** Boolean: do we need to regenerate the above? */ static int desc_needs_upload = 0; @@ -1389,6 +1394,14 @@ router_get_my_extrainfo(void) return desc_extrainfo; } +/** Return a human-readable string describing what triggered us to generate + * our current descriptor, or NULL if we don't know. */ +const char * +router_get_descriptor_gen_reason(void) +{ + return desc_gen_reason; +} + /** A list of nicknames that we've warned about including in our family * declaration verbatim rather than as digests. */ static smartlist_t *warned_nonexistent_family = NULL; @@ -1606,6 +1619,8 @@ router_rebuild_descriptor(int force) desc_clean_since = time(NULL); desc_needs_upload = 1; + desc_gen_reason = desc_dirty_reason; + desc_dirty_reason = NULL; control_event_my_descriptor_changed(); return 0; } @@ -1662,6 +1677,8 @@ mark_my_descriptor_dirty(const char *reason) { desc_clean_since = 0; log_info(LD_OR, "Decided to publish new relay descriptor: %s", reason); + if (!desc_dirty_reason) + desc_dirty_reason = reason; } /** How frequently will we republish our descriptor because of large (factor diff --git a/src/or/router.h b/src/or/router.h index af202e60c4..f9d156cb09 100644 --- a/src/or/router.h +++ b/src/or/router.h @@ -73,6 +73,7 @@ int router_my_exit_policy_is_reject_star(void); const routerinfo_t *router_get_my_routerinfo(void); extrainfo_t *router_get_my_extrainfo(void); const char *router_get_my_descriptor(void); +const char *router_get_descriptor_gen_reason(void); int router_digest_is_me(const char *digest); int router_extrainfo_digest_is_me(const char *digest); int router_is_me(const routerinfo_t *router);