summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/or/circuituse.c16
-rw-r--r--src/or/or.h4
-rw-r--r--src/or/rendservice.c16
3 files changed, 36 insertions, 0 deletions
diff --git a/src/or/circuituse.c b/src/or/circuituse.c
index d9d95bc68a..9778ae7b29 100644
--- a/src/or/circuituse.c
+++ b/src/or/circuituse.c
@@ -550,6 +550,22 @@ circuit_expire_building(void)
}
}
+ /* If this is a service-side rendezvous circuit which is far
+ * enough along in connecting to its destination, consider sparing
+ * it. */
+ if (!(TO_ORIGIN_CIRCUIT(victim)->hs_circ_has_timed_out) &&
+ victim->purpose == CIRCUIT_PURPOSE_S_CONNECT_REND) {
+ log_info(LD_CIRC,"Marking circ %s:%d:%d (state %d:%s, purpose %d) "
+ "as timed-out HS circ; relaunching rendezvous attempt.",
+ victim->n_conn->_base.address, victim->n_conn->_base.port,
+ victim->n_circ_id,
+ victim->state, circuit_state_to_string(victim->state),
+ victim->purpose);
+ TO_ORIGIN_CIRCUIT(victim)->hs_circ_has_timed_out = 1;
+ rend_service_relaunch_rendezvous(TO_ORIGIN_CIRCUIT(victim));
+ continue;
+ }
+
if (victim->n_conn)
log_info(LD_CIRC,"Abandoning circ %s:%d:%d (state %d:%s, purpose %d)",
victim->n_conn->_base.address, victim->n_conn->_base.port,
diff --git a/src/or/or.h b/src/or/or.h
index d84f04b250..3ac8b92516 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -2614,6 +2614,10 @@ typedef struct origin_circuit_t {
* circuit. */
unsigned int hs_circ_has_timed_out : 1;
+ /** Set iff this is a service-side rendezvous circuit for which a
+ * new connection attempt has been launched. */
+ unsigned int hs_service_side_rend_circ_has_been_relaunched : 1;
+
/** What commands were sent over this circuit that decremented the
* RELAY_EARLY counter? This is for debugging task 878. */
uint8_t relay_early_commands[MAX_RELAY_EARLY_CELLS_PER_CIRCUIT];
diff --git a/src/or/rendservice.c b/src/or/rendservice.c
index 76caeffd0f..bbc9c91866 100644
--- a/src/or/rendservice.c
+++ b/src/or/rendservice.c
@@ -1419,6 +1419,17 @@ rend_service_relaunch_rendezvous(origin_circuit_t *oldcirc)
tor_assert(oldcirc->_base.purpose == CIRCUIT_PURPOSE_S_CONNECT_REND);
+ /* Don't relaunch the same rend circ twice. */
+ if (oldcirc->hs_service_side_rend_circ_has_been_relaunched) {
+ log_info(LD_REND, "Rendezvous circuit to %s has already been relaunched; "
+ "not relaunching it again.",
+ oldcirc->build_state ?
+ safe_str(extend_info_describe(oldcirc->build_state->chosen_exit))
+ : "*unknown*");
+ return;
+ }
+ oldcirc->hs_service_side_rend_circ_has_been_relaunched = 1;
+
if (!oldcirc->build_state ||
oldcirc->build_state->failure_count > MAX_REND_FAILURES ||
oldcirc->build_state->expiry_time < time(NULL)) {
@@ -1727,6 +1738,11 @@ rend_service_rendezvous_has_opened(origin_circuit_t *circuit)
"cookie %s for service %s",
circuit->_base.n_circ_id, hexcookie, serviceid);
+ /* Clear the 'in-progress HS circ has timed out' flag for
+ * consistency with what happens on the client side; this line has
+ * no effect on Tor's behaviour. */
+ circuit->hs_circ_has_timed_out = 0;
+
service = rend_service_get_by_pk_digest(
circuit->rend_data->rend_pk_digest);
if (!service) {