commit 4aa4bce474e6fb3e52c0aecb48f3e5024576e693
Merge: a7f93b5 c5226bf
Author: Nick Mathewson <nickm(a)torproject.org>
Date: Mon Oct 3 15:06:07 2011 -0400
Merge remote-tracking branch 'rransom-tor/bug3335-v2'
Conflicts:
src/or/connection_edge.c
src/or/rendclient.c
changes/bug1297b | 8 ++
changes/bug3335 | 11 +++
changes/bug3825a | 8 ++
src/or/circuitlist.c | 33 +++++++--
src/or/circuituse.c | 7 ++
src/or/connection_edge.c | 12 +++
src/or/or.h | 17 +++++
src/or/rendclient.c | 177 ++++++++++++++++++++++++++++++++++++++--------
src/or/rendclient.h | 13 +++-
9 files changed, 247 insertions(+), 39 deletions(-)
diff --cc src/or/circuituse.c
index f7f080d,f2fd6fe..26bc451
--- a/src/or/circuituse.c
+++ b/src/or/circuituse.c
@@@ -1583,16 -1458,23 +1583,23 @@@ link_apconn_to_circ(entry_connection_t
log_debug(LD_APP|LD_CIRC, "attaching new conn to circ. n_circ_id %d.",
circ->_base.n_circ_id);
/* reset it, so we can measure circ timeouts */
- apconn->_base.timestamp_lastread = time(NULL);
- apconn->next_stream = circ->p_streams;
- apconn->on_circuit = TO_CIRCUIT(circ);
+ ENTRY_TO_CONN(apconn)->timestamp_lastread = time(NULL);
+ ENTRY_TO_EDGE_CONN(apconn)->next_stream = circ->p_streams;
+ ENTRY_TO_EDGE_CONN(apconn)->on_circuit = TO_CIRCUIT(circ);
/* assert_connection_ok(conn, time(NULL)); */
- circ->p_streams = apconn;
+ circ->p_streams = ENTRY_TO_EDGE_CONN(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;
- } else { /* use the last hop in the circuit */
+ } else {
+ /* use the last hop in the circuit */
tor_assert(circ->cpath);
tor_assert(circ->cpath->prev);
tor_assert(circ->cpath->prev->state == CPATH_STATE_OPEN);
diff --cc src/or/connection_edge.c
index f59f44c,0c5ebde..3393104
--- a/src/or/connection_edge.c
+++ b/src/or/connection_edge.c
@@@ -64,16 -62,27 +64,28 @@@ static int connection_ap_supports_optim
* has_sent_end to 1, and mark the conn.
*/
void
-_connection_mark_unattached_ap(edge_connection_t *conn, int endreason,
+_connection_mark_unattached_ap(entry_connection_t *conn, int endreason,
int line, const char *file)
{
- tor_assert(conn->_base.type == CONN_TYPE_AP);
- conn->edge_has_sent_end = 1; /* no circ yet */
+ connection_t *base_conn = ENTRY_TO_CONN(conn);
+ tor_assert(base_conn->type == CONN_TYPE_AP);
+ ENTRY_TO_EDGE_CONN(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) {
+ if (base_conn->marked_for_close) {
/* This call will warn as appropriate. */
- _connection_mark_for_close(TO_CONN(conn), line, file);
+ _connection_mark_for_close(base_conn, line, file);
return;
}
diff --cc src/or/rendclient.c
index 6fe9ba2,e66b242..47fda23
--- a/src/or/rendclient.c
+++ b/src/or/rendclient.c
@@@ -505,16 -541,13 +546,17 @@@ directory_get_from_hs_dir(const char *d
/* Only select those hidden service directories to which we did not send
* a request recently and for which we have a router descriptor here. */
- directory_clean_last_hid_serv_requests(); /* Clean request history first. */
+
+ /* Clean request history first. */
+ directory_clean_last_hid_serv_requests(now);
SMARTLIST_FOREACH(responsible_dirs, routerstatus_t *, dir, {
- time_t last = lookup_last_hid_serv_request(dir, desc_id_base32, 0, 0);
- if (lookup_last_hid_serv_request(dir, desc_id_base32, rend_query, 0, 0) +
- REND_HID_SERV_DIR_REQUERY_PERIOD >= now ||
- !router_get_by_digest(dir->identity_digest))
++ time_t last = lookup_last_hid_serv_request(
++ dir, desc_id_base32, rend_query, 0, 0);
+ const node_t *node = node_get_by_id(dir->identity_digest);
+ if (last + REND_HID_SERV_DIR_REQUERY_PERIOD >= now ||
+ !node || !node_has_descriptor(node))
- SMARTLIST_DEL_CURRENT(responsible_dirs, dir);
+ SMARTLIST_DEL_CURRENT(responsible_dirs, dir);
});
hs_dir = smartlist_choose(responsible_dirs);
@@@ -867,10 -940,36 +951,36 @@@ rend_client_desc_trynow(const char *que
"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);
+ } SMARTLIST_FOREACH_END(base_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; );
+ }
+
+ /* Remove the HS's entries in last_hid_serv_requests. */
+ purge_hid_serv_from_last_hid_serv_requests(onion_address);
+ }
+
/** 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.