Loading src/or/circuitbuild.c +2 −2 Original line number Diff line number Diff line Loading @@ -342,7 +342,7 @@ circuit_handle_first_hop(circuit_t *circ) /* imprint the circuit with its future n_conn->id */ memcpy(circ->n_conn_id_digest, firsthop->extend_info->identity_digest, DIGEST_LEN); n_conn = connection_get_by_identity_digest( n_conn = connection_or_get_by_identity_digest( firsthop->extend_info->identity_digest); if (!n_conn || n_conn->state != OR_CONN_STATE_OPEN || (n_conn->is_obsolete && Loading Loading @@ -637,7 +637,7 @@ circuit_extend(cell_t *cell, circuit_t *circ) onionskin = cell->payload+RELAY_HEADER_SIZE+4+2; id_digest = cell->payload+RELAY_HEADER_SIZE+4+2+ONIONSKIN_CHALLENGE_LEN; n_conn = connection_get_by_identity_digest(id_digest); n_conn = connection_or_get_by_identity_digest(id_digest); if (!n_conn || n_conn->state != OR_CONN_STATE_OPEN || (n_conn->is_obsolete && Loading src/or/connection.c +4 −41 Original line number Diff line number Diff line Loading @@ -237,6 +237,10 @@ _connection_free(connection_t *conn) tor_close_socket(conn->s); } if (conn->type == CONN_TYPE_OR && !tor_digest_is_zero(conn->identity_digest)) { connection_or_remove_from_identity_map(conn); } memset(conn, 0xAA, sizeof(connection_t)); /* poison memory */ tor_free(conn); } Loading Loading @@ -1570,47 +1574,6 @@ connection_get_by_type_addr_port_purpose(int type, uint32_t addr, uint16_t port, return NULL; } /** Return the best connection of type OR with the * digest <b>digest</b> that we have, or NULL if we have none. * * 1) Don't return it if it's marked for close. * 2) If there are any open conns, ignore non-open conns. * 3) If there are any non-obsolete conns, ignore obsolete conns. * 4) Then if there are any non-empty conns, ignore empty conns. * 5) Of the remaining conns, prefer newer conns. */ connection_t * connection_get_by_identity_digest(const char *digest) { int i, n, newer; connection_t *conn, *best=NULL; connection_t **carray; get_connection_array(&carray,&n); for (i=0;i<n;i++) { conn = carray[i]; if (conn->marked_for_close || conn->type != CONN_TYPE_OR || memcmp(conn->identity_digest, digest, DIGEST_LEN)) continue; if (!best) { best = conn; /* whatever it is, it's better than nothing. */ continue; } if (best->state == OR_CONN_STATE_OPEN && conn->state != OR_CONN_STATE_OPEN) continue; /* avoid non-open conns if we can */ newer = best->timestamp_created < conn->timestamp_created; if (conn->is_obsolete && (!best->is_obsolete || !newer)) continue; /* we have something, and it's better than this. */ if (best->n_circuits && !conn->n_circuits) continue; /* prefer conns with circuits on them */ if (newer) best = conn; /* lastly, prefer newer conns */ } return best; } /** Return the connection with id <b>id</b> if it is not already * marked for close. */ Loading src/or/connection_or.c +113 −7 Original line number Diff line number Diff line Loading @@ -22,6 +22,71 @@ static int connection_or_process_cells_from_inbuf(connection_t *conn); /**************************************************************/ /** Map from identity digest of connected OR or desired OR to a connection_t * with that identity digest. If there is more than one such connection_t, * they form a linked list, with next_with_same_id as the next pointer.*/ static digestmap_t *orconn_identity_map = NULL; /** If conn is listed in orconn_identity_map, remove it, and clear * conn->identity_digest. */ void connection_or_remove_from_identity_map(connection_t *conn) { connection_t *tmp; tor_assert(conn); tor_assert(conn->type == CONN_TYPE_OR); if (!orconn_identity_map) return; tmp = digestmap_get(orconn_identity_map, conn->identity_digest); if (!tmp) return; if (conn == tmp) { if (conn->next_with_same_id) digestmap_set(orconn_identity_map, conn->identity_digest, conn->next_with_same_id); else digestmap_remove(orconn_identity_map, conn->identity_digest); } else { while (tmp->next_with_same_id) { if (tmp->next_with_same_id == conn) { tmp->next_with_same_id = conn->next_with_same_id; break; } tmp = tmp->next_with_same_id; } } memset(conn->identity_digest, 0, DIGEST_LEN); conn->next_with_same_id = NULL; } /** Change conn->identity_digest to digest, and add conn into * orconn_digest_map. */ static void connection_or_set_identity_digest(connection_t *conn, const char *digest) { connection_t *tmp; tor_assert(conn); tor_assert(conn->type == CONN_TYPE_OR); tor_assert(digest); if (!orconn_identity_map) orconn_identity_map = digestmap_new(); if (!memcmp(conn->identity_digest, digest, DIGEST_LEN)) return; if (tor_digest_is_zero(conn->identity_digest)) connection_or_remove_from_identity_map(conn); memcpy(conn->identity_digest, digest, DIGEST_LEN); tmp = digestmap_set(orconn_identity_map, digest, conn); conn->next_with_same_id = tmp; /* Checking code; remove once I'm sure this works. XXXX*/ for (; tmp; tmp = tmp->next_with_same_id) { tor_assert(!memcmp(tmp->identity_digest, digest, DIGEST_LEN)); tor_assert(tmp != conn); } } /** Pack the cell_t host-order structure <b>src</b> into network-order * in the buffer <b>dest</b>. See tor-spec.txt for details about the * wire format. Loading Loading @@ -227,7 +292,7 @@ connection_or_init_conn_from_router(connection_t *conn, routerinfo_t *router) conn->port = router->or_port; conn->receiver_bucket = conn->bandwidth = (int)options->BandwidthBurst; conn->identity_pkey = crypto_pk_dup_key(router->identity_pkey); crypto_pk_get_digest(conn->identity_pkey, conn->identity_digest); connection_or_set_identity_digest(conn, router->cache_info.identity_digest); conn->nickname = tor_strdup(router->nickname); tor_free(conn->address); conn->address = tor_strdup(router->address); Loading @@ -252,7 +317,7 @@ connection_or_init_conn_from_address(connection_t *conn, conn->port = port; /* This next part isn't really right, but it's good enough for now. */ conn->receiver_bucket = conn->bandwidth = (int)options->BandwidthBurst; memcpy(conn->identity_digest, id_digest, DIGEST_LEN); connection_or_set_identity_digest(conn, id_digest); /* If we're an authoritative directory server, we may know a * nickname for this router. */ n = dirserv_get_nickname_by_digest(id_digest); Loading @@ -268,6 +333,50 @@ connection_or_init_conn_from_address(connection_t *conn, conn->address = tor_dup_addr(addr); } /** Return the best connection of type OR with the * digest <b>digest</b> that we have, or NULL if we have none. * * 1) Don't return it if it's marked for close. * 2) If there are any open conns, ignore non-open conns. * 3) If there are any non-obsolete conns, ignore obsolete conns. * 4) Then if there are any non-empty conns, ignore empty conns. * 5) Of the remaining conns, prefer newer conns. */ connection_t * connection_or_get_by_identity_digest(const char *digest) { int newer; connection_t *conn, *best=NULL; if (!orconn_identity_map) return NULL; conn = digestmap_get(orconn_identity_map, digest); for (; conn; conn = conn->next_with_same_id) { tor_assert(conn->magic == CONNECTION_MAGIC); tor_assert(conn->type == CONN_TYPE_OR); tor_assert(!memcmp(conn->identity_digest, digest, DIGEST_LEN)); if (conn->marked_for_close) continue; if (!best) { best = conn; /* whatever it is, it's better than nothing. */ continue; } if (best->state == OR_CONN_STATE_OPEN && conn->state != OR_CONN_STATE_OPEN) continue; /* avoid non-open conns if we can */ newer = best->timestamp_created < conn->timestamp_created; if (conn->is_obsolete && (!best->is_obsolete || !newer)) continue; /* we have something, and it's better than this. */ if (best->n_circuits && !conn->n_circuits) continue; /* prefer conns with circuits on them */ if (newer) best = conn; /* lastly, prefer newer conns */ } return best; } /** "update an OR connection nickname on the fly" * Actually, nobody calls this. Should we remove it? */ void Loading Loading @@ -419,8 +528,6 @@ connection_tls_continue_handshake(connection_t *conn) return 0; } static char ZERO_DIGEST[] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }; /** Return 1 if we initiated this connection, or 0 if it started * out as an incoming connection. * Loading @@ -431,10 +538,9 @@ static char ZERO_DIGEST[] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }; int connection_or_nonopen_was_started_here(connection_t *conn) { tor_assert(sizeof(ZERO_DIGEST) == DIGEST_LEN); tor_assert(conn->type == CONN_TYPE_OR); if (!memcmp(ZERO_DIGEST, conn->identity_digest, DIGEST_LEN)) if (tor_digest_is_zero(conn->identity_digest)) return 0; else return 1; Loading Loading @@ -560,7 +666,7 @@ connection_tls_finish_handshake(connection_t *conn) if (!connection_or_nonopen_was_started_here(conn)) { #if 0 connection_t *c; if ((c=connection_get_by_identity_digest(digest_rcvd))) { if ((c=connection_or_get_by_identity_digest(digest_rcvd))) { debug(LD_OR,"Router '%s' is already connected on fd %d. Dropping fd %d.", c->nickname, c->s, conn->s); return -1; Loading src/or/dirserv.c +2 −2 Original line number Diff line number Diff line Loading @@ -622,7 +622,7 @@ dirserv_thinks_router_is_reachable(routerinfo_t *router, time_t now) connection_t *conn; if (router_is_me(router) && !we_are_hibernating()) return 1; conn = connection_get_by_identity_digest(router->cache_info.identity_digest); conn = connection_or_get_by_identity_digest(router->cache_info.identity_digest); if (conn && conn->state == OR_CONN_STATE_OPEN) return get_options()->AssumeReachable || now < router->last_reachable + REACHABLE_TIMEOUT; Loading @@ -638,7 +638,7 @@ dirserv_thinks_router_is_blatantly_unreachable(routerinfo_t *router, time_t now) connection_t *conn; if (router->is_hibernating) return 0; conn = connection_get_by_identity_digest(router->cache_info.identity_digest); conn = connection_or_get_by_identity_digest(router->cache_info.identity_digest); if (conn && conn->state == OR_CONN_STATE_OPEN && now >= router->last_reachable + 2*REACHABLE_TIMEOUT && router->testing_since && Loading src/or/or.h +5 −1 Original line number Diff line number Diff line Loading @@ -665,6 +665,8 @@ struct connection_t { * we use? */ int n_circuits; /**< How many circuits use this connection as p_conn or * n_conn ? */ struct connection_t *next_with_same_id; /**< Next connection with same * identity digest as this one. */ /* Used only by DIR and AP connections: */ char rend_query[REND_SERVICE_ID_LEN+1]; /**< What rendezvous service are we Loading Loading @@ -1570,7 +1572,6 @@ void _connection_controller_force_write(connection_t *conn); void connection_write_to_buf(const char *string, size_t len, connection_t *conn); connection_t *connection_or_exact_get_by_addr_port(uint32_t addr, uint16_t port); connection_t *connection_get_by_identity_digest(const char *digest); connection_t *connection_get_by_global_id(uint32_t id); connection_t *connection_get_by_type(int type); Loading Loading @@ -1660,6 +1661,9 @@ hostname_type_t parse_extended_hostname(char *address); /********************************* connection_or.c ***************************/ void connection_or_remove_from_identity_map(connection_t *conn); connection_t *connection_or_get_by_identity_digest(const char *digest); int connection_or_reached_eof(connection_t *conn); int connection_or_process_inbuf(connection_t *conn); int connection_or_finished_flushing(connection_t *conn); Loading Loading
src/or/circuitbuild.c +2 −2 Original line number Diff line number Diff line Loading @@ -342,7 +342,7 @@ circuit_handle_first_hop(circuit_t *circ) /* imprint the circuit with its future n_conn->id */ memcpy(circ->n_conn_id_digest, firsthop->extend_info->identity_digest, DIGEST_LEN); n_conn = connection_get_by_identity_digest( n_conn = connection_or_get_by_identity_digest( firsthop->extend_info->identity_digest); if (!n_conn || n_conn->state != OR_CONN_STATE_OPEN || (n_conn->is_obsolete && Loading Loading @@ -637,7 +637,7 @@ circuit_extend(cell_t *cell, circuit_t *circ) onionskin = cell->payload+RELAY_HEADER_SIZE+4+2; id_digest = cell->payload+RELAY_HEADER_SIZE+4+2+ONIONSKIN_CHALLENGE_LEN; n_conn = connection_get_by_identity_digest(id_digest); n_conn = connection_or_get_by_identity_digest(id_digest); if (!n_conn || n_conn->state != OR_CONN_STATE_OPEN || (n_conn->is_obsolete && Loading
src/or/connection.c +4 −41 Original line number Diff line number Diff line Loading @@ -237,6 +237,10 @@ _connection_free(connection_t *conn) tor_close_socket(conn->s); } if (conn->type == CONN_TYPE_OR && !tor_digest_is_zero(conn->identity_digest)) { connection_or_remove_from_identity_map(conn); } memset(conn, 0xAA, sizeof(connection_t)); /* poison memory */ tor_free(conn); } Loading Loading @@ -1570,47 +1574,6 @@ connection_get_by_type_addr_port_purpose(int type, uint32_t addr, uint16_t port, return NULL; } /** Return the best connection of type OR with the * digest <b>digest</b> that we have, or NULL if we have none. * * 1) Don't return it if it's marked for close. * 2) If there are any open conns, ignore non-open conns. * 3) If there are any non-obsolete conns, ignore obsolete conns. * 4) Then if there are any non-empty conns, ignore empty conns. * 5) Of the remaining conns, prefer newer conns. */ connection_t * connection_get_by_identity_digest(const char *digest) { int i, n, newer; connection_t *conn, *best=NULL; connection_t **carray; get_connection_array(&carray,&n); for (i=0;i<n;i++) { conn = carray[i]; if (conn->marked_for_close || conn->type != CONN_TYPE_OR || memcmp(conn->identity_digest, digest, DIGEST_LEN)) continue; if (!best) { best = conn; /* whatever it is, it's better than nothing. */ continue; } if (best->state == OR_CONN_STATE_OPEN && conn->state != OR_CONN_STATE_OPEN) continue; /* avoid non-open conns if we can */ newer = best->timestamp_created < conn->timestamp_created; if (conn->is_obsolete && (!best->is_obsolete || !newer)) continue; /* we have something, and it's better than this. */ if (best->n_circuits && !conn->n_circuits) continue; /* prefer conns with circuits on them */ if (newer) best = conn; /* lastly, prefer newer conns */ } return best; } /** Return the connection with id <b>id</b> if it is not already * marked for close. */ Loading
src/or/connection_or.c +113 −7 Original line number Diff line number Diff line Loading @@ -22,6 +22,71 @@ static int connection_or_process_cells_from_inbuf(connection_t *conn); /**************************************************************/ /** Map from identity digest of connected OR or desired OR to a connection_t * with that identity digest. If there is more than one such connection_t, * they form a linked list, with next_with_same_id as the next pointer.*/ static digestmap_t *orconn_identity_map = NULL; /** If conn is listed in orconn_identity_map, remove it, and clear * conn->identity_digest. */ void connection_or_remove_from_identity_map(connection_t *conn) { connection_t *tmp; tor_assert(conn); tor_assert(conn->type == CONN_TYPE_OR); if (!orconn_identity_map) return; tmp = digestmap_get(orconn_identity_map, conn->identity_digest); if (!tmp) return; if (conn == tmp) { if (conn->next_with_same_id) digestmap_set(orconn_identity_map, conn->identity_digest, conn->next_with_same_id); else digestmap_remove(orconn_identity_map, conn->identity_digest); } else { while (tmp->next_with_same_id) { if (tmp->next_with_same_id == conn) { tmp->next_with_same_id = conn->next_with_same_id; break; } tmp = tmp->next_with_same_id; } } memset(conn->identity_digest, 0, DIGEST_LEN); conn->next_with_same_id = NULL; } /** Change conn->identity_digest to digest, and add conn into * orconn_digest_map. */ static void connection_or_set_identity_digest(connection_t *conn, const char *digest) { connection_t *tmp; tor_assert(conn); tor_assert(conn->type == CONN_TYPE_OR); tor_assert(digest); if (!orconn_identity_map) orconn_identity_map = digestmap_new(); if (!memcmp(conn->identity_digest, digest, DIGEST_LEN)) return; if (tor_digest_is_zero(conn->identity_digest)) connection_or_remove_from_identity_map(conn); memcpy(conn->identity_digest, digest, DIGEST_LEN); tmp = digestmap_set(orconn_identity_map, digest, conn); conn->next_with_same_id = tmp; /* Checking code; remove once I'm sure this works. XXXX*/ for (; tmp; tmp = tmp->next_with_same_id) { tor_assert(!memcmp(tmp->identity_digest, digest, DIGEST_LEN)); tor_assert(tmp != conn); } } /** Pack the cell_t host-order structure <b>src</b> into network-order * in the buffer <b>dest</b>. See tor-spec.txt for details about the * wire format. Loading Loading @@ -227,7 +292,7 @@ connection_or_init_conn_from_router(connection_t *conn, routerinfo_t *router) conn->port = router->or_port; conn->receiver_bucket = conn->bandwidth = (int)options->BandwidthBurst; conn->identity_pkey = crypto_pk_dup_key(router->identity_pkey); crypto_pk_get_digest(conn->identity_pkey, conn->identity_digest); connection_or_set_identity_digest(conn, router->cache_info.identity_digest); conn->nickname = tor_strdup(router->nickname); tor_free(conn->address); conn->address = tor_strdup(router->address); Loading @@ -252,7 +317,7 @@ connection_or_init_conn_from_address(connection_t *conn, conn->port = port; /* This next part isn't really right, but it's good enough for now. */ conn->receiver_bucket = conn->bandwidth = (int)options->BandwidthBurst; memcpy(conn->identity_digest, id_digest, DIGEST_LEN); connection_or_set_identity_digest(conn, id_digest); /* If we're an authoritative directory server, we may know a * nickname for this router. */ n = dirserv_get_nickname_by_digest(id_digest); Loading @@ -268,6 +333,50 @@ connection_or_init_conn_from_address(connection_t *conn, conn->address = tor_dup_addr(addr); } /** Return the best connection of type OR with the * digest <b>digest</b> that we have, or NULL if we have none. * * 1) Don't return it if it's marked for close. * 2) If there are any open conns, ignore non-open conns. * 3) If there are any non-obsolete conns, ignore obsolete conns. * 4) Then if there are any non-empty conns, ignore empty conns. * 5) Of the remaining conns, prefer newer conns. */ connection_t * connection_or_get_by_identity_digest(const char *digest) { int newer; connection_t *conn, *best=NULL; if (!orconn_identity_map) return NULL; conn = digestmap_get(orconn_identity_map, digest); for (; conn; conn = conn->next_with_same_id) { tor_assert(conn->magic == CONNECTION_MAGIC); tor_assert(conn->type == CONN_TYPE_OR); tor_assert(!memcmp(conn->identity_digest, digest, DIGEST_LEN)); if (conn->marked_for_close) continue; if (!best) { best = conn; /* whatever it is, it's better than nothing. */ continue; } if (best->state == OR_CONN_STATE_OPEN && conn->state != OR_CONN_STATE_OPEN) continue; /* avoid non-open conns if we can */ newer = best->timestamp_created < conn->timestamp_created; if (conn->is_obsolete && (!best->is_obsolete || !newer)) continue; /* we have something, and it's better than this. */ if (best->n_circuits && !conn->n_circuits) continue; /* prefer conns with circuits on them */ if (newer) best = conn; /* lastly, prefer newer conns */ } return best; } /** "update an OR connection nickname on the fly" * Actually, nobody calls this. Should we remove it? */ void Loading Loading @@ -419,8 +528,6 @@ connection_tls_continue_handshake(connection_t *conn) return 0; } static char ZERO_DIGEST[] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }; /** Return 1 if we initiated this connection, or 0 if it started * out as an incoming connection. * Loading @@ -431,10 +538,9 @@ static char ZERO_DIGEST[] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }; int connection_or_nonopen_was_started_here(connection_t *conn) { tor_assert(sizeof(ZERO_DIGEST) == DIGEST_LEN); tor_assert(conn->type == CONN_TYPE_OR); if (!memcmp(ZERO_DIGEST, conn->identity_digest, DIGEST_LEN)) if (tor_digest_is_zero(conn->identity_digest)) return 0; else return 1; Loading Loading @@ -560,7 +666,7 @@ connection_tls_finish_handshake(connection_t *conn) if (!connection_or_nonopen_was_started_here(conn)) { #if 0 connection_t *c; if ((c=connection_get_by_identity_digest(digest_rcvd))) { if ((c=connection_or_get_by_identity_digest(digest_rcvd))) { debug(LD_OR,"Router '%s' is already connected on fd %d. Dropping fd %d.", c->nickname, c->s, conn->s); return -1; Loading
src/or/dirserv.c +2 −2 Original line number Diff line number Diff line Loading @@ -622,7 +622,7 @@ dirserv_thinks_router_is_reachable(routerinfo_t *router, time_t now) connection_t *conn; if (router_is_me(router) && !we_are_hibernating()) return 1; conn = connection_get_by_identity_digest(router->cache_info.identity_digest); conn = connection_or_get_by_identity_digest(router->cache_info.identity_digest); if (conn && conn->state == OR_CONN_STATE_OPEN) return get_options()->AssumeReachable || now < router->last_reachable + REACHABLE_TIMEOUT; Loading @@ -638,7 +638,7 @@ dirserv_thinks_router_is_blatantly_unreachable(routerinfo_t *router, time_t now) connection_t *conn; if (router->is_hibernating) return 0; conn = connection_get_by_identity_digest(router->cache_info.identity_digest); conn = connection_or_get_by_identity_digest(router->cache_info.identity_digest); if (conn && conn->state == OR_CONN_STATE_OPEN && now >= router->last_reachable + 2*REACHABLE_TIMEOUT && router->testing_since && Loading
src/or/or.h +5 −1 Original line number Diff line number Diff line Loading @@ -665,6 +665,8 @@ struct connection_t { * we use? */ int n_circuits; /**< How many circuits use this connection as p_conn or * n_conn ? */ struct connection_t *next_with_same_id; /**< Next connection with same * identity digest as this one. */ /* Used only by DIR and AP connections: */ char rend_query[REND_SERVICE_ID_LEN+1]; /**< What rendezvous service are we Loading Loading @@ -1570,7 +1572,6 @@ void _connection_controller_force_write(connection_t *conn); void connection_write_to_buf(const char *string, size_t len, connection_t *conn); connection_t *connection_or_exact_get_by_addr_port(uint32_t addr, uint16_t port); connection_t *connection_get_by_identity_digest(const char *digest); connection_t *connection_get_by_global_id(uint32_t id); connection_t *connection_get_by_type(int type); Loading Loading @@ -1660,6 +1661,9 @@ hostname_type_t parse_extended_hostname(char *address); /********************************* connection_or.c ***************************/ void connection_or_remove_from_identity_map(connection_t *conn); connection_t *connection_or_get_by_identity_digest(const char *digest); int connection_or_reached_eof(connection_t *conn); int connection_or_process_inbuf(connection_t *conn); int connection_or_finished_flushing(connection_t *conn); Loading