aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2004-10-28 18:37:52 +0000
committerNick Mathewson <nickm@torproject.org>2004-10-28 18:37:52 +0000
commit11d330be5e8c0cdb41784673699f18f9d206d4d4 (patch)
tree61b98bc262f16b20150305dc9d0ef75de25386b7
parent36bbab2f2bd8fe8902f4852c240a09de13419325 (diff)
downloadtor-11d330be5e8c0cdb41784673699f18f9d206d4d4.tar
tor-11d330be5e8c0cdb41784673699f18f9d206d4d4.tar.gz
Tweaks to prevent obsolete restarting tors from hammering the dirservers. (1) Cache a received directory as soon as the signature checks out. (2) Treat a cached directory as "recent" based on its mtime. (3) If we have a recent directory, we dont need to fetch a newer one for DirFetchPostPeriod. This needs review!
svn:r2618
-rw-r--r--src/or/directory.c2
-rw-r--r--src/or/dirserv.c7
-rw-r--r--src/or/main.c11
-rw-r--r--src/or/or.h3
-rw-r--r--src/or/routerlist.c26
-rw-r--r--src/or/routerparse.c4
6 files changed, 35 insertions, 18 deletions
diff --git a/src/or/directory.c b/src/or/directory.c
index 038e4865b..998e3539b 100644
--- a/src/or/directory.c
+++ b/src/or/directory.c
@@ -585,7 +585,7 @@ connection_dir_client_reached_eof(connection_t *conn)
} else {
log_fn(LOG_INFO,"updated routers.");
}
- directory_has_arrived(); /* do things we've been waiting to do */
+ directory_has_arrived(time(NULL)); /* do things we've been waiting to do */
}
if(conn->purpose == DIR_PURPOSE_FETCH_RUNNING_LIST) {
diff --git a/src/or/dirserv.c b/src/or/dirserv.c
index 551c17f9f..56b2167d0 100644
--- a/src/or/dirserv.c
+++ b/src/or/dirserv.c
@@ -750,7 +750,6 @@ size_t dirserv_get_directory(const char **directory, int compress)
static int dirserv_regenerate_directory(void)
{
char *new_directory;
- char filename[512];
new_directory = tor_malloc(MAX_DIR_SIZE);
if (dirserv_dump_directory_to_string(new_directory, MAX_DIR_SIZE,
@@ -783,12 +782,6 @@ static int dirserv_regenerate_directory(void)
exit(0);
}
tor_free(new_directory);
- if(get_data_directory(&options)) {
- tor_snprintf(filename,sizeof(filename),"%s/cached-directory", get_data_directory(&options));
- if(write_str_to_file(filename,the_directory,0) < 0) {
- log_fn(LOG_WARN, "Couldn't write cached directory to disk. Ignoring.");
- }
- }
the_directory_is_dirty = 0;
return 0;
diff --git a/src/or/main.c b/src/or/main.c
index 09836af4c..a85ab53af 100644
--- a/src/or/main.c
+++ b/src/or/main.c
@@ -31,6 +31,9 @@ static uint64_t stats_n_bytes_read = 0;
static uint64_t stats_n_bytes_written = 0;
/** How many seconds have we been running? */
long stats_n_seconds_uptime = 0;
+/** When do we next download a directory? */
+static time_t time_to_fetch_directory = 0;
+
/** Array of all open connections; each element corresponds to the element of
* poll_array in the same position. The first nfds elements are valid. */
@@ -359,11 +362,16 @@ static void conn_close_if_marked(int i) {
}
/** This function is called whenever we successfully pull down a directory */
-void directory_has_arrived(void) {
+void directory_has_arrived(time_t now) {
log_fn(LOG_INFO, "A directory has arrived.");
has_fetched_directory=1;
+ /* Don't try to upload or download anything for DirFetchPostPeriod
+ * seconds after the directory we had when we started.
+ */
+ if (!time_to_fetch_directory)
+ time_to_fetch_directory = now + options.DirFetchPostPeriod;
if(server_mode()) { /* connect to the appropriate routers */
router_retry_connections();
@@ -496,7 +504,6 @@ int proxy_mode(void) {
* second by prepare_for_poll.
*/
static void run_scheduled_events(time_t now) {
- static long time_to_fetch_directory = 0;
static time_t last_uploaded_services = 0;
static time_t last_rotated_certificate = 0;
static time_t time_to_check_listeners = 0;
diff --git a/src/or/or.h b/src/or/or.h
index 38f0e553e..4f2aee9c4 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -1249,7 +1249,7 @@ int connection_is_writing(connection_t *conn);
void connection_stop_writing(connection_t *conn);
void connection_start_writing(connection_t *conn);
-void directory_has_arrived(void);
+void directory_has_arrived(time_t now);
int authdir_mode(void);
int clique_mode(void);
int server_mode(void);
@@ -1454,6 +1454,7 @@ routerinfo_t *router_get_by_hexdigest(const char *hexdigest);
routerinfo_t *router_get_by_digest(const char *digest);
int router_digest_is_trusted_dir(const char *digest);
void router_get_routerlist(routerlist_t **prouterlist);
+time_t routerlist_get_published_time(void);
void routerlist_free(routerlist_t *routerlist);
void routerinfo_free(routerinfo_t *router);
routerinfo_t *routerinfo_copy(const routerinfo_t *router);
diff --git a/src/or/routerlist.c b/src/or/routerlist.c
index 93f8e1652..65479536b 100644
--- a/src/or/routerlist.c
+++ b/src/or/routerlist.c
@@ -48,19 +48,29 @@ extern int has_fetched_directory; /**< from main.c */
int router_reload_router_list(void)
{
char filename[512];
+ int is_recent;
+ struct stat st;
if (get_data_directory(&options)) {
char *s;
tor_snprintf(filename,sizeof(filename),"%s/cached-directory", get_data_directory(&options));
+ if (stat(filename, &st)) {
+ log_fn(LOG_WARN, "Unable to check status for '%s': %s", filename,
+ strerror(errno));
+ return 0;
+ }
s = read_file_to_str(filename,0);
if (s) {
tor_strstrip(s,"\r"); /* XXXX This is a bug workaround for win32. */
log_fn(LOG_INFO, "Loading cached directory from %s", filename);
- if (router_load_routerlist_from_directory(s, NULL, 0) < 0) {
+ is_recent = st.st_mtime > time(NULL) - 60*15;
+ if (router_load_routerlist_from_directory(s, NULL, is_recent) < 0) {
log_fn(LOG_WARN, "Cached directory '%s' was unparseable; ignoring.", filename);
}
- if(routerlist && routerlist->published_on > time(NULL) - OLD_MIN_ONION_KEY_LIFETIME/2) {
+ if(routerlist &&
+ ((routerlist->published_on > time(NULL) - OLD_MIN_ONION_KEY_LIFETIME/2)
+ || is_recent)) {
/* XXX use new onion key lifetime when 0.0.8 servers are obsolete */
- directory_has_arrived(); /* do things we've been waiting to do */
+ directory_has_arrived(st.st_mtime); /* do things we've been waiting to do */
}
tor_free(s);
}
@@ -633,6 +643,12 @@ void router_get_routerlist(routerlist_t **prouterlist) {
*prouterlist = routerlist;
}
+/** Return the publication time on the current routerlist, or 0 if we have no
+ * routerlist. */
+time_t routerlist_get_published_time(void) {
+ return routerlist ? routerlist->published_on : 0;
+}
+
/** Free all storage held by <b>router</b>. */
void routerinfo_free(routerinfo_t *router)
{
@@ -851,10 +867,6 @@ int router_load_routerlist_from_directory(const char *s,
if (options.AuthoritativeDir) {
/* Learn about the descriptors in the directory. */
dirserv_load_from_directory_string(s);
- } else {
- /* Remember the directory. */
- if(dir_is_recent)
- dirserv_set_cached_directory(s, routerlist->published_on);
}
return 0;
}
diff --git a/src/or/routerparse.c b/src/or/routerparse.c
index 71bd0f421..9a792292f 100644
--- a/src/or/routerparse.c
+++ b/src/or/routerparse.c
@@ -343,6 +343,10 @@ router_parse_routerlist_from_directory(const char *str,
smartlist_free(tokens);
tokens = NULL;
+ /* Now that we know the signature is okay, cache the directory. */
+ /* XXXX009 extract published time if possible. */
+ dirserv_set_cached_directory(str, time(NULL));
+
/* Now that we know the signature is okay, check the version. */
if (check_version)
check_software_version_against_directory(str, options.IgnoreVersion);