r15653@tombo: nickm | 2007-12-23 14:15:12 -0500

Refactor circuit_launch* functions to take a bitfield of flags rather than 4 separate nonconsecutive flags arguments.  Also, note a possible but in circuit_find_to_cannibalize, which seems to be ignoring its purpose argument.


svn:r12948
This commit is contained in:
Nick Mathewson 2007-12-23 19:15:22 +00:00
parent 473725e1a4
commit da06bfb80f
8 changed files with 99 additions and 79 deletions

View File

@ -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*. 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 - document the "3/4 and 7/8" business in the clients fetching consensus
documents timeline. then document the bridge user download timeline. 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. actually a flags argument.
- config option __ControllerLimit that hangs up if there are a limit - config option __ControllerLimit that hangs up if there are a limit
of controller connections already. of controller connections already.

View File

@ -283,19 +283,23 @@ again:
} }
/** Create and return a new origin circuit. Initialize its purpose and /** Create and return a new origin circuit. Initialize its purpose and
* build-state based on our arguments. */ * build-state based on our arguments. The <b>flags</b> argument is a
* bitfield of CIRCLAUNCH_* flags. */
origin_circuit_t * origin_circuit_t *
origin_circuit_init(uint8_t purpose, int onehop_tunnel, origin_circuit_init(uint8_t purpose, int flags)
int need_uptime, int need_capacity, int internal)
{ {
/* sets circ->p_circ_id and circ->p_conn */ /* sets circ->p_circ_id and circ->p_conn */
origin_circuit_t *circ = origin_circuit_new(); origin_circuit_t *circ = origin_circuit_new();
circuit_set_state(TO_CIRCUIT(circ), CIRCUIT_STATE_OR_WAIT); circuit_set_state(TO_CIRCUIT(circ), CIRCUIT_STATE_OR_WAIT);
circ->build_state = tor_malloc_zero(sizeof(cpath_build_state_t)); circ->build_state = tor_malloc_zero(sizeof(cpath_build_state_t));
circ->build_state->onehop_tunnel = onehop_tunnel; circ->build_state->onehop_tunnel =
circ->build_state->need_uptime = need_uptime; ((flags & CIRCLAUNCH_ONEHOP_TUNNEL) ? 1 : 0);
circ->build_state->need_capacity = need_capacity; circ->build_state->need_uptime =
circ->build_state->is_internal = internal; ((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; circ->_base.purpose = purpose;
return circ; return circ;
} }
@ -308,15 +312,12 @@ origin_circuit_init(uint8_t purpose, int onehop_tunnel,
* it's not open already. * it's not open already.
*/ */
origin_circuit_t * origin_circuit_t *
circuit_establish_circuit(uint8_t purpose, int onehop_tunnel, circuit_establish_circuit(uint8_t purpose, extend_info_t *exit, int flags)
extend_info_t *exit,
int need_uptime, int need_capacity, int internal)
{ {
origin_circuit_t *circ; origin_circuit_t *circ;
int err_reason = 0; int err_reason = 0;
circ = origin_circuit_init(purpose, onehop_tunnel, circ = origin_circuit_init(purpose, flags);
need_uptime, need_capacity, internal);
if (onion_pick_cpath_exit(circ, exit) < 0 || if (onion_pick_cpath_exit(circ, exit) < 0 ||
onion_populate_cpath(circ) < 0) { onion_populate_cpath(circ) < 0) {

View File

@ -791,19 +791,24 @@ circuit_get_intro_point(const char *digest)
} }
/** Return a circuit that is open, is CIRCUIT_PURPOSE_C_GENERAL, /** Return a circuit that is open, is CIRCUIT_PURPOSE_C_GENERAL,
* has a timestamp_dirty value of 0, is uptime/capacity/internal * has a timestamp_dirty value of 0, has flags matching the CIRCLAUNCH_*
* if required, and if info is defined, does not already use info * flags in <b>flags</b>, and if info is defined, does not already use info
* as any of its hops; or NULL if no circuit fits this description. * 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 * origin_circuit_t *
circuit_find_to_cannibalize(uint8_t purpose, extend_info_t *info, circuit_find_to_cannibalize(uint8_t purpose, extend_info_t *info,
int need_uptime, int flags)
int need_capacity, int internal)
{ {
/*XXXX020 arma: The purpose argument is ignored. Can that possibly be
* right? */
circuit_t *_circ; circuit_t *_circ;
origin_circuit_t *best=NULL; 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, log_debug(LD_CIRC,
"Hunting for a circ to cannibalize: purpose %d, uptime %d, " "Hunting for a circ to cannibalize: purpose %d, uptime %d, "

View File

@ -371,6 +371,7 @@ circuit_predict_and_launch_new(void)
int hidserv_needs_uptime=0, hidserv_needs_capacity=1; int hidserv_needs_uptime=0, hidserv_needs_capacity=1;
int port_needs_uptime=0, port_needs_capacity=1; int port_needs_uptime=0, port_needs_capacity=1;
time_t now = time(NULL); time_t now = time(NULL);
int flags = 0;
/* First, count how many of each type of circuit we have already. */ /* First, count how many of each type of circuit we have already. */
for (circ=global_circuitlist;circ;circ = circ->next) { 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. */ * and no circuit is currently available that can handle it. */
if (!circuit_all_predicted_ports_handled(now, &port_needs_uptime, if (!circuit_all_predicted_ports_handled(now, &port_needs_uptime,
&port_needs_capacity)) { &port_needs_capacity)) {
if (port_needs_uptime)
flags |= CIRCLAUNCH_NEED_UPTIME;
if (port_needs_capacity)
flags |= CIRCLAUNCH_NEED_CAPACITY;
log_info(LD_CIRC, log_info(LD_CIRC,
"Have %d clean circs (%d internal), need another exit circ.", "Have %d clean circs (%d internal), need another exit circ.",
num, num_internal); num, num_internal);
circuit_launch_by_router(CIRCUIT_PURPOSE_C_GENERAL, 0, NULL, circuit_launch_by_router(CIRCUIT_PURPOSE_C_GENERAL, NULL, flags);
port_needs_uptime, port_needs_capacity, 0);
return; return;
} }
/* Third, see if we need any more hidden service (server) circuits. */ /* Third, see if we need any more hidden service (server) circuits. */
if (num_rend_services() && num_uptime_internal < 3) { if (num_rend_services() && num_uptime_internal < 3) {
flags = (CIRCLAUNCH_NEED_CAPACITY | CIRCLAUNCH_NEED_UPTIME |
CIRCLAUNCH_IS_INTERNAL);
log_info(LD_CIRC, log_info(LD_CIRC,
"Have %d clean circs (%d internal), need another internal " "Have %d clean circs (%d internal), need another internal "
"circ for my hidden service.", "circ for my hidden service.",
num, num_internal); num, num_internal);
circuit_launch_by_router(CIRCUIT_PURPOSE_C_GENERAL, 0, NULL, circuit_launch_by_router(CIRCUIT_PURPOSE_C_GENERAL, NULL, flags);
1, 1, 1);
return; return;
} }
@ -426,12 +431,16 @@ circuit_predict_and_launch_new(void)
&hidserv_needs_capacity) && &hidserv_needs_capacity) &&
((num_uptime_internal<2 && hidserv_needs_uptime) || ((num_uptime_internal<2 && hidserv_needs_uptime) ||
num_internal<2)) { 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, log_info(LD_CIRC,
"Have %d clean circs (%d uptime-internal, %d internal), need" "Have %d clean circs (%d uptime-internal, %d internal), need"
" another hidserv circ.", " another hidserv circ.",
num, num_uptime_internal, num_internal); num, num_uptime_internal, num_internal);
circuit_launch_by_router(CIRCUIT_PURPOSE_C_GENERAL, 0, NULL, circuit_launch_by_router(CIRCUIT_PURPOSE_C_GENERAL, NULL, flags);
hidserv_needs_uptime, hidserv_needs_capacity, 1);
return; return;
} }
} }
@ -469,7 +478,7 @@ circuit_build_needed_circs(time_t now)
circ && circ &&
circ->timestamp_created + TESTING_CIRCUIT_INTERVAL < now) { circ->timestamp_created + TESTING_CIRCUIT_INTERVAL < now) {
log_fn(LOG_INFO,"Creating a new testing circuit."); 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 #endif
} }
@ -798,34 +807,33 @@ static int did_circs_fail_last_period = 0;
/** Launch a new circuit; see circuit_launch_by_extend_info() for /** Launch a new circuit; see circuit_launch_by_extend_info() for
* details on arguments. */ * details on arguments. */
origin_circuit_t * origin_circuit_t *
circuit_launch_by_router(uint8_t purpose, int onehop_tunnel, circuit_launch_by_router(uint8_t purpose,
routerinfo_t *exit, int need_uptime, routerinfo_t *exit, int flags)
int need_capacity, int internal)
{ {
origin_circuit_t *circ; origin_circuit_t *circ;
extend_info_t *info = NULL; extend_info_t *info = NULL;
if (exit) if (exit)
info = extend_info_from_router(exit); info = extend_info_from_router(exit);
circ = circuit_launch_by_extend_info( circ = circuit_launch_by_extend_info(purpose, info, flags);
purpose, onehop_tunnel, info, need_uptime, need_capacity, internal);
if (info) if (info)
extend_info_free(info); extend_info_free(info);
return circ; return circ;
} }
/** Launch a new circuit with purpose <b>purpose</b> and exit node /** Launch a new circuit with purpose <b>purpose</b> and exit node
* <b>extend_info</b> (or NULL to select a random exit node). * <b>extend_info</b> (or NULL to select a random exit node). If flags
* If <b>need_uptime</b> is true, * contains CIRCLAUNCH_NEED_UPTIME, choose among routers with high uptime. If
* choose among routers with high uptime. If <b>need_capacity</b> is true, * CIRCLAUNCH_NEED_CAPACITY is set, choose among routers with high bandwidth.
* choose among routers with high bandwidth. If <b>internal</b> is true, the * If CIRCLAUNCH_IS_INTERNAL is true, the last hop need not be an exit node.
* last hop need not be an exit node. Return the newly allocated circuit on * If CIRCLAUNCH_ONEHOP_TUNNEL is set, the circuit will have only one hop.
* success, or NULL on failure. */ * Return the newly allocated circuit on success, or NULL on failure. */
origin_circuit_t * origin_circuit_t *
circuit_launch_by_extend_info(uint8_t purpose, int onehop_tunnel, circuit_launch_by_extend_info(uint8_t purpose,
extend_info_t *extend_info, int need_uptime, extend_info_t *extend_info,
int need_capacity, int internal) int flags)
{ {
origin_circuit_t *circ; origin_circuit_t *circ;
int onehop_tunnel = flags & CIRCLAUNCH_ONEHOP_TUNNEL;
if (!onehop_tunnel && !router_have_minimum_dir_info()) { if (!onehop_tunnel && !router_have_minimum_dir_info()) {
log_debug(LD_CIRC,"Haven't fetched enough directory info yet; canceling " 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. */ /* see if there are appropriate circs available to cannibalize. */
/* XXX020 if we're planning to add a hop, perhaps we want to look for /* XXX020 if we're planning to add a hop, perhaps we want to look for
* internal circs rather than exit circs? -RD */ * internal circs rather than exit circs? -RD */
circ = circuit_find_to_cannibalize(purpose, extend_info, circ = circuit_find_to_cannibalize(purpose, extend_info, flags);
need_uptime, need_capacity, internal);
if (circ) { if (circ) {
log_info(LD_CIRC,"Cannibalizing circ '%s' for purpose %d", log_info(LD_CIRC,"Cannibalizing circ '%s' for purpose %d",
build_state_get_exit_nickname(circ->build_state), purpose); 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 /* try a circ. if it fails, circuit_mark_for_close will increment
* n_circuit_failures */ * n_circuit_failures */
return circuit_establish_circuit(purpose, onehop_tunnel, extend_info, return circuit_establish_circuit(purpose, extend_info, flags);
need_uptime, need_capacity, internal);
} }
/** Launch a new circuit; see circuit_launch_by_extend_info() for /** Launch a new circuit; see circuit_launch_by_extend_info() for
* details on arguments. */ * details on arguments. */
origin_circuit_t * origin_circuit_t *
circuit_launch_by_nickname(uint8_t purpose, int onehop_tunnel, circuit_launch_by_nickname(uint8_t purpose,
const char *exit_nickname, const char *exit_nickname, int flags)
int need_uptime, int need_capacity, int internal)
{ {
routerinfo_t *router = NULL; routerinfo_t *router = NULL;
@ -902,8 +907,7 @@ circuit_launch_by_nickname(uint8_t purpose, int onehop_tunnel,
return NULL; return NULL;
} }
} }
return circuit_launch_by_router(purpose, onehop_tunnel, router, return circuit_launch_by_router(purpose, router, flags);
need_uptime, need_capacity, internal);
} }
/** Record another failure at opening a general circuit. When we have /** 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 else
new_circ_purpose = desired_circuit_purpose; new_circ_purpose = desired_circuit_purpose;
circ = circuit_launch_by_extend_info( {
new_circ_purpose, want_onehop, extend_info, int flags = CIRCLAUNCH_NEED_CAPACITY;
need_uptime, 1, need_internal); 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) if (extend_info)
extend_info_free(extend_info); extend_info_free(extend_info);

View File

@ -2019,7 +2019,7 @@ handle_control_extendcircuit(control_connection_t *conn, uint32_t len,
if (zero_circ) { if (zero_circ) {
/* start a new circuit */ /* 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 */ /* now circ refers to something that is ready to be extended */

View File

@ -2473,13 +2473,10 @@ char *circuit_list_path_for_controller(origin_circuit_t *circ);
void circuit_log_path(int severity, unsigned int domain, void circuit_log_path(int severity, unsigned int domain,
origin_circuit_t *circ); origin_circuit_t *circ);
void circuit_rep_hist_note_result(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, origin_circuit_t *origin_circuit_init(uint8_t purpose, int flags);
int need_uptime,
int need_capacity, int internal);
origin_circuit_t *circuit_establish_circuit(uint8_t purpose, origin_circuit_t *circuit_establish_circuit(uint8_t purpose,
int onehop_tunnel, extend_info_t *exit, extend_info_t *exit,
int need_uptime, int need_capacity, int flags);
int internal);
int circuit_handle_first_hop(origin_circuit_t *circ); int circuit_handle_first_hop(origin_circuit_t *circ);
void circuit_n_conn_done(or_connection_t *or_conn, int status); void circuit_n_conn_done(or_connection_t *or_conn, int status);
int inform_testing_reachability(void); 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_rendezvous(const char *cookie);
or_circuit_t *circuit_get_intro_point(const char *digest); or_circuit_t *circuit_get_intro_point(const char *digest);
origin_circuit_t *circuit_find_to_cannibalize(uint8_t purpose, origin_circuit_t *circuit_find_to_cannibalize(uint8_t purpose,
extend_info_t *info, extend_info_t *info, int flags);
int need_uptime,
int need_capacity, int internal);
void circuit_mark_all_unused_circs(void); void circuit_mark_all_unused_circs(void);
void circuit_expire_all_dirty_circs(void); void circuit_expire_all_dirty_circs(void);
void _circuit_mark_for_close(circuit_t *circ, int reason, 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_has_opened(origin_circuit_t *circ);
void circuit_build_failed(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, origin_circuit_t *circuit_launch_by_nickname(uint8_t purpose,
int onehop_tunnel, const char *exit_nickname,
const char *exit_nickname, int flags);
int need_uptime, int need_capacity,
int is_internal);
origin_circuit_t *circuit_launch_by_extend_info(uint8_t purpose, origin_circuit_t *circuit_launch_by_extend_info(uint8_t purpose,
int onehop_tunnel, extend_info_t *info,
extend_info_t *info, int flags);
int need_uptime, int need_capacity,
int is_internal);
origin_circuit_t *circuit_launch_by_router(uint8_t purpose, origin_circuit_t *circuit_launch_by_router(uint8_t purpose,
int onehop_tunnel, routerinfo_t *exit, int flags);
routerinfo_t *exit,
int need_uptime, int need_capacity,
int is_internal);
void circuit_reset_failure_count(int timeout); void circuit_reset_failure_count(int timeout);
int connection_ap_handshake_attach_chosen_circuit(edge_connection_t *conn, int connection_ap_handshake_attach_chosen_circuit(edge_connection_t *conn,
origin_circuit_t *circ, origin_circuit_t *circ,

View File

@ -647,9 +647,10 @@ rend_service_introduce(origin_circuit_t *circuit, const char *request,
/* Launch a circuit to alice's chosen rendezvous point. /* Launch a circuit to alice's chosen rendezvous point.
*/ */
for (i=0;i<MAX_REND_FAILURES;i++) { for (i=0;i<MAX_REND_FAILURES;i++) {
int flags = CIRCLAUNCH_NEED_CAPACITY | CIRCLAUNCH_IS_INTERNAL;
if (circ_needs_uptime) flags |= CIRCLAUNCH_NEED_UPTIME;
launched = circuit_launch_by_extend_info( launched = circuit_launch_by_extend_info(
CIRCUIT_PURPOSE_S_CONNECT_REND, 0, extend_info, CIRCUIT_PURPOSE_S_CONNECT_REND, extend_info, flags);
circ_needs_uptime, 1, 1);
if (launched) if (launched)
break; break;
@ -728,8 +729,10 @@ rend_service_relaunch_rendezvous(origin_circuit_t *oldcirc)
log_info(LD_REND,"Reattempting rendezvous circuit to '%s'", log_info(LD_REND,"Reattempting rendezvous circuit to '%s'",
oldstate->chosen_exit->nickname); oldstate->chosen_exit->nickname);
newcirc = circuit_launch_by_extend_info(CIRCUIT_PURPOSE_S_CONNECT_REND, 0, newcirc = circuit_launch_by_extend_info(CIRCUIT_PURPOSE_S_CONNECT_REND,
oldstate->chosen_exit, 0, 1, 1); oldstate->chosen_exit,
CIRCLAUNCH_NEED_CAPACITY|CIRCLAUNCH_IS_INTERNAL);
if (!newcirc) { if (!newcirc) {
log_warn(LD_REND,"Couldn't relaunch rendezvous circuit to '%s'.", log_warn(LD_REND,"Couldn't relaunch rendezvous circuit to '%s'.",
oldstate->chosen_exit->nickname); oldstate->chosen_exit->nickname);
@ -769,7 +772,9 @@ rend_service_launch_establish_intro(rend_service_t *service,
++service->n_intro_circuits_launched; ++service->n_intro_circuits_launched;
launched = circuit_launch_by_extend_info(CIRCUIT_PURPOSE_S_ESTABLISH_INTRO, 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) { if (!launched) {
log_info(LD_REND, log_info(LD_REND,
"Can't launch circuit to establish introduction at %s.", "Can't launch circuit to establish introduction at %s.",

View File

@ -699,7 +699,8 @@ consider_testing_reachability(int test_or, int test_dir)
log_info(LD_CIRC, "Testing %s of my ORPort: %s:%d.", log_info(LD_CIRC, "Testing %s of my ORPort: %s:%d.",
!orport_reachable ? "reachability" : "bandwidth", !orport_reachable ? "reachability" : "bandwidth",
me->address, me->or_port); 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, control_event_server_status(LOG_NOTICE,
"CHECKING_REACHABILITY ORADDRESS=%s:%d", "CHECKING_REACHABILITY ORADDRESS=%s:%d",
me->address, me->or_port); me->address, me->or_port);