aboutsummaryrefslogtreecommitdiff
path: root/src/or/rendservice.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/or/rendservice.c')
-rw-r--r--src/or/rendservice.c73
1 files changed, 60 insertions, 13 deletions
diff --git a/src/or/rendservice.c b/src/or/rendservice.c
index a86245b9f4..85f0fc7772 100644
--- a/src/or/rendservice.c
+++ b/src/or/rendservice.c
@@ -31,9 +31,12 @@
#include "routerparse.h"
#include "routerset.h"
+struct rend_service_t;
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);
+static rend_intro_point_t *find_expiring_intro_point(
+ struct rend_service_t *service, origin_circuit_t *circ);
static extend_info_t *find_rp_for_intro(
const rend_intro_cell_t *intro,
@@ -42,7 +45,6 @@ static extend_info_t *find_rp_for_intro(
static int intro_point_accepted_intro_count(rend_intro_point_t *intro);
static int intro_point_should_expire_now(rend_intro_point_t *intro,
time_t now);
-struct rend_service_t;
static int rend_service_derive_key_digests(struct rend_service_t *s);
static int rend_service_load_keys(struct rend_service_t *s);
static int rend_service_load_auth_keys(struct rend_service_t *s,
@@ -1503,12 +1505,15 @@ rend_service_introduce(origin_circuit_t *circuit, const uint8_t *request,
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));
- goto err;
+ intro_point = find_expiring_intro_point(service, 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));
+ goto err;
+ }
}
log_info(LD_REND, "Received INTRODUCE2 cell for service %s on circ %u.",
@@ -2688,8 +2693,8 @@ rend_service_launch_establish_intro(rend_service_t *service,
return 0;
}
-/** Return the number of introduction points that are or have been
- * established for the given service. */
+/** Return the number of introduction points that are established for the
+ * given service. */
static unsigned int
count_established_intro_points(const rend_service_t *service)
{
@@ -2701,6 +2706,30 @@ count_established_intro_points(const rend_service_t *service)
return num;
}
+/** Return the number of introduction points that are or are being
+ * established for the given service. This function iterates over all
+ * circuit and count those that are linked to the service and are waiting
+ * for the intro point to respond. */
+static unsigned int
+count_intro_point_circuits(const rend_service_t *service)
+{
+ unsigned int num_ipos = 0;
+ SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, circ) {
+ if (!circ->marked_for_close &&
+ circ->state == CIRCUIT_STATE_OPEN &&
+ (circ->purpose == CIRCUIT_PURPOSE_S_ESTABLISH_INTRO ||
+ circ->purpose == CIRCUIT_PURPOSE_S_INTRO)) {
+ origin_circuit_t *oc = TO_ORIGIN_CIRCUIT(circ);
+ if (oc->rend_data &&
+ !rend_cmp_service_ids(service->service_id,
+ oc->rend_data->onion_address))
+ num_ipos++;
+ }
+ }
+ SMARTLIST_FOREACH_END(circ);
+ return num_ipos;
+}
+
/** Called when we're done building a circuit to an introduction point:
* sends a RELAY_ESTABLISH_INTRO cell.
*/
@@ -2739,7 +2768,8 @@ rend_service_intro_has_opened(origin_circuit_t *circuit)
* redefine this one as a general circuit or close it, depending.
* Substract the amount of expiring nodes here since the circuits are
* still opened. */
- if (count_established_intro_points(service) >
+ if ((count_intro_point_circuits(service) -
+ smartlist_len(service->expiring_nodes)) >
service->n_intro_points_wanted) {
const or_options_t *options = get_options();
/* Remove the intro point associated with this circuit, it's being
@@ -3053,6 +3083,23 @@ find_intro_circuit(rend_intro_point_t *intro, const char *pk_digest)
return NULL;
}
+/** Return the corresponding introdution point using the circuit <b>circ</b>
+ * found in the <b>service</b>. NULL is returned if not found. */
+static rend_intro_point_t *
+find_expiring_intro_point(rend_service_t *service, origin_circuit_t *circ)
+{
+ tor_assert(service);
+ tor_assert(TO_CIRCUIT(circ)->purpose == CIRCUIT_PURPOSE_S_ESTABLISH_INTRO ||
+ TO_CIRCUIT(circ)->purpose == CIRCUIT_PURPOSE_S_INTRO);
+
+ SMARTLIST_FOREACH(service->intro_nodes, rend_intro_point_t *, intro_point,
+ if (crypto_pk_eq_keys(intro_point->intro_key, circ->intro_key)) {
+ return intro_point;
+ });
+
+ 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 *
@@ -3654,10 +3701,10 @@ rend_consider_services_upload(time_t now)
/* Does every introduction points have been established? */
unsigned int intro_points_ready =
count_established_intro_points(service) >= service->n_intro_points_wanted;
- if (service->next_upload_time < now ||
+ if (intro_points_ready &&
+ (service->next_upload_time < now ||
(service->desc_is_dirty &&
- service->desc_is_dirty < now-rendinitialpostdelay &&
- intro_points_ready)) {
+ service->desc_is_dirty < now-rendinitialpostdelay))) {
/* if it's time, or if the directory servers have a wrong service
* descriptor and ours has been stable for rendinitialpostdelay seconds,
* upload a new one of each format. */