Kaynağa Gözat

r16518@catbus: nickm | 2007-11-07 10:18:31 -0500
First attempt at fixing bug 543. Needs testing. Too slow.


svn:r12408

Nick Mathewson 16 yıl önce
ebeveyn
işleme
acaa9a7f69
2 değiştirilmiş dosya ile 75 ekleme ve 9 silme
  1. 3 0
      ChangeLog
  2. 72 9
      src/or/routerlist.c

+ 3 - 0
ChangeLog

@@ -19,6 +19,9 @@ Changes in version 0.2.0.10-alpha - 2007-11-0?
       by Fabian Keil.
     - When the clock jumps forward a lot, do not allow the bandwidth
       buckets to become negative.  Bugfix on 0.1.2.x; fixes Bug 544.
+    - When the consensus lists a router descriptor that we previously were
+      mirroring, but that we considered non-canonical, reload the
+      descriptor as canonical.
 
   o Major bugfixes (v3 dir, bugfixes on 0.2.0.9-alpha):
     - Consider replacing the current consensus when certificates arrive

+ 72 - 9
src/or/routerlist.c

@@ -2464,6 +2464,39 @@ routerlist_replace(routerlist_t *rl, routerinfo_t *ri_old,
 #endif
 }
 
+/** DOCDOC */
+static routerinfo_t *
+routerlist_reparse_old(routerlist_t * rl, signed_descriptor_t *sd)
+{
+  routerinfo_t *ri;
+  const char *body;
+
+  body = signed_descriptor_get_body(sd);
+
+  ri = router_parse_entry_from_string(body, body+sd->signed_descriptor_len,
+                                      0, 0, NULL);
+  if (!ri)
+    return NULL;
+  memcpy(&ri->cache_info, sd, sizeof(signed_descriptor_t));
+  if (sd->signed_descriptor_body) {
+    /* Nasty, but we can't have it get freed. Do better. XXXX020 */
+    ri->cache_info->signed_descriptor_body =
+      tor_strndup(sd->signed_descriptor_body, sd->signed_descriptor_len);
+  }
+
+  /* Awful and inefficient.  Store the index in signed_descriptor_t, or do a
+   * single big linear scan of old_routers, or _something_. XXXX020 */
+  {
+    SMARTLIST_FOREACH(rl->old_routers, signed_descriptor_t *, s,
+                      if (s == sd) {
+                        routerlist_remove_old(rl, s, s_sl_idx);
+                        break;
+                      });
+  }
+
+  return ri;
+}
+
 /** Free all memory held by the routerlist module. */
 void
 routerlist_free_all(void)
@@ -2656,9 +2689,9 @@ router_add_to_routerlist(routerinfo_t *router, const char **msg,
   old_router = rimap_get(routerlist->identity_map,
                          router->cache_info.identity_digest);
   if (old_router) {
-    if (router->cache_info.published_on <=
-        old_router->cache_info.published_on) {
-      /* Same key, but old */
+    if (!in_consensus && (router->cache_info.published_on <=
+                          old_router->cache_info.published_on)) {
+      /* Same key, but old.  This one is not listed in the consensus. */
       log_debug(LD_DIR, "Skipping not-new descriptor for router '%s'",
                 router->nickname);
       /* Only journal this desc if we'll be serving it. */
@@ -2669,7 +2702,7 @@ router_add_to_routerlist(routerinfo_t *router, const char **msg,
       *msg = "Router descriptor was not new.";
       return -1;
     } else {
-      /* Same key, new. */
+      /* Same key, and either new, or listed in the consensus. */
       log_debug(LD_DIR, "Replacing entry for router '%s/%s' [%s]",
                 router->nickname, old_router->nickname,
                 hex_str(id_digest,DIGEST_LEN));
@@ -3704,6 +3737,7 @@ update_consensus_router_descriptor_downloads(time_t now)
 {
   or_options_t *options = get_options();
   digestmap_t *map = NULL;
+  smartlist_t *no_longer_old = smartlist_create();
   smartlist_t *downloadable = smartlist_create();
   int authdir = authdir_mode(options);
   int dirserver = dirserver_mode(options);
@@ -3714,10 +3748,10 @@ update_consensus_router_descriptor_downloads(time_t now)
 
   if (!dirserver) {
     if (rep_hist_circbuilding_dormant(now))
-      return;
+      goto done;
   }
   if (!consensus)
-    return;
+    goto done;
 
   map = digestmap_new();
   list_pending_descriptor_downloads(map, 0);
@@ -3730,7 +3764,8 @@ update_consensus_router_descriptor_downloads(time_t now)
         if (!(ri = router_get_by_digest(rs->identity_digest)) ||
             memcmp(ri->cache_info.signed_descriptor_digest,
                    sd->signed_descriptor_digest, DIGEST_LEN)) {
-          ++n_in_oldrouters;
+          smartlist_add(no_longer_old, sd);
+          ++n_in_oldrouters; /* We have it in old_routers. */
         }
         continue; /* We have it already. */
       }
@@ -3754,8 +3789,34 @@ update_consensus_router_descriptor_downloads(time_t now)
       smartlist_add(downloadable, rs->descriptor_digest);
     });
 
+  if (smartlist_len(no_longer_old)) {
+    routerlist_t *rl = router_get_routerlist();
+    /* XXXX020 downgrade to info */
+    log_notice(LD_DIR, "%d router descriptors listed in consensus are "
+               "currently in in old_routers; making them current.",
+               smartlist_len(no_longer_old));
+    log_notice(LD_DIR, "Before: %d in routerlist; %d in old_routers",
+               smartlist_len(rl->routers), smartlist_len(rl->old_routers));
+    SMARTLIST_FOREACH(no_longer_old, signed_descriptor_t *, sd, {
+        const char *msg;
+        int r;
+        routerinfo_t *ri = routerlist_reparse_old(rl, sd);
+        if (!ri) {
+          log_notice(LD_DIR, "Failed to re-parse.");
+          continue;
+        }
+        r = router_add_to_routerlist(ri, &msg, 1, 0);
+        if (r == -1) {
+          log_notice(LD_DIR, "Couldn't add: %s", msg?msg:"???");
+        }
+      });
+    log_notice(LD_DIR, "After: %d in routerlist; %d in old_routers",
+               smartlist_len(rl->routers), smartlist_len(rl->old_routers));
+    routerlist_assert_ok(rl);
+  }
+
   log_info(LD_DIR,
-           "%d routers downloadable. %d delayed; %d present "
+           "%d router descriptors downloadable. %d delayed; %d present "
            "(%d of those in old_routers); %d would_reject; "
            "%d wouldnt_use, %d in progress.",
            smartlist_len(downloadable), n_delayed, n_have, n_in_oldrouters,
@@ -3763,8 +3824,10 @@ update_consensus_router_descriptor_downloads(time_t now)
 
   launch_router_descriptor_downloads(downloadable, now);
 
-  smartlist_free(downloadable);
   digestmap_free(map, NULL);
+ done:
+  smartlist_free(downloadable);
+  smartlist_free(no_longer_old);
 }
 
 /** Launch downloads for router status as needed. */