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.
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]
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
#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
#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
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. */
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,
send_control_error(conn, ERR_INTERNAL, "Unable to attach stream.");
return 0;
}
+ send_control_done(conn);
return 0;
}
static int
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
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: