diff options
Diffstat (limited to 'src/or/rendservice.c')
-rw-r--r-- | src/or/rendservice.c | 73 |
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. */ |