Browse Source

Implement redirectstream in control interface.

svn:r3785
Nick Mathewson 20 years ago
parent
commit
07a7b6af64
2 changed files with 97 additions and 6 deletions
  1. 15 4
      doc/control-spec.txt
  2. 82 2
      src/or/control.c

+ 15 - 4
doc/control-spec.txt

@@ -102,7 +102,9 @@ the message.
 
         0x000A No such stream
 
-        0x000B No such circuit.
+        0x000B No such circuit
+
+        0x000C No such OR
 
   The rest of the body should be a human-readable description of the error.
 
@@ -328,8 +330,6 @@ the message.
 
 3.14 EXTENDCIRCUIT (Type 0x000D)
 
-  [Proposal; not finalized]
-
   Sent from the client to the server.  The message body contains two fields:
       Circuit ID [4 octets]
       Path [NUL-terminated, comma-delimited string of OR nickname/identity]
@@ -401,7 +401,18 @@ the message.
 
   See FRAGMENTHEADER for more information
 
-3.19 
+3.19 REDIRECTSTREAM (Type 0x0012)
+
+  Sent form the client to the server. The message body contains two fields:
+      Stream ID [4 octets]
+      Address [variable-length, NUL-terminated.]
+
+  Tells the server to change the exit address on the specified stream.  No
+  remapping is performed on the new provided address.
+
+  To be sure that the modified address will be used, this event must be sent
+  after a new stream event is received, and before attaching this stream to
+  a circuit.
 
 4. Implementation notes
 

+ 82 - 2
src/or/control.c

@@ -48,7 +48,8 @@ const char control_c_id[] = "$Id$";
 #define CONTROL_CMD_POSTDESCRIPTOR 0x000F
 #define CONTROL_CMD_FRAGMENTHEADER 0x0010
 #define CONTROL_CMD_FRAGMENT       0x0011
-#define _CONTROL_CMD_MAX_RECOGNIZED 0x0011
+#define CONTROL_CMD_REDIRECTSTREAM  0x0012
+#define _CONTROL_CMD_MAX_RECOGNIZED 0x0012
 
 /* Recognized error codes. */
 #define ERR_UNSPECIFIED             0x0000
@@ -63,6 +64,7 @@ const char control_c_id[] = "$Id$";
 #define ERR_RESOURCE_EXHAUSETED     0x0009
 #define ERR_NO_STREAM               0x000A
 #define ERR_NO_CIRC                 0x000B
+#define ERR_NO_ROUTER               0x000C
 
 /* Recognized asynchronous event types. */
 #define _EVENT_MIN            0x0001
@@ -148,6 +150,8 @@ static int handle_control_attachstream(connection_t *conn, uint32_t len,
                                         const char *body);
 static int handle_control_postdescriptor(connection_t *conn, uint32_t len,
                                          const char *body);
+static int handle_control_redirectstream(connection_t *conn, uint32_t len,
+                                         const char *body);
 
 /** Given a possibly invalid message type code <b>cmd</b>, return a
  * human-readable string equivalent. */
@@ -631,7 +635,52 @@ static int
 handle_control_extendcircuit(connection_t *conn, uint32_t len,
                              const char *body)
 {
-  send_control_error(conn,ERR_UNRECOGNIZED_TYPE,"not yet implemented");
+  smartlist_t *router_nicknames, *routers;
+  uint32_t circ_id;
+  circuit_t *circ;
+  if (len<5) {
+    send_control_error(conn, ERR_SYNTAX, "extendcircuit message too short");
+    return 0;
+  }
+  circ_id = ntohl(get_uint32(body));
+  if (!(circ = circuit_get_by_global_id(circ_id))) {
+    send_control_error(conn, ERR_NO_STREAM,
+                       "No connection found with given ID");
+    return 0;
+  }
+
+  router_nicknames = smartlist_create();
+  routers = smartlist_create();
+  smartlist_split_string(router_nicknames, body, ",", 0, 0);
+  SMARTLIST_FOREACH(router_nicknames, const char *, n,
+    {
+      routerinfo_t *r = router_get_by_nickname(n);
+      if (!r) {
+        send_control_error(conn, ERR_NO_ROUTER, "Unrecognized router name");
+        goto done;
+      }
+      smartlist_add(routers, r);
+    });
+
+#if 1
+  /*XXXX RD*/
+  send_control_error(conn, ERR_INTERNAL, "EXTENDCIRCUIT not implemented.");
+#else
+  SMARTLIST_FOREACH(routers, routerinfo_t *, r,
+    {
+      /*XXXX RD*/
+      if (circuit_extend_path(circ, r)<0) {
+        send_control_error(conn, ERR_INTERNAL, "Unable to extend path.");
+        goto done;
+      }
+    });
+#endif
+
+  send_control_done(conn);
+ done:
+  SMARTLIST_FOREACH(router_nicknames, char *, n, tor_free(n));
+  smartlist_free(router_nicknames);
+  smartlist_free(routers);
   return 0;
 }
 static int handle_control_attachstream(connection_t *conn, uint32_t len,
@@ -677,6 +726,7 @@ static int handle_control_attachstream(connection_t *conn, uint32_t len,
     send_control_error(conn, ERR_INTERNAL, "Unable to attach stream.");
     return 0;
   }
+  send_control_done(conn);
   return 0;
 }
 static int
@@ -693,6 +743,32 @@ handle_control_postdescriptor(connection_t *conn, uint32_t len,
   send_control_done(conn);
   return 0;
 }
+static int
+handle_control_redirectstream(connection_t *conn, uint32_t len,
+                              const char *body)
+{
+  connection_t *ap_conn;
+  uint32_t conn_id;
+  if (len < 6) {
+    send_control_error(conn, ERR_SYNTAX, "attachstream message too short");
+    return 0;
+  }
+  conn_id = ntohl(get_uint32(body));
+
+  if (!(ap_conn = connection_get_by_global_id(conn_id))
+      || ap_conn->state != CONN_TYPE_AP
+      || !ap_conn->socks_request) {
+    send_control_error(conn, ERR_NO_STREAM,
+                       "No AP connection found with given ID");
+    return 0;
+  }
+  strlcpy(ap_conn->socks_request->address, body+1,
+          sizeof(ap_conn->socks_request->address));
+
+  send_control_done(conn);
+  return 0;
+}
+
 
 /** Called when <b>conn</b> has no more bytes left on its outbuf. */
 int
@@ -798,6 +874,10 @@ connection_control_process_inbuf(connection_t *conn) {
       if (handle_control_postdescriptor(conn, body_len, body))
         return -1;
       break;
+    case CONTROL_CMD_REDIRECTSTREAM:
+      if (handle_control_redirectstream(conn, body_len, body))
+        return -1;
+      break;
     case CONTROL_CMD_ERROR:
     case CONTROL_CMD_DONE:
     case CONTROL_CMD_CONFVALUE: