From 976c8f8a71b8dac7dc683e54cce02fcfe4146780 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Wed, 10 Oct 2007 20:06:38 +0000 Subject: [PATCH] r15646@catbus: nickm | 2007-10-10 16:01:54 -0400 Fix some memory leaks when serving v3 networkstatus documents and v3 certs. Generate 503 correctly when serving v3 networkstatus documents and v3 certs. svn:r11850 --- ChangeLog | 4 ++++ src/or/directory.c | 45 +++++++++++++++++++++++++++++++++------------ 2 files changed, 37 insertions(+), 12 deletions(-) diff --git a/ChangeLog b/ChangeLog index 34c59d4f1..395e5360d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -29,6 +29,8 @@ Changes in version 0.2.0.8-alpha - 2007-10-12 - Add more ways for tools to download the votes that lead to the current consensus. - Caches now download v3 network status documents as needed. + - Send a 503 when low on bandwidth and a vote, consensus, or certificate + is requested. o Minor features (network statuses): - Tweak the implementation of proposal 109 slightly: allow at most @@ -57,6 +59,8 @@ Changes in version 0.2.0.8-alpha - 2007-10-12 not on our preferred schedule. - Make the return values and messages from signature uploads and downloads more sensible. + - Fix a memory leak when serving votes and consensus documents, and + another when serving certificates. o Minor bugfixes (performance): - Use a slightly simpler string hashing algorithm (copying Python's diff --git a/src/or/directory.c b/src/or/directory.c index ba69bb75f..9dd218b4b 100644 --- a/src/or/directory.c +++ b/src/or/directory.c @@ -2161,9 +2161,10 @@ directory_handle_command_get(dir_connection_t *conn, const char *headers, if (!strcmpstart(url,"/tor/status-vote/current/") || !strcmpstart(url,"/tor/status-vote/next/")) { - /*XXXX020 implement if-modified-since and 503-rate-limiting */ + /*XXXX020 implement if-modified-since */ int current = 1; ssize_t body_len = 0; + ssize_t estimated_len = 0; smartlist_t *items = smartlist_create(); smartlist_t *dir_items = smartlist_create(); int lifetime = 60; /* XXXX020 should actually use vote intervals. */ @@ -2211,13 +2212,24 @@ directory_handle_command_get(dir_connection_t *conn, const char *headers, } if (!smartlist_len(dir_items) && !smartlist_len(items)) { write_http_status_line(conn, 404, "Not found"); - goto done; + goto vote_done; } - SMARTLIST_FOREACH(items, const char *, item, - if (!deflated) - body_len += strlen(item)); SMARTLIST_FOREACH(dir_items, cached_dir_t *, d, body_len += deflated ? d->dir_z_len : d->dir_len); + estimated_len += body_len; + SMARTLIST_FOREACH(items, const char *, item, { + size_t ln = strlen(item); + if (deflated) { + body_len += ln; estimated_len += ln; + } else { + estimated_len += ln/2; + } + }); + + if (global_write_bucket_low(TO_CONN(conn), estimated_len, 1)) { + write_http_status_line(conn, 503, "Directory busy, try again later."); + goto vote_done; + } write_http_response_header(conn, body_len ? body_len : -1, deflated, lifetime); @@ -2237,6 +2249,9 @@ directory_handle_command_get(dir_connection_t *conn, const char *headers, deflated ? d->dir_z_len : d->dir_len, TO_CONN(conn))); } + vote_done: + smartlist_free(items); + smartlist_free(dir_items); goto done; } @@ -2306,6 +2321,7 @@ directory_handle_command_get(dir_connection_t *conn, const char *headers, } if (!strcmpstart(url,"/tor/keys/")) { + /*XXXX020 implement if-modified-since */ smartlist_t *certs = smartlist_create(); ssize_t len = -1; if (!strcmp(url, "/tor/keys/all")) { @@ -2345,19 +2361,23 @@ directory_handle_command_get(dir_connection_t *conn, const char *headers, } else { write_http_status_line(conn, 400, "Bad request"); smartlist_free(certs); - goto done; + goto keys_done; } if (!smartlist_len(certs)) { write_http_status_line(conn, 404, "Not found"); smartlist_free(certs); - goto done; + goto keys_done; } - if (!deflated) { - len = 0; - SMARTLIST_FOREACH(certs, authority_cert_t *, c, - len += c->cache_info.signed_descriptor_len); + len = 0; + SMARTLIST_FOREACH(certs, authority_cert_t *, c, + len += c->cache_info.signed_descriptor_len); + + if (global_write_bucket_low(TO_CONN(conn), deflated?len/2:len, 1)) { + write_http_status_line(conn, 503, "Directory busy, try again later."); + goto keys_done; } - write_http_response_header(conn, len, deflated, 60*60); + + write_http_response_header(conn, deflated?-1:len, deflated, 60*60); if (deflated) { conn->zlib_state = tor_zlib_new(1, ZLIB_METHOD); SMARTLIST_FOREACH(certs, authority_cert_t *, c, @@ -2371,6 +2391,7 @@ directory_handle_command_get(dir_connection_t *conn, const char *headers, c->cache_info.signed_descriptor_len, TO_CONN(conn))); } + keys_done: smartlist_free(certs); goto done; }