From ed7fabcbc24b376bbf4b168aebcdb6f1a32cf688 Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Sat, 10 Mar 2018 17:19:45 +0900 Subject: [PATCH] Add SETTINGS_ENABLE_CONNECT_PROTOCOL --- lib/includes/nghttp2/nghttp2.h | 7 ++++++- lib/nghttp2_frame.c | 5 +++++ lib/nghttp2_session.c | 28 ++++++++++++++++++++++++++++ lib/nghttp2_session.h | 1 + tests/nghttp2_session_test.c | 23 +++++++++++++++++++++++ 5 files changed, 63 insertions(+), 1 deletion(-) diff --git a/lib/includes/nghttp2/nghttp2.h b/lib/includes/nghttp2/nghttp2.h index 8c54b9c8..3fe4e2d5 100644 --- a/lib/includes/nghttp2/nghttp2.h +++ b/lib/includes/nghttp2/nghttp2.h @@ -680,7 +680,12 @@ typedef enum { /** * SETTINGS_MAX_HEADER_LIST_SIZE */ - NGHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE = 0x06 + NGHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE = 0x06, + /** + * SETTINGS_ENABLE_CONNECT_PROTOCOL + * (https://tools.ietf.org/html/draft-ietf-httpbis-h2-websockets-00) + */ + NGHTTP2_SETTINGS_ENABLE_CONNECT_PROTOCOL = 0x08 } nghttp2_settings_id; /* Note: If we add SETTINGS, update the capacity of NGHTTP2_INBOUND_NUM_IV as well */ diff --git a/lib/nghttp2_frame.c b/lib/nghttp2_frame.c index 6e33f3c2..4821de40 100644 --- a/lib/nghttp2_frame.c +++ b/lib/nghttp2_frame.c @@ -1050,6 +1050,11 @@ int nghttp2_iv_check(const nghttp2_settings_entry *iv, size_t niv) { break; case NGHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE: break; + case NGHTTP2_SETTINGS_ENABLE_CONNECT_PROTOCOL: + if (iv[i].value != 0 && iv[i].value != 1) { + return 0; + } + break; } } return 1; diff --git a/lib/nghttp2_session.c b/lib/nghttp2_session.c index 418ad666..31e21023 100644 --- a/lib/nghttp2_session.c +++ b/lib/nghttp2_session.c @@ -4361,6 +4361,9 @@ int nghttp2_session_update_local_settings(nghttp2_session *session, case NGHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE: session->local_settings.max_header_list_size = iv[i].value; break; + case NGHTTP2_SETTINGS_ENABLE_CONNECT_PROTOCOL: + session->local_settings.enable_connect_protocol = iv[i].value; + break; } } @@ -4499,6 +4502,26 @@ int nghttp2_session_on_settings_received(nghttp2_session *session, session->remote_settings.max_header_list_size = entry->value; + break; + case NGHTTP2_SETTINGS_ENABLE_CONNECT_PROTOCOL: + + if (entry->value != 0 && entry->value != 1) { + return session_handle_invalid_connection( + session, frame, NGHTTP2_ERR_PROTO, + "SETTINGS: invalid SETTINGS_ENABLE_CONNECT_PROTOCOL"); + } + + if (!session->server && + session->remote_settings.enable_connect_protocol && + entry->value == 0) { + return session_handle_invalid_connection( + session, frame, NGHTTP2_ERR_PROTO, + "SETTINGS: server attempted to disable " + "SETTINGS_ENABLE_CONNECT_PROTOCOL"); + } + + session->remote_settings.enable_connect_protocol = entry->value; + break; } } @@ -5250,6 +5273,7 @@ static void inbound_frame_set_settings_entry(nghttp2_inbound_frame *iframe) { case NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE: case NGHTTP2_SETTINGS_MAX_FRAME_SIZE: case NGHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE: + case NGHTTP2_SETTINGS_ENABLE_CONNECT_PROTOCOL: break; default: DEBUGF("recv: unknown settings id=0x%02x\n", iv.settings_id); @@ -7360,6 +7384,8 @@ uint32_t nghttp2_session_get_remote_settings(nghttp2_session *session, return session->remote_settings.max_frame_size; case NGHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE: return session->remote_settings.max_header_list_size; + case NGHTTP2_SETTINGS_ENABLE_CONNECT_PROTOCOL: + return session->remote_settings.enable_connect_protocol; } assert(0); @@ -7381,6 +7407,8 @@ uint32_t nghttp2_session_get_local_settings(nghttp2_session *session, return session->local_settings.max_frame_size; case NGHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE: return session->local_settings.max_header_list_size; + case NGHTTP2_SETTINGS_ENABLE_CONNECT_PROTOCOL: + return session->local_settings.enable_connect_protocol; } assert(0); diff --git a/lib/nghttp2_session.h b/lib/nghttp2_session.h index 5add50bc..95c2afb7 100644 --- a/lib/nghttp2_session.h +++ b/lib/nghttp2_session.h @@ -164,6 +164,7 @@ typedef struct { uint32_t initial_window_size; uint32_t max_frame_size; uint32_t max_header_list_size; + uint32_t enable_connect_protocol; } nghttp2_settings_storage; typedef enum { diff --git a/tests/nghttp2_session_test.c b/tests/nghttp2_session_test.c index a7a5605b..a119d255 100644 --- a/tests/nghttp2_session_test.c +++ b/tests/nghttp2_session_test.c @@ -3480,6 +3480,29 @@ void test_nghttp2_session_on_settings_received(void) { CU_ASSERT(NGHTTP2_STREAM_CLOSING == stream1->state); nghttp2_session_del(session); + + /* It is invalid that peer disables ENABLE_CONNECT_PROTOCOL once it + has been enabled. */ + nghttp2_session_client_new(&session, &callbacks, NULL); + + session->remote_settings.enable_connect_protocol = 1; + + iv[0].settings_id = NGHTTP2_SETTINGS_ENABLE_CONNECT_PROTOCOL; + iv[0].value = 0; + + nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE, dup_iv(iv, 1), + 1); + + CU_ASSERT(0 == nghttp2_session_on_settings_received(session, &frame, 0)); + + nghttp2_frame_settings_free(&frame.settings, mem); + + item = nghttp2_session_get_next_ob_item(session); + + CU_ASSERT(NULL != item); + CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type); + + nghttp2_session_del(session); } void test_nghttp2_session_on_push_promise_received(void) {