diff options
author | Andrea Shepard <andrea@torproject.org> | 2013-11-13 16:50:26 -0800 |
---|---|---|
committer | Andrea Shepard <andrea@torproject.org> | 2014-09-30 22:49:03 -0700 |
commit | f314d9509cae7acb9a692895c709e7771c6321f0 (patch) | |
tree | c89991b3e4fb047ec694e9fa4d94b97850443af0 /src/or/channel.c | |
parent | 2fc3da3ff51f3fe7fa5338c2d6b52a06ed9c4f19 (diff) | |
download | tor-f314d9509cae7acb9a692895c709e7771c6321f0.tar.gz tor-f314d9509cae7acb9a692895c709e7771c6321f0.zip |
Fix return values from channel_flush_some_cells() to correctly count cells directly written by channel_flush_from_first_active_circuit()
Diffstat (limited to 'src/or/channel.c')
-rw-r--r-- | src/or/channel.c | 38 |
1 files changed, 35 insertions, 3 deletions
diff --git a/src/or/channel.c b/src/or/channel.c index e2d102d2ac..dddd7ab1f1 100644 --- a/src/or/channel.c +++ b/src/or/channel.c @@ -175,6 +175,7 @@ static cell_queue_entry_t * cell_queue_entry_new_fixed(cell_t *cell); static cell_queue_entry_t * cell_queue_entry_new_var(var_cell_t *var_cell); +static int chan_cell_queue_len(const chan_cell_queue_t *queue); static int is_destroy_cell(channel_t *chan, const cell_queue_entry_t *q, circid_t *circid_out); @@ -2218,6 +2219,7 @@ channel_flush_some_cells(channel_t *chan, ssize_t num_cells) unsigned int unlimited = 0; ssize_t flushed = 0; int num_cells_from_circs, clamped_num_cells; + int q_len_before, q_len_after; tor_assert(chan); @@ -2243,14 +2245,44 @@ channel_flush_some_cells(channel_t *chan, ssize_t num_cells) clamped_num_cells = (int)(num_cells - flushed); } } + + /* + * Keep track of the change in queue size; we have to count cells + * channel_flush_from_first_active_circuit() writes out directly, + * but not double-count ones we might get later in + * channel_flush_some_cells_from_outgoing_queue() + */ + q_len_before = chan_cell_queue_len(&(chan->outgoing_queue)); + /* Try to get more cells from any active circuits */ num_cells_from_circs = channel_flush_from_first_active_circuit( chan, clamped_num_cells); - /* If it claims we got some, process the queue again */ + q_len_after = chan_cell_queue_len(&(chan->outgoing_queue)); + + /* + * If it claims we got some, adjust the flushed counter and consider + * processing the queue again + */ if (num_cells_from_circs > 0) { - flushed += channel_flush_some_cells_from_outgoing_queue(chan, - (unlimited ? -1 : num_cells - flushed)); + /* + * Adjust flushed by the number of cells counted in + * num_cells_from_circs that didn't go to the cell queue. + */ + + if (q_len_after > q_len_before) { + num_cells_from_circs -= (q_len_after - q_len_before); + if (num_cells_from_circs < 0) num_cells_from_circs = 0; + } + + flushed += num_cells_from_circs; + + /* Now process the queue if necessary */ + + if (q_len_after > q_len_before && num_cells < flushed) { + flushed += channel_flush_some_cells_from_outgoing_queue(chan, + (unlimited ? -1 : num_cells - flushed)); + } } } } |