Strict handling of connection error

Following cases are now treated as connection error of type
PROTOCOL_ERROR.

* Receiving HEADERS from client in reserved (local)
* Receiving PUSH_PROMISE against peer-initiated stream
* Receiving WINDOW_UPDATE against in reserved (local, remote)
This commit is contained in:
Tatsuhiro Tsujikawa 2013-08-19 00:13:22 +09:00
parent 47ee8e3c79
commit e278efdf38
2 changed files with 32 additions and 1 deletions

View File

@ -1807,6 +1807,10 @@ int nghttp2_session_on_headers_received(nghttp2_session *session,
} }
} }
} }
} else if(stream->state == NGHTTP2_STREAM_RESERVED) {
/* reserved (local) */
return nghttp2_session_handle_invalid_connection(session, frame,
NGHTTP2_PROTOCOL_ERROR);
} else { } else {
/* half closed (remote): from the spec: /* half closed (remote): from the spec:
@ -2162,6 +2166,10 @@ int nghttp2_session_on_push_promise_received(nghttp2_session *session,
session->last_recv_stream_id = frame->push_promise.promised_stream_id; session->last_recv_stream_id = frame->push_promise.promised_stream_id;
stream = nghttp2_session_get_stream(session, frame->hd.stream_id); stream = nghttp2_session_get_stream(session, frame->hd.stream_id);
if(stream) { if(stream) {
if(!nghttp2_session_is_my_stream_id(session, frame->hd.stream_id)) {
return nghttp2_session_handle_invalid_connection(session, frame,
NGHTTP2_PROTOCOL_ERROR);
}
if((stream->shut_flags & NGHTTP2_SHUT_RD) == 0) { if((stream->shut_flags & NGHTTP2_SHUT_RD) == 0) {
if(stream->state == NGHTTP2_STREAM_CLOSING) { if(stream->state == NGHTTP2_STREAM_CLOSING) {
return nghttp2_session_add_rst_stream return nghttp2_session_add_rst_stream
@ -2293,6 +2301,10 @@ int nghttp2_session_on_window_update_received(nghttp2_session *session,
nghttp2_stream *stream; nghttp2_stream *stream;
stream = nghttp2_session_get_stream(session, frame->hd.stream_id); stream = nghttp2_session_get_stream(session, frame->hd.stream_id);
if(stream) { if(stream) {
if(stream->state == NGHTTP2_STREAM_RESERVED) {
return nghttp2_session_handle_invalid_connection
(session, frame, NGHTTP2_PROTOCOL_ERROR);
}
if(stream->remote_flow_control == 0) { if(stream->remote_flow_control == 0) {
/* Same reason with connection-level flow control */ /* Same reason with connection-level flow control */
nghttp2_session_call_on_frame_received(session, frame); nghttp2_session_call_on_frame_received(session, frame);

View File

@ -1043,7 +1043,7 @@ void test_nghttp2_session_on_push_promise_received(void)
/* After GOAWAY, PUSH_PROMISE will be discarded */ /* After GOAWAY, PUSH_PROMISE will be discarded */
frame.push_promise.promised_stream_id = 10; frame.push_promise.promised_stream_id = 10;
user_data.frame_recv_cb_called = 0; user_data.frame_recv_cb_called = 0;
user_data.invalid_frame_recv_cb_called = 0; user_data.invalid_frame_recv_cb_called = 0;
CU_ASSERT(0 == nghttp2_session_on_push_promise_received(session, &frame)); CU_ASSERT(0 == nghttp2_session_on_push_promise_received(session, &frame));
@ -1053,6 +1053,25 @@ void test_nghttp2_session_on_push_promise_received(void)
nghttp2_frame_push_promise_free(&frame.push_promise); nghttp2_frame_push_promise_free(&frame.push_promise);
nghttp2_session_del(session); nghttp2_session_del(session);
nghttp2_session_client_new(&session, &callbacks, &user_data);
stream = nghttp2_session_open_stream(session, 2, NGHTTP2_FLAG_NONE,
NGHTTP2_PRI_DEFAULT,
NGHTTP2_STREAM_RESERVED, NULL);
nvlen = nghttp2_nv_array_from_cstr(&nva, nv);
/* Attempt to PUSH_PROMISE against reserved (remote) stream */
nghttp2_frame_push_promise_init(&frame.push_promise,
NGHTTP2_FLAG_END_PUSH_PROMISE, 2, 4,
nva, nvlen);
user_data.frame_recv_cb_called = 0;
user_data.invalid_frame_recv_cb_called = 0;
CU_ASSERT(0 == nghttp2_session_on_push_promise_received(session, &frame));
CU_ASSERT(0 == user_data.frame_recv_cb_called);
CU_ASSERT(1 == user_data.invalid_frame_recv_cb_called);
nghttp2_session_del(session);
} }
void test_nghttp2_session_on_ping_received(void) void test_nghttp2_session_on_ping_received(void)