aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/or/config.c1
-rw-r--r--src/or/or.h2
-rw-r--r--src/or/rendmid.c16
-rw-r--r--src/or/rendservice.c184
4 files changed, 155 insertions, 48 deletions
diff --git a/src/or/config.c b/src/or/config.c
index d2981771c..443ebcac8 100644
--- a/src/or/config.c
+++ b/src/or/config.c
@@ -348,6 +348,7 @@ static config_var_t option_vars_[] = {
V(PerConnBWBurst, MEMUNIT, "0"),
V(PerConnBWRate, MEMUNIT, "0"),
V(PidFile, STRING, NULL),
+ V(IntroPointAcceptMutipleConnections, BOOL, "0"),
V(TestingTorNetwork, BOOL, "0"),
V(TestingMinExitFlagThreshold, MEMUNIT, "0"),
V(TestingMinFastFlagThreshold, MEMUNIT, "0"),
diff --git a/src/or/or.h b/src/or/or.h
index c47ae23ed..14097da6e 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -4020,6 +4020,8 @@ typedef struct {
* of certain configuration options. */
int TestingTorNetwork;
+ int IntroPointAcceptMutipleConnections;
+
/** Minimum value for the Exit flag threshold on testing networks. */
uint64_t TestingMinExitFlagThreshold;
diff --git a/src/or/rendmid.c b/src/or/rendmid.c
index 1bd11f6dc..8741397fc 100644
--- a/src/or/rendmid.c
+++ b/src/or/rendmid.c
@@ -92,13 +92,15 @@ rend_mid_establish_intro(or_circuit_t *circ, const uint8_t *request,
base32_encode(serviceid, REND_SERVICE_ID_LEN_BASE32+1,
pk_digest, REND_SERVICE_ID_LEN);
- /* Close any other intro circuits with the same pk. */
- c = NULL;
- while ((c = circuit_get_intro_point(pk_digest))) {
- log_info(LD_REND, "Replacing old circuit for service %s",
- safe_str(serviceid));
- circuit_mark_for_close(TO_CIRCUIT(c), END_CIRC_REASON_FINISHED);
- /* Now it's marked, and it won't be returned next time. */
+ if (!get_options()->IntroPointAcceptMutipleConnections) {
+ /* Close any other intro circuits with the same pk. */
+ c = NULL;
+ while ((c = circuit_get_intro_point(pk_digest))) {
+ log_info(LD_REND, "Replacing old circuit for service %s",
+ safe_str(serviceid));
+ circuit_mark_for_close(TO_CIRCUIT(c), END_CIRC_REASON_FINISHED);
+ /* Now it's marked, and it won't be returned next time. */
+ }
}
/* Acknowledge the request. */
diff --git a/src/or/rendservice.c b/src/or/rendservice.c
index 500efaf20..89b12a35c 100644
--- a/src/or/rendservice.c
+++ b/src/or/rendservice.c
@@ -14,6 +14,7 @@
#include "circuitbuild.h"
#include "circuitlist.h"
#include "circuituse.h"
+#include "connection.h"
#include "config.h"
#include "directory.h"
#include "networkstatus.h"
@@ -106,6 +107,8 @@ typedef struct rend_service_t {
char service_id[REND_SERVICE_ID_LEN_BASE32+1]; /**< Onion address without
* '.onion' */
char pk_digest[DIGEST_LEN]; /**< Hash of permanent hidden-service key. */
+ time_t descriptor_fetch_time; /**< The last time the service descriptor was
+ * fetched, 0 if it has not been */
smartlist_t *intro_nodes; /**< List of rend_intro_point_t's we have,
* or are trying to establish. */
time_t intro_period_started; /**< Start of the current period to build
@@ -3126,47 +3129,146 @@ rend_services_introduce(void)
* to. XXXX This is daft. */
prev_intro_nodes = smartlist_len(service->intro_nodes);
- /* We have enough directory information to start establishing our
- * intro points. We want to end up with n_intro_points_wanted
- * intro points, but if we're just starting, we launch two extra
- * circuits and use the first n_intro_points_wanted that complete.
- *
- * The ones after the first three will be converted to 'general'
- * internal circuits in rend_service_intro_has_opened(), and then
- * we'll drop them from the list of intro points next time we
- * go through the above "find out which introduction points we have
- * in progress" loop. */
- n_intro_points_to_open = (service->n_intro_points_wanted +
- (prev_intro_nodes == 0 ? 2 : 0));
- for (j = (int)n_intro_points_unexpired;
- j < (int)n_intro_points_to_open;
- ++j) { /* XXXX remove casts */
- router_crn_flags_t flags = CRN_NEED_UPTIME|CRN_NEED_DESC;
- if (get_options()->AllowInvalid_ & ALLOW_INVALID_INTRODUCTION)
- flags |= CRN_ALLOW_INVALID;
- node = router_choose_random_node(intro_nodes,
- options->ExcludeNodes, flags);
- if (!node) {
- log_warn(LD_REND,
- "Could only establish %d introduction points for %s; "
- "wanted %u.",
- smartlist_len(service->intro_nodes), service->service_id,
- n_intro_points_to_open);
- break;
- }
- intro_point_set_changed = 1;
- smartlist_add(intro_nodes, (void*)node);
- intro = tor_malloc_zero(sizeof(rend_intro_point_t));
- intro->extend_info = extend_info_from_node(node, 0);
- intro->intro_key = crypto_pk_new();
- tor_assert(!crypto_pk_generate_key(intro->intro_key));
- intro->time_published = -1;
- intro->time_to_expire = -1;
- intro->time_expiring = -1;
- smartlist_add(service->intro_nodes, intro);
- log_info(LD_REND, "Picked router %s as an intro point for %s.",
- safe_str_client(node_describe(node)),
- safe_str_client(service->service_id));
+ log_info(LD_REND, "Checking for existing descriptor");
+ log_info(LD_REND, "pk_digest %s", safe_str_client(service->service_id));
+
+ rend_cache_entry_t *entry;
+ int descriptor_available = (rend_cache_lookup_entry(service->service_id, -1, &entry) == 1);
+
+ if (descriptor_available) {
+ // Need to think about connecting to these introduction points now
+ log_info(LD_REND, "Descriptor available for %s", safe_str_client(service->service_id));
+
+ SMARTLIST_FOREACH(entry->parsed->intro_nodes, rend_intro_point_t *, intro, {
+ log_info(LD_REND, "Found router %s as an existing intro point for %s.",
+ safe_str_client(node_describe(node)),
+ safe_str_client(service->service_id));
+
+ int existing = 0;
+
+ SMARTLIST_FOREACH(service->intro_nodes, rend_intro_point_t *, existing_intro, {
+ // Unsure if this is the correct way to check
+ if (strcasecmp(existing_intro->extend_info->identity_digest, intro->extend_info->identity_digest) == 0) {
+ existing = 1;
+ // break, unsure if works
+ }
+ });
+
+ if (existing == 0) {
+ log_info(LD_REND, "Also connecting to %s.",
+ safe_str_client(node_describe(node)));
+
+ rend_intro_point_t *new_intro = tor_malloc_zero(sizeof(rend_intro_point_t));
+ memcpy((void*) new_intro, intro, sizeof(rend_intro_point_t));
+
+ intro->intro_key = crypto_pk_new();
+ tor_assert(!crypto_pk_generate_key(intro->intro_key));
+ intro->time_published = -1;
+ intro->time_to_expire = -1;
+ intro->time_expiring = -1;
+
+ smartlist_add(service->intro_nodes, intro);
+
+ intro_point_set_changed = 1;
+ } else {
+ log_info(LD_REND, "Already connected to %s, ignoring.",
+ safe_str_client(node_describe(node)));
+ }
+ });
+
+ log_info(LD_REND, "Finished checking introduction points for %s", safe_str_client(service->service_id));
+ } else {
+ // If the descriptor has not been fetched recently
+ if (now > service->descriptor_fetch_time+(60*5)) {
+ // Example from rendclient.c:168
+
+ log_info(LD_REND,
+ "query %s didn't have valid rend desc in cache. "
+ "Fetching descriptor.",
+ safe_str_client(service->service_id));
+
+ rend_data_t *rend_data = tor_malloc_zero(sizeof(rend_data_t)); // remember to free
+
+ strlcpy(rend_data->onion_address, service->service_id,
+ sizeof(rend_data->onion_address));
+
+ memcpy((void*) &rend_data->auth_type,
+ (void*) &service->auth_type,
+ sizeof(rend_auth_type_t));
+
+ rend_client_refetch_v2_renddesc(rend_data);
+
+ service->descriptor_fetch_time = now;
+
+ { // TODO: Unsure what this does?
+ connection_t *conn;
+
+ while ((conn = connection_get_by_type_state_rendquery(CONN_TYPE_AP,
+ AP_CONN_STATE_CIRCUIT_WAIT, // Waiting for a circuit
+ rend_data->onion_address))) {
+ conn->state = AP_CONN_STATE_RENDDESC_WAIT; // Change state to waiting to receive the descriptor
+ }
+ }
+ } else { // Descriptor has been recently fetched
+ if (now > service->descriptor_fetch_time+30) {
+ // Forget about trying to get the descriptor
+
+ log_info(LD_REND,
+ "query %s didn't have valid rend desc in cache. "
+ "Connecting to random introduction points",
+ safe_str_client(service->service_id));
+
+ /* We have enough directory information to start establishing our
+ * intro points. We want to end up with n_intro_points_wanted
+ * intro points, but if we're just starting, we launch two extra
+ * circuits and use the first n_intro_points_wanted that complete.
+ *
+ * The ones after the first three will be converted to 'general'
+ * internal circuits in rend_service_intro_has_opened(), and then
+ * we'll drop them from the list of intro points next time we
+ * go through the above "find out which introduction points we have
+ * in progress" loop. */
+ n_intro_points_to_open = (service->n_intro_points_wanted +
+ (prev_intro_nodes == 0 ? 2 : 0));
+ for (j = (int)n_intro_points_unexpired;
+ j < (int)n_intro_points_to_open;
+ ++j) { /* XXXX remove casts */
+ router_crn_flags_t flags = CRN_NEED_UPTIME|CRN_NEED_DESC;
+ if (get_options()->AllowInvalid_ & ALLOW_INVALID_INTRODUCTION)
+ flags |= CRN_ALLOW_INVALID;
+ node = router_choose_random_node(intro_nodes,
+ options->ExcludeNodes, flags);
+ if (!node) {
+ log_warn(LD_REND,
+ "Could only establish %d introduction points for %s; "
+ "wanted %u.",
+ smartlist_len(service->intro_nodes), service->service_id,
+ n_intro_points_to_open);
+ break;
+ }
+ intro_point_set_changed = 1;
+ smartlist_add(intro_nodes, (void*)node);
+ intro = tor_malloc_zero(sizeof(rend_intro_point_t));
+ intro->extend_info = extend_info_from_node(node, 0);
+ intro->intro_key = crypto_pk_new();
+ tor_assert(!crypto_pk_generate_key(intro->intro_key));
+ intro->time_published = -1;
+ intro->time_to_expire = -1;
+ intro->time_expiring = -1;
+ smartlist_add(service->intro_nodes, intro);
+ log_info(LD_REND, "Picked router %s as an intro point for %s.",
+ safe_str_client(node_describe(node)),
+ safe_str_client(service->service_id));
+ }
+ } else {
+ // Continue wating for the descriptor
+ log_info(LD_REND,
+ "query %s didn't have valid rend desc in cache. "
+ "Waiting for descriptor",
+ safe_str_client(service->service_id));
+ continue;
+ }
+ }
}
/* If there's no need to launch new circuits, stop here. */