Loading src/or/circuit.c +69 −50 Changes for src/or/circuit.c: 69 added lines, 50 removed lines. Original line number Diff line number Diff line Loading @@ -250,56 +250,38 @@ circuit_t *circuit_get_by_conn(connection_t *conn) { return NULL; } /* Dear god this function needs refactoring. */ /* Find the best circ that conn can use, preferably one which is * dirty. Circ must not be too old. * If !conn, return newest. * * If must_be_open, ignore circs not in CIRCUIT_STATE_OPEN. * * circ_purpose specifies what sort of circuit we must have. * It can be C_GENERAL, C_INTRODUCING, or C_REND_JOINED. * * If it's REND_JOINED and must_be_open==0, then return the closest * rendezvous-purposed circuit that you can find. * * If circ_purpose is not GENERAL, then conn must be defined. /* Return 1 iff 'c' could be returned by circuit_get_best. */ circuit_t *circuit_get_best(connection_t *conn, int must_be_open, uint8_t purpose) { circuit_t *circ, *best=NULL; static int circuit_is_acceptable(circuit_t *circ, connection_t *conn, int must_be_open, uint8_t purpose, time_t now) { routerinfo_t *exitrouter; time_t now = time(NULL); assert(purpose == CIRCUIT_PURPOSE_C_GENERAL || purpose == CIRCUIT_PURPOSE_C_INTRODUCING || 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 */ return 0; /* this circ doesn't start at us */ if (must_be_open && (circ->state != CIRCUIT_STATE_OPEN || !circ->n_conn)) continue; /* ignore non-open circs */ return 0; /* ignore non-open circs */ if (circ->marked_for_close) continue; return 0; /* if this circ isn't our purpose, skip. */ if(purpose == CIRCUIT_PURPOSE_C_REND_JOINED) { if(must_be_open && purpose != circ->purpose) continue; 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) continue; return 0; } else { if(purpose != circ->purpose) continue; return 0; } if(purpose == CIRCUIT_PURPOSE_C_GENERAL) if(circ->timestamp_dirty && circ->timestamp_dirty+options.NewCircuitPeriod < now) continue; /* too old */ return 0; if(conn) { /* decide if this circ is suitable for this conn */ Loading @@ -316,53 +298,90 @@ circuit_t *circuit_get_best(connection_t *conn, if(!exitrouter) { log_fn(LOG_INFO,"Skipping broken circ (exit router vanished)"); continue; /* this circuit is screwed and doesn't know it yet */ 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 */ continue; return 0; } } else { /* not general */ if(rend_cmp_service_ids(conn->rend_query, circ->rend_query)) { /* this circ is not for this conn */ continue; return 0; } } } return 0; } /* 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. /* Return 1 iff circuit 'a' is better than circuit 'b' for purpose. Used by * circuit_get_best */ if(!best) best = circ; 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(best->timestamp_dirty) { if(circ->timestamp_dirty && circ->timestamp_dirty > best->timestamp_dirty) best = circ; if(b->timestamp_dirty) { if(a->timestamp_dirty && a->timestamp_dirty > b->timestamp_dirty) return 1; } else { if(circ->timestamp_dirty || circ->timestamp_created > best->timestamp_created) best = circ; if(a->timestamp_dirty || a->timestamp_created > b->timestamp_created) return 1; } break; case CIRCUIT_PURPOSE_C_INTRODUCING: /* more recently created is best */ if(circ->timestamp_created > best->timestamp_created) best = circ; 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(circ->purpose > best->purpose) best = circ; 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. * * If must_be_open, ignore circs not in CIRCUIT_STATE_OPEN. * * circ_purpose specifies what sort of circuit we must have. * It can be C_GENERAL, C_INTRODUCING, or C_REND_JOINED. * * If it's REND_JOINED and must_be_open==0, then return the closest * rendezvous-purposed circuit that you can find. * * If circ_purpose is not GENERAL, then conn must be defined. */ circuit_t *circuit_get_best(connection_t *conn, int must_be_open, uint8_t purpose) { circuit_t *circ, *best=NULL; time_t now = time(NULL); assert(purpose == CIRCUIT_PURPOSE_C_GENERAL || purpose == CIRCUIT_PURPOSE_C_INTRODUCING || purpose == CIRCUIT_PURPOSE_C_REND_JOINED); for (circ=global_circuitlist;circ;circ = circ->next) { if (!circuit_is_acceptable(circ,conn,must_be_open,purpose,now)) 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 || circuit_is_better(circ,best,purpose)) best = circ; } return best; Loading Loading
src/or/circuit.c +69 −50 Changes for src/or/circuit.c: 69 added lines, 50 removed lines. Original line number Diff line number Diff line Loading @@ -250,56 +250,38 @@ circuit_t *circuit_get_by_conn(connection_t *conn) { return NULL; } /* Dear god this function needs refactoring. */ /* Find the best circ that conn can use, preferably one which is * dirty. Circ must not be too old. * If !conn, return newest. * * If must_be_open, ignore circs not in CIRCUIT_STATE_OPEN. * * circ_purpose specifies what sort of circuit we must have. * It can be C_GENERAL, C_INTRODUCING, or C_REND_JOINED. * * If it's REND_JOINED and must_be_open==0, then return the closest * rendezvous-purposed circuit that you can find. * * If circ_purpose is not GENERAL, then conn must be defined. /* Return 1 iff 'c' could be returned by circuit_get_best. */ circuit_t *circuit_get_best(connection_t *conn, int must_be_open, uint8_t purpose) { circuit_t *circ, *best=NULL; static int circuit_is_acceptable(circuit_t *circ, connection_t *conn, int must_be_open, uint8_t purpose, time_t now) { routerinfo_t *exitrouter; time_t now = time(NULL); assert(purpose == CIRCUIT_PURPOSE_C_GENERAL || purpose == CIRCUIT_PURPOSE_C_INTRODUCING || 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 */ return 0; /* this circ doesn't start at us */ if (must_be_open && (circ->state != CIRCUIT_STATE_OPEN || !circ->n_conn)) continue; /* ignore non-open circs */ return 0; /* ignore non-open circs */ if (circ->marked_for_close) continue; return 0; /* if this circ isn't our purpose, skip. */ if(purpose == CIRCUIT_PURPOSE_C_REND_JOINED) { if(must_be_open && purpose != circ->purpose) continue; 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) continue; return 0; } else { if(purpose != circ->purpose) continue; return 0; } if(purpose == CIRCUIT_PURPOSE_C_GENERAL) if(circ->timestamp_dirty && circ->timestamp_dirty+options.NewCircuitPeriod < now) continue; /* too old */ return 0; if(conn) { /* decide if this circ is suitable for this conn */ Loading @@ -316,53 +298,90 @@ circuit_t *circuit_get_best(connection_t *conn, if(!exitrouter) { log_fn(LOG_INFO,"Skipping broken circ (exit router vanished)"); continue; /* this circuit is screwed and doesn't know it yet */ 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 */ continue; return 0; } } else { /* not general */ if(rend_cmp_service_ids(conn->rend_query, circ->rend_query)) { /* this circ is not for this conn */ continue; return 0; } } } return 0; } /* 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. /* Return 1 iff circuit 'a' is better than circuit 'b' for purpose. Used by * circuit_get_best */ if(!best) best = circ; 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(best->timestamp_dirty) { if(circ->timestamp_dirty && circ->timestamp_dirty > best->timestamp_dirty) best = circ; if(b->timestamp_dirty) { if(a->timestamp_dirty && a->timestamp_dirty > b->timestamp_dirty) return 1; } else { if(circ->timestamp_dirty || circ->timestamp_created > best->timestamp_created) best = circ; if(a->timestamp_dirty || a->timestamp_created > b->timestamp_created) return 1; } break; case CIRCUIT_PURPOSE_C_INTRODUCING: /* more recently created is best */ if(circ->timestamp_created > best->timestamp_created) best = circ; 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(circ->purpose > best->purpose) best = circ; 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. * * If must_be_open, ignore circs not in CIRCUIT_STATE_OPEN. * * circ_purpose specifies what sort of circuit we must have. * It can be C_GENERAL, C_INTRODUCING, or C_REND_JOINED. * * If it's REND_JOINED and must_be_open==0, then return the closest * rendezvous-purposed circuit that you can find. * * If circ_purpose is not GENERAL, then conn must be defined. */ circuit_t *circuit_get_best(connection_t *conn, int must_be_open, uint8_t purpose) { circuit_t *circ, *best=NULL; time_t now = time(NULL); assert(purpose == CIRCUIT_PURPOSE_C_GENERAL || purpose == CIRCUIT_PURPOSE_C_INTRODUCING || purpose == CIRCUIT_PURPOSE_C_REND_JOINED); for (circ=global_circuitlist;circ;circ = circ->next) { if (!circuit_is_acceptable(circ,conn,must_be_open,purpose,now)) 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 || circuit_is_better(circ,best,purpose)) best = circ; } return best; Loading