|
@@ -70,6 +70,9 @@ uint64_t stats_n_relay_cells_relayed = 0;
|
|
|
*/
|
|
|
uint64_t stats_n_relay_cells_delivered = 0;
|
|
|
|
|
|
+/** Used to tell which stream to read from first on a circuit. */
|
|
|
+static tor_weak_rng_t stream_choice_rng = TOR_WEAK_RNG_INIT;
|
|
|
+
|
|
|
/** Update digest from the payload of cell. Assign integrity part to
|
|
|
* cell.
|
|
|
*/
|
|
@@ -1740,6 +1743,12 @@ circuit_resume_edge_reading(circuit_t *circ, crypt_path_t *layer_hint)
|
|
|
circ, layer_hint);
|
|
|
}
|
|
|
|
|
|
+void
|
|
|
+stream_choice_seed_weak_rng(void)
|
|
|
+{
|
|
|
+ crypto_seed_weak_rng(&stream_choice_rng);
|
|
|
+}
|
|
|
+
|
|
|
/** A helper function for circuit_resume_edge_reading() above.
|
|
|
* The arguments are the same, except that <b>conn</b> is the head
|
|
|
* of a linked list of edge streams that should each be considered.
|
|
@@ -1755,11 +1764,18 @@ circuit_resume_edge_reading_helper(edge_connection_t *first_conn,
|
|
|
int cells_on_queue;
|
|
|
int cells_per_conn;
|
|
|
edge_connection_t *chosen_stream = NULL;
|
|
|
+ int max_to_package;
|
|
|
+
|
|
|
+ if (first_conn == NULL) {
|
|
|
+ /* Don't bother to try to do the rest of this if there are no connections
|
|
|
+ * to resume. */
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
|
|
|
/* How many cells do we have space for? It will be the minimum of
|
|
|
* the number needed to exhaust the package window, and the minimum
|
|
|
* needed to fill the cell queue. */
|
|
|
- int max_to_package = circ->package_window;
|
|
|
+ max_to_package = circ->package_window;
|
|
|
if (CIRCUIT_IS_ORIGIN(circ)) {
|
|
|
cells_on_queue = circ->n_chan_cells.n;
|
|
|
} else {
|
|
@@ -1784,10 +1800,19 @@ circuit_resume_edge_reading_helper(edge_connection_t *first_conn,
|
|
|
int num_streams = 0;
|
|
|
for (conn = first_conn; conn; conn = conn->next_stream) {
|
|
|
num_streams++;
|
|
|
- if ((tor_weak_random() % num_streams)==0)
|
|
|
+ if (tor_weak_random_one_in_n(&stream_choice_rng, num_streams)) {
|
|
|
chosen_stream = conn;
|
|
|
+ }
|
|
|
/* Invariant: chosen_stream has been chosen uniformly at random from
|
|
|
- * among the first num_streams streams on first_conn. */
|
|
|
+ * among the first num_streams streams on first_conn.
|
|
|
+ *
|
|
|
+ * (Note that we iterate over every stream on the circuit, so that after
|
|
|
+ * we've considered the first stream, we've chosen it with P=1; and
|
|
|
+ * after we consider the second stream, we've switched to it with P=1/2
|
|
|
+ * and stayed with the first stream with P=1/2; and after we've
|
|
|
+ * considered the third stream, we've switched to it with P=1/3 and
|
|
|
+ * remained with one of the first two streams with P=(2/3), giving each
|
|
|
+ * one P=(1/2)(2/3) )=(1/3).) */
|
|
|
}
|
|
|
}
|
|
|
|