Browse Source

Clear the timed_out flag when an HS connection attempt ends

Robert Ransom 12 years ago
parent
commit
34a6b8b7e5
5 changed files with 52 additions and 0 deletions
  1. 8 0
      changes/bug1297b
  2. 7 0
      src/or/circuituse.c
  3. 12 0
      src/or/connection_edge.c
  4. 23 0
      src/or/rendclient.c
  5. 2 0
      src/or/rendclient.h

+ 8 - 0
changes/bug1297b

@@ -0,0 +1,8 @@
+  o Minor bugfixes:
+
+    - When one of a hidden service's introduction points times out,
+      consider trying it again during the next attempt to connect to
+      the HS.  Previously, we would not try it again unless a newly
+      fetched descriptor contained it.  Required by fixes for bugs
+      1297 and 3825.
+

+ 7 - 0
src/or/circuituse.c

@@ -1464,6 +1464,13 @@ link_apconn_to_circ(edge_connection_t *apconn, origin_circuit_t *circ,
   /* assert_connection_ok(conn, time(NULL)); */
   circ->p_streams = apconn;
 
+  if (connection_edge_is_rendezvous_stream(apconn)) {
+    /* We are attaching a stream to a rendezvous circuit.  That means
+     * that an attempt to connect to a hidden service just
+     * succeeded.  Tell rendclient.c. */
+   rend_client_note_connection_attempt_ended(apconn->rend_data->onion_address);
+  }
+
   if (cpath) { /* we were given one; use it */
     tor_assert(cpath_is_on_circuit(circ, cpath));
     apconn->cpath_layer = cpath;

+ 12 - 0
src/or/connection_edge.c

@@ -68,6 +68,18 @@ _connection_mark_unattached_ap(edge_connection_t *conn, int endreason,
   tor_assert(conn->_base.type == CONN_TYPE_AP);
   conn->edge_has_sent_end = 1; /* no circ yet */
 
+  /* If this is a rendezvous stream and it is failing without ever
+   * being attached to a circuit, assume that an attempt to connect to
+   * the destination hidden service has just ended.
+   *
+   * XXX023 This condition doesn't limit to only streams failing
+   * without ever being attached.  That sloppiness should be harmless,
+   * but we should fix it someday anyway. */
+  if ((conn->on_circuit != NULL || conn->edge_has_sent_end) &&
+      connection_edge_is_rendezvous_stream(conn)) {
+    rend_client_note_connection_attempt_ended(conn->rend_data->onion_address);
+  }
+
   if (conn->_base.marked_for_close) {
     /* This call will warn as appropriate. */
     _connection_mark_for_close(TO_CONN(conn), line, file);

+ 23 - 0
src/or/rendclient.c

@@ -881,10 +881,33 @@ rend_client_desc_trynow(const char *query)
                  "unavailable (try again later).",
                  safe_str_client(query));
       connection_mark_unattached_ap(conn, END_STREAM_REASON_RESOLVEFAILED);
+      rend_client_note_connection_attempt_ended(query);
     }
   } SMARTLIST_FOREACH_END(_conn);
 }
 
+/** Clear temporary state used only during an attempt to connect to
+ * the hidden service named <b>onion_address</b>.  Called when a
+ * connection attempt has ended; may be called occasionally at other
+ * times, and should be reasonably harmless. */
+void
+rend_client_note_connection_attempt_ended(const char *onion_address)
+{
+  rend_cache_entry_t *cache_entry = NULL;
+  rend_cache_lookup_entry(onion_address, -1, &cache_entry);
+
+  log_info(LD_REND, "Connection attempt for %s has ended; "
+           "cleaning up temporary state.",
+           safe_str_client(onion_address));
+
+  /* Clear the timed_out flag on all remaining intro points for this HS. */
+  if (cache_entry != NULL) {
+    SMARTLIST_FOREACH(cache_entry->parsed->intro_nodes,
+                      rend_intro_point_t *, ip,
+                      ip->timed_out = 0; );
+  }
+}
+
 /** Return a newly allocated extend_info_t* for a randomly chosen introduction
  * point for the named hidden service.  Return NULL if all introduction points
  * have been tried and failed.

+ 2 - 0
src/or/rendclient.h

@@ -38,6 +38,8 @@ int rend_client_receive_rendezvous(origin_circuit_t *circ,
                                    size_t request_len);
 void rend_client_desc_trynow(const char *query);
 
+void rend_client_note_connection_attempt_ended(const char *onion_address);
+
 extend_info_t *rend_client_get_random_intro(const rend_data_t *rend_query);
 int rend_client_any_intro_points_usable(const rend_cache_entry_t *entry);