[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

[or-cvs] r11126: Eliminate tons of repeated code in directory_handle_command_ (in tor/trunk: . src/or)



Author: nickm
Date: 2007-08-15 15:55:57 -0400 (Wed, 15 Aug 2007)
New Revision: 11126

Modified:
   tor/trunk/
   tor/trunk/src/or/directory.c
Log:
 r14050@Kushana:  nickm | 2007-08-15 15:21:02 -0400
 Eliminate tons of repeated code in directory_handle_command_get.



Property changes on: tor/trunk
___________________________________________________________________
 svk:merge ticket from /tor/trunk [r14050] on c95137ef-5f19-0410-b913-86e773d04f59

Modified: tor/trunk/src/or/directory.c
===================================================================
--- tor/trunk/src/or/directory.c	2007-08-15 19:55:52 UTC (rev 11125)
+++ tor/trunk/src/or/directory.c	2007-08-15 19:55:57 UTC (rev 11126)
@@ -1582,7 +1582,7 @@
  * If <b>cache_lifetime</b> is greater than 0, the content may be cached for
  * up to cache_lifetime seconds.  Otherwise, the content may not be cached. */
 static void
-write_http_response_header(dir_connection_t *conn, ssize_t length,
+write_http_response_header_impl(dir_connection_t *conn, ssize_t length,
                            const char *type, const char *encoding,
                            int cache_lifetime)
 {
@@ -1637,6 +1637,17 @@
   connection_write_to_buf(tmp, strlen(tmp), TO_CONN(conn));
 }
 
+/** DOCDOC */
+static void
+write_http_response_header(dir_connection_t *conn, ssize_t length,
+                           int deflated, int cache_lifetime)
+{
+  write_http_response_header_impl(conn, length,
+                          deflated?"application/octet-stream":"text/plain",
+                          deflated?"deflate":"identity",
+                             cache_lifetime);
+}
+
 /** Helper function: return 1 if there are any dir conns of purpose
  * <b>purpose</b> that are going elsewhere than our own ORPort/Dirport.
  * Else return 0.
@@ -1737,11 +1748,11 @@
                              const char *body, size_t body_len)
 {
   size_t dlen;
-  char *url = NULL; /* XXX020 every exit point needs to free url. this
-                     * function should use 'goto done' for that. */
+  char *url, *url_mem, *header;
   or_options_t *options = get_options();
   time_t if_modified_since = 0;
-  char *header;
+  int deflated = 0;
+  size_t url_len;
 
   /* We ignore the body of a GET request. */
   (void)body;
@@ -1766,8 +1777,15 @@
   }
   log_debug(LD_DIRSERV,"rewritten url as '%s'.", url);
 
-  if (!strcmp(url,"/tor/") || !strcmp(url,"/tor/dir.z")) { /* dir fetch */
-    int deflated = !strcmp(url,"/tor/dir.z");
+  url_mem = url;
+  url_len = strlen(url);
+  deflated = url_len > 2 && !strcmp(url+url_len-2, ".z");
+  if (deflated) {
+    url[url_len-2] = '\0';
+    url_len -= 2;
+  }
+
+  if (!strcmp(url,"/tor/") || !strcmp(url,"/tor/dir")) { /* dir fetch */
     cached_dir_t *d = dirserv_get_directory();
 
     if (!d) {
@@ -1779,13 +1797,11 @@
           !should_delay_dir_fetches(options))
         directory_get_from_dirserver(DIR_PURPOSE_FETCH_DIR,
                                      ROUTER_PURPOSE_GENERAL, NULL, 1);
-      tor_free(url);
-      return 0;
+      goto done;
     }
     if (d->published < if_modified_since) {
       write_http_status_line(conn, 304, "Not modified");
-      tor_free(url);
-      return 0;
+      goto done;
     }
 
     dlen = deflated ? d->dir_z_len : d->dir_len;
@@ -1795,18 +1811,14 @@
                "Client asked for the mirrored directory, but we've been "
                "writing too many bytes lately. Sending 503 Dir busy.");
       write_http_status_line(conn, 503, "Directory busy, try again later");
-      tor_free(url);
-      return 0;
+      goto done;
     }
 
     note_request(url, dlen);
-    tor_free(url);
 
     log_debug(LD_DIRSERV,"Dumping %sdirectory to client.",
               deflated?"deflated ":"");
