[tor-commits] [tor/master] Record intro point timeouts in rend_intro_point_t

nickm at torproject.org nickm at torproject.org
Mon Oct 3 19:14:00 UTC 2011


commit eaed37d14c6e1dc93a392f62ef2e501f75e4878a
Author: Robert Ransom <rransom.8774 at gmail.com>
Date:   Sat Sep 17 03:19:29 2011 -0700

    Record intro point timeouts in rend_intro_point_t
---
 src/or/circuitlist.c |   19 +++++++++++--------
 src/or/or.h          |    7 +++++++
 src/or/rendclient.c  |   50 ++++++++++++++++++++++++++++++++++++++++----------
 src/or/rendclient.h  |   10 ++++++++--
 4 files changed, 66 insertions(+), 20 deletions(-)

diff --git a/src/or/circuitlist.c b/src/or/circuitlist.c
index e9cc9eb..2fc645a 100644
--- a/src/or/circuitlist.c
+++ b/src/or/circuitlist.c
@@ -1119,9 +1119,8 @@ circuit_expire_all_dirty_circs(void)
  *   - If circ isn't open yet: call circuit_build_failed() if we're
  *     the origin, and in either case call circuit_rep_hist_note_result()
  *     to note stats.
- *   - If purpose is C_INTRODUCE_ACK_WAIT, remove the intro point we
- *     just tried from our list of intro points for that service
- *     descriptor.
+ *   - If purpose is C_INTRODUCE_ACK_WAIT, report the intro point
+ *     failure we just had to the hidden service client module.
  *   - Send appropriate destroys and edge_destroys for conns and
  *     streams attached to circ.
  *   - If circ->rend_splice is set (we are the midpoint of a joined
@@ -1190,16 +1189,20 @@ _circuit_mark_for_close(circuit_t *circ, int reason, int line,
   }
   if (circ->purpose == CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT) {
     origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ);
+    int timed_out = (reason == END_STREAM_REASON_TIMEOUT);
     tor_assert(circ->state == CIRCUIT_STATE_OPEN);
     tor_assert(ocirc->build_state->chosen_exit);
     tor_assert(ocirc->rend_data);
     /* treat this like getting a nack from it */
-    log_info(LD_REND, "Failed intro circ %s to %s (awaiting ack). "
-           "Removing from descriptor.",
+    log_info(LD_REND, "Failed intro circ %s to %s (awaiting ack). %s",
            safe_str_client(ocirc->rend_data->onion_address),
-           safe_str_client(build_state_get_exit_nickname(ocirc->build_state)));
-    rend_client_remove_intro_point(ocirc->build_state->chosen_exit,
-                                   ocirc->rend_data);
+           safe_str_client(build_state_get_exit_nickname(ocirc->build_state)),
+           timed_out ? "Recording timeout." : "Removing from descriptor.");
+    rend_client_report_intro_point_failure(ocirc->build_state->chosen_exit,
+                                           ocirc->rend_data,
+                                           timed_out ?
+                                           INTRO_POINT_FAILURE_TIMEOUT :
+                                           INTRO_POINT_FAILURE_GENERIC);
   }
   if (circ->n_conn) {
     circuit_clear_cell_queue(circ, circ->n_conn);
diff --git a/src/or/or.h b/src/or/or.h
index 31deb89..32d4b11 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -3463,6 +3463,13 @@ typedef struct rend_intro_point_t {
   extend_info_t *extend_info; /**< Extend info of this introduction point. */
   crypto_pk_env_t *intro_key; /**< Introduction key that replaces the service
                                * key, if this descriptor is V2. */
+
+  /** (Client side only) Flag indicating that a timeout has occurred
+   * after sending an INTRODUCE cell to this intro point.  After a
+   * timeout, an intro point should not be tried again during the same
+   * hidden service connection attempt, but it may be tried again
+   * during a future connection attempt. */
+  unsigned int timed_out : 1;
 } rend_intro_point_t;
 
 /** Information used to connect to a hidden service.  Used on both the
diff --git a/src/or/rendclient.c b/src/or/rendclient.c
index 773ac8d..013d544 100644
--- a/src/or/rendclient.c
+++ b/src/or/rendclient.c
@@ -366,8 +366,9 @@ rend_client_introduction_acked(origin_circuit_t *circ,
     log_info(LD_REND, "Got nack for %s from %s...",
         safe_str_client(circ->rend_data->onion_address),
         safe_str_client(extend_info_describe(circ->build_state->chosen_exit)));
-    if (rend_client_remove_intro_point(circ->build_state->chosen_exit,
-                                       circ->rend_data) > 0) {
+    if (rend_client_report_intro_point_failure(circ->build_state->chosen_exit,
+                                               circ->rend_data,
+                                               INTRO_POINT_FAILURE_GENERIC)>0){
       /* There are introduction points left. Re-extend the circuit to
        * another intro point and try again. */
       int result = rend_client_reextend_intro_circuit(circ);
@@ -648,16 +649,26 @@ rend_client_cancel_descriptor_fetches(void)
   } SMARTLIST_FOREACH_END(conn);
 }
 
