Browse Source

Controllers should now specify cache=no or cache=yes when using
the +POSTDESCRIPTOR command.


svn:r11892

Roger Dingledine 16 years ago
parent
commit
3977ccbc80
6 changed files with 66 additions and 45 deletions
  1. 2 0
      ChangeLog
  2. 7 1
      doc/spec/control-spec.txt
  3. 47 41
      src/or/control.c
  4. 4 1
      src/or/or.h
  5. 1 1
      src/or/router.c
  6. 5 1
      src/or/routerlist.c

+ 2 - 0
ChangeLog

@@ -9,6 +9,8 @@ Changes in version 0.2.0.8-alpha - 2007-10-12
     - Use annotations to record the purpose of each descriptor.
     - Use annotations to record the purpose of each descriptor.
     - Disable the SETROUTERPURPOSE controller command: it is now
     - Disable the SETROUTERPURPOSE controller command: it is now
       obsolete.
       obsolete.
+    - Controllers should now specify cache=no or cache=yes when using
+      the +POSTDESCRIPTOR command.
     - Bridge authorities now write bridge descriptors to disk, meaning
     - Bridge authorities now write bridge descriptors to disk, meaning
       we can export them to other programs and begin distributing them
       we can export them to other programs and begin distributing them
       to blocked users.
       to blocked users.

+ 7 - 1
doc/spec/control-spec.txt

@@ -635,12 +635,18 @@ $Id$
 3.14. POSTDESCRIPTOR
 3.14. POSTDESCRIPTOR
 
 
   Sent from the client to the server. The syntax is:
   Sent from the client to the server. The syntax is:
-    "+POSTDESCRIPTOR" [SP "purpose=" Purpose] CRLF Descriptor CRLF "." CRLF
+    "+POSTDESCRIPTOR" [SP "purpose=" Purpose] [SP "cache=" Cache]
+                      CRLF Descriptor CRLF "." CRLF
 
 
   This message informs the server about a new descriptor. If Purpose is
   This message informs the server about a new descriptor. If Purpose is
   specified, it must be either "general" or "controller", else we
   specified, it must be either "general" or "controller", else we
   return a 552 error.
   return a 552 error.
 
 
+  If Cache is specified, it must be either "no" or "yes", else we
+  return a 552 error. If Cache is not specified, Tor will decide for
+  itself whether it wants to cache the descriptor, and controllers
+  must not rely on its choice.
+
   The descriptor, when parsed, must contain a number of well-specified
   The descriptor, when parsed, must contain a number of well-specified
   fields, including fields for its nickname and identity.
   fields, including fields for its nickname and identity.
 
 

+ 47 - 41
src/or/control.c

@@ -1878,35 +1878,19 @@ handle_control_getinfo(control_connection_t *conn, uint32_t len,
   return 0;
   return 0;
 }
 }
 
 
