diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c index 4862442678..9d2b77286b 100644 --- a/src/or/circuitbuild.c +++ b/src/or/circuitbuild.c @@ -19,14 +19,13 @@ extern circuit_t *global_circuitlist; /********* END VARIABLES ************/ -static int -circuit_deliver_create_cell(circuit_t *circ, char *payload); -static cpath_build_state_t * -onion_new_cpath_build_state(uint8_t purpose, const char *exit_digest, - int need_uptime, int need_capacity, int internal); -static int onion_extend_cpath(crypt_path_t **head_ptr, - cpath_build_state_t *state, routerinfo_t **router_out); +static int circuit_deliver_create_cell(circuit_t *circ, char *payload); +static int onion_pick_cpath_exit(circuit_t *circ, routerinfo_t *exit); +static crypt_path_t *onion_next_hop_in_cpath(crypt_path_t *cpath); +static int onion_next_router_in_cpath(circuit_t *circ, routerinfo_t **router); +static int onion_extend_cpath(crypt_path_t **head_ptr, cpath_build_state_t *state); static int count_acceptable_routers(smartlist_t *routers); +static int onion_append_hop(crypt_path_t **head_ptr, routerinfo_t *choice); /** Iterate over values of circ_id, starting from conn-\>next_circ_id, * and with the high bit specified by circ_id_type (see @@ -229,7 +228,39 @@ void circuit_dump_by_conn(connection_t *conn, int severity) { } } -/** Build a new circuit for purpose. If exit_digest +/** Pick all the entries in our cpath. Stop and return 0 when we're + * happy, or return -1 if an error occurs. */ +static int +onion_populate_cpath(circuit_t *circ) { + int r; +again: + r = onion_extend_cpath(&circ->cpath, circ->build_state); +// || !CIRCUIT_IS_ORIGIN(circ)) { // wtf? -rd + if (r < 0) { + log_fn(LOG_INFO,"Generating cpath hop failed."); + circuit_mark_for_close(circ); + return -1; + } + if (r == 0) + goto again; + return 0; /* if r == 1 */ +} + +/** Create and return new circuit. Initialize its purpose and + * build-state based on our arguments. */ +circuit_t * +circuit_init(uint8_t purpose, int need_uptime, int need_capacity, int internal) { + circuit_t *circ = circuit_new(0, NULL); /* sets circ->p_circ_id and circ->p_conn */ + circ->state = CIRCUIT_STATE_OR_WAIT; + circ->build_state = tor_malloc_zero(sizeof(cpath_build_state_t)); + circ->build_state->need_uptime = need_uptime; + circ->build_state->need_capacity = need_capacity; + circ->build_state->is_internal = internal; + circ->purpose = purpose; + return circ; +} + +/** Build a new circuit for purpose. If exit * is defined, then use that as your exit router, else choose a suitable * exit node. * @@ -237,36 +268,39 @@ void circuit_dump_by_conn(connection_t *conn, int severity) { * it's not open already. */ circuit_t * -circuit_establish_circuit(uint8_t purpose, const char *exit_digest, +circuit_establish_circuit(uint8_t purpose, routerinfo_t *exit, int need_uptime, int need_capacity, int internal) { - routerinfo_t *firsthop; - connection_t *n_conn; circuit_t *circ; - circ = circuit_new(0, NULL); /* sets circ->p_circ_id and circ->p_conn */ - circ->state = CIRCUIT_STATE_OR_WAIT; - circ->build_state = onion_new_cpath_build_state(purpose, exit_digest, - need_uptime, need_capacity, internal); - circ->purpose = purpose; + circ = circuit_init(purpose, need_uptime, need_capacity, internal); - if (! circ->build_state) { - log_fn(LOG_INFO,"Generating cpath failed."); - circuit_mark_for_close(circ); - return NULL; - } - - if (onion_extend_cpath(&circ->cpath, circ->build_state, &firsthop)<0 || - !CIRCUIT_IS_ORIGIN(circ)) { - log_fn(LOG_INFO,"Generating first cpath hop failed."); + if (onion_pick_cpath_exit(circ, exit) < 0 || + onion_populate_cpath(circ) < 0) { circuit_mark_for_close(circ); return NULL; } control_event_circuit_status(circ, CIRC_EVENT_LAUNCHED); - /* now see if we're already connected to the first OR in 'route' */ + if (circuit_handle_first_hop(circ) < 0) { + circuit_mark_for_close(circ); + return NULL; + } + return circ; +} +/** Start establishing the first hop of our circuit. Figure out what + * OR we should connect to, and if necessary start the connection to + * it. If we're already connected, then send the 'create' cell. + * Return 0 for ok, -1 if circ should be marked-for-close. */ +int circuit_handle_first_hop(circuit_t *circ) { + routerinfo_t *firsthop; + connection_t *n_conn; + + onion_next_router_in_cpath(circ, &firsthop); tor_assert(firsthop); + + /* now see if we're already connected to the first OR in 'route' */ log_fn(LOG_DEBUG,"Looking for firsthop '%s:%u'", firsthop->address,firsthop->or_port); /* imprint the circuit with its future n_conn->id */ @@ -282,8 +316,7 @@ circuit_establish_circuit(uint8_t purpose, const char *exit_digest, firsthop->identity_digest); if (!n_conn) { /* connect failed, forget the whole thing */ log_fn(LOG_INFO,"connect to firsthop failed. Closing."); - circuit_mark_for_close(circ); - return NULL; + return -1; } } @@ -291,7 +324,7 @@ circuit_establish_circuit(uint8_t purpose, const char *exit_digest, /* return success. The onion/circuit/etc will be taken care of automatically * (may already have been) whenever n_conn reaches OR_CONN_STATE_OPEN. */ - return circ; + return 0; } else { /* it's already open. use it. */ circ->n_addr = n_conn->addr; circ->n_port = n_conn->port; @@ -299,11 +332,10 @@ circuit_establish_circuit(uint8_t purpose, const char *exit_digest, log_fn(LOG_DEBUG,"Conn open. Delivering first onion skin."); if (circuit_send_next_onion_skin(circ) < 0) { log_fn(LOG_INFO,"circuit_send_next_onion_skin failed."); - circuit_mark_for_close(circ); - return NULL; + return -1; } } - return circ; + return 0; } /** Find circuits that are waiting on or_conn to become open, @@ -425,8 +457,8 @@ int circuit_send_next_onion_skin(circuit_t *circ) { tor_assert(circ->cpath->state == CPATH_STATE_OPEN); tor_assert(circ->state == CIRCUIT_STATE_BUILDING); log_fn(LOG_DEBUG,"starting to send subsequent skin."); - r = onion_extend_cpath(&circ->cpath, circ->build_state, &router); - if (r==1) { + r = onion_next_router_in_cpath(circ, &router); + if (r > 0) { /* done building the circuit. whew. */ circ->state = CIRCUIT_STATE_OPEN; log_fn(LOG_INFO,"circuit built!"); @@ -439,11 +471,10 @@ int circuit_send_next_onion_skin(circuit_t *circ) { circuit_rep_hist_note_result(circ); circuit_has_opened(circ); /* do other actions as necessary */ return 0; - } else if (r<0) { - log_fn(LOG_INFO,"Unable to extend circuit path."); + } else if (r < 0) { return -1; } - hop = circ->cpath->prev; + hop = onion_next_hop_in_cpath(circ->cpath); *(uint32_t*)payload = htonl(hop->addr); *(uint16_t*)(payload+4) = htons(hop->port); @@ -469,6 +500,9 @@ int circuit_send_next_onion_skin(circuit_t *circ) { return 0; } +/** Our clock just jumped forward by seconds_elapsed. Assume + * something has also gone wrong with our network: notify the user, + * and abandon all not-yet-used circuits. */ void circuit_note_clock_jumped(int seconds_elapsed) { log_fn(LOG_NOTICE,"Your clock just jumped %d seconds forward; assuming established circuits no longer work.", seconds_elapsed); has_completed_circuit=0; /* so it'll log when it works again */ @@ -620,10 +654,8 @@ int circuit_finish_handshake(circuit_t *circ, char *reply) { if (circ->cpath->state == CPATH_STATE_AWAITING_KEYS) hop = circ->cpath; else { - for (hop=circ->cpath->next; - hop != circ->cpath && hop->state == CPATH_STATE_OPEN; - hop=hop->next) ; - if (hop == circ->cpath) { /* got an extended when we're all done? */ + hop = onion_next_hop_in_cpath(circ->cpath); + if (!hop) { /* got an extended when we're all done? */ log_fn(LOG_WARN,"got extended when circ already built? Closing."); return -1; } @@ -646,7 +678,7 @@ int circuit_finish_handshake(circuit_t *circ, char *reply) { } hop->state = CPATH_STATE_OPEN; - log_fn(LOG_INFO,"Finished building circuit:"); + log_fn(LOG_INFO,"Finished building circuit hop:"); circuit_log_path(LOG_INFO,circ); control_event_circuit_status(circ, CIRC_EVENT_EXTENDED); @@ -1101,81 +1133,53 @@ choose_good_exit_server(uint8_t purpose, routerlist_t *dir, return NULL; } -/** Allocate a cpath_build_state_t, populate it based on - * purpose and exit_digest (if specified), and - * return it. - */ -static cpath_build_state_t * -onion_new_cpath_build_state(uint8_t purpose, const char *exit_digest, - int need_uptime, int need_capacity, int internal) -{ +/** Decide a suitable length for circ's cpath, and pick an exit + * router (or use exit if provided). Store these in the + * cpath. Return 0 if ok, -1 if circuit should be closed. */ +static int +onion_pick_cpath_exit(circuit_t *circ, routerinfo_t *exit) { + cpath_build_state_t *state = circ->build_state; + routerlist_t *rl; int r; - cpath_build_state_t *info; - routerinfo_t *exit; router_get_routerlist(&rl); - if (!rl) - return NULL; - r = new_route_len(get_options()->PathlenCoinWeight, purpose, rl->routers); + if (!rl) { + log_fn(LOG_WARN,"router_get_routerlist returned empty list; closing circ."); + return -1; + } + r = new_route_len(get_options()->PathlenCoinWeight, circ->purpose, rl->routers); if (r < 1) /* must be at least 1 */ - return NULL; - info = tor_malloc_zero(sizeof(cpath_build_state_t)); - info->desired_path_len = r; - info->need_uptime = need_uptime; - info->need_capacity = need_capacity; - info->is_internal = internal; - if (exit_digest) { /* the circuit-builder pre-requested one */ - memcpy(info->chosen_exit_digest, exit_digest, DIGEST_LEN); - exit = router_get_by_digest(exit_digest); - if (exit) { - info->chosen_exit_name = tor_strdup(exit->nickname); - } else { - info->chosen_exit_name = tor_malloc(HEX_DIGEST_LEN+1); - base16_encode(info->chosen_exit_name, HEX_DIGEST_LEN+1, - exit_digest, DIGEST_LEN); - } - log_fn(LOG_INFO,"Using requested exit node '%s'", info->chosen_exit_name); + return -1; + state->desired_path_len = r; + + if (exit) { /* the circuit-builder pre-requested one */ + log_fn(LOG_INFO,"Using requested exit node '%s'", exit->nickname); } else { /* we have to decide one */ - exit = choose_good_exit_server(purpose, rl, need_uptime, need_capacity); + exit = choose_good_exit_server(circ->purpose, rl, + state->need_uptime, state->need_capacity); if (!exit) { log_fn(LOG_WARN,"failed to choose an exit server"); - tor_free(info); - return NULL; + return -1; } - memcpy(info->chosen_exit_digest, exit->identity_digest, DIGEST_LEN); - info->chosen_exit_name = tor_strdup(exit->nickname); } - return info; + memcpy(state->chosen_exit_digest, exit->identity_digest, DIGEST_LEN); + state->chosen_exit_name = tor_strdup(exit->nickname); + return 0; } /** Take the open circ originating here, give it a new exit destination - * to exit_digest (use nickname directly if it's provided, else strdup - * out of router->nickname), and get it to send the next extend cell. + * to exit, and get it to send the next extend cell. */ int -circuit_append_new_hop(circuit_t *circ, char *nickname, const char *exit_digest) { - routerinfo_t *exit = router_get_by_digest(exit_digest); - tor_assert(CIRCUIT_IS_ORIGIN(circ)); - circ->state = CIRCUIT_STATE_BUILDING; +circuit_append_new_exit(circuit_t *circ, routerinfo_t *exit) { + tor_assert(exit); + tor_assert(circ && CIRCUIT_IS_ORIGIN(circ)); tor_free(circ->build_state->chosen_exit_name); - if (nickname) { - circ->build_state->chosen_exit_name = nickname; - } else if (exit) { - circ->build_state->chosen_exit_name = tor_strdup(exit->nickname); - } else { - circ->build_state->chosen_exit_name = tor_malloc(HEX_DIGEST_LEN+1); - base16_encode(circ->build_state->chosen_exit_name, HEX_DIGEST_LEN+1, - exit_digest, DIGEST_LEN); - } - memcpy(circ->build_state->chosen_exit_digest, exit_digest, DIGEST_LEN); + circ->build_state->chosen_exit_name = tor_strdup(exit->nickname); + memcpy(circ->build_state->chosen_exit_digest, exit->identity_digest, DIGEST_LEN); ++circ->build_state->desired_path_len; - if (circuit_send_next_onion_skin(circ)<0) { - log_fn(LOG_WARN, "Couldn't extend circuit to new point '%s'.", - circ->build_state->chosen_exit_name); - circuit_mark_for_close(circ); - return -1; - } + onion_append_hop(&circ->cpath, exit); return 0; } @@ -1296,21 +1300,52 @@ static routerinfo_t *choose_good_entry_server(cpath_build_state_t *state) return choice; } -/** Choose a suitable next hop in the cpath head_ptr, - * based on state. Add the hop info to head_ptr, and return a - * pointer to the chosen router in router_out. +/** Return the first non-open hop in cpath, or return NULL if all + * hops are open. */ +static crypt_path_t * +onion_next_hop_in_cpath(crypt_path_t *cpath) { + crypt_path_t *hop = cpath; + do { + if (hop->state != CPATH_STATE_OPEN) + return hop; + hop = hop->next; + } while (hop != cpath); + return NULL; +} + +/** Find the router corresponding to the first non-open hop in + * circ->cpath. Make sure it's state closed. Return 1 if all + * hops are open (the circuit is complete), 0 if we find a router + * (and set it to *router), and -1 if we fail to lookup the router. */ static int -onion_extend_cpath(crypt_path_t **head_ptr, cpath_build_state_t - *state, routerinfo_t **router_out) +onion_next_router_in_cpath(circuit_t *circ, routerinfo_t **router) { + routerinfo_t *r; + crypt_path_t *hop = onion_next_hop_in_cpath(circ->cpath); + if (!hop) /* all hops are open */ + return 1; + tor_assert(hop->state == CPATH_STATE_CLOSED); + r = router_get_by_digest(hop->identity_digest); + if (!r) { + log_fn(LOG_WARN,"Circuit intended to extend to a hop whose routerinfo we've lost. Cancelling circuit."); + return -1; + } + *router = r; + return 0; +} + +/** Choose a suitable next hop in the cpath head_ptr, + * based on state. Append the hop info to head_ptr. + */ +static int +onion_extend_cpath(crypt_path_t **head_ptr, cpath_build_state_t *state) { int cur_len; - crypt_path_t *cpath, *hop; + crypt_path_t *cpath; routerinfo_t *choice; smartlist_t *excludednodes; tor_assert(head_ptr); - tor_assert(router_out); if (!*head_ptr) { cur_len = 0; @@ -1320,11 +1355,13 @@ onion_extend_cpath(crypt_path_t **head_ptr, cpath_build_state_t ++cur_len; } } + if (cur_len >= state->desired_path_len) { log_fn(LOG_DEBUG, "Path is complete: %d steps long", state->desired_path_len); return 1; } + log_fn(LOG_DEBUG, "Path is %d long; we want %d", cur_len, state->desired_path_len); @@ -1348,7 +1385,16 @@ onion_extend_cpath(crypt_path_t **head_ptr, cpath_build_state_t log_fn(LOG_DEBUG,"Chose router %s for hop %d (exit is %s)", choice->nickname, cur_len+1, state->chosen_exit_name); - hop = tor_malloc_zero(sizeof(crypt_path_t)); + onion_append_hop(head_ptr, choice); + return 0; +} + +/** Create a new hop, annotate it with information about its + * corresponding router choice, and append it to the + * end of the cpath head_ptr. */ +static int +onion_append_hop(crypt_path_t **head_ptr, routerinfo_t *choice) { + crypt_path_t *hop = tor_malloc_zero(sizeof(crypt_path_t)); /* link hop into the cpath, at the end. */ onion_append_to_cpath(head_ptr, hop); @@ -1362,9 +1408,6 @@ onion_extend_cpath(crypt_path_t **head_ptr, cpath_build_state_t hop->package_window = CIRCWINDOW_START; hop->deliver_window = CIRCWINDOW_START; - log_fn(LOG_DEBUG, "Extended circuit path with %s for hop %d", - choice->nickname, cur_len+1); - - *router_out = choice; return 0; } + diff --git a/src/or/circuitlist.c b/src/or/circuitlist.c index 2c5c300e3e..a25c874fd9 100644 --- a/src/or/circuitlist.c +++ b/src/or/circuitlist.c @@ -76,7 +76,8 @@ void circuit_close_all_marked(void) */ circuit_t *circuit_new(uint16_t p_circ_id, connection_t *p_conn) { circuit_t *circ; - static uint32_t n_circuits_allocated = 0; + static uint32_t n_circuits_allocated = 1; + /* never zero, since a global ID of 0 treated specially by the controller */ circ = tor_malloc_zero(sizeof(circuit_t)); circ->magic = CIRCUIT_MAGIC; diff --git a/src/or/circuituse.c b/src/or/circuituse.c index 836bb66b70..ea51a4c2d1 100644 --- a/src/or/circuituse.c +++ b/src/or/circuituse.c @@ -356,14 +356,14 @@ circuit_predict_and_launch_new(void) if (need_ports) { log_fn(LOG_INFO,"Have %d clean circs (%d internal), need another exit circ.", num, num_internal); - circuit_launch_by_identity(CIRCUIT_PURPOSE_C_GENERAL, NULL, + circuit_launch_by_router(CIRCUIT_PURPOSE_C_GENERAL, NULL, port_needs_uptime, port_needs_capacity, 0); } else if (need_hidserv && ((num_uptime_internal<2 && hidserv_needs_uptime) || num_internal<2)) { log_fn(LOG_INFO,"Have %d clean circs (%d uptime-internal, %d internal)," " need another hidserv circ.", num, num_uptime_internal, num_internal); - circuit_launch_by_identity(CIRCUIT_PURPOSE_C_GENERAL, NULL, + circuit_launch_by_router(CIRCUIT_PURPOSE_C_GENERAL, NULL, hidserv_needs_uptime, hidserv_needs_capacity, 1); } } @@ -400,7 +400,7 @@ void circuit_build_needed_circs(time_t now) { circ && circ->timestamp_created + TESTING_CIRCUIT_INTERVAL < now) { log_fn(LOG_INFO,"Creating a new testing circuit."); - circuit_launch_by_identity(CIRCUIT_PURPOSE_C_GENERAL, NULL, 0, 0, 0); + circuit_launch_by_router(CIRCUIT_PURPOSE_C_GENERAL, NULL, 0, 0, 0); } #endif } @@ -562,7 +562,7 @@ circuit_testing_failed(circuit_t *circ, int at_last_hop) { routerinfo_t *me = router_get_my_routerinfo(); if (!at_last_hop) - circuit_launch_by_identity(CIRCUIT_PURPOSE_TESTING, me->identity_digest, 0, 0, 1); + circuit_launch_by_router(CIRCUIT_PURPOSE_TESTING, me, 0, 0, 1); else log_fn(LOG_INFO,"Our testing circuit (to see if your ORPort is reachable) has failed. I'll try again later."); } @@ -684,9 +684,10 @@ static int did_circs_fail_last_period = 0; * success. */ #define MAX_CIRCUIT_FAILURES 5 +/** Launch a new circuit based on our arguments. */ circuit_t * -circuit_launch_by_identity(uint8_t purpose, const char *exit_digest, - int need_uptime, int need_capacity, int internal) +circuit_launch_by_router(uint8_t purpose, routerinfo_t *exit, + int need_uptime, int need_capacity, int internal) { circuit_t *circ; @@ -720,9 +721,15 @@ circuit_launch_by_identity(uint8_t purpose, const char *exit_digest, case CIRCUIT_PURPOSE_C_INTRODUCING: case CIRCUIT_PURPOSE_S_CONNECT_REND: /* need to add a new hop */ - tor_assert(exit_digest); - if (circuit_append_new_hop(circ, NULL, exit_digest) < 0) + tor_assert(exit); + circuit_append_new_exit(circ, exit); + circ->state = CIRCUIT_STATE_BUILDING; + if (circuit_send_next_onion_skin(circ)<0) { + log_fn(LOG_WARN, "Couldn't extend circuit to new point '%s'.", + circ->build_state->chosen_exit_name); + circuit_mark_for_close(circ); return NULL; + } break; default: log_fn(LOG_WARN,"Bug: unexpected purpose %d when cannibalizing a general circ.", @@ -744,7 +751,7 @@ circuit_launch_by_identity(uint8_t purpose, const char *exit_digest, } /* try a circ. if it fails, circuit_mark_for_close will increment n_circuit_failures */ - return circuit_establish_circuit(purpose, exit_digest, + return circuit_establish_circuit(purpose, exit, need_uptime, need_capacity, internal); } @@ -753,18 +760,17 @@ circuit_t * circuit_launch_by_nickname(uint8_t purpose, const char *exit_nickname, int need_uptime, int need_capacity, int internal) { - const char *digest = NULL; + routerinfo_t *router = NULL; if (exit_nickname) { - routerinfo_t *r = router_get_by_nickname(exit_nickname); - if (!r) { + router = router_get_by_nickname(exit_nickname); + if (!router) { log_fn(LOG_WARN, "No such OR as '%s'", exit_nickname); return NULL; } - digest = r->identity_digest; } - return circuit_launch_by_identity(purpose, digest, - need_uptime, need_capacity, internal); + return circuit_launch_by_router(purpose, router, + need_uptime, need_capacity, internal); } /** Record another failure at opening a general circuit. When we have diff --git a/src/or/control.c b/src/or/control.c index e8f6d0e35e..39e82c1664 100644 --- a/src/or/control.c +++ b/src/or/control.c @@ -642,12 +642,6 @@ handle_control_extendcircuit(connection_t *conn, uint32_t len, send_control_error(conn, ERR_SYNTAX, "extendcircuit message too short"); return 0; } - circ_id = ntohl(get_uint32(body)); - if (!(circ = circuit_get_by_global_id(circ_id))) { - send_control_error(conn, ERR_NO_STREAM, - "No connection found with given ID"); - return 0; - } router_nicknames = smartlist_create(); routers = smartlist_create(); @@ -661,20 +655,45 @@ handle_control_extendcircuit(connection_t *conn, uint32_t len, } smartlist_add(routers, r); }); + if (!smartlist_len(routers)) { + send_control_error(conn, ERR_SYNTAX, "No router names provided"); + goto done; + } + + circ_id = ntohl(get_uint32(body)); + if (!circ_id) { + /* start a new circuit */ + circ = circuit_init(CIRCUIT_PURPOSE_C_GENERAL, 0, 0, 0); + } else { + circ = circuit_get_by_global_id(circ_id); + if (!circ) { + send_control_error(conn, ERR_NO_CIRC, + "No circuit found with given ID"); + goto done; + } + } + + /* now circ refers to something that is ready to be extended */ -#if 1 - /*XXXX RD*/ - send_control_error(conn, ERR_INTERNAL, "EXTENDCIRCUIT not implemented."); -#else SMARTLIST_FOREACH(routers, routerinfo_t *, r, { - /*XXXX RD*/ - if (circuit_extend_path(circ, r)<0) { - send_control_error(conn, ERR_INTERNAL, "Unable to extend path."); - goto done; - } + circuit_append_new_exit(circ, r); }); -#endif + + /* now that we've populated the cpath, start extending */ + if (!circ_id) { + if (circuit_handle_first_hop(circ) < 0) { + circuit_mark_for_close(circ); + } + } else { + if (circ->state == CIRCUIT_STATE_OPEN) { + circ->state = CIRCUIT_STATE_BUILDING; + if (circuit_send_next_onion_skin(circ) < 0) { + log_fn(LOG_INFO,"send_next_onion_skin failed; circuit marked for closing."); + circuit_mark_for_close(circ); + } + } + } send_control_done(conn); done: diff --git a/src/or/or.h b/src/or/or.h index 1991d7fcf5..d35e95e3f1 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -1120,8 +1120,11 @@ char *circuit_list_path(circuit_t *circ, int verbose); void circuit_log_path(int severity, circuit_t *circ); void circuit_rep_hist_note_result(circuit_t *circ); void circuit_dump_by_conn(connection_t *conn, int severity); -circuit_t *circuit_establish_circuit(uint8_t purpose, const char *exit_digest, +circuit_t *circuit_init(uint8_t purpose, int need_uptime, + int need_capacity, int internal); +circuit_t *circuit_establish_circuit(uint8_t purpose, routerinfo_t *exit, int need_uptime, int need_capacity, int internal); +int circuit_handle_first_hop(circuit_t *circ); void circuit_n_conn_done(connection_t *or_conn, int status); int circuit_send_next_onion_skin(circuit_t *circ); void circuit_note_clock_jumped(int seconds_elapsed); @@ -1133,7 +1136,7 @@ int onionskin_answer(circuit_t *circ, unsigned char *payload, unsigned char *key int circuit_all_predicted_ports_handled(time_t now, int *need_uptime, int *need_capacity); -int circuit_append_new_hop(circuit_t *circ, char *nickname, const char *exit_digest); +int circuit_append_new_exit(circuit_t *circ, routerinfo_t *exit); void onion_append_to_cpath(crypt_path_t **head_ptr, crypt_path_t *new_hop); /********************************* circuitlist.c ***********************/ @@ -1181,8 +1184,8 @@ void circuit_has_opened(circuit_t *circ); void circuit_build_failed(circuit_t *circ); circuit_t *circuit_launch_by_nickname(uint8_t purpose, const char *exit_nickname, int need_uptime, int need_capacity, int is_internal); -circuit_t *circuit_launch_by_identity(uint8_t purpose, const char *exit_digest, - int need_uptime, int need_capacity, int is_internal); +circuit_t *circuit_launch_by_router(uint8_t purpose, routerinfo_t *exit, + int need_uptime, int need_capacity, int is_internal); void circuit_reset_failure_count(int timeout); int connection_ap_handshake_attach_chosen_circuit(connection_t *conn, circuit_t *circ); diff --git a/src/or/rendclient.c b/src/or/rendclient.c index 7111dadda6..7f44bc24f6 100644 --- a/src/or/rendclient.c +++ b/src/or/rendclient.c @@ -225,8 +225,15 @@ rend_client_introduction_acked(circuit_t *circ, } log_fn(LOG_INFO, "Chose new intro point %s for %s (circ %d)", nickname, circ->rend_query, circ->n_circ_id); - if (circuit_append_new_hop(circ, nickname, r->identity_digest) < 0) + tor_free(nickname); + circuit_append_new_exit(circ, r); + circ->state = CIRCUIT_STATE_BUILDING; + if (circuit_send_next_onion_skin(circ)<0) { + log_fn(LOG_WARN, "Couldn't extend circuit to new point '%s'.", + circ->build_state->chosen_exit_name); + circuit_mark_for_close(circ); return -1; + } } } return 0; diff --git a/src/or/router.c b/src/or/router.c index 0d158c7eaa..d70211bd0c 100644 --- a/src/or/router.c +++ b/src/or/router.c @@ -385,7 +385,7 @@ void consider_testing_reachability(void) { routerinfo_t *me = router_get_my_routerinfo(); if (!can_reach_or_port) { - circuit_launch_by_identity(CIRCUIT_PURPOSE_TESTING, me->identity_digest, 0, 0, 1); + circuit_launch_by_router(CIRCUIT_PURPOSE_TESTING, me, 0, 0, 1); } if (!can_reach_dir_port && me->dir_port) { diff --git a/src/or/routerlist.c b/src/or/routerlist.c index 0ae62ad308..6763902f88 100644 --- a/src/or/routerlist.c +++ b/src/or/routerlist.c @@ -628,7 +628,7 @@ routerinfo_t *router_get_by_hexdigest(const char *hexdigest) { } /** Return the router in our routerlist whose 20-byte key digest - * is hexdigest. Return NULL if no such router is known. */ + * is digest. Return NULL if no such router is known. */ routerinfo_t *router_get_by_digest(const char *digest) { int i; routerinfo_t *router;