[or-cvs] r10193: Be a lot smarter when parsing lists of routers and extrainfo (in tor/trunk: . src/or)

nickm at seul.org nickm at seul.org
Tue May 15 07:13:58 UTC 2007


Author: nickm
Date: 2007-05-15 03:13:56 -0400 (Tue, 15 May 2007)
New Revision: 10193

Modified:
   tor/trunk/
   tor/trunk/src/or/control.c
   tor/trunk/src/or/dirserv.c
   tor/trunk/src/or/or.h
   tor/trunk/src/or/router.c
   tor/trunk/src/or/routerparse.c
Log:
 r12761 at catbus:  nickm | 2007-05-15 03:13:52 -0400
 Be a lot smarter when parsing lists of routers and extrainfos.



Property changes on: tor/trunk
___________________________________________________________________
 svk:merge ticket from /tor/trunk [r12761] on 8246c3cf-6607-4228-993b-4d95d33730f1

Modified: tor/trunk/src/or/control.c
===================================================================
--- tor/trunk/src/or/control.c	2007-05-14 22:51:05 UTC (rev 10192)
+++ tor/trunk/src/or/control.c	2007-05-15 07:13:56 UTC (rev 10193)
@@ -3032,7 +3032,7 @@
  * been done with it, and also optionally give an explanation/reason. */
 int
 control_event_or_authdir_new_descriptor(const char *action,
-                                        const char *descriptor,
+                                        signed_descriptor_t *desc,
                                         const char *msg)
 {
   char firstline[1024];
@@ -3050,7 +3050,8 @@
                msg ? msg : "");
 
   /* Escape the server descriptor properly */
-  esclen = write_escaped_data(descriptor, strlen(descriptor), 1, &esc);
+  esclen = write_escaped_data(desc->signed_descriptor_body,
+                              desc->signed_descriptor_len, 1, &esc);
 
   totallen = strlen(firstline) + esclen + 1;
   buf = tor_malloc(totallen);

Modified: tor/trunk/src/or/dirserv.c
===================================================================
--- tor/trunk/src/or/dirserv.c	2007-05-14 22:51:05 UTC (rev 10192)
+++ tor/trunk/src/or/dirserv.c	2007-05-15 07:13:56 UTC (rev 10193)
@@ -51,6 +51,8 @@
                                               time_t now);
 static void clear_cached_dir(cached_dir_t *d);
 
+static int dirserv_add_extrainfo(extrainfo_t *ei, const char **msg);
+
 /************** Fingerprint handling code ************/
 
 #define FP_NAMED   1  /**< Listed in fingerprint file. */
@@ -521,84 +523,56 @@
   int r=100; /* higher than any actual return value. */
   int r_tmp;
   const char *msg_out;
+  smartlist_t *list;
+  const char *s;
+  int n_parsed = 0;
 
-  while (desc && *desc) {
-    const char *eos = strstr(desc, "\nrouter-signature");
-    const char *next = NULL;
-    if (eos) {
-      char *next_extra = strstr(eos, "\nextra-info");
-      char *next_routerinfo = strstr(eos, "\nrouter ");
-      if (next_extra)
-        next = next_extra;
-      if (!next || (next_routerinfo && next_routerinfo < next))
-        next = next_routerinfo;
-    }
-    if (next)
-      ++next;
+  s = desc;
+  list = smartlist_create();
+  if (!router_parse_list_from_string(&s, list, SAVED_NOWHERE, 0)) {
+    SMARTLIST_FOREACH(list, routerinfo_t *, ri, {
+        r_tmp = dirserv_add_descriptor(ri, &msg_out);
+        if (r_tmp < r) {
+          r = r_tmp;
+          *msg = msg_out;
+        }
+      });
+  }
+  n_parsed += smartlist_len(list);
+  smartlist_clear(list);
 
-    r_tmp = dirserv_add_descriptor(desc, next, &msg_out);
-    desc = next;
-
-    if (r_tmp < r) {
-      r = r_tmp;
-      *msg = msg_out;
-    }
+  s = desc;
+  if (!router_parse_list_from_string(&s, list, SAVED_NOWHERE, 1)) {
+    SMARTLIST_FOREACH(list, extrainfo_t *, ei, {
+        r_tmp = dirserv_add_extrainfo(ei, &msg_out);
+        if (r_tmp < r) {
+          r = r_tmp;
+          *msg = msg_out;
+        }
+      });
   }
+  n_parsed += smartlist_len(list);
+  smartlist_free(list);
 
-  return r <= 2 ? r : -2;
+  return r <= 2 ? r : 2;
 }
 
