diff options
-rw-r--r-- | src/or/circuituse.c | 16 | ||||
-rw-r--r-- | src/or/connection.c | 9 | ||||
-rw-r--r-- | src/or/cpuworker.c | 2 | ||||
-rw-r--r-- | src/or/directory.c | 2 | ||||
-rw-r--r-- | src/or/or.h | 4 | ||||
-rw-r--r-- | src/or/rendclient.c | 40 | ||||
-rw-r--r-- | src/or/rendcommon.c | 7 |
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 |