commit 4aa4bce474e6fb3e52c0aecb48f3e5024576e693 Merge: a7f93b5 c5226bf Author: Nick Mathewson nickm@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.
tor-commits@lists.torproject.org