Upate to draft-15

* Add NGHTTP2_HTTP_1_1_REQUIRED error code
* Allow transmission of WINDOW_UPDATE on reserved (remote)
* Allow reception of WINDOW_UPDATE on reserved (local)
* Treat frame larger than MAX_FRAME_SIZE as FRAME_SIZE_ERROR

ALPN identifier is still h2-14 to continue interop, since draft-14 and
-15 are binary compatible.  The new error code was added in draft-15,
but HTTP/2 allows extensions can freely add new error code, so it is
not a problem.
This commit is contained in:
Tatsuhiro Tsujikawa 2014-10-28 23:35:45 +09:00
parent be1a513c59
commit 4d93dd9d91
5 changed files with 32 additions and 5 deletions

View File

@ -586,7 +586,11 @@ typedef enum {
/** /**
* INADEQUATE_SECURITY * INADEQUATE_SECURITY
*/ */
NGHTTP2_INADEQUATE_SECURITY = 0x0c NGHTTP2_INADEQUATE_SECURITY = 0x0c,
/**
* HTTP_1_1_REQUIRED
*/
NGHTTP2_HTTP_1_1_REQUIRED = 0x0d
} nghttp2_error_code; } nghttp2_error_code;
/** /**

View File

@ -1314,7 +1314,7 @@ static int session_predicate_window_update_send
if(stream->state == NGHTTP2_STREAM_CLOSING) { if(stream->state == NGHTTP2_STREAM_CLOSING) {
return NGHTTP2_ERR_STREAM_CLOSING; return NGHTTP2_ERR_STREAM_CLOSING;
} }
if(stream->state == NGHTTP2_STREAM_RESERVED) { if(state_reserved_local(session, stream)) {
return NGHTTP2_ERR_INVALID_STREAM_STATE; return NGHTTP2_ERR_INVALID_STREAM_STATE;
} }
return 0; return 0;
@ -3884,7 +3884,7 @@ static int session_on_stream_window_update_received
} }
return 0; return 0;
} }
if(stream->state == NGHTTP2_STREAM_RESERVED) { if(state_reserved_remote(session, stream)) {
return session_handle_invalid_connection return session_handle_invalid_connection
(session, frame, NGHTTP2_PROTOCOL_ERROR, (session, frame, NGHTTP2_PROTOCOL_ERROR,
"WINDOW_UPADATE to reserved stream"); "WINDOW_UPADATE to reserved stream");
@ -4467,7 +4467,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session,
iframe->state = NGHTTP2_IB_IGN_PAYLOAD; iframe->state = NGHTTP2_IB_IGN_PAYLOAD;
rv = nghttp2_session_terminate_session_with_reason rv = nghttp2_session_terminate_session_with_reason
(session, NGHTTP2_PROTOCOL_ERROR, "too large frame size"); (session, NGHTTP2_FRAME_SIZE_ERROR, "too large frame size");
if(nghttp2_is_fatal(rv)) { if(nghttp2_is_fatal(rv)) {
return rv; return rv;

View File

@ -81,6 +81,8 @@ const char* strstatus(uint32_t error_code)
return "ENHANCE_YOUR_CALM"; return "ENHANCE_YOUR_CALM";
case NGHTTP2_INADEQUATE_SECURITY: case NGHTTP2_INADEQUATE_SECURITY:
return "INADEQUATE_SECURITY"; return "INADEQUATE_SECURITY";
case NGHTTP2_HTTP_1_1_REQUIRED:
return "HTTP_1_1_REQUIRED";
default: default:
return "UNKNOWN"; return "UNKNOWN";
} }

View File

@ -69,6 +69,7 @@ std::string get_status_string(unsigned int status_code)
case 415: return "415 Unsupported Media Type"; case 415: return "415 Unsupported Media Type";
case 416: return "416 Requested Range Not Satisfiable"; case 416: return "416 Requested Range Not Satisfiable";
case 417: return "417 Expectation Failed"; case 417: return "417 Expectation Failed";
case 421: return "421 Misdirected Request";
case 426: return "426 Upgrade Required"; case 426: return "426 Upgrade Required";
case 428: return "428 Precondition Required"; case 428: return "428 Precondition Required";
case 429: return "429 Too Many Requests"; case 429: return "429 Too Many Requests";

View File

@ -2585,7 +2585,8 @@ void test_nghttp2_session_on_window_update_received(void)
nghttp2_frame_window_update_free(&frame.window_update); nghttp2_frame_window_update_free(&frame.window_update);
/* WINDOW_UPDATE against reserved stream is a connection error */ /* Receiving WINDOW_UPDATE on reserved (remote) stream is a
connection error */
stream = nghttp2_session_open_stream(session, 2, NGHTTP2_STREAM_FLAG_NONE, stream = nghttp2_session_open_stream(session, 2, NGHTTP2_STREAM_FLAG_NONE,
&pri_spec_default, &pri_spec_default,
NGHTTP2_STREAM_RESERVED, NULL); NGHTTP2_STREAM_RESERVED, NULL);
@ -2600,6 +2601,25 @@ void test_nghttp2_session_on_window_update_received(void)
nghttp2_frame_window_update_free(&frame.window_update); nghttp2_frame_window_update_free(&frame.window_update);
nghttp2_session_del(session); nghttp2_session_del(session);
/* Receiving WINDOW_UPDATE on reserved (local) stream is allowed */
nghttp2_session_server_new(&session, &callbacks, &user_data);
stream = nghttp2_session_open_stream(session, 2, NGHTTP2_STREAM_FLAG_NONE,
&pri_spec_default,
NGHTTP2_STREAM_RESERVED, NULL);
nghttp2_frame_window_update_init(&frame.window_update, NGHTTP2_FLAG_NONE,
2, 4096);
CU_ASSERT(0 == nghttp2_session_on_window_update_received(session, &frame));
CU_ASSERT(!(session->goaway_flags & NGHTTP2_GOAWAY_FAIL_ON_SEND));
CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE + 4096 == stream->remote_window_size);
nghttp2_frame_window_update_free(&frame.window_update);
nghttp2_session_del(session);
} }
void test_nghttp2_session_on_data_received(void) void test_nghttp2_session_on_data_received(void)