|
@@ -1547,8 +1547,8 @@ connection_or_exact_get_by_addr_port(uint32_t addr, uint16_t port)
|
|
|
return best;
|
|
|
}
|
|
|
|
|
|
-/** Return a connection with give type, address, port, and purpose or NULL if
|
|
|
- * no such connection exists. */
|
|
|
+/** Return a connection with given type, address, port, and purpose;
|
|
|
+ * or NULL if no such connection exists. */
|
|
|
connection_t *
|
|
|
connection_get_by_type_addr_port_purpose(int type, uint32_t addr, uint16_t port,
|
|
|
int purpose)
|
|
@@ -1570,22 +1570,42 @@ connection_get_by_type_addr_port_purpose(int type, uint32_t addr, uint16_t port,
|
|
|
return NULL;
|
|
|
}
|
|
|
|
|
|
+/** Return the best connection of type OR with the
|
|
|
+ * digest <b>digest</b> that we have, or NULL if we have none.
|
|
|
+ *
|
|
|
+ * 1) Don't return it if it's marked for close.
|
|
|
+ * 2) If there are any open conns, ignore non-open conns.
|
|
|
+ * 3) If there are any non-obsolete conns, ignore obsolete conns.
|
|
|
+ * 4) Then if there are any non-empty conns, ignore empty conns.
|
|
|
+ * 5) Of the remaining conns, prefer newer conns.
|
|
|
+ */
|
|
|
connection_t *
|
|
|
-connection_get_by_identity_digest(const char *digest, int type)
|
|
|
+connection_get_by_identity_digest(const char *digest)
|
|
|
{
|
|
|
- int i, n;
|
|
|
+ int i, n, newer;
|
|
|
connection_t *conn, *best=NULL;
|
|
|
connection_t **carray;
|
|
|
|
|
|
get_connection_array(&carray,&n);
|
|
|
for (i=0;i<n;i++) {
|
|
|
conn = carray[i];
|
|
|
- if (conn->type != type)
|
|
|
+ if (conn->marked_for_close ||
|
|
|
+ memcmp(conn->identity_digest, digest, DIGEST_LEN))
|
|
|
continue;
|
|
|
- if (!memcmp(conn->identity_digest, digest, DIGEST_LEN) &&
|
|
|
- !conn->marked_for_close &&
|
|
|
- (!best || best->timestamp_created < conn->timestamp_created))
|
|
|
- best = conn;
|
|
|
+ if (!best) {
|
|
|
+ best = conn; /* whatever it is, it's better than nothing. */
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ if (best->state == OR_CONN_STATE_OPEN &&
|
|
|
+ conn->state != OR_CONN_STATE_OPEN)
|
|
|
+ continue; /* avoid non-open conns if we can */
|
|
|
+ newer = best->timestamp_created < conn->timestamp_created;
|
|
|
+ if (conn->is_obsolete && (!best->is_obsolete || !newer))
|
|
|
+ continue; /* we have something, and it's better than this. */
|
|
|
+ if (circuit_get_by_conn(best) && !circuit_get_by_conn(conn))
|
|
|
+ continue; /* prefer conns with circuits on them */
|
|
|
+ if (newer)
|
|
|
+ best = conn; /* lastly, prefer newer conns */
|
|
|
}
|
|
|
return best;
|
|
|
}
|