mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-12-06 19:41:15 +01:00
Cache running-routers; compress running-routers; serve compressed running-routers.z
svn:r2883
This commit is contained in:
+9
-6
@@ -780,23 +780,26 @@ directory_handle_command_get(connection_t *conn, char *headers,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(!strcmp(url,"/tor/running-routers")) { /* running-routers fetch */
|
||||
if(!strcmp(url,"/tor/running-routers") ||
|
||||
!strcmp(url,"/tor/running-routers.z")) { /* running-routers fetch */
|
||||
int deflated = !strcmp(url,"/tor/dir.z");
|
||||
tor_free(url);
|
||||
if(!authdir_mode(get_options())) {
|
||||
/* For now, we don't cache running-routers. Reject. */
|
||||
connection_write_to_buf(answer400, strlen(answer400), conn);
|
||||
return 0;
|
||||
}
|
||||
dlen = dirserv_get_runningrouters(&cp);
|
||||
if(!dlen) { /* we failed to create cp */
|
||||
dlen = dirserv_get_runningrouters(&cp, deflated);
|
||||
if(!dlen) { /* we failed to create/cache cp */
|
||||
connection_write_to_buf(answer503, strlen(answer503), conn);
|
||||
return 0;
|
||||
}
|
||||
|
||||
format_rfc1123_time(date, time(NULL));
|
||||
tor_snprintf(tmp, sizeof(tmp), "HTTP/1.0 200 OK\r\nDate: %s\r\nContent-Length: %d\r\nContent-Type: text/plain\r\n\r\n",
|
||||
date,
|
||||
(int)dlen);
|
||||
tor_snprintf(tmp, sizeof(tmp), "HTTP/1.0 200 OK\r\nDate: %s\r\nContent-Length: %d\r\nContent-Type: text/plain\r\nContent-Encoding: %s\r\n\r\n",
|
||||
date,
|
||||
(int)dlen,
|
||||
deflated?"deflate":"identity");
|
||||
connection_write_to_buf(tmp, strlen(tmp), conn);
|
||||
connection_write_to_buf(cp, strlen(cp), conn);
|
||||
return 0;
|
||||
|
||||
+62
-31
@@ -693,53 +693,65 @@ static size_t the_directory_len = 0;
|
||||
static char *the_directory_z = NULL;
|
||||
static size_t the_directory_z_len = 0;
|
||||
|
||||
static char *cached_directory = NULL; /* used only by non-auth dirservers */
|
||||
static size_t cached_directory_len = 0;
|
||||
static char *cached_directory_z = NULL;
|
||||
static size_t cached_directory_z_len = 0;
|
||||
static time_t cached_directory_published = 0;
|
||||
typedef struct cached_dir_t {
|
||||
char *dir;
|
||||
char *dir_z;
|
||||
size_t dir_len;
|
||||
size_t dir_z_len;
|
||||
time_t published;
|
||||
} cached_dir_t;
|
||||
|
||||
/* used only by non-auth dirservers */
|
||||
static cached_dir_t cached_directory = { NULL, NULL, 0, 0, 0 };
|
||||
static cached_dir_t cached_runningrouters = { NULL, NULL, 0, 0, 0 };
|
||||
|
||||
/** If we have no cached directory, or it is older than <b>when</b>, then
|
||||
* replace it with <b>directory</b>, published at <b>when</b>.
|
||||
*/
|
||||
void dirserv_set_cached_directory(const char *directory, time_t when)
|
||||
void dirserv_set_cached_directory(const char *directory, time_t when,
|
||||
int is_running_routers)
|
||||
{
|
||||
time_t now;
|
||||
char filename[512];
|
||||
cached_dir_t *d;
|
||||
tor_assert(!get_options()->AuthoritativeDir);
|
||||
now = time(NULL);
|
||||
if (when<=cached_directory_published) {
|
||||
d = is_running_routers ? &cached_runningrouters : &cached_directory;
|
||||
if (when<=d->published) {
|
||||
log_fn(LOG_INFO, "Ignoring old directory; not caching.");
|
||||
} else if (when>=now+ROUTER_ALLOW_SKEW) {
|
||||
log_fn(LOG_INFO, "Ignoring future directory; not caching.");
|
||||
} else if (when>cached_directory_published &&
|
||||
} else if (when>d->published &&
|
||||
when<now+ROUTER_ALLOW_SKEW) {
|
||||
log_fn(LOG_DEBUG, "Caching directory.");
|
||||
tor_free(cached_directory);
|
||||
cached_directory = tor_strdup(directory);
|
||||
cached_directory_len = strlen(cached_directory);
|
||||
tor_free(cached_directory_z);
|
||||
if (tor_gzip_compress(&cached_directory_z, &cached_directory_z_len,
|
||||
cached_directory, cached_directory_len,
|
||||
tor_free(d->dir);
|
||||
d->dir = tor_strdup(directory);
|
||||
d->dir_len = strlen(directory);
|
||||
tor_free(d->dir_z);
|
||||
if (tor_gzip_compress(&(d->dir_z), &(d->dir_z_len), d->dir, d->dir_len,
|
||||
ZLIB_METHOD)) {
|
||||
log_fn(LOG_WARN,"Error compressing cached directory");
|
||||
}
|
||||
cached_directory_published = when;
|
||||
tor_snprintf(filename,sizeof(filename),"%s/cached-directory", get_options()->DataDirectory);
|
||||
if(write_str_to_file(filename,cached_directory,0) < 0) {
|
||||
log_fn(LOG_WARN, "Couldn't write cached directory to disk. Ignoring.");
|
||||
d->published = when;
|
||||
if (!is_running_routers) {
|
||||
char filename[512];
|
||||
tor_snprintf(filename,sizeof(filename),"%s/cached-directory", get_options()->DataDirectory);
|
||||
if(write_str_to_file(filename,cached_directory.dir,0) < 0) {
|
||||
log_fn(LOG_WARN, "Couldn't write cached directory to disk. Ignoring.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Set *<b>directory</b> to the most recently generated encoded signed
|
||||
* directory, generating a new one as necessary. */
|
||||
* directory, generating a new one as necessary. If not an authoritative
|
||||
* directory may return 0 if no directory is yet cached.*/
|
||||
size_t dirserv_get_directory(const char **directory, int compress)
|
||||
{
|
||||
if (!get_options()->AuthoritativeDir) {
|
||||
if (compress?cached_directory_z:cached_directory) {
|
||||
*directory = compress?cached_directory_z:cached_directory;
|
||||
return compress?cached_directory_z_len:cached_directory_len;
|
||||
cached_dir_t *d = &cached_directory;
|
||||
*directory = compress ? d->dir_z : d->dir;
|
||||
if (*directory) {
|
||||
return compress ? d->dir_z_len : d->dir_len;
|
||||
} else {
|
||||
/* no directory yet retrieved */
|
||||
return 0;
|
||||
@@ -799,8 +811,10 @@ static int dirserv_regenerate_directory(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char *runningrouters_string=NULL;
|
||||
static size_t runningrouters_len=0;
|
||||
static char *the_runningrouters=NULL;
|
||||
static size_t the_runningrouters_len=0;
|
||||
static char *the_runningrouters_z=NULL;
|
||||
static size_t the_runningrouters_z_len=0;
|
||||
|
||||
/** Replace the current running-routers list with a newly generated one. */
|
||||
static int generate_runningrouters(crypto_pk_env_t *private_key)
|
||||
@@ -867,9 +881,16 @@ static int generate_runningrouters(crypto_pk_env_t *private_key)
|
||||
goto err;
|
||||
}
|
||||
|
||||
tor_free(runningrouters_string);
|
||||
runningrouters_string = s;
|
||||
runningrouters_len = strlen(s);
|
||||
tor_free(the_runningrouters);
|
||||
the_runningrouters = s;
|
||||
the_runningrouters_len = strlen(s);
|
||||
tor_free(the_runningrouters_z);
|
||||
if (tor_gzip_compress(&the_runningrouters_z, &the_runningrouters_z_len,
|
||||
the_runningrouters, the_runningrouters_len,
|
||||
ZLIB_METHOD)) {
|
||||
log_fn(LOG_WARN, "Error gzipping runningrouters");
|
||||
return -1;
|
||||
}
|
||||
runningrouters_is_dirty = 0;
|
||||
return 0;
|
||||
err:
|
||||
@@ -881,8 +902,18 @@ static int generate_runningrouters(crypto_pk_env_t *private_key)
|
||||
/** Set *<b>rr</b> to the most recently generated encoded signed
|
||||
* running-routers list, generating a new one as necessary. Return the
|
||||
* size of the directory on success, and 0 on failure. */
|
||||
size_t dirserv_get_runningrouters(const char **rr)
|
||||
size_t dirserv_get_runningrouters(const char **rr, int compress)
|
||||
{
|
||||
if (!get_options()->AuthoritativeDir) {
|
||||
cached_dir_t *d = &cached_runningrouters;
|
||||
*rr = compress ? d->dir_z : d->dir;
|
||||
if (*rr) {
|
||||
return compress ? d->dir_z_len : d->dir_len;
|
||||
} else {
|
||||
/* no directory yet retrieved */
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (runningrouters_is_dirty &&
|
||||
runningrouters_is_dirty + DIR_REGEN_SLACK_TIME < time(NULL)) {
|
||||
if(generate_runningrouters(get_identity_key())) {
|
||||
@@ -890,8 +921,8 @@ size_t dirserv_get_runningrouters(const char **rr)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
*rr = runningrouters_string;
|
||||
return runningrouters_len;
|
||||
*rr = compress ? the_runningrouters_z : the_runningrouters;
|
||||
return compress ? the_runningrouters_z_len : the_runningrouters_len;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+3
-2
@@ -1307,8 +1307,9 @@ int dirserv_dump_directory_to_string(char *s, size_t maxlen,
|
||||
crypto_pk_env_t *private_key);
|
||||
void directory_set_dirty(void);
|
||||
size_t dirserv_get_directory(const char **cp, int compress);
|
||||
size_t dirserv_get_runningrouters(const char **rr);
|
||||
void dirserv_set_cached_directory(const char *directory, time_t when);
|
||||
size_t dirserv_get_runningrouters(const char **rr, int compress);
|
||||
void dirserv_set_cached_directory(const char *directory, time_t when,
|
||||
int is_running_routers);
|
||||
|
||||
/********************************* dns.c ***************************/
|
||||
|
||||
|
||||
@@ -390,7 +390,7 @@ router_parse_routerlist_from_directory(const char *str,
|
||||
if(!get_options()->AuthoritativeDir) {
|
||||
/* Now that we know the signature is okay, and we have a
|
||||
* publication time, cache the directory. */
|
||||
dirserv_set_cached_directory(str, published_on);
|
||||
dirserv_set_cached_directory(str, published_on, 0);
|
||||
}
|
||||
|
||||
if (!(tok = find_first_by_keyword(tokens, K_RECOMMENDED_SOFTWARE))) {
|
||||
@@ -475,6 +475,7 @@ router_parse_routerlist_from_directory(const char *str,
|
||||
return r;
|
||||
}
|
||||
|
||||
/* DOCDOC */
|
||||
running_routers_t *
|
||||
router_parse_runningrouters(const char *str)
|
||||
{
|
||||
@@ -514,6 +515,12 @@ router_parse_runningrouters(const char *str)
|
||||
goto err;
|
||||
}
|
||||
|
||||
if(!get_options()->AuthoritativeDir) {
|
||||
/* Now that we know the signature is okay, and we have a
|
||||
* publication time, cache the list. */
|
||||
dirserv_set_cached_directory(str, published_on, 1);
|
||||
}
|
||||
|
||||
if (!(tok = find_first_by_keyword(tokens, K_ROUTER_STATUS))) {
|
||||
if (!(tok = find_first_by_keyword(tokens, K_RUNNING_ROUTERS))) {
|
||||
log_fn(LOG_WARN,
|
||||
|
||||
Reference in New Issue
Block a user