-    write_http_response_header(conn, dlen,
-                          deflated?"application/octet-stream":"text/plain",
-                          deflated?"deflate":"identity",
+    write_http_response_header(conn, dlen, deflated,
                           FULL_DIR_CACHE_LIFETIME);
     conn->cached_dir = d;
     conn->cached_dir_offset = 0;
@@ -1817,12 +1829,10 @@
     /* Prime the connection with some data. */
     conn->dir_spool_src = DIR_SPOOL_CACHED_DIR;
     connection_dirserv_flushed_some(conn);
-    return 0;
+    goto done;
   }
 
-  if (!strcmp(url,"/tor/running-routers") ||
-      !strcmp(url,"/tor/running-routers.z")) { /* running-routers fetch */
-    int deflated = !strcmp(url,"/tor/running-routers.z");
+  if (!strcmp(url,"/tor/running-routers")) { /* running-routers fetch */
     cached_dir_t *d = dirserv_get_runningrouters();
     if (!d) {
       write_http_status_line(conn, 503, "Directory unavailable");
@@ -1831,13 +1841,11 @@
           !should_delay_dir_fetches(options))
         directory_get_from_dirserver(DIR_PURPOSE_FETCH_RUNNING_LIST,
                                      ROUTER_PURPOSE_GENERAL, NULL, 1);
-      tor_free(url);
-      return 0;
+      goto done;
     }
     if (d->published < if_modified_since) {
       write_http_status_line(conn, 304, "Not modified");
-      tor_free(url);
-      return 0;
+      goto done;
     }
     dlen = deflated ? d->dir_z_len : d->dir_len;
 
@@ -1846,31 +1854,22 @@
                "Client asked for running-routers, but we've been "
                "writing too many bytes lately. Sending 503 Dir busy.");
       write_http_status_line(conn, 503, "Directory busy, try again later");
-      tor_free(url);
-      return 0;
+      goto done;
     }
     note_request(url, dlen);
-    tor_free(url);
-    write_http_response_header(conn, dlen,
-                 deflated?"application/octet-stream":"text/plain",
-                 deflated?"deflate":"identity",
+    write_http_response_header(conn, dlen, deflated,
                  RUNNINGROUTERS_CACHE_LIFETIME);
     connection_write_to_buf(deflated ? d->dir_z : d->dir, dlen, TO_CONN(conn));
-    return 0;
+    goto done;
   }
 
   if (!strcmpstart(url,"/tor/status/")
-      || !strcmp(url, "/tor/status-vote/current/consensus")
-      || !strcmp(url, "/tor/status-vote/current/consensus.z")) {
+      || !strcmp(url, "/tor/status-vote/current/consensus")) {
     /* v2 or v3 network status fetch. */
-    size_t url_len = strlen(url);
-    int deflated = !strcmp(url+url_len-2, ".z");
     smartlist_t *dir_fps = smartlist_create();
     int is_v3 = !strcmpstart(url, "/tor/status-vote");
     const char *request_type = NULL;
     const char *key = url + strlen("/tor/status/");
-    if (deflated)
-      url[url_len-2] = '\0';
     if (!is_v3) {
       dirserv_get_networkstatus_v2_fingerprints(dir_fps, key);
       if (!strcmpstart(key, "fp/"))
@@ -1888,23 +1887,22 @@
       request_type = deflated?"v3.z":"v3";
     }
 
-    tor_free(url);
     if (!smartlist_len(dir_fps)) { /* we failed to create/cache cp */
       write_http_status_line(conn, 503, "Network status object unavailable");
       smartlist_free(dir_fps);
-      return 0;
+      goto done;
     }
 
     if (!dirserv_remove_old_statuses(dir_fps, if_modified_since)) {
       write_http_status_line(conn, 404, "Not found");
       SMARTLIST_FOREACH(dir_fps, char *, cp, tor_free(cp));
       smartlist_free(dir_fps);
-      return 0;
+      goto done;
     } else if (!smartlist_len(dir_fps)) {
       write_http_status_line(conn, 304, "Not modified");
       SMARTLIST_FOREACH(dir_fps, char *, cp, tor_free(cp));
       smartlist_free(dir_fps);
-      return 0;
+      goto done;
     }
 
     dlen = dirserv_estimate_data_size(dir_fps, 0, deflated);
@@ -1915,14 +1913,12 @@
       write_http_status_line(conn, 503, "Directory busy, try again later");
       SMARTLIST_FOREACH(dir_fps, char *, fp, tor_free(fp));
       smartlist_free(dir_fps);
-      return 0;
+      goto done;
     }
 
     // note_request(request_type,dlen);
     (void) request_type;
