move hidden-service stuff out of directory.c

svn:r13287
This commit is contained in:
Roger Dingledine 2008-01-26 00:42:13 +00:00
parent aa25bf1405
commit af4b735e9a
4 changed files with 169 additions and 173 deletions

View File

@ -3198,172 +3198,3 @@ dir_split_resource_into_fingerprints(const char *resource,
return 0;
}
/** Determine the responsible hidden service directories for the
* rend_encoded_v2_service_descriptor_t's in <b>descs</b> and upload them;
* <b>service_id</b> and <b>seconds_valid</b> are only passed for logging
* purposes. */
void
directory_post_to_hs_dir(smartlist_t *descs, const char *service_id,
int seconds_valid)
{
int i, j;
smartlist_t *responsible_dirs = smartlist_create();
routerstatus_t *hs_dir;
for (i = 0; i < smartlist_len(descs); i++) {
rend_encoded_v2_service_descriptor_t *desc = smartlist_get(descs, i);
/* Determine responsible dirs. */
if (hid_serv_get_responsible_directories(responsible_dirs,
desc->desc_id) < 0) {
log_warn(LD_REND, "Could not determine the responsible hidden service "
"directories to post descriptors to.");
smartlist_free(responsible_dirs);
return;
}
for (j = 0; j < smartlist_len(responsible_dirs); j++) {
char desc_id_base32[REND_DESC_ID_V2_LEN_BASE32 + 1];
hs_dir = smartlist_get(responsible_dirs, j);
/* Send publish request. */
directory_initiate_command_routerstatus(hs_dir,
DIR_PURPOSE_UPLOAD_RENDDESC_V2,
ROUTER_PURPOSE_GENERAL,
1, NULL, desc->desc_str,
strlen(desc->desc_str), 0);
base32_encode(desc_id_base32, sizeof(desc_id_base32),
desc->desc_id, DIGEST_LEN);
log_info(LD_REND, "Sending publish request for v2 descriptor for "
"service '%s' with descriptor ID '%s' with validity "
"of %d seconds to hidden service directory '%s' on "
"port %d.",
service_id,
desc_id_base32,
seconds_valid,
hs_dir->nickname,
hs_dir->dir_port);
}
smartlist_clear(responsible_dirs);
}
smartlist_free(responsible_dirs);
}
/** The period for which a hidden service directory cannot be queried for
* the same descriptor ID again. */
#define REND_HID_SERV_DIR_REQUERY_PERIOD (15 * 60)
/** Contains the last request times to hidden service directories for
* certain queries; keys are strings consisting of base32-encoded
* hidden service directory identities and base32-encoded descriptor IDs;
* values are pointers to timestamps of the last requests. */
static strmap_t *last_hid_serv_requests = NULL;
/** Look up the last request time to hidden service directory <b>hs_dir</b>
* for descriptor ID <b>desc_id_base32</b>. If <b>set</b> is non-zero,
* assign the current time <b>now</b> and return that. Otherwise, return
* the most recent request time, or 0 if no such request has been sent
* before. */
static time_t
lookup_last_hid_serv_request(routerstatus_t *hs_dir,
const char *desc_id_base32, time_t now, int set)
{
char hsdir_id_base32[REND_DESC_ID_V2_LEN_BASE32 + 1];
char hsdir_desc_comb_id[2 * REND_DESC_ID_V2_LEN_BASE32 + 1];
time_t *last_request_ptr;
base32_encode(hsdir_id_base32, sizeof(hsdir_id_base32),
hs_dir->identity_digest, DIGEST_LEN);
tor_snprintf(hsdir_desc_comb_id, sizeof(hsdir_desc_comb_id), "%s%s",
hsdir_id_base32, desc_id_base32);
if (set) {
last_request_ptr = tor_malloc_zero(sizeof(time_t *));
*last_request_ptr = now;
strmap_set(last_hid_serv_requests, hsdir_desc_comb_id, last_request_ptr);
} else
last_request_ptr = strmap_get_lc(last_hid_serv_requests,
hsdir_desc_comb_id);
return (last_request_ptr) ? *last_request_ptr : 0;
}
/** Clean the history of request times to hidden service directories, so that
* it does not contain requests older than REND_HID_SERV_DIR_REQUERY_PERIOD
* seconds any more. */
static void
directory_clean_last_hid_serv_requests(void)
{
strmap_iter_t *iter;
time_t cutoff = time(NULL) - REND_HID_SERV_DIR_REQUERY_PERIOD;
if (!last_hid_serv_requests)
last_hid_serv_requests = strmap_new();
for (iter = strmap_iter_init(last_hid_serv_requests);
!strmap_iter_done(iter); ) {
const char *key;
void *val;
time_t *ent;
strmap_iter_get(iter, &key, &val);
ent = (time_t *) val;
if (*ent < cutoff) {
iter = strmap_iter_next_rmv(last_hid_serv_requests, iter);
tor_free(ent);
} else {
iter = strmap_iter_next(last_hid_serv_requests, iter);
}
}
}
/** Determine the responsible hidden service directories for <b>desc_id</b>
* and fetch the descriptor belonging to that ID from one of them. Only
* send a request to hidden service directories that we did not try within
* the last REND_HID_SERV_DIR_REQUERY_PERIOD seconds; on success, return 1,
* in the case that no hidden service directory is left to ask for the
* descriptor, return 0, and in case of a failure -1. <b>query</b> is only
* passed for pretty log statements. */
int
directory_get_from_hs_dir(const char *desc_id, const char *query)
{
smartlist_t *responsible_dirs = smartlist_create();
routerstatus_t *hs_dir;
char desc_id_base32[REND_DESC_ID_V2_LEN_BASE32 + 1];
time_t now = time(NULL);
tor_assert(desc_id);
tor_assert(query);
tor_assert(strlen(query) == REND_SERVICE_ID_LEN_BASE32);
/* Determine responsible dirs. Even if we can't get all we want,
* work with the ones we have. If it's empty, we'll notice below. */
(int) hid_serv_get_responsible_directories(responsible_dirs, desc_id);
base32_encode(desc_id_base32, sizeof(desc_id_base32),
desc_id, DIGEST_LEN);
/* Only select those hidden service directories to which we did not send
* a request recently. */
directory_clean_last_hid_serv_requests(); /* Clean request history first. */
SMARTLIST_FOREACH(responsible_dirs, routerstatus_t *, dir, {
if (lookup_last_hid_serv_request(dir, desc_id_base32, 0, 0) +
REND_HID_SERV_DIR_REQUERY_PERIOD >= now)
SMARTLIST_DEL_CURRENT(responsible_dirs, dir);
});
hs_dir = smartlist_choose(responsible_dirs);
smartlist_free(responsible_dirs);
if (!hs_dir) {
log_info(LD_REND, "Could not pick one of the responsible hidden "
"service directories, because we requested them all "
"recently without success.");
return 0;
}
/* Remember, that we are requesting a descriptor from this hidden service
* directory now. */
lookup_last_hid_serv_request(hs_dir, desc_id_base32, now, 1);
/* Send fetch request. (Pass query as payload to write it to the directory
* connection so that it can be referred to when the response arrives.) */
directory_initiate_command_routerstatus(hs_dir,
DIR_PURPOSE_FETCH_RENDDESC_V2,
ROUTER_PURPOSE_GENERAL,
1, desc_id_base32, query, 0, 0);
log_info(LD_REND, "Sending fetch request for v2 descriptor for "
"service '%s' with descriptor ID '%s' to hidden "
"service directory '%s' on port %d.",
query, desc_id_base32, hs_dir->nickname, hs_dir->dir_port);
return 1;
}

