diff --git a/lib/nghttp2_frame.c b/lib/nghttp2_frame.c index 676a9f77..f8f73861 100644 --- a/lib/nghttp2_frame.c +++ b/lib/nghttp2_frame.c @@ -487,11 +487,33 @@ int nghttp2_frame_pack_rst_stream(nghttp2_bufs *bufs, return 0; } +static nghttp2_error_code normalize_error_code(uint32_t error_code) +{ + switch(error_code) { + case NGHTTP2_NO_ERROR: + case NGHTTP2_PROTOCOL_ERROR: + case NGHTTP2_INTERNAL_ERROR: + case NGHTTP2_FLOW_CONTROL_ERROR: + case NGHTTP2_SETTINGS_TIMEOUT: + case NGHTTP2_STREAM_CLOSED: + case NGHTTP2_FRAME_SIZE_ERROR: + case NGHTTP2_REFUSED_STREAM: + case NGHTTP2_CANCEL: + case NGHTTP2_COMPRESSION_ERROR: + case NGHTTP2_CONNECT_ERROR: + case NGHTTP2_ENHANCE_YOUR_CALM: + case NGHTTP2_INADEQUATE_SECURITY: + return error_code; + default: + return NGHTTP2_INTERNAL_ERROR; + } +} + void nghttp2_frame_unpack_rst_stream_payload(nghttp2_rst_stream *frame, const uint8_t *payload, size_t payloadlen) { - frame->error_code = nghttp2_get_uint32(payload); + frame->error_code = normalize_error_code(nghttp2_get_uint32(payload)); } int nghttp2_frame_pack_settings(nghttp2_bufs *bufs, nghttp2_settings *frame) @@ -700,7 +722,7 @@ void nghttp2_frame_unpack_goaway_payload(nghttp2_goaway *frame, size_t var_gift_payloadlen) { frame->last_stream_id = nghttp2_get_uint32(payload) & NGHTTP2_STREAM_ID_MASK; - frame->error_code = nghttp2_get_uint32(payload+4); + frame->error_code = normalize_error_code(nghttp2_get_uint32(payload + 4)); frame->opaque_data = var_gift_payload; frame->opaque_data_len = var_gift_payloadlen; diff --git a/tests/nghttp2_frame_test.c b/tests/nghttp2_frame_test.c index 5f772a34..0e96dbed 100644 --- a/tests/nghttp2_frame_test.c +++ b/tests/nghttp2_frame_test.c @@ -257,9 +257,26 @@ void test_nghttp2_frame_pack_rst_stream(void) &oframe.hd); CU_ASSERT(NGHTTP2_PROTOCOL_ERROR == oframe.error_code); - nghttp2_bufs_free(&bufs); nghttp2_frame_rst_stream_free(&oframe); + nghttp2_bufs_reset(&bufs); + + /* Unknown error code is treated as NGHTTP2_INTERNAL_ERROR */ + frame.error_code = 1000000009; + rv = nghttp2_frame_pack_rst_stream(&bufs, &frame); + + CU_ASSERT(0 == rv); + CU_ASSERT(0 == unpack_framebuf((nghttp2_frame*)&oframe, &bufs)); + + check_frame_header(4, NGHTTP2_RST_STREAM, NGHTTP2_FLAG_NONE, 1000000007, + &oframe.hd); + + CU_ASSERT(NGHTTP2_INTERNAL_ERROR == oframe.error_code); + + nghttp2_frame_rst_stream_free(&oframe); + nghttp2_frame_rst_stream_free(&frame); + + nghttp2_bufs_free(&bufs); } void test_nghttp2_frame_pack_settings() @@ -403,9 +420,24 @@ void test_nghttp2_frame_pack_goaway() CU_ASSERT(opaque_data_len == oframe.opaque_data_len); CU_ASSERT(memcmp(opaque_data, oframe.opaque_data, opaque_data_len) == 0); - nghttp2_bufs_free(&bufs); nghttp2_frame_goaway_free(&oframe); + nghttp2_bufs_reset(&bufs); + + /* Unknown error code is treated as NGHTTP2_INTERNAL_ERROR */ + frame.error_code = 1000000009; + + rv = nghttp2_frame_pack_goaway(&bufs, &frame); + + CU_ASSERT(0 == rv); + CU_ASSERT(0 == unpack_framebuf((nghttp2_frame*)&oframe, &bufs)); + check_frame_header(24, NGHTTP2_GOAWAY, NGHTTP2_FLAG_NONE, 0, &oframe.hd); + CU_ASSERT(NGHTTP2_INTERNAL_ERROR == oframe.error_code); + + nghttp2_frame_goaway_free(&oframe); + nghttp2_frame_goaway_free(&frame); + + nghttp2_bufs_free(&bufs); } void test_nghttp2_frame_pack_window_update(void)