diff --git a/src/or/connection.c b/src/or/connection.c index e4aba96208..0a72f6437d 100644 --- a/src/or/connection.c +++ b/src/or/connection.c @@ -665,6 +665,10 @@ int connection_process_inbuf(connection_t *conn) { return connection_or_process_inbuf(conn); case CONN_TYPE_EXIT: case CONN_TYPE_AP: + if(conn->package_window <= 0) { + log_fn(LOG_WARN,"called with package_window %d. Tell Roger.", conn->package_window); + return 0; + } return connection_edge_process_inbuf(conn); case CONN_TYPE_DIR: return connection_dir_process_inbuf(conn); diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c index df6a840efc..7100369a69 100644 --- a/src/or/connection_edge.c +++ b/src/or/connection_edge.c @@ -408,7 +408,8 @@ int connection_edge_finished_flushing(connection_t *conn) { if(connection_edge_send_command(conn, circuit_get_by_conn(conn), RELAY_COMMAND_CONNECTED, NULL, 0, conn->cpath_layer) < 0) return 0; /* circuit is closed, don't continue */ - return connection_process_inbuf(conn); /* in case the server has written anything */ + assert(conn->package_window > 0); + return connection_edge_process_inbuf(conn); /* in case the server has written anything */ case AP_CONN_STATE_OPEN: case EXIT_CONN_STATE_OPEN: connection_stop_writing(conn); diff --git a/src/or/onion.c b/src/or/onion.c index 0434436ad3..51dd1d0465 100644 --- a/src/or/onion.c +++ b/src/or/onion.c @@ -34,8 +34,9 @@ static int ol_length=0; int onion_pending_add(circuit_t *circ) { struct onion_queue_t *tmp; - tmp = tor_malloc_zero(sizeof(struct onion_queue_t)); + tmp = tor_malloc(sizeof(struct onion_queue_t)); tmp->circ = circ; + tmp->next = NULL; if(!ol_tail) { assert(!ol_list); @@ -70,14 +71,6 @@ circuit_t *onion_next_task(void) { assert(ol_list->circ); assert(ol_list->circ->p_conn); /* make sure it's still valid */ -#if 0 - if(!ol_list->circ->p_conn) { - log_fn(LOG_INFO,"ol_list->circ->p_conn null, must have died?"); - onion_pending_remove(ol_list->circ); - return onion_next_task(); /* recurse: how about the next one? */ - } -#endif - assert(ol_length > 0); circ = ol_list->circ; onion_pending_remove(ol_list->circ); @@ -182,7 +175,7 @@ char **parse_nickname_list(char *list, int *num) { strncpy(out[i],start,end-start); out[i][end-start] = 0; /* null terminate it */ i++; - while(isspace(*end)) end++; + while(*end && isspace(*end)) end++; start = end; } *num = i; @@ -209,15 +202,11 @@ static int new_route_len(double cw, routerinfo_t **rarray, int rarray_len) { } if(num_acceptable_routers < routelen) { - log_fn(LOG_INFO,"Not enough routers: cutting routelen from %d to %d.",routelen, num_acceptable_routers); + log_fn(LOG_INFO,"Not enough routers: cutting routelen from %d to %d.", + routelen, num_acceptable_routers); routelen = num_acceptable_routers; } - if (routelen < 1) { - log_fn(LOG_WARN,"Didn't find any acceptable routers. Failing."); - return -1; - } - return routelen; } @@ -235,7 +224,7 @@ static routerinfo_t *choose_good_exit_server(routerlist_t *dir) int best_maybe_support_idx = -1; int n_best_support=0, n_best_maybe_support=0; int n_running_routers=0; - + get_connection_array(&carray, &n_connections); /* Count how many connections are waiting for a circuit to be built. @@ -316,7 +305,8 @@ static routerinfo_t *choose_good_exit_server(routerlist_t *dir) ++n_best_maybe_support; } } - log_fn(LOG_INFO, "Found %d servers that will definitely support %d/%d pending connections, and %d that might support %d/%d.", + log_fn(LOG_INFO, "Found %d servers that will definitely support %d/%d " + "pending connections, and %d that might support %d/%d.", n_best_support, best_support, n_pending_connections, n_best_maybe_support, best_maybe_support, n_pending_connections); /* If any routers definitely support any pending connections, choose one @@ -469,10 +459,9 @@ int onion_extend_cpath(crypt_path_t **head_ptr, cpath_build_state_t *state, rout log_fn(LOG_DEBUG, "Picked an already-selected router for hop %d; retrying.", cur_len); ++n_failures; - if (n_failures == 25) { - /* This actually happens with P=1/30,000,000 when we _could_ build a - * circuit. For now, let's leave it in. - */ + if (n_failures == 50) { + /* XXX hack to prevent infinite loop. Ideally we should build a list + * of acceptable choices and then choose from it. */ log_fn(LOG_INFO, "Unable to continue generating circuit path"); return -1; } @@ -505,23 +494,21 @@ int onion_extend_cpath(crypt_path_t **head_ptr, cpath_build_state_t *state, rout choice->nickname, cur_len, state->chosen_exit); if (cur_len != state->desired_path_len-1 && !strcasecmp(choice->nickname, state->chosen_exit)) { + /* make sure we don't pick the exit for another node in the path */ goto again; } for (i = 0, cpath = *head_ptr; i < cur_len; ++i, cpath=cpath->next) { r = router_get_by_addr_port(cpath->addr, cpath->port); - if ((r && !crypto_pk_cmp_keys(r->onion_pkey, choice->onion_pkey)) - || (cur_len != state->desired_path_len-1 && - !strcasecmp(choice->nickname, state->chosen_exit)) - || (cpath->addr == choice->addr && - cpath->port == choice->or_port) - || (options.ORPort && - !(connection_twin_get_by_addr_port(choice->addr, - choice->or_port)))) { - goto again; - } + assert(r); + if (!crypto_pk_cmp_keys(r->onion_pkey, choice->onion_pkey)) + goto again; /* same key -- it or a twin is already chosen */ + if (options.ORPort && + !(connection_twin_get_by_addr_port(choice->addr, choice->or_port))) + goto again; /* this node is not connected to us. */ + } - + /* Okay, so we haven't used 'choice' before. */ hop = (crypt_path_t *)tor_malloc_zero(sizeof(crypt_path_t)); @@ -537,16 +524,16 @@ int onion_extend_cpath(crypt_path_t **head_ptr, cpath_build_state_t *state, rout } hop->state = CPATH_STATE_CLOSED; - + hop->port = choice->or_port; hop->addr = choice->addr; - + 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); - + *router_out = choice; return 0; } @@ -628,7 +615,7 @@ onion_skin_create(crypto_pk_env_t *dest_router_key, if (crypto_cipher_encrypt(cipher, pubkey+pkbytes, dhbytes+16-pkbytes, onion_skin_out+pkbytes)) goto err; - + free(pubkey); crypto_free_cipher_env(cipher); *handshake_state_out = dh; @@ -658,7 +645,7 @@ onion_skin_server_handshake(char *onion_skin, /* DH_ONIONSKIN_LEN bytes long */ crypto_cipher_env_t *cipher = NULL; int pkbytes; int len; - + memset(iv, 0, 16); pkbytes = crypto_pk_keysize(private_key); @@ -666,7 +653,7 @@ onion_skin_server_handshake(char *onion_skin, /* DH_ONIONSKIN_LEN bytes long */ onion_skin, pkbytes, buf, RSA_NO_PADDING) == -1) goto err; - + #ifdef DEBUG_ONION_SKINS printf("Server: client symkey:"); PA(buf+0,16); @@ -737,7 +724,7 @@ onion_skin_client_handshake(crypto_dh_env_t *handshake_state, { int len; assert(crypto_dh_get_bytes(handshake_state) == DH_KEY_LEN); - + #ifdef DEBUG_ONION_SKINS printf("Client: server g^y:"); PA(handshake_reply+0,3); @@ -750,7 +737,7 @@ onion_skin_client_handshake(crypto_dh_env_t *handshake_state, key_out, key_out_len); if (len < 0) return -1; - + #ifdef DEBUG_ONION_SKINS printf("Client: keys out:"); PA(key_out, key_out_len);