Commit a3e39b0c authored by Roger Dingledine's avatar Roger Dingledine
Browse files

don't build too many circs at once

expire circs that have been building for too long


svn:r835
parent bb0e409f
Loading
Loading
Loading
Loading
+41 −1
Changes for src/or/circuit.c: 41 added lines, 1 removed line.
Original line number Diff line number Diff line
@@ -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;
+2 −2
Changes for src/or/command.c: 2 added lines, 2 removed lines.
Original line number Diff line number Diff line
@@ -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. */
+16 −5
Changes for src/or/main.c: 16 added lines, 5 removed lines.
Original line number Diff line number Diff line
@@ -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<nfds;i++) {
    run_connection_housekeeping(i, now);
  }

  /* 5. and blow away any connections that need to die. can't do this later
  /* 6. and blow away any connections that need to die. can't do this later
   * because we might open up a circuit and not realize we're about to cull
   * the connection it's running over.
   * XXX we can remove this step once we audit circuit-building to make sure
+3 −1
Changes for src/or/or.h: 3 added lines, 1 removed line.
Original line number Diff line number Diff line
@@ -110,7 +110,6 @@

#define CIRC_ID_TYPE_LOWER 0
#define CIRC_ID_TYPE_HIGHER 1
#define CIRC_ID_TYPE_BOTH 2

#define _CONN_TYPE_MIN 3
#define CONN_TYPE_OR_LISTENER 3
@@ -518,6 +517,9 @@ circuit_t *circuit_get_by_circ_id_conn(circ_id_t circ_id, connection_t *conn);
circuit_t *circuit_get_by_conn(connection_t *conn);
circuit_t *circuit_get_newest(connection_t *conn, int must_be_open);

void circuit_expire_building(void);
int circuit_count_building(void);

int circuit_deliver_relay_cell(cell_t *cell, circuit_t *circ,
                               int cell_direction, crypt_path_t *layer_hint);
int relay_crypt(circuit_t *circ, char *in, int inlen, char cell_direction,