-/** If *<b>string</b> contains a recognized purpose (for
- * circuits if <b>for_circuits</b> is 1, else for routers),
- * possibly prefaced with the string "purpose=", then assign it
- * and return 0. Otherwise return -1.
- *
- * If it's prefaced with "purpose=", then set *<b>string</b> to
- * the remainder of the string. */
-static int
-get_purpose(char **string, int for_circuits, uint8_t *purpose)
+/** Given a string, convert it to a circuit purpose. */
+static uint8_t
+circuit_purpose_from_string(const char *string)
 {
 {
-  if (!strcmpstart(*string, "purpose="))
-    *string += strlen("purpose=");
+  if (!strcmpstart(string, "purpose="))
+    string += strlen("purpose=");
 
 
-  if (!for_circuits) {
-    int r = router_purpose_from_string(*string);
-    if (r == ROUTER_PURPOSE_UNKNOWN)
-      return -1;
-    *purpose = r;
-    return 0;
-  }
-
-  if (!strcmp(*string, "general"))
-    *purpose = CIRCUIT_PURPOSE_C_GENERAL;
-  else if (!strcmp(*string, "controller"))
-    *purpose = CIRCUIT_PURPOSE_CONTROLLER;
-  else { /* not a recognized purpose */
-    return -1;
-  }
-  return 0;
+  if (!strcmp(string, "general"))
+    return CIRCUIT_PURPOSE_C_GENERAL;
+  else if (!strcmp(string, "controller"))
+    return CIRCUIT_PURPOSE_CONTROLLER;
+  else
+    return CIRCUIT_PURPOSE_UNKNOWN;
 }
 }
 
 
 /** Return a newly allocated smartlist containing the arguments to the command
 /** Return a newly allocated smartlist containing the arguments to the command
@@ -1963,7 +1947,8 @@ handle_control_extendcircuit(control_connection_t *conn, uint32_t len,
 
 
   if (zero_circ && smartlist_len(args)>2) {
   if (zero_circ && smartlist_len(args)>2) {
     char *purp = smartlist_get(args,2);
     char *purp = smartlist_get(args,2);
-    if (get_purpose(&purp, 1, &intended_purpose) < 0) {
+    intended_purpose = circuit_purpose_from_string(purp);
+    if (intended_purpose == CIRCUIT_PURPOSE_UNKNOWN) {
       connection_printf_to_buf(conn, "552 Unknown purpose \"%s\"\r\n", purp);
       connection_printf_to_buf(conn, "552 Unknown purpose \"%s\"\r\n", purp);
       SMARTLIST_FOREACH(args, char *, cp, tor_free(cp));
       SMARTLIST_FOREACH(args, char *, cp, tor_free(cp));
       smartlist_free(args);
       smartlist_free(args);
@@ -2061,7 +2046,8 @@ handle_control_setcircuitpurpose(control_connection_t *conn,
 
 
   {
   {
     char *purp = smartlist_get(args,1);
     char *purp = smartlist_get(args,1);
-    if (get_purpose(&purp, 1, &new_purpose) < 0) {
+    new_purpose = circuit_purpose_from_string(purp);
+    if (new_purpose == CIRCUIT_PURPOSE_UNKNOWN) {
       connection_printf_to_buf(conn, "552 Unknown purpose \"%s\"\r\n", purp);
       connection_printf_to_buf(conn, "552 Unknown purpose \"%s\"\r\n", purp);
       goto done;
       goto done;
     }
     }
@@ -2178,6 +2164,7 @@ handle_control_postdescriptor(control_connection_t *conn, uint32_t len,
   char *desc;
   char *desc;
   const char *msg=NULL;
   const char *msg=NULL;
   uint8_t purpose = ROUTER_PURPOSE_GENERAL;
   uint8_t purpose = ROUTER_PURPOSE_GENERAL;
+  int cache = 0; /* eventually, we may switch this to 1 */
 
 
   char *cp = memchr(body, '\n', len);
   char *cp = memchr(body, '\n', len);
   smartlist_t *args = smartlist_create();
   smartlist_t *args = smartlist_create();
