diff options
-rw-r--r-- | src/or/directory.c | 1 | ||||
-rw-r--r-- | src/or/hs_client.c | 63 | ||||
-rw-r--r-- | src/or/hs_client.h | 3 |
3 files changed, 67 insertions, 0 deletions
diff --git a/src/or/directory.c b/src/or/directory.c index 9268c3ca2f..f3e76be62f 100644 --- a/src/or/directory.c +++ b/src/or/directory.c @@ -3103,6 +3103,7 @@ handle_response_fetch_hsdesc_v3(dir_connection_t *conn, } else { log_info(LD_REND, "Stored hidden service descriptor successfully."); TO_CONN(conn)->purpose = DIR_PURPOSE_HAS_FETCHED_HSDESC; + hs_client_desc_has_arrived(conn->hs_ident); } break; case 404: diff --git a/src/or/hs_client.c b/src/or/hs_client.c index 2674e2c1e7..cf9bdba5a4 100644 --- a/src/or/hs_client.c +++ b/src/or/hs_client.c @@ -24,6 +24,7 @@ #include "circuituse.h" #include "connection.h" #include "circpathbias.h" +#include "connection.h" /* Get all connections that are waiting on a circuit and flag them back to * waiting for a hidden service descriptor for the given service key @@ -580,3 +581,65 @@ hs_client_receive_rendezvous_acked(origin_circuit_t *circ, return -1; } +/* This is called when a descriptor has arrived following a fetch request and + * has been stored in the client cache. Every entry connection that matches + * the service identity key in the ident will get attached to the hidden + * service circuit. */ +void +hs_client_desc_has_arrived(const hs_ident_dir_conn_t *ident) +{ + time_t now = time(NULL); + smartlist_t *conns = NULL; + + tor_assert(ident); + + conns = connection_list_by_type_state(CONN_TYPE_AP, + AP_CONN_STATE_RENDDESC_WAIT); + SMARTLIST_FOREACH_BEGIN(conns, connection_t *, base_conn) { + const hs_descriptor_t *desc; + entry_connection_t *entry_conn = TO_ENTRY_CONN(base_conn); + const edge_connection_t *edge_conn = ENTRY_TO_EDGE_CONN(entry_conn); + + /* Only consider the entry connections that matches the service for which + * we just fetched its descriptor. */ + if (!edge_conn->hs_ident || + !ed25519_pubkey_eq(&ident->identity_pk, + &edge_conn->hs_ident->identity_pk)) { + continue; + } + assert_connection_ok(base_conn, now); + + /* We were just called because we stored the descriptor for this service + * so not finding a descriptor means we have a bigger problem. */ + desc = hs_cache_lookup_as_client(&ident->identity_pk); + if (BUG(desc == NULL)) { + goto end; + } + + if (!hs_client_any_intro_points_usable(desc)) { + log_info(LD_REND, "Hidden service descriptor is unusable. " + "Closing streams."); + connection_mark_unattached_ap(entry_conn, + END_STREAM_REASON_RESOLVEFAILED); + /* XXX: Note the connection attempt. */ + goto end; + } + + log_info(LD_REND, "Descriptor has arrived. Launching circuits."); + + /* Restart their timeout values, so they get a fair shake at connecting to + * the hidden service. XXX: Improve comment on why this is needed. */ + base_conn->timestamp_created = now; + base_conn->timestamp_lastread = now; + base_conn->timestamp_lastwritten = now; + /* Change connection's state into waiting for a circuit. */ + base_conn->state = AP_CONN_STATE_CIRCUIT_WAIT; + + connection_ap_mark_as_pending_circuit(entry_conn); + } SMARTLIST_FOREACH_END(base_conn); + + end: + /* We don't have ownership of the objects in this list. */ + smartlist_free(conns); +} + diff --git a/src/or/hs_client.h b/src/or/hs_client.h index 0f82a830f4..50d0ad7601 100644 --- a/src/or/hs_client.h +++ b/src/or/hs_client.h @@ -11,6 +11,7 @@ #include "crypto_ed25519.h" #include "hs_descriptor.h" +#include "hs_ident.h" void hs_client_note_connection_attempt_succeeded( const edge_connection_t *conn); @@ -31,5 +32,7 @@ int hs_client_receive_rendezvous_acked(origin_circuit_t *circ, const uint8_t *payload, size_t payload_len); +void hs_client_desc_has_arrived(const hs_ident_dir_conn_t *ident); + #endif /* TOR_HS_CLIENT_H */ |