diff --git a/doc/TODO b/doc/TODO
index 9f7746cb24..2d9c2432cf 100644
--- a/doc/TODO
+++ b/doc/TODO
@@ -75,7 +75,7 @@ Things we'd like to do in 0.2.0.x:
info and it's old enough, delete it. same with cached-routers*.
- document the "3/4 and 7/8" business in the clients fetching consensus
documents timeline. then document the bridge user download timeline.
- - refactor circuit_launch_by_foo so all those flags at the end are
+ o refactor circuit_launch_by_foo so all those flags at the end are
actually a flags argument.
- config option __ControllerLimit that hangs up if there are a limit
of controller connections already.
diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c
index 6ca23b9d51..851d7ff430 100644
--- a/src/or/circuitbuild.c
+++ b/src/or/circuitbuild.c
@@ -283,19 +283,23 @@ again:
}
/** Create and return a new origin circuit. Initialize its purpose and
- * build-state based on our arguments. */
+ * build-state based on our arguments. The flags argument is a
+ * bitfield of CIRCLAUNCH_* flags. */
origin_circuit_t *
-origin_circuit_init(uint8_t purpose, int onehop_tunnel,
- int need_uptime, int need_capacity, int internal)
+origin_circuit_init(uint8_t purpose, int flags)
{
/* sets circ->p_circ_id and circ->p_conn */
origin_circuit_t *circ = origin_circuit_new();
circuit_set_state(TO_CIRCUIT(circ), CIRCUIT_STATE_OR_WAIT);
circ->build_state = tor_malloc_zero(sizeof(cpath_build_state_t));
- circ->build_state->onehop_tunnel = onehop_tunnel;
- circ->build_state->need_uptime = need_uptime;
- circ->build_state->need_capacity = need_capacity;
- circ->build_state->is_internal = internal;
+ circ->build_state->onehop_tunnel =
+ ((flags & CIRCLAUNCH_ONEHOP_TUNNEL) ? 1 : 0);
+ circ->build_state->need_uptime =
+ ((flags & CIRCLAUNCH_NEED_UPTIME) ? 1 : 0);
+ circ->build_state->need_capacity =
+ ((flags & CIRCLAUNCH_NEED_CAPACITY) ? 1 : 0);
+ circ->build_state->is_internal =
+ ((flags & CIRCLAUNCH_IS_INTERNAL) ? 1 : 0);
circ->_base.purpose = purpose;
return circ;
}
@@ -308,15 +312,12 @@ origin_circuit_init(uint8_t purpose, int onehop_tunnel,
* it's not open already.
*/
origin_circuit_t *
-circuit_establish_circuit(uint8_t purpose, int onehop_tunnel,
- extend_info_t *exit,
- int need_uptime, int need_capacity, int internal)
+circuit_establish_circuit(uint8_t purpose, extend_info_t *exit, int flags)
{
origin_circuit_t *circ;
int err_reason = 0;
- circ = origin_circuit_init(purpose, onehop_tunnel,
- need_uptime, need_capacity, internal);
+ circ = origin_circuit_init(purpose, flags);
if (onion_pick_cpath_exit(circ, exit) < 0 ||
onion_populate_cpath(circ) < 0) {
diff --git a/src/or/circuitlist.c b/src/or/circuitlist.c
index 375156b4e3..8eb442df84 100644
--- a/src/or/circuitlist.c
+++ b/src/or/circuitlist.c
@@ -791,19 +791,24 @@ circuit_get_intro_point(const char *digest)
}
/** Return a circuit that is open, is CIRCUIT_PURPOSE_C_GENERAL,
- * has a timestamp_dirty value of 0, is uptime/capacity/internal
- * if required, and if info is defined, does not already use info
+ * has a timestamp_dirty value of 0, has flags matching the CIRCLAUNCH_*
+ * flags in flags, and if info is defined, does not already use info
* as any of its hops; or NULL if no circuit fits this description.
*
- * If ! need_uptime, prefer returning non-uptime circuits.
+ * If !CIRCLAUNCH_NEED_UPTIME, prefer returning non-uptime circuits.
*/
origin_circuit_t *
circuit_find_to_cannibalize(uint8_t purpose, extend_info_t *info,
- int need_uptime,
- int need_capacity, int internal)
+ int flags)
{
+ /*XXXX020 arma: The purpose argument is ignored. Can that possibly be
+ * right? */
+
circuit_t *_circ;
origin_circuit_t *best=NULL;
+ int need_uptime = flags & CIRCLAUNCH_NEED_UPTIME;
+ int need_capacity = flags & CIRCLAUNCH_NEED_CAPACITY;
+ int internal = flags & CIRCLAUNCH_IS_INTERNAL;
log_debug(LD_CIRC,
"Hunting for a circ to cannibalize: purpose %d, uptime %d, "
diff --git a/src/or/circuituse.c b/src/or/circuituse.c
index 5bad9e65fe..fb752e0d2e 100644
--- a/src/or/circuituse.c
+++ b/src/or/circuituse.c
@@ -371,6 +371,7 @@ circuit_predict_and_launch_new(void)
int hidserv_needs_uptime=0, hidserv_needs_capacity=1;
int port_needs_uptime=0, port_needs_capacity=1;
time_t now = time(NULL);
+ int flags = 0;
/* First, count how many of each type of circuit we have already. */
for (circ=global_circuitlist;circ;circ = circ->next) {
@@ -402,22 +403,26 @@ circuit_predict_and_launch_new(void)
* and no circuit is currently available that can handle it. */
if (!circuit_all_predicted_ports_handled(now, &port_needs_uptime,
&port_needs_capacity)) {
+ if (port_needs_uptime)
+ flags |= CIRCLAUNCH_NEED_UPTIME;
+ if (port_needs_capacity)
+ flags |= CIRCLAUNCH_NEED_CAPACITY;
log_info(LD_CIRC,
"Have %d clean circs (%d internal), need another exit circ.",
num, num_internal);
- circuit_launch_by_router(CIRCUIT_PURPOSE_C_GENERAL, 0, NULL,
- port_needs_uptime, port_needs_capacity, 0);
+ circuit_launch_by_router(CIRCUIT_PURPOSE_C_GENERAL, NULL, flags);
return;
}
/* Third, see if we need any more hidden service (server) circuits. */
if (num_rend_services() && num_uptime_internal < 3) {
+ flags = (CIRCLAUNCH_NEED_CAPACITY | CIRCLAUNCH_NEED_UPTIME |
+ CIRCLAUNCH_IS_INTERNAL);
log_info(LD_CIRC,
"Have %d clean circs (%d internal), need another internal "
"circ for my hidden service.",
num, num_internal);
- circuit_launch_by_router(CIRCUIT_PURPOSE_C_GENERAL, 0, NULL,
- 1, 1, 1);
+ circuit_launch_by_router(CIRCUIT_PURPOSE_C_GENERAL, NULL, flags);
return;
}
@@ -426,12 +431,16 @@ circuit_predict_and_launch_new(void)
&hidserv_needs_capacity) &&
((num_uptime_internal<2 && hidserv_needs_uptime) ||
num_internal<2)) {
+ if (hidserv_needs_uptime)
+ flags |= CIRCLAUNCH_NEED_UPTIME;
+ if (hidserv_needs_capacity)
+ flags |= CIRCLAUNCH_NEED_CAPACITY;
+ flags |= CIRCLAUNCH_IS_INTERNAL;
log_info(LD_CIRC,
"Have %d clean circs (%d uptime-internal, %d internal), need"
" another hidserv circ.",
num, num_uptime_internal, num_internal);
- circuit_launch_by_router(CIRCUIT_PURPOSE_C_GENERAL, 0, NULL,
- hidserv_needs_uptime, hidserv_needs_capacity, 1);
+ circuit_launch_by_router(CIRCUIT_PURPOSE_C_GENERAL, NULL, flags);
return;
}
}
@@ -469,7 +478,7 @@ circuit_build_needed_circs(time_t now)
circ &&
circ->timestamp_created + TESTING_CIRCUIT_INTERVAL < now) {
log_fn(LOG_INFO,"Creating a new testing circuit.");
- circuit_launch_by_router(CIRCUIT_PURPOSE_C_GENERAL, 0, NULL, 0, 0, 0);
+ circuit_launch_by_router(CIRCUIT_PURPOSE_C_GENERAL, NULL, 0);
}
#endif
}
@@ -798,34 +807,33 @@ static int did_circs_fail_last_period = 0;
/** Launch a new circuit; see circuit_launch_by_extend_info() for
* details on arguments. */
origin_circuit_t *
-circuit_launch_by_router(uint8_t purpose, int onehop_tunnel,
- routerinfo_t *exit, int need_uptime,
- int need_capacity, int internal)
+circuit_launch_by_router(uint8_t purpose,
+ routerinfo_t *exit, int flags)
{
origin_circuit_t *circ;
extend_info_t *info = NULL;
if (exit)
info = extend_info_from_router(exit);
- circ = circuit_launch_by_extend_info(
- purpose, onehop_tunnel, info, need_uptime, need_capacity, internal);
+ circ = circuit_launch_by_extend_info(purpose, info, flags);
if (info)
extend_info_free(info);
return circ;
}
/** Launch a new circuit with purpose purpose and exit node
- * extend_info (or NULL to select a random exit node).
- * If need_uptime is true,
- * choose among routers with high uptime. If need_capacity is true,
- * choose among routers with high bandwidth. If internal is true, the
- * last hop need not be an exit node. Return the newly allocated circuit on
- * success, or NULL on failure. */
+ * extend_info (or NULL to select a random exit node). If flags
+ * contains CIRCLAUNCH_NEED_UPTIME, choose among routers with high uptime. If
+ * CIRCLAUNCH_NEED_CAPACITY is set, choose among routers with high bandwidth.
+ * If CIRCLAUNCH_IS_INTERNAL is true, the last hop need not be an exit node.
+ * If CIRCLAUNCH_ONEHOP_TUNNEL is set, the circuit will have only one hop.
+ * Return the newly allocated circuit on success, or NULL on failure. */
origin_circuit_t *
-circuit_launch_by_extend_info(uint8_t purpose, int onehop_tunnel,
- extend_info_t *extend_info, int need_uptime,
- int need_capacity, int internal)
+circuit_launch_by_extend_info(uint8_t purpose,
+ extend_info_t *extend_info,
+ int flags)
{
origin_circuit_t *circ;
+ int onehop_tunnel = flags & CIRCLAUNCH_ONEHOP_TUNNEL;
if (!onehop_tunnel && !router_have_minimum_dir_info()) {
log_debug(LD_CIRC,"Haven't fetched enough directory info yet; canceling "
@@ -838,8 +846,7 @@ circuit_launch_by_extend_info(uint8_t purpose, int onehop_tunnel,
/* see if there are appropriate circs available to cannibalize. */
/* XXX020 if we're planning to add a hop, perhaps we want to look for
* internal circs rather than exit circs? -RD */
- circ = circuit_find_to_cannibalize(purpose, extend_info,
- need_uptime, need_capacity, internal);
+ circ = circuit_find_to_cannibalize(purpose, extend_info, flags);
if (circ) {
log_info(LD_CIRC,"Cannibalizing circ '%s' for purpose %d",
build_state_get_exit_nickname(circ->build_state), purpose);
@@ -881,16 +888,14 @@ circuit_launch_by_extend_info(uint8_t purpose, int onehop_tunnel,
/* try a circ. if it fails, circuit_mark_for_close will increment
* n_circuit_failures */
- return circuit_establish_circuit(purpose, onehop_tunnel, extend_info,
- need_uptime, need_capacity, internal);
+ return circuit_establish_circuit(purpose, extend_info, flags);
}
/** Launch a new circuit; see circuit_launch_by_extend_info() for
* details on arguments. */
origin_circuit_t *
-circuit_launch_by_nickname(uint8_t purpose, int onehop_tunnel,
- const char *exit_nickname,
- int need_uptime, int need_capacity, int internal)
+circuit_launch_by_nickname(uint8_t purpose,
+ const char *exit_nickname, int flags)
{
routerinfo_t *router = NULL;
@@ -902,8 +907,7 @@ circuit_launch_by_nickname(uint8_t purpose, int onehop_tunnel,
return NULL;
}
}
- return circuit_launch_by_router(purpose, onehop_tunnel, router,
- need_uptime, need_capacity, internal);
+ return circuit_launch_by_router(purpose, router, flags);
}
/** Record another failure at opening a general circuit. When we have
@@ -1085,9 +1089,15 @@ circuit_get_open_circ_or_launch(edge_connection_t *conn,
else
new_circ_purpose = desired_circuit_purpose;
- circ = circuit_launch_by_extend_info(
- new_circ_purpose, want_onehop, extend_info,
- need_uptime, 1, need_internal);
+ {
+ int flags = CIRCLAUNCH_NEED_CAPACITY;
+ if (want_onehop) flags |= CIRCLAUNCH_ONEHOP_TUNNEL;
+ if (need_uptime) flags |= CIRCLAUNCH_NEED_UPTIME;
+ if (need_internal) flags |= CIRCLAUNCH_IS_INTERNAL;
+ circ = circuit_launch_by_extend_info(new_circ_purpose, extend_info,
+ flags);
+ }
+
if (extend_info)
extend_info_free(extend_info);
diff --git a/src/or/control.c b/src/or/control.c
index 64712cff96..c91890cf6c 100644
--- a/src/or/control.c
+++ b/src/or/control.c
@@ -2019,7 +2019,7 @@ handle_control_extendcircuit(control_connection_t *conn, uint32_t len,
if (zero_circ) {
/* start a new circuit */
- circ = origin_circuit_init(intended_purpose, 0, 0, 0, 0);
+ circ = origin_circuit_init(intended_purpose, 0);
}
/* now circ refers to something that is ready to be extended */
diff --git a/src/or/or.h b/src/or/or.h
index 5e2610994e..1e817144a0 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -2473,13 +2473,10 @@ char *circuit_list_path_for_controller(origin_circuit_t *circ);
void circuit_log_path(int severity, unsigned int domain,
origin_circuit_t *circ);
void circuit_rep_hist_note_result(origin_circuit_t *circ);
-origin_circuit_t *origin_circuit_init(uint8_t purpose, int onehop_tunnel,
- int need_uptime,
- int need_capacity, int internal);
+origin_circuit_t *origin_circuit_init(uint8_t purpose, int flags);
origin_circuit_t *circuit_establish_circuit(uint8_t purpose,
- int onehop_tunnel, extend_info_t *exit,
- int need_uptime, int need_capacity,
- int internal);
+ extend_info_t *exit,
+ int flags);
int circuit_handle_first_hop(origin_circuit_t *circ);
void circuit_n_conn_done(or_connection_t *or_conn, int status);
int inform_testing_reachability(void);
@@ -2556,9 +2553,7 @@ origin_circuit_t *circuit_get_next_by_pk_and_purpose(origin_circuit_t *start,
or_circuit_t *circuit_get_rendezvous(const char *cookie);
or_circuit_t *circuit_get_intro_point(const char *digest);
origin_circuit_t *circuit_find_to_cannibalize(uint8_t purpose,
- extend_info_t *info,
- int need_uptime,
- int need_capacity, int internal);
+ extend_info_t *info, int flags);
void circuit_mark_all_unused_circs(void);
void circuit_expire_all_dirty_circs(void);
void _circuit_mark_for_close(circuit_t *circ, int reason,
@@ -2590,21 +2585,24 @@ int circuit_enough_testing_circs(void);
void circuit_has_opened(origin_circuit_t *circ);
void circuit_build_failed(origin_circuit_t *circ);
+
+/** Flag to set when a circuit should have only a single hop. */
+#define CIRCLAUNCH_ONEHOP_TUNNEL (1<<0)
+/** Flag to set when a circuit needs to be built of high-uptime nodes */
+#define CIRCLAUNCH_NEED_UPTIME (1<<1)
+/** Flag to set when a circuit needs to be build of high-capcity nodes */
+#define CIRCLAUNCH_NEED_CAPACITY (1<<2)
+/** Flag to set when the last hop of a circuit doesn't need to be an
+ * exit node. */
+#define CIRCLAUNCH_IS_INTERNAL (1<<3)
origin_circuit_t *circuit_launch_by_nickname(uint8_t purpose,
- int onehop_tunnel,
- const char *exit_nickname,
- int need_uptime, int need_capacity,
- int is_internal);
+ const char *exit_nickname,
+ int flags);
origin_circuit_t *circuit_launch_by_extend_info(uint8_t purpose,
- int onehop_tunnel,
- extend_info_t *info,
- int need_uptime, int need_capacity,
- int is_internal);
+ extend_info_t *info,
+ int flags);
origin_circuit_t *circuit_launch_by_router(uint8_t purpose,
- int onehop_tunnel,
- routerinfo_t *exit,
- int need_uptime, int need_capacity,
- int is_internal);
+ routerinfo_t *exit, int flags);
void circuit_reset_failure_count(int timeout);
int connection_ap_handshake_attach_chosen_circuit(edge_connection_t *conn,
origin_circuit_t *circ,
diff --git a/src/or/rendservice.c b/src/or/rendservice.c
index e80d5e947e..60bced974d 100644
--- a/src/or/rendservice.c
+++ b/src/or/rendservice.c
@@ -647,9 +647,10 @@ rend_service_introduce(origin_circuit_t *circuit, const char *request,
/* Launch a circuit to alice's chosen rendezvous point.
*/
for (i=0;ichosen_exit->nickname);
- newcirc = circuit_launch_by_extend_info(CIRCUIT_PURPOSE_S_CONNECT_REND, 0,
- oldstate->chosen_exit, 0, 1, 1);
+ newcirc = circuit_launch_by_extend_info(CIRCUIT_PURPOSE_S_CONNECT_REND,
+ oldstate->chosen_exit,
+ CIRCLAUNCH_NEED_CAPACITY|CIRCLAUNCH_IS_INTERNAL);
+
if (!newcirc) {
log_warn(LD_REND,"Couldn't relaunch rendezvous circuit to '%s'.",
oldstate->chosen_exit->nickname);
@@ -769,7 +772,9 @@ rend_service_launch_establish_intro(rend_service_t *service,
++service->n_intro_circuits_launched;
launched = circuit_launch_by_extend_info(CIRCUIT_PURPOSE_S_ESTABLISH_INTRO,
- 0, intro->extend_info, 1, 0, 1);
+ intro->extend_info,
+ CIRCLAUNCH_NEED_UPTIME|CIRCLAUNCH_IS_INTERNAL);
+
if (!launched) {
log_info(LD_REND,
"Can't launch circuit to establish introduction at %s.",
diff --git a/src/or/router.c b/src/or/router.c
index 510b0b773c..cdceac44ad 100644
--- a/src/or/router.c
+++ b/src/or/router.c
@@ -699,7 +699,8 @@ consider_testing_reachability(int test_or, int test_dir)
log_info(LD_CIRC, "Testing %s of my ORPort: %s:%d.",
!orport_reachable ? "reachability" : "bandwidth",
me->address, me->or_port);
- circuit_launch_by_router(CIRCUIT_PURPOSE_TESTING, 0, me, 0, 1, 1);
+ circuit_launch_by_router(CIRCUIT_PURPOSE_TESTING, me,
+ CIRCLAUNCH_NEED_CAPACITY|CIRCLAUNCH_IS_INTERNAL);
control_event_server_status(LOG_NOTICE,
"CHECKING_REACHABILITY ORADDRESS=%s:%d",
me->address, me->or_port);