aboutsummaryrefslogtreecommitdiff
path: root/src/or/circuit.c
diff options
context:
space:
mode:
authorRoger Dingledine <arma@torproject.org>2003-11-16 21:49:52 +0000
committerRoger Dingledine <arma@torproject.org>2003-11-16 21:49:52 +0000
commit6d0e611fde9d8610a0e3837da17545f8f42e1adc (patch)
tree18fd02ae1cea86594471ff9dd9e89c10a41df07e /src/or/circuit.c
parentf5089681f795b435ec8a7454e2b91d8b3596a01b (diff)
downloadtor-6d0e611fde9d8610a0e3837da17545f8f42e1adc.tar.gz
tor-6d0e611fde9d8610a0e3837da17545f8f42e1adc.zip
change when circuits are built and expired
not quite happy with it yet svn:r817
Diffstat (limited to 'src/or/circuit.c')
-rw-r--r--src/or/circuit.c78
1 files changed, 47 insertions, 31 deletions
diff --git a/src/or/circuit.c b/src/or/circuit.c
index 7208489fac..f591c11a88 100644
--- a/src/or/circuit.c
+++ b/src/or/circuit.c
@@ -205,18 +205,45 @@ circuit_t *circuit_get_by_conn(connection_t *conn) {
return NULL;
}
-circuit_t *circuit_get_newest_open(void) {
- circuit_t *circ, *bestcirc=NULL;
+/* Find the newest circ that conn can use, preferably one which is
+ * dirty and not too old.
+ * If !conn, return newest open.
+ */
+circuit_t *circuit_get_newest_open(connection_t *conn) {
+ circuit_t *circ, *newest=NULL, *leastdirty=NULL;
for(circ=global_circuitlist;circ;circ = circ->next) {
- if(circ->cpath && circ->state == CIRCUIT_STATE_OPEN && circ->n_conn && (!bestcirc ||
- bestcirc->timestamp_created < circ->timestamp_created)) {
- log_fn(LOG_DEBUG,"Choosing circuit %s:%d:%d.", circ->n_conn->address, circ->n_port, circ->n_circ_id);
- assert(circ->n_circ_id);
- bestcirc = circ;
+ if(conn && connection_ap_can_use_exit(conn,
+ router_get_by_addr_port(circ->cpath->prev->addr, circ->cpath->prev->port)) < 0) {
+ log_fn(LOG_DEBUG,"Skipping %s:%d:%d because we couldn't exit there.",
+ circ->n_conn->address, circ->n_port, circ->n_circ_id);
+ continue;
}
+ if(circ->cpath && circ->state == CIRCUIT_STATE_OPEN && circ->n_conn) {
+ if(!newest || newest->timestamp_created < circ->timestamp_created) {
+ assert(circ->n_circ_id);
+ newest = circ;
+ }
+ if(conn && circ->timestamp_dirty &&
+ (!leastdirty || leastdirty->timestamp_dirty < circ->timestamp_dirty)) {
+ assert(circ->n_circ_id);
+ leastdirty = circ;
+ }
+ }
+ }
+
+ if(leastdirty &&
+ leastdirty->timestamp_dirty+options.NewCircuitPeriod > time(NULL)) {
+ log_fn(LOG_DEBUG,"Choosing in-use circuit %s:%d:%d.",
+ leastdirty->n_conn->address, leastdirty->n_port, leastdirty->n_circ_id);
+ return leastdirty;
+ }
+ if(newest) {
+ log_fn(LOG_DEBUG,"Choosing circuit %s:%d:%d.",
+ newest->n_conn->address, newest->n_port, newest->n_circ_id);
+ return newest;
}
- return bestcirc;
+ return NULL;
}
int circuit_deliver_relay_cell(cell_t *cell, circuit_t *circ,
@@ -491,13 +518,8 @@ int circuit_consider_sending_sendme(circuit_t *circ, int edge_type, crypt_path_t
void circuit_close(circuit_t *circ) {
connection_t *conn;
- circuit_t *youngest=NULL;
assert(circ);
- if(options.SocksPort) {
- youngest = circuit_get_newest_open();
- log_fn(LOG_DEBUG,"youngest %d, circ %d.",(int)youngest, (int)circ);
- }
circuit_remove(circ);
if(circ->n_conn)
connection_send_destroy(circ->n_circ_id, circ->n_conn);
@@ -509,11 +531,6 @@ void circuit_close(circuit_t *circ) {
for(conn=circ->p_streams; conn; conn=conn->next_stream) {
connection_send_destroy(circ->p_circ_id, conn);
}
- if(options.SocksPort && youngest == circ) { /* check this after we've sent the destroys, to reduce races */
- /* our current circuit just died. Launch another one pronto. */
- log_fn(LOG_INFO,"Youngest circuit dying. Launching a replacement.");
- circuit_launch_new(1);
- }
circuit_free(circ);
}
@@ -606,15 +623,15 @@ void circuit_dump_by_conn(connection_t *conn, int severity) {
void circuit_expire_unused_circuits(void) {
circuit_t *circ, *tmpcirc;
- circuit_t *youngest;
-
- youngest = circuit_get_newest_open();
+ time_t now = time(NULL);
circ = global_circuitlist;
while(circ) {
tmpcirc = circ;
circ = circ->next;
- if(tmpcirc != youngest && !tmpcirc->p_conn && !tmpcirc->p_streams) {
+ if(tmpcirc->timestamp_dirty &&
+ tmpcirc->timestamp_dirty + options.NewCircuitPeriod < now &&
+ !tmpcirc->p_conn && !tmpcirc->p_streams) {
log_fn(LOG_DEBUG,"Closing n_circ_id %d",tmpcirc->n_circ_id);
circuit_close(tmpcirc);
}
@@ -624,34 +641,33 @@ void circuit_expire_unused_circuits(void) {
/* failure_status code: negative means reset failures to 0. Other values mean
* add that value to the current number of failures, then if we don't have too
* many failures on record, try to make a new circuit.
+ *
+ * Return -1 if you aren't going to try to make a circuit, 0 if you did try.
*/
-void circuit_launch_new(int failure_status) {
+int circuit_launch_new(int failure_status) {
static int failures=0;
if(!options.SocksPort) /* we're not an application proxy. no need for circuits. */
- return;
+ return -1;
if(failure_status == -1) { /* I was called because a circuit succeeded */
failures = 0;
- return;
+ return -1;
}
failures += failure_status;
-retry_circuit:
-
if(failures > 5) {
- log_fn(LOG_INFO,"Giving up for now, %d failures.", failures);
- return;
+ return -1;
}
if(circuit_establish_circuit() < 0) {
failures++;
- goto retry_circuit;
+ return 0;
}
failures = 0;
- return;
+ return 0;
}
int circuit_establish_circuit(void) {