Don't send push response if GOAWAY has been received

This commit is contained in:
Tatsuhiro Tsujikawa 2015-11-16 22:47:12 +09:00
parent 7463493259
commit b918f9650a
4 changed files with 57 additions and 20 deletions

View File

@ -1415,6 +1415,9 @@ static int session_predicate_response_headers_send(nghttp2_session *session,
* RST_STREAM was queued for this stream. * RST_STREAM was queued for this stream.
* NGHTTP2_ERR_SESSION_CLOSING * NGHTTP2_ERR_SESSION_CLOSING
* This session is closing. * This session is closing.
* NGHTTP2_ERR_START_STREAM_NOT_ALLOWED
* New stream cannot be created because GOAWAY is already sent or
* received.
*/ */
static int static int
session_predicate_push_response_headers_send(nghttp2_session *session, session_predicate_push_response_headers_send(nghttp2_session *session,
@ -1432,6 +1435,9 @@ session_predicate_push_response_headers_send(nghttp2_session *session,
if (stream->state == NGHTTP2_STREAM_CLOSING) { if (stream->state == NGHTTP2_STREAM_CLOSING) {
return NGHTTP2_ERR_STREAM_CLOSING; return NGHTTP2_ERR_STREAM_CLOSING;
} }
if (session->goaway_flags & NGHTTP2_GOAWAY_RECV) {
return NGHTTP2_ERR_START_STREAM_NOT_ALLOWED;
}
return 0; return 0;
} }
@ -1795,40 +1801,41 @@ static int session_prep_frame(nghttp2_session *session,
stream = nghttp2_session_get_stream(session, frame->hd.stream_id); stream = nghttp2_session_get_stream(session, frame->hd.stream_id);
if (session_predicate_push_response_headers_send(session, stream) == if (stream && stream->state == NGHTTP2_STREAM_RESERVED) {
0) { rv = session_predicate_push_response_headers_send(session, stream);
frame->headers.cat = NGHTTP2_HCAT_PUSH_RESPONSE; if (rv == 0) {
frame->headers.cat = NGHTTP2_HCAT_PUSH_RESPONSE;
if (aux_data->stream_user_data) { if (aux_data->stream_user_data) {
stream->stream_user_data = aux_data->stream_user_data; stream->stream_user_data = aux_data->stream_user_data;
}
} }
} else if (session_predicate_response_headers_send(session, stream) == } else if (session_predicate_response_headers_send(session, stream) ==
0) { 0) {
frame->headers.cat = NGHTTP2_HCAT_RESPONSE; frame->headers.cat = NGHTTP2_HCAT_RESPONSE;
rv = 0;
} else { } else {
frame->headers.cat = NGHTTP2_HCAT_HEADERS; frame->headers.cat = NGHTTP2_HCAT_HEADERS;
rv = session_predicate_headers_send(session, stream); rv = session_predicate_headers_send(session, stream);
}
if (rv != 0) { if (rv != 0) {
// If stream was alreay closed, // If stream was alreay closed, nghttp2_session_get_stream()
// nghttp2_session_get_stream() returns NULL, but item is // returns NULL, but item is still attached to the stream.
// still attached to the stream. Search stream including // Search stream including closed again.
// closed again. stream = nghttp2_session_get_stream_raw(session, frame->hd.stream_id);
stream = if (stream && stream->item == item) {
nghttp2_session_get_stream_raw(session, frame->hd.stream_id); int rv2;
if (stream && stream->item == item) {
int rv2;
rv2 = nghttp2_stream_detach_item(stream); rv2 = nghttp2_stream_detach_item(stream);
if (nghttp2_is_fatal(rv2)) { if (nghttp2_is_fatal(rv2)) {
return rv2; return rv2;
}
} }
return rv;
} }
return rv;
} }
} }

View File

@ -159,6 +159,8 @@ int main(int argc _U_, char *argv[] _U_) {
test_nghttp2_submit_response_with_data) || test_nghttp2_submit_response_with_data) ||
!CU_add_test(pSuite, "submit_response_without_data", !CU_add_test(pSuite, "submit_response_without_data",
test_nghttp2_submit_response_without_data) || test_nghttp2_submit_response_without_data) ||
!CU_add_test(pSuite, "Submit_response_push_response",
test_nghttp2_submit_response_push_response) ||
!CU_add_test(pSuite, "submit_trailer", test_nghttp2_submit_trailer) || !CU_add_test(pSuite, "submit_trailer", test_nghttp2_submit_trailer) ||
!CU_add_test(pSuite, "submit_headers_start_stream", !CU_add_test(pSuite, "submit_headers_start_stream",
test_nghttp2_submit_headers_start_stream) || test_nghttp2_submit_headers_start_stream) ||

View File

@ -3879,6 +3879,33 @@ void test_nghttp2_submit_response_without_data(void) {
nghttp2_session_del(session); nghttp2_session_del(session);
} }
void test_nghttp2_submit_response_push_response(void) {
nghttp2_session *session;
nghttp2_session_callbacks callbacks;
my_user_data ud;
memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
callbacks.send_callback = null_send_callback;
callbacks.on_frame_not_send_callback = on_frame_not_send_callback;
nghttp2_session_server_new(&session, &callbacks, &ud);
nghttp2_session_open_stream(session, 2, NGHTTP2_FLAG_NONE, &pri_spec_default,
NGHTTP2_STREAM_RESERVED, NULL);
session->goaway_flags |= NGHTTP2_GOAWAY_RECV;
CU_ASSERT(0 ==
nghttp2_submit_response(session, 2, resnv, ARRLEN(resnv), NULL));
ud.frame_not_send_cb_called = 0;
CU_ASSERT(0 == nghttp2_session_send(session));
CU_ASSERT(1 == ud.frame_not_send_cb_called);
nghttp2_session_del(session);
}
void test_nghttp2_submit_trailer(void) { void test_nghttp2_submit_trailer(void) {
nghttp2_session *session; nghttp2_session *session;
nghttp2_session_callbacks callbacks; nghttp2_session_callbacks callbacks;

View File

@ -70,6 +70,7 @@ void test_nghttp2_submit_request_with_data(void);
void test_nghttp2_submit_request_without_data(void); void test_nghttp2_submit_request_without_data(void);
void test_nghttp2_submit_response_with_data(void); void test_nghttp2_submit_response_with_data(void);
void test_nghttp2_submit_response_without_data(void); void test_nghttp2_submit_response_without_data(void);
void test_nghttp2_submit_response_push_response(void);
void test_nghttp2_submit_trailer(void); void test_nghttp2_submit_trailer(void);
void test_nghttp2_submit_headers_start_stream(void); void test_nghttp2_submit_headers_start_stream(void);
void test_nghttp2_submit_headers_reply(void); void test_nghttp2_submit_headers_reply(void);