[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

[or-cvs] Implement all the easy bits of the new control protocol



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

Modified Files:
	buffers.c control.c main.c 
Log Message:
Implement all the easy bits of the new control protocol

Index: buffers.c
===================================================================
RCS file: /home/or/cvsroot/tor/src/or/buffers.c,v
retrieving revision 1.163
retrieving revision 1.164
diff -u -d -r1.163 -r1.164
--- buffers.c	17 Jun 2005 18:49:54 -0000	1.163
+++ buffers.c	17 Jun 2005 20:37:21 -0000	1.164
@@ -1198,19 +1198,20 @@
   char *eol;
   size_t sz;
   /* Look for a CRLF. */
-  if (!(eol = find_crlf_on_buf(buf, buf->cur)))
+  if (!(eol = find_crlf_on_buf(buf, buf->cur))) {
     return 0;
+  }
   sz = _buf_offset(buf, eol);
-  if (sz+2 > *data_len) {
-    *data_len = sz+2;
+  if (sz+3 > *data_len) {
+    *data_len = sz+3;
     return -1;
   }
   fetch_from_buf(data_out, sz+2, buf);
+  data_out[sz+2] = '\0';
   *data_len = sz+2;
   return 1;
 }
 
-
 /** Log an error and exit if <b>buf</b> is corrupted.
  */
 void assert_buf_ok(buf_t *buf)

Index: control.c
===================================================================
RCS file: /home/or/cvsroot/tor/src/or/control.c,v
retrieving revision 1.89
retrieving revision 1.90
diff -u -d -r1.89 -r1.90
--- control.c	17 Jun 2005 18:49:55 -0000	1.89
+++ control.c	17 Jun 2005 20:37:21 -0000	1.90
@@ -102,11 +102,15 @@
  * has interest in without having to walk over the global connection
  * list to find out.
  **/
-static uint32_t global_event_mask = 0;
+static uint32_t global_event_mask0 = 0;
+static uint32_t global_event_mask1 = 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)))
+#define EVENT_IS_INTERESTING0(e) (global_event_mask0 & (1<<(e)))
+#define EVENT_IS_INTERESTING1(e) (global_event_mask1 & (1<<(e)))
+#define EVENT_IS_INTERESTING(e) \
+  ((global_event_mask0|global_event_mask1) & (1<<(e)))
 
 /** If we're using cookie-type authentication, how long should our cookies be?
  */
@@ -117,6 +121,8 @@
 static int authentication_cookie_is_set = 0;
 static char authentication_cookie[AUTHENTICATION_COOKIE_LEN];
 
+static void connection_printf_to_buf(connection_t *conn, const char *format, ...)
+  CHECK_PRINTF(2,3);
 static void update_global_event_mask(void);
 static void send_control0_message(connection_t *conn, uint16_t type,
                                  uint32_t len, const char *body);
@@ -125,6 +131,8 @@
 static void send_control0_error(connection_t *conn, uint16_t error,
                                const char *message);
 static void send_control0_event(uint16_t event, uint32_t len, const char *body);
