mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-12-06 19:41:15 +01:00
clients can now pick non-authdirservers for fetching directories.
servers still pick authdirservers, but they never pick themselves. but picking themselves for fetching rend descs is ok. svn:r2059
This commit is contained in:
+27
-15
@@ -80,11 +80,27 @@ void
|
||||
directory_get_from_dirserver(uint8_t purpose, const char *payload,
|
||||
int payload_len)
|
||||
{
|
||||
/* FFFF we might pass pick_directory_server a boolean to prefer
|
||||
* picking myself for some purposes, or prefer picking not myself
|
||||
* for other purposes. */
|
||||
directory_initiate_command(router_pick_directory_server(),
|
||||
purpose, payload, payload_len);
|
||||
routerinfo_t *ds;
|
||||
|
||||
if (purpose == DIR_PURPOSE_FETCH_DIR) {
|
||||
if (server_mode()) {
|
||||
/* only ask authdirservers, don't ask myself */
|
||||
ds = router_pick_directory_server(1, 1);
|
||||
} else {
|
||||
/* anybody with a non-zero dirport will do */
|
||||
ds = router_pick_directory_server(0, 1);
|
||||
}
|
||||
} else { // (purpose == DIR_PURPOSE_FETCH_RENDDESC)
|
||||
/* only ask authdirservers, any of them will do */
|
||||
ds = router_pick_directory_server(1, 0);
|
||||
}
|
||||
|
||||
if (!ds) { /* no viable dirserver found */
|
||||
log_fn(LOG_WARN,"No running dirservers known. Not trying. (purpose %d)", purpose);
|
||||
return;
|
||||
}
|
||||
|
||||
directory_initiate_command(ds, purpose, payload, payload_len);
|
||||
}
|
||||
|
||||
/** Launch a new connection to the directory server <b>router</b> to upload or
|
||||
@@ -102,6 +118,9 @@ directory_initiate_command(routerinfo_t *router, uint8_t purpose,
|
||||
{
|
||||
connection_t *conn;
|
||||
|
||||
tor_assert(router);
|
||||
tor_assert(router->dir_port);
|
||||
|
||||
switch (purpose)
|
||||
{
|
||||
case DIR_PURPOSE_FETCH_DIR:
|
||||
@@ -121,13 +140,6 @@ directory_initiate_command(routerinfo_t *router, uint8_t purpose,
|
||||
tor_assert(0);
|
||||
}
|
||||
|
||||
if (!router) { /* i guess they didn't have one in mind for me to use */
|
||||
log_fn(LOG_WARN,"No running dirservers known. Not trying. (purpose %d)", purpose);
|
||||
return;
|
||||
}
|
||||
|
||||
tor_assert(router->dir_port);
|
||||
|
||||
conn = connection_new(CONN_TYPE_DIR);
|
||||
|
||||
/* set up conn so it's got all the data we need to remember */
|
||||
@@ -169,7 +181,7 @@ directory_initiate_command(routerinfo_t *router, uint8_t purpose,
|
||||
}
|
||||
} else { /* we want to connect via tor */
|
||||
/* make an AP connection
|
||||
* populate it and add it at the right state
|
||||
* populate it and add it at the right state
|
||||
* socketpair and hook up both sides
|
||||
*/
|
||||
conn->s = connection_ap_make_bridge(conn->address, conn->port);
|
||||
@@ -297,7 +309,7 @@ parse_http_response(char *headers, int *code, char **message)
|
||||
* will take care of marking the connection for close.
|
||||
*/
|
||||
static int
|
||||
connection_dir_client_finished_reading(connection_t *conn)
|
||||
connection_dir_client_reached_eof(connection_t *conn)
|
||||
{
|
||||
char *body;
|
||||
char *headers;
|
||||
@@ -445,7 +457,7 @@ int connection_dir_process_inbuf(connection_t *conn) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
retval = connection_dir_client_finished_reading(conn);
|
||||
retval = connection_dir_client_reached_eof(conn);
|
||||
connection_mark_for_close(conn);
|
||||
return retval;
|
||||
} /* endif 'reached eof' */
|
||||
|
||||
+1
-1
@@ -1355,7 +1355,7 @@ int router_dump_router_to_string(char *s, int maxlen, routerinfo_t *router,
|
||||
|
||||
/********************************* routerlist.c ***************************/
|
||||
|
||||
routerinfo_t *router_pick_directory_server(void);
|
||||
routerinfo_t *router_pick_directory_server(int requireauth, int requireothers);
|
||||
int all_directory_servers_down(void);
|
||||
struct smartlist_t;
|
||||
void add_nickname_list_to_smartlist(struct smartlist_t *sl, const char *list);
|
||||
|
||||
+53
-37
@@ -19,7 +19,9 @@ extern or_options_t options; /**< command-line and config-file options */
|
||||
/* ********************************************************************** */
|
||||
|
||||
/* static function prototypes */
|
||||
static routerinfo_t *router_pick_directory_server_impl(void);
|
||||
static routerinfo_t *
|
||||
router_pick_directory_server_impl(int requireauth, int preferothers);
|
||||
static void mark_all_authdirservers_up(void);
|
||||
static int router_resolve_routerlist(routerlist_t *dir);
|
||||
|
||||
/****************************************************************************/
|
||||
@@ -35,32 +37,46 @@ static routerlist_t *routerlist = NULL;
|
||||
|
||||
extern int has_fetched_directory; /**< from main.c */
|
||||
|
||||
/** Try to find a running dirserver. If there are no running dirservers
|
||||
* in our routerlist, reload the routerlist and try again. */
|
||||
routerinfo_t *router_pick_directory_server(void) {
|
||||
/** Try to find a running dirserver. If there are no running dirservers
|
||||
* in our routerlist, set all the authoritative ones as running again,
|
||||
* and pick one. If there are no dirservers at all in our routerlist,
|
||||
* reload the routerlist and try one last time. */
|
||||
routerinfo_t *router_pick_directory_server(int requireauth, int requireothers) {
|
||||
routerinfo_t *choice;
|
||||
|
||||
choice = router_pick_directory_server_impl();
|
||||
if(!choice) {
|
||||
log_fn(LOG_WARN,"No dirservers known. Reloading and trying again.");
|
||||
has_fetched_directory=0; /* reset it */
|
||||
routerlist_clear_trusted_directories();
|
||||
if(options.RouterFile) {
|
||||
if(router_load_routerlist_from_file(options.RouterFile, 1) < 0)
|
||||
return NULL;
|
||||
} else {
|
||||
if(config_assign_default_dirservers() < 0)
|
||||
return NULL;
|
||||
}
|
||||
/* give it another try */
|
||||
choice = router_pick_directory_server_impl();
|
||||
choice = router_pick_directory_server_impl(requireauth, requireothers);
|
||||
if(choice)
|
||||
return choice;
|
||||
|
||||
log_fn(LOG_INFO,"No dirservers are reachable. Trying them all again.");
|
||||
/* mark all authdirservers are up again */
|
||||
mark_all_authdirservers_up();
|
||||
/* try again */
|
||||
choice = router_pick_directory_server_impl(requireauth, requireothers);
|
||||
if(choice)
|
||||
return choice;
|
||||
|
||||
log_fn(LOG_WARN,"No dirservers known. Reloading and trying again.");
|
||||
has_fetched_directory=0; /* reset it */
|
||||
routerlist_clear_trusted_directories();
|
||||
if(options.RouterFile) {
|
||||
if(router_load_routerlist_from_file(options.RouterFile, 1) < 0)
|
||||
return NULL;
|
||||
} else {
|
||||
if(config_assign_default_dirservers() < 0)
|
||||
return NULL;
|
||||
}
|
||||
/* give it one last try */
|
||||
choice = router_pick_directory_server_impl(requireauth, requireothers);
|
||||
return choice;
|
||||
}
|
||||
|
||||
/** Pick a random running router that's a trusted dirserver from our
|
||||
* routerlist. */
|
||||
static routerinfo_t *router_pick_directory_server_impl(void) {
|
||||
/** Pick a random running router from our routerlist. If requireauth,
|
||||
* it has to be a trusted server. If requireothers, it cannot be us.
|
||||
*/
|
||||
static routerinfo_t *
|
||||
router_pick_directory_server_impl(int requireauth, int requireothers)
|
||||
{
|
||||
int i;
|
||||
routerinfo_t *router;
|
||||
smartlist_t *sl;
|
||||
@@ -72,36 +88,36 @@ static routerinfo_t *router_pick_directory_server_impl(void) {
|
||||
sl = smartlist_create();
|
||||
for(i=0;i< smartlist_len(routerlist->routers); i++) {
|
||||
router = smartlist_get(routerlist->routers, i);
|
||||
if(router->is_running && router->is_trusted_dir) {
|
||||
tor_assert(router->dir_port > 0);
|
||||
smartlist_add(sl, router);
|
||||
}
|
||||
if(!router->is_running || !router->dir_port)
|
||||
continue;
|
||||
if(requireauth && !router->is_trusted_dir)
|
||||
continue;
|
||||
if(requireothers && router_is_me(router))
|
||||
continue;
|
||||
smartlist_add(sl, router);
|
||||
}
|
||||
|
||||
router = smartlist_choose(sl);
|
||||
smartlist_free(sl);
|
||||
return router;
|
||||
}
|
||||
|
||||
if(router)
|
||||
return router;
|
||||
log_fn(LOG_INFO,"No dirservers are reachable. Trying them all again.");
|
||||
/** Go through and mark the auth dirservers as up */
|
||||
static void mark_all_authdirservers_up(void) {
|
||||
int i;
|
||||
routerinfo_t *router;
|
||||
|
||||
if(!routerlist)
|
||||
return;
|
||||
|
||||
/* No running dir servers found? go through and mark them all as up,
|
||||
* so we cycle through the list again. */
|
||||
sl = smartlist_create();
|
||||
for(i=0; i < smartlist_len(routerlist->routers); i++) {
|
||||
router = smartlist_get(routerlist->routers, i);
|
||||
if(router->is_trusted_dir) {
|
||||
tor_assert(router->dir_port > 0);
|
||||
router->is_running = 1;
|
||||
router->status_set_at = time(NULL);
|
||||
smartlist_add(sl, router);
|
||||
}
|
||||
}
|
||||
router = smartlist_choose(sl);
|
||||
smartlist_free(sl);
|
||||
if(!router)
|
||||
log_fn(LOG_WARN,"No dirservers in directory! Returning NULL.");
|
||||
return router;
|
||||
}
|
||||
|
||||
/** Return 0 if \exists an authoritative dirserver that's currently
|
||||
|
||||
Reference in New Issue
Block a user