altsvc: Add tests, ignore altsvc if stream does not exist

This commit is contained in:
Tatsuhiro Tsujikawa 2016-04-09 19:14:15 +09:00
parent 6638ca9333
commit d4144a7475
4 changed files with 245 additions and 2 deletions

View File

@ -4663,6 +4663,7 @@ static int session_process_window_update_frame(nghttp2_session *session) {
int nghttp2_session_on_altsvc_received(nghttp2_session *session,
nghttp2_frame *frame) {
nghttp2_ext_altsvc *altsvc;
nghttp2_stream *stream;
altsvc = frame->ext.payload;
@ -4672,10 +4673,21 @@ int nghttp2_session_on_altsvc_received(nghttp2_session *session,
if (altsvc->origin_len == 0) {
return 0;
}
} else if (altsvc->origin_len > 0) {
} else {
if (altsvc->origin_len > 0) {
return 0;
}
stream = nghttp2_session_get_stream(session, frame->hd.stream_id);
if (!stream) {
return 0;
}
if (stream->state == NGHTTP2_STREAM_CLOSING) {
return 0;
}
}
return session_call_on_frame_received(session, frame);
}

View File

@ -103,6 +103,8 @@ int main(int argc _U_, char *argv[] _U_) {
test_nghttp2_session_recv_too_large_frame_length) ||
!CU_add_test(pSuite, "session_recv_extension",
test_nghttp2_session_recv_extension) ||
!CU_add_test(pSuite, "session_recv_altsvc",
test_nghttp2_session_recv_altsvc) ||
!CU_add_test(pSuite, "session_continue", test_nghttp2_session_continue) ||
!CU_add_test(pSuite, "session_add_frame",
test_nghttp2_session_add_frame) ||
@ -132,6 +134,8 @@ int main(int argc _U_, char *argv[] _U_) {
test_nghttp2_session_on_data_received) ||
!CU_add_test(pSuite, "session_on_data_received_fail_fast",
test_nghttp2_session_on_data_received_fail_fast) ||
!CU_add_test(pSuite, "session_on_altsvc_received",
test_nghttp2_session_on_altsvc_received) ||
!CU_add_test(pSuite, "session_send_headers_start_stream",
test_nghttp2_session_send_headers_start_stream) ||
!CU_add_test(pSuite, "session_send_headers_reply",

View File

@ -1955,6 +1955,124 @@ void test_nghttp2_session_recv_extension(void) {
nghttp2_option_del(option);
}
void test_nghttp2_session_recv_altsvc(void) {
nghttp2_session *session;
nghttp2_session_callbacks callbacks;
my_user_data ud;
nghttp2_buf buf;
nghttp2_frame_hd hd;
nghttp2_mem *mem;
ssize_t rv;
nghttp2_option *option;
static const uint8_t origin[] = "nghttp2.org";
static const uint8_t field_value[] = "h2=\":443\"";
mem = nghttp2_mem_default();
nghttp2_buf_init2(&buf, NGHTTP2_FRAME_HDLEN + NGHTTP2_MAX_FRAME_SIZE_MIN,
mem);
memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
callbacks.on_frame_recv_callback = on_frame_recv_callback;
nghttp2_option_new(&option);
nghttp2_option_set_builtin_recv_extension_type(option, NGHTTP2_ALTSVC);
nghttp2_session_client_new2(&session, &callbacks, &ud, option);
nghttp2_frame_hd_init(&hd, 2 + sizeof(origin) - 1 + sizeof(field_value) - 1,
NGHTTP2_ALTSVC, NGHTTP2_FLAG_NONE, 0);
nghttp2_frame_pack_frame_hd(buf.last, &hd);
buf.last += NGHTTP2_FRAME_HDLEN;
nghttp2_put_uint16be(buf.last, sizeof(origin) - 1);
buf.last += 2;
buf.last = nghttp2_cpymem(buf.last, origin, sizeof(origin) - 1);
buf.last = nghttp2_cpymem(buf.last, field_value, sizeof(field_value) - 1);
ud.frame_recv_cb_called = 0;
rv = nghttp2_session_mem_recv(session, buf.pos, nghttp2_buf_len(&buf));
CU_ASSERT((ssize_t)nghttp2_buf_len(&buf) == rv);
CU_ASSERT(1 == ud.frame_recv_cb_called);
CU_ASSERT(NGHTTP2_ALTSVC == ud.recv_frame_hd.type);
CU_ASSERT(NGHTTP2_FLAG_NONE == ud.recv_frame_hd.flags);
CU_ASSERT(0 == ud.recv_frame_hd.stream_id);
nghttp2_session_del(session);
/* size of origin is larger than frame length */
nghttp2_buf_reset(&buf);
nghttp2_session_client_new2(&session, &callbacks, &ud, option);
nghttp2_frame_hd_init(&hd, 2 + sizeof(origin) - 1 - 1, NGHTTP2_ALTSVC,
NGHTTP2_FLAG_NONE, 0);
nghttp2_frame_pack_frame_hd(buf.last, &hd);
buf.last += NGHTTP2_FRAME_HDLEN;
nghttp2_put_uint16be(buf.last, sizeof(origin) - 1);
buf.last += 2;
buf.last = nghttp2_cpymem(buf.last, origin, sizeof(origin) - 1 - 1);
ud.frame_recv_cb_called = 0;
rv = nghttp2_session_mem_recv(session, buf.pos, nghttp2_buf_len(&buf));
CU_ASSERT((ssize_t)nghttp2_buf_len(&buf) == rv);
CU_ASSERT(0 == ud.frame_recv_cb_called);
nghttp2_session_del(session);
/* send large frame (16KiB) */
nghttp2_buf_reset(&buf);
nghttp2_session_client_new2(&session, &callbacks, &ud, option);
nghttp2_frame_hd_init(&hd, NGHTTP2_MAX_FRAME_SIZE_MIN, NGHTTP2_ALTSVC,
NGHTTP2_FLAG_NONE, 0);
nghttp2_frame_pack_frame_hd(buf.last, &hd);
buf.last += NGHTTP2_FRAME_HDLEN;
nghttp2_put_uint16be(buf.last, sizeof(origin) - 1);
buf.last += 2;
buf.last = nghttp2_cpymem(buf.last, origin, sizeof(origin) - 1);
memset(buf.last, 0, nghttp2_buf_avail(&buf));
buf.last += nghttp2_buf_avail(&buf);
ud.frame_recv_cb_called = 0;
rv = nghttp2_session_mem_recv(session, buf.pos, nghttp2_buf_len(&buf));
CU_ASSERT((ssize_t)nghttp2_buf_len(&buf) == rv);
CU_ASSERT(1 == ud.frame_recv_cb_called);
CU_ASSERT(NGHTTP2_ALTSVC == ud.recv_frame_hd.type);
CU_ASSERT(NGHTTP2_MAX_FRAME_SIZE_MIN == ud.recv_frame_hd.length);
nghttp2_session_del(session);
/* received by server */
nghttp2_buf_reset(&buf);
nghttp2_session_server_new2(&session, &callbacks, &ud, option);
nghttp2_frame_hd_init(&hd, 2 + sizeof(origin) - 1 + sizeof(field_value) - 1,
NGHTTP2_ALTSVC, NGHTTP2_FLAG_NONE, 0);
nghttp2_frame_pack_frame_hd(buf.last, &hd);
buf.last += NGHTTP2_FRAME_HDLEN;
nghttp2_put_uint16be(buf.last, sizeof(origin) - 1);
buf.last += 2;
buf.last = nghttp2_cpymem(buf.last, origin, sizeof(origin) - 1);
buf.last = nghttp2_cpymem(buf.last, field_value, sizeof(field_value) - 1);
ud.frame_recv_cb_called = 0;
rv = nghttp2_session_mem_recv(session, buf.pos, nghttp2_buf_len(&buf));
CU_ASSERT((ssize_t)nghttp2_buf_len(&buf) == rv);
CU_ASSERT(0 == ud.frame_recv_cb_called);
nghttp2_session_del(session);
nghttp2_buf_free(&buf, mem);
nghttp2_option_del(option);
}
void test_nghttp2_session_continue(void) {
nghttp2_session *session;
nghttp2_session_callbacks callbacks;
@ -3364,6 +3482,113 @@ void test_nghttp2_session_on_data_received_fail_fast(void) {
nghttp2_session_del(session);
}
void test_nghttp2_session_on_altsvc_received(void) {
nghttp2_session *session;
nghttp2_session_callbacks callbacks;
my_user_data ud;
nghttp2_frame frame;
nghttp2_mem *mem;
nghttp2_option *option;
uint8_t origin[] = "nghttp2.org";
uint8_t field_value[] = "h2=\":443\"";
int rv;
mem = nghttp2_mem_default();
memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
callbacks.on_frame_recv_callback = on_frame_recv_callback;
nghttp2_option_new(&option);
nghttp2_option_set_builtin_recv_extension_type(option, NGHTTP2_ALTSVC);
nghttp2_session_client_new2(&session, &callbacks, &ud, option);
frame.ext.payload = &session->iframe.ext_frame_payload;
/* We just pass the strings without making a copy. This is OK,
since we never call nghttp2_frame_altsvc_free(). */
nghttp2_frame_altsvc_init(&frame.ext, 0, origin, sizeof(origin) - 1,
field_value, sizeof(field_value) - 1);
ud.frame_recv_cb_called = 0;
rv = nghttp2_session_on_altsvc_received(session, &frame);
CU_ASSERT(0 == rv);
CU_ASSERT(1 == ud.frame_recv_cb_called);
nghttp2_session_del(session);
/* Receiving empty origin with stream ID == 0 */
nghttp2_session_client_new2(&session, &callbacks, &ud, option);
frame.ext.payload = &session->iframe.ext_frame_payload;
nghttp2_frame_altsvc_init(&frame.ext, 0, origin, 0, field_value,
sizeof(field_value) - 1);
ud.frame_recv_cb_called = 0;
rv = nghttp2_session_on_altsvc_received(session, &frame);
CU_ASSERT(0 == rv);
CU_ASSERT(0 == ud.frame_recv_cb_called);
nghttp2_session_del(session);
/* Receiving non-empty origin with stream ID != 0 */
nghttp2_session_client_new2(&session, &callbacks, &ud, option);
frame.ext.payload = &session->iframe.ext_frame_payload;
open_sent_stream(session, 1);
nghttp2_frame_altsvc_init(&frame.ext, 1, origin, sizeof(origin) - 1,
field_value, sizeof(field_value) - 1);
ud.frame_recv_cb_called = 0;
rv = nghttp2_session_on_altsvc_received(session, &frame);
CU_ASSERT(0 == rv);
CU_ASSERT(0 == ud.frame_recv_cb_called);
nghttp2_session_del(session);
/* Receiving empty origin with stream ID != 0; this is OK */
nghttp2_session_client_new2(&session, &callbacks, &ud, option);
frame.ext.payload = &session->iframe.ext_frame_payload;
open_sent_stream(session, 1);
nghttp2_frame_altsvc_init(&frame.ext, 1, origin, 0, field_value,
sizeof(field_value) - 1);
ud.frame_recv_cb_called = 0;
rv = nghttp2_session_on_altsvc_received(session, &frame);
CU_ASSERT(0 == rv);
CU_ASSERT(1 == ud.frame_recv_cb_called);
nghttp2_session_del(session);
/* Stream does not exist; ALTSVC will be ignored. */
nghttp2_session_client_new2(&session, &callbacks, &ud, option);
frame.ext.payload = &session->iframe.ext_frame_payload;
nghttp2_frame_altsvc_init(&frame.ext, 1, origin, 0, field_value,
sizeof(field_value) - 1);
ud.frame_recv_cb_called = 0;
rv = nghttp2_session_on_altsvc_received(session, &frame);
CU_ASSERT(0 == rv);
CU_ASSERT(0 == ud.frame_recv_cb_called);
nghttp2_session_del(session);
nghttp2_option_del(option);
}
void test_nghttp2_session_send_headers_start_stream(void) {
nghttp2_session *session;
nghttp2_session_callbacks callbacks;

View File

@ -45,6 +45,7 @@ void test_nghttp2_session_recv_unexpected_continuation(void);
void test_nghttp2_session_recv_settings_header_table_size(void);
void test_nghttp2_session_recv_too_large_frame_length(void);
void test_nghttp2_session_recv_extension(void);
void test_nghttp2_session_recv_altsvc(void);
void test_nghttp2_session_continue(void);
void test_nghttp2_session_add_frame(void);
void test_nghttp2_session_on_request_headers_received(void);
@ -60,6 +61,7 @@ void test_nghttp2_session_on_goaway_received(void);
void test_nghttp2_session_on_window_update_received(void);
void test_nghttp2_session_on_data_received(void);
void test_nghttp2_session_on_data_received_fail_fast(void);
void test_nghttp2_session_on_altsvc_received(void);
void test_nghttp2_session_send_headers_start_stream(void);
void test_nghttp2_session_send_headers_reply(void);
void test_nghttp2_session_send_headers_frame_size_error(void);