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*.
- 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.

View File

@ -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 <b>flags</b> 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) {

View File

@ -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 <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.
*
* 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, "

View File

@ -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 <b>purpose</b> and exit node
* <b>extend_info</b> (or NULL to select a random exit node).
* If <b>need_uptime</b> is true,
* choose among routers with high uptime. If <b>need_capacity</b> is true,
* choose among routers with high bandwidth. If <b>internal</b> is true, the
* last hop need not be an exit node. Return the newly allocated circuit on
* success, or NULL on failure. */
* <b>extend_info</b> (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);

View File

@ -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 */

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,
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,

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.
*/
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(
CIRCUIT_PURPOSE_S_CONNECT_REND, 0, extend_info,
circ_needs_uptime, 1, 1);
CIRCUIT_PURPOSE_S_CONNECT_REND, extend_info, flags);
if (launched)
break;
@ -728,8 +729,10 @@ rend_service_relaunch_rendezvous(origin_circuit_t *oldcirc)
log_info(LD_REND,"Reattempting rendezvous circuit to '%s'",
oldstate->chosen_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.",

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.",
!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);