commit 190aac0eab9e9911a274c0c52b9271e1e4e79cbd
Author: Robert Ransom <rransom.8774(a)gmail.com>
Date: Tue Oct 4 17:34:42 2011 -0700
Allow different HSes to maintain different numbers of intro points
---
src/or/rendservice.c | 34 ++++++++++++++++++++++------------
1 files changed, 22 insertions(+), 12 deletions(-)
diff --git a/src/or/rendservice.c b/src/or/rendservice.c
index 6ed9650..906a330 100644
--- a/src/or/rendservice.c
+++ b/src/or/rendservice.c
@@ -35,8 +35,10 @@ …
[View More]typedef struct rend_service_port_config_t {
tor_addr_t real_addr;
} rend_service_port_config_t;
-/** Try to maintain this many intro points per service if possible. */
-#define NUM_INTRO_POINTS 3
+/** Try to maintain this many intro points per service by default. */
+#define NUM_INTRO_POINTS_DEFAULT 3
+/** Maintain no more than this many intro points per hidden service. */
+#define NUM_INTRO_POINTS_MAX 10
/** If we can't build our intro circuits, don't retry for this long. */
#define INTRO_CIRC_RETRY_PERIOD (60*5)
@@ -71,6 +73,8 @@ typedef struct rend_service_t {
* introduction points. */
int n_intro_circuits_launched; /**< Count of intro circuits we have
* established in this period. */
+ unsigned int n_intro_points_wanted; /**< Number of intro points this
+ * service wants to have open. */
rend_service_descriptor_t *desc; /**< Current hidden service descriptor. */
time_t desc_is_dirty; /**< Time at which changes to the hidden service
* descriptor content occurred, or 0 if it's
@@ -315,6 +319,7 @@ rend_config_services(or_options_t *options, int validate_only)
service->directory = tor_strdup(line->value);
service->ports = smartlist_create();
service->intro_period_started = time(NULL);
+ service->n_intro_points_wanted = NUM_INTRO_POINTS_DEFAULT;
continue;
}
if (!service) {
@@ -1406,7 +1411,8 @@ rend_service_intro_has_opened(origin_circuit_t *circuit)
/* If we already have enough introduction circuits for this service,
* redefine this one as a general circuit or close it, depending. */
- if (count_established_intro_points(serviceid) > NUM_INTRO_POINTS) {
+ if (count_established_intro_points(serviceid) >
+ (int)service->n_intro_points_wanted) { /* XXX023 remove cast */
or_options_t *options = get_options();
if (options->ExcludeNodes) {
/* XXXX in some future version, we can test whether the transition is
@@ -1845,6 +1851,7 @@ rend_services_introduce(void)
rend_service_t *service;
rend_intro_point_t *intro;
int changed, prev_intro_nodes;
+ unsigned int n_intro_points_to_open;
smartlist_t *intro_routers;
time_t now;
or_options_t *options = get_options();
@@ -1901,7 +1908,8 @@ rend_services_introduce(void)
/* We have enough intro points, and the intro points we thought we had were
* all connected.
*/
- if (!changed && smartlist_len(service->intro_nodes) >= NUM_INTRO_POINTS) {
+ if (!changed && (smartlist_len(service->intro_nodes) >=
+ (int)service->n_intro_points_wanted)) { /*XXX023 remove cast*/
/* We have all our intro points! Start a fresh period and reset the
* circuit count. */
service->intro_period_started = now;
@@ -1912,18 +1920,18 @@ rend_services_introduce(void)
/* Remember how many introduction circuits we started with. */
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 three intro points, but if
- * we're just starting, we launch five and pick the first three that
- * complete.
+ * 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. */
-#define NUM_INTRO_POINTS_INIT (NUM_INTRO_POINTS + 2)
- for (j=prev_intro_nodes; j < (prev_intro_nodes == 0 ?
- NUM_INTRO_POINTS_INIT : NUM_INTRO_POINTS); ++j) {
+ n_intro_points_to_open = (service->n_intro_points_wanted +
+ (prev_intro_nodes == 0 ? 2 : 0));
+ for (j=prev_intro_nodes; j < (int)n_intro_points_to_open; ++j) { /* XXXX remove cast */
router_crn_flags_t flags = CRN_NEED_UPTIME;
if (get_options()->_AllowInvalid & ALLOW_INVALID_INTRODUCTION)
flags |= CRN_ALLOW_INVALID;
@@ -1931,8 +1939,10 @@ rend_services_introduce(void)
options->ExcludeNodes, flags);
if (!router) {
log_warn(LD_REND,
- "Could only establish %d introduction points for %s.",
- smartlist_len(service->intro_nodes), service->service_id);
+ "Could only establish %d introduction points for %s; "
+ "wanted %u.",
+ smartlist_len(service->intro_nodes), service->service_id,
+ n_intro_points_to_open);
break;
}
changed = 1;
[View Less]
commit c60148c7f52e76397b79faaddf1bdb6204c4d170
Author: Robert Ransom <rransom.8774(a)gmail.com>
Date: Wed Oct 5 15:43:02 2011 -0700
Record the time at which each intro point was first published
---
src/or/or.h | 5 +++++
src/or/rendservice.c | 8 ++++++++
2 files changed, 13 insertions(+), 0 deletions(-)
diff --git a/src/or/or.h b/src/or/or.h
index f884c12..cf241a6 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -3480,6 +3480,11 @@ typedef struct rend_intro_point_t {…
[View More]
* circuit to this intro point for some reason other than our
* circuit-build timeout. See also MAX_INTRO_POINT_REACHABILITY_FAILURES. */
unsigned int unreachable_count : 3;
+
+ /** (Service side only) The time at which this intro point was first
+ * published, or -1 if this intro point has not yet been
+ * published. */
+ time_t time_published;
} rend_intro_point_t;
/** Information used to connect to a hidden service. Used on both the
diff --git a/src/or/rendservice.c b/src/or/rendservice.c
index 682d13d..24d5937 100644
--- a/src/or/rendservice.c
+++ b/src/or/rendservice.c
@@ -554,6 +554,13 @@ rend_service_update_descriptor(rend_service_t *service)
if (intro_svc->intro_key)
intro_desc->intro_key = crypto_pk_dup_key(intro_svc->intro_key);
smartlist_add(d->intro_nodes, intro_desc);
+
+ if (intro_svc->time_published == -1) {
+ /* We are publishing this intro point in a descriptor for the
+ * first time -- note the current time in the service's copy of
+ * the intro point. */
+ intro_svc->time_published = time(NULL);
+ }
}
}
@@ -1952,6 +1959,7 @@ rend_services_introduce(void)
intro->extend_info = extend_info_from_router(router);
intro->intro_key = crypto_new_pk_env();
tor_assert(!crypto_pk_generate_key(intro->intro_key));
+ intro->time_published = -1;
smartlist_add(service->intro_nodes, intro);
log_info(LD_REND, "Picked router %s as an intro point for %s.",
safe_str_client(router_describe(router)),
[View Less]
commit 6f035cb2b450e8779bff50d6ed83e4822a49f0fe
Author: Robert Ransom <rransom.8774(a)gmail.com>
Date: Wed Oct 5 23:52:14 2011 -0700
Record the number of INTRODUCE2 cells each intro point has received
---
src/or/or.h | 4 ++++
src/or/rendservice.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 50 insertions(+), 0 deletions(-)
diff --git a/src/or/or.h b/src/or/or.h
index cf241a6..215bde2 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -3481,6 +…
[View More]3481,10 @@ typedef struct rend_intro_point_t {
* circuit-build timeout. See also MAX_INTRO_POINT_REACHABILITY_FAILURES. */
unsigned int unreachable_count : 3;
+ /** (Service side only) The number of INTRODUCE2 cells this intro
+ * point's circuit has received. */
+ unsigned int introduction_count : 24;
+
/** (Service side only) The time at which this intro point was first
* published, or -1 if this intro point has not yet been
* published. */
diff --git a/src/or/rendservice.c b/src/or/rendservice.c
index d21fdcc..a341dd6 100644
--- a/src/or/rendservice.c
+++ b/src/or/rendservice.c
@@ -25,6 +25,7 @@
static origin_circuit_t *find_intro_circuit(rend_intro_point_t *intro,
const char *pk_digest);
+static rend_intro_point_t *find_intro_point(origin_circuit_t *circ);
/** Represents the mapping from a virtual port of a rendezvous service to
* a real port on some IP.
@@ -899,6 +900,7 @@ rend_service_introduce(origin_circuit_t *circuit, const uint8_t *request,
char buf[RELAY_PAYLOAD_SIZE];
char keys[DIGEST_LEN+CPATH_KEY_MATERIAL_LEN]; /* Holds KH, Df, Db, Kf, Kb */
rend_service_t *service;
+ rend_intro_point_t *intro_point;
int r, i, v3_shift = 0;
size_t len, keylen;
crypto_dh_env_t *dh = NULL;
@@ -971,6 +973,14 @@ rend_service_introduce(origin_circuit_t *circuit, const uint8_t *request,
return -1;
}
+ intro_point = find_intro_point(circuit);
+ if (intro_point == NULL) {
+ log_warn(LD_BUG, "Internal error: Got an INTRODUCE2 cell on an intro circ "
+ "(for service %s) with no corresponding rend_intro_point_t.",
+ escaped(serviceid));
+ return -1;
+ }
+
if (!service->accepted_intros)
service->accepted_intros = digestmap_new();
@@ -993,6 +1003,13 @@ rend_service_introduce(origin_circuit_t *circuit, const uint8_t *request,
digestmap_set(service->accepted_intros, pkpart_digest, access_time);
}
+ /* Record that we've received another INTRODUCE2 cell through this
+ * intro point. */
+ ++(intro_point->introduction_count);
+ if (intro_point->introduction_count == 0) {
+ --(intro_point->introduction_count);
+ }
+
/* Next N bytes is encrypted with service key */
note_crypto_pk_op(REND_SERVER);
r = crypto_pk_private_hybrid_decrypt(
@@ -1647,6 +1664,35 @@ find_intro_circuit(rend_intro_point_t *intro, const char *pk_digest)
return NULL;
}
+/** Return a pointer to the rend_intro_point_t corresponding to the
+ * service-side introduction circuit <b>circ</b>. */
+static rend_intro_point_t *
+find_intro_point(origin_circuit_t *circ)
+{
+ const char *serviceid;
+ rend_service_t *service = NULL;
+
+ tor_assert(TO_CIRCUIT(circ)->purpose == CIRCUIT_PURPOSE_S_ESTABLISH_INTRO ||
+ TO_CIRCUIT(circ)->purpose == CIRCUIT_PURPOSE_S_INTRO);
+ tor_assert(circ->rend_data);
+ serviceid = circ->rend_data->onion_address;
+
+ SMARTLIST_FOREACH(rend_service_list, rend_service_t *, s,
+ if (tor_memeq(s->service_id, serviceid, REND_SERVICE_ID_LEN_BASE32)) {
+ service = s;
+ break;
+ });
+
+ if (service == NULL) return NULL;
+
+ SMARTLIST_FOREACH(service->intro_nodes, rend_intro_point_t *, intro_point,
+ if (crypto_pk_cmp_keys(intro_point->intro_key, circ->intro_key) == 0) {
+ return intro_point;
+ });
+
+ 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
[View Less]
commit 68331cbd81931b395355553531ee42961d3385e5
Author: Robert Ransom <rransom.8774(a)gmail.com>
Date: Thu Oct 13 09:41:29 2011 -0700
Determine whether an intro point was in the last HS desc in a sane way
---
src/or/rendservice.c | 16 +++++-----------
1 files changed, 5 insertions(+), 11 deletions(-)
diff --git a/src/or/rendservice.c b/src/or/rendservice.c
index 96ab7a6..ce7295e 100644
--- a/src/or/rendservice.c
+++ b/src/or/rendservice.c
@@ -1947,17 +1947,11 @@ …
[View More]rend_services_introduce(void)
log_info(LD_REND,"Giving up on %s as intro point for %s.",
safe_str_client(extend_info_describe(intro->extend_info)),
safe_str_client(service->service_id));
- if (service->desc) {
- SMARTLIST_FOREACH(service->desc->intro_nodes, rend_intro_point_t *,
- dintro, {
- if (tor_memeq(dintro->extend_info->identity_digest,
- intro->extend_info->identity_digest, DIGEST_LEN)) {
- log_info(LD_REND, "The intro point we are giving up on was "
- "included in the last published descriptor. "
- "Marking current descriptor as dirty.");
- service->desc_is_dirty = now;
- }
- });
+ if (intro->listed_in_last_desc) {
+ log_info(LD_REND, "The intro point we are giving up on was "
+ "included in the last published descriptor. "
+ "Marking current descriptor as dirty.");
+ service->desc_is_dirty = now;
}
rend_intro_point_free(intro);
smartlist_del(service->intro_nodes,j--);
[View Less]
commit 3f6a2d3e2a83d60f287c485c4f444220792b0a66
Author: Robert Ransom <rransom.8774(a)gmail.com>
Date: Thu Oct 13 08:48:31 2011 -0700
Record which intro points were listed in the last HS desc
---
src/or/or.h | 4 ++++
src/or/rendservice.c | 7 +++++++
2 files changed, 11 insertions(+), 0 deletions(-)
diff --git a/src/or/or.h b/src/or/or.h
index 215bde2..e1bd25c 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -3481,6 +3481,10 @@ typedef struct rend_intro_point_t {
…
[View More]* circuit-build timeout. See also MAX_INTRO_POINT_REACHABILITY_FAILURES. */
unsigned int unreachable_count : 3;
+ /** (Service side only) Flag indicating that this intro point was
+ * included in the last HS descriptor we generated. */
+ unsigned int listed_in_last_desc : 1;
+
/** (Service side only) The number of INTRODUCE2 cells this intro
* point's circuit has received. */
unsigned int introduction_count : 24;
diff --git a/src/or/rendservice.c b/src/or/rendservice.c
index a341dd6..96ab7a6 100644
--- a/src/or/rendservice.c
+++ b/src/or/rendservice.c
@@ -544,10 +544,17 @@ rend_service_update_descriptor(rend_service_t *service)
for (i = 0; i < smartlist_len(service->intro_nodes); ++i) {
rend_intro_point_t *intro_svc = smartlist_get(service->intro_nodes, i);
rend_intro_point_t *intro_desc;
+
+ /* This intro point won't be listed in the descriptor... */
+ intro_svc->listed_in_last_desc = 0;
+
circ = find_intro_circuit(intro_svc, service->pk_digest);
if (!circ || circ->_base.purpose != CIRCUIT_PURPOSE_S_INTRO)
continue;
+ /* ...unless this intro point is listed in the descriptor. */
+ intro_svc->listed_in_last_desc = 1;
+
/* We have an entirely established intro circuit. Publish it in
* our descriptor. */
intro_desc = tor_malloc_zero(sizeof(rend_intro_point_t));
[View Less]