-    write_http_response_header(conn, -1,
-                 deflated?"application/octet_stream":"text/plain",
-                 deflated?"deflate":NULL,
+    write_http_response_header(conn, -1, deflated,
                  smartlist_len(dir_fps) == 1 ? NETWORKSTATUS_CACHE_LIFETIME:0);
     conn->fingerprint_stack = dir_fps;
     if (! deflated)
@@ -1931,22 +1927,17 @@
     /* Prime the connection with some data. */
     conn->dir_spool_src = DIR_SPOOL_NETWORKSTATUS;
     connection_dirserv_flushed_some(conn);
-
-    return 0;
+    goto done;
   }
 
   if (!strcmpstart(url,"/tor/status-vote/current/") ||
       !strcmpstart(url,"/tor/status-vote/next/")) {
-    char *url_mem = url;
-    size_t url_len = strlen(url);
-    int deflated = !strcmp(url+url_len-2, ".z");
+    /*XXXX020 implement if-modified-since and 503-rate-limiting */
     int current = 1;
     ssize_t body_len = 0;
     smartlist_t *items = smartlist_create();
     smartlist_t *dir_items = smartlist_create();
     int lifetime = 60; /* XXXX020 should actually use vote intervals. */
-    if (deflated)
-      url[url_len-2] = '\0';
     url += strlen("/tor/status-vote/");
     current = !strcmpstart(url, "current/");
     url = strchr(url, '/');
@@ -1981,17 +1972,14 @@
     }
     if (!smartlist_len(dir_items) && !smartlist_len(items)) {
       write_http_status_line(conn, 404, "Not found");
-      tor_free(url_mem);
-      return 0;
+      goto 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);
-    write_http_response_header(conn, body_len ? body_len : -1,
-                 deflated?"application/octet_stream":"text/plain",
-                 deflated?"deflate":NULL,
+    write_http_response_header(conn, body_len ? body_len : -1, deflated,
                  lifetime);
 
     if (smartlist_len(items)) {
@@ -2010,22 +1998,16 @@
                                   deflated ? d->dir_z_len : d->dir_len,
                                   TO_CONN(conn)));
     }
-    tor_free(url_mem);
-    return 0;
+    goto done;
   }
 
   if (!strcmpstart(url,"/tor/server/") ||
       !strcmpstart(url,"/tor/extra/")) {
-    char *url_mem = url;
-    size_t url_len = strlen(url);
-    int deflated = !strcmp(url+url_len-2, ".z");
     int res;
     const char *msg;
     const char *request_type = NULL;
     int cache_lifetime = 0;
     int is_extra = !strcmpstart(url,"/tor/extra/");
-    if (deflated)
-      url[url_len-2] = '\0';
     url += is_extra ? strlen("/tor/extra/") : strlen("/tor/server/");
     conn->fingerprint_stack = smartlist_create();
     res = dirserv_get_routerdesc_fingerprints(conn->fingerprint_stack, url,
@@ -2056,7 +2038,6 @@
     else
       conn->dir_spool_src =
         is_extra ? DIR_SPOOL_EXTRA_BY_FP : DIR_SPOOL_SERVER_BY_FP;
-    tor_free(url_mem);
 
     if (!dirserv_have_any_serverdesc(conn->fingerprint_stack,
                                      conn->dir_spool_src)) {
@@ -2074,26 +2055,20 @@
                  "Client asked for server descriptors, but we've been "
                  "writing too many bytes lately. Sending 503 Dir busy.");
         write_http_status_line(conn, 503, "Directory busy, try again later");
-        return 0;
+        goto done;
       }
-      write_http_response_header(conn, -1,
-                     deflated?"application/octet_stream":"text/plain",
-                     deflated?"deflate":NULL, cache_lifetime);
+      write_http_response_header(conn, -1, deflated, cache_lifetime);
       if (deflated)
         conn->zlib_state = tor_zlib_new(1, ZLIB_METHOD);
       /* Prime the connection with some data. */
       connection_dirserv_flushed_some(conn);
     }
