diff options
Diffstat (limited to 'src/or/onion.c')
-rw-r--r-- | src/or/onion.c | 87 |
1 files changed, 36 insertions, 51 deletions
diff --git a/src/or/onion.c b/src/or/onion.c index 40b36685d4..924cbece12 100644 --- a/src/or/onion.c +++ b/src/or/onion.c @@ -223,7 +223,8 @@ static routerinfo_t *choose_good_exit_server(routerlist_t *dir) int best_support_idx = -1; int best_maybe_support_idx = -1; int n_best_support=0, n_best_maybe_support=0; - int n_running_routers=0; + smartlist_t *sl; + routerinfo_t *router; get_connection_array(&carray, &n_connections); @@ -262,7 +263,6 @@ static routerinfo_t *choose_good_exit_server(routerlist_t *dir) continue; /* skip routers that reject all */ } n_supported[i] = n_maybe_supported[i] = 0; - ++n_running_routers; for (j = 0; j < n_connections; ++j) { /* iterate over connections */ if (carray[j]->type != CONN_TYPE_AP || carray[j]->state != AP_CONN_STATE_CIRCUIT_WAIT || @@ -314,63 +314,48 @@ static routerinfo_t *choose_good_exit_server(routerlist_t *dir) /* If any routers definitely support any pending connections, choose one * at random. */ if (best_support > 0) { - i = crypto_pseudo_rand_int(n_best_support); - /* Iterate over the routers, until we find the i-th one such that - * n_supported[j] == best_support - */ - for (j = best_support_idx; j < dir->n_routers; ++j) { - if (n_supported[j] == best_support) { - if (i) - --i; - else { - tor_free(n_supported); tor_free(n_maybe_supported); - log_fn(LOG_DEBUG, "Chose exit server '%s'", dir->routers[j]->nickname); - return dir->routers[j]; - } - } - } - /* This point should never be reached. */ - assert(0); + sl = smartlist_create(MAX_ROUTERS_IN_DIR); + for(i = best_support_idx; i < dir->n_routers; i++) + if(n_supported[i] == best_support) + smartlist_add(sl, dir->routers[i]); + + router = smartlist_choose(sl); + smartlist_free(sl); + tor_free(n_supported); tor_free(n_maybe_supported); + log_fn(LOG_DEBUG, "Chose exit server '%s'", router->nickname); + return router; } + /* If any routers _maybe_ support pending connections, choose one at * random, as above. */ if (best_maybe_support > 0) { - i = crypto_pseudo_rand_int(n_best_maybe_support); - for (j = best_maybe_support_idx; j < dir->n_routers; ++j) { - if (n_maybe_supported[j] == best_maybe_support) { - if (i) - --i; - else { - tor_free(n_supported); tor_free(n_maybe_supported); - log_fn(LOG_DEBUG, "Chose exit server '%s'", dir->routers[j]->nickname); - return dir->routers[j]; - } - } - } - /* This point should never be reached. */ - assert(0); + sl = smartlist_create(MAX_ROUTERS_IN_DIR); + for(i = best_maybe_support_idx; i < dir->n_routers; i++) + if(n_maybe_supported[i] == best_maybe_support) + smartlist_add(sl, dir->routers[i]); + + router = smartlist_choose(sl); + smartlist_free(sl); + tor_free(n_supported); tor_free(n_maybe_supported); + log_fn(LOG_DEBUG, "Chose exit server '%s'", router->nickname); + return router; } + /* Either there are no pending connections, or no routers even seem to * possibly support any of them. Choose a router at random. */ - if (!n_running_routers) { - log_fn(LOG_WARN, "No exit routers seem to be running; can't choose an exit."); - return NULL; - } - /* Iterate over the routers, till we find the i'th one that has ->is_running - * and allows exits. */ - i = crypto_pseudo_rand_int(n_running_routers); - for (j = 0; j < dir->n_routers; ++j) { - if (n_supported[j] != -1) { - if (i) - --i; - else { - tor_free(n_supported); tor_free(n_maybe_supported); - log_fn(LOG_DEBUG, "Chose exit server '%s'", dir->routers[j]->nickname); - return dir->routers[j]; - } - } + sl = smartlist_create(MAX_ROUTERS_IN_DIR); + for(i = best_maybe_support_idx; i < dir->n_routers; i++) + if(n_supported[i] != -1) + smartlist_add(sl, dir->routers[i]); + + router = smartlist_choose(sl); + smartlist_free(sl); + if(router) { + tor_free(n_supported); tor_free(n_maybe_supported); + log_fn(LOG_DEBUG, "Chose exit server '%s'", router->nickname); + return router; } - assert(0); + log_fn(LOG_WARN, "No exit routers seem to be running; can't choose an exit."); return NULL; } |