-/** Parse the server descriptor at <b>desc</b> and maybe insert it into
- * the list of server descriptors. Set *<b>msg</b> to a message that
- * should be passed back to the origin of this descriptor.
+/** Parse the server descriptor at <b>desc</b> and maybe insert it into the
+ * list of server descriptors. Set *<b>msg</b> to a message that should be
+ * passed back to the origin of this descriptor. DOCDOC no longer parses.
  *
  * Return 2 if descriptor is well-formed and accepted;
  *  1 if well-formed and accepted but origin should hear *msg;
  *  0 if well-formed but redundant with one we already have;
  * -1 if it looks vaguely like a router descriptor but rejected;
- * -2 if we can't find a router descriptor in <b>desc</b>.
  */
 int
-dirserv_add_descriptor(const char *desc, const char *end, const char **msg)
+dirserv_add_descriptor(routerinfo_t *ri, const char **msg)
 {
   int r;
-  routerinfo_t *ri = NULL, *ri_old = NULL;
-  extrainfo_t *ei = NULL;
-  tor_assert(msg);
-  *msg = NULL;
-  desc = eat_whitespace(desc);
+  routerinfo_t *ri_old;
+  signed_descriptor_t *desc = &ri->cache_info;
 
-  if (!strcmpstart(desc, "extra-info")) {
-    /* It's an extra-info thingie. */
-    routerlist_t *rl = router_get_routerlist();
-    ei = extrainfo_parse_entry_from_string(desc, end, 1, rl->identity_map);
-    if (!ei) {
-      log_warn(LD_DIRSERV, "Couldn't parse uploaded extra-info descriptor");
-      *msg = "Rejected: couldn't parse extra-info descriptor";
-      return -2;
-    }
-    ri = router_get_by_digest(ei->cache_info.identity_digest);
-    if (!ri) {
-      *msg = "No corresponding router descriptor for extra-info descriptor";
-      extrainfo_free(ei);
-      return -1;
-    }
-    if (routerinfo_incompatible_with_extrainfo(ri, ei)) {
-      *msg = "Router descriptor incompatible with extra-info descriptor";
-      extrainfo_free(ei);
-      return -1;
-    }
-    router_add_extrainfo_to_routerlist(ei, msg, 0, 0);
-    return 2;
-  }
-
-  /* Check: is the descriptor syntactically valid? */
-  ri = router_parse_entry_from_string(desc, end, 1);
-  if (!ri) {
-    log_warn(LD_DIRSERV, "Couldn't parse uploaded server descriptor");
-    *msg = "Rejected: Couldn't parse server descriptor.";
-    return -2;
-  }
   /* Check whether this descriptor is semantically identical to the last one
    * from this server.  (We do this here and not in router_add_to_routerlist
    * because we want to be able to accept the newest router descriptor that
@@ -636,6 +610,29 @@
   }
 }
 
+/** DOCDOC */
+static int
+dirserv_add_extrainfo(extrainfo_t *ei, const char **msg)
+{
+  routerinfo_t *ri;
+  tor_assert(msg);
+  *msg = NULL;
+
+  ri = router_get_by_digest(ei->cache_info.identity_digest);
+  if (!ri) {
+    *msg = "No corresponding router descriptor for extra-info descriptor";
+    extrainfo_free(ei);
+    return -1;
+  }
+  if (routerinfo_incompatible_with_extrainfo(ri, ei)) {
+    *msg = "Router descriptor incompatible with extra-info descriptor";
+    extrainfo_free(ei);
+    return -1;
+  }
+  router_add_extrainfo_to_routerlist(ei, msg, 0, 0);
+  return 2;
+}
+
 /** Remove all descriptors whose nicknames or fingerprints no longer
  * are allowed by our fingerprint list. (Descriptors that used to be
  * good can become bad when we reload the fingerprint list.)

Modified: tor/trunk/src/or/or.h
===================================================================
--- tor/trunk/src/or/or.h	2007-05-14 22:51:05 UTC (rev 10192)
+++ tor/trunk/src/or/or.h	2007-05-15 07:13:56 UTC (rev 10193)
@@ -2487,7 +2487,7 @@
 int control_event_address_mapped(const char *from, const char *to,
                                  time_t expires);
 int control_event_or_authdir_new_descriptor(const char *action,
-                                            const char *descriptor,
+                                            signed_descriptor_t *desc,
                                             const char *msg);
 int control_event_my_descriptor_changed(void);
 int control_event_networkstatus_changed(smartlist_t *statuses);
@@ -2572,8 +2572,7 @@
 void dirserv_free_fingerprint_list(void);
 const char *dirserv_get_nickname_by_digest(const char *digest);
 int dirserv_add_multiple_descriptors(const char *desc, const char **msg);
-int dirserv_add_descriptor(const char *desc, const char *end,
-                           const char **msg);
+int dirserv_add_descriptor(routerinfo_t *ri, const char **msg);
 int getinfo_helper_dirserv_unregistered(control_connection_t *conn,
                                         const char *question, char **answer);
 void dirserv_free_descriptors(void);

Modified: tor/trunk/src/or/router.c
===================================================================
--- tor/trunk/src/or/router.c	2007-05-14 22:51:05 UTC (rev 10192)
+++ tor/trunk/src/or/router.c	2007-05-15 07:13:56 UTC (rev 10193)
@@ -328,7 +328,7 @@
       log_err(LD_GENERAL,"Error initializing descriptor.");
       return -1;
     }
-    if (dirserv_add_descriptor(mydesc, NULL, &m) < 0) {
+    if (dirserv_add_descriptor(router_get_my_routerinfo(), &m) < 0) {
       log_err(LD_GENERAL,"Unable to add own descriptor to directory: %s",
               m?m:"<unknown error>");
       return -1;

Modified: tor/trunk/src/or/routerparse.c
===================================================================
--- tor/trunk/src/or/routerparse.c	2007-05-14 22:51:05 UTC (rev 10192)
+++ tor/trunk/src/or/routerparse.c	2007-05-15 07:13:56 UTC (rev 10193)
@@ -833,13 +833,14 @@
 int
 router_parse_list_from_string(const char **s, smartlist_t *dest,
                               saved_location_t saved_location,
-                              int is_extrainfo)
+                              int want_extrainfo)
 {
   routerinfo_t *router;
   extrainfo_t *extrainfo;
   signed_descriptor_t *signed_desc;
   void *elt;
-  const char *end, *cp, *start;
+  const char *end, *start;
+  int have_extrainfo;
 
   tor_assert(s);
   tor_assert(*s);
@@ -849,60 +850,46 @@
   while (1) {
     *s = eat_whitespace(*s);
     /* Don't start parsing the rest of *s unless it contains a router. */
-    if (is_extrainfo) {
-      if (strcmpstart(*s, "extra-info")!=0)
-        break;
+    if (strcmpstart(*s, "extra-info ")==0) {
+      have_extrainfo = 1;
+    } else  if (strcmpstart(*s, "router ")==0) {
+      have_extrainfo = 0;
     } else {
-      if (strcmpstart(*s, "router ")!=0)
+      /* skip junk. */
+      const char *ei = strstr(*s, "\nextra-info ");
+      const char *ri = strstr(*s, "\nrouter ");
+      if (ri && (!ei || ri < ei)) {
+        have_extrainfo = 0;
+        *s = ri + 1;
+      } else if (ei) {
+        have_extrainfo = 1;
+        *s = ei + 1;
+      } else {
         break;
+      }
     }
-    /* XXXX020 this is hideously complicated.  Can't we just search for the
-     * first -----END SIGNATURE----- and be done with it?  Or the first
-     * -----END SIGNATURE----- after the first \nrouter-signature ?*/
-    if (is_extrainfo && (end = strstr(*s+1, "\nextra-info"))) {
-      cp = end;
-      end++;
-    } else if (!is_extrainfo && (end = strstr(*s+1, "\nrouter "))) {
-      cp = end;
-      end++;
-    } else if ((end = strstr(*s+1, "\ndirectory-signature"))) {
-      cp = end;
-      end++;
-    } else {
-      cp = end = *s+strlen(*s);
-    }
+    end = strstr(*s, "\nrouter-signature");
+    if (end)
+      end = strstr(end, "\n-----END SIGNATURE-----\n");
+    if (end)
+      end += strlen("\n-----END SIGNATURE-----\n");
 
-    while (cp > *s && (!*cp || TOR_ISSPACE(*cp)))
-      --cp;
-    /* cp now points to the last non-space character in this descriptor. */
+    if (!end)
+      break;
 
-    while (cp > *s  && *cp != '\n')
-      --cp;
-    /* cp now points to the first \n before the last non-blank line in this
-     * descriptor */
-
-    if (strcmpstart(cp, "\n-----END SIGNATURE-----\n")) {
-      log_info(LD_DIR, "Ignoring truncated router descriptor.");
-      *s = end;
-      continue;
-    }
-
-    if (is_extrainfo) {
+    if (have_extrainfo && want_extrainfo) {
       routerlist_t *rl = router_get_routerlist();
       extrainfo = extrainfo_parse_entry_from_string(*s, end,
                                        saved_location != SAVED_IN_CACHE,
                                        rl->identity_map);
       signed_desc = &extrainfo->cache_info;
       elt = extrainfo;
-    } else {
+    } else if (!have_extrainfo && !want_extrainfo) {
       router = router_parse_entry_from_string(*s, end,
                                           saved_location != SAVED_IN_CACHE);
       signed_desc = &router->cache_info;
       elt = router;
-    }
-
-    if (!elt) {
-      log_warn(LD_DIR, "Error reading router; skipping");
+    } else {
       *s = end;
       continue;
     }
@@ -2138,7 +2125,6 @@
   s = &start;
   if (!end)
     end = start+strlen(start);
-  memset(counts, 0, sizeof(counts));
   for (i = 0; i < _NIL; ++i)
     counts[i] = 0;
   while (*s < end && (!tok || tok->tp != _EOF)) {



More information about the tor-commits mailing list