Browse Source

Merge branch 'bug5609_rebased'

Nick Mathewson 10 years ago
parent
commit
3417939565
5 changed files with 137 additions and 47 deletions
  1. 4 0
      changes/bug5609
  2. 29 47
      src/or/control.c
  3. 56 0
      src/or/control.h
  4. 4 0
      src/or/transports.c
  5. 44 0
      src/test/test_pt.c

+ 4 - 0
changes/bug5609

@@ -0,0 +1,4 @@
+  o Minor features:
+    - Implement the TRANSPORT_LAUNCHED control port event that
+      notifies controllers about new launched pluggable
+      transports. Resolves ticket 5609.

+ 29 - 47
src/or/control.c

@@ -52,46 +52,13 @@
  * finished authentication and is accepting commands. */
 #define STATE_IS_OPEN(s) ((s) == CONTROL_CONN_STATE_OPEN)
 
-/* Recognized asynchronous event types.  It's okay to expand this list
- * because it is used both as a list of v0 event types, and as indices
- * into the bitfield to determine which controllers want which events.
- */
-#define EVENT_MIN_             0x0001
-#define EVENT_CIRCUIT_STATUS   0x0001
-#define EVENT_STREAM_STATUS    0x0002
-#define EVENT_OR_CONN_STATUS   0x0003
-#define EVENT_BANDWIDTH_USED   0x0004
-#define EVENT_CIRCUIT_STATUS_MINOR 0x0005
-#define EVENT_NEW_DESC         0x0006
-#define EVENT_DEBUG_MSG        0x0007
-#define EVENT_INFO_MSG         0x0008
-#define EVENT_NOTICE_MSG       0x0009
-#define EVENT_WARN_MSG         0x000A
-#define EVENT_ERR_MSG          0x000B
-#define EVENT_ADDRMAP          0x000C
-// #define EVENT_AUTHDIR_NEWDESCS 0x000D
-#define EVENT_DESCCHANGED      0x000E
-// #define EVENT_NS               0x000F
-#define EVENT_STATUS_CLIENT    0x0010
-#define EVENT_STATUS_SERVER    0x0011
-#define EVENT_STATUS_GENERAL   0x0012
-#define EVENT_GUARD            0x0013
-#define EVENT_STREAM_BANDWIDTH_USED   0x0014
-#define EVENT_CLIENTS_SEEN     0x0015
-#define EVENT_NEWCONSENSUS     0x0016
-#define EVENT_BUILDTIMEOUT_SET     0x0017
-#define EVENT_SIGNAL           0x0018
-#define EVENT_CONF_CHANGED     0x0019
-#define EVENT_MAX_             0x0019
-/* If EVENT_MAX_ ever hits 0x0020, we need to make the mask wider. */
-
 /** Bitfield: The bit 1&lt;&lt;e is set if <b>any</b> open control
  * connection is interested in events of type <b>e</b>.  We use this
  * so that we can decide to skip generating event messages that nobody
  * has interest in without having to walk over the global connection
  * list to find out.
  **/
-typedef uint32_t event_mask_t;
+typedef uint64_t event_mask_t;
 
 /** An event mask of all the events that any controller is interested in
  * receiving. */
@@ -103,7 +70,7 @@ static int disable_log_messages = 0;
 /** Macro: true if any control connection is interested in events of type
  * <b>e</b>. */
 #define EVENT_IS_INTERESTING(e) \
-  (global_event_mask & (1<<(e)))
+  (!! (global_event_mask & (((uint64_t)1)<<(e))))
 
 /** If we're using cookie-type authentication, how long should our cookies be?
  */
@@ -130,15 +97,6 @@ static uint8_t *authentication_cookie = NULL;
  * of this so we can respond to getinfo status/bootstrap-phase queries. */
 static char last_sent_bootstrap_message[BOOTSTRAP_MSG_LEN];
 
-/** Flag for event_format_t.  Indicates that we should use the one standard
-    format.
- */
-#define ALL_FORMATS 1
-
-/** Bit field of flags to select how to format a controller event.  Recognized
- * flag is ALL_FORMATS. */
-typedef int event_format_t;
-
 static void connection_printf_to_buf(control_connection_t *conn,
                                      const char *format, ...)
   CHECK_PRINTF(2,3);
@@ -592,9 +550,9 @@ send_control_done(control_connection_t *conn)
  *
  * The EXTENDED_FORMAT and NONEXTENDED_FORMAT flags behave similarly with
  * respect to the EXTENDED_EVENTS feature. */
-static void
-send_control_event_string(uint16_t event, event_format_t which,
-                          const char *msg)
+MOCK_IMPL(STATIC void,
+send_control_event_string,(uint16_t event, event_format_t which,
+                           const char *msg))
 {
   smartlist_t *conns = get_connection_array();
   (void)which;
@@ -958,6 +916,7 @@ static const struct control_event_t control_event_table[] = {
   { EVENT_BUILDTIMEOUT_SET, "BUILDTIMEOUT_SET" },
   { EVENT_SIGNAL, "SIGNAL" },
   { EVENT_CONF_CHANGED, "CONF_CHANGED"},
+  { EVENT_TRANSPORT_LAUNCHED, "TRANSPORT_LAUNCHED" },
   { 0, NULL },
 };
 
@@ -4737,6 +4696,21 @@ control_event_clients_seen(const char *controller_str)
     "650 CLIENTS_SEEN %s\r\n", controller_str);
 }
 
