[or-cvs] Split out major functionality of circuit_get_best; rephrase...
Nick Mathewson
nickm at seul.org
Thu Apr 8 01:55:23 UTC 2004
Update of /home/or/cvsroot/src/or
In directory moria.mit.edu:/tmp/cvs-serv23322/src/or
Modified Files:
circuit.c
Log Message:
Split out major functionality of circuit_get_best; rephrase a few booleans
Index: circuit.c
===================================================================
RCS file: /home/or/cvsroot/src/or/circuit.c,v
retrieving revision 1.195
retrieving revision 1.196
diff -u -d -r1.195 -r1.196
--- circuit.c 7 Apr 2004 21:12:54 -0000 1.195
+++ circuit.c 8 Apr 2004 01:55:21 -0000 1.196
@@ -250,7 +250,106 @@
return NULL;
}
-/* Dear god this function needs refactoring. */
+/* Return 1 iff 'c' could be returned by circuit_get_best.
+ */
+static int circuit_is_acceptable(circuit_t *circ,
+ connection_t *conn,
+ int must_be_open,
+ uint8_t purpose,
+ time_t now)
+{
+ routerinfo_t *exitrouter;
+
+ if (!circ->cpath)
+ return 0; /* this circ doesn't start at us */
+ if (must_be_open && (circ->state != CIRCUIT_STATE_OPEN || !circ->n_conn))
+ return 0; /* ignore non-open circs */
+ if (circ->marked_for_close)
+ return 0;
+
+ /* if this circ isn't our purpose, skip. */
+ if(purpose == CIRCUIT_PURPOSE_C_REND_JOINED && !must_be_open) {
+ if(circ->purpose != CIRCUIT_PURPOSE_C_ESTABLISH_REND &&
+ circ->purpose != CIRCUIT_PURPOSE_C_REND_READY &&
+ circ->purpose != CIRCUIT_PURPOSE_C_REND_JOINED)
+ return 0;
+ } else {
+ if(purpose != circ->purpose)
+ return 0;
+ }
+
+ if(purpose == CIRCUIT_PURPOSE_C_GENERAL)
+ if(circ->timestamp_dirty &&
+ circ->timestamp_dirty+options.NewCircuitPeriod < now)
+ return 0;
+
+ if(conn) {
+ /* decide if this circ is suitable for this 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 */
+ /* for rend circs, circ->cpath->prev is not the last router in the
+ * circuit, it's the magical extra bob hop. so just check the nickname
+ * of the one we meant to finish at.
+ */
+ exitrouter = router_get_by_nickname(circ->build_state->chosen_exit);
+
+ if(!exitrouter) {
+ log_fn(LOG_INFO,"Skipping broken circ (exit router vanished)");
+ return 0; /* this circuit is screwed and doesn't know it yet */
+ }
+
+ if(purpose == CIRCUIT_PURPOSE_C_GENERAL) {
+ if(connection_ap_can_use_exit(conn, exitrouter) == ADDR_POLICY_REJECTED) {
+ /* can't exit from this router */
+ return 0;
+ }
+ } else { /* not general */
+ if(rend_cmp_service_ids(conn->rend_query, circ->rend_query)) {
+ /* this circ is not for this conn */
+ return 0;
+ }
+ }
+ }
+ return 0;
+}
+
+/* Return 1 iff circuit 'a' is better than circuit 'b' for purpose. Used by
+ * circuit_get_best
+ */
+static int circuit_is_better(circuit_t *a, circuit_t *b, uint8_t purpose)
+{
+ switch(purpose) {
+ case CIRCUIT_PURPOSE_C_GENERAL:
+ /* if it's used but less dirty it's best;
+ * else if it's more recently created it's best
+ */
+ if(b->timestamp_dirty) {
+ if(a->timestamp_dirty &&
+ a->timestamp_dirty > b->timestamp_dirty)
+ return 1;
+ } else {
+ if(a->timestamp_dirty ||
+ a->timestamp_created > b->timestamp_created)
+ return 1;
+ }
+ break;
+ case CIRCUIT_PURPOSE_C_INTRODUCING:
+ /* more recently created is best */
+ if(a->timestamp_created > b->timestamp_created)
+ return 1;
+ break;
+ case CIRCUIT_PURPOSE_C_REND_JOINED:
+ /* the closer it is to rend_joined the better it is */
+ if(a->purpose > b->purpose)
+ return 1;
+ break;
+ }
+ return 0;
+}
+
/* Find the best circ that conn can use, preferably one which is
* dirty. Circ must not be too old.
* If !conn, return newest.
@@ -268,7 +367,6 @@
circuit_t *circuit_get_best(connection_t *conn,
int must_be_open, uint8_t purpose) {
circuit_t *circ, *best=NULL;
- routerinfo_t *exitrouter;
time_t now = time(NULL);
assert(purpose == CIRCUIT_PURPOSE_C_GENERAL ||
@@ -276,93 +374,14 @@
purpose == CIRCUIT_PURPOSE_C_REND_JOINED);
for (circ=global_circuitlist;circ;circ = circ->next) {
- 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 (circ->marked_for_close)
+ if (!circuit_is_acceptable(circ,conn,must_be_open,purpose,now))
continue;
- /* if this circ isn't our purpose, skip. */
- if(purpose == CIRCUIT_PURPOSE_C_REND_JOINED) {
- if(must_be_open && purpose != circ->purpose)
- continue;
- if(circ->purpose != CIRCUIT_PURPOSE_C_ESTABLISH_REND &&
- circ->purpose != CIRCUIT_PURPOSE_C_REND_READY &&
- circ->purpose != CIRCUIT_PURPOSE_C_REND_JOINED)
- continue;
- } else {
- if(purpose != circ->purpose)
- continue;
- }
-
- if(purpose == CIRCUIT_PURPOSE_C_GENERAL)
- if(circ->timestamp_dirty &&
- circ->timestamp_dirty+options.NewCircuitPeriod < now)
- continue; /* too old */
-
- if(conn) {
- /* decide if this circ is suitable for this 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 */
-/* for rend circs, circ->cpath->prev is not the last router in the
- * circuit, it's the magical extra bob hop. so just check the nickname
- * of the one we meant to finish at.
- */
- exitrouter = router_get_by_nickname(circ->build_state->chosen_exit);
-
- if(!exitrouter) {
- log_fn(LOG_INFO,"Skipping broken circ (exit router vanished)");
- continue; /* this circuit is screwed and doesn't know it yet */
- }
-
- if(purpose == CIRCUIT_PURPOSE_C_GENERAL) {
- if(connection_ap_can_use_exit(conn, exitrouter) == ADDR_POLICY_REJECTED) {
- /* can't exit from this router */
- continue;
- }
- } else { /* not general */
- if(rend_cmp_service_ids(conn->rend_query, circ->rend_query)) {
- /* this circ is not for this conn */
- continue;
- }
- }
- }
-
/* now this is an acceptable circ to hand back. but that doesn't
* mean it's the *best* circ to hand back. try to decide.
*/
- if(!best)
+ if(!best || circuit_is_better(circ,best,purpose))
best = circ;
- switch(purpose) {
- case CIRCUIT_PURPOSE_C_GENERAL:
- /* if it's used but less dirty it's best;
- * else if it's more recently created it's best
- */
- if(best->timestamp_dirty) {
- if(circ->timestamp_dirty &&
- circ->timestamp_dirty > best->timestamp_dirty)
- best = circ;
- } else {
- if(circ->timestamp_dirty ||
- circ->timestamp_created > best->timestamp_created)
- best = circ;
- }
- break;
- case CIRCUIT_PURPOSE_C_INTRODUCING:
- /* more recently created is best */
- if(circ->timestamp_created > best->timestamp_created)
- best = circ;
- break;
- case CIRCUIT_PURPOSE_C_REND_JOINED:
- /* the closer it is to rend_joined the better it is */
- if(circ->purpose > best->purpose)
- best = circ;
- break;
- }
}
return best;
More information about the tor-commits
mailing list