@@ -2186,21 +2173,37 @@ handle_control_postdescriptor(control_connection_t *conn, uint32_t len,
 
 
   smartlist_split_string(args, body, " ",
   smartlist_split_string(args, body, " ",
                          SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
                          SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
-  if (smartlist_len(args)) {
-    char *purp = smartlist_get(args,0);
-    if (get_purpose(&purp, 0, &purpose) < 0) {
-      connection_printf_to_buf(conn, "552 Unknown purpose \"%s\"\r\n",
-                               purp);
-      SMARTLIST_FOREACH(args, char *, arg, tor_free(arg));
-      smartlist_free(args);
-      return 0;
+  SMARTLIST_FOREACH(args, char *, option,
+  {
+    if (!strcasecmpstart(option, "purpose=")) {
+      option += strlen("purpose=");
+      purpose = router_purpose_from_string(option);
+      if (purpose == ROUTER_PURPOSE_UNKNOWN) {
+        connection_printf_to_buf(conn, "552 Unknown purpose \"%s\"\r\n",
+                                 option);
+        goto done;
+      }
+    } else if (!strcasecmpstart(option, "cache=")) {
+      option += strlen("cache=");
+      if (!strcmp(option, "no"))
+        cache = 0;
+      else if (!strcmp(option, "yes"))
+        cache = 1;
+      else {
+        connection_printf_to_buf(conn, "552 Unknown cache request \"%s\"\r\n",
+                                 option);
+        goto done;
+      }
+    } else { /* unrecognized argument? */
+      connection_printf_to_buf(conn,
+        "512 Unexpected argument \"%s\" to postdescriptor\r\n", option);
+      goto done;
     }
     }
-  }
-  SMARTLIST_FOREACH(args, char *, arg, tor_free(arg));
-  smartlist_free(args);
+  });
+
   read_escaped_data(cp, len-(cp-body), &desc);
   read_escaped_data(cp, len-(cp-body), &desc);
 
 
-  switch (router_load_single_router(desc, purpose, &msg)) {
+  switch (router_load_single_router(desc, purpose, cache, &msg)) {
   case -1:
   case -1:
     if (!msg) msg = "Could not parse descriptor";
     if (!msg) msg = "Could not parse descriptor";
     connection_printf_to_buf(conn, "554 %s\r\n", msg);
     connection_printf_to_buf(conn, "554 %s\r\n", msg);
@@ -2215,6 +2218,9 @@ handle_control_postdescriptor(control_connection_t *conn, uint32_t len,
   }
   }
 
 
   tor_free(desc);
   tor_free(desc);
+ done:
+  SMARTLIST_FOREACH(args, char *, arg, tor_free(arg));
+  smartlist_free(args);
   return 0;
   return 0;
 }
 }
 
 

+ 4 - 1
src/or/or.h

@@ -451,6 +451,9 @@ typedef enum {
 /** A controller made this circuit and Tor should not use it. */
 /** A controller made this circuit and Tor should not use it. */
 #define CIRCUIT_PURPOSE_CONTROLLER 18
 #define CIRCUIT_PURPOSE_CONTROLLER 18
 #define _CIRCUIT_PURPOSE_MAX 18
 #define _CIRCUIT_PURPOSE_MAX 18
+/** A catch-all for unrecognized purposes. Currently we don't expect
+ * to make or see any circuits with this purpose. */
+#define CIRCUIT_PURPOSE_UNKNOWN 255
 
 
 /** True iff the circuit purpose <b>p</b> is for a circuit that
 /** True iff the circuit purpose <b>p</b> is for a circuit that
  * originated at this node. */
  * originated at this node. */
@@ -3600,7 +3603,7 @@ int router_add_to_routerlist(routerinfo_t *router, const char **msg,
 void router_add_extrainfo_to_routerlist(extrainfo_t *ei, const char **msg,
 void router_add_extrainfo_to_routerlist(extrainfo_t *ei, const char **msg,
                                         int from_cache, int from_fetch);
                                         int from_cache, int from_fetch);
 void routerlist_remove_old_routers(void);
 void routerlist_remove_old_routers(void);
-int router_load_single_router(const char *s, uint8_t purpose,
+int router_load_single_router(const char *s, uint8_t purpose, int cache,
                               const char **msg);
                               const char **msg);
 void router_load_routers_from_string(const char *s, const char *eos,
 void router_load_routers_from_string(const char *s, const char *eos,
                                      saved_location_t saved_location,
                                      saved_location_t saved_location,

+ 1 - 1
src/or/router.c

@@ -1803,7 +1803,7 @@ router_purpose_to_string(uint8_t p)
   return NULL;
   return NULL;
 }
 }
 
 
-/** Given a string, convert it to a router purpose.  */
+/** Given a string, convert it to a router purpose. */
 uint8_t
 uint8_t
 router_purpose_from_string(const char *s)
 router_purpose_from_string(const char *s)
 {
 {

+ 5 - 1
src/or/routerlist.c

@@ -2991,7 +2991,8 @@ routerlist_descriptors_added(smartlist_t *sl)
  * This is used only by the controller.
  * This is used only by the controller.
  */
  */
 int
 int
-router_load_single_router(const char *s, uint8_t purpose, const char **msg)
+router_load_single_router(const char *s, uint8_t purpose, int cache,
+                          const char **msg)
 {
 {
   routerinfo_t *ri;
   routerinfo_t *ri;
   int r;
   int r;
@@ -3017,6 +3018,9 @@ router_load_single_router(const char *s, uint8_t purpose, const char **msg)
     return 0;
     return 0;
   }
   }
 
 
+  if (!cache) /* obey the preference of the controller */
+    ri->cache_info.do_not_cache = 1;
+
   lst = smartlist_create();
   lst = smartlist_create();
   smartlist_add(lst, ri);
   smartlist_add(lst, ri);
   routers_update_status_from_networkstatus(lst, 0);
   routers_update_status_from_networkstatus(lst, 0);