diff --git a/lib/nghttp2_session.c b/lib/nghttp2_session.c index d41d5699..b420c983 100644 --- a/lib/nghttp2_session.c +++ b/lib/nghttp2_session.c @@ -1708,8 +1708,14 @@ static int nghttp2_session_prep_frame(nghttp2_session *session, next_readmax = nghttp2_session_next_data_read(session, stream); if(next_readmax == 0) { - nghttp2_stream_defer_data(stream, - NGHTTP2_STREAM_FLAG_DEFERRED_FLOW_CONTROL); + rv = nghttp2_stream_defer_data(stream, + NGHTTP2_STREAM_FLAG_DEFERRED_FLOW_CONTROL, + &session->ob_pq); + + if(nghttp2_is_fatal(rv)) { + return rv; + } + session->aob.item = NULL; nghttp2_active_outbound_item_reset(&session->aob); return NGHTTP2_ERR_DEFERRED; @@ -1719,7 +1725,13 @@ static int nghttp2_session_prep_frame(nghttp2_session *session, next_readmax, data_frame); if(framerv == NGHTTP2_ERR_DEFERRED) { - nghttp2_stream_defer_data(stream, NGHTTP2_STREAM_FLAG_DEFERRED_USER); + rv = nghttp2_stream_defer_data(stream, NGHTTP2_STREAM_FLAG_DEFERRED_USER, + &session->ob_pq); + + if(nghttp2_is_fatal(rv)) { + return rv; + } + session->aob.item = NULL; nghttp2_active_outbound_item_reset(&session->aob); return NGHTTP2_ERR_DEFERRED; @@ -2107,8 +2119,13 @@ static int nghttp2_session_after_frame_sent(nghttp2_session *session) next_readmax = nghttp2_session_next_data_read(session, stream); if(next_readmax == 0) { - nghttp2_stream_defer_data(stream, - NGHTTP2_STREAM_FLAG_DEFERRED_FLOW_CONTROL); + rv = nghttp2_stream_defer_data + (stream, NGHTTP2_STREAM_FLAG_DEFERRED_FLOW_CONTROL, &session->ob_pq); + + if(nghttp2_is_fatal(rv)) { + return rv; + } + aob->item = NULL; nghttp2_active_outbound_item_reset(aob); @@ -2123,7 +2140,14 @@ static int nghttp2_session_after_frame_sent(nghttp2_session *session) return rv; } if(rv == NGHTTP2_ERR_DEFERRED) { - nghttp2_stream_defer_data(stream, NGHTTP2_STREAM_FLAG_DEFERRED_USER); + rv = nghttp2_stream_defer_data(stream, + NGHTTP2_STREAM_FLAG_DEFERRED_USER, + &session->ob_pq); + + if(nghttp2_is_fatal(rv)) { + return rv; + } + aob->item = NULL; nghttp2_active_outbound_item_reset(aob); diff --git a/lib/nghttp2_stream.c b/lib/nghttp2_stream.c index c9883877..ecd067ff 100644 --- a/lib/nghttp2_stream.c +++ b/lib/nghttp2_stream.c @@ -359,11 +359,17 @@ int nghttp2_stream_detach_data(nghttp2_stream *stream, nghttp2_pq *pq) return stream_update_dep_on_detach_data(stream, pq); } -void nghttp2_stream_defer_data(nghttp2_stream *stream, uint8_t flags) +int nghttp2_stream_defer_data(nghttp2_stream *stream, uint8_t flags, + nghttp2_pq *pq) { assert(stream->data_item); + DEBUGF(fprintf(stderr, "stream: stream=%d defer data=%p cause=%02x\n", + stream->stream_id, stream->data_item, flags)); + stream->flags |= flags; + + return stream_update_dep_on_detach_data(stream, pq); } int nghttp2_stream_resume_deferred_data(nghttp2_stream *stream, diff --git a/lib/nghttp2_stream.h b/lib/nghttp2_stream.h index 9fa6e56f..eb30c2fd 100644 --- a/lib/nghttp2_stream.h +++ b/lib/nghttp2_stream.h @@ -185,8 +185,15 @@ void nghttp2_stream_shutdown(nghttp2_stream *stream, nghttp2_shut_flag flag); * bitwise OR of zero or more of NGHTTP2_STREAM_FLAG_DEFERRED_USER and * NGHTTP2_STREAM_FLAG_DEFERRED_FLOW_CONTROL. The |flags| indicates * the reason of this action. + * + * This function returns 0 if it succeeds, or one of the following + * negative error codes: + * + * NGHTTP2_ERR_NOMEM + * Out of memory */ -void nghttp2_stream_defer_data(nghttp2_stream *stream, uint8_t flags); +int nghttp2_stream_defer_data(nghttp2_stream *stream, uint8_t flags, + nghttp2_pq *pq); /* * Detaches deferred data in this stream and it is back to active diff --git a/tests/nghttp2_session_test.c b/tests/nghttp2_session_test.c index 20ec06d6..0fc461d3 100644 --- a/tests/nghttp2_session_test.c +++ b/tests/nghttp2_session_test.c @@ -2201,7 +2201,9 @@ void test_nghttp2_session_on_window_update_received(void) CU_ASSERT(1 == user_data.frame_recv_cb_called); CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE+16*1024 == stream->remote_window_size); - nghttp2_stream_defer_data(stream, NGHTTP2_STREAM_FLAG_DEFERRED_FLOW_CONTROL); + CU_ASSERT(0 == nghttp2_stream_defer_data + (stream, NGHTTP2_STREAM_FLAG_DEFERRED_FLOW_CONTROL, + &session->ob_pq)); CU_ASSERT(0 == nghttp2_session_on_window_update_received(session, &frame)); CU_ASSERT(2 == user_data.frame_recv_cb_called);