+static void send_control1_event(uint16_t event, const char *format, ...)
+  CHECK_PRINTF(2,3);
 static int handle_control_setconf(connection_t *conn, uint32_t len,
                                   char *body);
 static int handle_control_getconf(connection_t *conn, uint32_t len,
@@ -196,12 +204,16 @@
 {
   connection_t **conns;
   int n_conns, i;
-  global_event_mask = 0;
+  global_event_mask0 = 0;
+  global_event_mask1 = 0;
   get_connection_array(&conns, &n_conns);
   for (i = 0; i < n_conns; ++i) {
     if (conns[i]->type == CONN_TYPE_CONTROL &&
         STATE_IS_OPEN(conns[i]->state)) {
-      global_event_mask |= conns[i]->event_mask;
+      if (STATE_IS_V0(conns[i]->state))
+        global_event_mask0 |= conns[i]->event_mask;
+      else
+        global_event_mask1 |= conns[i]->event_mask;
     }
   }
 
@@ -246,6 +258,7 @@
 }
 
 
+
 static void
 connection_printf_to_buf(connection_t *conn, const char *format, ...)
 {
@@ -254,7 +267,7 @@
   int r;
   size_t len;
   va_start(ap,format);
-  r = tor_snprintf(buf, sizeof(buf), format, ap);
+  r = tor_vsnprintf(buf, sizeof(buf), format, ap);
   va_end(ap);
   len = strlen(buf);
   if (memcmp("\r\n\0", buf+len-2, 3)) {
@@ -265,6 +278,28 @@
   connection_write_to_buf(buf, len, conn);
 }
 
+#if 0
+static void
+connection_write_reply_lines_to_buf(connection_t *conn,
+                                    const char *code, smartlist_t *lines)
+{
+  int i, len;
+
+  tor_assert(strlen(code) == 3);
+  len = smartlist_len(lines);
+  if (!len)
+    return;
+
+  for (i=0; i < len-1; ++i) {
+    connection_write_to_buf(code, 3, conn);
+    connection_write_to_buf("-", 1, conn);
+    connection_write_str_to_buf(smartlist_get(lines, i), conn);
+  }
+  connection_write_to_buf(code, 3, conn);
+  connection_write_to_buf(" ", 1, conn);
+  connection_write_str_to_buf(smartlist_get(lines, len-1), conn);
+}
+#endif
 
 /** Send a message of type <b>type</b> containing <b>len</b> bytes
  * from <b>body</b> along the control connection <b>conn</b> */
@@ -371,11 +406,47 @@
   tor_free(buf);
 }
 
+static void
+send_control1_event(uint16_t event, const char *format, ...)
+{
+  connection_t **conns;
+  int n_conns, i, r;
+  char buf[1024]; /* XXXX Length */
+  va_list ap;
+  size_t len;
+
+  va_start(ap, format);
+  r = tor_vsnprintf(buf, sizeof(buf), format, ap);
+  va_end(ap);
+
+  len = strlen(buf);
+  if (memcmp("\r\n\0", buf+len-2, 3)) {
+    buf[1023] = '\0';
+    buf[1022] = '\n';
+    buf[1021] = '\r';
+  }
+
+  tor_assert(event >= _EVENT_MIN && event <= _EVENT_MAX);
+
+  get_connection_array(&conns, &n_conns);
+  for (i = 0; i < n_conns; ++i) {
+    if (conns[i]->type == CONN_TYPE_CONTROL &&
+        conns[i]->state == CONTROL_CONN_STATE_OPEN_V1 &&
+        conns[i]->event_mask & (1<<event)) {
+      connection_write_to_buf(buf, len, conns[i]);
+      if (event == EVENT_ERR_MSG) {
+        _connection_controller_force_write(conns[i]);
+      }
+    }
+  }
+}
+
 /** Called when we receive a SETCONF message: parse the body and try
  * to update our configuration.  Reply with a DONE or ERROR message. */
 static int
 handle_control_setconf(connection_t *conn, uint32_t len, char *body)
 {
+  /* XXXX V1 */
   int r;
   struct config_line_t *lines=NULL;
 
@@ -413,28 +484,42 @@
 {
   smartlist_t *questions = NULL;
   smartlist_t *answers = NULL;
+  smartlist_t *unrecognized = NULL;
   char *msg = NULL;
   size_t msg_len;
   or_options_t *options = get_options();
+  int v0 = STATE_IS_V0(conn->state);
 
   questions = smartlist_create();
-  smartlist_split_string(questions, body, "\n",
-                         SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
+  if (v0) {
+    smartlist_split_string(questions, body, "\n",
+                           SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
+  } else {
+    smartlist_split_string(questions, body, " ",
+                           SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
+  }
   answers = smartlist_create();
-  SMARTLIST_FOREACH(questions, const char *, q,
+  unrecognized = smartlist_create();
+  SMARTLIST_FOREACH(questions, char *, q,
   {
-    int recognized = config_option_is_recognized(q);
-    if (!recognized) {
-      send_control0_error(conn, ERR_UNRECOGNIZED_CONFIG_KEY, q);
-      goto done;
+    if (!config_option_is_recognized(q)) {
+      if (v0) {
+        send_control0_error(conn, ERR_UNRECOGNIZED_CONFIG_KEY, q);
+        goto done;
+      } else {
+        smartlist_add(unrecognized, q);
+      }
     } else {
       struct config_line_t *answer = config_get_assigned_option(options,q);
 
       while (answer) {
         struct config_line_t *next;
-        size_t alen = strlen(answer->key)+strlen(answer->value)+3;
+        size_t alen = strlen(answer->key)+strlen(answer->value)+8;
         char *astr = tor_malloc(alen);
-        tor_snprintf(astr, alen, "%s %s\n", answer->key, answer->value);
+        if (v0)
+          tor_snprintf(astr, alen, "%s %s\n", answer->key, answer->value);
+        else
+          tor_snprintf(astr, alen, "250-%s=%s\r\n", answer->key, answer->value);
         smartlist_add(answers, astr);
 
         next = answer->next;
@@ -446,15 +531,37 @@
     }
   });
 
-  msg = smartlist_join_strings(answers, "", 0, &msg_len);
-  send_control0_message(conn, CONTROL0_CMD_CONFVALUE,
-                       (uint16_t)msg_len, msg_len?msg:NULL);
+  if (v0) {
+    msg = smartlist_join_strings(answers, "", 0, &msg_len);
+    send_control0_message(conn, CONTROL0_CMD_CONFVALUE,
+                          (uint16_t)msg_len, msg_len?msg:NULL);
+  } else {
+    int i,len;
+    if ((len = smartlist_len(unrecognized))) {
+      for (i=0; i < len-1; ++i)
+        connection_printf_to_buf(conn,
+                                 "552-Unrecognized configuration key \"%s\"\r\n",
+                                 (char*)smartlist_get(unrecognized, i));
+      connection_printf_to_buf(conn,
+                               "552 Unrecognized configuration key \"%s\"\r\n",
+                               (char*)smartlist_get(unrecognized, len-1));
+    } else if ((len = smartlist_len(answers))) {
+      char *tmp = smartlist_get(answers, len-1);
+      tor_assert(strlen(tmp)>4);
+      tmp[3] = ' ';
+      msg = smartlist_join_strings(answers, "", 0, &msg_len);
+      connection_write_to_buf(msg, msg_len, conn);
+    } else {
+      connection_write_str_to_buf("250 OK\r\n", conn);
+    }
+  }
 
  done:
   if (answers) SMARTLIST_FOREACH(answers, char *, cp, tor_free(cp));
   if (questions) SMARTLIST_FOREACH(questions, char *, cp, tor_free(cp));
   smartlist_free(answers);
   smartlist_free(questions);
+  smartlist_free(unrecognized);
   tor_free(msg);
 
   return 0;
@@ -467,22 +574,61 @@
 {
   uint16_t event_code;
   uint32_t event_mask = 0;
-  if (len % 2) {
-    send_control0_error(conn, ERR_SYNTAX,
-                       "Odd number of bytes in setevents message");
-    return 0;
-  }
 
-  for (; len; len -= 2, body += 2) {
-    event_code = ntohs(get_uint16(body));
-    if (event_code < _EVENT_MIN || event_code > _EVENT_MAX) {
-      send_control0_error(conn, ERR_UNRECOGNIZED_EVENT_CODE,
-                         "Unrecognized event code");
+  if (STATE_IS_V0(conn->state)) {
+    if (len % 2) {
+      send_control0_error(conn, ERR_SYNTAX,
+                          "Odd number of bytes in setevents message");
       return 0;
     }
-    event_mask |= (1 << event_code);
-  }
 
+    for (; len; len -= 2, body += 2) {
+      event_code = ntohs(get_uint16(body));
+      if (event_code < _EVENT_MIN || event_code > _EVENT_MAX) {
+        send_control0_error(conn, ERR_UNRECOGNIZED_EVENT_CODE,
+                            "Unrecognized event code");
+        return 0;
+      }
+      event_mask |= (1 << event_code);
+    }
+  } else {
+    smartlist_t *events = smartlist_create();
+    smartlist_split_string(events, body, " ",
+                           SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
+    SMARTLIST_FOREACH(events, const char *, ev,
+      {
+        if (!strcasecmp(ev, "CIRC"))
+          event_code = EVENT_CIRCUIT_STATUS;
+        else if (!strcasecmp(ev, "STREAM"))
+          event_code = EVENT_STREAM_STATUS;
+        else if (!strcasecmp(ev, "ORCONN"))
+          event_code = EVENT_OR_CONN_STATUS;
+        else if (!strcasecmp(ev, "BW"))
+          event_code = EVENT_BANDWIDTH_USED;
+        else if (!strcasecmp(ev, "DEBUG"))
+          continue; /* Don't do debug messages */
+        else if (!strcasecmp(ev, "INFO"))
+          event_code = EVENT_INFO_MSG;
+        else if (!strcasecmp(ev, "NOTICE"))
+          event_code = EVENT_NOTICE_MSG;
+        else if (!strcasecmp(ev, "WARN"))
+          event_code = EVENT_WARN_MSG;
+        else if (!strcasecmp(ev, "ERR"))
+          event_code = EVENT_ERR_MSG;
+        else if (!strcasecmp(ev, "NEWDESC"))
+          event_code = EVENT_NEW_DESC;
+        else {
+          connection_printf_to_buf(conn, "552 Unrecognized event \"%s\"\r\n",
+                                   ev);
+          SMARTLIST_FOREACH(events, char *, e, tor_free(e));
+          smartlist_free(events);
+          return 0;
+        }
+        event_mask |= (1 << event_code);
+      });
+    SMARTLIST_FOREACH(events, char *, e, tor_free(e));
+    smartlist_free(events);
+  }
   conn->event_mask = event_mask;
 
   update_global_event_mask();
@@ -522,6 +668,7 @@
 static int
 handle_control_authenticate(connection_t *conn, uint32_t len, const char *body)
 {
+  /* XXXX V1 */
   or_options_t *options = get_options();
   if (options->CookieAuthentication) {
     if (len == AUTHENTICATION_COOKIE_LEN &&
@@ -540,16 +687,16 @@
       goto ok;
     goto err;
   } else {
-    if (len == 0) {
-      /* if Tor doesn't demand any stronger authentication, then
-       * the controller can get in with a blank auth line. */
-      goto ok;
-    }
-    goto err;
+    /* if Tor doesn't demand any stronger authentication, then
+     * the controller can get in with anything. */
+    goto ok;
   }
 
  err:
-  send_control0_error(conn, ERR_REJECTED_AUTHENTICATION,"Authentication failed");
+  if (STATE_IS_V0(conn->state))
+    send_control0_error(conn,ERR_REJECTED_AUTHENTICATION,"Authentication failed");
+  else
+    connection_write_str_to_buf("515 Authentication failed\r\n", conn);
   return 0;
  ok:
   log_fn(LOG_INFO, "Authenticated control connection (%d)", conn->s);
@@ -567,8 +714,12 @@
                         const char *body)
 {
   if (save_current_config()<0) {
-    send_control0_error(conn, ERR_INTERNAL,
-                       "Unable to write configuration to disk.");
+    if (STATE_IS_V0(conn->state))
+      send_control0_error(conn, ERR_INTERNAL,
+                          "Unable to write configuration to disk.");
+    else
+      connection_write_str_to_buf("551 Unable to write configuration to disk.",
+                                  conn);
   } else {
     send_control_done(conn);
   }
@@ -580,11 +731,47 @@
 handle_control_signal(connection_t *conn, uint32_t len,
                       const char *body)
 {
-  if (len != 1) {
-    send_control0_error(conn, ERR_SYNTAX,
-                       "Body of SIGNAL command too long or too short.");
-  } else if (control_signal_act((uint8_t)body[0]) < 0) {
-    send_control0_error(conn, ERR_SYNTAX, "Unrecognized signal number.");
+  int sig;
+  if (STATE_IS_V0(conn->state)) {
+    if (len != 1) {
+      send_control0_error(conn, ERR_SYNTAX,
+                          "Body of SIGNAL command too long or too short.");
+      return 0;
+    } else {
+      sig = (uint8_t)body[0];
+    }
+  } else {
+    int n = 0;
+    char *s;
+    while (body[n] && ! TOR_ISSPACE(body[n]))
+      ++n;
+    s = tor_strndup(body, n);
+    if (!strcasecmp(s, "RELOAD") || !strcasecmp(s, "HUP"))
+      sig = SIGHUP;
+    else if (!strcasecmp(s, "SHUTDOWN") || !strcasecmp(s, "INT"))
+      sig = SIGINT;
+    else if (!strcasecmp(s, "DUMP") || !strcasecmp(s, "USR1"))
+      sig = SIGUSR1;
+    else if (!strcasecmp(s, "DEBUG") || !strcasecmp(s, "USR2"))
+      sig = SIGUSR2;
+    else if (!strcasecmp(s, "HALT") || !strcasecmp(s, "TERM"))
+      sig = SIGTERM;
+    else {
+      connection_printf_to_buf(conn, "552 Unrecognized signal code \"%s\"\r\n",
+                               body);
+      sig = -1;
+    }
+    tor_free(s);
+    if (sig<0)
+      return 0;
+  }
+
+  if (control_signal_act(sig) < 0) {
+    if (STATE_IS_V0(conn->state))
+      send_control0_error(conn, ERR_SYNTAX, "Unrecognized signal number.");
+    else
+      connection_write_str_to_buf("551 Internal error acting on signal\r\n",
+                                  conn);
   } else {
     send_control_done(conn);
   }
@@ -595,6 +782,7 @@
 static int
 handle_control_mapaddress(connection_t *conn, uint32_t len, const char *body)
 {
+  /* XXXX V1 */
   smartlist_t *elts;
   smartlist_t *lines;
   smartlist_t *reply;
@@ -704,6 +892,7 @@
 static int
 handle_control_getinfo(connection_t *conn, uint32_t len, const char *body)
 {
+  /* XXXX V1 */
   smartlist_t *questions = NULL;
   smartlist_t *answers = NULL;
   char *msg = NULL, *ans;
@@ -746,6 +935,7 @@
 handle_control_extendcircuit(connection_t *conn, uint32_t len,
                              const char *body)
 {
+  /* XXXX V1 */
   smartlist_t *router_nicknames, *routers;
   uint32_t circ_id;
   circuit_t *circ;
@@ -825,6 +1015,7 @@
 handle_control_attachstream(connection_t *conn, uint32_t len,
                                         const char *body)
 {
+  /* XXXX V1 */
   uint32_t conn_id;
   uint32_t circ_id;
   connection_t *ap_conn;
@@ -878,6 +1069,7 @@
 handle_control_postdescriptor(connection_t *conn, uint32_t len,
                               const char *body)
 {
+  /* XXXX V1 */
   const char *msg=NULL;
   switch (router_load_single_router(body, &msg)) {
   case -1:
@@ -899,6 +1091,7 @@
 handle_control_redirectstream(connection_t *conn, uint32_t len,
                               const char *body)
 {
+  /* XXXX V1 */
   connection_t *ap_conn;
   uint32_t conn_id;
   if (len < 6) {
@@ -926,6 +1119,7 @@
 handle_control_closestream(connection_t *conn, uint32_t len,
                            const char *body)
 {
+  /* XXXX V1 */
   uint32_t conn_id;
   connection_t *ap_conn;
   uint8_t reason;
@@ -955,6 +1149,7 @@
 handle_control_closecircuit(connection_t *conn, uint32_t len,
                             const char *body)
 {
+  /* XXXX V1 */
   uint32_t circ_id;
   circuit_t *circ;
   int safe;
@@ -1048,6 +1243,7 @@
 connection_control_process_inbuf_v1(connection_t *conn)
 {
   size_t data_len, cmd_len;
+  char *args;
 
   tor_assert(conn);
   tor_assert(conn->type == CONN_TYPE_CONTROL);
@@ -1064,7 +1260,7 @@
   while (1) {
     size_t last_idx;
     int r;
-    while (1) {
+    do {
       data_len = conn->incoming_cmd_len - conn->incoming_cmd_cur_len;
       r = fetch_from_buf_line(conn->inbuf,
                                   conn->incoming_cmd+conn->incoming_cmd_cur_len,
@@ -1073,7 +1269,7 @@
         /* Line not all here yet. Wait. */
         return 0;
       else if (r == -1) {
-          while (conn->incoming_cmd_len < data_len)
+          while (conn->incoming_cmd_len < data_len+conn->incoming_cmd_cur_len)
             conn->incoming_cmd_len *= 2;
           conn->incoming_cmd = tor_realloc(conn->incoming_cmd, conn->incoming_cmd_len);
       }
@@ -1098,70 +1294,84 @@
   /* Okay, we now have a command sitting on conn->incoming_cmd. See if we
    * recognize it.
    */
+  cmd_len = 0;
   while (cmd_len < data_len && !isspace(conn->incoming_cmd[cmd_len]))
     ++cmd_len;
 
+  /*
+  log_fn(LOG_NOTICE, "READ A COMMAND FROM THE BUFFER: <%s> [%d]",
+         conn->incoming_cmd, (int)cmd_len);
+  */
+  data_len -= cmd_len;
+  conn->incoming_cmd[cmd_len]='\0';
+  args = conn->incoming_cmd+cmd_len+1;
+  while (*args == ' ' || *args == '\t') {
+    ++args;
+    --data_len;
+  }
+  /*
+  log_fn(LOG_NOTICE, "COMMAND IS: <%s>", conn->incoming_cmd);
+  log_fn(LOG_NOTICE, "ARGS ARE: <%s>", args);
+  */
+
   if (conn->state == CONTROL_CONN_STATE_NEEDAUTH_V1 &&
-      strncasecmp(conn->incoming_cmd, "AUTHENTICATE", cmd_len)) {
+      strcasecmp(conn->incoming_cmd, "AUTHENTICATE")) {
     connection_write_str_to_buf("514 Authentication required.\r\n", conn);
     conn->incoming_cmd_cur_len = 0;
     goto again;
   }
 
-  if (!strncasecmp(conn->incoming_cmd, "SETCONF", cmd_len)) {
-    if (handle_control_setconf(conn, 0, NULL))
+  if (!strcasecmp(conn->incoming_cmd, "SETCONF")) {
+    if (handle_control_setconf(conn, data_len, args))
       return -1;
-  } else if (!strncasecmp(conn->incoming_cmd, "GETCONF", cmd_len)) {
-    if (handle_control_getconf(conn, 0, NULL))
+  } else if (!strcasecmp(conn->incoming_cmd, "GETCONF")) {
+    if (handle_control_getconf(conn, data_len, args))
       return -1;
-  } else if (!strncasecmp(conn->incoming_cmd, "SETEVENTS", cmd_len)) {
-    if (handle_control_setevents(conn, 0, NULL))
+  } else if (!strcasecmp(conn->incoming_cmd, "SETEVENTS")) {
+    if (handle_control_setevents(conn, data_len, args))
       return -1;
-  } else if (!strncasecmp(conn->incoming_cmd, "AUTENTICATE", cmd_len)) {
-    if (handle_control_authenticate(conn, 0, NULL))
+  } else if (!strcasecmp(conn->incoming_cmd, "AUTHENTICATE")) {
+    if (handle_control_authenticate(conn, data_len, args))
       return -1;
-  } else if (!strncasecmp(conn->incoming_cmd, "SAVECONF", cmd_len)) {
-    if (handle_control_saveconf(conn, 0, NULL))
+  } else if (!strcasecmp(conn->incoming_cmd, "SAVECONF")) {
+    if (handle_control_saveconf(conn, data_len, args))
       return -1;
-  } else if (!strncasecmp(conn->incoming_cmd, "SIGNAL", cmd_len)) {
-    if (handle_control_signal(conn, 0, NULL))
+  } else if (!strcasecmp(conn->incoming_cmd, "SIGNAL")) {
+    if (handle_control_signal(conn, data_len, args))
       return -1;
-  } else if (!strncasecmp(conn->incoming_cmd, "MAPADDRESS", cmd_len)) {
-    if (handle_control_mapaddress(conn, 0, NULL))
+  } else if (!strcasecmp(conn->incoming_cmd, "MAPADDRESS")) {
+    if (handle_control_mapaddress(conn, data_len, args))
       return -1;
-  } else if (!strncasecmp(conn->incoming_cmd, "GETINFO", cmd_len)) {
-    if (handle_control_getinfo(conn, 0, NULL))
+  } else if (!strcasecmp(conn->incoming_cmd, "GETINFO")) {
+    if (handle_control_getinfo(conn, data_len, args))
       return -1;
-  } else if (!strncasecmp(conn->incoming_cmd, "EXTENDCIRCUIT", cmd_len)) {
-    if (handle_control_extendcircuit(conn, 0, NULL))
+  } else if (!strcasecmp(conn->incoming_cmd, "EXTENDCIRCUIT")) {
+    if (handle_control_extendcircuit(conn, data_len, args))
       return -1;
-  } else if (!strncasecmp(conn->incoming_cmd, "ATTACHSTREAM", cmd_len)) {
-    if (handle_control_attachstream(conn, 0, NULL))
+  } else if (!strcasecmp(conn->incoming_cmd, "ATTACHSTREAM")) {
+    if (handle_control_attachstream(conn, data_len, args))
       return -1;
-  } else if (!strncasecmp(conn->incoming_cmd, "+POSTDESCRIPTOR", cmd_len)) {
-    if (handle_control_postdescriptor(conn, 0, NULL))
+  } else if (!strcasecmp(conn->incoming_cmd, "+POSTDESCRIPTOR")) {
+    if (handle_control_postdescriptor(conn, data_len, args))
       return -1;
-  } else if (!strncasecmp(conn->incoming_cmd, "REDIRECTSTREAM", cmd_len)) {
-    if (handle_control_redirectstream(conn, 0, NULL))
+  } else if (!strcasecmp(conn->incoming_cmd, "REDIRECTSTREAM")) {
+    if (handle_control_redirectstream(conn, data_len, args))
       return -1;
-  } else if (!strncasecmp(conn->incoming_cmd, "CLOSESTREAM", cmd_len)) {
-    if (handle_control_closestream(conn, 0, NULL))
+  } else if (!strcasecmp(conn->incoming_cmd, "CLOSESTREAM")) {
+    if (handle_control_closestream(conn, data_len, args))
       return -1;
-  } else if (!strncasecmp(conn->incoming_cmd, "CLOSECIRCUIT", cmd_len)) {
-    if (handle_control_closecircuit(conn, 0, NULL))
+  } else if (!strcasecmp(conn->incoming_cmd, "CLOSECIRCUIT")) {
+    if (handle_control_closecircuit(conn, data_len, args))
       return -1;
   } else {
-    conn->incoming_cmd[cmd_len] = '\0';
-    connection_printf_to_buf(conn, "510 Unrecognizd command \"%s\"\r\n",
+    connection_printf_to_buf(conn, "510 Unrecognized command \"%s\"\r\n",
                              conn->incoming_cmd);
   }
 
   conn->incoming_cmd_cur_len = 0;
   goto again;
-
 }
 
-
 static int
 connection_control_process_inbuf_v0(connection_t *conn)
 {
@@ -1326,22 +1536,42 @@
 control_event_circuit_status(circuit_t *circ, circuit_status_event_t tp)
 {
   char *path, *msg;
-  size_t path_len;
   if (!EVENT_IS_INTERESTING(EVENT_CIRCUIT_STATUS))
     return 0;
   tor_assert(circ);
   tor_assert(CIRCUIT_IS_ORIGIN(circ));
 
   path = circuit_list_path(circ,0);
-  path_len = strlen(path);
-  msg = tor_malloc(1+4+path_len+1); /* event, circid, path, NUL. */
-  msg[0] = (uint8_t) tp;
-  set_uint32(msg+1, htonl(circ->global_identifier));
-  strlcpy(msg+5,path,path_len+1);
+  if (EVENT_IS_INTERESTING0(EVENT_CIRCUIT_STATUS)) {
+    size_t path_len = strlen(path);
+    msg = tor_malloc(1+4+path_len+1); /* event, circid, path, NUL. */
+    msg[0] = (uint8_t) tp;
+    set_uint32(msg+1, htonl(circ->global_identifier));
+    strlcpy(msg+5,path,path_len+1);
 
-  send_control0_event(EVENT_CIRCUIT_STATUS, (uint32_t)(path_len+6), msg);
+    send_control0_event(EVENT_CIRCUIT_STATUS, (uint32_t)(path_len+6), msg);
+    tor_free(msg);
+  }
+  if (EVENT_IS_INTERESTING1(EVENT_CIRCUIT_STATUS)) {
+    const char *status;
+    switch (tp)
+      {
+      case CIRC_EVENT_LAUNCHED: status = "LAUNCHED"; break;
+      case CIRC_EVENT_BUILT: status = "BUILT"; break;
+      case CIRC_EVENT_EXTENDED: status = "EXTENDED"; break;
+      case CIRC_EVENT_FAILED: status = "FAILED"; break;
+      case CIRC_EVENT_CLOSED: status = "CLOSED"; break;
+      default:
+        log_fn(LOG_WARN, "Unrecognized status code %d", (int)tp);
+        return 0;
+      }
+    send_control1_event(EVENT_CIRCUIT_STATUS,
+                        "650 CIRC %lu %s %s\r\n",
+                        (unsigned long)circ->global_identifier,
+                        status, path);
+  }
   tor_free(path);
-  tor_free(msg);
+
   return 0;
 }
 
@@ -1364,15 +1594,38 @@
   tor_snprintf(buf, sizeof(buf), "%s%s:%d",
                conn->socks_request->address,
                conn->chosen_exit_name ? buf2 : "",
-               conn->socks_request->port),
-  len = strlen(buf);
-  msg = tor_malloc(5+len+1);
-  msg[0] = (uint8_t) tp;
-  set_uint32(msg+1, htonl(conn->global_identifier));
-  strlcpy(msg+5, buf, len+1);
+               conn->socks_request->port);
+  if (EVENT_IS_INTERESTING0(EVENT_STREAM_STATUS)) {
+    len = strlen(buf);
+    msg = tor_malloc(5+len+1);
+    msg[0] = (uint8_t) tp;
+    set_uint32(msg+1, htonl(conn->global_identifier));
+    strlcpy(msg+5, buf, len+1);
 
-  send_control0_event(EVENT_STREAM_STATUS, (uint32_t)(5+len+1), msg);
-  tor_free(msg);
+    send_control0_event(EVENT_STREAM_STATUS, (uint32_t)(5+len+1), msg);
+    tor_free(msg);
+  }
+  if (EVENT_IS_INTERESTING0(EVENT_STREAM_STATUS)) {
+    const char *status;
+    switch (tp)
+      {
+      case STREAM_EVENT_SENT_CONNECT: status = "SENTCONNECT"; break;
+      case STREAM_EVENT_SENT_RESOLVE: status = "SENTRESOLVE"; break;
+      case STREAM_EVENT_SUCCEEDED: status = "SUCCEEDED"; break;
+      case STREAM_EVENT_FAILED: status = "FAILED"; break;
+      case STREAM_EVENT_CLOSED: status = "CLOSED"; break;
+      case STREAM_EVENT_NEW: status = "NEW"; break;
+      case STREAM_EVENT_NEW_RESOLVE: status = "NEWRESOLVE"; break;
+      case STREAM_EVENT_FAILED_RETRIABLE: status = "DETACHED"; break;
+      default:
+        log_fn(LOG_WARN, "Unrecognized status code %d", (int)tp);
+        return 0;
+      }
+    send_control1_event(EVENT_STREAM_STATUS,
+                        "650 STREAM %lu %s %s\r\n",
+                        (unsigned long)conn->global_identifier,
+                        status, buf);
+  }
   return 0;
 }
 
@@ -1389,10 +1642,28 @@
   if (!EVENT_IS_INTERESTING(EVENT_OR_CONN_STATUS))
     return 0;
 
-  buf[0] = (uint8_t)tp;
-  strlcpy(buf+1,conn->nickname,sizeof(buf)-1);
-  len = strlen(buf+1);
-  send_control0_event(EVENT_OR_CONN_STATUS, (uint32_t)(len+1), buf);
+  if (EVENT_IS_INTERESTING0(EVENT_OR_CONN_STATUS)) {
+    buf[0] = (uint8_t)tp;
+    strlcpy(buf+1,conn->nickname,sizeof(buf)-1);
+    len = strlen(buf+1);
+    send_control0_event(EVENT_OR_CONN_STATUS, (uint32_t)(len+1), buf);
+  }
+  if (EVENT_IS_INTERESTING1(EVENT_OR_CONN_STATUS)) {
+    const char *status;
+    switch (tp)
+      {
+      case OR_CONN_EVENT_LAUNCHED: status = "LAUNCHED"; break;
+      case OR_CONN_EVENT_CONNECTED: status = "CONNECTED"; break;
+      case OR_CONN_EVENT_FAILED: status = "FAILED"; break;
+      case OR_CONN_EVENT_CLOSED: status = "CLOSED"; break;
+      default:
+        log_fn(LOG_WARN, "Unrecognized status code %d", (int)tp);
+        return 0;
+      }
+    send_control1_event(EVENT_OR_CONN_STATUS,
+                        "650 ORCONN %s %s\r\n",
+                        conn->nickname, status);
+  }
   return 0;
 }
 
@@ -1403,12 +1674,17 @@
 {
   char buf[8];
 
-  if (!EVENT_IS_INTERESTING(EVENT_BANDWIDTH_USED))
-    return 0;
-
-  set_uint32(buf, htonl(n_read));
-  set_uint32(buf+4, htonl(n_written));
-  send_control0_event(EVENT_BANDWIDTH_USED, 8, buf);
+  if (EVENT_IS_INTERESTING0(EVENT_BANDWIDTH_USED)) {
+    set_uint32(buf, htonl(n_read));
+    set_uint32(buf+4, htonl(n_written));
+    send_control0_event(EVENT_BANDWIDTH_USED, 8, buf);
+  }
+  if (EVENT_IS_INTERESTING1(EVENT_BANDWIDTH_USED)) {
+    send_control1_event(EVENT_BANDWIDTH_USED,
+                        "650 BW %lu %lu\r\n",
+                        (unsigned long)n_read,
+                        (unsigned long)n_written);
+  }
 
   return 0;
 }
@@ -1417,6 +1693,7 @@
 void
 control_event_logmsg(int severity, const char *msg)
 {
+  /* XXXX V1 */
   static int sending_logmsg=0;
   int oldlog, event;
 
@@ -1461,12 +1738,19 @@
     base16_encode(buf,sizeof(buf),r->identity_digest,DIGEST_LEN);
     smartlist_add(identities, tor_strdup(buf));
   });
-  msg = smartlist_join_strings(identities, ",", 1, &len);
-  send_control0_event(EVENT_NEW_DESC, len+1, msg);
-
+  if (EVENT_IS_INTERESTING0(EVENT_NEW_DESC)) {
+    msg = smartlist_join_strings(identities, ",", 0, &len);
+    send_control0_event(EVENT_NEW_DESC, len+1, msg);
+    tor_free(msg);
+  }
+  if (EVENT_IS_INTERESTING1(EVENT_NEW_DESC)) {
+    msg = smartlist_join_strings(identities, " ", 0, &len);
+    send_control1_event(EVENT_NEW_DESC, "650 NEWDESC %s\r\n", msg);
+    tor_free(msg);
+  }
   SMARTLIST_FOREACH(identities, char *, cp, tor_free(cp));
   smartlist_free(identities);
-  tor_free(msg);
+
   return 0;
 }
 

Index: main.c
===================================================================
RCS file: /home/or/cvsroot/tor/src/or/main.c,v
retrieving revision 1.517
retrieving revision 1.518
diff -u -d -r1.517 -r1.518
--- main.c	13 Jun 2005 00:35:19 -0000	1.517
+++ main.c	17 Jun 2005 20:37:21 -0000	1.518
@@ -16,7 +16,9 @@
 #include <dmalloc.h>
 #endif
 
-/* These signals are defined to help control_signal_act work. */
+/* These signals are defined to help control_signal_act work.
+ * XXXX Move into or.h or compat.h
+ */
 #ifndef SIGHUP
 #define SIGHUP 1
 #endif