View File

@ -3030,10 +3030,6 @@ int dir_split_resource_into_fingerprints(const char *resource,
char *directory_dump_request_log(void);
int router_supports_extrainfo(const char *identity_digest, int is_authority);
void directory_post_to_hs_dir(smartlist_t *descs, const char *service_id,
int seconds_valid);
int directory_get_from_hs_dir(const char *desc_id, const char *query);
time_t download_status_increment_failure(download_status_t *dls,
int status_code, const char *item,
int server, time_t now);

View File

@ -267,6 +267,128 @@ rend_client_introduction_acked(origin_circuit_t *circ,
return 0;
}
/** The period for which a hidden service directory cannot be queried for
* the same descriptor ID again. */
#define REND_HID_SERV_DIR_REQUERY_PERIOD (15 * 60)
/** Contains the last request times to hidden service directories for
* certain queries; keys are strings consisting of base32-encoded
* hidden service directory identities and base32-encoded descriptor IDs;
* values are pointers to timestamps of the last requests. */
static strmap_t *last_hid_serv_requests = NULL;
/** Look up the last request time to hidden service directory <b>hs_dir</b>
* for descriptor ID <b>desc_id_base32</b>. If <b>set</b> is non-zero,
* assign the current time <b>now</b> and return that. Otherwise, return
* the most recent request time, or 0 if no such request has been sent
* before. */
static time_t
lookup_last_hid_serv_request(routerstatus_t *hs_dir,
const char *desc_id_base32, time_t now, int set)
{
char hsdir_id_base32[REND_DESC_ID_V2_LEN_BASE32 + 1];
char hsdir_desc_comb_id[2 * REND_DESC_ID_V2_LEN_BASE32 + 1];
time_t *last_request_ptr;
base32_encode(hsdir_id_base32, sizeof(hsdir_id_base32),
hs_dir->identity_digest, DIGEST_LEN);
tor_snprintf(hsdir_desc_comb_id, sizeof(hsdir_desc_comb_id), "%s%s",
hsdir_id_base32, desc_id_base32);
if (set) {
last_request_ptr = tor_malloc_zero(sizeof(time_t *));
*last_request_ptr = now;
strmap_set(last_hid_serv_requests, hsdir_desc_comb_id, last_request_ptr);
} else
last_request_ptr = strmap_get_lc(last_hid_serv_requests,
hsdir_desc_comb_id);
return (last_request_ptr) ? *last_request_ptr : 0;
}
/** Clean the history of request times to hidden service directories, so that
* it does not contain requests older than REND_HID_SERV_DIR_REQUERY_PERIOD
* seconds any more. */
static void
directory_clean_last_hid_serv_requests(void)
{
strmap_iter_t *iter;
time_t cutoff = time(NULL) - REND_HID_SERV_DIR_REQUERY_PERIOD;
if (!last_hid_serv_requests)
last_hid_serv_requests = strmap_new();
for (iter = strmap_iter_init(last_hid_serv_requests);
!strmap_iter_done(iter); ) {
const char *key;
void *val;
time_t *ent;
strmap_iter_get(iter, &key, &val);
ent = (time_t *) val;
if (*ent < cutoff) {
iter = strmap_iter_next_rmv(last_hid_serv_requests, iter);
tor_free(ent);
} else {
iter = strmap_iter_next(last_hid_serv_requests, iter);
}
}
}
/** Determine the responsible hidden service directories for <b>desc_id</b>
* and fetch the descriptor belonging to that ID from one of them. Only
* send a request to hidden service directories that we did not try within
* the last REND_HID_SERV_DIR_REQUERY_PERIOD seconds; on success, return 1,
* in the case that no hidden service directory is left to ask for the
* descriptor, return 0, and in case of a failure -1. <b>query</b> is only
* passed for pretty log statements. */
static int
directory_get_from_hs_dir(const char *desc_id, const char *query)
{
smartlist_t *responsible_dirs = smartlist_create();
routerstatus_t *hs_dir;
char desc_id_base32[REND_DESC_ID_V2_LEN_BASE32 + 1];
time_t now = time(NULL);
tor_assert(desc_id);
tor_assert(query);
tor_assert(strlen(query) == REND_SERVICE_ID_LEN_BASE32);
/* Determine responsible dirs. Even if we can't get all we want,
* work with the ones we have. If it's empty, we'll notice below. */
(int) hid_serv_get_responsible_directories(responsible_dirs, desc_id);
base32_encode(desc_id_base32, sizeof(desc_id_base32),
desc_id, DIGEST_LEN);
/* Only select those hidden service directories to which we did not send
* a request recently. */
directory_clean_last_hid_serv_requests(); /* Clean request history first. */
SMARTLIST_FOREACH(responsible_dirs, routerstatus_t *, dir, {
if (lookup_last_hid_serv_request(dir, desc_id_base32, 0, 0) +
REND_HID_SERV_DIR_REQUERY_PERIOD >= now)
SMARTLIST_DEL_CURRENT(responsible_dirs, dir);
});
hs_dir = smartlist_choose(responsible_dirs);
smartlist_free(responsible_dirs);
if (!hs_dir) {
log_info(LD_REND, "Could not pick one of the responsible hidden "
"service directories, because we requested them all "
"recently without success.");
return 0;
}
/* Remember, that we are requesting a descriptor from this hidden service
* directory now. */
lookup_last_hid_serv_request(hs_dir, desc_id_base32, now, 1);
/* Send fetch request. (Pass query as payload to write it to the directory
* connection so that it can be referred to when the response arrives.) */
directory_initiate_command_routerstatus(hs_dir,
DIR_PURPOSE_FETCH_RENDDESC_V2,
ROUTER_PURPOSE_GENERAL,
1, desc_id_base32, query, 0, 0);
log_info(LD_REND, "Sending fetch request for v2 descriptor for "
"service '%s' with descriptor ID '%s' to hidden "
"service directory '%s' on port %d.",
query, desc_id_base32, hs_dir->nickname, hs_dir->dir_port);
return 1;
}
/** If we are not currently fetching a rendezvous service descriptor
* for the service ID <b>query</b>, start a directory connection to fetch a
* new one.

View File

@ -1030,6 +1030,53 @@ find_intro_circuit(rend_intro_point_t *intro, const char *pk_digest,
return NULL;
}
/** Determine the responsible hidden service directories for the
* rend_encoded_v2_service_descriptor_t's in <b>descs</b> and upload them;
* <b>service_id</b> and <b>seconds_valid</b> are only passed for logging
* purposes. */
static void
directory_post_to_hs_dir(smartlist_t *descs, const char *service_id,
int seconds_valid)
{
int i, j;
smartlist_t *responsible_dirs = smartlist_create();
routerstatus_t *hs_dir;
for (i = 0; i < smartlist_len(descs); i++) {
rend_encoded_v2_service_descriptor_t *desc = smartlist_get(descs, i);
/* Determine responsible dirs. */
if (hid_serv_get_responsible_directories(responsible_dirs,
desc->desc_id) < 0) {
log_warn(LD_REND, "Could not determine the responsible hidden service "
"directories to post descriptors to.");
smartlist_free(responsible_dirs);
return;
}
for (j = 0; j < smartlist_len(responsible_dirs); j++) {
char desc_id_base32[REND_DESC_ID_V2_LEN_BASE32 + 1];
hs_dir = smartlist_get(responsible_dirs, j);
/* Send publish request. */
directory_initiate_command_routerstatus(hs_dir,
DIR_PURPOSE_UPLOAD_RENDDESC_V2,
ROUTER_PURPOSE_GENERAL,
1, NULL, desc->desc_str,
strlen(desc->desc_str), 0);
base32_encode(desc_id_base32, sizeof(desc_id_base32),
desc->desc_id, DIGEST_LEN);
log_info(LD_REND, "Sending publish request for v2 descriptor for "
"service '%s' with descriptor ID '%s' with validity "
"of %d seconds to hidden service directory '%s' on "
"port %d.",
service_id,
desc_id_base32,
seconds_valid,
hs_dir->nickname,
hs_dir->dir_port);
}
smartlist_clear(responsible_dirs);
}
smartlist_free(responsible_dirs);
}
/** Encode and sign up-to-date v0 and/or v2 service descriptors for
* <b>service</b>, and upload it/them to all the dirservers/to the
* responsible hidden service directories.