mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-10 21:23:58 +01:00
Merge remote-tracking branch 'public/ticket9969'
Conflicts: src/or/directory.c src/or/routerlist.c src/or/routerlist.h src/test/include.am src/test/test.c
This commit is contained in:
commit
5d4bb6f61f
@ -64,8 +64,6 @@ static void directory_send_command(dir_connection_t *conn,
|
|||||||
time_t if_modified_since);
|
time_t if_modified_since);
|
||||||
static int directory_handle_command(dir_connection_t *conn);
|
static int directory_handle_command(dir_connection_t *conn);
|
||||||
static int body_is_plausible(const char *body, size_t body_len, int purpose);
|
static int body_is_plausible(const char *body, size_t body_len, int purpose);
|
||||||
static int purpose_needs_anonymity(uint8_t dir_purpose,
|
|
||||||
uint8_t router_purpose);
|
|
||||||
static char *http_get_header(const char *headers, const char *which);
|
static char *http_get_header(const char *headers, const char *which);
|
||||||
static void http_set_address_origin(const char *headers, connection_t *conn);
|
static void http_set_address_origin(const char *headers, connection_t *conn);
|
||||||
static void connection_dir_download_routerdesc_failed(dir_connection_t *conn);
|
static void connection_dir_download_routerdesc_failed(dir_connection_t *conn);
|
||||||
@ -120,7 +118,7 @@ static void directory_initiate_command_rend(const tor_addr_t *addr,
|
|||||||
/** Return true iff the directory purpose <b>dir_purpose</b> (and if it's
|
/** Return true iff the directory purpose <b>dir_purpose</b> (and if it's
|
||||||
* fetching descriptors, it's fetching them for <b>router_purpose</b>)
|
* fetching descriptors, it's fetching them for <b>router_purpose</b>)
|
||||||
* must use an anonymous connection to a directory. */
|
* must use an anonymous connection to a directory. */
|
||||||
static int
|
STATIC int
|
||||||
purpose_needs_anonymity(uint8_t dir_purpose, uint8_t router_purpose)
|
purpose_needs_anonymity(uint8_t dir_purpose, uint8_t router_purpose)
|
||||||
{
|
{
|
||||||
if (get_options()->AllDirActionsPrivate)
|
if (get_options()->AllDirActionsPrivate)
|
||||||
@ -198,6 +196,47 @@ dir_conn_purpose_to_string(int purpose)
|
|||||||
return "(unknown)";
|
return "(unknown)";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Return the requisite directory information types. */
|
||||||
|
STATIC dirinfo_type_t
|
||||||
|
dir_fetch_type(int dir_purpose, int router_purpose, const char *resource)
|
||||||
|
{
|
||||||
|
dirinfo_type_t type;
|
||||||
|
switch (dir_purpose) {
|
||||||
|
case DIR_PURPOSE_FETCH_EXTRAINFO:
|
||||||
|
type = EXTRAINFO_DIRINFO;
|
||||||
|
if (router_purpose == ROUTER_PURPOSE_BRIDGE)
|
||||||
|
type |= BRIDGE_DIRINFO;
|
||||||
|
else
|
||||||
|
type |= V3_DIRINFO;
|
||||||
|
break;
|
||||||
|
case DIR_PURPOSE_FETCH_SERVERDESC:
|
||||||
|
if (router_purpose == ROUTER_PURPOSE_BRIDGE)
|
||||||
|
type = BRIDGE_DIRINFO;
|
||||||
|
else
|
||||||
|
type = V3_DIRINFO;
|
||||||
|
break;
|
||||||
|
case DIR_PURPOSE_FETCH_STATUS_VOTE:
|
||||||
|
case DIR_PURPOSE_FETCH_DETACHED_SIGNATURES:
|
||||||
|
case DIR_PURPOSE_FETCH_CERTIFICATE:
|
||||||
|
type = V3_DIRINFO;
|
||||||
|
break;
|
||||||
|
case DIR_PURPOSE_FETCH_CONSENSUS:
|
||||||
|
type = V3_DIRINFO;
|
||||||
|
if (resource && !strcmp(resource, "microdesc"))
|
||||||
|
type |= MICRODESC_DIRINFO;
|
||||||
|
break;
|
||||||
|
case DIR_PURPOSE_FETCH_MICRODESC:
|
||||||
|
type = MICRODESC_DIRINFO;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
log_warn(LD_BUG, "Unexpected purpose %d", (int)dir_purpose);
|
||||||
|
type = NO_DIRINFO;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/** Return true iff <b>identity_digest</b> is the digest of a router which
|
/** Return true iff <b>identity_digest</b> is the digest of a router which
|
||||||
* says that it caches extrainfos. (If <b>is_authority</b> we always
|
* says that it caches extrainfos. (If <b>is_authority</b> we always
|
||||||
* believe that to be true.) */
|
* believe that to be true.) */
|
||||||
@ -386,47 +425,21 @@ directory_pick_generic_dirserver(dirinfo_type_t type, int pds_flags,
|
|||||||
* Use <b>pds_flags</b> as arguments to router_pick_directory_server()
|
* Use <b>pds_flags</b> as arguments to router_pick_directory_server()
|
||||||
* or router_pick_trusteddirserver().
|
* or router_pick_trusteddirserver().
|
||||||
*/
|
*/
|
||||||
void
|
MOCK_IMPL(void, directory_get_from_dirserver, (uint8_t dir_purpose,
|
||||||
directory_get_from_dirserver(uint8_t dir_purpose, uint8_t router_purpose,
|
uint8_t router_purpose,
|
||||||
const char *resource, int pds_flags)
|
const char *resource,
|
||||||
|
int pds_flags))
|
||||||
{
|
{
|
||||||
const routerstatus_t *rs = NULL;
|
const routerstatus_t *rs = NULL;
|
||||||
const or_options_t *options = get_options();
|
const or_options_t *options = get_options();
|
||||||
int prefer_authority = directory_fetches_from_authorities(options);
|
int prefer_authority = directory_fetches_from_authorities(options);
|
||||||
int require_authority = 0;
|
int require_authority = 0;
|
||||||
int get_via_tor = purpose_needs_anonymity(dir_purpose, router_purpose);
|
int get_via_tor = purpose_needs_anonymity(dir_purpose, router_purpose);
|
||||||
dirinfo_type_t type;
|
dirinfo_type_t type = dir_fetch_type(dir_purpose, router_purpose, resource);
|
||||||
time_t if_modified_since = 0;
|
time_t if_modified_since = 0;
|
||||||
|
|
||||||
/* FFFF we could break this switch into its own function, and call
|
if (type == NO_DIRINFO)
|
||||||
* it elsewhere in directory.c. -RD */
|
return;
|
||||||
switch (dir_purpose) {
|
|
||||||
case DIR_PURPOSE_FETCH_EXTRAINFO:
|
|
||||||
type = EXTRAINFO_DIRINFO |
|
|
||||||
(router_purpose == ROUTER_PURPOSE_BRIDGE ? BRIDGE_DIRINFO :
|
|
||||||
V3_DIRINFO);
|
|
||||||
break;
|
|
||||||
case DIR_PURPOSE_FETCH_SERVERDESC:
|
|
||||||
type = (router_purpose == ROUTER_PURPOSE_BRIDGE ? BRIDGE_DIRINFO :
|
|
||||||
V3_DIRINFO);
|
|
||||||
break;
|
|
||||||
case DIR_PURPOSE_FETCH_STATUS_VOTE:
|
|
||||||
case DIR_PURPOSE_FETCH_DETACHED_SIGNATURES:
|
|
||||||
case DIR_PURPOSE_FETCH_CERTIFICATE:
|
|
||||||
type = V3_DIRINFO;
|
|
||||||
break;
|
|
||||||
case DIR_PURPOSE_FETCH_CONSENSUS:
|
|
||||||
type = V3_DIRINFO;
|
|
||||||
if (resource && !strcmp(resource,"microdesc"))
|
|
||||||
type |= MICRODESC_DIRINFO;
|
|
||||||
break;
|
|
||||||
case DIR_PURPOSE_FETCH_MICRODESC:
|
|
||||||
type = MICRODESC_DIRINFO;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
log_warn(LD_BUG, "Unexpected purpose %d", (int)dir_purpose);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dir_purpose == DIR_PURPOSE_FETCH_CONSENSUS) {
|
if (dir_purpose == DIR_PURPOSE_FETCH_CONSENSUS) {
|
||||||
int flav = FLAV_NS;
|
int flav = FLAV_NS;
|
||||||
@ -526,20 +539,16 @@ directory_get_from_dirserver(uint8_t dir_purpose, uint8_t router_purpose,
|
|||||||
/* */
|
/* */
|
||||||
rs = directory_pick_generic_dirserver(type, pds_flags,
|
rs = directory_pick_generic_dirserver(type, pds_flags,
|
||||||
dir_purpose);
|
dir_purpose);
|
||||||
if (!rs) {
|
if (!rs)
|
||||||
/*XXXX024 I'm pretty sure this can never do any good, since
|
|
||||||
* rs isn't set. */
|
|
||||||
get_via_tor = 1; /* last resort: try routing it via Tor */
|
get_via_tor = 1; /* last resort: try routing it via Tor */
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else { /* get_via_tor */
|
}
|
||||||
|
|
||||||
|
if (get_via_tor) {
|
||||||
/* Never use fascistfirewall; we're going via Tor. */
|
/* Never use fascistfirewall; we're going via Tor. */
|
||||||
if (1) {
|
pds_flags |= PDS_IGNORE_FASCISTFIREWALL;
|
||||||
/* anybody with a non-zero dirport will do. Disregard firewalls. */
|
rs = router_pick_directory_server(type, pds_flags);
|
||||||
pds_flags |= PDS_IGNORE_FASCISTFIREWALL;
|
|
||||||
rs = router_pick_directory_server(type, pds_flags);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If we have any hope of building an indirect conn, we know some router
|
/* If we have any hope of building an indirect conn, we know some router
|
||||||
@ -1271,7 +1280,8 @@ directory_send_command(dir_connection_t *conn,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strlen(proxystring) + strlen(url) >= 4096) {
|
/* warn in the non-tunneled case */
|
||||||
|
if (direct && (strlen(proxystring) + strlen(url) >= 4096)) {
|
||||||
log_warn(LD_BUG,
|
log_warn(LD_BUG,
|
||||||
"Squid does not like URLs longer than 4095 bytes, and this "
|
"Squid does not like URLs longer than 4095 bytes, and this "
|
||||||
"one is %d bytes long: %s%s",
|
"one is %d bytes long: %s%s",
|
||||||
|
@ -16,9 +16,10 @@ int directories_have_accepted_server_descriptor(void);
|
|||||||
void directory_post_to_dirservers(uint8_t dir_purpose, uint8_t router_purpose,
|
void directory_post_to_dirservers(uint8_t dir_purpose, uint8_t router_purpose,
|
||||||
dirinfo_type_t type, const char *payload,
|
dirinfo_type_t type, const char *payload,
|
||||||
size_t payload_len, size_t extrainfo_len);
|
size_t payload_len, size_t extrainfo_len);
|
||||||
void directory_get_from_dirserver(uint8_t dir_purpose, uint8_t router_purpose,
|
MOCK_DECL(void, directory_get_from_dirserver, (uint8_t dir_purpose,
|
||||||
const char *resource,
|
uint8_t router_purpose,
|
||||||
int pds_flags);
|
const char *resource,
|
||||||
|
int pds_flags));
|
||||||
void directory_get_from_all_authorities(uint8_t dir_purpose,
|
void directory_get_from_all_authorities(uint8_t dir_purpose,
|
||||||
uint8_t router_purpose,
|
uint8_t router_purpose,
|
||||||
const char *resource);
|
const char *resource);
|
||||||
@ -120,7 +121,11 @@ int download_status_get_n_failures(const download_status_t *dls);
|
|||||||
|
|
||||||
#ifdef TOR_UNIT_TESTS
|
#ifdef TOR_UNIT_TESTS
|
||||||
/* Used only by directory.c and test_dir.c */
|
/* Used only by directory.c and test_dir.c */
|
||||||
|
|
||||||
STATIC int parse_http_url(const char *headers, char **url);
|
STATIC int parse_http_url(const char *headers, char **url);
|
||||||
|
STATIC int purpose_needs_anonymity(uint8_t dir_purpose, uint8_t router_purpose);
|
||||||
|
STATIC dirinfo_type_t dir_fetch_type(int dir_purpose, int router_purpose,
|
||||||
|
const char *resource);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
11
src/or/or.h
11
src/or/or.h
@ -4961,14 +4961,13 @@ typedef struct dir_server_t {
|
|||||||
* or extrainfo documents.
|
* or extrainfo documents.
|
||||||
*
|
*
|
||||||
* Passed to router_pick_directory_server (et al)
|
* Passed to router_pick_directory_server (et al)
|
||||||
*
|
|
||||||
* [XXXX NOTE: This option is only implemented for pick_trusteddirserver,
|
|
||||||
* not pick_directory_server. If we make it work on pick_directory_server
|
|
||||||
* too, we could conservatively make it only prevent multiple fetches to
|
|
||||||
* the same authority, or we could aggressively make it prevent multiple
|
|
||||||
* fetches to _any_ single directory server.]
|
|
||||||
*/
|
*/
|
||||||
#define PDS_NO_EXISTING_SERVERDESC_FETCH (1<<3)
|
#define PDS_NO_EXISTING_SERVERDESC_FETCH (1<<3)
|
||||||
|
/** Flag to indicate that we should not use any directory authority to which
|
||||||
|
* we have an existing directory connection for downloading microdescs.
|
||||||
|
*
|
||||||
|
* Passed to router_pick_directory_server (et al)
|
||||||
|
*/
|
||||||
#define PDS_NO_EXISTING_MICRODESC_FETCH (1<<4)
|
#define PDS_NO_EXISTING_MICRODESC_FETCH (1<<4)
|
||||||
|
|
||||||
/** This node is to be chosen as a directory guard, so don't choose any
|
/** This node is to be chosen as a directory guard, so don't choose any
|
||||||
|
@ -65,7 +65,7 @@ static int compute_weighted_bandwidths(const smartlist_t *sl,
|
|||||||
bandwidth_weight_rule_t rule,
|
bandwidth_weight_rule_t rule,
|
||||||
u64_dbl_t **bandwidths_out);
|
u64_dbl_t **bandwidths_out);
|
||||||
static const routerstatus_t *router_pick_directory_server_impl(
|
static const routerstatus_t *router_pick_directory_server_impl(
|
||||||
dirinfo_type_t auth, int flags);
|
dirinfo_type_t auth, int flags, int *n_busy_out);
|
||||||
static const routerstatus_t *router_pick_trusteddirserver_impl(
|
static const routerstatus_t *router_pick_trusteddirserver_impl(
|
||||||
const smartlist_t *sourcelist, dirinfo_type_t auth,
|
const smartlist_t *sourcelist, dirinfo_type_t auth,
|
||||||
int flags, int *n_busy_out);
|
int flags, int *n_busy_out);
|
||||||
@ -1288,22 +1288,32 @@ router_get_fallback_dir_servers(void)
|
|||||||
const routerstatus_t *
|
const routerstatus_t *
|
||||||
router_pick_directory_server(dirinfo_type_t type, int flags)
|
router_pick_directory_server(dirinfo_type_t type, int flags)
|
||||||
{
|
{
|
||||||
|
int busy = 0;
|
||||||
const routerstatus_t *choice;
|
const routerstatus_t *choice;
|
||||||
|
|
||||||
if (!routerlist)
|
if (!routerlist)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
choice = router_pick_directory_server_impl(type, flags);
|
choice = router_pick_directory_server_impl(type, flags, &busy);
|
||||||
if (choice || !(flags & PDS_RETRY_IF_NO_SERVERS))
|
if (choice || !(flags & PDS_RETRY_IF_NO_SERVERS))
|
||||||
return choice;
|
return choice;
|
||||||
|
|
||||||
|
if (busy) {
|
||||||
|
/* If the reason that we got no server is that servers are "busy",
|
||||||
|
* we must be excluding good servers because we already have serverdesc
|
||||||
|
* fetches with them. Do not mark down servers up because of this. */
|
||||||
|
tor_assert((flags & (PDS_NO_EXISTING_SERVERDESC_FETCH|
|
||||||
|
PDS_NO_EXISTING_MICRODESC_FETCH)));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
log_info(LD_DIR,
|
log_info(LD_DIR,
|
||||||
"No reachable router entries for dirservers. "
|
"No reachable router entries for dirservers. "
|
||||||
"Trying them all again.");
|
"Trying them all again.");
|
||||||
/* mark all authdirservers as up again */
|
/* mark all authdirservers as up again */
|
||||||
mark_all_dirservers_up(fallback_dir_servers);
|
mark_all_dirservers_up(fallback_dir_servers);
|
||||||
/* try again */
|
/* try again */
|
||||||
choice = router_pick_directory_server_impl(type, flags);
|
choice = router_pick_directory_server_impl(type, flags, NULL);
|
||||||
return choice;
|
return choice;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1413,11 +1423,15 @@ router_pick_dirserver_generic(smartlist_t *sourcelist,
|
|||||||
#define DIR_503_TIMEOUT (60*60)
|
#define DIR_503_TIMEOUT (60*60)
|
||||||
|
|
||||||
/** Pick a random running valid directory server/mirror from our
|
/** Pick a random running valid directory server/mirror from our
|
||||||
* routerlist. Arguments are as for router_pick_directory_server(), except
|
* routerlist. Arguments are as for router_pick_directory_server(), except:
|
||||||
* that RETRY_IF_NO_SERVERS is ignored.
|
*
|
||||||
|
* If <b>n_busy_out</b> is provided, set *<b>n_busy_out</b> to the number of
|
||||||
|
* directories that we excluded for no other reason than
|
||||||
|
* PDS_NO_EXISTING_SERVERDESC_FETCH or PDS_NO_EXISTING_MICRODESC_FETCH.
|
||||||
*/
|
*/
|
||||||
static const routerstatus_t *
|
static const routerstatus_t *
|
||||||
router_pick_directory_server_impl(dirinfo_type_t type, int flags)
|
router_pick_directory_server_impl(dirinfo_type_t type, int flags,
|
||||||
|
int *n_busy_out)
|
||||||
{
|
{
|
||||||
const or_options_t *options = get_options();
|
const or_options_t *options = get_options();
|
||||||
const node_t *result;
|
const node_t *result;
|
||||||
@ -1426,10 +1440,12 @@ router_pick_directory_server_impl(dirinfo_type_t type, int flags)
|
|||||||
smartlist_t *overloaded_direct, *overloaded_tunnel;
|
smartlist_t *overloaded_direct, *overloaded_tunnel;
|
||||||
time_t now = time(NULL);
|
time_t now = time(NULL);
|
||||||
const networkstatus_t *consensus = networkstatus_get_latest_consensus();
|
const networkstatus_t *consensus = networkstatus_get_latest_consensus();
|
||||||
int requireother = ! (flags & PDS_ALLOW_SELF);
|
const int requireother = ! (flags & PDS_ALLOW_SELF);
|
||||||
int fascistfirewall = ! (flags & PDS_IGNORE_FASCISTFIREWALL);
|
const int fascistfirewall = ! (flags & PDS_IGNORE_FASCISTFIREWALL);
|
||||||
int for_guard = (flags & PDS_FOR_GUARD);
|
const int no_serverdesc_fetching = (flags & PDS_NO_EXISTING_SERVERDESC_FETCH);
|
||||||
int try_excluding = 1, n_excluded = 0;
|
const int no_microdesc_fetching = (flags & PDS_NO_EXISTING_MICRODESC_FETCH);
|
||||||
|
const int for_guard = (flags & PDS_FOR_GUARD);
|
||||||
|
int try_excluding = 1, n_excluded = 0, n_busy = 0;
|
||||||
|
|
||||||
if (!consensus)
|
if (!consensus)
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -1476,7 +1492,24 @@ router_pick_directory_server_impl(dirinfo_type_t type, int flags)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* XXXX IP6 proposal 118 */
|
/* XXXX IP6 proposal 118 */
|
||||||
tor_addr_from_ipv4h(&addr, node->rs->addr);
|
tor_addr_from_ipv4h(&addr, status->addr);
|
||||||
|
|
||||||
|
if (no_serverdesc_fetching && (
|
||||||
|
connection_get_by_type_addr_port_purpose(
|
||||||
|
CONN_TYPE_DIR, &addr, status->dir_port, DIR_PURPOSE_FETCH_SERVERDESC)
|
||||||
|
|| connection_get_by_type_addr_port_purpose(
|
||||||
|
CONN_TYPE_DIR, &addr, status->dir_port, DIR_PURPOSE_FETCH_EXTRAINFO)
|
||||||
|
)) {
|
||||||
|
++n_busy;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (no_microdesc_fetching && connection_get_by_type_addr_port_purpose(
|
||||||
|
CONN_TYPE_DIR, &addr, status->dir_port, DIR_PURPOSE_FETCH_MICRODESC)
|
||||||
|
) {
|
||||||
|
++n_busy;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
is_overloaded = status->last_dir_503_at + DIR_503_TIMEOUT > now;
|
is_overloaded = status->last_dir_503_at + DIR_503_TIMEOUT > now;
|
||||||
|
|
||||||
@ -1521,9 +1554,13 @@ router_pick_directory_server_impl(dirinfo_type_t type, int flags)
|
|||||||
* not set, try again without excluding nodes. */
|
* not set, try again without excluding nodes. */
|
||||||
try_excluding = 0;
|
try_excluding = 0;
|
||||||
n_excluded = 0;
|
n_excluded = 0;
|
||||||
|
n_busy = 0;
|
||||||
goto retry_without_exclude;
|
goto retry_without_exclude;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (n_busy_out)
|
||||||
|
*n_busy_out = n_busy;
|
||||||
|
|
||||||
return result ? result->rs : NULL;
|
return result ? result->rs : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4188,51 +4225,56 @@ list_pending_fpsk_downloads(fp_pair_map_t *result)
|
|||||||
* range.) If <b>source</b> is given, download from <b>source</b>;
|
* range.) If <b>source</b> is given, download from <b>source</b>;
|
||||||
* otherwise, download from an appropriate random directory server.
|
* otherwise, download from an appropriate random directory server.
|
||||||
*/
|
*/
|
||||||
static void
|
MOCK_IMPL(STATIC void, initiate_descriptor_downloads,
|
||||||
initiate_descriptor_downloads(const routerstatus_t *source,
|
(const routerstatus_t *source, int purpose, smartlist_t *digests,
|
||||||
int purpose,
|
int lo, int hi, int pds_flags))
|
||||||
smartlist_t *digests,
|
|
||||||
int lo, int hi, int pds_flags)
|
|
||||||
{
|
{
|
||||||
int i, n = hi-lo;
|
|
||||||
char *resource, *cp;
|
char *resource, *cp;
|
||||||
size_t r_len;
|
int digest_len, enc_digest_len;
|
||||||
|
const char *sep;
|
||||||
int digest_len = DIGEST_LEN, enc_digest_len = HEX_DIGEST_LEN;
|
int b64_256;
|
||||||
char sep = '+';
|
smartlist_t *tmp;
|
||||||
int b64_256 = 0;
|
|
||||||
|
|
||||||
if (purpose == DIR_PURPOSE_FETCH_MICRODESC) {
|
if (purpose == DIR_PURPOSE_FETCH_MICRODESC) {
|
||||||
/* Microdescriptors are downloaded by "-"-separated base64-encoded
|
/* Microdescriptors are downloaded by "-"-separated base64-encoded
|
||||||
* 256-bit digests. */
|
* 256-bit digests. */
|
||||||
digest_len = DIGEST256_LEN;
|
digest_len = DIGEST256_LEN;
|
||||||
enc_digest_len = BASE64_DIGEST256_LEN;
|
enc_digest_len = BASE64_DIGEST256_LEN + 1;
|
||||||
sep = '-';
|
sep = "-";
|
||||||
b64_256 = 1;
|
b64_256 = 1;
|
||||||
|
} else {
|
||||||
|
digest_len = DIGEST_LEN;
|
||||||
|
enc_digest_len = HEX_DIGEST_LEN + 1;
|
||||||
|
sep = "+";
|
||||||
|
b64_256 = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (n <= 0)
|
|
||||||
return;
|
|
||||||
if (lo < 0)
|
if (lo < 0)
|
||||||
lo = 0;
|
lo = 0;
|
||||||
if (hi > smartlist_len(digests))
|
if (hi > smartlist_len(digests))
|
||||||
hi = smartlist_len(digests);
|
hi = smartlist_len(digests);
|
||||||
|
|
||||||
r_len = 8 + (enc_digest_len+1)*n;
|
if (hi-lo <= 0)
|
||||||
cp = resource = tor_malloc(r_len);
|
return;
|
||||||
memcpy(cp, "d/", 2);
|
|
||||||
cp += 2;
|
tmp = smartlist_new();
|
||||||
for (i = lo; i < hi; ++i) {
|
|
||||||
|
for (; lo < hi; ++lo) {
|
||||||
|
cp = tor_malloc(enc_digest_len);
|
||||||
if (b64_256) {
|
if (b64_256) {
|
||||||
digest256_to_base64(cp, smartlist_get(digests, i));
|
digest256_to_base64(cp, smartlist_get(digests, lo));
|
||||||
} else {
|
} else {
|
||||||
base16_encode(cp, r_len-(cp-resource),
|
base16_encode(cp, enc_digest_len, smartlist_get(digests, lo), digest_len);
|
||||||
smartlist_get(digests,i), digest_len);
|
|
||||||
}
|
}
|
||||||
cp += enc_digest_len;
|
smartlist_add(tmp, cp);
|
||||||
*cp++ = sep;
|
|
||||||
}
|
}
|
||||||
memcpy(cp-1, ".z", 3);
|
|
||||||
|
cp = smartlist_join_strings(tmp, sep, 0, NULL);
|
||||||
|
tor_asprintf(&resource, "d/%s.z", cp);
|
||||||
|
|
||||||
|
SMARTLIST_FOREACH(tmp, char *, cp1, tor_free(cp1));
|
||||||
|
smartlist_free(tmp);
|
||||||
|
tor_free(cp);
|
||||||
|
|
||||||
if (source) {
|
if (source) {
|
||||||
/* We know which authority we want. */
|
/* We know which authority we want. */
|
||||||
@ -4247,14 +4289,28 @@ initiate_descriptor_downloads(const routerstatus_t *source,
|
|||||||
tor_free(resource);
|
tor_free(resource);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Max amount of hashes to download per request.
|
/** Return the max number of hashes to put in a URL for a given request.
|
||||||
* Since squid does not like URLs >= 4096 bytes we limit it to 96.
|
|
||||||
* 4096 - strlen(http://255.255.255.255/tor/server/d/.z) == 4058
|
|
||||||
* 4058/41 (40 for the hash and 1 for the + that separates them) => 98
|
|
||||||
* So use 96 because it's a nice number.
|
|
||||||
*/
|
*/
|
||||||
#define MAX_DL_PER_REQUEST 96
|
static int
|
||||||
#define MAX_MICRODESC_DL_PER_REQUEST 92
|
max_dl_per_request(const or_options_t *options, int purpose)
|
||||||
|
{
|
||||||
|
/* Since squid does not like URLs >= 4096 bytes we limit it to 96.
|
||||||
|
* 4096 - strlen(http://255.255.255.255/tor/server/d/.z) == 4058
|
||||||
|
* 4058/41 (40 for the hash and 1 for the + that separates them) => 98
|
||||||
|
* So use 96 because it's a nice number.
|
||||||
|
*/
|
||||||
|
int max = 96;
|
||||||
|
if (purpose == DIR_PURPOSE_FETCH_MICRODESC) {
|
||||||
|
max = 92;
|
||||||
|
}
|
||||||
|
/* If we're going to tunnel our connections, we can ask for a lot more
|
||||||
|
* in a request. */
|
||||||
|
if (!directory_fetches_from_authorities(options)) {
|
||||||
|
max = 500;
|
||||||
|
}
|
||||||
|
return max;
|
||||||
|
}
|
||||||
|
|
||||||
/** Don't split our requests so finely that we are requesting fewer than
|
/** Don't split our requests so finely that we are requesting fewer than
|
||||||
* this number per server. */
|
* this number per server. */
|
||||||
#define MIN_DL_PER_REQUEST 4
|
#define MIN_DL_PER_REQUEST 4
|
||||||
@ -4276,92 +4332,90 @@ launch_descriptor_downloads(int purpose,
|
|||||||
smartlist_t *downloadable,
|
smartlist_t *downloadable,
|
||||||
const routerstatus_t *source, time_t now)
|
const routerstatus_t *source, time_t now)
|
||||||
{
|
{
|
||||||
int should_delay = 0, n_downloadable;
|
|
||||||
const or_options_t *options = get_options();
|
const or_options_t *options = get_options();
|
||||||
const char *descname;
|
const char *descname;
|
||||||
|
const int fetch_microdesc = (purpose == DIR_PURPOSE_FETCH_MICRODESC);
|
||||||
|
int n_downloadable = smartlist_len(downloadable);
|
||||||
|
|
||||||
tor_assert(purpose == DIR_PURPOSE_FETCH_SERVERDESC ||
|
int i, n_per_request, max_dl_per_req;
|
||||||
purpose == DIR_PURPOSE_FETCH_MICRODESC);
|
const char *req_plural = "", *rtr_plural = "";
|
||||||
|
int pds_flags = PDS_RETRY_IF_NO_SERVERS;
|
||||||
|
|
||||||
descname = (purpose == DIR_PURPOSE_FETCH_SERVERDESC) ?
|
tor_assert(fetch_microdesc || purpose == DIR_PURPOSE_FETCH_SERVERDESC);
|
||||||
"routerdesc" : "microdesc";
|
descname = fetch_microdesc ? "microdesc" : "routerdesc";
|
||||||
|
|
||||||
|
if (!n_downloadable)
|
||||||
|
return;
|
||||||
|
|
||||||
n_downloadable = smartlist_len(downloadable);
|
|
||||||
if (!directory_fetches_dir_info_early(options)) {
|
if (!directory_fetches_dir_info_early(options)) {
|
||||||
if (n_downloadable >= MAX_DL_TO_DELAY) {
|
if (n_downloadable >= MAX_DL_TO_DELAY) {
|
||||||
log_debug(LD_DIR,
|
log_debug(LD_DIR,
|
||||||
"There are enough downloadable %ss to launch requests.",
|
"There are enough downloadable %ss to launch requests.",
|
||||||
descname);
|
descname);
|
||||||
should_delay = 0;
|
|
||||||
} else {
|
} else {
|
||||||
should_delay = (last_descriptor_download_attempted +
|
|
||||||
options->TestingClientMaxIntervalWithoutRequest) > now;
|
/* should delay */
|
||||||
if (!should_delay && n_downloadable) {
|
if ((last_descriptor_download_attempted +
|
||||||
if (last_descriptor_download_attempted) {
|
options->TestingClientMaxIntervalWithoutRequest) > now)
|
||||||
log_info(LD_DIR,
|
return;
|
||||||
"There are not many downloadable %ss, but we've "
|
|
||||||
"been waiting long enough (%d seconds). Downloading.",
|
if (last_descriptor_download_attempted) {
|
||||||
descname,
|
log_info(LD_DIR,
|
||||||
(int)(now-last_descriptor_download_attempted));
|
"There are not many downloadable %ss, but we've "
|
||||||
} else {
|
"been waiting long enough (%d seconds). Downloading.",
|
||||||
log_info(LD_DIR,
|
descname,
|
||||||
"There are not many downloadable %ss, but we haven't "
|
(int)(now-last_descriptor_download_attempted));
|
||||||
"tried downloading descriptors recently. Downloading.",
|
} else {
|
||||||
descname);
|
log_info(LD_DIR,
|
||||||
}
|
"There are not many downloadable %ss, but we haven't "
|
||||||
|
"tried downloading descriptors recently. Downloading.",
|
||||||
|
descname);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! should_delay && n_downloadable) {
|
if (!authdir_mode_any_nonhidserv(options)) {
|
||||||
int i, n_per_request;
|
/* If we wind up going to the authorities, we want to only open one
|
||||||
const char *req_plural = "", *rtr_plural = "";
|
* connection to each authority at a time, so that we don't overload
|
||||||
int pds_flags = PDS_RETRY_IF_NO_SERVERS;
|
* them. We do this by setting PDS_NO_EXISTING_SERVERDESC_FETCH
|
||||||
if (! authdir_mode_any_nonhidserv(options)) {
|
* regardless of whether we're a cache or not.
|
||||||
/* If we wind up going to the authorities, we want to only open one
|
*
|
||||||
* connection to each authority at a time, so that we don't overload
|
* Setting this flag can make initiate_descriptor_downloads() ignore
|
||||||
* them. We do this by setting PDS_NO_EXISTING_SERVERDESC_FETCH
|
* requests. We need to make sure that we do in fact call
|
||||||
* regardless of whether we're a cache or not; it gets ignored if we're
|
* update_router_descriptor_downloads() later on, once the connections
|
||||||
* not calling router_pick_trusteddirserver.
|
* have succeeded or failed.
|
||||||
*
|
*/
|
||||||
* Setting this flag can make initiate_descriptor_downloads() ignore
|
pds_flags |= fetch_microdesc ?
|
||||||
* requests. We need to make sure that we do in fact call
|
PDS_NO_EXISTING_MICRODESC_FETCH :
|
||||||
* update_router_descriptor_downloads() later on, once the connections
|
PDS_NO_EXISTING_SERVERDESC_FETCH;
|
||||||
* have succeeded or failed.
|
|
||||||
*/
|
|
||||||
pds_flags |= (purpose == DIR_PURPOSE_FETCH_MICRODESC) ?
|
|
||||||
PDS_NO_EXISTING_MICRODESC_FETCH :
|
|
||||||
PDS_NO_EXISTING_SERVERDESC_FETCH;
|
|
||||||
}
|
|
||||||
|
|
||||||
n_per_request = CEIL_DIV(n_downloadable, MIN_REQUESTS);
|
|
||||||
if (purpose == DIR_PURPOSE_FETCH_MICRODESC) {
|
|
||||||
if (n_per_request > MAX_MICRODESC_DL_PER_REQUEST)
|
|
||||||
n_per_request = MAX_MICRODESC_DL_PER_REQUEST;
|
|
||||||
} else {
|
|
||||||
if (n_per_request > MAX_DL_PER_REQUEST)
|
|
||||||
n_per_request = MAX_DL_PER_REQUEST;
|
|
||||||
}
|
|
||||||
if (n_per_request < MIN_DL_PER_REQUEST)
|
|
||||||
n_per_request = MIN_DL_PER_REQUEST;
|
|
||||||
|
|
||||||
if (n_downloadable > n_per_request)
|
|
||||||
req_plural = rtr_plural = "s";
|
|
||||||
else if (n_downloadable > 1)
|
|
||||||
rtr_plural = "s";
|
|
||||||
|
|
||||||
log_info(LD_DIR,
|
|
||||||
"Launching %d request%s for %d %s%s, %d at a time",
|
|
||||||
CEIL_DIV(n_downloadable, n_per_request), req_plural,
|
|
||||||
n_downloadable, descname, rtr_plural, n_per_request);
|
|
||||||
smartlist_sort_digests(downloadable);
|
|
||||||
for (i=0; i < n_downloadable; i += n_per_request) {
|
|
||||||
initiate_descriptor_downloads(source, purpose,
|
|
||||||
downloadable, i, i+n_per_request,
|
|
||||||
pds_flags);
|
|
||||||
}
|
|
||||||
last_descriptor_download_attempted = now;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
n_per_request = CEIL_DIV(n_downloadable, MIN_REQUESTS);
|
||||||
|
max_dl_per_req = max_dl_per_request(options, purpose);
|
||||||
|
|
||||||
|
if (n_per_request > max_dl_per_req)
|
||||||
|
n_per_request = max_dl_per_req;
|
||||||
|
|
||||||
|
if (n_per_request < MIN_DL_PER_REQUEST)
|
||||||
|
n_per_request = MIN_DL_PER_REQUEST;
|
||||||
|
|
||||||
|
if (n_downloadable > n_per_request)
|
||||||
|
req_plural = rtr_plural = "s";
|
||||||
|
else if (n_downloadable > 1)
|
||||||
|
rtr_plural = "s";
|
||||||
|
|
||||||
|
log_info(LD_DIR,
|
||||||
|
"Launching %d request%s for %d %s%s, %d at a time",
|
||||||
|
CEIL_DIV(n_downloadable, n_per_request), req_plural,
|
||||||
|
n_downloadable, descname, rtr_plural, n_per_request);
|
||||||
|
smartlist_sort_digests(downloadable);
|
||||||
|
for (i=0; i < n_downloadable; i += n_per_request) {
|
||||||
|
initiate_descriptor_downloads(source, purpose,
|
||||||
|
downloadable, i, i+n_per_request,
|
||||||
|
pds_flags);
|
||||||
|
}
|
||||||
|
last_descriptor_download_attempted = now;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** For any descriptor that we want that's currently listed in
|
/** For any descriptor that we want that's currently listed in
|
||||||
@ -4541,7 +4595,7 @@ update_extrainfo_downloads(time_t now)
|
|||||||
routerlist_t *rl;
|
routerlist_t *rl;
|
||||||
smartlist_t *wanted;
|
smartlist_t *wanted;
|
||||||
digestmap_t *pending;
|
digestmap_t *pending;
|
||||||
int old_routers, i;
|
int old_routers, i, max_dl_per_req;
|
||||||
int n_no_ei = 0, n_pending = 0, n_have = 0, n_delay = 0;
|
int n_no_ei = 0, n_pending = 0, n_have = 0, n_delay = 0;
|
||||||
if (! options->DownloadExtraInfo)
|
if (! options->DownloadExtraInfo)
|
||||||
return;
|
return;
|
||||||
@ -4597,9 +4651,11 @@ update_extrainfo_downloads(time_t now)
|
|||||||
n_no_ei, n_have, n_delay, n_pending, smartlist_len(wanted));
|
n_no_ei, n_have, n_delay, n_pending, smartlist_len(wanted));
|
||||||
|
|
||||||
smartlist_shuffle(wanted);
|
smartlist_shuffle(wanted);
|
||||||
for (i = 0; i < smartlist_len(wanted); i += MAX_DL_PER_REQUEST) {
|
|
||||||
|
max_dl_per_req = max_dl_per_request(options, DIR_PURPOSE_FETCH_EXTRAINFO);
|
||||||
|
for (i = 0; i < smartlist_len(wanted); i += max_dl_per_req) {
|
||||||
initiate_descriptor_downloads(NULL, DIR_PURPOSE_FETCH_EXTRAINFO,
|
initiate_descriptor_downloads(NULL, DIR_PURPOSE_FETCH_EXTRAINFO,
|
||||||
wanted, i, i + MAX_DL_PER_REQUEST,
|
wanted, i, i+max_dl_per_req,
|
||||||
PDS_RETRY_IF_NO_SERVERS|PDS_NO_EXISTING_SERVERDESC_FETCH);
|
PDS_RETRY_IF_NO_SERVERS|PDS_NO_EXISTING_SERVERDESC_FETCH);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -229,6 +229,10 @@ MOCK_DECL(int, router_descriptor_is_older_than, (const routerinfo_t *router,
|
|||||||
MOCK_DECL(STATIC was_router_added_t, extrainfo_insert,
|
MOCK_DECL(STATIC was_router_added_t, extrainfo_insert,
|
||||||
(routerlist_t *rl, extrainfo_t *ei, int warn_if_incompatible));
|
(routerlist_t *rl, extrainfo_t *ei, int warn_if_incompatible));
|
||||||
|
|
||||||
|
MOCK_DECL(STATIC void, initiate_descriptor_downloads,
|
||||||
|
(const routerstatus_t *source, int purpose, smartlist_t *digests,
|
||||||
|
int lo, int hi, int pds_flags));
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -17,44 +17,45 @@ src_test_AM_CPPFLAGS = -DSHARE_DATADIR="\"$(datadir)\"" \
|
|||||||
|
|
||||||
src_test_test_SOURCES = \
|
src_test_test_SOURCES = \
|
||||||
src/test/test.c \
|
src/test/test.c \
|
||||||
|
src/test/test_accounting.c \
|
||||||
src/test/test_addr.c \
|
src/test/test_addr.c \
|
||||||
src/test/test_buffers.c \
|
src/test/test_buffers.c \
|
||||||
src/test/test_cell_formats.c \
|
src/test/test_cell_formats.c \
|
||||||
|
src/test/test_cell_queue.c \
|
||||||
src/test/test_channel.c \
|
src/test/test_channel.c \
|
||||||
src/test/test_channeltls.c \
|
src/test/test_channeltls.c \
|
||||||
|
src/test/test_checkdir.c \
|
||||||
src/test/test_circuitlist.c \
|
src/test/test_circuitlist.c \
|
||||||
src/test/test_circuitmux.c \
|
src/test/test_circuitmux.c \
|
||||||
|
src/test/test_config.c \
|
||||||
src/test/test_containers.c \
|
src/test/test_containers.c \
|
||||||
src/test/test_controller_events.c \
|
src/test/test_controller_events.c \
|
||||||
src/test/test_crypto.c \
|
src/test/test_crypto.c \
|
||||||
src/test/test_cell_queue.c \
|
|
||||||
src/test/test_data.c \
|
src/test/test_data.c \
|
||||||
src/test/test_dir.c \
|
src/test/test_dir.c \
|
||||||
src/test/test_checkdir.c \
|
|
||||||
src/test/test_entryconn.c \
|
src/test/test_entryconn.c \
|
||||||
src/test/test_entrynodes.c \
|
src/test/test_entrynodes.c \
|
||||||
src/test/test_extorport.c \
|
src/test/test_extorport.c \
|
||||||
|
src/test/test_hs.c \
|
||||||
src/test/test_introduce.c \
|
src/test/test_introduce.c \
|
||||||
src/test/test_logging.c \
|
src/test/test_logging.c \
|
||||||
src/test/test_microdesc.c \
|
src/test/test_microdesc.c \
|
||||||
|
src/test/test_nodelist.c \
|
||||||
src/test/test_oom.c \
|
src/test/test_oom.c \
|
||||||
src/test/test_accounting.c \
|
|
||||||
src/test/test_options.c \
|
src/test/test_options.c \
|
||||||
|
src/test/test_policy.c \
|
||||||
src/test/test_pt.c \
|
src/test/test_pt.c \
|
||||||
src/test/test_relaycell.c \
|
|
||||||
src/test/test_relay.c \
|
src/test/test_relay.c \
|
||||||
|
src/test/test_relaycell.c \
|
||||||
src/test/test_replay.c \
|
src/test/test_replay.c \
|
||||||
src/test/test_routerkeys.c \
|
src/test/test_routerkeys.c \
|
||||||
|
src/test/test_routerlist.c \
|
||||||
|
src/test/test_routerset.c \
|
||||||
src/test/test_scheduler.c \
|
src/test/test_scheduler.c \
|
||||||
src/test/test_socks.c \
|
src/test/test_socks.c \
|
||||||
|
src/test/test_status.c \
|
||||||
src/test/test_threads.c \
|
src/test/test_threads.c \
|
||||||
src/test/test_util.c \
|
src/test/test_util.c \
|
||||||
src/test/test_config.c \
|
|
||||||
src/test/test_hs.c \
|
|
||||||
src/test/test_nodelist.c \
|
|
||||||
src/test/test_policy.c \
|
|
||||||
src/test/test_status.c \
|
|
||||||
src/test/test_routerset.c \
|
|
||||||
src/ext/tinytest.c
|
src/ext/tinytest.c
|
||||||
|
|
||||||
src_test_test_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS)
|
src_test_test_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS)
|
||||||
|
128
src/test/test.c
128
src/test/test.c
@ -1294,84 +1294,86 @@ static struct testcase_t test_array[] = {
|
|||||||
END_OF_TESTCASES
|
END_OF_TESTCASES
|
||||||
};
|
};
|
||||||
|
|
||||||
|
extern struct testcase_t accounting_tests[];
|
||||||
extern struct testcase_t addr_tests[];
|
extern struct testcase_t addr_tests[];
|
||||||
extern struct testcase_t buffer_tests[];
|
extern struct testcase_t buffer_tests[];
|
||||||
extern struct testcase_t crypto_tests[];
|
|
||||||
extern struct testcase_t container_tests[];
|
|
||||||
extern struct testcase_t util_tests[];
|
|
||||||
extern struct testcase_t dir_tests[];
|
|
||||||
extern struct testcase_t checkdir_tests[];
|
|
||||||
extern struct testcase_t microdesc_tests[];
|
|
||||||
extern struct testcase_t pt_tests[];
|
|
||||||
extern struct testcase_t config_tests[];
|
|
||||||
extern struct testcase_t introduce_tests[];
|
|
||||||
extern struct testcase_t replaycache_tests[];
|
|
||||||
extern struct testcase_t relaycell_tests[];
|
|
||||||
extern struct testcase_t cell_format_tests[];
|
extern struct testcase_t cell_format_tests[];
|
||||||
extern struct testcase_t circuitlist_tests[];
|
|
||||||
extern struct testcase_t circuitmux_tests[];
|
|
||||||
extern struct testcase_t cell_queue_tests[];
|
extern struct testcase_t cell_queue_tests[];
|
||||||
extern struct testcase_t options_tests[];
|
|
||||||
extern struct testcase_t socks_tests[];
|
|
||||||
extern struct testcase_t entrynodes_tests[];
|
|
||||||
extern struct testcase_t thread_tests[];
|
|
||||||
extern struct testcase_t extorport_tests[];
|
|
||||||
extern struct testcase_t controller_event_tests[];
|
|
||||||
extern struct testcase_t logging_tests[];
|
|
||||||
extern struct testcase_t hs_tests[];
|
|
||||||
extern struct testcase_t nodelist_tests[];
|
|
||||||
extern struct testcase_t routerkeys_tests[];
|
|
||||||
extern struct testcase_t oom_tests[];
|
|
||||||
extern struct testcase_t accounting_tests[];
|
|
||||||
extern struct testcase_t policy_tests[];
|
|
||||||
extern struct testcase_t status_tests[];
|
|
||||||
extern struct testcase_t routerset_tests[];
|
|
||||||
extern struct testcase_t router_tests[];
|
|
||||||
extern struct testcase_t channel_tests[];
|
extern struct testcase_t channel_tests[];
|
||||||
extern struct testcase_t channeltls_tests[];
|
extern struct testcase_t channeltls_tests[];
|
||||||
extern struct testcase_t relay_tests[];
|
extern struct testcase_t checkdir_tests[];
|
||||||
extern struct testcase_t scheduler_tests[];
|
extern struct testcase_t circuitlist_tests[];
|
||||||
|
extern struct testcase_t circuitmux_tests[];
|
||||||
|
extern struct testcase_t config_tests[];
|
||||||
|
extern struct testcase_t container_tests[];
|
||||||
|
extern struct testcase_t controller_event_tests[];
|
||||||
|
extern struct testcase_t crypto_tests[];
|
||||||
|
extern struct testcase_t dir_tests[];
|
||||||
extern struct testcase_t entryconn_tests[];
|
extern struct testcase_t entryconn_tests[];
|
||||||
|
extern struct testcase_t entrynodes_tests[];
|
||||||
|
extern struct testcase_t extorport_tests[];
|
||||||
|
extern struct testcase_t hs_tests[];
|
||||||
|
extern struct testcase_t introduce_tests[];
|
||||||
|
extern struct testcase_t logging_tests[];
|
||||||
|
extern struct testcase_t microdesc_tests[];
|
||||||
|
extern struct testcase_t nodelist_tests[];
|
||||||
|
extern struct testcase_t oom_tests[];
|
||||||
|
extern struct testcase_t options_tests[];
|
||||||
|
extern struct testcase_t policy_tests[];
|
||||||
|
extern struct testcase_t pt_tests[];
|
||||||
|
extern struct testcase_t relay_tests[];
|
||||||
|
extern struct testcase_t relaycell_tests[];
|
||||||
|
extern struct testcase_t replaycache_tests[];
|
||||||
|
extern struct testcase_t router_tests[];
|
||||||
|
extern struct testcase_t routerkeys_tests[];
|
||||||
|
extern struct testcase_t routerlist_tests[];
|
||||||
|
extern struct testcase_t routerset_tests[];
|
||||||
|
extern struct testcase_t scheduler_tests[];
|
||||||
|
extern struct testcase_t socks_tests[];
|
||||||
|
extern struct testcase_t status_tests[];
|
||||||
|
extern struct testcase_t thread_tests[];
|
||||||
|
extern struct testcase_t util_tests[];
|
||||||
|
|
||||||
static struct testgroup_t testgroups[] = {
|
static struct testgroup_t testgroups[] = {
|
||||||
{ "", test_array },
|
{ "", test_array },
|
||||||
{ "buffer/", buffer_tests },
|
{ "accounting/", accounting_tests },
|
||||||
{ "socks/", socks_tests },
|
|
||||||
{ "addr/", addr_tests },
|
{ "addr/", addr_tests },
|
||||||
{ "crypto/", crypto_tests },
|
{ "buffer/", buffer_tests },
|
||||||
|
{ "cellfmt/", cell_format_tests },
|
||||||
|
{ "cellqueue/", cell_queue_tests },
|
||||||
|
{ "channel/", channel_tests },
|
||||||
|
{ "channeltls/", channeltls_tests },
|
||||||
|
{ "checkdir/", checkdir_tests },
|
||||||
|
{ "circuitlist/", circuitlist_tests },
|
||||||
|
{ "circuitmux/", circuitmux_tests },
|
||||||
|
{ "config/", config_tests },
|
||||||
{ "container/", container_tests },
|
{ "container/", container_tests },
|
||||||
|
{ "control/", controller_event_tests },
|
||||||
|
{ "crypto/", crypto_tests },
|
||||||
|
{ "dir/", dir_tests },
|
||||||
|
{ "dir/md/", microdesc_tests },
|
||||||
|
{ "entryconn/", entryconn_tests },
|
||||||
|
{ "entrynodes/", entrynodes_tests },
|
||||||
|
{ "extorport/", extorport_tests },
|
||||||
|
{ "hs/", hs_tests },
|
||||||
|
{ "introduce/", introduce_tests },
|
||||||
|
{ "nodelist/", nodelist_tests },
|
||||||
|
{ "oom/", oom_tests },
|
||||||
|
{ "options/", options_tests },
|
||||||
|
{ "policy/" , policy_tests },
|
||||||
|
{ "pt/", pt_tests },
|
||||||
|
{ "relay/" , relay_tests },
|
||||||
|
{ "relaycell/", relaycell_tests },
|
||||||
|
{ "replaycache/", replaycache_tests },
|
||||||
|
{ "routerkeys/", routerkeys_tests },
|
||||||
|
{ "routerlist/", routerlist_tests },
|
||||||
|
{ "routerset/" , routerset_tests },
|
||||||
|
{ "scheduler/", scheduler_tests },
|
||||||
|
{ "socks/", socks_tests },
|
||||||
|
{ "status/" , status_tests },
|
||||||
{ "util/", util_tests },
|
{ "util/", util_tests },
|
||||||
{ "util/logging/", logging_tests },
|
{ "util/logging/", logging_tests },
|
||||||
{ "util/thread/", thread_tests },
|
{ "util/thread/", thread_tests },
|
||||||
{ "cellfmt/", cell_format_tests },
|
|
||||||
{ "cellqueue/", cell_queue_tests },
|
|
||||||
{ "dir/", dir_tests },
|
|
||||||
{ "checkdir/", checkdir_tests },
|
|
||||||
{ "dir/md/", microdesc_tests },
|
|
||||||
{ "pt/", pt_tests },
|
|
||||||
{ "config/", config_tests },
|
|
||||||
{ "replaycache/", replaycache_tests },
|
|
||||||
{ "relaycell/", relaycell_tests },
|
|
||||||
{ "introduce/", introduce_tests },
|
|
||||||
{ "circuitlist/", circuitlist_tests },
|
|
||||||
{ "circuitmux/", circuitmux_tests },
|
|
||||||
{ "options/", options_tests },
|
|
||||||
{ "entrynodes/", entrynodes_tests },
|
|
||||||
{ "entryconn/", entryconn_tests },
|
|
||||||
{ "extorport/", extorport_tests },
|
|
||||||
{ "control/", controller_event_tests },
|
|
||||||
{ "hs/", hs_tests },
|
|
||||||
{ "nodelist/", nodelist_tests },
|
|
||||||
{ "routerkeys/", routerkeys_tests },
|
|
||||||
{ "oom/", oom_tests },
|
|
||||||
{ "accounting/", accounting_tests },
|
|
||||||
{ "policy/" , policy_tests },
|
|
||||||
{ "status/" , status_tests },
|
|
||||||
{ "routerset/" , routerset_tests },
|
|
||||||
{ "channel/", channel_tests },
|
|
||||||
{ "channeltls/", channeltls_tests },
|
|
||||||
{ "relay/" , relay_tests },
|
|
||||||
{ "scheduler/", scheduler_tests },
|
|
||||||
END_OF_GROUPS
|
END_OF_GROUPS
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2930,6 +2930,30 @@ test_dir_http_handling(void *args)
|
|||||||
tor_free(url);
|
tor_free(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_dir_purpose_needs_anonymity(void *arg)
|
||||||
|
{
|
||||||
|
(void)arg;
|
||||||
|
tt_int_op(1, ==, purpose_needs_anonymity(0, ROUTER_PURPOSE_BRIDGE));
|
||||||
|
tt_int_op(1, ==, purpose_needs_anonymity(0, ROUTER_PURPOSE_GENERAL));
|
||||||
|
tt_int_op(0, ==, purpose_needs_anonymity(DIR_PURPOSE_FETCH_MICRODESC,
|
||||||
|
ROUTER_PURPOSE_GENERAL));
|
||||||
|
done: ;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_dir_fetch_type(void *arg)
|
||||||
|
{
|
||||||
|
(void)arg;
|
||||||
|
tt_assert(dir_fetch_type(DIR_PURPOSE_FETCH_MICRODESC, ROUTER_PURPOSE_GENERAL,
|
||||||
|
NULL) == MICRODESC_DIRINFO);
|
||||||
|
tt_assert(dir_fetch_type(DIR_PURPOSE_FETCH_SERVERDESC, ROUTER_PURPOSE_BRIDGE,
|
||||||
|
NULL) == BRIDGE_DIRINFO);
|
||||||
|
tt_assert(dir_fetch_type(DIR_PURPOSE_FETCH_CONSENSUS, ROUTER_PURPOSE_GENERAL,
|
||||||
|
"microdesc") == (V3_DIRINFO | MICRODESC_DIRINFO));
|
||||||
|
done: ;
|
||||||
|
}
|
||||||
|
|
||||||
#define DIR_LEGACY(name) \
|
#define DIR_LEGACY(name) \
|
||||||
{ #name, test_dir_ ## name , TT_FORK, NULL, NULL }
|
{ #name, test_dir_ ## name , TT_FORK, NULL, NULL }
|
||||||
|
|
||||||
@ -2957,6 +2981,8 @@ struct testcase_t dir_tests[] = {
|
|||||||
DIR_LEGACY(clip_unmeasured_bw_kb_alt),
|
DIR_LEGACY(clip_unmeasured_bw_kb_alt),
|
||||||
DIR(fmt_control_ns, 0),
|
DIR(fmt_control_ns, 0),
|
||||||
DIR(http_handling, 0),
|
DIR(http_handling, 0),
|
||||||
|
DIR(purpose_needs_anonymity, 0),
|
||||||
|
DIR(fetch_type, 0),
|
||||||
END_OF_TESTCASES
|
END_OF_TESTCASES
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
#include "nodelist.h"
|
#include "nodelist.h"
|
||||||
#include "test.h"
|
#include "test.h"
|
||||||
|
|
||||||
/** Tese the case when node_get_by_id() returns NULL,
|
/** Test the case when node_get_by_id() returns NULL,
|
||||||
* node_get_verbose_nickname_by_id should return the base 16 encoding
|
* node_get_verbose_nickname_by_id should return the base 16 encoding
|
||||||
* of the id.
|
* of the id.
|
||||||
*/
|
*/
|
||||||
|
103
src/test/test_routerlist.c
Normal file
103
src/test/test_routerlist.c
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
/* Copyright (c) 2014, The Tor Project, Inc. */
|
||||||
|
/* See LICENSE for licensing information */
|
||||||
|
|
||||||
|
#define ROUTERLIST_PRIVATE
|
||||||
|
#include "or.h"
|
||||||
|
#include "routerlist.h"
|
||||||
|
#include "directory.h"
|
||||||
|
#include "test.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* 4 digests + 3 sep + pre + post + NULL */
|
||||||
|
static char output[4*BASE64_DIGEST256_LEN+3+2+2+1];
|
||||||
|
|
||||||
|
static void
|
||||||
|
mock_get_from_dirserver(uint8_t dir_purpose, uint8_t router_purpose,
|
||||||
|
const char *resource, int pds_flags)
|
||||||
|
{
|
||||||
|
(void)dir_purpose;
|
||||||
|
(void)router_purpose;
|
||||||
|
(void)pds_flags;
|
||||||
|
tt_assert(resource);
|
||||||
|
strlcpy(output, resource, sizeof(output));
|
||||||
|
done:
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_routerlist_initiate_descriptor_downloads(void *arg)
|
||||||
|
{
|
||||||
|
const char *prose = "unhurried and wise, we perceive.";
|
||||||
|
smartlist_t *digests = smartlist_new();
|
||||||
|
(void)arg;
|
||||||
|
|
||||||
|
for (int i = 0; i < 20; i++) {
|
||||||
|
smartlist_add(digests, (char*)prose);
|
||||||
|
}
|
||||||
|
|
||||||
|
MOCK(directory_get_from_dirserver, mock_get_from_dirserver);
|
||||||
|
initiate_descriptor_downloads(NULL, DIR_PURPOSE_FETCH_MICRODESC,
|
||||||
|
digests, 3, 7, 0);
|
||||||
|
UNMOCK(directory_get_from_dirserver);
|
||||||
|
|
||||||
|
tt_str_op(output, OP_EQ, "d/"
|
||||||
|
"dW5odXJyaWVkIGFuZCB3aXNlLCB3ZSBwZXJjZWl2ZS4-"
|
||||||
|
"dW5odXJyaWVkIGFuZCB3aXNlLCB3ZSBwZXJjZWl2ZS4-"
|
||||||
|
"dW5odXJyaWVkIGFuZCB3aXNlLCB3ZSBwZXJjZWl2ZS4-"
|
||||||
|
"dW5odXJyaWVkIGFuZCB3aXNlLCB3ZSBwZXJjZWl2ZS4"
|
||||||
|
".z");
|
||||||
|
|
||||||
|
done:
|
||||||
|
smartlist_free(digests);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int count = 0;
|
||||||
|
|
||||||
|
static void
|
||||||
|
mock_initiate_descriptor_downloads(const routerstatus_t *source,
|
||||||
|
int purpose, smartlist_t *digests,
|
||||||
|
int lo, int hi, int pds_flags)
|
||||||
|
{
|
||||||
|
(void)source;
|
||||||
|
(void)purpose;
|
||||||
|
(void)digests;
|
||||||
|
(void)pds_flags;
|
||||||
|
(void)hi;
|
||||||
|
(void)lo;
|
||||||
|
count += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_routerlist_launch_descriptor_downloads(void *arg)
|
||||||
|
{
|
||||||
|
smartlist_t *downloadable = smartlist_new();
|
||||||
|
time_t now = time(NULL);
|
||||||
|
char *cp;
|
||||||
|
(void)arg;
|
||||||
|
|
||||||
|
for (int i = 0; i < 100; i++) {
|
||||||
|
cp = tor_malloc(DIGEST256_LEN);
|
||||||
|
tt_assert(cp);
|
||||||
|
crypto_rand(cp, DIGEST256_LEN);
|
||||||
|
smartlist_add(downloadable, cp);
|
||||||
|
}
|
||||||
|
|
||||||
|
MOCK(initiate_descriptor_downloads, mock_initiate_descriptor_downloads);
|
||||||
|
launch_descriptor_downloads(DIR_PURPOSE_FETCH_MICRODESC, downloadable,
|
||||||
|
NULL, now);
|
||||||
|
tt_int_op(3, ==, count);
|
||||||
|
UNMOCK(initiate_descriptor_downloads);
|
||||||
|
|
||||||
|
done:
|
||||||
|
SMARTLIST_FOREACH(downloadable, char *, cp1, tor_free(cp1));
|
||||||
|
smartlist_free(downloadable);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define NODE(name, flags) \
|
||||||
|
{ #name, test_routerlist_##name, (flags), NULL, NULL }
|
||||||
|
|
||||||
|
struct testcase_t routerlist_tests[] = {
|
||||||
|
NODE(initiate_descriptor_downloads, 0),
|
||||||
|
NODE(launch_descriptor_downloads, 0),
|
||||||
|
END_OF_TESTCASES
|
||||||
|
};
|
Loading…
Reference in New Issue
Block a user