+/** A new pluggable transport called <b>transport_name</b> was
+ *  launched on <b>addr</b>:<b>port</b>. <b>mode</b> is either
+ *  "server" or "client" depending on the mode of the pluggable
+ *  transport.
+ *  "650" SP "TRANSPORT_LAUNCHED" SP Mode SP Name SP Address SP Port
+ */
+void
+control_event_transport_launched(const char *mode, const char *transport_name,
+                                 tor_addr_t *addr, uint16_t port)
+{
+  send_control_event(EVENT_TRANSPORT_LAUNCHED, ALL_FORMATS,
+                     "650 TRANSPORT_LAUNCHED %s %s %s %u\r\n",
+                     mode, transport_name, fmt_addr(addr), port);
+}
+
 /** Free any leftover allocated memory of the control.c subsystem. */
 void
 control_free_all(void)
@@ -4745,3 +4719,11 @@ control_free_all(void)
     tor_free(authentication_cookie);
 }
 
+#ifdef TOR_UNIT_TESTS
+/* For testing: change the value of global_event_mask */
+void
+control_testing_set_global_event_mask(uint64_t mask)
+{
+  global_event_mask = mask;
+}
+#endif

+ 56 - 0
src/or/control.h

@@ -89,12 +89,68 @@ MOCK_DECL(void, control_event_bootstrap_problem,(const char *warn,
                                                  int reason));
 
 void control_event_clients_seen(const char *controller_str);
+void control_event_transport_launched(const char *mode,
+                                      const char *transport_name,
+                                      tor_addr_t *addr, uint16_t port);
+
 void control_free_all(void);
 
 #ifdef CONTROL_PRIVATE
+/* Recognized asynchronous event types.  It's okay to expand this list
+ * because it is used both as a list of v0 event types, and as indices
+ * into the bitfield to determine which controllers want which events.
+ */
+#define EVENT_MIN_                    0x0001
+#define EVENT_CIRCUIT_STATUS          0x0001
+#define EVENT_STREAM_STATUS           0x0002
+#define EVENT_OR_CONN_STATUS          0x0003
+#define EVENT_BANDWIDTH_USED          0x0004
+#define EVENT_CIRCUIT_STATUS_MINOR    0x0005
+#define EVENT_NEW_DESC                0x0006
+#define EVENT_DEBUG_MSG               0x0007
+#define EVENT_INFO_MSG                0x0008
+#define EVENT_NOTICE_MSG              0x0009
+#define EVENT_WARN_MSG                0x000A
+#define EVENT_ERR_MSG                 0x000B
+#define EVENT_ADDRMAP                 0x000C
+/* Exposed above */
+// #define EVENT_AUTHDIR_NEWDESCS     0x000D
+#define EVENT_DESCCHANGED             0x000E
+/* Exposed above */
+// #define EVENT_NS                   0x000F
+#define EVENT_STATUS_CLIENT           0x0010
+#define EVENT_STATUS_SERVER           0x0011
+#define EVENT_STATUS_GENERAL          0x0012
+#define EVENT_GUARD                   0x0013
+#define EVENT_STREAM_BANDWIDTH_USED   0x0014
+#define EVENT_CLIENTS_SEEN            0x0015
+#define EVENT_NEWCONSENSUS            0x0016
+#define EVENT_BUILDTIMEOUT_SET        0x0017
+#define EVENT_SIGNAL                  0x0018
+#define EVENT_CONF_CHANGED            0x0019
+#define EVENT_TRANSPORT_LAUNCHED      0x0020
+#define EVENT_MAX_                    0x0020
+/* If EVENT_MAX_ ever hits 0x0040, we need to make the mask into a
+ * different structure. */
+
 /* Used only by control.c and test.c */
 STATIC size_t write_escaped_data(const char *data, size_t len, char **out);
 STATIC size_t read_escaped_data(const char *data, size_t len, char **out);
+/** Flag for event_format_t.  Indicates that we should use the one standard
+    format.  (Other formats previous existed, and are now deprecated)
+ */
+#define ALL_FORMATS 1
+/** Bit field of flags to select how to format a controller event.  Recognized
+ * flag is ALL_FORMATS. */
+typedef int event_format_t;
+
+#ifdef TOR_UNIT_TESTS
+MOCK_DECL(STATIC void,
+send_control_event_string,(uint16_t event, event_format_t which,
+                           const char *msg));
+
+void control_testing_set_global_event_mask(uint64_t mask);
+#endif
 #endif
 
 #endif

+ 4 - 0
src/or/transports.c

