From 4aede010b9e2bb53c3dfc954bfe0ff393d03525f Mon Sep 17 00:00:00 2001 From: Roger Dingledine Date: Mon, 17 Nov 2003 00:57:56 +0000 Subject: [PATCH] recognize in-progress circs and don't start redundant ones quickly notice streams that don't have a circ on the way, and start one svn:r819 --- src/or/circuit.c | 44 ++++++++++++++++++++++++---------------- src/or/connection_edge.c | 15 +++++++------- src/or/main.c | 12 +++++------ src/or/or.h | 3 ++- 4 files changed, 42 insertions(+), 32 deletions(-) diff --git a/src/or/circuit.c b/src/or/circuit.c index f591c11a88..246c7ba1ff 100644 --- a/src/or/circuit.c +++ b/src/or/circuit.c @@ -207,28 +207,37 @@ circuit_t *circuit_get_by_conn(connection_t *conn) { /* Find the newest circ that conn can use, preferably one which is * dirty and not too old. - * If !conn, return newest open. + * If !conn, return newest. + * + * If must_be_open, ignore circs not in CIRCUIT_STATE_OPEN. */ -circuit_t *circuit_get_newest_open(connection_t *conn) { +circuit_t *circuit_get_newest(connection_t *conn, int must_be_open) { circuit_t *circ, *newest=NULL, *leastdirty=NULL; + routerinfo_t *exitrouter; for(circ=global_circuitlist;circ;circ = circ->next) { - 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) + continue; /* this circ doesn't start at us */ + if(must_be_open && (circ->state != CIRCUIT_STATE_OPEN || !circ->n_conn)) + continue; /* ignore non-open circs */ + if(conn) { + if(circ->state == CIRCUIT_STATE_OPEN && circ->n_conn) /* open */ + exitrouter = router_get_by_addr_port(circ->cpath->prev->addr, circ->cpath->prev->port); + else /* not open */ + exitrouter = router_get_by_nickname(circ->build_state->chosen_exit); + if(!exitrouter || connection_ap_can_use_exit(conn, exitrouter) < 0) { + /* can't exit from this router */ + 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(!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; } } @@ -743,6 +752,7 @@ void circuit_n_conn_open(connection_t *or_conn) { if(!circ) return; + assert(circ->state == CIRCUIT_STATE_OR_WAIT); log_fn(LOG_DEBUG,"Found circ, sending onion skin."); circ->n_conn = or_conn; if(circuit_send_next_onion_skin(circ) < 0) { diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c index 849d4afe69..d20f1d4059 100644 --- a/src/or/connection_edge.c +++ b/src/or/connection_edge.c @@ -481,7 +481,6 @@ void connection_ap_attach_pending(void) { connection_t **carray; int n, i; - int need_new_circuit = 0; get_connection_array(&carray, &n); @@ -490,11 +489,12 @@ void connection_ap_attach_pending(void) carray[i]->type != AP_CONN_STATE_CIRCUIT_WAIT) continue; if (connection_ap_handshake_attach_circuit(carray[i])<0) { - need_new_circuit = 1; + if(!circuit_get_newest(carray[i], 0)) { + /* if there are no acceptable clean or not-very-dirty circs on the way */ + circuit_launch_new(1); + } } } - if(need_new_circuit) - circuit_launch_new(1); } static void connection_edge_consider_sending_sendme(connection_t *conn) { @@ -549,9 +549,8 @@ static int connection_ap_handshake_process_socks(connection_t *conn) { } /* else socks handshake is done, continue processing */ conn->state = AP_CONN_STATE_CIRCUIT_WAIT; - if (connection_ap_handshake_attach_circuit(conn)<0) { - circuit_launch_new(1); - } + if(connection_ap_handshake_attach_circuit(conn) < 0) + circuit_launch_new(1); /* Build another circuit to handle this stream */ return 0; } @@ -569,7 +568,7 @@ static int connection_ap_handshake_attach_circuit(connection_t *conn) { assert(conn->socks_request); /* find the circuit that we should use, if there is one. */ - circ = circuit_get_newest_open(conn); + circ = circuit_get_newest(conn, 1); if(!circ) { log_fn(LOG_INFO,"No safe circuit ready for edge connection; delaying."); diff --git a/src/or/main.c b/src/or/main.c index ad3c1304f3..19aae30447 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -341,7 +341,11 @@ static void run_scheduled_events(time_t now) { * and we make a new circ if there are no clean circuits. */ if(options.SocksPort) { - circ = circuit_get_newest_open(NULL); + + /* launch a new circ for any pending streams that need one */ + connection_ap_attach_pending(); + + circ = circuit_get_newest(NULL, 1); if(time_to_new_circuit < now) { client_dns_clean(); circuit_expire_unused_circuits(); @@ -352,12 +356,8 @@ static void run_scheduled_events(time_t now) { } time_to_new_circuit = now + options.NewCircuitPeriod; } - if(!circ) { + if(!circ) circuit_launch_new(1); - } - /* XXX also check if we have any circuit_pending streams and we're not - * currently building a circuit for them. - */ } /* 3. Every second, we check how much bandwidth we've consumed and diff --git a/src/or/or.h b/src/or/or.h index b2b4617a1b..fe9196e08d 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -187,6 +187,7 @@ #define RELAY_COMMAND_EXTENDED 7 #define RELAY_COMMAND_TRUNCATE 8 #define RELAY_COMMAND_TRUNCATED 9 +#define RELAY_COMMAND_DROP 10 #define RELAY_HEADER_SIZE 8 @@ -515,7 +516,7 @@ void circuit_free_cpath(crypt_path_t *cpath); circuit_t *circuit_enumerate_by_naddr_nport(circuit_t *start, uint32_t naddr, uint16_t nport); 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_open(connection_t *conn); +circuit_t *circuit_get_newest(connection_t *conn, int must_be_open); int circuit_deliver_relay_cell(cell_t *cell, circuit_t *circ, int cell_direction, crypt_path_t *layer_hint);