|
@@ -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,
|