From a3e39b0ceb4478339f9903ab6e01a3984e208d42 Mon Sep 17 00:00:00 2001 From: Roger Dingledine Date: Tue, 18 Nov 2003 07:48:00 +0000 Subject: [PATCH] don't build too many circs at once expire circs that have been building for too long svn:r835 --- src/or/circuit.c | 42 +++++++++++++++++++++++++++++++++++++++++- src/or/command.c | 4 ++-- src/or/main.c | 21 ++++++++++++++++----- src/or/or.h | 4 +++- 4 files changed, 62 insertions(+), 9 deletions(-) diff --git a/src/or/circuit.c b/src/or/circuit.c index 47911f2dde..5c2a263561 100644 --- a/src/or/circuit.c +++ b/src/or/circuit.c @@ -250,6 +250,46 @@ circuit_t *circuit_get_newest(connection_t *conn, int must_be_open) { return NULL; } +#define MIN_SECONDS_BEFORE_EXPIRING_CIRC 2 +/* circuits that were born at the end of their second might be expired + * after 2.1 seconds; circuits born at the beginning might be expired + * after closer to 3 seconds. + */ + +/* close all circuits that start at us, aren't open, and were born + * at least MIN_SECONDS_BEFORE_EXPIRING_CIRC seconds ago */ +void circuit_expire_building(void) { + circuit_t *circ; + int now = time(NULL); + + for(circ=global_circuitlist;circ;circ = circ->next) { + if(circ->cpath && + circ->state != CIRCUIT_STATE_OPEN && + circ->timestamp_created + MIN_SECONDS_BEFORE_EXPIRING_CIRC+1 < now) { + if(circ->n_conn) + log_fn(LOG_INFO,"Abandoning circ %s:%d:%d (state %d:%s)", + circ->n_conn->address, circ->n_port, circ->n_circ_id, + circ->state, circuit_state_to_string[circ->state]); + else + log_fn(LOG_INFO,"Abandoning circ %d (state %d:%s)", circ->n_circ_id, + circ->state, circuit_state_to_string[circ->state]); + circuit_close(circ); + } + } +} + +/* count the number of circs starting at us that aren't open */ +int circuit_count_building(void) { + circuit_t *circ; + int num=0; + + for(circ=global_circuitlist;circ;circ = circ->next) { + if(circ->cpath && circ->state != CIRCUIT_STATE_OPEN) + num++; + } + return num; +} + int circuit_deliver_relay_cell(cell_t *cell, circuit_t *circ, int cell_direction, crypt_path_t *layer_hint) { connection_t *conn=NULL; @@ -818,7 +858,7 @@ int circuit_send_next_onion_skin(circuit_t *circ) { connection_ap_attach_pending(); return 0; } else if (r<0) { - log_fn(LOG_WARN,"Unable to extend circuit path."); + log_fn(LOG_INFO,"Unable to extend circuit path."); return -1; } hop = circ->cpath->prev; diff --git a/src/or/command.c b/src/or/command.c index b3302a301f..fa83d23c83 100644 --- a/src/or/command.c +++ b/src/or/command.c @@ -146,8 +146,8 @@ static void command_process_created_cell(cell_t *cell, connection_t *conn) { } log_fn(LOG_DEBUG,"Moving to next skin."); if(circuit_send_next_onion_skin(circ) < 0) { - log_fn(LOG_WARN,"circuit_send_next_onion_skin failed."); - circuit_close(circ); + log_fn(LOG_INFO,"circuit_send_next_onion_skin failed."); + circuit_close(circ); /* XXX push this circuit_close lower */ return; } } else { /* pack it into an extended relay cell, and send it. */ diff --git a/src/or/main.c b/src/or/main.c index 19aae30447..d0e9459211 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -335,7 +335,14 @@ static void run_scheduled_events(time_t now) { time_to_fetch_directory = now + options.DirFetchPostPeriod; } - /* 2. Every second, we try a new circuit if there are no valid + /* 2. Every second, we examine pending circuits and prune the + * ones which have been pending for more than 2 seconds. + * We do this before step 3, so it can try building more if + * it's not comfortable with the number of available circuits. + */ + circuit_expire_building(); + + /* 3. Every second, we try a new circuit if there are no valid * circuits. Every NewCircuitPeriod seconds, we expire circuits * that became dirty more than NewCircuitPeriod seconds ago, * and we make a new circ if there are no clean circuits. @@ -356,11 +363,15 @@ static void run_scheduled_events(time_t now) { } time_to_new_circuit = now + options.NewCircuitPeriod; } - if(!circ) +#define CIRCUIT_MIN_BUILDING 3 + if(!circ && circuit_count_building() < CIRCUIT_MIN_BUILDING) + /* if there's no open circ, and less than 3 are on the way, + * go ahead and try another. + */ circuit_launch_new(1); } - /* 3. Every second, we check how much bandwidth we've consumed and + /* 4. Every second, we check how much bandwidth we've consumed and * increment global_read_bucket. */ stats_n_bytes_read += stats_prev_global_read_bucket-global_read_bucket; @@ -370,12 +381,12 @@ static void run_scheduled_events(time_t now) { } stats_prev_global_read_bucket = global_read_bucket; - /* 4. We do houskeeping for each connection... */ + /* 5. We do housekeeping for each connection... */ for(i=0;i