From bd959adcb7d7c671e0f36986d4996d5b3bc298e6 Mon Sep 17 00:00:00 2001 From: Roger Dingledine Date: Sun, 17 Feb 2008 16:47:47 +0000 Subject: patch from karsten: Resolved problems with (re-)fetching hidden service descriptors. Before, v0 descriptors were not fetched at all (fix on 0.2.0.18-alpha), re-fetching of v2 descriptors did not stop when a v0 descriptor was received (fix on 0.2.0.18-alpha), and re-fetching of v2 descriptors did not work in all cases (fix on 0.2.0.19-alpha). svn:r13540 --- src/or/connection.c | 8 ++++++-- src/or/directory.c | 2 ++ src/or/or.h | 6 +++++- src/or/rendclient.c | 11 +++++++++-- 4 files changed, 22 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/or/connection.c b/src/or/connection.c index 738cdaa9e9..0041a35cba 100644 --- a/src/or/connection.c +++ b/src/or/connection.c @@ -2436,11 +2436,13 @@ connection_get_by_type_state(int type, int state) /** Return a connection of type type that has rendquery equal * to rendquery, and that is not marked for close. If state - * is non-zero, conn must be of that state too. + * is non-zero, conn must be of that state too. If rendversion is + * nonnegative, conn must fetch that rendversion, too. */ connection_t * connection_get_by_type_state_rendquery(int type, int state, - const char *rendquery) + const char *rendquery, + int rendversion) { smartlist_t *conns = get_connection_array(); @@ -2453,6 +2455,8 @@ connection_get_by_type_state_rendquery(int type, int state, !conn->marked_for_close && (!state || state == conn->state)) { if (type == CONN_TYPE_DIR && + (rendversion < 0 || + rendversion == TO_DIR_CONN(conn)->rend_version) && !rend_cmp_service_ids(rendquery, TO_DIR_CONN(conn)->rend_query)) return conn; else if (CONN_IS_EDGE(conn) && diff --git a/src/or/directory.c b/src/or/directory.c index 51fc75a29b..7a5990105e 100644 --- a/src/or/directory.c +++ b/src/or/directory.c @@ -880,6 +880,7 @@ directory_send_command(dir_connection_t *conn, tor_assert(strlen(resource) <= REND_SERVICE_ID_LEN_BASE32); /* This breaks the function abstraction. */ strlcpy(conn->rend_query, resource, sizeof(conn->rend_query)); + conn->rend_version = 0; httpcommand = "GET"; /* Request the most recent versioned descriptor. */ @@ -894,6 +895,7 @@ directory_send_command(dir_connection_t *conn, tor_assert(strlen(resource) <= REND_DESC_ID_V2_LEN_BASE32); /* Remember the query to refer to it when a response arrives. */ strlcpy(conn->rend_query, payload, sizeof(conn->rend_query)); + conn->rend_version = 2; payload = NULL; httpcommand = "GET"; len = strlen(resource) + 32; diff --git a/src/or/or.h b/src/or/or.h index 3cd7fd7d53..28c7bfdbd3 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -1053,6 +1053,9 @@ typedef struct dir_connection_t { /** The zlib object doing on-the-fly compression for spooled data. */ tor_zlib_state_t *zlib_state; + /** What hidden service descriptor are we fetching, if any? */ + int rend_version; + /** What rendezvous service are we querying for? */ char rend_query[REND_SERVICE_ID_LEN_BASE32+1]; @@ -2751,7 +2754,8 @@ connection_t *connection_get_by_type_addr_port_purpose(int type, uint32_t addr, uint16_t port, int purpose); connection_t *connection_get_by_type_state(int type, int state); connection_t *connection_get_by_type_state_rendquery(int type, int state, - const char *rendquery); + const char *rendquery, + int rendversion); #define connection_speaks_cells(conn) ((conn)->type == CONN_TYPE_OR) int connection_is_listener(connection_t *conn); diff --git a/src/or/rendclient.c b/src/or/rendclient.c index b30be2310e..6e92ef50b0 100644 --- a/src/or/rendclient.c +++ b/src/or/rendclient.c @@ -401,7 +401,7 @@ rend_client_refetch_renddesc(const char *query) return; log_info(LD_REND, "Fetching rendezvous descriptor for service %s", escaped_safe_str(query)); - if (connection_get_by_type_state_rendquery(CONN_TYPE_DIR, 0, query)) { + if (connection_get_by_type_state_rendquery(CONN_TYPE_DIR, 0, query, 0)) { log_info(LD_REND,"Would fetch a new renddesc here (for %s), but one is " "already in progress.", escaped_safe_str(query)); } else { @@ -421,6 +421,7 @@ rend_client_refetch_v2_renddesc(const char *query) char descriptor_id[DIGEST_LEN]; int replicas_left_to_try[REND_NUMBER_OF_NON_CONSECUTIVE_REPLICAS]; int i, tries_left; + rend_cache_entry_t *e = NULL; tor_assert(query); tor_assert(strlen(query) == REND_SERVICE_ID_LEN_BASE32); /* Are we configured to fetch descriptors? */ @@ -429,6 +430,12 @@ rend_client_refetch_v2_renddesc(const char *query) "service descriptor, but are not fetching service descriptors."); return; } + /* Before fetching, check if we already have the descriptor here. */ + if (rend_cache_lookup_entry(query, -1, &e) > 0) { + log_info(LD_REND, "We would fetch a v2 rendezvous descriptor, but we " + "already have that descriptor here. Not fetching."); + return; + } log_debug(LD_REND, "Fetching v2 rendezvous descriptor for service %s", safe_str(query)); /* Randomly iterate over the replicas until a descriptor can be fetched @@ -506,7 +513,7 @@ rend_client_remove_intro_point(extend_info_t *failed_intro, const char *query) /* move all pending streams back to renddesc_wait */ while ((conn = connection_get_by_type_state_rendquery(CONN_TYPE_AP, - AP_CONN_STATE_CIRCUIT_WAIT, query))) { + AP_CONN_STATE_CIRCUIT_WAIT, query, -1))) { conn->state = AP_CONN_STATE_RENDDESC_WAIT; } -- cgit v1.2.3-54-g00ecf