-    return 0;
+    goto done;
   }
 
   if (!strcmpstart(url,"/tor/keys/")) {
     smartlist_t *certs = smartlist_create();
-    int compressed;
     ssize_t len = -1;
-    compressed = !strcmpend(url, ".z");
-    if (compressed)
-      url[strlen(url)-2] = '\0';
     if (!strcmp(url, "/tor/keys/all")) {
       SMARTLIST_FOREACH(router_get_trusted_dir_servers(),
                         trusted_dir_server_t *, ds,
@@ -2130,26 +2105,21 @@
       smartlist_free(fps);
     } else {
       write_http_status_line(conn, 400, "Bad request");
-      tor_free(url);
       smartlist_free(certs);
-      return 0;
+      goto done;
     }
     if (!smartlist_len(certs)) {
       write_http_status_line(conn, 404, "Not found");
-      tor_free(url);
       smartlist_free(certs);
-      return 0;
+      goto done;
     }
-    if (!compressed) {
+    if (!deflated) {
       len = 0;
       SMARTLIST_FOREACH(certs, authority_cert_t *, c,
                         len += c->cache_info.signed_descriptor_len);
     }
-    write_http_response_header(conn, len,
-                           compressed?"application/octet-stream":"text/plain",
-                           compressed?"deflate":"identity",
-                           60*60);
-    if (compressed) {
+    write_http_response_header(conn, len, deflated, 60*60);
+    if (deflated) {
       conn->zlib_state = tor_zlib_new(1, ZLIB_METHOD);
       SMARTLIST_FOREACH(certs, authority_cert_t *, c,
             connection_write_to_buf_zlib(c->cache_info.signed_descriptor_body,
@@ -2163,7 +2133,7 @@
                                     TO_CONN(conn)));
     }
     smartlist_free(certs);
-    tor_free(url);
+    goto done;
   }
 
   if (options->HSAuthoritativeDir &&
@@ -2178,7 +2148,8 @@
     log_info(LD_REND, "Handling rendezvous descriptor get");
     switch (rend_cache_lookup_desc(query, versioned?-1:0, &descp, &desc_len)) {
       case 1: /* valid */
-        write_http_response_header(conn, desc_len, "application/octet-stream",
+        write_http_response_header_impl(conn, desc_len,
+                                   "application/octet-stream",
                                    NULL, 0);
         note_request("/tor/rendezvous?/", desc_len);
         /* need to send descp separately, because it may include nuls */
@@ -2200,29 +2171,25 @@
         write_http_status_line(conn, 400, "Bad request");
         break;
     }
-    tor_free(url);
-    return 0;
+    goto done;
   }
 
   if (!strcmpstart(url,"/tor/bytes.txt")) {
     char *bytes = directory_dump_request_log();
     size_t len = strlen(bytes);
-    write_http_response_header(conn, len, "text/plain", NULL, 0);
+    write_http_response_header(conn, len, 0, 0);
     connection_write_to_buf(bytes, len, TO_CONN(conn));
     tor_free(bytes);
-    tor_free(url);
-    return 0;
+    goto done;
   }
 
   if (!strcmp(url,"/tor/robots.txt")) { /* /robots.txt will have been
                                            rewritten to /tor/robots.txt */
     char robots[] = "User-agent: *\r\nDisallow: /\r\n";
     size_t len = strlen(robots);
-    write_http_response_header(conn, len, "text/plain", NULL,
-                               ROBOTS_CACHE_LIFETIME);
+    write_http_response_header(conn, len, 0, ROBOTS_CACHE_LIFETIME);
     connection_write_to_buf(robots, len, TO_CONN(conn));
-    tor_free(url);
-    return 0;
+    goto done;
   }
 
   if (!strcmp(url,"/tor/dir-all-weaselhack") &&
@@ -2237,22 +2204,23 @@
       log_warn(LD_BUG, "Error creating full v1 directory.");
       tor_free(new_directory);
       write_http_status_line(conn, 503, "Directory unavailable");
-      return 0;
+      goto done;
     }
 
     dlen = strlen(new_directory);
 
-    write_http_response_header(conn, dlen, "text/plain", "identity", 0);
+    write_http_response_header(conn, dlen, 0, 0);
 
     connection_write_to_buf(new_directory, dlen, TO_CONN(conn));
     tor_free(new_directory);
-    tor_free(url);
-    return 0;
+    goto done;
   }
 
   /* we didn't recognize the url */
   write_http_status_line(conn, 404, "Not found");
-  tor_free(url);
+
+ done:
+  tor_free(url_mem);
   return 0;
 }