summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/or/circuituse.c16
-rw-r--r--src/or/connection.c9
-rw-r--r--src/or/cpuworker.c2
-rw-r--r--src/or/directory.c2
-rw-r--r--src/or/or.h4
-rw-r--r--src/or/rendclient.c40
-rw-r--r--src/or/rendcommon.c7
7 files changed, 45 insertions, 35 deletions
diff --git a/src/or/circuituse.c b/src/or/circuituse.c
index f5e85adcc4..d7295596d4 100644
--- a/src/or/circuituse.c
+++ b/src/or/circuituse.c
@@ -817,18 +817,22 @@ circuit_get_open_circ_or_launch(connection_t *conn,
if (desired_circuit_purpose == CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT) {
/* need to pick an intro point */
+try_an_intro_point:
exitname = rend_client_get_random_intro(conn->rend_query);
if (!exitname) {
- log_fn(LOG_WARN,"Couldn't get an intro point for '%s'. Closing.",
+ log_fn(LOG_INFO,"No intro points for '%s': refetching service descriptor.",
conn->rend_query);
- return -1;
+ rend_client_refetch_renddesc(conn->rend_query);
+ conn->state = AP_CONN_STATE_RENDDESC_WAIT;
+ return 0;
}
if (!router_get_by_nickname(exitname)) {
- log_fn(LOG_WARN,"Advertised intro point '%s' is not known. Closing.", exitname);
+ log_fn(LOG_NOTICE,"Advertised intro point '%s' is not recognized for '%s'. Skipping over.",
+ exitname, conn->rend_query);
+ rend_client_remove_intro_point(exitname, conn->rend_query);
tor_free(exitname);
- return -1;
+ goto try_an_intro_point;
}
- /* XXX if we failed, then refetch the descriptor */
log_fn(LOG_INFO,"Chose %s as intro point for %s.", exitname, conn->rend_query);
}
@@ -839,7 +843,7 @@ circuit_get_open_circ_or_launch(connection_t *conn,
if (conn->chosen_exit_name) {
exitname = tor_strdup(conn->chosen_exit_name);
if (!router_get_by_nickname(exitname)) {
- log_fn(LOG_WARN,"Requested exit point '%s' is not known. Closing.", exitname);
+ log_fn(LOG_NOTICE,"Requested exit point '%s' is not known. Closing.", exitname);
tor_free(exitname);
return -1;
}
diff --git a/src/or/connection.c b/src/or/connection.c
index 459542e32c..7aa6fc5d9c 100644
--- a/src/or/connection.c
+++ b/src/or/connection.c
@@ -219,7 +219,7 @@ void connection_about_to_close_connection(connection_t *conn)
connection_dir_connect_failed(conn);
}
if (conn->purpose == DIR_PURPOSE_FETCH_RENDDESC)
- rend_client_desc_fetched(conn->rend_query, 0);
+ rend_client_desc_here(conn->rend_query); /* give it a try */
break;
case CONN_TYPE_OR:
/* Remember why we're closing this connection. */
@@ -1243,9 +1243,11 @@ connection_t *connection_get_by_type_state_lastwritten(int type, int state) {
}
/** Return a connection of type <b>type</b> that has rendquery equal
- * to <b>rendquery</b>, and that is not marked for close.
+ * to <b>rendquery</b>, and that is not marked for close. If state
+ * is non-zero, conn must be of that state too.
*/
-connection_t *connection_get_by_type_rendquery(int type, const char *rendquery) {
+connection_t *
+connection_get_by_type_state_rendquery(int type, int state, const char *rendquery) {
int i, n;
connection_t *conn;
connection_t **carray;
@@ -1255,6 +1257,7 @@ connection_t *connection_get_by_type_rendquery(int type, const char *rendquery)
conn = carray[i];
if (conn->type == type &&
!conn->marked_for_close &&
+ (!state || state == conn->state) &&
!rend_cmp_service_ids(rendquery, conn->rend_query))
return conn;
}
diff --git a/src/or/cpuworker.c b/src/or/cpuworker.c
index 4ca69c2293..c198325b86 100644
--- a/src/or/cpuworker.c
+++ b/src/or/cpuworker.c
@@ -227,7 +227,7 @@ static int cpuworker_main(void *data) {
if (r == 0) {
log_fn(LOG_INFO,"CPU worker exiting because Tor process closed connection (either rotated keys or died).");
} else {
- log_fn(LOG_INFO,"CPU worker editing because of error on connection To Tor process.");
+ log_fn(LOG_INFO,"CPU worker editing because of error on connection to Tor process.");
log_fn(LOG_INFO,"(Error on %d was %s)", fd, tor_socket_strerror(tor_socket_errno(fd)));
}
goto end;
diff --git a/src/or/directory.c b/src/or/directory.c
index 4aedbf8b6f..dc12d056db 100644
--- a/src/or/directory.c
+++ b/src/or/directory.c
@@ -746,8 +746,8 @@ connection_dir_client_reached_eof(connection_t *conn)
* cleans it up */
} else {
/* success. notify pending connections about this. */
- rend_client_desc_fetched(conn->rend_query, 1);
conn->purpose = DIR_PURPOSE_HAS_FETCHED_RENDDESC;
+ rend_client_desc_here(conn->rend_query);
}
break;
case 404:
diff --git a/src/or/or.h b/src/or/or.h
index 6c951add11..30ee523337 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -1206,7 +1206,7 @@ connection_t *connection_get_by_identity_digest(const char *digest, int type);
connection_t *connection_get_by_type(int type);
connection_t *connection_get_by_type_state(int type, int state);
connection_t *connection_get_by_type_state_lastwritten(int type, int state);
-connection_t *connection_get_by_type_rendquery(int type, const char *rendquery);
+connection_t *connection_get_by_type_state_rendquery(int type, int state, const char *rendquery);
#define connection_speaks_cells(conn) ((conn)->type == CONN_TYPE_OR)
#define connection_has_pending_tls_data(conn) \
@@ -1495,7 +1495,7 @@ void rend_client_refetch_renddesc(const char *query);
int rend_client_remove_intro_point(char *failed_intro, const char *query);
int rend_client_rendezvous_acked(circuit_t *circ, const char *request, size_t request_len);
int rend_client_receive_rendezvous(circuit_t *circ, const char *request, size_t request_len);
-void rend_client_desc_fetched(char *query, int status);
+void rend_client_desc_here(char *query);
char *rend_client_get_random_intro(char *query);
diff --git a/src/or/rendclient.c b/src/or/rendclient.c
index c7c9e1ee3f..7111dadda6 100644
--- a/src/or/rendclient.c
+++ b/src/or/rendclient.c
@@ -239,7 +239,7 @@ rend_client_introduction_acked(circuit_t *circ,
void
rend_client_refetch_renddesc(const char *query)
{
- if (connection_get_by_type_rendquery(CONN_TYPE_DIR, query)) {
+ if (connection_get_by_type_state_rendquery(CONN_TYPE_DIR, 0, query)) {
log_fn(LOG_INFO,"Would fetch a new renddesc here (for %s), but one is already in progress.", query);
} else {
/* not one already; initiate a dir rend desc lookup */
@@ -258,6 +258,7 @@ rend_client_remove_intro_point(char *failed_intro, const char *query)
{
int i, r;
rend_cache_entry_t *ent;
+ connection_t *conn;
r = rend_cache_lookup_entry(query, &ent);
if (r<0) {
@@ -282,6 +283,13 @@ rend_client_remove_intro_point(char *failed_intro, const char *query)
if (!ent->parsed->n_intro_points) {
log_fn(LOG_INFO,"No more intro points remain for %s. Re-fetching descriptor.", query);
rend_client_refetch_renddesc(query);
+
+ /* move all pending streams back to renddesc_wait */
+ while ((conn = connection_get_by_type_state_rendquery(CONN_TYPE_AP,
+ AP_CONN_STATE_CIRCUIT_WAIT, query))) {
+ conn->state = AP_CONN_STATE_RENDDESC_WAIT;
+ }
+
return 0;
}
log_fn(LOG_INFO,"%d options left for %s.", ent->parsed->n_intro_points, query);
@@ -366,30 +374,21 @@ rend_client_receive_rendezvous(circuit_t *circ, const char *request, size_t requ
}
/** Find all the apconns in state AP_CONN_STATE_RENDDESC_WAIT that
- * are waiting on query. If status==1, move them to the next state.
- * If status==0, fail them.
+ * are waiting on query. If there's a working cache entry here
+ * with at least one intro point, move them to the next state;
+ * else fail them.
*/
-void rend_client_desc_fetched(char *query, int status) {
- connection_t **carray;
+void rend_client_desc_here(char *query) {
connection_t *conn;
- int n, i;
rend_cache_entry_t *entry;
- get_connection_array(&carray, &n);
-
- for (i = 0; i < n; ++i) {
- conn = carray[i];
- if (conn->type != CONN_TYPE_AP ||
- conn->state != AP_CONN_STATE_RENDDESC_WAIT)
- continue;
- if (rend_cmp_service_ids(conn->rend_query, query))
- continue;
- /* great, this guy was waiting */
- if (status!=0 ||
- rend_cache_lookup_entry(conn->rend_query, &entry) == 1) {
+ while ((conn = connection_get_by_type_state_rendquery(CONN_TYPE_AP,
+ AP_CONN_STATE_RENDDESC_WAIT, query))) {
+ if (rend_cache_lookup_entry(conn->rend_query, &entry) == 1 &&
+ entry->parsed->n_intro_points > 0) {
/* either this fetch worked, or it failed but there was a
* valid entry from before which we should reuse */
- log_fn(LOG_INFO,"Rend desc retrieved. Launching circuits.");
+ log_fn(LOG_INFO,"Rend desc is usable. Launching circuits.");
conn->state = AP_CONN_STATE_CIRCUIT_WAIT;
if (connection_ap_handshake_attach_circuit(conn) < 0) {
/* it will never work */
@@ -397,8 +396,9 @@ void rend_client_desc_fetched(char *query, int status) {
conn->has_sent_end = 1;
connection_mark_for_close(conn);
}
+ tor_assert(conn->state != AP_CONN_STATE_RENDDESC_WAIT); /* avoid loop */
} else { /* 404, or fetch didn't get that far */
- log_fn(LOG_NOTICE,"Failed to fetch service id '%s', and not in cache. Closing conn.", query);
+ log_fn(LOG_NOTICE,"Closing stream for '%s.onion': hidden service is unavailable (try again later).", query);
conn->has_sent_end = 1;
connection_mark_for_close(conn);
}
diff --git a/src/or/rendcommon.c b/src/or/rendcommon.c
index 7b47667bc5..090b803785 100644
--- a/src/or/rendcommon.c
+++ b/src/or/rendcommon.c
@@ -242,7 +242,9 @@ int rend_cache_lookup_desc(const char *query, const char **desc, size_t *desc_le
/** Parse *desc, calculate its service id, and store it in the cache.
* If we have a newer descriptor with the same ID, ignore this one.
* If we have an older descriptor with the same ID, replace it.
- * Returns -1 if it's malformed or otherwise rejected, else return 0.
+ * Return -1 if it's malformed or otherwise rejected; return 0 if
+ * it's the same or older than one we've already got; return 1 if
+ * it's novel.
*/
int rend_cache_store(const char *desc, size_t desc_len)
{
@@ -250,6 +252,7 @@ int rend_cache_store(const char *desc, size_t desc_len)
rend_service_descriptor_t *parsed;
char query[REND_SERVICE_ID_LEN+1];
time_t now;
+
tor_assert(rend_cache);
parsed = rend_parse_service_descriptor(desc,desc_len);
if (!parsed) {
@@ -298,7 +301,7 @@ int rend_cache_store(const char *desc, size_t desc_len)
memcpy(e->desc, desc, desc_len);
log_fn(LOG_INFO,"Successfully stored rend desc '%s', len %d", query, (int)desc_len);
- return 0;
+ return 1;
}
/** Called when we get a rendezvous-related relay cell on circuit