-/** Remove failed_intro from ent. If ent now has no intro points, or
- * service is unrecognized, then launch a new renddesc fetch.
-
+/** Mark <b>failed_intro</b> as a failed introduction point for the
+ * hidden service specified by <b>rend_query</b>. If the HS now has no
+ * usable intro points, or we do not have an HS descriptor for it,
+ * then launch a new renddesc fetch.
+ *
+ * If <b>failure_type</b> is INTRO_POINT_FAILURE_GENERIC, remove the
+ * intro point from (our parsed copy of) the HS descriptor.
+ *
+ * If <b>failure_type</b> is INTRO_POINT_FAILURE_TIMEOUT, mark the
+ * intro point as 'timed out'; it will not be retried until the
+ * current hidden service connection attempt has ended or it has
+ * appeared in a newly fetched rendezvous descriptor.
  *
- * Return -1 if error, 0 if no intro points remain or service
+ * Return -1 if error, 0 if no usable intro points remain or service
  * unrecognized, 1 if recognized and some intro points remain.
  */
 int
-rend_client_remove_intro_point(extend_info_t *failed_intro,
-                               const rend_data_t *rend_query)
+rend_client_report_intro_point_failure(extend_info_t *failed_intro,
+                                       const rend_data_t *rend_query,
+                                       unsigned int failure_type)
 {
   int i, r;
   rend_cache_entry_t *ent;
@@ -680,8 +691,20 @@ rend_client_remove_intro_point(extend_info_t *failed_intro,
     rend_intro_point_t *intro = smartlist_get(ent->parsed->intro_nodes, i);
     if (tor_memeq(failed_intro->identity_digest,
                 intro->extend_info->identity_digest, DIGEST_LEN)) {
-      rend_intro_point_free(intro);
-      smartlist_del(ent->parsed->intro_nodes, i);
+      switch (failure_type) {
+      default:
+        log_warn(LD_BUG, "Unknown failure type %u. Removing intro point.",
+                 failure_type);
+        tor_fragile_assert();
+        /* fall through */
+      case INTRO_POINT_FAILURE_GENERIC:
+        rend_intro_point_free(intro);
+        smartlist_del(ent->parsed->intro_nodes, i);
+        break;
+      case INTRO_POINT_FAILURE_TIMEOUT:
+        intro->timed_out = 1;
+        break;
+      }
       break;
     }
   }
@@ -911,6 +934,13 @@ rend_client_get_random_intro_impl(const rend_cache_entry_t *entry,
   usable_nodes = smartlist_create();
   smartlist_add_all(usable_nodes, entry->parsed->intro_nodes);
 
+  /* Remove the intro points that have timed out during this HS
+   * connection attempt from our list of usable nodes. */
+  SMARTLIST_FOREACH(usable_nodes, rend_intro_point_t *, ip,
+                    if (ip->timed_out) {
+                      SMARTLIST_DEL_CURRENT(usable_nodes, ip);
+                    });
+
  again:
   if (smartlist_len(usable_nodes) == 0) {
     if (n_excluded && get_options()->StrictNodes && warnings) {
diff --git a/src/or/rendclient.h b/src/or/rendclient.h
index c6cf82b..3421e07 100644
--- a/src/or/rendclient.h
+++ b/src/or/rendclient.h
@@ -22,8 +22,14 @@ int rend_client_introduction_acked(origin_circuit_t *circ,
 void rend_client_refetch_v2_renddesc(const rend_data_t *rend_query);
 void rend_client_cancel_descriptor_fetches(void);
 void rend_client_purge_last_hid_serv_requests(void);
-int rend_client_remove_intro_point(extend_info_t *failed_intro,
-                                   const rend_data_t *rend_query);
+
+#define INTRO_POINT_FAILURE_GENERIC 0
+#define INTRO_POINT_FAILURE_TIMEOUT 1
+
+int rend_client_report_intro_point_failure(extend_info_t *failed_intro,
+                                           const rend_data_t *rend_query,
+                                           unsigned int failure_type);
+
 int rend_client_rendezvous_acked(origin_circuit_t *circ,
                                  const uint8_t *request,
                                  size_t request_len);





More information about the tor-commits mailing list