mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-12-06 19:41:15 +01:00
Only caches download network-status for now, and they use a different strategy. Add an element to connection_t to remember what we are downloading, and a function to recognize our own fingerprint.
svn:r4944
This commit is contained in:
@@ -231,6 +231,7 @@ _connection_free(connection_t *conn)
|
||||
tor_free(conn->incoming_cmd);
|
||||
tor_free(conn->read_event); /* Probably already freed by connection_free. */
|
||||
tor_free(conn->write_event); /* Probably already freed by connection_free. */
|
||||
tor_free(conn->requested_resource);
|
||||
|
||||
if (conn->s >= 0) {
|
||||
log_fn(LOG_INFO,"closing fd %d.",conn->s);
|
||||
|
||||
+5
-5
@@ -180,9 +180,6 @@ directory_get_from_dirserver(uint8_t purpose, const char *resource,
|
||||
char digest[DIGEST_LEN];
|
||||
base16_decode(digest, DIGEST_LEN, resource+3, HEX_DIGEST_LEN);
|
||||
ds = router_get_trusteddirserver_by_digest(digest);
|
||||
// XXXXX NM remove this.
|
||||
log_fn(LOG_NOTICE, "Going straight to the authority for %s? %s",resource,
|
||||
ds? "Ok.":"Oops. I can't.");
|
||||
}
|
||||
if (!ds && fetch_fresh_first) {
|
||||
/* only ask authdirservers, and don't ask myself */
|
||||
@@ -403,6 +400,9 @@ directory_send_command(connection_t *conn, const char *platform,
|
||||
tor_assert(conn);
|
||||
tor_assert(conn->type == CONN_TYPE_DIR);
|
||||
|
||||
tor_free(conn->requested_resource);
|
||||
conn->requested_resource = tor_strdup(resource);
|
||||
|
||||
/* come up with a string for which Host: we want */
|
||||
if (conn->port == 80) {
|
||||
strlcpy(hoststring, conn->address, sizeof(hoststring));
|
||||
@@ -453,7 +453,6 @@ directory_send_command(connection_t *conn, const char *platform,
|
||||
httpcommand = "GET";//XXXX
|
||||
len = strlen(resource)+32;
|
||||
url = tor_malloc(len);
|
||||
log_fn(LOG_NOTICE, "Asking for %s", resource);
|
||||
tor_snprintf(url, len, "/tor/status/%s", resource);
|
||||
break;
|
||||
case DIR_PURPOSE_FETCH_SERVERDESC:
|
||||
@@ -889,7 +888,8 @@ connection_dir_client_reached_eof(connection_t *conn)
|
||||
|
||||
if (conn->purpose == DIR_PURPOSE_FETCH_NETWORKSTATUS) {
|
||||
/* XXXX NM We *must* make certain we get the one(s) we asked for or we
|
||||
* could be partitioned. */
|
||||
* could be partitioned. Also, never ask someone else for a status we
|
||||
* generated! */
|
||||
log_fn(LOG_INFO,"Received networkstatus objects (size %d) from server '%s:%d'",(int) body_len, conn->address, conn->port);
|
||||
if (status_code != 200) {
|
||||
log_fn(LOG_WARN,"Received http status code %d (\"%s\") from server '%s:%d'. Failing.",
|
||||
|
||||
+1
-3
@@ -1183,15 +1183,13 @@ dirserv_get_networkstatus_v2(smartlist_t *result,
|
||||
smartlist_add(result, val);
|
||||
}
|
||||
} else if (!strcmpstart(key, "fp/")) {
|
||||
char own_fp[HEX_DIGEST_LEN+1];
|
||||
crypto_pk_get_fingerprint(get_identity_key(), own_fp, 0);
|
||||
smartlist_t *hexdigests = smartlist_create();
|
||||
smartlist_split_string(hexdigests, key+3, "+", 0, 0);
|
||||
SMARTLIST_FOREACH(hexdigests, char *, cp,
|
||||
{
|
||||
cached_dir_t *cached;
|
||||
tor_strupper(cp);
|
||||
if (!strcmp(cp, own_fp) &&
|
||||
if (router_fingerprint_is_me(cp) &&
|
||||
get_options()->AuthoritativeDir &&
|
||||
the_v2_networkstatus_is_dirty &&
|
||||
the_v2_networkstatus_is_dirty + DIR_REGEN_SLACK_TIME < time(NULL))
|
||||
|
||||
+6
-1
@@ -732,7 +732,12 @@ run_scheduled_events(time_t now)
|
||||
!we_are_hibernating())
|
||||
consider_testing_reachability();
|
||||
|
||||
update_networkstatus_downloads();
|
||||
if (server_mode(options) && options->DirPort)
|
||||
update_networkstatus_cache_downloads(now);
|
||||
/* XXXX Disabled until 0.1.1.6 is out: only servers need networkstatus.
|
||||
else
|
||||
update_networkstatus_client_downloads(now);
|
||||
*/
|
||||
}
|
||||
|
||||
/** 3a. Every second, we examine pending circuits and prune the
|
||||
|
||||
+7
-2
@@ -673,7 +673,10 @@ struct connection_t {
|
||||
struct circuit_t *on_circuit; /**< The circuit (if any) that this edge
|
||||
* connection is using. */
|
||||
|
||||
/* Used only by AP connections */
|
||||
/* Used only by Dir connections */
|
||||
char *requested_resource; /**< Which 'resource' did we ask the directory for?*/
|
||||
|
||||
/* Used only by AP connections */
|
||||
socks_request_t *socks_request; /**< SOCKS structure describing request (AP
|
||||
* only.) */
|
||||
|
||||
@@ -1997,6 +2000,7 @@ routerinfo_t *router_get_my_routerinfo(void);
|
||||
const char *router_get_my_descriptor(void);
|
||||
int router_digest_is_me(const char *digest);
|
||||
int router_is_me(routerinfo_t *router);
|
||||
int router_fingerprint_is_me(const char *fp);
|
||||
int router_rebuild_descriptor(int force);
|
||||
int router_dump_router_to_string(char *s, size_t maxlen, routerinfo_t *router,
|
||||
crypto_pk_env_t *ident_key);
|
||||
@@ -2088,7 +2092,8 @@ void add_trusted_dir_server(const char *addr, uint16_t port,
|
||||
const char *digest, int supports_v1);
|
||||
void clear_trusted_dir_servers(void);
|
||||
networkstatus_t *networkstatus_get_by_digest(const char *digest);
|
||||
void update_networkstatus_downloads(void);
|
||||
void update_networkstatus_cache_downloads(time_t now);
|
||||
void update_networkstatus_client_downloads(time_t now);
|
||||
|
||||
/********************************* routerparse.c ************************/
|
||||
|
||||
|
||||
@@ -676,6 +676,18 @@ router_is_me(routerinfo_t *router)
|
||||
return router_digest_is_me(router->identity_digest);
|
||||
}
|
||||
|
||||
/** Return true iff <b>fp</b> is a hex fingerprint of my identity digest. */
|
||||
int
|
||||
router_fingerprint_is_me(const char *fp)
|
||||
{
|
||||
char digest[DIGEST_LEN];
|
||||
if (strlen(fp) == HEX_DIGEST_LEN &&
|
||||
base16_decode(digest, sizeof(digest), fp, HEX_DIGEST_LEN) == 0)
|
||||
return router_digest_is_me(digest);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Return a routerinfo for this OR, rebuilding a fresh one if
|
||||
* necessary. Return NULL on error, or if called on an OP. */
|
||||
routerinfo_t *
|
||||
|
||||
+41
-7
@@ -1208,8 +1208,6 @@ router_set_networkstatus(const char *s, time_t arrived_at, int is_cached)
|
||||
time_t now;
|
||||
char fp[HEX_DIGEST_LEN+1];
|
||||
|
||||
log_fn(LOG_NOTICE, "setting status (%d)", is_cached);
|
||||
|
||||
ns = networkstatus_parse_from_string(s);
|
||||
if (!ns) {
|
||||
log_fn(LOG_WARN, "Couldn't parse network status.");
|
||||
@@ -1277,19 +1275,54 @@ router_set_networkstatus(const char *s, time_t arrived_at, int is_cached)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* These should be configurable, perhaps. */
|
||||
#define AUTHORITY_NS_CACHE_INTERVAL 10*60
|
||||
#define NONAUTHORITY_NS_CACHE_INTERVAL 15*60
|
||||
void
|
||||
update_networkstatus_cache_downloads(time_t now)
|
||||
{
|
||||
static time_t last_downloaded = 0;
|
||||
int authority = authdir_mode(get_options());
|
||||
int interval =
|
||||
authority ? AUTHORITY_NS_CACHE_INTERVAL : NONAUTHORITY_NS_CACHE_INTERVAL;
|
||||
|
||||
if (last_downloaded + interval >= now)
|
||||
return;
|
||||
if (!trusted_dir_servers)
|
||||
return;
|
||||
|
||||
last_downloaded = now;
|
||||
|
||||
if (authority) {
|
||||
/* An authority launches a separate connection for everybody. */
|
||||
SMARTLIST_FOREACH(trusted_dir_servers, trusted_dir_server_t *, ds,
|
||||
{
|
||||
char resource[HEX_DIGEST_LEN+6];
|
||||
if (router_digest_is_me(ds->digest))
|
||||
continue;
|
||||
strlcpy(resource, "fp/", sizeof(resource));
|
||||
base16_encode(resource+3, sizeof(resource)-3, ds->digest, DIGEST_LEN);
|
||||
strlcat(resource, ".z", sizeof(resource));
|
||||
directory_get_from_dirserver(DIR_PURPOSE_FETCH_NETWORKSTATUS,resource,1);
|
||||
});
|
||||
} else {
|
||||
/* A non-authority cache launches one connection to a random authority. */
|
||||
directory_get_from_dirserver(DIR_PURPOSE_FETCH_NETWORKSTATUS,"all.z",1);
|
||||
}
|
||||
}
|
||||
|
||||
#define ABOUT_TWO_DAYS (48*60*60)
|
||||
#define ABOUT_HALF_AN_HOUR (30*60)
|
||||
/** DOCDOC */
|
||||
void
|
||||
update_networkstatus_downloads(void)
|
||||
update_networkstatus_client_downloads(time_t now)
|
||||
{
|
||||
/* XXX Yes, these constants are supposed to be dumb, so we can choose better
|
||||
* values. */
|
||||
#define ABOUT_TWO_DAYS (48*60*60)
|
||||
#define ABOUT_HALF_AN_HOUR (30*60)
|
||||
int n_live = 0, needed = 0, n_dirservers, i;
|
||||
int most_recent_idx = -1;
|
||||
trusted_dir_server_t *most_recent = NULL;
|
||||
time_t most_recent_received = 0;
|
||||
time_t now = time(NULL);
|
||||
|
||||
/* This is a little tricky. We want to download enough network-status
|
||||
* objects so that we have at least half of them under ABOUT_TWO_DAYS
|
||||
@@ -1332,13 +1365,14 @@ update_networkstatus_downloads(void)
|
||||
/* XXXX NM This could compress multiple downloads into a single request.
|
||||
* It could also be smarter on failures. */
|
||||
for (i = most_recent_idx+1; needed; ++i) {
|
||||
char resource[HEX_DIGEST_LEN+4];
|
||||
char resource[HEX_DIGEST_LEN+6];
|
||||
trusted_dir_server_t *ds;
|
||||
if (i >= n_dirservers)
|
||||
i = 0;
|
||||
ds = smartlist_get(trusted_dir_servers, i);
|
||||
strlcpy(resource, "fp/", sizeof(resource));
|
||||
base16_encode(resource+3, sizeof(resource)-3, ds->digest, DIGEST_LEN);
|
||||
strlcat(resource, ".z", sizeof(resource));
|
||||
directory_get_from_dirserver(DIR_PURPOSE_FETCH_NETWORKSTATUS, resource, 1);
|
||||
--needed;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user