From c925c32233b3c71808b7c82b2d020a24fc00dfb5 Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Thu, 23 Apr 2015 23:57:39 +0900 Subject: [PATCH] Fix bug that promised stream is not reset on temporal failure from on_header_callback --- lib/nghttp2_session.c | 6 +++++- tests/nghttp2_session_test.c | 33 +++++++++++++++++++++++++++++++-- 2 files changed, 36 insertions(+), 3 deletions(-) diff --git a/lib/nghttp2_session.c b/lib/nghttp2_session.c index c4f61355..d0937c7c 100644 --- a/lib/nghttp2_session.c +++ b/lib/nghttp2_session.c @@ -5533,8 +5533,12 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, in += hd_proclen; iframe->payloadleft -= hd_proclen; + /* Use promised stream ID for PUSH_PROMISE */ rv = nghttp2_session_add_rst_stream( - session, iframe->frame.hd.stream_id, NGHTTP2_INTERNAL_ERROR); + session, iframe->frame.hd.type == NGHTTP2_PUSH_PROMISE + ? iframe->frame.push_promise.promised_stream_id + : iframe->frame.hd.stream_id, + NGHTTP2_INTERNAL_ERROR); if (nghttp2_is_fatal(rv)) { return rv; } diff --git a/tests/nghttp2_session_test.c b/tests/nghttp2_session_test.c index 3e83d2b4..0a465d4f 100644 --- a/tests/nghttp2_session_test.c +++ b/tests/nghttp2_session_test.c @@ -6711,21 +6711,50 @@ void test_nghttp2_session_on_header_temporal_failure(void) { nghttp2_frame_pack_frame_hd(&buf->pos[hdpos], &hd); + ud.header_cb_called = 0; rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_bufs_len(&bufs)); CU_ASSERT(rv == nghttp2_bufs_len(&bufs)); + CU_ASSERT(1 == ud.header_cb_called); item = nghttp2_session_get_next_ob_item(session); CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type); + CU_ASSERT(1 == item->frame.hd.stream_id); /* Make sure no header decompression error occurred */ CU_ASSERT(NGHTTP2_GOAWAY_NONE == session->goaway_flags); - nghttp2_bufs_free(&bufs); - nghttp2_hd_deflate_free(&deflater); nghttp2_session_del(session); + + nghttp2_bufs_reset(&bufs); + + /* Check for PUSH_PROMISE */ + nghttp2_hd_deflate_init(&deflater, mem); + nghttp2_session_client_new(&session, &callbacks, &ud); + + nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE, + &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL); + + rv = pack_push_promise(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, 2, + reqnv, ARRLEN(reqnv), mem); + CU_ASSERT(0 == rv); + + ud.header_cb_called = 0; + rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos, + nghttp2_bufs_len(&bufs)); + CU_ASSERT(nghttp2_bufs_len(&bufs) == rv); + CU_ASSERT(1 == ud.header_cb_called); + + item = nghttp2_session_get_next_ob_item(session); + CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type); + CU_ASSERT(2 == item->frame.hd.stream_id); + CU_ASSERT(NGHTTP2_INTERNAL_ERROR == item->frame.rst_stream.error_code); + + nghttp2_session_del(session); + nghttp2_hd_deflate_free(&deflater); + nghttp2_bufs_free(&bufs); } void test_nghttp2_session_recv_client_preface(void) {