Fix heap-use-after-free due to duplicated push of DATA item

This commit is contained in:
Tatsuhiro Tsujikawa 2014-11-06 23:43:10 +09:00
parent 154876a17b
commit 62ede05c09
4 changed files with 124 additions and 78 deletions

View File

@ -588,10 +588,11 @@ int nghttp2_session_reprioritize_stream
session->roots.num_streams <= NGHTTP2_MAX_DEP_TREE_LENGTH) { session->roots.num_streams <= NGHTTP2_MAX_DEP_TREE_LENGTH) {
rv = nghttp2_stream_dep_all_your_stream_are_belong_to_us rv = nghttp2_stream_dep_all_your_stream_are_belong_to_us
(stream, &session->ob_da_pq, session->last_cycle); (stream, &session->ob_da_pq, session->last_cycle, session->aob.item);
} else { } else {
rv = nghttp2_stream_dep_make_root(stream, &session->ob_da_pq, rv = nghttp2_stream_dep_make_root(stream, &session->ob_da_pq,
session->last_cycle); session->last_cycle,
session->aob.item);
} }
return rv; return rv;
@ -612,7 +613,7 @@ int nghttp2_session_reprioritize_stream
nghttp2_stream_dep_remove_subtree(dep_stream); nghttp2_stream_dep_remove_subtree(dep_stream);
nghttp2_stream_dep_make_root(dep_stream, &session->ob_da_pq, nghttp2_stream_dep_make_root(dep_stream, &session->ob_da_pq,
session->last_cycle); session->last_cycle, session->aob.item);
} }
nghttp2_stream_dep_remove_subtree(stream); nghttp2_stream_dep_remove_subtree(stream);
@ -625,16 +626,18 @@ int nghttp2_session_reprioritize_stream
if(root_stream->num_substreams + stream->num_substreams > if(root_stream->num_substreams + stream->num_substreams >
NGHTTP2_MAX_DEP_TREE_LENGTH) { NGHTTP2_MAX_DEP_TREE_LENGTH) {
rv = nghttp2_stream_dep_make_root(stream, &session->ob_da_pq, rv = nghttp2_stream_dep_make_root(stream, &session->ob_da_pq,
session->last_cycle); session->last_cycle, session->aob.item);
} else { } else {
if(pri_spec->exclusive) { if(pri_spec->exclusive) {
rv = nghttp2_stream_dep_insert_subtree(dep_stream, stream, rv = nghttp2_stream_dep_insert_subtree(dep_stream, stream,
&session->ob_da_pq, &session->ob_da_pq,
session->last_cycle); session->last_cycle,
session->aob.item);
} else { } else {
rv = nghttp2_stream_dep_add_subtree(dep_stream, stream, rv = nghttp2_stream_dep_add_subtree(dep_stream, stream,
&session->ob_da_pq, &session->ob_da_pq,
session->last_cycle); session->last_cycle,
session->aob.item);
} }
} }
@ -732,7 +735,8 @@ int nghttp2_session_add_item(nghttp2_session *session,
item->cycle = session->last_cycle; item->cycle = session->last_cycle;
rv = nghttp2_stream_attach_data(stream, item, &session->ob_da_pq, rv = nghttp2_stream_attach_data(stream, item, &session->ob_da_pq,
session->last_cycle); session->last_cycle,
session->aob.item);
if(rv != 0) { if(rv != 0) {
return rv; return rv;
@ -837,7 +841,7 @@ nghttp2_stream* nghttp2_session_open_stream(nghttp2_session *session,
if(pri_spec->exclusive && if(pri_spec->exclusive &&
session->roots.num_streams <= NGHTTP2_MAX_DEP_TREE_LENGTH) { session->roots.num_streams <= NGHTTP2_MAX_DEP_TREE_LENGTH) {
rv = nghttp2_stream_dep_all_your_stream_are_belong_to_us rv = nghttp2_stream_dep_all_your_stream_are_belong_to_us
(stream, &session->ob_da_pq, session->last_cycle); (stream, &session->ob_da_pq, session->last_cycle, session->aob.item);
/* Since no dpri is changed in dependency tree, the above /* Since no dpri is changed in dependency tree, the above
function call never fail. */ function call never fail. */
@ -896,7 +900,7 @@ int nghttp2_session_close_stream(nghttp2_session *session, int32_t stream_id,
item = stream->data_item; item = stream->data_item;
rv = nghttp2_stream_detach_data(stream, &session->ob_da_pq, rv = nghttp2_stream_detach_data(stream, &session->ob_da_pq,
session->last_cycle); session->last_cycle, session->aob.item);
if(rv != 0) { if(rv != 0) {
return rv; return rv;
@ -1790,7 +1794,8 @@ static int session_prep_frame(nghttp2_session *session,
int rv2; int rv2;
rv2 = nghttp2_stream_detach_data(stream, &session->ob_da_pq, rv2 = nghttp2_stream_detach_data(stream, &session->ob_da_pq,
session->last_cycle); session->last_cycle,
session->aob.item);
if(nghttp2_is_fatal(rv2)) { if(nghttp2_is_fatal(rv2)) {
return rv2; return rv2;
@ -1811,7 +1816,7 @@ static int session_prep_frame(nghttp2_session *session,
rv = nghttp2_stream_defer_data rv = nghttp2_stream_defer_data
(stream, NGHTTP2_STREAM_FLAG_DEFERRED_FLOW_CONTROL, (stream, NGHTTP2_STREAM_FLAG_DEFERRED_FLOW_CONTROL,
&session->ob_da_pq, session->last_cycle); &session->ob_da_pq, session->last_cycle, session->aob.item);
if(nghttp2_is_fatal(rv)) { if(nghttp2_is_fatal(rv)) {
return rv; return rv;
@ -1829,7 +1834,8 @@ static int session_prep_frame(nghttp2_session *session,
&item->aux_data.data); &item->aux_data.data);
if(framerv == NGHTTP2_ERR_DEFERRED) { if(framerv == NGHTTP2_ERR_DEFERRED) {
rv = nghttp2_stream_defer_data(stream, NGHTTP2_STREAM_FLAG_DEFERRED_USER, rv = nghttp2_stream_defer_data(stream, NGHTTP2_STREAM_FLAG_DEFERRED_USER,
&session->ob_da_pq, session->last_cycle); &session->ob_da_pq, session->last_cycle,
session->aob.item);
if(nghttp2_is_fatal(rv)) { if(nghttp2_is_fatal(rv)) {
return rv; return rv;
@ -1841,7 +1847,8 @@ static int session_prep_frame(nghttp2_session *session,
} }
if(framerv == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) { if(framerv == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) {
rv = nghttp2_stream_detach_data(stream, &session->ob_da_pq, rv = nghttp2_stream_detach_data(stream, &session->ob_da_pq,
session->last_cycle); session->last_cycle,
session->aob.item);
if(nghttp2_is_fatal(rv)) { if(nghttp2_is_fatal(rv)) {
return rv; return rv;
@ -1856,7 +1863,8 @@ static int session_prep_frame(nghttp2_session *session,
} }
if(framerv < 0) { if(framerv < 0) {
rv = nghttp2_stream_detach_data(stream, &session->ob_da_pq, rv = nghttp2_stream_detach_data(stream, &session->ob_da_pq,
session->last_cycle); session->last_cycle,
session->aob.item);
if(nghttp2_is_fatal(rv)) { if(nghttp2_is_fatal(rv)) {
return rv; return rv;
@ -2196,7 +2204,7 @@ static int session_after_frame_sent(nghttp2_session *session)
if(stream && aux_data->eof) { if(stream && aux_data->eof) {
rv = nghttp2_stream_detach_data(stream, &session->ob_da_pq, rv = nghttp2_stream_detach_data(stream, &session->ob_da_pq,
session->last_cycle); session->last_cycle, aob->item);
if(nghttp2_is_fatal(rv)) { if(nghttp2_is_fatal(rv)) {
return rv; return rv;
@ -2255,7 +2263,7 @@ static int session_after_frame_sent(nghttp2_session *session)
frame->hd.stream_id) != 0) { frame->hd.stream_id) != 0) {
if(stream) { if(stream) {
rv = nghttp2_stream_detach_data(stream, &session->ob_da_pq, rv = nghttp2_stream_detach_data(stream, &session->ob_da_pq,
session->last_cycle); session->last_cycle, aob->item);
if(nghttp2_is_fatal(rv)) { if(nghttp2_is_fatal(rv)) {
return rv; return rv;
@ -2301,7 +2309,7 @@ static int session_after_frame_sent(nghttp2_session *session)
} else { } else {
rv = nghttp2_stream_defer_data rv = nghttp2_stream_defer_data
(stream, NGHTTP2_STREAM_FLAG_DEFERRED_FLOW_CONTROL, (stream, NGHTTP2_STREAM_FLAG_DEFERRED_FLOW_CONTROL,
&session->ob_da_pq, session->last_cycle); &session->ob_da_pq, session->last_cycle, aob->item);
if(nghttp2_is_fatal(rv)) { if(nghttp2_is_fatal(rv)) {
return rv; return rv;
@ -2324,7 +2332,7 @@ static int session_after_frame_sent(nghttp2_session *session)
if(rv == NGHTTP2_ERR_DEFERRED) { if(rv == NGHTTP2_ERR_DEFERRED) {
rv = nghttp2_stream_defer_data rv = nghttp2_stream_defer_data
(stream, NGHTTP2_STREAM_FLAG_DEFERRED_USER, (stream, NGHTTP2_STREAM_FLAG_DEFERRED_USER,
&session->ob_da_pq, session->last_cycle); &session->ob_da_pq, session->last_cycle, aob->item);
if(nghttp2_is_fatal(rv)) { if(nghttp2_is_fatal(rv)) {
return rv; return rv;
@ -2348,7 +2356,7 @@ static int session_after_frame_sent(nghttp2_session *session)
} }
rv = nghttp2_stream_detach_data(stream, &session->ob_da_pq, rv = nghttp2_stream_detach_data(stream, &session->ob_da_pq,
session->last_cycle); session->last_cycle, aob->item);
if(nghttp2_is_fatal(rv)) { if(nghttp2_is_fatal(rv)) {
return rv; return rv;
@ -3283,7 +3291,8 @@ static int update_remote_initial_window_size_func
rv = nghttp2_stream_resume_deferred_data rv = nghttp2_stream_resume_deferred_data
(stream, NGHTTP2_STREAM_FLAG_DEFERRED_FLOW_CONTROL, (stream, NGHTTP2_STREAM_FLAG_DEFERRED_FLOW_CONTROL,
&arg->session->ob_da_pq, arg->session->last_cycle); &arg->session->ob_da_pq, arg->session->last_cycle,
arg->session->aob.item);
if(nghttp2_is_fatal(rv)) { if(nghttp2_is_fatal(rv)) {
return rv; return rv;
@ -3904,7 +3913,7 @@ static int session_on_stream_window_update_received
rv = nghttp2_stream_resume_deferred_data rv = nghttp2_stream_resume_deferred_data
(stream, NGHTTP2_STREAM_FLAG_DEFERRED_FLOW_CONTROL, &session->ob_da_pq, (stream, NGHTTP2_STREAM_FLAG_DEFERRED_FLOW_CONTROL, &session->ob_da_pq,
session->last_cycle); session->last_cycle, session->aob.item);
if(nghttp2_is_fatal(rv)) { if(nghttp2_is_fatal(rv)) {
return rv; return rv;
@ -5923,7 +5932,7 @@ int nghttp2_session_resume_data(nghttp2_session *session, int32_t stream_id)
rv = nghttp2_stream_resume_deferred_data rv = nghttp2_stream_resume_deferred_data
(stream, NGHTTP2_STREAM_FLAG_DEFERRED_USER, &session->ob_da_pq, (stream, NGHTTP2_STREAM_FLAG_DEFERRED_USER, &session->ob_da_pq,
session->last_cycle); session->last_cycle, session->aob.item);
if(nghttp2_is_fatal(rv)) { if(nghttp2_is_fatal(rv)) {
return rv; return rv;

View File

@ -86,13 +86,19 @@ void nghttp2_stream_shutdown(nghttp2_stream *stream, nghttp2_shut_flag flag)
} }
static int stream_push_data(nghttp2_stream *stream, nghttp2_pq *pq, static int stream_push_data(nghttp2_stream *stream, nghttp2_pq *pq,
uint64_t cycle) uint64_t cycle, nghttp2_outbound_item *active_item)
{ {
int rv; int rv;
assert(stream->data_item); assert(stream->data_item);
assert(stream->data_item->queued == 0); assert(stream->data_item->queued == 0);
/* If stream->data_item is now sent, don't push it to the queue.
Otherwise, we may push same item twice. */
if(active_item == stream->data_item) {
return 0;
}
if(stream->data_item->weight > stream->effective_weight) { if(stream->data_item->weight > stream->effective_weight) {
stream->data_item->weight = stream->effective_weight; stream->data_item->weight = stream->effective_weight;
} }
@ -297,7 +303,8 @@ static void stream_update_dep_set_top(nghttp2_stream *stream)
* Out of memory. * Out of memory.
*/ */
static int stream_update_dep_queue_top(nghttp2_stream *stream, nghttp2_pq *pq, static int stream_update_dep_queue_top(nghttp2_stream *stream, nghttp2_pq *pq,
uint64_t cycle) uint64_t cycle,
nghttp2_outbound_item *active_item)
{ {
int rv; int rv;
nghttp2_stream *si; nghttp2_stream *si;
@ -310,7 +317,7 @@ static int stream_update_dep_queue_top(nghttp2_stream *stream, nghttp2_pq *pq,
if(!stream->data_item->queued) { if(!stream->data_item->queued) {
DEBUGF(fprintf(stderr, "stream: stream=%d enqueue\n", DEBUGF(fprintf(stderr, "stream: stream=%d enqueue\n",
stream->stream_id)); stream->stream_id));
rv = stream_push_data(stream, pq, cycle); rv = stream_push_data(stream, pq, cycle, active_item);
if(rv != 0) { if(rv != 0) {
return rv; return rv;
@ -321,7 +328,7 @@ static int stream_update_dep_queue_top(nghttp2_stream *stream, nghttp2_pq *pq,
} }
for(si = stream->dep_next; si; si = si->sib_next) { for(si = stream->dep_next; si; si = si->sib_next) {
rv = stream_update_dep_queue_top(si, pq, cycle); rv = stream_update_dep_queue_top(si, pq, cycle, active_item);
if(rv != 0) { if(rv != 0) {
return rv; return rv;
@ -379,7 +386,8 @@ static int stream_update_dep_sum_norest_weight(nghttp2_stream *stream)
} }
static int stream_update_dep_on_attach_data(nghttp2_stream *stream, static int stream_update_dep_on_attach_data(nghttp2_stream *stream,
nghttp2_pq *pq, uint64_t cycle) nghttp2_pq *pq, uint64_t cycle,
nghttp2_outbound_item *active_item)
{ {
nghttp2_stream *root_stream; nghttp2_stream *root_stream;
@ -396,11 +404,12 @@ static int stream_update_dep_on_attach_data(nghttp2_stream *stream,
stream_update_dep_sum_norest_weight(root_stream); stream_update_dep_sum_norest_weight(root_stream);
stream_update_dep_effective_weight(root_stream); stream_update_dep_effective_weight(root_stream);
return stream_update_dep_queue_top(root_stream, pq, cycle); return stream_update_dep_queue_top(root_stream, pq, cycle, active_item);
} }
static int stream_update_dep_on_detach_data(nghttp2_stream *stream, static int stream_update_dep_on_detach_data(nghttp2_stream *stream,
nghttp2_pq *pq, uint64_t cycle) nghttp2_pq *pq, uint64_t cycle,
nghttp2_outbound_item *active_item)
{ {
nghttp2_stream *root_stream; nghttp2_stream *root_stream;
@ -413,13 +422,14 @@ static int stream_update_dep_on_detach_data(nghttp2_stream *stream,
stream_update_dep_sum_norest_weight(root_stream); stream_update_dep_sum_norest_weight(root_stream);
stream_update_dep_effective_weight(root_stream); stream_update_dep_effective_weight(root_stream);
return stream_update_dep_queue_top(root_stream, pq, cycle); return stream_update_dep_queue_top(root_stream, pq, cycle, active_item);
} }
int nghttp2_stream_attach_data(nghttp2_stream *stream, int nghttp2_stream_attach_data(nghttp2_stream *stream,
nghttp2_outbound_item *data_item, nghttp2_outbound_item *data_item,
nghttp2_pq *pq, nghttp2_pq *pq,
uint64_t cycle) uint64_t cycle,
nghttp2_outbound_item *active_item)
{ {
assert((stream->flags & NGHTTP2_STREAM_FLAG_DEFERRED_ALL) == 0); assert((stream->flags & NGHTTP2_STREAM_FLAG_DEFERRED_ALL) == 0);
assert(stream->data_item == NULL); assert(stream->data_item == NULL);
@ -429,11 +439,12 @@ int nghttp2_stream_attach_data(nghttp2_stream *stream,
stream->data_item = data_item; stream->data_item = data_item;
return stream_update_dep_on_attach_data(stream, pq, cycle); return stream_update_dep_on_attach_data(stream, pq, cycle, active_item);
} }
int nghttp2_stream_detach_data(nghttp2_stream *stream, nghttp2_pq *pq, int nghttp2_stream_detach_data(nghttp2_stream *stream, nghttp2_pq *pq,
uint64_t cycle) uint64_t cycle,
nghttp2_outbound_item *active_item)
{ {
DEBUGF(fprintf(stderr, "stream: stream=%d detach data=%p\n", DEBUGF(fprintf(stderr, "stream: stream=%d detach data=%p\n",
stream->stream_id, stream->data_item)); stream->stream_id, stream->data_item));
@ -441,11 +452,12 @@ int nghttp2_stream_detach_data(nghttp2_stream *stream, nghttp2_pq *pq,
stream->data_item = NULL; stream->data_item = NULL;
stream->flags &= ~NGHTTP2_STREAM_FLAG_DEFERRED_ALL; stream->flags &= ~NGHTTP2_STREAM_FLAG_DEFERRED_ALL;
return stream_update_dep_on_detach_data(stream, pq, cycle); return stream_update_dep_on_detach_data(stream, pq, cycle, active_item);
} }
int nghttp2_stream_defer_data(nghttp2_stream *stream, uint8_t flags, int nghttp2_stream_defer_data(nghttp2_stream *stream, uint8_t flags,
nghttp2_pq *pq, uint64_t cycle) nghttp2_pq *pq, uint64_t cycle,
nghttp2_outbound_item *active_item)
{ {
assert(stream->data_item); assert(stream->data_item);
@ -454,11 +466,12 @@ int nghttp2_stream_defer_data(nghttp2_stream *stream, uint8_t flags,
stream->flags |= flags; stream->flags |= flags;
return stream_update_dep_on_detach_data(stream, pq, cycle); return stream_update_dep_on_detach_data(stream, pq, cycle, active_item);
} }
int nghttp2_stream_resume_deferred_data(nghttp2_stream *stream, uint8_t flags, int nghttp2_stream_resume_deferred_data(nghttp2_stream *stream, uint8_t flags,
nghttp2_pq *pq, uint64_t cycle) nghttp2_pq *pq, uint64_t cycle,
nghttp2_outbound_item *active_item)
{ {
assert(stream->data_item); assert(stream->data_item);
@ -471,7 +484,7 @@ int nghttp2_stream_resume_deferred_data(nghttp2_stream *stream, uint8_t flags,
return 0; return 0;
} }
return stream_update_dep_on_attach_data(stream, pq, cycle); return stream_update_dep_on_attach_data(stream, pq, cycle, active_item);
} }
int nghttp2_stream_check_deferred_data(nghttp2_stream *stream) int nghttp2_stream_check_deferred_data(nghttp2_stream *stream)
@ -805,7 +818,8 @@ void nghttp2_stream_dep_remove(nghttp2_stream *stream)
int nghttp2_stream_dep_insert_subtree(nghttp2_stream *dep_stream, int nghttp2_stream_dep_insert_subtree(nghttp2_stream *dep_stream,
nghttp2_stream *stream, nghttp2_stream *stream,
nghttp2_pq *pq, nghttp2_pq *pq,
uint64_t cycle) uint64_t cycle,
nghttp2_outbound_item *active_item)
{ {
nghttp2_stream *last_sib; nghttp2_stream *last_sib;
nghttp2_stream *dep_next; nghttp2_stream *dep_next;
@ -857,13 +871,14 @@ int nghttp2_stream_dep_insert_subtree(nghttp2_stream *dep_stream,
stream_update_dep_sum_norest_weight(root_stream); stream_update_dep_sum_norest_weight(root_stream);
stream_update_dep_effective_weight(root_stream); stream_update_dep_effective_weight(root_stream);
return stream_update_dep_queue_top(root_stream, pq, cycle); return stream_update_dep_queue_top(root_stream, pq, cycle, active_item);
} }
int nghttp2_stream_dep_add_subtree(nghttp2_stream *dep_stream, int nghttp2_stream_dep_add_subtree(nghttp2_stream *dep_stream,
nghttp2_stream *stream, nghttp2_stream *stream,
nghttp2_pq *pq, nghttp2_pq *pq,
uint64_t cycle) uint64_t cycle,
nghttp2_outbound_item *active_item)
{ {
nghttp2_stream *root_stream; nghttp2_stream *root_stream;
@ -892,7 +907,7 @@ int nghttp2_stream_dep_add_subtree(nghttp2_stream *dep_stream,
stream_update_dep_sum_norest_weight(root_stream); stream_update_dep_sum_norest_weight(root_stream);
stream_update_dep_effective_weight(root_stream); stream_update_dep_effective_weight(root_stream);
return stream_update_dep_queue_top(root_stream, pq, cycle); return stream_update_dep_queue_top(root_stream, pq, cycle, active_item);
} }
void nghttp2_stream_dep_remove_subtree(nghttp2_stream *stream) void nghttp2_stream_dep_remove_subtree(nghttp2_stream *stream)
@ -947,7 +962,8 @@ void nghttp2_stream_dep_remove_subtree(nghttp2_stream *stream)
} }
int nghttp2_stream_dep_make_root(nghttp2_stream *stream, nghttp2_pq *pq, int nghttp2_stream_dep_make_root(nghttp2_stream *stream, nghttp2_pq *pq,
uint64_t cycle) uint64_t cycle,
nghttp2_outbound_item *active_item)
{ {
DEBUGF(fprintf(stderr, "stream: dep_make_root stream(%p)=%d\n", DEBUGF(fprintf(stderr, "stream: dep_make_root stream(%p)=%d\n",
stream, stream->stream_id)); stream, stream->stream_id));
@ -963,11 +979,12 @@ int nghttp2_stream_dep_make_root(nghttp2_stream *stream, nghttp2_pq *pq,
stream_update_dep_sum_norest_weight(stream); stream_update_dep_sum_norest_weight(stream);
stream_update_dep_effective_weight(stream); stream_update_dep_effective_weight(stream);
return stream_update_dep_queue_top(stream, pq, cycle); return stream_update_dep_queue_top(stream, pq, cycle, active_item);
} }
int nghttp2_stream_dep_all_your_stream_are_belong_to_us int nghttp2_stream_dep_all_your_stream_are_belong_to_us
(nghttp2_stream *stream, nghttp2_pq *pq, uint64_t cycle) (nghttp2_stream *stream, nghttp2_pq *pq, uint64_t cycle,
nghttp2_outbound_item *active_item)
{ {
nghttp2_stream *first, *si; nghttp2_stream *first, *si;
@ -1022,7 +1039,7 @@ int nghttp2_stream_dep_all_your_stream_are_belong_to_us
nghttp2_stream_roots_remove_all(stream->roots); nghttp2_stream_roots_remove_all(stream->roots);
return nghttp2_stream_dep_make_root(stream, pq, cycle); return nghttp2_stream_dep_make_root(stream, pq, cycle, active_item);
} }
int nghttp2_stream_in_dep_tree(nghttp2_stream *stream) int nghttp2_stream_in_dep_tree(nghttp2_stream *stream)

View File

@ -216,7 +216,8 @@ void nghttp2_stream_shutdown(nghttp2_stream *stream, nghttp2_shut_flag flag);
* Out of memory * Out of memory
*/ */
int nghttp2_stream_defer_data(nghttp2_stream *stream, uint8_t flags, int nghttp2_stream_defer_data(nghttp2_stream *stream, uint8_t flags,
nghttp2_pq *pq, uint64_t cycle); nghttp2_pq *pq, uint64_t cycle,
nghttp2_outbound_item *active_item);
/* /*
* Put back deferred data in this stream to active state. The |flags| * Put back deferred data in this stream to active state. The |flags|
@ -227,7 +228,8 @@ int nghttp2_stream_defer_data(nghttp2_stream *stream, uint8_t flags,
* one of flag is still set, data does not become active. * one of flag is still set, data does not become active.
*/ */
int nghttp2_stream_resume_deferred_data(nghttp2_stream *stream, uint8_t flags, int nghttp2_stream_resume_deferred_data(nghttp2_stream *stream, uint8_t flags,
nghttp2_pq *pq, uint64_t cycle); nghttp2_pq *pq, uint64_t cycle,
nghttp2_outbound_item *active_item);
/* /*
* Returns nonzero if data item is deferred by whatever reason. * Returns nonzero if data item is deferred by whatever reason.
@ -339,7 +341,8 @@ void nghttp2_stream_dep_remove(nghttp2_stream *stream);
int nghttp2_stream_attach_data(nghttp2_stream *stream, int nghttp2_stream_attach_data(nghttp2_stream *stream,
nghttp2_outbound_item *data_item, nghttp2_outbound_item *data_item,
nghttp2_pq *pq, nghttp2_pq *pq,
uint64_t cycle); uint64_t cycle,
nghttp2_outbound_item *active_item);
/* /*
* Detaches |stream->data_item|. Updates dpri members in this * Detaches |stream->data_item|. Updates dpri members in this
@ -353,7 +356,8 @@ int nghttp2_stream_attach_data(nghttp2_stream *stream,
* Out of memory * Out of memory
*/ */
int nghttp2_stream_detach_data(nghttp2_stream *stream, nghttp2_pq *pq, int nghttp2_stream_detach_data(nghttp2_stream *stream, nghttp2_pq *pq,
uint64_t cycle); uint64_t cycle,
nghttp2_outbound_item *active_item);
/* /*
@ -369,7 +373,8 @@ int nghttp2_stream_detach_data(nghttp2_stream *stream, nghttp2_pq *pq,
int nghttp2_stream_dep_insert_subtree(nghttp2_stream *dep_stream, int nghttp2_stream_dep_insert_subtree(nghttp2_stream *dep_stream,
nghttp2_stream *stream, nghttp2_stream *stream,
nghttp2_pq *pq, nghttp2_pq *pq,
uint64_t cycle); uint64_t cycle,
nghttp2_outbound_item *active_item);
/* /*
* Makes the |stream| depend on the |dep_stream|. This dependency is * Makes the |stream| depend on the |dep_stream|. This dependency is
@ -384,7 +389,8 @@ int nghttp2_stream_dep_insert_subtree(nghttp2_stream *dep_stream,
int nghttp2_stream_dep_add_subtree(nghttp2_stream *dep_stream, int nghttp2_stream_dep_add_subtree(nghttp2_stream *dep_stream,
nghttp2_stream *stream, nghttp2_stream *stream,
nghttp2_pq *pq, nghttp2_pq *pq,
uint64_t cycle); uint64_t cycle,
nghttp2_outbound_item *active_item);
/* /*
* Removes subtree whose root stream is |stream|. Removing subtree * Removes subtree whose root stream is |stream|. Removing subtree
@ -410,7 +416,8 @@ void nghttp2_stream_dep_remove_subtree(nghttp2_stream *stream);
* Out of memory * Out of memory
*/ */
int nghttp2_stream_dep_make_root(nghttp2_stream *stream, nghttp2_pq *pq, int nghttp2_stream_dep_make_root(nghttp2_stream *stream, nghttp2_pq *pq,
uint64_t cycle); uint64_t cycle,
nghttp2_outbound_item *active_item);
/* /*
* Makes the |stream| as root and all existing root streams become * Makes the |stream| as root and all existing root streams become
@ -423,7 +430,8 @@ int nghttp2_stream_dep_make_root(nghttp2_stream *stream, nghttp2_pq *pq,
* Out of memory * Out of memory
*/ */
int nghttp2_stream_dep_all_your_stream_are_belong_to_us int nghttp2_stream_dep_all_your_stream_are_belong_to_us
(nghttp2_stream *stream, nghttp2_pq *pq, uint64_t cycle); (nghttp2_stream *stream, nghttp2_pq *pq, uint64_t cycle,
nghttp2_outbound_item *active_item);
/* /*
* Returns nonzero if |stream| is in any dependency tree. * Returns nonzero if |stream| is in any dependency tree.

View File

@ -2564,7 +2564,8 @@ void test_nghttp2_session_on_window_update_received(void)
CU_ASSERT(0 == nghttp2_stream_attach_data(stream, data_item, CU_ASSERT(0 == nghttp2_stream_attach_data(stream, data_item,
&session->ob_da_pq, &session->ob_da_pq,
session->last_cycle)); session->last_cycle,
NULL));
nghttp2_frame_window_update_init(&frame.window_update, NGHTTP2_FLAG_NONE, nghttp2_frame_window_update_init(&frame.window_update, NGHTTP2_FLAG_NONE,
1, 16*1024); 1, 16*1024);
@ -2575,7 +2576,7 @@ void test_nghttp2_session_on_window_update_received(void)
CU_ASSERT(0 == nghttp2_stream_defer_data CU_ASSERT(0 == nghttp2_stream_defer_data
(stream, NGHTTP2_STREAM_FLAG_DEFERRED_FLOW_CONTROL, (stream, NGHTTP2_STREAM_FLAG_DEFERRED_FLOW_CONTROL,
&session->ob_da_pq, session->last_cycle)); &session->ob_da_pq, session->last_cycle, NULL));
CU_ASSERT(0 == nghttp2_session_on_window_update_received(session, &frame)); CU_ASSERT(0 == nghttp2_session_on_window_update_received(session, &frame));
CU_ASSERT(2 == user_data.frame_recv_cb_called); CU_ASSERT(2 == user_data.frame_recv_cb_called);
@ -5656,7 +5657,7 @@ void test_nghttp2_session_stream_dep_add_subtree(void)
*/ */
nghttp2_stream_dep_add_subtree(a, e, &session->ob_da_pq, nghttp2_stream_dep_add_subtree(a, e, &session->ob_da_pq,
session->last_cycle); session->last_cycle, NULL);
/* becomes /* becomes
* a * a
@ -5708,7 +5709,7 @@ void test_nghttp2_session_stream_dep_add_subtree(void)
*/ */
nghttp2_stream_dep_insert_subtree(a, e, &session->ob_da_pq, nghttp2_stream_dep_insert_subtree(a, e, &session->ob_da_pq,
session->last_cycle); session->last_cycle, NULL);
/* becomes /* becomes
* a * a
@ -5901,7 +5902,7 @@ void test_nghttp2_session_stream_dep_all_your_stream_are_belong_to_us(void)
nghttp2_stream_dep_remove_subtree(c); nghttp2_stream_dep_remove_subtree(c);
CU_ASSERT(0 == nghttp2_stream_dep_all_your_stream_are_belong_to_us CU_ASSERT(0 == nghttp2_stream_dep_all_your_stream_are_belong_to_us
(c, &session->ob_da_pq, session->last_cycle)); (c, &session->ob_da_pq, session->last_cycle, NULL));
/* /*
* c * c
@ -5939,7 +5940,7 @@ void test_nghttp2_session_stream_dep_all_your_stream_are_belong_to_us(void)
nghttp2_stream_dep_remove_subtree(c); nghttp2_stream_dep_remove_subtree(c);
CU_ASSERT(0 == nghttp2_stream_dep_all_your_stream_are_belong_to_us CU_ASSERT(0 == nghttp2_stream_dep_all_your_stream_are_belong_to_us
(c, &session->ob_da_pq, session->last_cycle)); (c, &session->ob_da_pq, session->last_cycle, NULL));
/* /*
* c * c
@ -5976,7 +5977,7 @@ void test_nghttp2_session_stream_dep_all_your_stream_are_belong_to_us(void)
nghttp2_stream_dep_remove_subtree(c); nghttp2_stream_dep_remove_subtree(c);
CU_ASSERT(0 == nghttp2_stream_dep_all_your_stream_are_belong_to_us CU_ASSERT(0 == nghttp2_stream_dep_all_your_stream_are_belong_to_us
(c, &session->ob_da_pq, session->last_cycle)); (c, &session->ob_da_pq, session->last_cycle, NULL));
/* /*
* c * c
@ -6029,7 +6030,8 @@ void test_nghttp2_session_stream_attach_data(void)
db = create_data_ob_item(); db = create_data_ob_item();
nghttp2_stream_attach_data(b, db, &session->ob_da_pq, session->last_cycle); nghttp2_stream_attach_data(b, db, &session->ob_da_pq, session->last_cycle,
NULL);
CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_DATA == a->dpri); CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_DATA == a->dpri);
CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == b->dpri); CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == b->dpri);
@ -6044,7 +6046,8 @@ void test_nghttp2_session_stream_attach_data(void)
dc = create_data_ob_item(); dc = create_data_ob_item();
nghttp2_stream_attach_data(c, dc, &session->ob_da_pq, session->last_cycle); nghttp2_stream_attach_data(c, dc, &session->ob_da_pq, session->last_cycle,
NULL);
CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_DATA == a->dpri); CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_DATA == a->dpri);
CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == b->dpri); CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == b->dpri);
@ -6060,7 +6063,8 @@ void test_nghttp2_session_stream_attach_data(void)
da = create_data_ob_item(); da = create_data_ob_item();
nghttp2_stream_attach_data(a, da, &session->ob_da_pq, session->last_cycle); nghttp2_stream_attach_data(a, da, &session->ob_da_pq, session->last_cycle,
NULL);
CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == a->dpri); CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == a->dpri);
CU_ASSERT(NGHTTP2_STREAM_DPRI_REST == b->dpri); CU_ASSERT(NGHTTP2_STREAM_DPRI_REST == b->dpri);
@ -6071,7 +6075,7 @@ void test_nghttp2_session_stream_attach_data(void)
CU_ASSERT(1 == da->queued); CU_ASSERT(1 == da->queued);
nghttp2_stream_detach_data(a, &session->ob_da_pq, session->last_cycle); nghttp2_stream_detach_data(a, &session->ob_da_pq, session->last_cycle, NULL);
CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_DATA == a->dpri); CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_DATA == a->dpri);
CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == b->dpri); CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == b->dpri);
@ -6083,7 +6087,8 @@ void test_nghttp2_session_stream_attach_data(void)
dd = create_data_ob_item(); dd = create_data_ob_item();
nghttp2_stream_attach_data(d, dd, &session->ob_da_pq, session->last_cycle); nghttp2_stream_attach_data(d, dd, &session->ob_da_pq, session->last_cycle,
NULL);
CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_DATA == a->dpri); CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_DATA == a->dpri);
CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == b->dpri); CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == b->dpri);
@ -6095,7 +6100,7 @@ void test_nghttp2_session_stream_attach_data(void)
CU_ASSERT(0 == dd->queued); CU_ASSERT(0 == dd->queued);
nghttp2_stream_detach_data(c, &session->ob_da_pq, session->last_cycle); nghttp2_stream_detach_data(c, &session->ob_da_pq, session->last_cycle, NULL);
CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_DATA == a->dpri); CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_DATA == a->dpri);
CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == b->dpri); CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == b->dpri);
@ -6106,7 +6111,7 @@ void test_nghttp2_session_stream_attach_data(void)
CU_ASSERT(0 == dd->queued); CU_ASSERT(0 == dd->queued);
nghttp2_stream_detach_data(b, &session->ob_da_pq, session->last_cycle); nghttp2_stream_detach_data(b, &session->ob_da_pq, session->last_cycle, NULL);
CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_DATA == a->dpri); CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_DATA == a->dpri);
CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_DATA == b->dpri); CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_DATA == b->dpri);
@ -6148,11 +6153,13 @@ void test_nghttp2_session_stream_attach_data_subtree(void)
de = create_data_ob_item(); de = create_data_ob_item();
nghttp2_stream_attach_data(e, de, &session->ob_da_pq, session->last_cycle); nghttp2_stream_attach_data(e, de, &session->ob_da_pq, session->last_cycle,
NULL);
db = create_data_ob_item(); db = create_data_ob_item();
nghttp2_stream_attach_data(b, db, &session->ob_da_pq, session->last_cycle); nghttp2_stream_attach_data(b, db, &session->ob_da_pq, session->last_cycle,
NULL);
CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_DATA == a->dpri); CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_DATA == a->dpri);
CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == b->dpri); CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == b->dpri);
@ -6168,7 +6175,7 @@ void test_nghttp2_session_stream_attach_data_subtree(void)
nghttp2_stream_dep_remove_subtree(e); nghttp2_stream_dep_remove_subtree(e);
nghttp2_stream_dep_insert_subtree(a, e, &session->ob_da_pq, nghttp2_stream_dep_insert_subtree(a, e, &session->ob_da_pq,
session->last_cycle); session->last_cycle, NULL);
/* /*
* a * a
@ -6193,7 +6200,8 @@ void test_nghttp2_session_stream_attach_data_subtree(void)
nghttp2_stream_dep_remove_subtree(b); nghttp2_stream_dep_remove_subtree(b);
nghttp2_stream_dep_make_root(b, &session->ob_da_pq, session->last_cycle); nghttp2_stream_dep_make_root(b, &session->ob_da_pq, session->last_cycle,
NULL);
/* /*
* a b * a b
@ -6219,7 +6227,8 @@ void test_nghttp2_session_stream_attach_data_subtree(void)
nghttp2_stream_dep_remove_subtree(a); nghttp2_stream_dep_remove_subtree(a);
nghttp2_stream_dep_make_root(a, &session->ob_da_pq, session->last_cycle); nghttp2_stream_dep_make_root(a, &session->ob_da_pq, session->last_cycle,
NULL);
CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_DATA == a->dpri); CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_DATA == a->dpri);
CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == b->dpri); CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == b->dpri);
@ -6232,7 +6241,8 @@ void test_nghttp2_session_stream_attach_data_subtree(void)
nghttp2_stream_dep_remove_subtree(c); nghttp2_stream_dep_remove_subtree(c);
nghttp2_stream_dep_make_root(c, &session->ob_da_pq, session->last_cycle); nghttp2_stream_dep_make_root(c, &session->ob_da_pq, session->last_cycle,
NULL);
/* /*
* a b c * a b c
@ -6251,13 +6261,14 @@ void test_nghttp2_session_stream_attach_data_subtree(void)
dd = create_data_ob_item(); dd = create_data_ob_item();
nghttp2_stream_attach_data(d, dd, &session->ob_da_pq, session->last_cycle); nghttp2_stream_attach_data(d, dd, &session->ob_da_pq, session->last_cycle,
NULL);
/* Add subtree c to a */ /* Add subtree c to a */
nghttp2_stream_dep_remove_subtree(c); nghttp2_stream_dep_remove_subtree(c);
nghttp2_stream_dep_add_subtree(a, c, &session->ob_da_pq, nghttp2_stream_dep_add_subtree(a, c, &session->ob_da_pq,
session->last_cycle); session->last_cycle, NULL);
/* /*
* a b * a b
@ -6284,7 +6295,7 @@ void test_nghttp2_session_stream_attach_data_subtree(void)
nghttp2_stream_dep_remove_subtree(b); nghttp2_stream_dep_remove_subtree(b);
nghttp2_stream_dep_insert_subtree(a, b, &session->ob_da_pq, nghttp2_stream_dep_insert_subtree(a, b, &session->ob_da_pq,
session->last_cycle); session->last_cycle, NULL);
/* /*
* a * a
@ -6311,7 +6322,8 @@ void test_nghttp2_session_stream_attach_data_subtree(void)
/* Remove subtree b */ /* Remove subtree b */
nghttp2_stream_dep_remove_subtree(b); nghttp2_stream_dep_remove_subtree(b);
nghttp2_stream_dep_make_root(b, &session->ob_da_pq, session->last_cycle); nghttp2_stream_dep_make_root(b, &session->ob_da_pq, session->last_cycle,
NULL);
/* /*
* b a * b a