aboutsummaryrefslogtreecommitdiff
path: root/src/or
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2007-06-02 15:26:57 +0000
committerNick Mathewson <nickm@torproject.org>2007-06-02 15:26:57 +0000
commitaee7f016242c0fea9243be1c82a67b804bfb6792 (patch)
tree6e28814091a4325047b48c2d95131f21ef25a846 /src/or
parent80954dcd2faefe477bd0a3b646ffd3dce3c56481 (diff)
downloadtor-aee7f016242c0fea9243be1c82a67b804bfb6792.tar
tor-aee7f016242c0fea9243be1c82a67b804bfb6792.tar.gz
r13154@catbus: nickm | 2007-06-02 11:26:44 -0400
Server-side support for If-Modified-Since in HTTP requsts for v1 stuff, and for network-status documents. svn:r10451
Diffstat (limited to 'src/or')
-rw-r--r--src/or/directory.c38
-rw-r--r--src/or/dirserv.c27
-rw-r--r--src/or/or.h3
3 files changed, 60 insertions, 8 deletions
diff --git a/src/or/directory.c b/src/or/directory.c
index 087029f4c..3ef2a2233 100644
--- a/src/or/directory.c
+++ b/src/or/directory.c
@@ -1633,9 +1633,11 @@ directory_handle_command_get(dir_connection_t *conn, const char *headers,
const char *body, size_t body_len)
{
size_t dlen;
- const char *cp;
char *url = NULL;
or_options_t *options = get_options();
+ time_t if_modified_since = 0;
+ char *header;
+
/* We ignore the body of a GET request. */
(void)body;
(void)body_len;
@@ -1648,6 +1650,15 @@ directory_handle_command_get(dir_connection_t *conn, const char *headers,
write_http_status_line(conn, 400, "Bad request");
return 0;
}
+ if ((header = http_get_header(headers, "If-Modified-Since: "))) {
+ struct tm tm;
+ if (parse_http_time(header, &tm) == 0) {
+ if_modified_since = tor_timegm(&tm);
+ }
+ /* The correct behavior on a malformed If-Modified-Since header is to
+ * act as if no If-Modified-Since header had been given. */
+ tor_free(header);
+ }
log_debug(LD_DIRSERV,"rewritten url as '%s'.", url);
if (!strcmp(url,"/tor/") || !strcmp(url,"/tor/dir.z")) { /* dir fetch */
@@ -1664,6 +1675,12 @@ directory_handle_command_get(dir_connection_t *conn, const char *headers,
tor_free(url);
return 0;
}
+ if (d->published < if_modified_since) {
+ write_http_status_line(conn, 304, "Not modified");
+ tor_free(url);
+ return 0;
+ }
+
dlen = deflated ? d->dir_z_len : d->dir_len;
if (global_write_bucket_low(TO_CONN(conn), dlen, 1)) {
@@ -1699,8 +1716,8 @@ directory_handle_command_get(dir_connection_t *conn, const char *headers,
if (!strcmp(url,"/tor/running-routers") ||
!strcmp(url,"/tor/running-routers.z")) { /* running-routers fetch */
int deflated = !strcmp(url,"/tor/running-routers.z");
- dlen = dirserv_get_runningrouters(&cp, deflated);
- if (!dlen) { /* we failed to create/cache cp */
+ cached_dir_t *d = dirserv_get_runningrouters();
+ if (!d) {
write_http_status_line(conn, 503, "Directory unavailable");
/* try to get a new one now */
if (!already_fetching_directory(DIR_PURPOSE_FETCH_RUNNING_LIST))
@@ -1708,6 +1725,13 @@ directory_handle_command_get(dir_connection_t *conn, const char *headers,
tor_free(url);
return 0;
}
+ if (d->published < if_modified_since) {
+ write_http_status_line(conn, 304, "Not modified");
+ tor_free(url);
+ return 0;
+ }
+ dlen = deflated ? d->dir_z_len : d->dir_len;
+
if (global_write_bucket_low(TO_CONN(conn), dlen, 1)) {
log_info(LD_DIRSERV,
"Client asked for running-routers, but we've been "
@@ -1722,7 +1746,7 @@ directory_handle_command_get(dir_connection_t *conn, const char *headers,
deflated?"application/octet-stream":"text/plain",
deflated?"deflate":"identity",
RUNNINGROUTERS_CACHE_LIFETIME);
- connection_write_to_buf(cp, strlen(cp), TO_CONN(conn));
+ connection_write_to_buf(deflated ? d->dir_z : d->dir, dlen, TO_CONN(conn));
return 0;
}
@@ -1751,6 +1775,12 @@ directory_handle_command_get(dir_connection_t *conn, const char *headers,
smartlist_free(dir_fps);
return 0;
}
+ if (dirserv_statuses_are_old(dir_fps, if_modified_since)) {
+ write_http_status_line(conn, 304, "Not modified");
+ smartlist_free(dir_fps);
+ return 0;
+ }
+
dlen = dirserv_estimate_data_size(dir_fps, 0, deflated);
if (global_write_bucket_low(TO_CONN(conn), dlen, 2)) {
log_info(LD_DIRSERV,
diff --git a/src/or/dirserv.c b/src/or/dirserv.c
index 31d85a249..82a42af11 100644
--- a/src/or/dirserv.c
+++ b/src/or/dirserv.c
@@ -1279,6 +1279,7 @@ dirserv_pick_cached_dir_obj(cached_dir_t *cache_src,
}
}
+#if 0
/** Helper: If we're authoritative and <b>auth_src</b> is set, use
* <b>auth_src</b>, otherwise use <b>cache_src</b>. If we're using
* <b>auth_src</b> and it's been <b>dirty</b> for at least
@@ -1313,6 +1314,7 @@ dirserv_get_obj(const char **out,
return 0;
}
}
+#endif
/** Return the most recently generated encoded signed v1 directory,
* generating a new one as necessary. If not a v1 authoritative directory
@@ -1418,10 +1420,10 @@ generate_runningrouters(void)
/** 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, int compress)
+cached_dir_t *
+dirserv_get_runningrouters(void)
{
- return dirserv_get_obj(rr, compress,
+ return dirserv_pick_cached_dir_obj(
&cached_runningrouters, &the_runningrouters,
runningrouters_is_dirty,
generate_runningrouters,
@@ -2247,6 +2249,25 @@ dirserv_test_reachability(int try_all)
ctr = (ctr + 1) % 128;
}
+/** Return true iff every networkstatus listed in <b>fps</b> is older
+ * than <b>cutoff</b>. */
+int
+dirserv_statuses_are_old(smartlist_t *fps, time_t cutoff)
+{
+ SMARTLIST_FOREACH(fps, const char *, digest,
+ {
+ cached_dir_t *d;
+ if (router_digest_is_me(digest) && the_v2_networkstatus)
+ d = the_v2_networkstatus;
+ else
+ d = digestmap_get(cached_v2_networkstatus, digest);
+ if (d && d->published > cutoff)
+ return 0;
+ });
+
+ return 1;
+}
+
/** Return an approximate estimate of the number of bytes that will
* be needed to transmit the server descriptors (if is_serverdescs --
* they can be either d/ or fp/ queries) or networkstatus objects (if
diff --git a/src/or/or.h b/src/or/or.h
index 26ec35b4c..9680b8768 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -2670,7 +2670,7 @@ int dirserv_dump_directory_to_string(char **dir_out,
int complete);
void directory_set_dirty(void);
cached_dir_t *dirserv_get_directory(void);
-size_t dirserv_get_runningrouters(const char **rr, int compress);
+cached_dir_t *dirserv_get_runningrouters(void);
void dirserv_set_cached_directory(const char *directory, time_t when,
int is_running_routers);
void dirserv_set_cached_networkstatus_v2(const char *directory,
@@ -2693,6 +2693,7 @@ void dirserv_test_reachability(int try_all);
int authdir_wants_to_reject_router(routerinfo_t *ri, const char **msg,
int complain);
int dirserv_would_reject_router(routerstatus_t *rs);
+int dirserv_statuses_are_old(smartlist_t *fps, time_t cutoff);
size_t dirserv_estimate_data_size(smartlist_t *fps, int is_serverdescs,
int compressed);
int routerstatus_format_entry(char *buf, size_t buf_len,