@@ -98,6 +98,7 @@
 #include "entrynodes.h"
 #include "connection_or.h"
 #include "ext_orport.h"
+#include "control.h"
 
 static process_environment_t *
 create_managed_proxy_environment(const managed_proxy_t *mp);
@@ -659,6 +660,7 @@ register_server_proxy(const managed_proxy_t *mp)
     save_transport_to_state(t->name, &t->addr, t->port);
     log_notice(LD_GENERAL, "Registered server transport '%s' at '%s'",
                t->name, fmt_addrport(&t->addr, t->port));
+    control_event_transport_launched("server", t->name, &t->addr, t->port);
   } SMARTLIST_FOREACH_END(t);
 }
 
@@ -681,9 +683,11 @@ register_client_proxy(const managed_proxy_t *mp)
       break;
     case 0:
       log_info(LD_GENERAL, "Successfully registered transport %s", t->name);
+      control_event_transport_launched("client", t->name, &t->addr, t->port);
       break;
     case 1:
       log_info(LD_GENERAL, "Successfully registered transport %s", t->name);
+      control_event_transport_launched("client", t->name, &t->addr, t->port);
       transport_free(transport_tmp);
       break;
     }

+ 44 - 0
src/test/test_pt.c

@@ -7,9 +7,11 @@
 #define PT_PRIVATE
 #define UTIL_PRIVATE
 #define STATEFILE_PRIVATE
+#define CONTROL_PRIVATE
 #include "or.h"
 #include "config.h"
 #include "confparse.h"
+#include "control.h"
 #include "transports.h"
 #include "circuitbuild.h"
 #include "util.h"
@@ -318,6 +320,22 @@ get_or_state_replacement(void)
   return dummy_state;
 }
 
+static int controlevent_n = 0;
+static uint16_t controlevent_event = 0;
+static smartlist_t *controlevent_msgs = NULL;
+
+static void
+send_control_event_string_replacement(uint16_t event, event_format_t which,
+                                      const char *msg)
+{
+  (void) which;
+  ++controlevent_n;
+  controlevent_event = event;
+  if (!controlevent_msgs)
+    controlevent_msgs = smartlist_new();
+  smartlist_add(controlevent_msgs, tor_strdup(msg));
+}
+
 /* Test the configure_proxy() function. */
 static void
 test_pt_configure_proxy(void *arg)
@@ -334,6 +352,10 @@ test_pt_configure_proxy(void *arg)
        tor_process_handle_destroy_replacement);
   MOCK(get_or_state,
        get_or_state_replacement);
+  MOCK(send_control_event_string,
+       send_control_event_string_replacement);
+
+  control_testing_set_global_event_mask(EVENT_TRANSPORT_LAUNCHED);
 
   mp = tor_malloc(sizeof(managed_proxy_t));
   mp->conf_state = PT_PROTO_ACCEPTING_METHODS;
@@ -364,6 +386,21 @@ test_pt_configure_proxy(void *arg)
   /* check the mp state */
   test_assert(mp->conf_state == PT_PROTO_COMPLETED);
 
+  tt_int_op(controlevent_n, ==, 5);
+  tt_int_op(controlevent_event, ==, EVENT_TRANSPORT_LAUNCHED);
+  tt_int_op(smartlist_len(controlevent_msgs), ==, 5);
+  smartlist_sort_strings(controlevent_msgs);
+  tt_str_op(smartlist_get(controlevent_msgs, 0), ==,
+            "650 TRANSPORT_LAUNCHED server mock1 127.0.0.1 5551\r\n");
+  tt_str_op(smartlist_get(controlevent_msgs, 1), ==,
+            "650 TRANSPORT_LAUNCHED server mock2 127.0.0.1 5552\r\n");
+  tt_str_op(smartlist_get(controlevent_msgs, 2), ==,
+            "650 TRANSPORT_LAUNCHED server mock3 127.0.0.1 5553\r\n");
+  tt_str_op(smartlist_get(controlevent_msgs, 3), ==,
+            "650 TRANSPORT_LAUNCHED server mock4 127.0.0.1 5554\r\n");
+  tt_str_op(smartlist_get(controlevent_msgs, 4), ==,
+            "650 TRANSPORT_LAUNCHED server mock5 127.0.0.1 5555\r\n");
+
   { /* check that the transport info were saved properly in the tor state */
     config_line_t *transport_in_state = NULL;
     smartlist_t *transport_info_sl = smartlist_new();
@@ -389,6 +426,13 @@ test_pt_configure_proxy(void *arg)
   tor_free(dummy_state);
   UNMOCK(tor_get_lines_from_handle);
   UNMOCK(tor_process_handle_destroy);
+  UNMOCK(get_or_state);
+  UNMOCK(send_control_event_string);
+  if (controlevent_msgs) {
+    SMARTLIST_FOREACH(controlevent_msgs, char *, cp, tor_free(cp));
+    smartlist_free(controlevent_msgs);
+    controlevent_msgs = NULL;
+  }
 }
 
 #define PT_LEGACY(name)                                               \