[or-cvs] Start spooling v2 networkstatus docs as well.

Nick Mathewson nickm at seul.org
Tue Jun 20 00:48:25 UTC 2006


Update of /home/or/cvsroot/tor/src/or
In directory moria:/tmp/cvs-serv18366/src/or

Modified Files:
	directory.c dirserv.c or.h 
Log Message:
Start spooling v2 networkstatus docs as well.

Index: directory.c
===================================================================
RCS file: /home/or/cvsroot/tor/src/or/directory.c,v
retrieving revision 1.380
retrieving revision 1.381
diff -u -p -d -r1.380 -r1.381
--- directory.c	18 Jun 2006 08:46:55 -0000	1.380
+++ directory.c	20 Jun 2006 00:48:23 -0000	1.381
@@ -1418,7 +1418,7 @@ directory_handle_command_get(connection_
     ++d->refcnt;
 
     /* Prime the connection with some data. */
-    conn->dir_refresh_src = DIR_REFRESH_CACHED_DIR;
+    conn->dir_spool_src = DIR_SPOOL_CACHED_DIR;
     connection_dirserv_flushed_some(conn);
     return 0;
   }
@@ -1454,12 +1454,12 @@ directory_handle_command_get(connection_
     /* v2 network status fetch. */
     size_t url_len = strlen(url);
     int deflated = !strcmp(url+url_len-2, ".z");
-    smartlist_t *dir_objs = smartlist_create();
+    smartlist_t *dir_fps = smartlist_create();
     const char *request_type = NULL;
     const char *key = url + strlen("/tor/status/");
     if (deflated)
       url[url_len-2] = '\0';
-    dirserv_get_networkstatus_v2(dir_objs, key);
+    dirserv_get_networkstatus_v2_fingerprints(dir_fps, key);
     if (!strcmpstart(key, "fp/"))
       request_type = deflated?"/tor/status/fp.z":"/tor/status/fp";
     else if (!strcmpstart(key, "authority"))
@@ -1470,32 +1470,29 @@ directory_handle_command_get(connection_
     else
       request_type = "/tor/status/?";
     tor_free(url);
-    if (!smartlist_len(dir_objs)) { /* we failed to create/cache cp */
+    if (!smartlist_len(dir_fps)) { /* we failed to create/cache cp */
       write_http_status_line(conn, 503, "Network status object unavailable");
-      smartlist_free(dir_objs);
+      smartlist_free(dir_fps);
       return 0;
     }
-    dlen = 0;
-    SMARTLIST_FOREACH(dir_objs, cached_dir_t *, d,
-                      dlen += deflated?d->dir_z_len:d->dir_len);
-    note_request(request_type,dlen);
+    // note_request(request_type,dlen);
     format_rfc1123_time(date, time(NULL));
     tor_snprintf(tmp, sizeof(tmp),
-                 "HTTP/1.0 200 OK\r\nDate: %s\r\nContent-Length: %d\r\n"
+                 "HTTP/1.0 200 OK\r\nDate: %s\r\n"
                  "Content-Type: %s\r\nContent-Encoding: %s\r\n\r\n",
                  date,
-                 (int)dlen,
                  deflated?"application/octet-stream":"text/plain",
                  deflated?"deflate":"identity");
     connection_write_to_buf(tmp, strlen(tmp), conn);
-    SMARTLIST_FOREACH(dir_objs, cached_dir_t *, d,
-       {
-         if (deflated)
-           connection_write_to_buf(d->dir_z, d->dir_z_len, conn);
-         else
-           connection_write_to_buf(d->dir, d->dir_len, conn);
-       });
-    smartlist_free(dir_objs);
+
+    conn->fingerprint_stack = dir_fps;
+    if (! deflated)
+      conn->zlib_state = tor_zlib_new(0, ZLIB_METHOD);
+
+    /* Prime the connection with some data. */
+    conn->dir_spool_src = DIR_SPOOL_NETWORKSTATUS;
+    connection_dirserv_flushed_some(conn);
+
     return 0;
   }
 
@@ -1523,9 +1520,9 @@ directory_handle_command_get(connection_
     else
       request_type = "/tor/server/?";
     if (!strcmpstart(url, "/tor/server/d/"))
-      conn->dir_refresh_src = DIR_REFRESH_SERVER_BY_DIGEST;
+      conn->dir_spool_src = DIR_SPOOL_SERVER_BY_DIGEST;
     else
-      conn->dir_refresh_src = DIR_REFRESH_SERVER_BY_FP;
+      conn->dir_spool_src = DIR_SPOOL_SERVER_BY_FP;
     tor_free(url);
     if (res < 0)
       write_http_status_line(conn, 404, msg);

Index: dirserv.c
===================================================================
RCS file: /home/or/cvsroot/tor/src/or/dirserv.c,v
retrieving revision 1.341
retrieving revision 1.342
diff -u -p -d -r1.341 -r1.342
--- dirserv.c	18 Jun 2006 21:30:03 -0000	1.341
+++ dirserv.c	20 Jun 2006 00:48:23 -0000	1.342
@@ -945,11 +945,10 @@ clear_cached_dir(cached_dir_t *d)
 
 /** Free all storage held by the cached_dir_t in <b>d</b>. */
 static void
-free_cached_dir(void *_d)
+_free_cached_dir(void *_d)
 {
   cached_dir_t *d = (cached_dir_t *)_d;
-  clear_cached_dir(d);
-  tor_free(d);
+  cached_dir_decref(d);
 }
 
 /** If we have no cached directory, or it is older than <b>when</b>, then
@@ -978,28 +977,30 @@ dirserv_set_cached_networkstatus_v2(cons
                                     const char *identity,
                                     time_t published)
 {
-  cached_dir_t *d;
+  cached_dir_t *d, *old_d;
   smartlist_t *trusted_dirs;
   if (!cached_v2_networkstatus)
     cached_v2_networkstatus = digestmap_new();
 
-  if (!(d = digestmap_get(cached_v2_networkstatus, identity))) {
-    if (!networkstatus)
-      return;
-    d = tor_malloc_zero(sizeof(cached_dir_t));
-    digestmap_set(cached_v2_networkstatus, identity, d);
-  }
+  old_d = digestmap_get(cached_v2_networkstatus, identity);
+  if (!old_d && !networkstatus)
+    return;
 
-  tor_assert(d);
   if (networkstatus) {
-    if (published > d->published) {
-      set_cached_dir(d, tor_strdup(networkstatus), published);
+    if (!old_d || published > old_d->published) {
+      d = new_cached_dir(tor_strdup(networkstatus), published);
+      digestmap_set(cached_v2_networkstatus, identity, d);
+      if (old_d)
+        cached_dir_decref(old_d);
     }
   } else {
-    free_cached_dir(d);
-    digestmap_remove(cached_v2_networkstatus, identity);
+    if (old_d) {
+      digestmap_remove(cached_v2_networkstatus, identity);
+      cached_dir_decref(old_d);
+    }
   }
 
+  /* Now purge old entries. */
   trusted_dirs = router_get_trusted_dir_servers();
   if (digestmap_size(cached_v2_networkstatus) >
       smartlist_len(trusted_dirs) + MAX_UNTRUSTED_NETWORKSTATUSES) {
@@ -1024,7 +1025,7 @@ dirserv_set_cached_networkstatus_v2(cons
     tor_assert(oldest);
     d = digestmap_remove(cached_v2_networkstatus, oldest);
     if (d)
-      free_cached_dir(d);
+      cached_dir_decref(d);
   }
 }
 
@@ -1209,7 +1210,7 @@ dirserv_get_runningrouters(const char **
 }
 
 /** For authoritative directories: the current (v2) network status */
-static cached_dir_t the_v2_networkstatus = { NULL, NULL, 0, 0, 0, -1 };
+static cached_dir_t *the_v2_networkstatus = NULL;
 
 static int
 should_generate_v2_networkstatus(void)
@@ -1485,13 +1486,14 @@ generate_v2_networkstatus(void)
     goto done;
   }
 
-  set_cached_dir(&the_v2_networkstatus, status, time(NULL));
+  if (the_v2_networkstatus)
+    cached_dir_decref(the_v2_networkstatus);
+  the_v2_networkstatus = new_cached_dir(status, time(NULL));
   status = NULL; /* So it doesn't get double-freed. */
   the_v2_networkstatus_is_dirty = 0;
-  router_set_networkstatus(the_v2_networkstatus.dir, time(NULL), NS_GENERATED,
-                           NULL);
-
-  r = &the_v2_networkstatus;
+  router_set_networkstatus(the_v2_networkstatus->dir,
+                           time(NULL), NS_GENERATED, NULL);
+  r = the_v2_networkstatus;
  done:
   tor_free(client_versions);
   tor_free(server_versions);
@@ -1501,6 +1503,44 @@ generate_v2_networkstatus(void)
   return r;
 }
 
+/* DOCDOC */
+void
+dirserv_get_networkstatus_v2_fingerprints(smartlist_t *result,
+                                          const char *key)
+{
+  tor_assert(result);
+
+  if (!cached_v2_networkstatus)
+    cached_v2_networkstatus = digestmap_new();
+
+  if (should_generate_v2_networkstatus())
+    generate_v2_networkstatus();
+
+  if (!strcmp(key,"authority")) {
+    if (get_options()->AuthoritativeDir) {
+      routerinfo_t *me = router_get_my_routerinfo();
+      if (me)
+        smartlist_add(result,
+                      tor_memdup(me->cache_info.identity_digest, DIGEST_LEN));
+    }
+  } else if (!strcmp(key, "all")) {
+    digestmap_iter_t *iter;
+    iter = digestmap_iter_init(cached_v2_networkstatus);
+    while (!digestmap_iter_done(iter)) {
+      const char *ident;
+      void *val;
+      digestmap_iter_get(iter, &ident, &val);
+      smartlist_add(result, tor_memdup(ident, DIGEST_LEN));
+      iter = digestmap_iter_next(cached_v2_networkstatus, iter);
+    }
+    if (smartlist_len(result) == 0)
+      log_warn(LD_DIRSERV,
+               "Client requested 'all' network status objects; we have none.");
+  } else if (!strcmpstart(key, "fp/")) {
+    dir_split_resource_into_fingerprints(key+3, result, NULL, 1);
+  }
+}
+
 /** Look for a network status object as specified by <b>key</b>, which should
  * be either "authority" (to find a network status generated by us), a hex
  * identity digest (to find a network status generated by given directory), or
@@ -1519,7 +1559,7 @@ dirserv_get_networkstatus_v2(smartlist_t
     if (get_options()->AuthoritativeDir) {
       cached_dir_t *d =
         dirserv_pick_cached_dir_obj(NULL,
-                                    &the_v2_networkstatus,
+                                    the_v2_networkstatus,
                                     the_v2_networkstatus_is_dirty,
                                     generate_v2_networkstatus,
                                     "network status list", 0);
@@ -1747,11 +1787,23 @@ dirserv_orconn_tls_done(const char *addr
  * below this threshold. */
 #define DIRSERV_BUFFER_MIN 16384
 
+static int
+connection_dirserv_finish_spooling(connection_t *conn)
+{
+  if (conn->zlib_state) {
+    connection_write_to_buf_zlib(conn, conn->zlib_state, "", 0, 1);
+    tor_zlib_free(conn->zlib_state);
+    conn->zlib_state = NULL;
+  }
+  conn->dir_spool_src = DIR_SPOOL_NONE;
+  return 0;
+}
+
 /** DOCDOC */
 static int
 connection_dirserv_add_servers_to_outbuf(connection_t *conn)
 {
-  int by_fp = conn->dir_refresh_src == DIR_REFRESH_SERVER_BY_FP;
+  int by_fp = conn->dir_spool_src == DIR_SPOOL_SERVER_BY_FP;
 
   while (smartlist_len(conn->fingerprint_stack) &&
          buf_datalen(conn->outbuf) < DIRSERV_BUFFER_MIN) {
@@ -1785,14 +1837,9 @@ connection_dirserv_add_servers_to_outbuf
 
   if (!smartlist_len(conn->fingerprint_stack)) {
     /* We just wrote the last one; finish up. */
-    if (conn->zlib_state) {
-      connection_write_to_buf_zlib(conn, conn->zlib_state, "", 0, 1);
-      tor_zlib_free(conn->zlib_state);
-      conn->zlib_state = NULL;
-    }
+    connection_dirserv_finish_spooling(conn);
     smartlist_free(conn->fingerprint_stack);
     conn->fingerprint_stack = NULL;
-    conn->dir_refresh_src = DIR_REFRESH_NONE;
   }
   return 0;
 }
@@ -1823,14 +1870,44 @@ connection_dirserv_add_dir_bytes_to_outb
   conn->cached_dir_offset += bytes;
   if (conn->cached_dir_offset == (int)conn->cached_dir->dir_z_len) {
     /* We just wrote the last one; finish up. */
-    if (conn->zlib_state) {
-      connection_write_to_buf_zlib(conn, conn->zlib_state, "", 0, 1);
-      tor_zlib_free(conn->zlib_state);
-      conn->zlib_state = NULL;
-    }
+    if (conn->dir_spool_src == DIR_SPOOL_CACHED_DIR)
+      connection_dirserv_finish_spooling(conn);
     cached_dir_decref(conn->cached_dir);
     conn->cached_dir = NULL;
-    conn->dir_refresh_src = DIR_REFRESH_NONE;
+  }
+  return 0;
+}
+
+static int
+connection_dirserv_add_networkstatus_bytes_to_outbuf(connection_t *conn)
+{
+  int r;
+  while (buf_datalen(conn->outbuf) < DIRSERV_BUFFER_MIN) {
+    if (conn->cached_dir) {
+      if ((r = connection_dirserv_add_dir_bytes_to_outbuf(conn)))
+        return r;
+    } else if (conn->fingerprint_stack &&
+               smartlist_len(conn->fingerprint_stack)) {
+      /* Add another networkstatus; start serving it. */
+      char *fp = smartlist_pop_last(conn->fingerprint_stack);
+      cached_dir_t *d;
+      if (router_digest_is_me(fp))
+        d = the_v2_networkstatus;
+      else
+        d = digestmap_get(cached_v2_networkstatus, fp);
+      tor_free(fp);
+      if (d) {
+        ++d->refcnt;
+        conn->cached_dir = d;
+        conn->cached_dir_offset = 0;
+      }
+    } else {
+      connection_dirserv_finish_spooling(conn);
+      if (conn->fingerprint_stack)
+        smartlist_free(conn->fingerprint_stack);
+      conn->fingerprint_stack = NULL;
+      return 0;
+    }
   }
   return 0;
 }
@@ -1843,16 +1920,18 @@ connection_dirserv_flushed_some(connecti
   tor_assert(conn->type == CONN_TYPE_DIR);
   tor_assert(conn->state == DIR_CONN_STATE_SERVER_WRITING);
 
-  if (conn->dir_refresh_src == DIR_REFRESH_NONE
+  if (conn->dir_spool_src == DIR_SPOOL_NONE
       || buf_datalen(conn->outbuf) >= DIRSERV_BUFFER_MIN)
     return 0;
 
-  switch (conn->dir_refresh_src) {
-    case DIR_REFRESH_SERVER_BY_DIGEST:
-    case DIR_REFRESH_SERVER_BY_FP:
+  switch (conn->dir_spool_src) {
+    case DIR_SPOOL_SERVER_BY_DIGEST:
+    case DIR_SPOOL_SERVER_BY_FP:
       return connection_dirserv_add_servers_to_outbuf(conn);
-    case DIR_REFRESH_CACHED_DIR:
+    case DIR_SPOOL_CACHED_DIR:
       return connection_dirserv_add_dir_bytes_to_outbuf(conn);
+    case DIR_SPOOL_NETWORKSTATUS:
+      return connection_dirserv_add_networkstatus_bytes_to_outbuf(conn);
     default:
       return 0;
   }
@@ -1872,11 +1951,11 @@ dirserv_free_all(void)
   }
   cached_dir_decref(the_directory);
   clear_cached_dir(&the_runningrouters);
-  clear_cached_dir(&the_v2_networkstatus);
+  cached_dir_decref(the_v2_networkstatus);
   cached_dir_decref(cached_directory);
   clear_cached_dir(&cached_runningrouters);
   if (cached_v2_networkstatus) {
-    digestmap_free(cached_v2_networkstatus, free_cached_dir);
+    digestmap_free(cached_v2_networkstatus, _free_cached_dir);
     cached_v2_networkstatus = NULL;
   }
 }

Index: or.h
===================================================================
RCS file: /home/or/cvsroot/tor/src/or/or.h,v
retrieving revision 1.843
retrieving revision 1.844
diff -u -p -d -r1.843 -r1.844
--- or.h	18 Jun 2006 08:46:55 -0000	1.843
+++ or.h	20 Jun 2006 00:48:23 -0000	1.844
@@ -699,9 +699,9 @@ struct connection_t {
                              * for?*/
 /* Used only for server sides of some dir connections. */
   enum {
-    DIR_REFRESH_NONE=0, DIR_REFRESH_SERVER_BY_DIGEST, DIR_REFRESH_SERVER_BY_FP,
-    DIR_REFRESH_CACHED_DIR
-  } dir_refresh_src;
+    DIR_SPOOL_NONE=0, DIR_SPOOL_SERVER_BY_DIGEST, DIR_SPOOL_SERVER_BY_FP,
+    DIR_SPOOL_CACHED_DIR, DIR_SPOOL_NETWORKSTATUS
+  } dir_spool_src;
   smartlist_t *fingerprint_stack;
   struct cached_dir_t *cached_dir;
   off_t cached_dir_offset;
@@ -1938,6 +1938,8 @@ void dirserv_set_cached_networkstatus_v2
                                          const char *identity,
                                          time_t published);
 void dirserv_get_networkstatus_v2(smartlist_t *result, const char *key);
+void dirserv_get_networkstatus_v2_fingerprints(smartlist_t *result,
+                                               const char *key);
 int dirserv_get_routerdesc_fingerprints(smartlist_t *fps_out, const char *key,
                                         const char **msg);
 int dirserv_get_routerdescs(smartlist_t *descs_out, const char *key,



More information about the tor-commits mailing list