2 * nghttp2 - HTTP/2 C Library
4 * Copyright (c) 2013 Tatsuhiro Tsujikawa
6 * Permission is hereby granted, free of charge, to any person obtaining
7 * a copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sublicense, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
14 * The above copyright notice and this permission notice shall be
15 * included in all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 #include "nghttp2_session_test.h"
30 #include <CUnit/CUnit.h>
32 #include "nghttp2_session.h"
33 #include "nghttp2_stream.h"
34 #include "nghttp2_net.h"
35 #include "nghttp2_helper.h"
36 #include "nghttp2_test_helper.h"
37 #include "nghttp2_priority_spec.h"
39 extern int nghttp2_enable_strict_preface;
41 #define OB_CTRL(ITEM) nghttp2_outbound_item_get_ctrl_frame(ITEM)
42 #define OB_CTRL_TYPE(ITEM) nghttp2_outbound_item_get_ctrl_frame_type(ITEM)
43 #define OB_DATA(ITEM) nghttp2_outbound_item_get_data_frame(ITEM)
60 scripted_data_feed *df;
61 int frame_recv_cb_called, invalid_frame_recv_cb_called;
62 uint8_t recv_frame_type;
63 int frame_send_cb_called;
64 uint8_t sent_frame_type;
65 int frame_not_send_cb_called;
66 uint8_t not_sent_frame_type;
68 int stream_close_cb_called;
69 uint32_t stream_close_error_code;
70 size_t data_source_length;
73 int data_chunk_recv_cb_called;
74 const nghttp2_frame *frame;
77 int begin_headers_cb_called;
79 size_t data_chunk_len;
81 int begin_frame_cb_called;
84 static const nghttp2_nv reqnv[] = {
85 MAKE_NV(":method", "GET"), MAKE_NV(":path", "/"),
86 MAKE_NV(":scheme", "https"), MAKE_NV(":authority", "localhost"),
89 static const nghttp2_nv resnv[] = {
90 MAKE_NV(":status", "200"),
93 static const nghttp2_nv trailernv[] = {
94 // from http://tools.ietf.org/html/rfc6249#section-7
95 MAKE_NV("digest", "SHA-256="
96 "MWVkMWQxYTRiMzk5MDQ0MzI3NGU5NDEyZTk5OWY1ZGFmNzgyZTJlODYz"
97 "YjRjYzFhOTlmNTQwYzI2M2QwM2U2MQ=="),
100 static void scripted_data_feed_init2(scripted_data_feed *df,
101 nghttp2_bufs *bufs) {
102 nghttp2_buf_chain *ci;
107 memset(df, 0, sizeof(scripted_data_feed));
111 for (ci = bufs->head; ci; ci = ci->next) {
113 ptr = nghttp2_cpymem(ptr, buf->pos, nghttp2_buf_len(buf));
114 len += nghttp2_buf_len(buf);
117 df->datamark = df->data;
118 df->datalimit = df->data + len;
119 df->feedseq[0] = len;
122 static ssize_t null_send_callback(nghttp2_session *session _U_,
123 const uint8_t *data _U_, size_t len,
124 int flags _U_, void *user_data _U_) {
128 static ssize_t fail_send_callback(nghttp2_session *session _U_,
129 const uint8_t *data _U_, size_t len _U_,
130 int flags _U_, void *user_data _U_) {
131 return NGHTTP2_ERR_CALLBACK_FAILURE;
134 static ssize_t fixed_bytes_send_callback(nghttp2_session *session _U_,
135 const uint8_t *data _U_, size_t len,
136 int flags _U_, void *user_data) {
137 size_t fixed_sendlen = ((my_user_data *)user_data)->fixed_sendlen;
138 return fixed_sendlen < len ? fixed_sendlen : len;
141 static ssize_t scripted_recv_callback(nghttp2_session *session _U_,
142 uint8_t *data, size_t len, int flags _U_,
144 scripted_data_feed *df = ((my_user_data *)user_data)->df;
145 size_t wlen = df->feedseq[df->seqidx] > len ? len : df->feedseq[df->seqidx];
146 memcpy(data, df->datamark, wlen);
147 df->datamark += wlen;
148 df->feedseq[df->seqidx] -= wlen;
149 if (df->feedseq[df->seqidx] == 0) {
155 static ssize_t eof_recv_callback(nghttp2_session *session _U_,
156 uint8_t *data _U_, size_t len _U_,
157 int flags _U_, void *user_data _U_) {
158 return NGHTTP2_ERR_EOF;
161 static ssize_t accumulator_send_callback(nghttp2_session *session _U_,
162 const uint8_t *buf, size_t len,
163 int flags _U_, void *user_data) {
164 accumulator *acc = ((my_user_data *)user_data)->acc;
165 assert(acc->length + len < sizeof(acc->buf));
166 memcpy(acc->buf + acc->length, buf, len);
171 static int on_begin_frame_callback(nghttp2_session *session _U_,
172 const nghttp2_frame_hd *hd _U_,
174 my_user_data *ud = (my_user_data *)user_data;
175 ++ud->begin_frame_cb_called;
179 static int on_frame_recv_callback(nghttp2_session *session _U_,
180 const nghttp2_frame *frame, void *user_data) {
181 my_user_data *ud = (my_user_data *)user_data;
182 ++ud->frame_recv_cb_called;
183 ud->recv_frame_type = frame->hd.type;
187 static int on_invalid_frame_recv_callback(nghttp2_session *session _U_,
188 const nghttp2_frame *frame _U_,
189 int lib_error_code _U_,
191 my_user_data *ud = (my_user_data *)user_data;
192 ++ud->invalid_frame_recv_cb_called;
196 static int on_frame_send_callback(nghttp2_session *session _U_,
197 const nghttp2_frame *frame, void *user_data) {
198 my_user_data *ud = (my_user_data *)user_data;
199 ++ud->frame_send_cb_called;
200 ud->sent_frame_type = frame->hd.type;
204 static int on_frame_not_send_callback(nghttp2_session *session _U_,
205 const nghttp2_frame *frame, int lib_error,
207 my_user_data *ud = (my_user_data *)user_data;
208 ++ud->frame_not_send_cb_called;
209 ud->not_sent_frame_type = frame->hd.type;
210 ud->not_sent_error = lib_error;
214 static int on_data_chunk_recv_callback(nghttp2_session *session _U_,
215 uint8_t flags _U_, int32_t stream_id _U_,
216 const uint8_t *data _U_, size_t len,
218 my_user_data *ud = (my_user_data *)user_data;
219 ++ud->data_chunk_recv_cb_called;
220 ud->data_chunk_len = len;
224 static int pause_on_data_chunk_recv_callback(nghttp2_session *session _U_,
226 int32_t stream_id _U_,
227 const uint8_t *data _U_,
228 size_t len _U_, void *user_data) {
229 my_user_data *ud = (my_user_data *)user_data;
230 ++ud->data_chunk_recv_cb_called;
231 return NGHTTP2_ERR_PAUSE;
234 static ssize_t select_padding_callback(nghttp2_session *session _U_,
235 const nghttp2_frame *frame,
236 size_t max_payloadlen, void *user_data) {
237 my_user_data *ud = (my_user_data *)user_data;
238 return nghttp2_min(max_payloadlen, frame->hd.length + ud->padlen);
241 static ssize_t too_large_data_source_length_callback(
242 nghttp2_session *session _U_, uint8_t frame_type _U_, int32_t stream_id _U_,
243 int32_t session_remote_window_size _U_,
244 int32_t stream_remote_window_size _U_, uint32_t remote_max_frame_size _U_,
245 void *user_data _U_) {
246 return NGHTTP2_MAX_FRAME_SIZE_MAX + 1;
249 static ssize_t smallest_length_data_source_length_callback(
250 nghttp2_session *session _U_, uint8_t frame_type _U_, int32_t stream_id _U_,
251 int32_t session_remote_window_size _U_,
252 int32_t stream_remote_window_size _U_, uint32_t remote_max_frame_size _U_,
253 void *user_data _U_) {
257 static ssize_t fixed_length_data_source_read_callback(
258 nghttp2_session *session _U_, int32_t stream_id _U_, uint8_t *buf _U_,
259 size_t len, uint32_t *data_flags, nghttp2_data_source *source _U_,
261 my_user_data *ud = (my_user_data *)user_data;
263 if (len < ud->data_source_length) {
266 wlen = ud->data_source_length;
268 ud->data_source_length -= wlen;
269 if (ud->data_source_length == 0) {
270 *data_flags |= NGHTTP2_DATA_FLAG_EOF;
275 static ssize_t temporal_failure_data_source_read_callback(
276 nghttp2_session *session _U_, int32_t stream_id _U_, uint8_t *buf _U_,
277 size_t len _U_, uint32_t *data_flags _U_, nghttp2_data_source *source _U_,
278 void *user_data _U_) {
279 return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
282 static ssize_t fail_data_source_read_callback(nghttp2_session *session _U_,
283 int32_t stream_id _U_,
284 uint8_t *buf _U_, size_t len _U_,
285 uint32_t *data_flags _U_,
286 nghttp2_data_source *source _U_,
287 void *user_data _U_) {
288 return NGHTTP2_ERR_CALLBACK_FAILURE;
291 static ssize_t no_end_stream_data_source_read_callback(
292 nghttp2_session *session _U_, int32_t stream_id _U_, uint8_t *buf _U_,
293 size_t len _U_, uint32_t *data_flags, nghttp2_data_source *source _U_,
294 void *user_data _U_) {
295 *data_flags |= NGHTTP2_DATA_FLAG_EOF | NGHTTP2_DATA_FLAG_NO_END_STREAM;
299 static ssize_t no_copy_data_source_read_callback(
300 nghttp2_session *session _U_, int32_t stream_id _U_, uint8_t *buf _U_,
301 size_t len, uint32_t *data_flags, nghttp2_data_source *source _U_,
303 my_user_data *ud = (my_user_data *)user_data;
305 if (len < ud->data_source_length) {
308 wlen = ud->data_source_length;
311 ud->data_source_length -= wlen;
313 *data_flags |= NGHTTP2_DATA_FLAG_NO_COPY;
315 if (ud->data_source_length == 0) {
316 *data_flags |= NGHTTP2_DATA_FLAG_EOF;
321 static int send_data_callback(nghttp2_session *session _U_,
322 nghttp2_frame *frame, const uint8_t *framehd,
323 size_t length, nghttp2_data_source *source _U_,
325 accumulator *acc = ((my_user_data *)user_data)->acc;
327 memcpy(acc->buf + acc->length, framehd, NGHTTP2_FRAME_HDLEN);
328 acc->length += NGHTTP2_FRAME_HDLEN;
330 if (frame->data.padlen) {
331 *(acc->buf + acc->length++) = frame->data.padlen - 1;
334 acc->length += length;
336 if (frame->data.padlen) {
337 acc->length += frame->data.padlen - 1;
343 /* static void no_stream_user_data_stream_close_callback */
344 /* (nghttp2_session *session, */
345 /* int32_t stream_id, */
346 /* nghttp2_error_code error_code, */
347 /* void *user_data) */
349 /* my_user_data* my_data = (my_user_data*)user_data; */
350 /* ++my_data->stream_close_cb_called; */
353 static ssize_t block_count_send_callback(nghttp2_session *session _U_,
354 const uint8_t *data _U_, size_t len,
355 int flags _U_, void *user_data) {
356 my_user_data *ud = (my_user_data *)user_data;
358 if (ud->block_count == 0) {
359 r = NGHTTP2_ERR_WOULDBLOCK;
367 static int on_header_callback(nghttp2_session *session _U_,
368 const nghttp2_frame *frame, const uint8_t *name,
369 size_t namelen, const uint8_t *value,
370 size_t valuelen, uint8_t flags _U_,
372 my_user_data *ud = (my_user_data *)user_data;
373 ++ud->header_cb_called;
374 ud->nv.name = (uint8_t *)name;
375 ud->nv.namelen = namelen;
376 ud->nv.value = (uint8_t *)value;
377 ud->nv.valuelen = valuelen;
383 static int pause_on_header_callback(nghttp2_session *session,
384 const nghttp2_frame *frame,
385 const uint8_t *name, size_t namelen,
386 const uint8_t *value, size_t valuelen,
387 uint8_t flags, void *user_data) {
388 on_header_callback(session, frame, name, namelen, value, valuelen, flags,
390 return NGHTTP2_ERR_PAUSE;
393 static int temporal_failure_on_header_callback(
394 nghttp2_session *session, const nghttp2_frame *frame, const uint8_t *name,
395 size_t namelen, const uint8_t *value, size_t valuelen, uint8_t flags,
397 on_header_callback(session, frame, name, namelen, value, valuelen, flags,
399 return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
402 static int on_begin_headers_callback(nghttp2_session *session _U_,
403 const nghttp2_frame *frame _U_,
405 my_user_data *ud = (my_user_data *)user_data;
406 ++ud->begin_headers_cb_called;
410 static int temporal_failure_on_begin_headers_callback(
411 nghttp2_session *session, const nghttp2_frame *frame, void *user_data) {
412 on_begin_headers_callback(session, frame, user_data);
413 return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
416 static ssize_t defer_data_source_read_callback(nghttp2_session *session _U_,
417 int32_t stream_id _U_,
418 uint8_t *buf _U_, size_t len _U_,
419 uint32_t *data_flags _U_,
420 nghttp2_data_source *source _U_,
421 void *user_data _U_) {
422 return NGHTTP2_ERR_DEFERRED;
425 static int on_stream_close_callback(nghttp2_session *session _U_,
426 int32_t stream_id _U_,
427 nghttp2_error_code error_code _U_,
429 my_user_data *my_data = (my_user_data *)user_data;
430 ++my_data->stream_close_cb_called;
431 my_data->stream_close_error_code = error_code;
436 static nghttp2_settings_entry *dup_iv(const nghttp2_settings_entry *iv,
438 return nghttp2_frame_iv_copy(iv, niv, nghttp2_mem_default());
441 static nghttp2_priority_spec pri_spec_default = {0, NGHTTP2_DEFAULT_WEIGHT, 0};
443 void test_nghttp2_session_recv(void) {
444 nghttp2_session *session;
445 nghttp2_session_callbacks callbacks;
446 scripted_data_feed df;
447 my_user_data user_data;
452 nghttp2_outbound_item *item;
455 nghttp2_hd_deflater deflater;
459 mem = nghttp2_mem_default();
460 frame_pack_bufs_init(&bufs);
462 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
463 callbacks.send_callback = null_send_callback;
464 callbacks.recv_callback = scripted_recv_callback;
465 callbacks.on_frame_recv_callback = on_frame_recv_callback;
466 callbacks.on_begin_frame_callback = on_begin_frame_callback;
470 nghttp2_session_server_new(&session, &callbacks, &user_data);
471 nghttp2_hd_deflate_init(&deflater, mem);
473 nvlen = ARRLEN(reqnv);
474 nghttp2_nv_array_copy(&nva, reqnv, nvlen, mem);
475 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 1,
476 NGHTTP2_HCAT_HEADERS, NULL, nva, nvlen);
477 rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
481 scripted_data_feed_init2(&df, &bufs);
483 framelen = nghttp2_bufs_len(&bufs);
485 /* Send 1 byte per each read */
486 for (i = 0; i < framelen; ++i) {
490 nghttp2_frame_headers_free(&frame.headers, mem);
492 user_data.frame_recv_cb_called = 0;
493 user_data.begin_frame_cb_called = 0;
495 while ((ssize_t)df.seqidx < framelen) {
496 CU_ASSERT(0 == nghttp2_session_recv(session));
498 CU_ASSERT(1 == user_data.frame_recv_cb_called);
499 CU_ASSERT(1 == user_data.begin_frame_cb_called);
501 nghttp2_bufs_reset(&bufs);
503 /* Receive PRIORITY */
504 nghttp2_frame_priority_init(&frame.priority, 5, &pri_spec_default);
506 rv = nghttp2_frame_pack_priority(&bufs, &frame.priority);
510 nghttp2_frame_priority_free(&frame.priority);
512 scripted_data_feed_init2(&df, &bufs);
514 user_data.frame_recv_cb_called = 0;
515 user_data.begin_frame_cb_called = 0;
517 CU_ASSERT(0 == nghttp2_session_recv(session));
518 CU_ASSERT(1 == user_data.frame_recv_cb_called);
519 CU_ASSERT(1 == user_data.begin_frame_cb_called);
521 nghttp2_bufs_reset(&bufs);
523 nghttp2_hd_deflate_free(&deflater);
524 nghttp2_session_del(session);
526 /* Some tests for frame too large */
527 nghttp2_session_server_new(&session, &callbacks, &user_data);
529 /* Receive PING with too large payload */
530 nghttp2_frame_ping_init(&frame.ping, NGHTTP2_FLAG_NONE, NULL);
532 rv = nghttp2_frame_pack_ping(&bufs, &frame.ping);
536 /* Add extra 16 bytes */
537 nghttp2_bufs_seek_last_present(&bufs);
538 assert(nghttp2_buf_len(&bufs.cur->buf) >= 16);
540 bufs.cur->buf.last += 16;
541 nghttp2_put_uint32be(
543 (uint32_t)(((frame.hd.length + 16) << 8) + bufs.cur->buf.pos[3]));
545 nghttp2_frame_ping_free(&frame.ping);
547 scripted_data_feed_init2(&df, &bufs);
548 user_data.frame_recv_cb_called = 0;
549 user_data.begin_frame_cb_called = 0;
551 CU_ASSERT(0 == nghttp2_session_recv(session));
552 CU_ASSERT(0 == user_data.frame_recv_cb_called);
553 CU_ASSERT(0 == user_data.begin_frame_cb_called);
555 item = nghttp2_session_get_next_ob_item(session);
556 CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
557 CU_ASSERT(NGHTTP2_FRAME_SIZE_ERROR == item->frame.goaway.error_code);
558 CU_ASSERT(0 == nghttp2_session_send(session));
560 nghttp2_bufs_free(&bufs);
561 nghttp2_session_del(session);
564 void test_nghttp2_session_recv_invalid_stream_id(void) {
565 nghttp2_session *session;
566 nghttp2_session_callbacks callbacks;
567 scripted_data_feed df;
568 my_user_data user_data;
571 nghttp2_hd_deflater deflater;
577 mem = nghttp2_mem_default();
578 frame_pack_bufs_init(&bufs);
580 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
581 callbacks.recv_callback = scripted_recv_callback;
582 callbacks.on_invalid_frame_recv_callback = on_invalid_frame_recv_callback;
585 user_data.invalid_frame_recv_cb_called = 0;
586 nghttp2_session_server_new(&session, &callbacks, &user_data);
587 nghttp2_hd_deflate_init(&deflater, mem);
589 nvlen = ARRLEN(reqnv);
590 nghttp2_nv_array_copy(&nva, reqnv, nvlen, mem);
591 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 2,
592 NGHTTP2_HCAT_HEADERS, NULL, nva, nvlen);
593 rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
596 CU_ASSERT(nghttp2_bufs_len(&bufs) > 0);
598 scripted_data_feed_init2(&df, &bufs);
599 nghttp2_frame_headers_free(&frame.headers, mem);
601 CU_ASSERT(0 == nghttp2_session_recv(session));
602 CU_ASSERT(1 == user_data.invalid_frame_recv_cb_called);
604 nghttp2_bufs_free(&bufs);
605 nghttp2_hd_deflate_free(&deflater);
606 nghttp2_session_del(session);
609 void test_nghttp2_session_recv_invalid_frame(void) {
610 nghttp2_session *session;
611 nghttp2_session_callbacks callbacks;
612 scripted_data_feed df;
613 my_user_data user_data;
618 nghttp2_hd_deflater deflater;
622 mem = nghttp2_mem_default();
623 frame_pack_bufs_init(&bufs);
625 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
626 callbacks.recv_callback = scripted_recv_callback;
627 callbacks.send_callback = null_send_callback;
628 callbacks.on_frame_send_callback = on_frame_send_callback;
631 user_data.frame_send_cb_called = 0;
632 nghttp2_session_server_new(&session, &callbacks, &user_data);
633 nghttp2_hd_deflate_init(&deflater, mem);
634 nvlen = ARRLEN(reqnv);
635 nghttp2_nv_array_copy(&nva, reqnv, nvlen, mem);
636 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 1,
637 NGHTTP2_HCAT_HEADERS, NULL, nva, nvlen);
638 rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
641 CU_ASSERT(nghttp2_bufs_len(&bufs) > 0);
643 scripted_data_feed_init2(&df, &bufs);
645 CU_ASSERT(0 == nghttp2_session_recv(session));
646 CU_ASSERT(0 == nghttp2_session_send(session));
647 CU_ASSERT(0 == user_data.frame_send_cb_called);
649 /* Receive exactly same bytes of HEADERS is treated as error, because it has
650 * pseudo headers and without END_STREAM flag set */
651 scripted_data_feed_init2(&df, &bufs);
653 CU_ASSERT(0 == nghttp2_session_recv(session));
654 CU_ASSERT(0 == nghttp2_session_send(session));
655 CU_ASSERT(1 == user_data.frame_send_cb_called);
656 CU_ASSERT(NGHTTP2_RST_STREAM == user_data.sent_frame_type);
658 nghttp2_bufs_free(&bufs);
659 nghttp2_frame_headers_free(&frame.headers, mem);
661 nghttp2_hd_deflate_free(&deflater);
662 nghttp2_session_del(session);
665 void test_nghttp2_session_recv_eof(void) {
666 nghttp2_session *session;
667 nghttp2_session_callbacks callbacks;
669 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
670 callbacks.send_callback = null_send_callback;
671 callbacks.recv_callback = eof_recv_callback;
673 nghttp2_session_client_new(&session, &callbacks, NULL);
674 CU_ASSERT(NGHTTP2_ERR_EOF == nghttp2_session_recv(session));
676 nghttp2_session_del(session);
679 void test_nghttp2_session_recv_data(void) {
680 nghttp2_session *session;
681 nghttp2_session_callbacks callbacks;
685 nghttp2_outbound_item *item;
686 nghttp2_stream *stream;
690 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
691 callbacks.send_callback = null_send_callback;
692 callbacks.on_data_chunk_recv_callback = on_data_chunk_recv_callback;
693 callbacks.on_frame_recv_callback = on_frame_recv_callback;
695 nghttp2_session_client_new(&session, &callbacks, &ud);
697 /* Create DATA frame with length 4KiB */
698 memset(data, 0, sizeof(data));
700 hd.type = NGHTTP2_DATA;
701 hd.flags = NGHTTP2_FLAG_NONE;
703 nghttp2_frame_pack_frame_hd(data, &hd);
705 /* stream 1 is not opened, so it must be responded with connection
706 error. This is not mandated by the spec */
707 ud.data_chunk_recv_cb_called = 0;
708 ud.frame_recv_cb_called = 0;
709 rv = nghttp2_session_mem_recv(session, data, NGHTTP2_FRAME_HDLEN + 4096);
710 CU_ASSERT(NGHTTP2_FRAME_HDLEN + 4096 == rv);
712 CU_ASSERT(0 == ud.data_chunk_recv_cb_called);
713 CU_ASSERT(0 == ud.frame_recv_cb_called);
714 item = nghttp2_session_get_next_ob_item(session);
715 CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
717 nghttp2_session_del(session);
719 nghttp2_session_client_new(&session, &callbacks, &ud);
721 /* Create stream 1 with CLOSING state. DATA is ignored. */
722 stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
724 NGHTTP2_STREAM_CLOSING, NULL);
725 /* Set initial window size 16383 to check stream flow control,
726 isolating it from the conneciton flow control */
727 stream->local_window_size = 16383;
729 ud.data_chunk_recv_cb_called = 0;
730 ud.frame_recv_cb_called = 0;
731 rv = nghttp2_session_mem_recv(session, data, NGHTTP2_FRAME_HDLEN + 4096);
732 CU_ASSERT(NGHTTP2_FRAME_HDLEN + 4096 == rv);
734 CU_ASSERT(0 == ud.data_chunk_recv_cb_called);
735 CU_ASSERT(0 == ud.frame_recv_cb_called);
736 item = nghttp2_session_get_next_ob_item(session);
737 CU_ASSERT(NULL == item);
739 /* This is normal case. DATA is acceptable. */
740 stream->state = NGHTTP2_STREAM_OPENED;
742 ud.data_chunk_recv_cb_called = 0;
743 ud.frame_recv_cb_called = 0;
744 rv = nghttp2_session_mem_recv(session, data, NGHTTP2_FRAME_HDLEN + 4096);
745 CU_ASSERT(NGHTTP2_FRAME_HDLEN + 4096 == rv);
747 CU_ASSERT(1 == ud.data_chunk_recv_cb_called);
748 CU_ASSERT(1 == ud.frame_recv_cb_called);
750 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
752 ud.data_chunk_recv_cb_called = 0;
753 ud.frame_recv_cb_called = 0;
754 rv = nghttp2_session_mem_recv(session, data, NGHTTP2_FRAME_HDLEN + 4096);
755 CU_ASSERT(NGHTTP2_FRAME_HDLEN + 4096 == rv);
757 /* Now we got data more than initial-window-size / 2, WINDOW_UPDATE
759 CU_ASSERT(1 == ud.data_chunk_recv_cb_called);
760 CU_ASSERT(1 == ud.frame_recv_cb_called);
761 item = nghttp2_session_get_next_ob_item(session);
762 CU_ASSERT(NGHTTP2_WINDOW_UPDATE == item->frame.hd.type);
763 CU_ASSERT(1 == item->frame.window_update.hd.stream_id);
764 CU_ASSERT(0 == nghttp2_session_send(session));
766 /* Set initial window size to 1MiB, so that we can check connection
767 flow control individually */
768 stream->local_window_size = 1 << 20;
769 /* Connection flow control takes into account DATA which is received
770 in the error condition. We have received 4096 * 4 bytes of
771 DATA. Additional 4 DATA frames, connection flow control will kick
773 for (i = 0; i < 5; ++i) {
774 rv = nghttp2_session_mem_recv(session, data, NGHTTP2_FRAME_HDLEN + 4096);
775 CU_ASSERT(NGHTTP2_FRAME_HDLEN + 4096 == rv);
777 item = nghttp2_session_get_next_ob_item(session);
778 CU_ASSERT(NGHTTP2_WINDOW_UPDATE == item->frame.hd.type);
779 CU_ASSERT(0 == item->frame.window_update.hd.stream_id);
780 CU_ASSERT(0 == nghttp2_session_send(session));
782 /* Reception of DATA with stream ID = 0 causes connection error */
784 hd.type = NGHTTP2_DATA;
785 hd.flags = NGHTTP2_FLAG_NONE;
787 nghttp2_frame_pack_frame_hd(data, &hd);
789 ud.data_chunk_recv_cb_called = 0;
790 ud.frame_recv_cb_called = 0;
791 rv = nghttp2_session_mem_recv(session, data, NGHTTP2_FRAME_HDLEN + 4096);
792 CU_ASSERT(NGHTTP2_FRAME_HDLEN + 4096 == rv);
794 CU_ASSERT(0 == ud.data_chunk_recv_cb_called);
795 CU_ASSERT(0 == ud.frame_recv_cb_called);
796 item = nghttp2_session_get_next_ob_item(session);
797 CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
798 CU_ASSERT(NGHTTP2_PROTOCOL_ERROR == item->frame.goaway.error_code);
800 nghttp2_session_del(session);
803 void test_nghttp2_session_recv_continuation(void) {
804 nghttp2_session *session;
805 nghttp2_session_callbacks callbacks;
813 nghttp2_hd_deflater deflater;
816 nghttp2_frame_hd cont_hd;
817 nghttp2_priority_spec pri_spec;
820 mem = nghttp2_mem_default();
821 frame_pack_bufs_init(&bufs);
823 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
824 callbacks.on_header_callback = on_header_callback;
825 callbacks.on_begin_headers_callback = on_begin_headers_callback;
826 callbacks.on_begin_frame_callback = on_begin_frame_callback;
828 nghttp2_session_server_new(&session, &callbacks, &ud);
830 nghttp2_hd_deflate_init(&deflater, mem);
832 /* Make 1 HEADERS and insert CONTINUATION header */
833 nvlen = ARRLEN(reqnv);
834 nghttp2_nv_array_copy(&nva, reqnv, nvlen, mem);
835 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_NONE, 1,
836 NGHTTP2_HCAT_HEADERS, NULL, nva, nvlen);
837 rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
840 CU_ASSERT(nghttp2_bufs_len(&bufs) > 0);
842 /* make sure that all data is in the first buf */
843 buf = &bufs.head->buf;
844 assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
846 nghttp2_frame_headers_free(&frame.headers, mem);
848 /* HEADERS's payload is 1 byte */
849 memcpy(data, buf->pos, NGHTTP2_FRAME_HDLEN + 1);
850 datalen = NGHTTP2_FRAME_HDLEN + 1;
851 buf->pos += NGHTTP2_FRAME_HDLEN + 1;
853 nghttp2_put_uint32be(data, (1 << 8) + data[3]);
855 /* First CONTINUATION, 2 bytes */
856 nghttp2_frame_hd_init(&cont_hd, 2, NGHTTP2_CONTINUATION, NGHTTP2_FLAG_NONE,
859 nghttp2_frame_pack_frame_hd(data + datalen, &cont_hd);
860 datalen += NGHTTP2_FRAME_HDLEN;
862 memcpy(data + datalen, buf->pos, cont_hd.length);
863 datalen += cont_hd.length;
864 buf->pos += cont_hd.length;
866 /* Second CONTINUATION, rest of the bytes */
867 nghttp2_frame_hd_init(&cont_hd, nghttp2_buf_len(buf), NGHTTP2_CONTINUATION,
868 NGHTTP2_FLAG_END_HEADERS, 1);
870 nghttp2_frame_pack_frame_hd(data + datalen, &cont_hd);
871 datalen += NGHTTP2_FRAME_HDLEN;
873 memcpy(data + datalen, buf->pos, cont_hd.length);
874 datalen += cont_hd.length;
875 buf->pos += cont_hd.length;
877 CU_ASSERT(0 == nghttp2_buf_len(buf));
879 ud.header_cb_called = 0;
880 ud.begin_frame_cb_called = 0;
882 rv = nghttp2_session_mem_recv(session, data, datalen);
883 CU_ASSERT((ssize_t)datalen == rv);
884 CU_ASSERT(4 == ud.header_cb_called);
885 CU_ASSERT(3 == ud.begin_frame_cb_called);
887 nghttp2_hd_deflate_free(&deflater);
888 nghttp2_session_del(session);
890 /* Expecting CONTINUATION, but get the other frame */
891 nghttp2_session_server_new(&session, &callbacks, &ud);
893 nghttp2_hd_deflate_init(&deflater, mem);
895 /* HEADERS without END_HEADERS flag */
896 nvlen = ARRLEN(reqnv);
897 nghttp2_nv_array_copy(&nva, reqnv, nvlen, mem);
898 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_NONE, 1,
899 NGHTTP2_HCAT_HEADERS, NULL, nva, nvlen);
900 nghttp2_bufs_reset(&bufs);
901 rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
904 CU_ASSERT(nghttp2_bufs_len(&bufs) > 0);
906 nghttp2_frame_headers_free(&frame.headers, mem);
908 /* make sure that all data is in the first buf */
909 buf = &bufs.head->buf;
910 assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
912 memcpy(data, buf->pos, nghttp2_buf_len(buf));
913 datalen = nghttp2_buf_len(buf);
915 /* Followed by PRIORITY */
916 nghttp2_priority_spec_default_init(&pri_spec);
918 nghttp2_frame_priority_init(&frame.priority, 1, &pri_spec);
919 nghttp2_bufs_reset(&bufs);
921 rv = nghttp2_frame_pack_priority(&bufs, &frame.priority);
924 CU_ASSERT(nghttp2_bufs_len(&bufs) > 0);
926 memcpy(data + datalen, buf->pos, nghttp2_buf_len(buf));
927 datalen += nghttp2_buf_len(buf);
929 ud.begin_headers_cb_called = 0;
930 rv = nghttp2_session_mem_recv(session, data, datalen);
931 CU_ASSERT((ssize_t)datalen == rv);
933 CU_ASSERT(1 == ud.begin_headers_cb_called);
934 CU_ASSERT(NGHTTP2_GOAWAY ==
935 nghttp2_session_get_next_ob_item(session)->frame.hd.type);
937 nghttp2_bufs_free(&bufs);
938 nghttp2_hd_deflate_free(&deflater);
939 nghttp2_session_del(session);
942 void test_nghttp2_session_recv_headers_with_priority(void) {
943 nghttp2_session *session;
944 nghttp2_session_callbacks callbacks;
952 nghttp2_hd_deflater deflater;
953 nghttp2_outbound_item *item;
954 nghttp2_priority_spec pri_spec;
955 nghttp2_stream *stream;
958 mem = nghttp2_mem_default();
959 frame_pack_bufs_init(&bufs);
961 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
962 callbacks.on_frame_recv_callback = on_frame_recv_callback;
964 nghttp2_session_server_new(&session, &callbacks, &ud);
966 nghttp2_hd_deflate_init(&deflater, mem);
968 open_stream(session, 1);
970 /* With NGHTTP2_FLAG_PRIORITY without exclusive flag set */
971 nvlen = ARRLEN(reqnv);
972 nghttp2_nv_array_copy(&nva, reqnv, nvlen, mem);
974 nghttp2_priority_spec_init(&pri_spec, 1, 99, 0);
976 nghttp2_frame_headers_init(&frame.headers,
977 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PRIORITY,
978 3, NGHTTP2_HCAT_HEADERS, &pri_spec, nva, nvlen);
980 rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
983 CU_ASSERT(nghttp2_bufs_len(&bufs) > 0);
985 nghttp2_frame_headers_free(&frame.headers, mem);
987 buf = &bufs.head->buf;
988 assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
990 ud.frame_recv_cb_called = 0;
992 rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
994 CU_ASSERT(nghttp2_buf_len(buf) == rv);
995 CU_ASSERT(1 == ud.frame_recv_cb_called);
997 stream = nghttp2_session_get_stream(session, 3);
999 CU_ASSERT(99 == stream->weight);
1000 CU_ASSERT(1 == stream->dep_prev->stream_id);
1002 nghttp2_bufs_reset(&bufs);
1004 /* With NGHTTP2_FLAG_PRIORITY, but cut last 1 byte to make it
1006 nvlen = ARRLEN(reqnv);
1007 nghttp2_nv_array_copy(&nva, reqnv, nvlen, mem);
1009 nghttp2_priority_spec_init(&pri_spec, 0, 99, 0);
1011 nghttp2_frame_headers_init(&frame.headers,
1012 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PRIORITY,
1013 5, NGHTTP2_HCAT_HEADERS, &pri_spec, nva, nvlen);
1015 rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
1018 CU_ASSERT(nghttp2_bufs_len(&bufs) > NGHTTP2_FRAME_HDLEN + 5);
1020 nghttp2_frame_headers_free(&frame.headers, mem);
1022 buf = &bufs.head->buf;
1023 /* Make payload shorter than required length to store priority
1025 nghttp2_put_uint32be(buf->pos, (4 << 8) + buf->pos[3]);
1027 ud.frame_recv_cb_called = 0;
1029 rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
1031 CU_ASSERT(nghttp2_buf_len(buf) == rv);
1032 CU_ASSERT(0 == ud.frame_recv_cb_called);
1034 stream = nghttp2_session_get_stream(session, 5);
1036 CU_ASSERT(NULL == stream);
1038 item = nghttp2_session_get_next_ob_item(session);
1039 CU_ASSERT(NULL != item);
1040 CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
1041 CU_ASSERT(NGHTTP2_FRAME_SIZE_ERROR == item->frame.goaway.error_code);
1043 nghttp2_bufs_reset(&bufs);
1045 nghttp2_hd_deflate_free(&deflater);
1046 nghttp2_session_del(session);
1048 /* Check dep_stream_id == stream_id */
1049 nghttp2_session_server_new(&session, &callbacks, &ud);
1051 nghttp2_hd_deflate_init(&deflater, mem);
1053 nvlen = ARRLEN(reqnv);
1054 nghttp2_nv_array_copy(&nva, reqnv, nvlen, mem);
1056 nghttp2_priority_spec_init(&pri_spec, 1, 0, 0);
1058 nghttp2_frame_headers_init(&frame.headers,
1059 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PRIORITY,
1060 1, NGHTTP2_HCAT_HEADERS, &pri_spec, nva, nvlen);
1062 rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
1065 CU_ASSERT(nghttp2_bufs_len(&bufs) > 0);
1067 nghttp2_frame_headers_free(&frame.headers, mem);
1069 buf = &bufs.head->buf;
1070 assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
1072 ud.frame_recv_cb_called = 0;
1074 rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
1076 CU_ASSERT(nghttp2_buf_len(buf) == rv);
1077 CU_ASSERT(0 == ud.frame_recv_cb_called);
1079 stream = nghttp2_session_get_stream(session, 1);
1081 CU_ASSERT(NULL == stream);
1083 item = nghttp2_session_get_next_ob_item(session);
1084 CU_ASSERT(NULL != item);
1085 CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
1086 CU_ASSERT(NGHTTP2_PROTOCOL_ERROR == item->frame.goaway.error_code);
1088 nghttp2_bufs_reset(&bufs);
1090 nghttp2_bufs_free(&bufs);
1091 nghttp2_hd_deflate_free(&deflater);
1092 nghttp2_session_del(session);
1095 void test_nghttp2_session_recv_premature_headers(void) {
1096 nghttp2_session *session;
1097 nghttp2_session_callbacks callbacks;
1102 nghttp2_hd_deflater deflater;
1103 nghttp2_outbound_item *item;
1105 uint32_t payloadlen;
1107 mem = nghttp2_mem_default();
1108 frame_pack_bufs_init(&bufs);
1110 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
1111 callbacks.send_callback = null_send_callback;
1113 nghttp2_session_server_new(&session, &callbacks, &ud);
1115 nghttp2_hd_deflate_init(&deflater, mem);
1117 rv = pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, reqnv,
1118 ARRLEN(reqnv), mem);
1120 buf = &bufs.head->buf;
1121 /* Intentionally feed payload cutting last 1 byte off */
1122 payloadlen = nghttp2_get_uint32(buf->pos) >> 8;
1123 nghttp2_put_uint32be(buf->pos, ((payloadlen - 1) << 8) + buf->pos[3]);
1124 rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf) - 1);
1126 CU_ASSERT(rv == nghttp2_buf_len(buf) - 1);
1128 item = nghttp2_session_get_next_ob_item(session);
1130 CU_ASSERT(NULL != item);
1131 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
1132 CU_ASSERT(NGHTTP2_COMPRESSION_ERROR == item->frame.rst_stream.error_code);
1133 CU_ASSERT(1 == item->frame.hd.stream_id);
1134 CU_ASSERT(0 == nghttp2_session_send(session));
1136 nghttp2_bufs_reset(&bufs);
1137 nghttp2_hd_deflate_free(&deflater);
1138 nghttp2_session_del(session);
1140 /* Test for PUSH_PROMISE */
1141 nghttp2_session_client_new(&session, &callbacks, &ud);
1142 nghttp2_hd_deflate_init(&deflater, mem);
1144 nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
1145 &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL);
1147 rv = pack_push_promise(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, 2,
1148 reqnv, ARRLEN(reqnv), mem);
1152 buf = &bufs.head->buf;
1153 payloadlen = nghttp2_get_uint32(buf->pos) >> 8;
1154 /* Intentionally feed payload cutting last 1 byte off */
1155 nghttp2_put_uint32be(buf->pos, ((payloadlen - 1) << 8) + buf->pos[3]);
1156 rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf) - 1);
1158 CU_ASSERT(rv == nghttp2_buf_len(buf) - 1);
1160 item = nghttp2_session_get_next_ob_item(session);
1162 CU_ASSERT(NULL != item);
1163 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
1164 CU_ASSERT(NGHTTP2_COMPRESSION_ERROR == item->frame.rst_stream.error_code);
1165 CU_ASSERT(2 == item->frame.hd.stream_id);
1166 CU_ASSERT(0 == nghttp2_session_send(session));
1168 nghttp2_hd_deflate_free(&deflater);
1169 nghttp2_session_del(session);
1170 nghttp2_bufs_free(&bufs);
1173 void test_nghttp2_session_recv_unknown_frame(void) {
1174 nghttp2_session *session;
1175 nghttp2_session_callbacks callbacks;
1177 uint8_t data[16384];
1179 nghttp2_frame_hd hd;
1182 nghttp2_frame_hd_init(&hd, 16000, 99, NGHTTP2_FLAG_NONE, 0);
1184 nghttp2_frame_pack_frame_hd(data, &hd);
1185 datalen = NGHTTP2_FRAME_HDLEN + hd.length;
1187 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
1188 callbacks.on_frame_recv_callback = on_frame_recv_callback;
1190 nghttp2_session_server_new(&session, &callbacks, &ud);
1192 ud.frame_recv_cb_called = 0;
1194 /* Unknown frame must be ignored */
1195 rv = nghttp2_session_mem_recv(session, data, datalen);
1197 CU_ASSERT(rv == (ssize_t)datalen);
1198 CU_ASSERT(0 == ud.frame_recv_cb_called);
1199 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
1201 nghttp2_session_del(session);
1204 void test_nghttp2_session_recv_unexpected_continuation(void) {
1205 nghttp2_session *session;
1206 nghttp2_session_callbacks callbacks;
1208 uint8_t data[16384];
1210 nghttp2_frame_hd hd;
1212 nghttp2_outbound_item *item;
1214 nghttp2_frame_hd_init(&hd, 16000, NGHTTP2_CONTINUATION,
1215 NGHTTP2_FLAG_END_HEADERS, 1);
1217 nghttp2_frame_pack_frame_hd(data, &hd);
1218 datalen = NGHTTP2_FRAME_HDLEN + hd.length;
1220 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
1221 callbacks.on_frame_recv_callback = on_frame_recv_callback;
1223 nghttp2_session_server_new(&session, &callbacks, &ud);
1225 open_stream(session, 1);
1227 ud.frame_recv_cb_called = 0;
1229 /* unexpected CONTINUATION must be treated as connection error */
1230 rv = nghttp2_session_mem_recv(session, data, datalen);
1232 CU_ASSERT(rv == (ssize_t)datalen);
1233 CU_ASSERT(0 == ud.frame_recv_cb_called);
1235 item = nghttp2_session_get_next_ob_item(session);
1237 CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
1239 nghttp2_session_del(session);
1242 void test_nghttp2_session_recv_settings_header_table_size(void) {
1243 nghttp2_session *session;
1244 nghttp2_session_callbacks callbacks;
1245 nghttp2_frame frame;
1250 nghttp2_settings_entry iv[3];
1251 nghttp2_nv nv = MAKE_NV(":authority", "example.org");
1254 mem = nghttp2_mem_default();
1255 frame_pack_bufs_init(&bufs);
1257 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
1258 callbacks.on_frame_recv_callback = on_frame_recv_callback;
1259 callbacks.send_callback = null_send_callback;
1261 nghttp2_session_client_new(&session, &callbacks, &ud);
1263 iv[0].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
1266 iv[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
1267 iv[1].value = 16384;
1269 nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE, dup_iv(iv, 2),
1272 rv = nghttp2_frame_pack_settings(&bufs, &frame.settings);
1275 CU_ASSERT(nghttp2_bufs_len(&bufs) > 0);
1277 nghttp2_frame_settings_free(&frame.settings, mem);
1279 buf = &bufs.head->buf;
1280 assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
1282 ud.frame_recv_cb_called = 0;
1284 rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
1286 CU_ASSERT(rv == nghttp2_buf_len(buf));
1287 CU_ASSERT(1 == ud.frame_recv_cb_called);
1289 CU_ASSERT(3000 == session->remote_settings.header_table_size);
1290 CU_ASSERT(16384 == session->remote_settings.initial_window_size);
1292 nghttp2_bufs_reset(&bufs);
1294 /* 2 SETTINGS_HEADER_TABLE_SIZE */
1295 iv[0].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
1298 iv[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
1299 iv[1].value = 16383;
1301 iv[2].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
1304 nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE, dup_iv(iv, 3),
1307 rv = nghttp2_frame_pack_settings(&bufs, &frame.settings);
1310 CU_ASSERT(nghttp2_bufs_len(&bufs) > 0);
1312 nghttp2_frame_settings_free(&frame.settings, mem);
1314 buf = &bufs.head->buf;
1315 assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
1317 ud.frame_recv_cb_called = 0;
1319 rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
1321 CU_ASSERT(rv == nghttp2_buf_len(buf));
1322 CU_ASSERT(1 == ud.frame_recv_cb_called);
1324 CU_ASSERT(3001 == session->remote_settings.header_table_size);
1325 CU_ASSERT(16383 == session->remote_settings.initial_window_size);
1327 nghttp2_bufs_reset(&bufs);
1329 /* 2 SETTINGS_HEADER_TABLE_SIZE; first entry clears dynamic header
1332 nghttp2_submit_request(session, NULL, &nv, 1, NULL, NULL);
1333 nghttp2_session_send(session);
1335 CU_ASSERT(0 < session->hd_deflater.ctx.hd_table.len);
1337 iv[0].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
1340 iv[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
1341 iv[1].value = 16382;
1343 iv[2].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
1346 nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE, dup_iv(iv, 3),
1349 rv = nghttp2_frame_pack_settings(&bufs, &frame.settings);
1352 CU_ASSERT(nghttp2_bufs_len(&bufs) > 0);
1354 nghttp2_frame_settings_free(&frame.settings, mem);
1356 buf = &bufs.head->buf;
1357 assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
1359 ud.frame_recv_cb_called = 0;
1361 rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
1363 CU_ASSERT(rv == nghttp2_buf_len(buf));
1364 CU_ASSERT(1 == ud.frame_recv_cb_called);
1366 CU_ASSERT(4096 == session->remote_settings.header_table_size);
1367 CU_ASSERT(16382 == session->remote_settings.initial_window_size);
1368 CU_ASSERT(0 == session->hd_deflater.ctx.hd_table.len);
1370 nghttp2_bufs_reset(&bufs);
1372 /* 2 SETTINGS_HEADER_TABLE_SIZE; second entry clears dynamic header
1375 nghttp2_submit_request(session, NULL, &nv, 1, NULL, NULL);
1376 nghttp2_session_send(session);
1378 CU_ASSERT(0 < session->hd_deflater.ctx.hd_table.len);
1380 iv[0].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
1383 iv[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
1384 iv[1].value = 16381;
1386 iv[2].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
1389 nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE, dup_iv(iv, 3),
1392 rv = nghttp2_frame_pack_settings(&bufs, &frame.settings);
1395 CU_ASSERT(nghttp2_bufs_len(&bufs) > 0);
1397 nghttp2_frame_settings_free(&frame.settings, mem);
1399 buf = &bufs.head->buf;
1400 assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
1402 ud.frame_recv_cb_called = 0;
1404 rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
1406 CU_ASSERT(rv == nghttp2_buf_len(buf));
1407 CU_ASSERT(1 == ud.frame_recv_cb_called);
1409 CU_ASSERT(0 == session->remote_settings.header_table_size);
1410 CU_ASSERT(16381 == session->remote_settings.initial_window_size);
1411 CU_ASSERT(0 == session->hd_deflater.ctx.hd_table.len);
1413 nghttp2_bufs_reset(&bufs);
1415 nghttp2_bufs_free(&bufs);
1416 nghttp2_session_del(session);
1419 void test_nghttp2_session_recv_too_large_frame_length(void) {
1420 nghttp2_session *session;
1421 nghttp2_session_callbacks callbacks;
1422 uint8_t buf[NGHTTP2_FRAME_HDLEN];
1423 nghttp2_outbound_item *item;
1424 nghttp2_frame_hd hd;
1426 /* Initial max frame size is NGHTTP2_MAX_FRAME_SIZE_MIN */
1427 nghttp2_frame_hd_init(&hd, NGHTTP2_MAX_FRAME_SIZE_MIN + 1, NGHTTP2_HEADERS,
1428 NGHTTP2_FLAG_NONE, 1);
1430 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
1432 nghttp2_session_server_new(&session, &callbacks, NULL);
1434 nghttp2_frame_pack_frame_hd(buf, &hd);
1436 CU_ASSERT(sizeof(buf) == nghttp2_session_mem_recv(session, buf, sizeof(buf)));
1438 item = nghttp2_session_get_next_ob_item(session);
1440 CU_ASSERT(item != NULL);
1441 CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
1443 nghttp2_session_del(session);
1446 void test_nghttp2_session_continue(void) {
1447 nghttp2_session *session;
1448 nghttp2_session_callbacks callbacks;
1449 my_user_data user_data;
1450 const nghttp2_nv nv1[] = {MAKE_NV(":method", "GET"), MAKE_NV(":path", "/")};
1451 const nghttp2_nv nv2[] = {MAKE_NV("user-agent", "nghttp2/1.0.0"),
1452 MAKE_NV("alpha", "bravo")};
1455 size_t framelen1, framelen2;
1457 uint8_t buffer[4096];
1458 nghttp2_buf databuf;
1459 nghttp2_frame frame;
1462 const nghttp2_frame *recv_frame;
1463 nghttp2_frame_hd data_hd;
1464 nghttp2_hd_deflater deflater;
1467 mem = nghttp2_mem_default();
1468 frame_pack_bufs_init(&bufs);
1469 nghttp2_buf_wrap_init(&databuf, buffer, sizeof(buffer));
1471 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
1472 callbacks.send_callback = null_send_callback;
1473 callbacks.on_frame_recv_callback = on_frame_recv_callback;
1474 callbacks.on_data_chunk_recv_callback = pause_on_data_chunk_recv_callback;
1475 callbacks.on_header_callback = pause_on_header_callback;
1476 callbacks.on_begin_headers_callback = on_begin_headers_callback;
1478 nghttp2_session_server_new(&session, &callbacks, &user_data);
1479 /* disable strict HTTP layering checks */
1480 session->opt_flags |= NGHTTP2_OPTMASK_NO_HTTP_MESSAGING;
1482 nghttp2_hd_deflate_init(&deflater, mem);
1484 /* Make 2 HEADERS frames */
1485 nvlen = ARRLEN(nv1);
1486 nghttp2_nv_array_copy(&nva, nv1, nvlen, mem);
1487 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 1,
1488 NGHTTP2_HCAT_HEADERS, NULL, nva, nvlen);
1489 rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
1492 CU_ASSERT(nghttp2_bufs_len(&bufs) > 0);
1494 nghttp2_frame_headers_free(&frame.headers, mem);
1496 buf = &bufs.head->buf;
1497 assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
1499 framelen1 = nghttp2_buf_len(buf);
1500 databuf.last = nghttp2_cpymem(databuf.last, buf->pos, nghttp2_buf_len(buf));
1502 nvlen = ARRLEN(nv2);
1503 nghttp2_nv_array_copy(&nva, nv2, nvlen, mem);
1504 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 3,
1505 NGHTTP2_HCAT_HEADERS, NULL, nva, nvlen);
1506 nghttp2_bufs_reset(&bufs);
1507 rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
1510 CU_ASSERT(nghttp2_bufs_len(&bufs) > 0);
1512 nghttp2_frame_headers_free(&frame.headers, mem);
1514 assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
1516 framelen2 = nghttp2_buf_len(buf);
1517 databuf.last = nghttp2_cpymem(databuf.last, buf->pos, nghttp2_buf_len(buf));
1519 /* Receive 1st HEADERS and pause */
1520 user_data.begin_headers_cb_called = 0;
1521 user_data.header_cb_called = 0;
1523 nghttp2_session_mem_recv(session, databuf.pos, nghttp2_buf_len(&databuf));
1528 recv_frame = user_data.frame;
1529 CU_ASSERT(NGHTTP2_HEADERS == recv_frame->hd.type);
1530 CU_ASSERT(framelen1 - NGHTTP2_FRAME_HDLEN == recv_frame->hd.length);
1532 CU_ASSERT(1 == user_data.begin_headers_cb_called);
1533 CU_ASSERT(1 == user_data.header_cb_called);
1535 CU_ASSERT(nghttp2_nv_equal(&nv1[0], &user_data.nv));
1537 /* get 2nd header field */
1538 user_data.begin_headers_cb_called = 0;
1539 user_data.header_cb_called = 0;
1541 nghttp2_session_mem_recv(session, databuf.pos, nghttp2_buf_len(&databuf));
1546 CU_ASSERT(0 == user_data.begin_headers_cb_called);
1547 CU_ASSERT(1 == user_data.header_cb_called);
1549 CU_ASSERT(nghttp2_nv_equal(&nv1[1], &user_data.nv));
1551 /* will call end_headers_callback and receive 2nd HEADERS and pause */
1552 user_data.begin_headers_cb_called = 0;
1553 user_data.header_cb_called = 0;
1555 nghttp2_session_mem_recv(session, databuf.pos, nghttp2_buf_len(&databuf));
1560 recv_frame = user_data.frame;
1561 CU_ASSERT(NGHTTP2_HEADERS == recv_frame->hd.type);
1562 CU_ASSERT(framelen2 - NGHTTP2_FRAME_HDLEN == recv_frame->hd.length);
1564 CU_ASSERT(1 == user_data.begin_headers_cb_called);
1565 CU_ASSERT(1 == user_data.header_cb_called);
1567 CU_ASSERT(nghttp2_nv_equal(&nv2[0], &user_data.nv));
1569 /* get 2nd header field */
1570 user_data.begin_headers_cb_called = 0;
1571 user_data.header_cb_called = 0;
1573 nghttp2_session_mem_recv(session, databuf.pos, nghttp2_buf_len(&databuf));
1578 CU_ASSERT(0 == user_data.begin_headers_cb_called);
1579 CU_ASSERT(1 == user_data.header_cb_called);
1581 CU_ASSERT(nghttp2_nv_equal(&nv2[1], &user_data.nv));
1583 /* No input data, frame_recv_callback is called */
1584 user_data.begin_headers_cb_called = 0;
1585 user_data.header_cb_called = 0;
1586 user_data.frame_recv_cb_called = 0;
1588 nghttp2_session_mem_recv(session, databuf.pos, nghttp2_buf_len(&databuf));
1593 CU_ASSERT(0 == user_data.begin_headers_cb_called);
1594 CU_ASSERT(0 == user_data.header_cb_called);
1595 CU_ASSERT(1 == user_data.frame_recv_cb_called);
1598 nghttp2_frame_hd_init(&data_hd, 16, NGHTTP2_DATA, NGHTTP2_FLAG_NONE, 1);
1600 nghttp2_buf_reset(&databuf);
1601 nghttp2_frame_pack_frame_hd(databuf.pos, &data_hd);
1603 /* Intentionally specify larger buffer size to see pause is kicked
1605 databuf.last = databuf.end;
1607 user_data.frame_recv_cb_called = 0;
1609 nghttp2_session_mem_recv(session, databuf.pos, nghttp2_buf_len(&databuf));
1611 CU_ASSERT(16 + NGHTTP2_FRAME_HDLEN == rv);
1612 CU_ASSERT(0 == user_data.frame_recv_cb_called);
1614 /* Next nghttp2_session_mem_recv invokes on_frame_recv_callback and
1615 pause again in on_data_chunk_recv_callback since we pass same
1617 user_data.frame_recv_cb_called = 0;
1619 nghttp2_session_mem_recv(session, databuf.pos, nghttp2_buf_len(&databuf));
1620 CU_ASSERT(16 + NGHTTP2_FRAME_HDLEN == rv);
1621 CU_ASSERT(1 == user_data.frame_recv_cb_called);
1623 /* And finally call on_frame_recv_callback with 0 size input */
1624 user_data.frame_recv_cb_called = 0;
1625 rv = nghttp2_session_mem_recv(session, NULL, 0);
1627 CU_ASSERT(1 == user_data.frame_recv_cb_called);
1629 nghttp2_bufs_free(&bufs);
1630 nghttp2_hd_deflate_free(&deflater);
1631 nghttp2_session_del(session);
1634 void test_nghttp2_session_add_frame(void) {
1635 nghttp2_session *session;
1636 nghttp2_session_callbacks callbacks;
1638 my_user_data user_data;
1639 nghttp2_outbound_item *item;
1640 nghttp2_frame *frame;
1645 mem = nghttp2_mem_default();
1646 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
1647 callbacks.send_callback = accumulator_send_callback;
1650 user_data.acc = &acc;
1652 CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, &user_data));
1654 item = mem->malloc(sizeof(nghttp2_outbound_item), NULL);
1656 nghttp2_outbound_item_init(item);
1658 frame = &item->frame;
1660 nvlen = ARRLEN(reqnv);
1661 nghttp2_nv_array_copy(&nva, reqnv, nvlen, mem);
1663 nghttp2_frame_headers_init(
1664 &frame->headers, NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PRIORITY,
1665 session->next_stream_id, NGHTTP2_HCAT_REQUEST, NULL, nva, nvlen);
1667 session->next_stream_id += 2;
1669 CU_ASSERT(0 == nghttp2_session_add_item(session, item));
1670 CU_ASSERT(NULL != nghttp2_outbound_queue_top(&session->ob_syn));
1671 CU_ASSERT(0 == nghttp2_session_send(session));
1672 CU_ASSERT(NGHTTP2_HEADERS == acc.buf[3]);
1673 CU_ASSERT((NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PRIORITY) == acc.buf[4]);
1674 /* check stream id */
1675 CU_ASSERT(1 == nghttp2_get_uint32(&acc.buf[5]));
1677 nghttp2_session_del(session);
1680 void test_nghttp2_session_on_request_headers_received(void) {
1681 nghttp2_session *session;
1682 nghttp2_session_callbacks callbacks;
1683 my_user_data user_data;
1684 nghttp2_frame frame;
1685 nghttp2_stream *stream;
1686 int32_t stream_id = 1;
1687 nghttp2_nv malformed_nva[] = {MAKE_NV(":path", "\x01")};
1690 nghttp2_priority_spec pri_spec;
1693 mem = nghttp2_mem_default();
1694 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
1695 callbacks.on_begin_headers_callback = on_begin_headers_callback;
1696 callbacks.on_invalid_frame_recv_callback = on_invalid_frame_recv_callback;
1698 nghttp2_session_server_new(&session, &callbacks, &user_data);
1700 nghttp2_priority_spec_init(&pri_spec, 0, 255, 0);
1702 nghttp2_frame_headers_init(
1703 &frame.headers, NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PRIORITY,
1704 stream_id, NGHTTP2_HCAT_REQUEST, &pri_spec, NULL, 0);
1706 user_data.begin_headers_cb_called = 0;
1707 user_data.invalid_frame_recv_cb_called = 0;
1709 CU_ASSERT(0 == nghttp2_session_on_request_headers_received(session, &frame));
1710 CU_ASSERT(1 == user_data.begin_headers_cb_called);
1711 stream = nghttp2_session_get_stream(session, stream_id);
1712 CU_ASSERT(NGHTTP2_STREAM_OPENING == stream->state);
1713 CU_ASSERT(255 == stream->weight);
1715 nghttp2_frame_headers_free(&frame.headers, mem);
1717 /* More than un-ACKed max concurrent streams leads REFUSED_STREAM */
1718 session->pending_local_max_concurrent_stream = 1;
1719 nghttp2_frame_headers_init(&frame.headers,
1720 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PRIORITY,
1721 3, NGHTTP2_HCAT_HEADERS, NULL, NULL, 0);
1722 user_data.invalid_frame_recv_cb_called = 0;
1723 CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
1724 nghttp2_session_on_request_headers_received(session, &frame));
1725 CU_ASSERT(1 == user_data.invalid_frame_recv_cb_called);
1726 CU_ASSERT(0 == (session->goaway_flags & NGHTTP2_GOAWAY_TERM_ON_SEND));
1728 nghttp2_frame_headers_free(&frame.headers, mem);
1729 session->local_settings.max_concurrent_streams =
1730 NGHTTP2_INITIAL_MAX_CONCURRENT_STREAMS;
1732 /* Stream ID less than or equal to the previouly received request
1733 HEADERS is just ignored due to race condition */
1734 nghttp2_frame_headers_init(&frame.headers,
1735 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PRIORITY,
1736 3, NGHTTP2_HCAT_HEADERS, NULL, NULL, 0);
1737 user_data.invalid_frame_recv_cb_called = 0;
1738 CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
1739 nghttp2_session_on_request_headers_received(session, &frame));
1740 CU_ASSERT(0 == user_data.invalid_frame_recv_cb_called);
1741 CU_ASSERT(0 == (session->goaway_flags & NGHTTP2_GOAWAY_TERM_ON_SEND));
1743 nghttp2_frame_headers_free(&frame.headers, mem);
1745 /* Stream ID is our side and it is idle stream ID, then treat it as
1747 nghttp2_frame_headers_init(&frame.headers,
1748 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PRIORITY,
1749 2, NGHTTP2_HCAT_HEADERS, NULL, NULL, 0);
1750 user_data.invalid_frame_recv_cb_called = 0;
1751 CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
1752 nghttp2_session_on_request_headers_received(session, &frame));
1753 CU_ASSERT(1 == user_data.invalid_frame_recv_cb_called);
1754 CU_ASSERT(session->goaway_flags & NGHTTP2_GOAWAY_TERM_ON_SEND);
1756 nghttp2_frame_headers_free(&frame.headers, mem);
1758 nghttp2_session_del(session);
1760 /* Check malformed headers. The library accept it. */
1761 nghttp2_session_server_new(&session, &callbacks, &user_data);
1763 nvlen = ARRLEN(malformed_nva);
1764 nghttp2_nv_array_copy(&nva, malformed_nva, nvlen, mem);
1765 nghttp2_frame_headers_init(&frame.headers,
1766 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PRIORITY,
1767 1, NGHTTP2_HCAT_HEADERS, NULL, nva, nvlen);
1768 user_data.begin_headers_cb_called = 0;
1769 user_data.invalid_frame_recv_cb_called = 0;
1770 CU_ASSERT(0 == nghttp2_session_on_request_headers_received(session, &frame));
1771 CU_ASSERT(1 == user_data.begin_headers_cb_called);
1772 CU_ASSERT(0 == user_data.invalid_frame_recv_cb_called);
1774 nghttp2_frame_headers_free(&frame.headers, mem);
1776 nghttp2_session_del(session);
1778 /* Check client side */
1779 nghttp2_session_client_new(&session, &callbacks, &user_data);
1781 /* Receiving peer's idle stream ID is subject to connection error */
1782 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 2,
1783 NGHTTP2_HCAT_REQUEST, NULL, NULL, 0);
1785 user_data.invalid_frame_recv_cb_called = 0;
1786 CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
1787 nghttp2_session_on_request_headers_received(session, &frame));
1788 CU_ASSERT(1 == user_data.invalid_frame_recv_cb_called);
1789 CU_ASSERT(session->goaway_flags & NGHTTP2_GOAWAY_TERM_ON_SEND);
1791 nghttp2_frame_headers_free(&frame.headers, mem);
1793 nghttp2_session_del(session);
1795 nghttp2_session_client_new(&session, &callbacks, &user_data);
1797 /* Receiving our's idle stream ID is subject to connection error */
1798 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 1,
1799 NGHTTP2_HCAT_REQUEST, NULL, NULL, 0);
1801 user_data.invalid_frame_recv_cb_called = 0;
1802 CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
1803 nghttp2_session_on_request_headers_received(session, &frame));
1804 CU_ASSERT(1 == user_data.invalid_frame_recv_cb_called);
1805 CU_ASSERT(session->goaway_flags & NGHTTP2_GOAWAY_TERM_ON_SEND);
1807 nghttp2_frame_headers_free(&frame.headers, mem);
1809 nghttp2_session_del(session);
1811 nghttp2_session_client_new(&session, &callbacks, &user_data);
1813 session->next_stream_id = 5;
1815 /* Stream ID which is not idle and not in stream map is just
1817 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 3,
1818 NGHTTP2_HCAT_REQUEST, NULL, NULL, 0);
1820 user_data.invalid_frame_recv_cb_called = 0;
1821 CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
1822 nghttp2_session_on_request_headers_received(session, &frame));
1823 CU_ASSERT(0 == user_data.invalid_frame_recv_cb_called);
1824 CU_ASSERT(0 == (session->goaway_flags & NGHTTP2_GOAWAY_TERM_ON_SEND));
1826 nghttp2_frame_headers_free(&frame.headers, mem);
1828 nghttp2_session_del(session);
1830 nghttp2_session_server_new(&session, &callbacks, &user_data);
1832 /* Stream ID which is equal to local_last_stream_id is ok. */
1833 session->local_last_stream_id = 3;
1835 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 3,
1836 NGHTTP2_HCAT_REQUEST, NULL, NULL, 0);
1838 CU_ASSERT(0 == nghttp2_session_on_request_headers_received(session, &frame));
1840 nghttp2_frame_headers_free(&frame.headers, mem);
1842 /* If GOAWAY has been sent, new stream is ignored */
1843 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 5,
1844 NGHTTP2_HCAT_REQUEST, NULL, NULL, 0);
1846 session->goaway_flags |= NGHTTP2_GOAWAY_SENT;
1847 user_data.invalid_frame_recv_cb_called = 0;
1848 CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
1849 nghttp2_session_on_request_headers_received(session, &frame));
1850 CU_ASSERT(0 == user_data.invalid_frame_recv_cb_called);
1851 CU_ASSERT(0 == (session->goaway_flags & NGHTTP2_GOAWAY_TERM_ON_SEND));
1853 nghttp2_frame_headers_free(&frame.headers, mem);
1855 nghttp2_session_del(session);
1858 void test_nghttp2_session_on_response_headers_received(void) {
1859 nghttp2_session *session;
1860 nghttp2_session_callbacks callbacks;
1861 my_user_data user_data;
1862 nghttp2_frame frame;
1863 nghttp2_stream *stream;
1866 mem = nghttp2_mem_default();
1867 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
1868 callbacks.on_begin_headers_callback = on_begin_headers_callback;
1869 callbacks.on_invalid_frame_recv_callback = on_invalid_frame_recv_callback;
1871 nghttp2_session_client_new(&session, &callbacks, &user_data);
1872 stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
1874 NGHTTP2_STREAM_OPENING, NULL);
1875 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 1,
1876 NGHTTP2_HCAT_HEADERS, NULL, NULL, 0);
1878 user_data.begin_headers_cb_called = 0;
1879 user_data.invalid_frame_recv_cb_called = 0;
1881 CU_ASSERT(0 == nghttp2_session_on_response_headers_received(session, &frame,
1883 CU_ASSERT(1 == user_data.begin_headers_cb_called);
1884 CU_ASSERT(NGHTTP2_STREAM_OPENED == stream->state);
1886 nghttp2_frame_headers_free(&frame.headers, mem);
1887 nghttp2_session_del(session);
1890 void test_nghttp2_session_on_headers_received(void) {
1891 nghttp2_session *session;
1892 nghttp2_session_callbacks callbacks;
1893 my_user_data user_data;
1894 nghttp2_frame frame;
1895 nghttp2_stream *stream;
1898 mem = nghttp2_mem_default();
1899 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
1900 callbacks.on_begin_headers_callback = on_begin_headers_callback;
1901 callbacks.on_invalid_frame_recv_callback = on_invalid_frame_recv_callback;
1903 nghttp2_session_client_new(&session, &callbacks, &user_data);
1904 stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
1905 &pri_spec_default, NGHTTP2_STREAM_OPENED,
1907 nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_WR);
1908 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 1,
1909 NGHTTP2_HCAT_HEADERS, NULL, NULL, 0);
1911 user_data.begin_headers_cb_called = 0;
1912 user_data.invalid_frame_recv_cb_called = 0;
1914 CU_ASSERT(0 == nghttp2_session_on_headers_received(session, &frame, stream));
1915 CU_ASSERT(1 == user_data.begin_headers_cb_called);
1916 CU_ASSERT(NGHTTP2_STREAM_OPENED == stream->state);
1919 frame.hd.flags |= NGHTTP2_FLAG_END_STREAM;
1921 CU_ASSERT(0 == nghttp2_session_on_headers_received(session, &frame, stream));
1922 CU_ASSERT(2 == user_data.begin_headers_cb_called);
1924 /* Check to see when NGHTTP2_STREAM_CLOSING, incoming HEADERS is
1926 stream = nghttp2_session_open_stream(session, 3, NGHTTP2_STREAM_FLAG_NONE,
1928 NGHTTP2_STREAM_CLOSING, NULL);
1929 frame.hd.stream_id = 3;
1930 frame.hd.flags = NGHTTP2_FLAG_END_HEADERS;
1931 CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
1932 nghttp2_session_on_headers_received(session, &frame, stream));
1933 /* See no counters are updated */
1934 CU_ASSERT(2 == user_data.begin_headers_cb_called);
1935 CU_ASSERT(0 == user_data.invalid_frame_recv_cb_called);
1937 /* Server initiated stream */
1938 stream = nghttp2_session_open_stream(session, 2, NGHTTP2_STREAM_FLAG_NONE,
1940 NGHTTP2_STREAM_OPENING, NULL);
1942 /* half closed (remote) */
1943 frame.hd.flags = NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM;
1944 frame.hd.stream_id = 2;
1946 CU_ASSERT(0 == nghttp2_session_on_headers_received(session, &frame, stream));
1947 CU_ASSERT(3 == user_data.begin_headers_cb_called);
1948 CU_ASSERT(NGHTTP2_STREAM_OPENING == stream->state);
1950 nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_RD);
1952 /* Further reception of HEADERS is subject to stream error */
1953 CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
1954 nghttp2_session_on_headers_received(session, &frame, stream));
1955 CU_ASSERT(1 == user_data.invalid_frame_recv_cb_called);
1957 nghttp2_frame_headers_free(&frame.headers, mem);
1959 nghttp2_session_del(session);
1962 void test_nghttp2_session_on_push_response_headers_received(void) {
1963 nghttp2_session *session;
1964 nghttp2_session_callbacks callbacks;
1965 my_user_data user_data;
1966 nghttp2_frame frame;
1967 nghttp2_stream *stream;
1968 nghttp2_outbound_item *item;
1971 mem = nghttp2_mem_default();
1972 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
1973 callbacks.send_callback = null_send_callback;
1974 callbacks.on_begin_headers_callback = on_begin_headers_callback;
1975 callbacks.on_invalid_frame_recv_callback = on_invalid_frame_recv_callback;
1977 nghttp2_session_client_new(&session, &callbacks, &user_data);
1978 stream = nghttp2_session_open_stream(session, 2, NGHTTP2_STREAM_FLAG_NONE,
1980 NGHTTP2_STREAM_RESERVED, NULL);
1981 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 2,
1982 NGHTTP2_HCAT_HEADERS, NULL, NULL, 0);
1983 /* nghttp2_session_on_push_response_headers_received assumes
1984 stream's state is NGHTTP2_STREAM_RESERVED and session->server is
1987 user_data.begin_headers_cb_called = 0;
1988 user_data.invalid_frame_recv_cb_called = 0;
1990 CU_ASSERT(0 == nghttp2_session_on_push_response_headers_received(
1991 session, &frame, stream));
1992 CU_ASSERT(1 == user_data.begin_headers_cb_called);
1993 CU_ASSERT(NGHTTP2_STREAM_OPENED == stream->state);
1994 CU_ASSERT(1 == session->num_incoming_streams);
1995 CU_ASSERT(0 == (stream->flags & NGHTTP2_STREAM_FLAG_PUSH));
1997 /* If un-ACKed max concurrent streams limit is exceeded,
1999 session->pending_local_max_concurrent_stream = 1;
2000 stream = nghttp2_session_open_stream(session, 4, NGHTTP2_STREAM_FLAG_NONE,
2002 NGHTTP2_STREAM_RESERVED, NULL);
2003 frame.hd.stream_id = 4;
2004 CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
2005 nghttp2_session_on_push_response_headers_received(session, &frame,
2007 item = nghttp2_session_get_next_ob_item(session);
2008 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
2009 CU_ASSERT(NGHTTP2_REFUSED_STREAM == item->frame.rst_stream.error_code);
2010 CU_ASSERT(1 == session->num_incoming_streams);
2012 CU_ASSERT(0 == nghttp2_session_send(session));
2013 CU_ASSERT(1 == session->num_incoming_streams);
2015 /* If ACKed max concurrent streams limit is exceeded, GOAWAY is
2017 session->local_settings.max_concurrent_streams = 1;
2019 stream = nghttp2_session_open_stream(session, 6, NGHTTP2_STREAM_FLAG_NONE,
2021 NGHTTP2_STREAM_RESERVED, NULL);
2022 frame.hd.stream_id = 6;
2024 CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
2025 nghttp2_session_on_push_response_headers_received(session, &frame,
2027 item = nghttp2_session_get_next_ob_item(session);
2028 CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
2029 CU_ASSERT(NGHTTP2_PROTOCOL_ERROR == item->frame.goaway.error_code);
2030 CU_ASSERT(1 == session->num_incoming_streams);
2032 nghttp2_frame_headers_free(&frame.headers, mem);
2033 nghttp2_session_del(session);
2036 void test_nghttp2_session_on_priority_received(void) {
2037 nghttp2_session *session;
2038 nghttp2_session_callbacks callbacks;
2039 my_user_data user_data;
2040 nghttp2_frame frame;
2041 nghttp2_stream *stream, *dep_stream;
2042 nghttp2_priority_spec pri_spec;
2043 nghttp2_outbound_item *item;
2045 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
2046 callbacks.on_frame_recv_callback = on_frame_recv_callback;
2047 callbacks.on_invalid_frame_recv_callback = on_invalid_frame_recv_callback;
2049 nghttp2_session_server_new(&session, &callbacks, &user_data);
2050 stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
2052 NGHTTP2_STREAM_OPENING, NULL);
2054 nghttp2_priority_spec_init(&pri_spec, 0, 2, 0);
2056 nghttp2_frame_priority_init(&frame.priority, 1, &pri_spec);
2058 /* depend on stream 0 */
2059 CU_ASSERT(0 == nghttp2_session_on_priority_received(session, &frame));
2061 CU_ASSERT(2 == stream->weight);
2063 stream = nghttp2_session_open_stream(session, 2, NGHTTP2_STREAM_FLAG_NONE,
2065 NGHTTP2_STREAM_OPENING, NULL);
2067 dep_stream = nghttp2_session_open_stream(session, 3, NGHTTP2_STREAM_FLAG_NONE,
2069 NGHTTP2_STREAM_OPENING, NULL);
2071 frame.hd.stream_id = 2;
2073 /* using dependency stream */
2074 nghttp2_priority_spec_init(&frame.priority.pri_spec, 3, 1, 0);
2076 CU_ASSERT(0 == nghttp2_session_on_priority_received(session, &frame));
2077 CU_ASSERT(dep_stream == stream->dep_prev);
2079 /* PRIORITY against idle stream */
2081 frame.hd.stream_id = 100;
2083 CU_ASSERT(0 == nghttp2_session_on_priority_received(session, &frame));
2085 stream = nghttp2_session_get_stream_raw(session, frame.hd.stream_id);
2087 CU_ASSERT(NGHTTP2_STREAM_IDLE == stream->state);
2088 CU_ASSERT(dep_stream == stream->dep_prev);
2090 nghttp2_frame_priority_free(&frame.priority);
2091 nghttp2_session_del(session);
2093 /* Check dep_stream_id == stream_id case */
2094 nghttp2_session_server_new(&session, &callbacks, &user_data);
2095 nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
2096 &pri_spec_default, NGHTTP2_STREAM_OPENED, NULL);
2098 nghttp2_priority_spec_init(&pri_spec, 1, 0, 0);
2100 nghttp2_frame_priority_init(&frame.priority, 1, &pri_spec);
2102 CU_ASSERT(0 == nghttp2_session_on_priority_received(session, &frame));
2104 item = nghttp2_session_get_next_ob_item(session);
2106 CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
2108 nghttp2_frame_priority_free(&frame.priority);
2109 nghttp2_session_del(session);
2112 void test_nghttp2_session_on_rst_stream_received(void) {
2113 nghttp2_session *session;
2114 nghttp2_session_callbacks callbacks;
2115 my_user_data user_data;
2116 nghttp2_frame frame;
2117 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
2118 nghttp2_session_server_new(&session, &callbacks, &user_data);
2119 nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
2120 &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL);
2122 nghttp2_frame_rst_stream_init(&frame.rst_stream, 1, NGHTTP2_PROTOCOL_ERROR);
2124 CU_ASSERT(0 == nghttp2_session_on_rst_stream_received(session, &frame));
2125 CU_ASSERT(NULL == nghttp2_session_get_stream(session, 1));
2127 nghttp2_frame_rst_stream_free(&frame.rst_stream);
2128 nghttp2_session_del(session);
2131 void test_nghttp2_session_on_settings_received(void) {
2132 nghttp2_session *session;
2133 nghttp2_session_callbacks callbacks;
2134 my_user_data user_data;
2135 nghttp2_stream *stream1, *stream2;
2136 nghttp2_frame frame;
2137 const size_t niv = 5;
2138 nghttp2_settings_entry iv[255];
2139 nghttp2_outbound_item *item;
2140 nghttp2_nv nv = MAKE_NV(":authority", "example.org");
2143 mem = nghttp2_mem_default();
2145 iv[0].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS;
2148 iv[1].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS;
2149 iv[1].value = 1000000009;
2151 iv[2].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
2152 iv[2].value = 64 * 1024;
2154 iv[3].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
2157 iv[4].settings_id = NGHTTP2_SETTINGS_ENABLE_PUSH;
2160 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
2161 callbacks.send_callback = null_send_callback;
2163 nghttp2_session_client_new(&session, &callbacks, &user_data);
2164 session->remote_settings.initial_window_size = 16 * 1024;
2166 stream1 = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
2168 NGHTTP2_STREAM_OPENING, NULL);
2169 stream2 = nghttp2_session_open_stream(session, 2, NGHTTP2_STREAM_FLAG_NONE,
2171 NGHTTP2_STREAM_OPENING, NULL);
2172 /* Set window size for each streams and will see how settings
2173 updates these values */
2174 stream1->remote_window_size = 16 * 1024;
2175 stream2->remote_window_size = -48 * 1024;
2177 nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE,
2178 dup_iv(iv, niv), niv);
2180 CU_ASSERT(0 == nghttp2_session_on_settings_received(session, &frame, 0));
2181 CU_ASSERT(1000000009 == session->remote_settings.max_concurrent_streams);
2182 CU_ASSERT(64 * 1024 == session->remote_settings.initial_window_size);
2183 CU_ASSERT(1024 == session->remote_settings.header_table_size);
2184 CU_ASSERT(0 == session->remote_settings.enable_push);
2186 CU_ASSERT(64 * 1024 == stream1->remote_window_size);
2187 CU_ASSERT(0 == stream2->remote_window_size);
2189 frame.settings.iv[2].value = 16 * 1024;
2191 CU_ASSERT(0 == nghttp2_session_on_settings_received(session, &frame, 0));
2193 CU_ASSERT(16 * 1024 == stream1->remote_window_size);
2194 CU_ASSERT(-48 * 1024 == stream2->remote_window_size);
2196 CU_ASSERT(16 * 1024 == nghttp2_session_get_stream_remote_window_size(
2197 session, stream1->stream_id));
2198 CU_ASSERT(0 == nghttp2_session_get_stream_remote_window_size(
2199 session, stream2->stream_id));
2201 nghttp2_frame_settings_free(&frame.settings, mem);
2203 nghttp2_session_del(session);
2205 /* Check ACK with niv > 0 */
2206 nghttp2_session_server_new(&session, &callbacks, NULL);
2207 nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_ACK, dup_iv(iv, 1),
2209 /* Specify inflight_iv deliberately */
2210 session->inflight_iv = frame.settings.iv;
2211 session->inflight_niv = frame.settings.niv;
2213 CU_ASSERT(0 == nghttp2_session_on_settings_received(session, &frame, 0));
2214 item = nghttp2_session_get_next_ob_item(session);
2215 CU_ASSERT(item != NULL);
2216 CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
2218 session->inflight_iv = NULL;
2219 session->inflight_niv = -1;
2221 nghttp2_frame_settings_free(&frame.settings, mem);
2222 nghttp2_session_del(session);
2224 /* Check ACK against no inflight SETTINGS */
2225 nghttp2_session_server_new(&session, &callbacks, NULL);
2226 nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_ACK, NULL, 0);
2228 CU_ASSERT(0 == nghttp2_session_on_settings_received(session, &frame, 0));
2229 item = nghttp2_session_get_next_ob_item(session);
2230 CU_ASSERT(item != NULL);
2231 CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
2233 nghttp2_frame_settings_free(&frame.settings, mem);
2234 nghttp2_session_del(session);
2236 /* Check that 2 SETTINGS_HEADER_TABLE_SIZE 0 and 4096 are included
2237 and header table size is once cleared to 0. */
2238 nghttp2_session_client_new(&session, &callbacks, NULL);
2240 nghttp2_submit_request(session, NULL, &nv, 1, NULL, NULL);
2242 nghttp2_session_send(session);
2244 CU_ASSERT(session->hd_deflater.ctx.hd_table.len > 0);
2246 iv[0].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
2249 iv[1].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
2252 nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE, dup_iv(iv, 2),
2255 CU_ASSERT(0 == nghttp2_session_on_settings_received(session, &frame, 0));
2257 CU_ASSERT(0 == session->hd_deflater.ctx.hd_table.len);
2258 CU_ASSERT(2048 == session->hd_deflater.ctx.hd_table_bufsize_max);
2259 CU_ASSERT(2048 == session->remote_settings.header_table_size);
2261 nghttp2_frame_settings_free(&frame.settings, mem);
2262 nghttp2_session_del(session);
2264 /* Check too large SETTINGS_MAX_FRAME_SIZE */
2265 nghttp2_session_server_new(&session, &callbacks, NULL);
2267 iv[0].settings_id = NGHTTP2_SETTINGS_MAX_FRAME_SIZE;
2268 iv[0].value = NGHTTP2_MAX_FRAME_SIZE_MAX + 1;
2270 nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE, dup_iv(iv, 1),
2273 CU_ASSERT(0 == nghttp2_session_on_settings_received(session, &frame, 0));
2275 item = nghttp2_session_get_next_ob_item(session);
2277 CU_ASSERT(item != NULL);
2278 CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
2280 nghttp2_frame_settings_free(&frame.settings, mem);
2281 nghttp2_session_del(session);
2284 void test_nghttp2_session_on_push_promise_received(void) {
2285 nghttp2_session *session;
2286 nghttp2_session_callbacks callbacks;
2287 my_user_data user_data;
2288 nghttp2_frame frame;
2289 nghttp2_stream *stream, *promised_stream;
2290 nghttp2_outbound_item *item;
2291 nghttp2_nv malformed_nva[] = {MAKE_NV(":path", "\x01")};
2295 nghttp2_settings_entry iv = {NGHTTP2_SETTINGS_ENABLE_PUSH, 0};
2297 mem = nghttp2_mem_default();
2298 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
2299 callbacks.send_callback = null_send_callback;
2300 callbacks.on_begin_headers_callback = on_begin_headers_callback;
2301 callbacks.on_invalid_frame_recv_callback = on_invalid_frame_recv_callback;
2303 nghttp2_session_client_new(&session, &callbacks, &user_data);
2305 stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
2307 NGHTTP2_STREAM_OPENING, NULL);
2308 nghttp2_frame_push_promise_init(&frame.push_promise, NGHTTP2_FLAG_END_HEADERS,
2311 user_data.begin_headers_cb_called = 0;
2312 user_data.invalid_frame_recv_cb_called = 0;
2314 CU_ASSERT(0 == nghttp2_session_on_push_promise_received(session, &frame));
2316 CU_ASSERT(1 == user_data.begin_headers_cb_called);
2317 promised_stream = nghttp2_session_get_stream(session, 2);
2318 CU_ASSERT(NGHTTP2_STREAM_RESERVED == promised_stream->state);
2319 CU_ASSERT(2 == session->last_recv_stream_id);
2321 /* Attempt to PUSH_PROMISE against half close (remote) */
2322 nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_RD);
2323 frame.push_promise.promised_stream_id = 4;
2325 user_data.begin_headers_cb_called = 0;
2326 user_data.invalid_frame_recv_cb_called = 0;
2327 CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
2328 nghttp2_session_on_push_promise_received(session, &frame));
2330 CU_ASSERT(0 == user_data.begin_headers_cb_called);
2331 CU_ASSERT(1 == user_data.invalid_frame_recv_cb_called);
2332 CU_ASSERT(NULL == nghttp2_session_get_stream(session, 4));
2333 item = nghttp2_session_get_next_ob_item(session);
2334 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
2335 CU_ASSERT(4 == item->frame.hd.stream_id);
2336 CU_ASSERT(NGHTTP2_PROTOCOL_ERROR == item->frame.rst_stream.error_code);
2337 CU_ASSERT(0 == nghttp2_session_send(session));
2338 CU_ASSERT(4 == session->last_recv_stream_id);
2340 /* Attempt to PUSH_PROMISE against stream in closing state */
2341 stream->shut_flags = NGHTTP2_SHUT_NONE;
2342 stream->state = NGHTTP2_STREAM_CLOSING;
2343 frame.push_promise.promised_stream_id = 6;
2345 user_data.begin_headers_cb_called = 0;
2346 user_data.invalid_frame_recv_cb_called = 0;
2347 CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
2348 nghttp2_session_on_push_promise_received(session, &frame));
2350 CU_ASSERT(0 == user_data.begin_headers_cb_called);
2351 CU_ASSERT(NULL == nghttp2_session_get_stream(session, 6));
2352 item = nghttp2_session_get_next_ob_item(session);
2353 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
2354 CU_ASSERT(6 == item->frame.hd.stream_id);
2355 CU_ASSERT(NGHTTP2_REFUSED_STREAM == item->frame.rst_stream.error_code);
2356 CU_ASSERT(0 == nghttp2_session_send(session));
2358 /* Attempt to PUSH_PROMISE against non-existent stream */
2359 frame.hd.stream_id = 3;
2360 frame.push_promise.promised_stream_id = 8;
2362 user_data.begin_headers_cb_called = 0;
2363 user_data.invalid_frame_recv_cb_called = 0;
2364 CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
2365 nghttp2_session_on_push_promise_received(session, &frame));
2367 CU_ASSERT(0 == user_data.begin_headers_cb_called);
2368 CU_ASSERT(NULL == nghttp2_session_get_stream(session, 8));
2369 item = nghttp2_session_get_next_ob_item(session);
2370 CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
2371 CU_ASSERT(0 == item->frame.hd.stream_id);
2372 CU_ASSERT(NGHTTP2_PROTOCOL_ERROR == item->frame.goaway.error_code);
2373 CU_ASSERT(0 == nghttp2_session_send(session));
2375 nghttp2_session_del(session);
2377 nghttp2_session_client_new(&session, &callbacks, &user_data);
2379 stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
2381 NGHTTP2_STREAM_OPENING, NULL);
2384 stream->state = NGHTTP2_STREAM_OPENING;
2386 user_data.begin_headers_cb_called = 0;
2387 user_data.invalid_frame_recv_cb_called = 0;
2388 CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
2389 nghttp2_session_on_push_promise_received(session, &frame));
2391 CU_ASSERT(0 == user_data.begin_headers_cb_called);
2392 CU_ASSERT(NULL == nghttp2_session_get_stream(session, 8));
2393 item = nghttp2_session_get_next_ob_item(session);
2394 CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
2395 CU_ASSERT(NGHTTP2_PROTOCOL_ERROR == item->frame.goaway.error_code);
2396 CU_ASSERT(0 == nghttp2_session_send(session));
2398 /* After GOAWAY, PUSH_PROMISE will be discarded */
2399 frame.push_promise.promised_stream_id = 10;
2401 user_data.begin_headers_cb_called = 0;
2402 user_data.invalid_frame_recv_cb_called = 0;
2403 CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
2404 nghttp2_session_on_push_promise_received(session, &frame));
2406 CU_ASSERT(0 == user_data.begin_headers_cb_called);
2407 CU_ASSERT(NULL == nghttp2_session_get_stream(session, 10));
2408 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
2410 nghttp2_frame_push_promise_free(&frame.push_promise, mem);
2411 nghttp2_session_del(session);
2413 nghttp2_session_client_new(&session, &callbacks, &user_data);
2415 nghttp2_session_open_stream(session, 2, NGHTTP2_STREAM_FLAG_NONE,
2416 &pri_spec_default, NGHTTP2_STREAM_RESERVED, NULL);
2417 /* Attempt to PUSH_PROMISE against reserved (remote) stream */
2418 nghttp2_frame_push_promise_init(&frame.push_promise, NGHTTP2_FLAG_END_HEADERS,
2421 user_data.begin_headers_cb_called = 0;
2422 user_data.invalid_frame_recv_cb_called = 0;
2423 CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
2424 nghttp2_session_on_push_promise_received(session, &frame));
2426 CU_ASSERT(0 == user_data.begin_headers_cb_called);
2427 CU_ASSERT(1 == user_data.invalid_frame_recv_cb_called);
2429 nghttp2_frame_push_promise_free(&frame.push_promise, mem);
2430 nghttp2_session_del(session);
2433 nghttp2_session_client_new(&session, &callbacks, &user_data);
2435 nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
2436 &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL);
2438 session->local_settings.enable_push = 0;
2440 nghttp2_frame_push_promise_init(&frame.push_promise, NGHTTP2_FLAG_END_HEADERS,
2443 user_data.begin_headers_cb_called = 0;
2444 user_data.invalid_frame_recv_cb_called = 0;
2445 CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
2446 nghttp2_session_on_push_promise_received(session, &frame));
2448 CU_ASSERT(0 == user_data.begin_headers_cb_called);
2449 CU_ASSERT(1 == user_data.invalid_frame_recv_cb_called);
2451 nghttp2_frame_push_promise_free(&frame.push_promise, mem);
2452 nghttp2_session_del(session);
2454 /* Check malformed headers. We accept malformed headers */
2455 nghttp2_session_client_new(&session, &callbacks, &user_data);
2457 nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
2458 &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL);
2459 nvlen = ARRLEN(malformed_nva);
2460 nghttp2_nv_array_copy(&nva, malformed_nva, nvlen, mem);
2461 nghttp2_frame_push_promise_init(&frame.push_promise, NGHTTP2_FLAG_END_HEADERS,
2463 user_data.begin_headers_cb_called = 0;
2464 user_data.invalid_frame_recv_cb_called = 0;
2465 CU_ASSERT(0 == nghttp2_session_on_push_promise_received(session, &frame));
2467 CU_ASSERT(1 == user_data.begin_headers_cb_called);
2468 CU_ASSERT(0 == user_data.invalid_frame_recv_cb_called);
2470 nghttp2_frame_push_promise_free(&frame.push_promise, mem);
2471 nghttp2_session_del(session);
2473 /* If local_settings.enable_push = 0 is pending, but not acked from
2474 peer, incoming PUSH_PROMISE is rejected */
2475 nghttp2_session_client_new(&session, &callbacks, &user_data);
2477 nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
2478 &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL);
2479 /* Submit settings with ENABLE_PUSH = 0 (thus disabling push) */
2480 nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, &iv, 1);
2482 nghttp2_frame_push_promise_init(&frame.push_promise, NGHTTP2_FLAG_END_HEADERS,
2485 CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
2486 nghttp2_session_on_push_promise_received(session, &frame));
2488 nghttp2_frame_push_promise_free(&frame.push_promise, mem);
2489 nghttp2_session_del(session);
2492 void test_nghttp2_session_on_ping_received(void) {
2493 nghttp2_session *session;
2494 nghttp2_session_callbacks callbacks;
2495 my_user_data user_data;
2496 nghttp2_frame frame;
2497 nghttp2_outbound_item *top;
2498 const uint8_t opaque_data[] = "01234567";
2500 user_data.frame_recv_cb_called = 0;
2501 user_data.invalid_frame_recv_cb_called = 0;
2503 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
2504 callbacks.on_frame_recv_callback = on_frame_recv_callback;
2505 callbacks.on_invalid_frame_recv_callback = on_invalid_frame_recv_callback;
2507 nghttp2_session_client_new(&session, &callbacks, &user_data);
2508 nghttp2_frame_ping_init(&frame.ping, NGHTTP2_FLAG_ACK, opaque_data);
2510 CU_ASSERT(0 == nghttp2_session_on_ping_received(session, &frame));
2511 CU_ASSERT(1 == user_data.frame_recv_cb_called);
2513 /* Since this ping frame has ACK flag set, no further action is
2515 CU_ASSERT(NULL == nghttp2_outbound_queue_top(&session->ob_urgent));
2517 /* Clear the flag, and receive it again */
2518 frame.hd.flags = NGHTTP2_FLAG_NONE;
2520 CU_ASSERT(0 == nghttp2_session_on_ping_received(session, &frame));
2521 CU_ASSERT(2 == user_data.frame_recv_cb_called);
2522 top = nghttp2_outbound_queue_top(&session->ob_urgent);
2523 CU_ASSERT(NGHTTP2_PING == top->frame.hd.type);
2524 CU_ASSERT(NGHTTP2_FLAG_ACK == top->frame.hd.flags);
2525 CU_ASSERT(memcmp(opaque_data, top->frame.ping.opaque_data, 8) == 0);
2527 nghttp2_frame_ping_free(&frame.ping);
2528 nghttp2_session_del(session);
2531 void test_nghttp2_session_on_goaway_received(void) {
2532 nghttp2_session *session;
2533 nghttp2_session_callbacks callbacks;
2534 my_user_data user_data;
2535 nghttp2_frame frame;
2539 mem = nghttp2_mem_default();
2540 user_data.frame_recv_cb_called = 0;
2541 user_data.invalid_frame_recv_cb_called = 0;
2543 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
2544 callbacks.on_frame_recv_callback = on_frame_recv_callback;
2545 callbacks.on_invalid_frame_recv_callback = on_invalid_frame_recv_callback;
2546 callbacks.on_stream_close_callback = on_stream_close_callback;
2548 nghttp2_session_client_new(&session, &callbacks, &user_data);
2550 for (i = 1; i <= 7; ++i) {
2551 open_stream(session, i);
2554 nghttp2_frame_goaway_init(&frame.goaway, 3, NGHTTP2_PROTOCOL_ERROR, NULL, 0);
2556 user_data.stream_close_cb_called = 0;
2558 CU_ASSERT(0 == nghttp2_session_on_goaway_received(session, &frame));
2560 CU_ASSERT(1 == user_data.frame_recv_cb_called);
2561 CU_ASSERT(3 == session->remote_last_stream_id);
2562 /* on_stream_close should be callsed for 2 times (stream 5 and 7) */
2563 CU_ASSERT(2 == user_data.stream_close_cb_called);
2565 CU_ASSERT(NULL != nghttp2_session_get_stream(session, 1));
2566 CU_ASSERT(NULL != nghttp2_session_get_stream(session, 2));
2567 CU_ASSERT(NULL != nghttp2_session_get_stream(session, 3));
2568 CU_ASSERT(NULL != nghttp2_session_get_stream(session, 4));
2569 CU_ASSERT(NULL == nghttp2_session_get_stream(session, 5));
2570 CU_ASSERT(NULL != nghttp2_session_get_stream(session, 6));
2571 CU_ASSERT(NULL == nghttp2_session_get_stream(session, 7));
2573 nghttp2_frame_goaway_free(&frame.goaway, mem);
2574 nghttp2_session_del(session);
2577 void test_nghttp2_session_on_window_update_received(void) {
2578 nghttp2_session *session;
2579 nghttp2_session_callbacks callbacks;
2580 my_user_data user_data;
2581 nghttp2_frame frame;
2582 nghttp2_stream *stream;
2583 nghttp2_outbound_item *data_item;
2586 mem = nghttp2_mem_default();
2588 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
2589 callbacks.on_frame_recv_callback = on_frame_recv_callback;
2590 callbacks.on_invalid_frame_recv_callback = on_invalid_frame_recv_callback;
2591 user_data.frame_recv_cb_called = 0;
2592 user_data.invalid_frame_recv_cb_called = 0;
2594 nghttp2_session_client_new(&session, &callbacks, &user_data);
2596 stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
2597 &pri_spec_default, NGHTTP2_STREAM_OPENED,
2600 data_item = create_data_ob_item(mem);
2602 CU_ASSERT(0 == nghttp2_stream_attach_item(stream, data_item, session));
2604 nghttp2_frame_window_update_init(&frame.window_update, NGHTTP2_FLAG_NONE, 1,
2607 CU_ASSERT(0 == nghttp2_session_on_window_update_received(session, &frame));
2608 CU_ASSERT(1 == user_data.frame_recv_cb_called);
2609 CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE + 16 * 1024 ==
2610 stream->remote_window_size);
2613 nghttp2_stream_defer_item(
2614 stream, NGHTTP2_STREAM_FLAG_DEFERRED_FLOW_CONTROL, session));
2616 CU_ASSERT(0 == nghttp2_session_on_window_update_received(session, &frame));
2617 CU_ASSERT(2 == user_data.frame_recv_cb_called);
2618 CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE + 16 * 1024 * 2 ==
2619 stream->remote_window_size);
2620 CU_ASSERT(0 == (stream->flags & NGHTTP2_STREAM_FLAG_DEFERRED_ALL));
2622 nghttp2_frame_window_update_free(&frame.window_update);
2624 /* Receiving WINDOW_UPDATE on reserved (remote) stream is a
2626 nghttp2_session_open_stream(session, 2, NGHTTP2_STREAM_FLAG_NONE,
2627 &pri_spec_default, NGHTTP2_STREAM_RESERVED, NULL);
2629 nghttp2_frame_window_update_init(&frame.window_update, NGHTTP2_FLAG_NONE, 2,
2632 CU_ASSERT(!(session->goaway_flags & NGHTTP2_GOAWAY_TERM_ON_SEND));
2633 CU_ASSERT(0 == nghttp2_session_on_window_update_received(session, &frame));
2634 CU_ASSERT(session->goaway_flags & NGHTTP2_GOAWAY_TERM_ON_SEND);
2636 nghttp2_frame_window_update_free(&frame.window_update);
2638 nghttp2_session_del(session);
2640 /* Receiving WINDOW_UPDATE on reserved (local) stream is allowed */
2641 nghttp2_session_server_new(&session, &callbacks, &user_data);
2643 stream = nghttp2_session_open_stream(session, 2, NGHTTP2_STREAM_FLAG_NONE,
2645 NGHTTP2_STREAM_RESERVED, NULL);
2647 nghttp2_frame_window_update_init(&frame.window_update, NGHTTP2_FLAG_NONE, 2,
2650 CU_ASSERT(0 == nghttp2_session_on_window_update_received(session, &frame));
2651 CU_ASSERT(!(session->goaway_flags & NGHTTP2_GOAWAY_TERM_ON_SEND));
2653 CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE + 4096 == stream->remote_window_size);
2655 nghttp2_frame_window_update_free(&frame.window_update);
2657 nghttp2_session_del(session);
2660 void test_nghttp2_session_on_data_received(void) {
2661 nghttp2_session *session;
2662 nghttp2_session_callbacks callbacks;
2663 my_user_data user_data;
2664 nghttp2_outbound_item *top;
2665 nghttp2_stream *stream;
2666 nghttp2_frame frame;
2668 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
2670 nghttp2_session_client_new(&session, &callbacks, &user_data);
2671 stream = nghttp2_session_open_stream(session, 2, NGHTTP2_STREAM_FLAG_NONE,
2673 NGHTTP2_STREAM_OPENING, NULL);
2675 nghttp2_frame_hd_init(&frame.hd, 4096, NGHTTP2_DATA, NGHTTP2_FLAG_NONE, 2);
2677 CU_ASSERT(0 == nghttp2_session_on_data_received(session, &frame));
2678 CU_ASSERT(0 == stream->shut_flags);
2680 frame.hd.flags = NGHTTP2_FLAG_END_STREAM;
2682 CU_ASSERT(0 == nghttp2_session_on_data_received(session, &frame));
2683 CU_ASSERT(NGHTTP2_SHUT_RD == stream->shut_flags);
2685 /* If NGHTTP2_STREAM_CLOSING state, DATA frame is discarded. */
2686 nghttp2_session_open_stream(session, 4, NGHTTP2_STREAM_FLAG_NONE,
2687 &pri_spec_default, NGHTTP2_STREAM_CLOSING, NULL);
2689 frame.hd.flags = NGHTTP2_FLAG_NONE;
2690 frame.hd.stream_id = 4;
2692 CU_ASSERT(0 == nghttp2_session_on_data_received(session, &frame));
2693 CU_ASSERT(NULL == nghttp2_outbound_queue_top(&session->ob_reg));
2695 /* Check INVALID_STREAM case: DATA frame with stream ID which does
2698 frame.hd.stream_id = 6;
2700 CU_ASSERT(0 == nghttp2_session_on_data_received(session, &frame));
2701 top = nghttp2_outbound_queue_top(&session->ob_reg);
2702 /* DATA against nonexistent stream is just ignored for now */
2703 CU_ASSERT(top == NULL);
2704 /* CU_ASSERT(NGHTTP2_RST_STREAM == top->frame.hd.type); */
2705 /* CU_ASSERT(NGHTTP2_PROTOCOL_ERROR == top->frame.rst_stream.error_code); */
2707 nghttp2_session_del(session);
2710 void test_nghttp2_session_send_headers_start_stream(void) {
2711 nghttp2_session *session;
2712 nghttp2_session_callbacks callbacks;
2713 nghttp2_outbound_item *item;
2714 nghttp2_frame *frame;
2715 nghttp2_stream *stream;
2718 mem = nghttp2_mem_default();
2720 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
2721 callbacks.send_callback = null_send_callback;
2723 nghttp2_session_client_new(&session, &callbacks, NULL);
2725 item = mem->malloc(sizeof(nghttp2_outbound_item), NULL);
2727 nghttp2_outbound_item_init(item);
2729 frame = &item->frame;
2731 nghttp2_frame_headers_init(&frame->headers, NGHTTP2_FLAG_END_HEADERS,
2732 session->next_stream_id, NGHTTP2_HCAT_REQUEST,
2734 session->next_stream_id += 2;
2736 nghttp2_session_add_item(session, item);
2737 CU_ASSERT(0 == nghttp2_session_send(session));
2738 stream = nghttp2_session_get_stream(session, 1);
2739 CU_ASSERT(NGHTTP2_STREAM_OPENING == stream->state);
2741 nghttp2_session_del(session);
2744 void test_nghttp2_session_send_headers_reply(void) {
2745 nghttp2_session *session;
2746 nghttp2_session_callbacks callbacks;
2747 nghttp2_outbound_item *item;
2748 nghttp2_frame *frame;
2749 nghttp2_stream *stream;
2752 mem = nghttp2_mem_default();
2754 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
2755 callbacks.send_callback = null_send_callback;
2757 CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, NULL));
2758 nghttp2_session_open_stream(session, 2, NGHTTP2_STREAM_FLAG_NONE,
2759 &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL);
2761 item = mem->malloc(sizeof(nghttp2_outbound_item), NULL);
2763 nghttp2_outbound_item_init(item);
2765 frame = &item->frame;
2767 nghttp2_frame_headers_init(&frame->headers, NGHTTP2_FLAG_END_HEADERS, 2,
2768 NGHTTP2_HCAT_HEADERS, NULL, NULL, 0);
2769 nghttp2_session_add_item(session, item);
2770 CU_ASSERT(0 == nghttp2_session_send(session));
2771 stream = nghttp2_session_get_stream(session, 2);
2772 CU_ASSERT(NGHTTP2_STREAM_OPENED == stream->state);
2774 nghttp2_session_del(session);
2777 void test_nghttp2_session_send_headers_frame_size_error(void) {
2778 nghttp2_session *session;
2779 nghttp2_session_callbacks callbacks;
2780 nghttp2_outbound_item *item;
2781 nghttp2_frame *frame;
2784 size_t vallen = NGHTTP2_HD_MAX_NV;
2786 size_t nnv = ARRLEN(nv);
2791 mem = nghttp2_mem_default();
2793 for (i = 0; i < nnv; ++i) {
2794 nv[i].name = (uint8_t *)"header";
2795 nv[i].namelen = strlen((const char *)nv[i].name);
2796 nv[i].value = mem->malloc(vallen + 1, NULL);
2797 memset(nv[i].value, '0' + (int)i, vallen);
2798 nv[i].value[vallen] = '\0';
2799 nv[i].valuelen = vallen;
2800 nv[i].flags = NGHTTP2_NV_FLAG_NONE;
2803 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
2804 callbacks.send_callback = null_send_callback;
2805 callbacks.on_frame_not_send_callback = on_frame_not_send_callback;
2807 nghttp2_session_client_new(&session, &callbacks, &ud);
2809 nghttp2_nv_array_copy(&nva, nv, nvlen, mem);
2811 item = mem->malloc(sizeof(nghttp2_outbound_item), NULL);
2813 nghttp2_outbound_item_init(item);
2815 frame = &item->frame;
2817 nghttp2_frame_headers_init(&frame->headers, NGHTTP2_FLAG_END_HEADERS,
2818 session->next_stream_id, NGHTTP2_HCAT_REQUEST,
2821 session->next_stream_id += 2;
2823 nghttp2_session_add_item(session, item);
2825 ud.frame_not_send_cb_called = 0;
2827 CU_ASSERT(0 == nghttp2_session_send(session));
2829 CU_ASSERT(1 == ud.frame_not_send_cb_called);
2830 CU_ASSERT(NGHTTP2_HEADERS == ud.not_sent_frame_type);
2831 CU_ASSERT(NGHTTP2_ERR_FRAME_SIZE_ERROR == ud.not_sent_error);
2833 for (i = 0; i < nnv; ++i) {
2834 mem->free(nv[i].value, NULL);
2836 nghttp2_session_del(session);
2839 void test_nghttp2_session_send_headers_push_reply(void) {
2840 nghttp2_session *session;
2841 nghttp2_session_callbacks callbacks;
2842 nghttp2_outbound_item *item;
2843 nghttp2_frame *frame;
2844 nghttp2_stream *stream;
2847 mem = nghttp2_mem_default();
2849 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
2850 callbacks.send_callback = null_send_callback;
2852 CU_ASSERT(0 == nghttp2_session_server_new(&session, &callbacks, NULL));
2853 nghttp2_session_open_stream(session, 2, NGHTTP2_STREAM_FLAG_NONE,
2854 &pri_spec_default, NGHTTP2_STREAM_RESERVED, NULL);
2856 item = mem->malloc(sizeof(nghttp2_outbound_item), NULL);
2858 nghttp2_outbound_item_init(item);
2860 frame = &item->frame;
2862 nghttp2_frame_headers_init(&frame->headers, NGHTTP2_FLAG_END_HEADERS, 2,
2863 NGHTTP2_HCAT_HEADERS, NULL, NULL, 0);
2864 nghttp2_session_add_item(session, item);
2865 CU_ASSERT(0 == session->num_outgoing_streams);
2866 CU_ASSERT(0 == nghttp2_session_send(session));
2867 CU_ASSERT(1 == session->num_outgoing_streams);
2868 stream = nghttp2_session_get_stream(session, 2);
2869 CU_ASSERT(NGHTTP2_STREAM_OPENED == stream->state);
2870 CU_ASSERT(0 == (stream->flags & NGHTTP2_STREAM_FLAG_PUSH));
2871 nghttp2_session_del(session);
2874 void test_nghttp2_session_send_rst_stream(void) {
2875 nghttp2_session *session;
2876 nghttp2_session_callbacks callbacks;
2877 my_user_data user_data;
2878 nghttp2_outbound_item *item;
2879 nghttp2_frame *frame;
2882 mem = nghttp2_mem_default();
2884 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
2885 callbacks.send_callback = null_send_callback;
2886 nghttp2_session_client_new(&session, &callbacks, &user_data);
2887 nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
2888 &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL);
2890 item = mem->malloc(sizeof(nghttp2_outbound_item), NULL);
2892 nghttp2_outbound_item_init(item);
2894 frame = &item->frame;
2896 nghttp2_frame_rst_stream_init(&frame->rst_stream, 1, NGHTTP2_PROTOCOL_ERROR);
2897 nghttp2_session_add_item(session, item);
2898 CU_ASSERT(0 == nghttp2_session_send(session));
2900 CU_ASSERT(NULL == nghttp2_session_get_stream(session, 1));
2902 nghttp2_session_del(session);
2905 void test_nghttp2_session_send_push_promise(void) {
2906 nghttp2_session *session;
2907 nghttp2_session_callbacks callbacks;
2908 nghttp2_outbound_item *item;
2909 nghttp2_frame *frame;
2910 nghttp2_stream *stream;
2911 nghttp2_settings_entry iv;
2915 mem = nghttp2_mem_default();
2916 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
2917 callbacks.send_callback = null_send_callback;
2918 callbacks.on_frame_not_send_callback = on_frame_not_send_callback;
2920 nghttp2_session_server_new(&session, &callbacks, &ud);
2921 nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
2922 &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL);
2924 item = mem->malloc(sizeof(nghttp2_outbound_item), NULL);
2926 nghttp2_outbound_item_init(item);
2928 frame = &item->frame;
2930 nghttp2_frame_push_promise_init(&frame->push_promise,
2931 NGHTTP2_FLAG_END_HEADERS, 1,
2932 session->next_stream_id, NULL, 0);
2934 session->next_stream_id += 2;
2936 nghttp2_session_add_item(session, item);
2938 CU_ASSERT(0 == nghttp2_session_send(session));
2939 stream = nghttp2_session_get_stream(session, 2);
2940 CU_ASSERT(NGHTTP2_STREAM_RESERVED == stream->state);
2942 /* Received ENABLE_PUSH = 0 */
2943 iv.settings_id = NGHTTP2_SETTINGS_ENABLE_PUSH;
2945 frame = mem->malloc(sizeof(nghttp2_frame), NULL);
2946 nghttp2_frame_settings_init(&frame->settings, NGHTTP2_FLAG_NONE,
2948 nghttp2_session_on_settings_received(session, frame, 1);
2949 nghttp2_frame_settings_free(&frame->settings, mem);
2950 mem->free(frame, NULL);
2952 item = mem->malloc(sizeof(nghttp2_outbound_item), NULL);
2954 nghttp2_outbound_item_init(item);
2956 frame = &item->frame;
2958 nghttp2_frame_push_promise_init(&frame->push_promise,
2959 NGHTTP2_FLAG_END_HEADERS, 1, -1, NULL, 0);
2960 nghttp2_session_add_item(session, item);
2962 ud.frame_not_send_cb_called = 0;
2963 CU_ASSERT(0 == nghttp2_session_send(session));
2965 CU_ASSERT(1 == ud.frame_not_send_cb_called);
2966 CU_ASSERT(NGHTTP2_PUSH_PROMISE == ud.not_sent_frame_type);
2967 CU_ASSERT(NGHTTP2_ERR_PUSH_DISABLED == ud.not_sent_error);
2969 nghttp2_session_del(session);
2971 /* PUSH_PROMISE from client is error */
2972 nghttp2_session_client_new(&session, &callbacks, &ud);
2973 nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
2974 &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL);
2975 item = mem->malloc(sizeof(nghttp2_outbound_item), NULL);
2977 nghttp2_outbound_item_init(item);
2979 frame = &item->frame;
2981 nghttp2_frame_push_promise_init(&frame->push_promise,
2982 NGHTTP2_FLAG_END_HEADERS, 1, -1, NULL, 0);
2983 nghttp2_session_add_item(session, item);
2985 CU_ASSERT(0 == nghttp2_session_send(session));
2986 CU_ASSERT(NULL == nghttp2_session_get_stream(session, 3));
2988 nghttp2_session_del(session);
2991 void test_nghttp2_session_is_my_stream_id(void) {
2992 nghttp2_session *session;
2993 nghttp2_session_callbacks callbacks;
2994 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
2995 nghttp2_session_server_new(&session, &callbacks, NULL);
2997 CU_ASSERT(0 == nghttp2_session_is_my_stream_id(session, 0));
2998 CU_ASSERT(0 == nghttp2_session_is_my_stream_id(session, 1));
2999 CU_ASSERT(1 == nghttp2_session_is_my_stream_id(session, 2));
3001 nghttp2_session_del(session);
3003 nghttp2_session_client_new(&session, &callbacks, NULL);
3005 CU_ASSERT(0 == nghttp2_session_is_my_stream_id(session, 0));
3006 CU_ASSERT(1 == nghttp2_session_is_my_stream_id(session, 1));
3007 CU_ASSERT(0 == nghttp2_session_is_my_stream_id(session, 2));
3009 nghttp2_session_del(session);
3012 void test_nghttp2_session_upgrade(void) {
3013 nghttp2_session *session;
3014 nghttp2_session_callbacks callbacks;
3015 uint8_t settings_payload[128];
3016 size_t settings_payloadlen;
3017 nghttp2_settings_entry iv[16];
3018 nghttp2_stream *stream;
3019 nghttp2_outbound_item *item;
3021 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
3022 callbacks.send_callback = null_send_callback;
3023 iv[0].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS;
3025 iv[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
3027 settings_payloadlen = nghttp2_pack_settings_payload(
3028 settings_payload, sizeof(settings_payload), iv, 2);
3030 /* Check client side */
3031 nghttp2_session_client_new(&session, &callbacks, NULL);
3032 CU_ASSERT(0 == nghttp2_session_upgrade(session, settings_payload,
3033 settings_payloadlen, &callbacks));
3034 stream = nghttp2_session_get_stream(session, 1);
3035 CU_ASSERT(stream != NULL);
3036 CU_ASSERT(&callbacks == stream->stream_user_data);
3037 CU_ASSERT(NGHTTP2_SHUT_WR == stream->shut_flags);
3038 item = nghttp2_session_get_next_ob_item(session);
3039 CU_ASSERT(NGHTTP2_SETTINGS == item->frame.hd.type);
3040 CU_ASSERT(2 == item->frame.settings.niv);
3041 CU_ASSERT(NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS ==
3042 item->frame.settings.iv[0].settings_id);
3043 CU_ASSERT(1 == item->frame.settings.iv[0].value);
3044 CU_ASSERT(NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE ==
3045 item->frame.settings.iv[1].settings_id);
3046 CU_ASSERT(4095 == item->frame.settings.iv[1].value);
3048 /* Call nghttp2_session_upgrade() again is error */
3049 CU_ASSERT(NGHTTP2_ERR_PROTO ==
3050 nghttp2_session_upgrade(session, settings_payload,
3051 settings_payloadlen, &callbacks));
3052 nghttp2_session_del(session);
3054 /* Check server side */
3055 nghttp2_session_server_new(&session, &callbacks, NULL);
3056 CU_ASSERT(0 == nghttp2_session_upgrade(session, settings_payload,
3057 settings_payloadlen, &callbacks));
3058 stream = nghttp2_session_get_stream(session, 1);
3059 CU_ASSERT(stream != NULL);
3060 CU_ASSERT(NULL == stream->stream_user_data);
3061 CU_ASSERT(NGHTTP2_SHUT_RD == stream->shut_flags);
3062 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
3063 CU_ASSERT(1 == session->remote_settings.max_concurrent_streams);
3064 CU_ASSERT(4095 == session->remote_settings.initial_window_size);
3065 /* Call nghttp2_session_upgrade() again is error */
3066 CU_ASSERT(NGHTTP2_ERR_PROTO ==
3067 nghttp2_session_upgrade(session, settings_payload,
3068 settings_payloadlen, &callbacks));
3069 nghttp2_session_del(session);
3071 /* Empty SETTINGS is OK */
3072 settings_payloadlen = nghttp2_pack_settings_payload(
3073 settings_payload, sizeof(settings_payload), NULL, 0);
3075 nghttp2_session_client_new(&session, &callbacks, NULL);
3076 CU_ASSERT(0 == nghttp2_session_upgrade(session, settings_payload,
3077 settings_payloadlen, NULL));
3078 nghttp2_session_del(session);
3081 void test_nghttp2_session_reprioritize_stream(void) {
3082 nghttp2_session *session;
3083 nghttp2_session_callbacks callbacks;
3085 nghttp2_stream *stream;
3086 nghttp2_stream *dep_stream;
3087 nghttp2_priority_spec pri_spec;
3089 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
3090 callbacks.send_callback = block_count_send_callback;
3092 nghttp2_session_server_new(&session, &callbacks, &ud);
3094 stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
3096 NGHTTP2_STREAM_OPENING, NULL);
3098 nghttp2_priority_spec_init(&pri_spec, 0, 10, 0);
3100 nghttp2_session_reprioritize_stream(session, stream, &pri_spec);
3102 CU_ASSERT(10 == stream->weight);
3103 CU_ASSERT(NULL == stream->dep_prev);
3105 /* If depenency to idle stream which is not in depdenency tree yet */
3107 nghttp2_priority_spec_init(&pri_spec, 3, 99, 0);
3109 nghttp2_session_reprioritize_stream(session, stream, &pri_spec);
3111 CU_ASSERT(99 == stream->weight);
3112 CU_ASSERT(3 == stream->dep_prev->stream_id);
3114 dep_stream = nghttp2_session_get_stream_raw(session, 3);
3116 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == dep_stream->weight);
3118 dep_stream = open_stream(session, 3);
3121 pri_spec.weight = 128;
3123 nghttp2_session_reprioritize_stream(session, stream, &pri_spec);
3125 CU_ASSERT(128 == stream->weight);
3126 CU_ASSERT(dep_stream == stream->dep_prev);
3128 /* Test circular dependency; stream 1 is first removed and becomes
3129 root. Then stream 3 depends on it. */
3130 nghttp2_priority_spec_init(&pri_spec, 1, 1, 0);
3132 nghttp2_session_reprioritize_stream(session, dep_stream, &pri_spec);
3134 CU_ASSERT(1 == dep_stream->weight);
3135 CU_ASSERT(stream == dep_stream->dep_prev);
3137 /* Making priority to closed stream will result in default
3139 session->last_recv_stream_id = 9;
3141 nghttp2_priority_spec_init(&pri_spec, 5, 5, 0);
3143 nghttp2_session_reprioritize_stream(session, stream, &pri_spec);
3145 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == stream->weight);
3147 nghttp2_session_del(session);
3150 void test_nghttp2_session_reprioritize_stream_with_idle_stream_dep(void) {
3151 nghttp2_session *session;
3152 nghttp2_session_callbacks callbacks;
3153 nghttp2_stream *stream;
3154 nghttp2_priority_spec pri_spec;
3156 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
3157 callbacks.send_callback = block_count_send_callback;
3159 nghttp2_session_server_new(&session, &callbacks, NULL);
3161 stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
3163 NGHTTP2_STREAM_OPENING, NULL);
3165 session->pending_local_max_concurrent_stream = 1;
3167 nghttp2_priority_spec_init(&pri_spec, 101, 10, 0);
3169 nghttp2_session_reprioritize_stream(session, stream, &pri_spec);
3171 /* idle stream is not counteed to max concurrent streams */
3173 CU_ASSERT(10 == stream->weight);
3174 CU_ASSERT(101 == stream->dep_prev->stream_id);
3176 stream = nghttp2_session_get_stream_raw(session, 101);
3178 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == stream->weight);
3180 nghttp2_session_del(session);
3183 void test_nghttp2_submit_data(void) {
3184 nghttp2_session *session;
3185 nghttp2_session_callbacks callbacks;
3186 nghttp2_data_provider data_prd;
3188 nghttp2_frame *frame;
3189 nghttp2_frame_hd hd;
3190 nghttp2_active_outbound_item *aob;
3191 nghttp2_bufs *framebufs;
3194 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
3195 callbacks.send_callback = block_count_send_callback;
3197 data_prd.read_callback = fixed_length_data_source_read_callback;
3198 ud.data_source_length = NGHTTP2_DATA_PAYLOADLEN * 2;
3199 CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, &ud));
3200 aob = &session->aob;
3201 framebufs = &aob->framebufs;
3203 nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
3204 &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL);
3206 0 == nghttp2_submit_data(session, NGHTTP2_FLAG_END_STREAM, 1, &data_prd));
3209 CU_ASSERT(0 == nghttp2_session_send(session));
3210 frame = &aob->item->frame;
3212 buf = &framebufs->head->buf;
3213 nghttp2_frame_unpack_frame_hd(&hd, buf->pos);
3215 CU_ASSERT(NGHTTP2_FLAG_NONE == hd.flags);
3216 CU_ASSERT(NGHTTP2_FLAG_NONE == frame->hd.flags);
3217 /* aux_data.data.flags has these flags */
3218 CU_ASSERT(NGHTTP2_FLAG_END_STREAM == aob->item->aux_data.data.flags);
3220 nghttp2_session_del(session);
3223 void test_nghttp2_submit_data_read_length_too_large(void) {
3224 nghttp2_session *session;
3225 nghttp2_session_callbacks callbacks;
3226 nghttp2_data_provider data_prd;
3228 nghttp2_frame *frame;
3229 nghttp2_frame_hd hd;
3230 nghttp2_active_outbound_item *aob;
3231 nghttp2_bufs *framebufs;
3235 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
3236 callbacks.send_callback = block_count_send_callback;
3237 callbacks.read_length_callback = too_large_data_source_length_callback;
3239 data_prd.read_callback = fixed_length_data_source_read_callback;
3240 ud.data_source_length = NGHTTP2_DATA_PAYLOADLEN * 2;
3241 CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, &ud));
3242 aob = &session->aob;
3243 framebufs = &aob->framebufs;
3245 nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
3246 &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL);
3248 0 == nghttp2_submit_data(session, NGHTTP2_FLAG_END_STREAM, 1, &data_prd));
3251 CU_ASSERT(0 == nghttp2_session_send(session));
3252 frame = &aob->item->frame;
3254 buf = &framebufs->head->buf;
3255 nghttp2_frame_unpack_frame_hd(&hd, buf->pos);
3257 CU_ASSERT(NGHTTP2_FLAG_NONE == hd.flags);
3258 CU_ASSERT(NGHTTP2_FLAG_NONE == frame->hd.flags);
3259 CU_ASSERT(16384 == hd.length)
3260 /* aux_data.data.flags has these flags */
3261 CU_ASSERT(NGHTTP2_FLAG_END_STREAM == aob->item->aux_data.data.flags);
3263 nghttp2_session_del(session);
3265 /* Check that buffers are expanded */
3266 CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, &ud));
3268 ud.data_source_length = NGHTTP2_MAX_FRAME_SIZE_MAX;
3270 session->remote_settings.max_frame_size = NGHTTP2_MAX_FRAME_SIZE_MAX;
3272 nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
3273 &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL);
3275 0 == nghttp2_submit_data(session, NGHTTP2_FLAG_END_STREAM, 1, &data_prd));
3278 CU_ASSERT(0 == nghttp2_session_send(session));
3280 aob = &session->aob;
3282 frame = &aob->item->frame;
3284 framebufs = &aob->framebufs;
3286 buf = &framebufs->head->buf;
3287 nghttp2_frame_unpack_frame_hd(&hd, buf->pos);
3289 payloadlen = nghttp2_min(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE,
3290 NGHTTP2_INITIAL_WINDOW_SIZE);
3292 CU_ASSERT(NGHTTP2_FRAME_HDLEN + 1 + payloadlen ==
3293 (size_t)nghttp2_buf_cap(buf));
3294 CU_ASSERT(NGHTTP2_FLAG_NONE == hd.flags);
3295 CU_ASSERT(NGHTTP2_FLAG_NONE == frame->hd.flags);
3296 CU_ASSERT(payloadlen == hd.length);
3297 /* aux_data.data.flags has these flags */
3298 CU_ASSERT(NGHTTP2_FLAG_END_STREAM == aob->item->aux_data.data.flags);
3300 nghttp2_session_del(session);
3303 void test_nghttp2_submit_data_read_length_smallest(void) {
3304 nghttp2_session *session;
3305 nghttp2_session_callbacks callbacks;
3306 nghttp2_data_provider data_prd;
3308 nghttp2_frame *frame;
3309 nghttp2_frame_hd hd;
3310 nghttp2_active_outbound_item *aob;
3311 nghttp2_bufs *framebufs;
3314 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
3315 callbacks.send_callback = block_count_send_callback;
3316 callbacks.read_length_callback = smallest_length_data_source_length_callback;
3318 data_prd.read_callback = fixed_length_data_source_read_callback;
3319 ud.data_source_length = NGHTTP2_DATA_PAYLOADLEN * 2;
3320 CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, &ud));
3321 aob = &session->aob;
3322 framebufs = &aob->framebufs;
3324 nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
3325 &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL);
3327 0 == nghttp2_submit_data(session, NGHTTP2_FLAG_END_STREAM, 1, &data_prd));
3330 CU_ASSERT(0 == nghttp2_session_send(session));
3331 frame = &aob->item->frame;
3333 buf = &framebufs->head->buf;
3334 nghttp2_frame_unpack_frame_hd(&hd, buf->pos);
3336 CU_ASSERT(NGHTTP2_FLAG_NONE == hd.flags);
3337 CU_ASSERT(NGHTTP2_FLAG_NONE == frame->hd.flags);
3338 CU_ASSERT(1 == hd.length)
3339 /* aux_data.data.flags has these flags */
3340 CU_ASSERT(NGHTTP2_FLAG_END_STREAM == aob->item->aux_data.data.flags);
3342 nghttp2_session_del(session);
3345 static ssize_t submit_data_twice_data_source_read_callback(
3346 nghttp2_session *session _U_, int32_t stream_id _U_, uint8_t *buf _U_,
3347 size_t len, uint32_t *data_flags, nghttp2_data_source *source _U_,
3348 void *user_data _U_) {
3349 *data_flags |= NGHTTP2_DATA_FLAG_EOF;
3350 return nghttp2_min(len, 16);
3353 static int submit_data_twice_on_frame_send_callback(nghttp2_session *session,
3354 const nghttp2_frame *frame,
3355 void *user_data _U_) {
3356 static int called = 0;
3358 nghttp2_data_provider data_prd;
3363 data_prd.read_callback = submit_data_twice_data_source_read_callback;
3365 rv = nghttp2_submit_data(session, NGHTTP2_FLAG_END_STREAM,
3366 frame->hd.stream_id, &data_prd);
3373 void test_nghttp2_submit_data_twice(void) {
3374 nghttp2_session *session;
3375 nghttp2_session_callbacks callbacks;
3376 nghttp2_data_provider data_prd;
3380 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
3381 callbacks.send_callback = accumulator_send_callback;
3382 callbacks.on_frame_send_callback = submit_data_twice_on_frame_send_callback;
3384 data_prd.read_callback = submit_data_twice_data_source_read_callback;
3389 CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, &ud));
3391 nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
3392 &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL);
3394 CU_ASSERT(0 == nghttp2_submit_data(session, NGHTTP2_FLAG_NONE, 1, &data_prd));
3396 CU_ASSERT(0 == nghttp2_session_send(session));
3398 /* We should have sent 2 DATA frame with 16 bytes payload each */
3399 CU_ASSERT(NGHTTP2_FRAME_HDLEN * 2 + 16 * 2 == acc.length);
3401 nghttp2_session_del(session);
3404 void test_nghttp2_submit_request_with_data(void) {
3405 nghttp2_session *session;
3406 nghttp2_session_callbacks callbacks;
3407 nghttp2_data_provider data_prd;
3409 nghttp2_outbound_item *item;
3412 mem = nghttp2_mem_default();
3414 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
3415 callbacks.send_callback = null_send_callback;
3417 data_prd.read_callback = fixed_length_data_source_read_callback;
3418 ud.data_source_length = 64 * 1024 - 1;
3419 CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, &ud));
3420 CU_ASSERT(1 == nghttp2_submit_request(session, NULL, reqnv, ARRLEN(reqnv),
3422 item = nghttp2_session_get_next_ob_item(session);
3423 CU_ASSERT(ARRLEN(reqnv) == item->frame.headers.nvlen);
3424 assert_nv_equal(reqnv, item->frame.headers.nva, item->frame.headers.nvlen,
3426 CU_ASSERT(0 == nghttp2_session_send(session));
3427 CU_ASSERT(0 == ud.data_source_length);
3429 nghttp2_session_del(session);
3432 void test_nghttp2_submit_request_without_data(void) {
3433 nghttp2_session *session;
3434 nghttp2_session_callbacks callbacks;
3436 nghttp2_data_provider data_prd = {{-1}, NULL};
3437 nghttp2_outbound_item *item;
3439 nghttp2_frame frame;
3440 nghttp2_hd_inflater inflater;
3445 mem = nghttp2_mem_default();
3446 frame_pack_bufs_init(&bufs);
3451 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
3452 callbacks.send_callback = accumulator_send_callback;
3453 CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, &ud));
3455 nghttp2_hd_inflate_init(&inflater, mem);
3456 CU_ASSERT(1 == nghttp2_submit_request(session, NULL, reqnv, ARRLEN(reqnv),
3458 item = nghttp2_session_get_next_ob_item(session);
3459 CU_ASSERT(ARRLEN(reqnv) == item->frame.headers.nvlen);
3460 assert_nv_equal(reqnv, item->frame.headers.nva, item->frame.headers.nvlen,
3462 CU_ASSERT(item->frame.hd.flags & NGHTTP2_FLAG_END_STREAM);
3464 CU_ASSERT(0 == nghttp2_session_send(session));
3465 CU_ASSERT(0 == unpack_frame(&frame, acc.buf, acc.length));
3467 nghttp2_bufs_add(&bufs, acc.buf, acc.length);
3468 inflate_hd(&inflater, &out, &bufs, NGHTTP2_FRAME_HDLEN, mem);
3470 CU_ASSERT(ARRLEN(reqnv) == out.nvlen);
3471 assert_nv_equal(reqnv, out.nva, out.nvlen, mem);
3472 nghttp2_frame_headers_free(&frame.headers, mem);
3473 nva_out_reset(&out, mem);
3475 nghttp2_bufs_free(&bufs);
3476 nghttp2_hd_inflate_free(&inflater);
3477 nghttp2_session_del(session);
3480 void test_nghttp2_submit_response_with_data(void) {
3481 nghttp2_session *session;
3482 nghttp2_session_callbacks callbacks;
3483 nghttp2_data_provider data_prd;
3485 nghttp2_outbound_item *item;
3488 mem = nghttp2_mem_default();
3490 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
3491 callbacks.send_callback = null_send_callback;
3493 data_prd.read_callback = fixed_length_data_source_read_callback;
3494 ud.data_source_length = 64 * 1024 - 1;
3495 CU_ASSERT(0 == nghttp2_session_server_new(&session, &callbacks, &ud));
3496 nghttp2_session_open_stream(session, 1, NGHTTP2_FLAG_END_STREAM,
3497 &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL);
3498 CU_ASSERT(0 == nghttp2_submit_response(session, 1, resnv, ARRLEN(resnv),
3500 item = nghttp2_session_get_next_ob_item(session);
3501 CU_ASSERT(ARRLEN(resnv) == item->frame.headers.nvlen);
3502 assert_nv_equal(resnv, item->frame.headers.nva, item->frame.headers.nvlen,
3504 CU_ASSERT(0 == nghttp2_session_send(session));
3505 CU_ASSERT(0 == ud.data_source_length);
3507 nghttp2_session_del(session);
3510 void test_nghttp2_submit_response_without_data(void) {
3511 nghttp2_session *session;
3512 nghttp2_session_callbacks callbacks;
3514 nghttp2_data_provider data_prd = {{-1}, NULL};
3515 nghttp2_outbound_item *item;
3517 nghttp2_frame frame;
3518 nghttp2_hd_inflater inflater;
3523 mem = nghttp2_mem_default();
3524 frame_pack_bufs_init(&bufs);
3529 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
3530 callbacks.send_callback = accumulator_send_callback;
3531 CU_ASSERT(0 == nghttp2_session_server_new(&session, &callbacks, &ud));
3533 nghttp2_hd_inflate_init(&inflater, mem);
3534 nghttp2_session_open_stream(session, 1, NGHTTP2_FLAG_END_STREAM,
3535 &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL);
3536 CU_ASSERT(0 == nghttp2_submit_response(session, 1, resnv, ARRLEN(resnv),
3538 item = nghttp2_session_get_next_ob_item(session);
3539 CU_ASSERT(ARRLEN(resnv) == item->frame.headers.nvlen);
3540 assert_nv_equal(resnv, item->frame.headers.nva, item->frame.headers.nvlen,
3542 CU_ASSERT(item->frame.hd.flags & NGHTTP2_FLAG_END_STREAM);
3544 CU_ASSERT(0 == nghttp2_session_send(session));
3545 CU_ASSERT(0 == unpack_frame(&frame, acc.buf, acc.length));
3547 nghttp2_bufs_add(&bufs, acc.buf, acc.length);
3548 inflate_hd(&inflater, &out, &bufs, NGHTTP2_FRAME_HDLEN, mem);
3550 CU_ASSERT(ARRLEN(resnv) == out.nvlen);
3551 assert_nv_equal(resnv, out.nva, out.nvlen, mem);
3553 nva_out_reset(&out, mem);
3554 nghttp2_bufs_free(&bufs);
3555 nghttp2_frame_headers_free(&frame.headers, mem);
3556 nghttp2_hd_inflate_free(&inflater);
3557 nghttp2_session_del(session);
3560 void test_nghttp2_submit_trailer(void) {
3561 nghttp2_session *session;
3562 nghttp2_session_callbacks callbacks;
3564 nghttp2_data_provider data_prd;
3565 nghttp2_outbound_item *item;
3567 nghttp2_frame frame;
3568 nghttp2_hd_inflater inflater;
3573 mem = nghttp2_mem_default();
3574 frame_pack_bufs_init(&bufs);
3576 data_prd.read_callback = no_end_stream_data_source_read_callback;
3580 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
3581 callbacks.send_callback = null_send_callback;
3582 CU_ASSERT(0 == nghttp2_session_server_new(&session, &callbacks, &ud));
3584 nghttp2_hd_inflate_init(&inflater, mem);
3585 nghttp2_session_open_stream(session, 1, NGHTTP2_FLAG_END_STREAM,
3586 &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL);
3587 CU_ASSERT(0 == nghttp2_submit_response(session, 1, resnv, ARRLEN(resnv),
3589 CU_ASSERT(0 == nghttp2_session_send(session));
3592 nghttp2_submit_trailer(session, 1, trailernv, ARRLEN(trailernv)));
3594 session->callbacks.send_callback = accumulator_send_callback;
3596 item = nghttp2_session_get_next_ob_item(session);
3597 CU_ASSERT(NGHTTP2_HEADERS == item->frame.hd.type);
3598 CU_ASSERT(NGHTTP2_HCAT_HEADERS == item->frame.headers.cat);
3599 CU_ASSERT(item->frame.hd.flags & NGHTTP2_FLAG_END_STREAM);
3601 CU_ASSERT(0 == nghttp2_session_send(session));
3602 CU_ASSERT(0 == unpack_frame(&frame, acc.buf, acc.length));
3604 nghttp2_bufs_add(&bufs, acc.buf, acc.length);
3605 inflate_hd(&inflater, &out, &bufs, NGHTTP2_FRAME_HDLEN, mem);
3607 CU_ASSERT(ARRLEN(trailernv) == out.nvlen);
3608 assert_nv_equal(trailernv, out.nva, out.nvlen, mem);
3610 nva_out_reset(&out, mem);
3611 nghttp2_bufs_free(&bufs);
3612 nghttp2_frame_headers_free(&frame.headers, mem);
3613 nghttp2_hd_inflate_free(&inflater);
3614 nghttp2_session_del(session);
3617 void test_nghttp2_submit_headers_start_stream(void) {
3618 nghttp2_session *session;
3619 nghttp2_session_callbacks callbacks;
3620 nghttp2_outbound_item *item;
3623 mem = nghttp2_mem_default();
3625 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
3626 CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, NULL));
3627 CU_ASSERT(1 == nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, -1,
3628 NULL, reqnv, ARRLEN(reqnv), NULL));
3629 item = nghttp2_session_get_next_ob_item(session);
3630 CU_ASSERT(ARRLEN(reqnv) == item->frame.headers.nvlen);
3631 assert_nv_equal(reqnv, item->frame.headers.nva, item->frame.headers.nvlen,
3633 CU_ASSERT((NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM) ==
3634 item->frame.hd.flags);
3635 CU_ASSERT(0 == (item->frame.hd.flags & NGHTTP2_FLAG_PRIORITY));
3637 nghttp2_session_del(session);
3640 void test_nghttp2_submit_headers_reply(void) {
3641 nghttp2_session *session;
3642 nghttp2_session_callbacks callbacks;
3644 nghttp2_outbound_item *item;
3645 nghttp2_stream *stream;
3648 mem = nghttp2_mem_default();
3650 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
3651 callbacks.send_callback = null_send_callback;
3652 callbacks.on_frame_send_callback = on_frame_send_callback;
3654 CU_ASSERT(0 == nghttp2_session_server_new(&session, &callbacks, &ud));
3655 CU_ASSERT(0 == nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, 1,
3656 NULL, resnv, ARRLEN(resnv), NULL));
3657 item = nghttp2_session_get_next_ob_item(session);
3658 CU_ASSERT(ARRLEN(resnv) == item->frame.headers.nvlen);
3659 assert_nv_equal(resnv, item->frame.headers.nva, item->frame.headers.nvlen,
3661 CU_ASSERT((NGHTTP2_FLAG_END_STREAM | NGHTTP2_FLAG_END_HEADERS) ==
3662 item->frame.hd.flags);
3664 ud.frame_send_cb_called = 0;
3665 ud.sent_frame_type = 0;
3666 /* The transimission will be canceled because the stream 1 is not
3668 CU_ASSERT(0 == nghttp2_session_send(session));
3669 CU_ASSERT(0 == ud.frame_send_cb_called);
3671 stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
3673 NGHTTP2_STREAM_OPENING, NULL);
3675 CU_ASSERT(0 == nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, 1,
3676 NULL, resnv, ARRLEN(resnv), NULL));
3677 CU_ASSERT(0 == nghttp2_session_send(session));
3678 CU_ASSERT(1 == ud.frame_send_cb_called);
3679 CU_ASSERT(NGHTTP2_HEADERS == ud.sent_frame_type);
3680 CU_ASSERT(stream->shut_flags & NGHTTP2_SHUT_WR);
3682 nghttp2_session_del(session);
3685 void test_nghttp2_submit_headers_push_reply(void) {
3686 nghttp2_session *session;
3687 nghttp2_session_callbacks callbacks;
3689 nghttp2_stream *stream;
3692 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
3693 callbacks.send_callback = null_send_callback;
3694 callbacks.on_frame_send_callback = on_frame_send_callback;
3696 CU_ASSERT(0 == nghttp2_session_server_new(&session, &callbacks, &ud));
3697 stream = nghttp2_session_open_stream(session, 2, NGHTTP2_STREAM_FLAG_NONE,
3699 NGHTTP2_STREAM_RESERVED, NULL);
3700 CU_ASSERT(0 == nghttp2_submit_headers(session, NGHTTP2_FLAG_NONE, 2, NULL,
3701 resnv, ARRLEN(resnv), &foo));
3703 ud.frame_send_cb_called = 0;
3704 ud.sent_frame_type = 0;
3705 CU_ASSERT(0 == nghttp2_session_send(session));
3706 CU_ASSERT(1 == ud.frame_send_cb_called);
3707 CU_ASSERT(NGHTTP2_HEADERS == ud.sent_frame_type);
3708 CU_ASSERT(NGHTTP2_STREAM_OPENED == stream->state);
3709 CU_ASSERT(&foo == stream->stream_user_data);
3711 nghttp2_session_del(session);
3713 /* Sending HEADERS from client against stream in reserved state is
3715 CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, &ud));
3716 nghttp2_session_open_stream(session, 2, NGHTTP2_STREAM_FLAG_NONE,
3717 &pri_spec_default, NGHTTP2_STREAM_RESERVED, NULL);
3718 CU_ASSERT(0 == nghttp2_submit_headers(session, NGHTTP2_FLAG_NONE, 2, NULL,
3719 reqnv, ARRLEN(reqnv), NULL));
3721 ud.frame_send_cb_called = 0;
3722 ud.sent_frame_type = 0;
3723 CU_ASSERT(0 == nghttp2_session_send(session));
3724 CU_ASSERT(0 == ud.frame_send_cb_called);
3726 nghttp2_session_del(session);
3729 void test_nghttp2_submit_headers(void) {
3730 nghttp2_session *session;
3731 nghttp2_session_callbacks callbacks;
3733 nghttp2_outbound_item *item;
3734 nghttp2_stream *stream;
3736 nghttp2_frame frame;
3737 nghttp2_hd_inflater inflater;
3742 mem = nghttp2_mem_default();
3743 frame_pack_bufs_init(&bufs);
3748 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
3749 callbacks.send_callback = accumulator_send_callback;
3750 callbacks.on_frame_send_callback = on_frame_send_callback;
3752 CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, &ud));
3754 nghttp2_hd_inflate_init(&inflater, mem);
3755 CU_ASSERT(0 == nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, 1,
3756 NULL, reqnv, ARRLEN(reqnv), NULL));
3757 item = nghttp2_session_get_next_ob_item(session);
3758 CU_ASSERT(ARRLEN(reqnv) == item->frame.headers.nvlen);
3759 assert_nv_equal(reqnv, item->frame.headers.nva, item->frame.headers.nvlen,
3761 CU_ASSERT((NGHTTP2_FLAG_END_STREAM | NGHTTP2_FLAG_END_HEADERS) ==
3762 item->frame.hd.flags);
3764 ud.frame_send_cb_called = 0;
3765 ud.sent_frame_type = 0;
3766 /* The transimission will be canceled because the stream 1 is not
3768 CU_ASSERT(0 == nghttp2_session_send(session));
3769 CU_ASSERT(0 == ud.frame_send_cb_called);
3771 stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
3773 NGHTTP2_STREAM_OPENING, NULL);
3775 CU_ASSERT(0 == nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, 1,
3776 NULL, reqnv, ARRLEN(reqnv), NULL));
3777 CU_ASSERT(0 == nghttp2_session_send(session));
3778 CU_ASSERT(1 == ud.frame_send_cb_called);
3779 CU_ASSERT(NGHTTP2_HEADERS == ud.sent_frame_type);
3780 CU_ASSERT(stream->shut_flags & NGHTTP2_SHUT_WR);
3782 CU_ASSERT(0 == unpack_frame(&frame, acc.buf, acc.length));
3784 nghttp2_bufs_add(&bufs, acc.buf, acc.length);
3785 inflate_hd(&inflater, &out, &bufs, NGHTTP2_FRAME_HDLEN, mem);
3787 CU_ASSERT(ARRLEN(reqnv) == out.nvlen);
3788 assert_nv_equal(reqnv, out.nva, out.nvlen, mem);
3790 nva_out_reset(&out, mem);
3791 nghttp2_bufs_free(&bufs);
3792 nghttp2_frame_headers_free(&frame.headers, mem);
3794 nghttp2_hd_inflate_free(&inflater);
3795 nghttp2_session_del(session);
3798 void test_nghttp2_submit_headers_continuation(void) {
3799 nghttp2_session *session;
3800 nghttp2_session_callbacks callbacks;
3802 MAKE_NV("h1", ""), MAKE_NV("h1", ""), MAKE_NV("h1", ""),
3803 MAKE_NV("h1", ""), MAKE_NV("h1", ""), MAKE_NV("h1", ""),
3806 nghttp2_outbound_item *item;
3811 memset(data, '0', sizeof(data));
3812 for (i = 0; i < ARRLEN(nv); ++i) {
3813 nv[i].valuelen = sizeof(data);
3817 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
3818 callbacks.send_callback = null_send_callback;
3819 callbacks.on_frame_send_callback = on_frame_send_callback;
3821 CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, &ud));
3822 CU_ASSERT(1 == nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, -1,
3823 NULL, nv, ARRLEN(nv), NULL));
3824 item = nghttp2_session_get_next_ob_item(session);
3825 CU_ASSERT(NGHTTP2_HEADERS == item->frame.hd.type);
3826 CU_ASSERT((NGHTTP2_FLAG_END_STREAM | NGHTTP2_FLAG_END_HEADERS) ==
3827 item->frame.hd.flags);
3828 CU_ASSERT(0 == (item->frame.hd.flags & NGHTTP2_FLAG_PRIORITY));
3830 ud.frame_send_cb_called = 0;
3831 CU_ASSERT(0 == nghttp2_session_send(session));
3832 CU_ASSERT(1 == ud.frame_send_cb_called);
3834 nghttp2_session_del(session);
3837 void test_nghttp2_submit_priority(void) {
3838 nghttp2_session *session;
3839 nghttp2_session_callbacks callbacks;
3840 nghttp2_stream *stream;
3842 nghttp2_priority_spec pri_spec;
3844 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
3845 callbacks.send_callback = null_send_callback;
3846 callbacks.on_frame_send_callback = on_frame_send_callback;
3848 nghttp2_session_client_new(&session, &callbacks, &ud);
3849 stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
3851 NGHTTP2_STREAM_OPENING, NULL);
3853 nghttp2_priority_spec_init(&pri_spec, 0, 3, 0);
3855 /* depends on stream 0 */
3857 nghttp2_submit_priority(session, NGHTTP2_FLAG_NONE, 1, &pri_spec));
3858 CU_ASSERT(0 == nghttp2_session_send(session));
3859 CU_ASSERT(3 == stream->weight);
3861 /* submit against idle stream */
3863 nghttp2_submit_priority(session, NGHTTP2_FLAG_NONE, 3, &pri_spec));
3865 ud.frame_send_cb_called = 0;
3866 CU_ASSERT(0 == nghttp2_session_send(session));
3867 CU_ASSERT(1 == ud.frame_send_cb_called);
3869 nghttp2_session_del(session);
3872 void test_nghttp2_submit_settings(void) {
3873 nghttp2_session *session;
3874 nghttp2_session_callbacks callbacks;
3876 nghttp2_outbound_item *item;
3877 nghttp2_frame *frame;
3878 nghttp2_settings_entry iv[7];
3879 nghttp2_frame ack_frame;
3880 const int32_t UNKNOWN_ID = 1000000007;
3883 mem = nghttp2_mem_default();
3885 iv[0].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS;
3888 iv[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
3889 iv[1].value = 16 * 1024;
3891 iv[2].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS;
3894 iv[3].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
3897 iv[4].settings_id = UNKNOWN_ID;
3900 iv[5].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
3901 iv[5].value = (uint32_t)NGHTTP2_MAX_WINDOW_SIZE + 1;
3903 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
3904 callbacks.send_callback = null_send_callback;
3905 callbacks.on_frame_send_callback = on_frame_send_callback;
3906 nghttp2_session_server_new(&session, &callbacks, &ud);
3908 CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT ==
3909 nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, iv, 6));
3911 /* Make sure that local settings are not changed */
3912 CU_ASSERT(NGHTTP2_INITIAL_MAX_CONCURRENT_STREAMS ==
3913 session->local_settings.max_concurrent_streams);
3914 CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE ==
3915 session->local_settings.initial_window_size);
3917 /* Now sends without 6th one */
3918 CU_ASSERT(0 == nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, iv, 5));
3920 item = nghttp2_session_get_next_ob_item(session);
3922 CU_ASSERT(NGHTTP2_SETTINGS == item->frame.hd.type);
3924 frame = &item->frame;
3925 CU_ASSERT(5 == frame->settings.niv);
3926 CU_ASSERT(5 == frame->settings.iv[0].value);
3927 CU_ASSERT(NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS ==
3928 frame->settings.iv[0].settings_id);
3930 CU_ASSERT(16 * 1024 == frame->settings.iv[1].value);
3931 CU_ASSERT(NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE ==
3932 frame->settings.iv[1].settings_id);
3934 CU_ASSERT(UNKNOWN_ID == frame->settings.iv[4].settings_id);
3935 CU_ASSERT(999 == frame->settings.iv[4].value);
3937 ud.frame_send_cb_called = 0;
3938 CU_ASSERT(0 == nghttp2_session_send(session));
3939 CU_ASSERT(1 == ud.frame_send_cb_called);
3941 CU_ASSERT(50 == session->pending_local_max_concurrent_stream);
3943 nghttp2_frame_settings_init(&ack_frame.settings, NGHTTP2_FLAG_ACK, NULL, 0);
3944 CU_ASSERT(0 == nghttp2_session_on_settings_received(session, &ack_frame, 0));
3945 nghttp2_frame_settings_free(&ack_frame.settings, mem);
3947 CU_ASSERT(16 * 1024 == session->local_settings.initial_window_size);
3948 CU_ASSERT(0 == session->hd_inflater.ctx.hd_table_bufsize_max);
3949 CU_ASSERT(50 == session->local_settings.max_concurrent_streams);
3950 CU_ASSERT(NGHTTP2_INITIAL_MAX_CONCURRENT_STREAMS ==
3951 session->pending_local_max_concurrent_stream);
3953 nghttp2_session_del(session);
3956 void test_nghttp2_submit_settings_update_local_window_size(void) {
3957 nghttp2_session *session;
3958 nghttp2_session_callbacks callbacks;
3959 nghttp2_outbound_item *item;
3960 nghttp2_settings_entry iv[4];
3961 nghttp2_stream *stream;
3962 nghttp2_frame ack_frame;
3965 mem = nghttp2_mem_default();
3966 nghttp2_frame_settings_init(&ack_frame.settings, NGHTTP2_FLAG_ACK, NULL, 0);
3968 iv[0].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
3969 iv[0].value = 16 * 1024;
3971 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
3972 callbacks.send_callback = null_send_callback;
3974 nghttp2_session_server_new(&session, &callbacks, NULL);
3976 stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
3977 &pri_spec_default, NGHTTP2_STREAM_OPENED,
3979 stream->local_window_size = NGHTTP2_INITIAL_WINDOW_SIZE + 100;
3980 stream->recv_window_size = 32768;
3982 nghttp2_session_open_stream(session, 3, NGHTTP2_STREAM_FLAG_NONE,
3983 &pri_spec_default, NGHTTP2_STREAM_OPENED, NULL);
3985 CU_ASSERT(0 == nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, iv, 1));
3986 CU_ASSERT(0 == nghttp2_session_send(session));
3987 CU_ASSERT(0 == nghttp2_session_on_settings_received(session, &ack_frame, 0));
3989 stream = nghttp2_session_get_stream(session, 1);
3990 CU_ASSERT(0 == stream->recv_window_size);
3991 CU_ASSERT(16 * 1024 + 100 == stream->local_window_size);
3993 stream = nghttp2_session_get_stream(session, 3);
3994 CU_ASSERT(16 * 1024 == stream->local_window_size);
3996 item = nghttp2_session_get_next_ob_item(session);
3997 CU_ASSERT(NGHTTP2_WINDOW_UPDATE == item->frame.hd.type);
3998 CU_ASSERT(32768 == item->frame.window_update.window_size_increment);
4000 nghttp2_session_del(session);
4002 /* Check overflow case */
4003 iv[0].value = 128 * 1024;
4004 nghttp2_session_server_new(&session, &callbacks, NULL);
4005 stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
4006 &pri_spec_default, NGHTTP2_STREAM_OPENED,
4008 stream->local_window_size = NGHTTP2_MAX_WINDOW_SIZE;
4010 CU_ASSERT(0 == nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, iv, 1));
4011 CU_ASSERT(0 == nghttp2_session_send(session));
4012 CU_ASSERT(0 == nghttp2_session_on_settings_received(session, &ack_frame, 0));
4014 item = nghttp2_session_get_next_ob_item(session);
4015 CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
4016 CU_ASSERT(NGHTTP2_FLOW_CONTROL_ERROR == item->frame.goaway.error_code);
4018 nghttp2_session_del(session);
4019 nghttp2_frame_settings_free(&ack_frame.settings, mem);
4022 void test_nghttp2_submit_push_promise(void) {
4023 nghttp2_session *session;
4024 nghttp2_session_callbacks callbacks;
4026 nghttp2_stream *stream;
4028 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4029 callbacks.send_callback = null_send_callback;
4030 callbacks.on_frame_send_callback = on_frame_send_callback;
4031 callbacks.on_frame_not_send_callback = on_frame_not_send_callback;
4033 CU_ASSERT(0 == nghttp2_session_server_new(&session, &callbacks, &ud));
4034 nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
4035 &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL);
4036 CU_ASSERT(2 == nghttp2_submit_push_promise(session, NGHTTP2_FLAG_NONE, 1,
4037 reqnv, ARRLEN(reqnv), &ud));
4039 ud.frame_send_cb_called = 0;
4040 ud.sent_frame_type = 0;
4041 CU_ASSERT(0 == nghttp2_session_send(session));
4042 CU_ASSERT(1 == ud.frame_send_cb_called);
4043 CU_ASSERT(NGHTTP2_PUSH_PROMISE == ud.sent_frame_type);
4044 stream = nghttp2_session_get_stream(session, 2);
4045 CU_ASSERT(NGHTTP2_STREAM_RESERVED == stream->state);
4046 CU_ASSERT(&ud == nghttp2_session_get_stream_user_data(session, 2));
4048 /* submit PUSH_PROMISE while associated stream is not opened */
4049 CU_ASSERT(4 == nghttp2_submit_push_promise(session, NGHTTP2_FLAG_NONE, 3,
4050 reqnv, ARRLEN(reqnv), &ud));
4052 ud.frame_not_send_cb_called = 0;
4054 CU_ASSERT(0 == nghttp2_session_send(session));
4055 CU_ASSERT(1 == ud.frame_not_send_cb_called);
4056 CU_ASSERT(NGHTTP2_PUSH_PROMISE == ud.not_sent_frame_type);
4058 stream = nghttp2_session_get_stream(session, 4);
4060 CU_ASSERT(NULL == stream);
4062 nghttp2_session_del(session);
4065 void test_nghttp2_submit_window_update(void) {
4066 nghttp2_session *session;
4067 nghttp2_session_callbacks callbacks;
4069 nghttp2_outbound_item *item;
4070 nghttp2_stream *stream;
4072 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4073 callbacks.send_callback = null_send_callback;
4075 nghttp2_session_client_new(&session, &callbacks, &ud);
4076 stream = nghttp2_session_open_stream(session, 2, NGHTTP2_STREAM_FLAG_NONE,
4077 &pri_spec_default, NGHTTP2_STREAM_OPENED,
4079 stream->recv_window_size = 4096;
4082 nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 2, 1024));
4083 item = nghttp2_session_get_next_ob_item(session);
4084 CU_ASSERT(NGHTTP2_WINDOW_UPDATE == item->frame.hd.type);
4085 CU_ASSERT(1024 == item->frame.window_update.window_size_increment);
4086 CU_ASSERT(0 == nghttp2_session_send(session));
4087 CU_ASSERT(3072 == stream->recv_window_size);
4090 nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 2, 4096));
4091 item = nghttp2_session_get_next_ob_item(session);
4092 CU_ASSERT(NGHTTP2_WINDOW_UPDATE == item->frame.hd.type);
4093 CU_ASSERT(4096 == item->frame.window_update.window_size_increment);
4094 CU_ASSERT(0 == nghttp2_session_send(session));
4095 CU_ASSERT(0 == stream->recv_window_size);
4098 nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 2, 4096));
4099 item = nghttp2_session_get_next_ob_item(session);
4100 CU_ASSERT(NGHTTP2_WINDOW_UPDATE == item->frame.hd.type);
4101 CU_ASSERT(4096 == item->frame.window_update.window_size_increment);
4102 CU_ASSERT(0 == nghttp2_session_send(session));
4103 CU_ASSERT(0 == stream->recv_window_size);
4106 nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 2, 0));
4107 /* It is ok if stream is closed or does not exist at the call
4110 nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 4, 4096));
4112 nghttp2_session_del(session);
4115 void test_nghttp2_submit_window_update_local_window_size(void) {
4116 nghttp2_session *session;
4117 nghttp2_session_callbacks callbacks;
4118 nghttp2_outbound_item *item;
4119 nghttp2_stream *stream;
4121 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4122 callbacks.send_callback = null_send_callback;
4124 nghttp2_session_client_new(&session, &callbacks, NULL);
4125 stream = nghttp2_session_open_stream(session, 2, NGHTTP2_STREAM_FLAG_NONE,
4126 &pri_spec_default, NGHTTP2_STREAM_OPENED,
4128 stream->recv_window_size = 4096;
4130 CU_ASSERT(0 == nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 2,
4131 stream->recv_window_size + 1));
4132 CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE + 1 == stream->local_window_size);
4133 CU_ASSERT(0 == stream->recv_window_size);
4134 item = nghttp2_session_get_next_ob_item(session);
4135 CU_ASSERT(NGHTTP2_WINDOW_UPDATE == item->frame.hd.type);
4136 CU_ASSERT(4097 == item->frame.window_update.window_size_increment);
4138 CU_ASSERT(0 == nghttp2_session_send(session));
4140 /* Let's decrement local window size */
4141 stream->recv_window_size = 4096;
4142 CU_ASSERT(0 == nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 2,
4143 -stream->local_window_size / 2));
4144 CU_ASSERT(32768 == stream->local_window_size);
4145 CU_ASSERT(-28672 == stream->recv_window_size);
4146 CU_ASSERT(32768 == stream->recv_reduction);
4148 item = nghttp2_session_get_next_ob_item(session);
4149 CU_ASSERT(item == NULL);
4151 /* Increase local window size */
4153 nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 2, 16384));
4154 CU_ASSERT(49152 == stream->local_window_size);
4155 CU_ASSERT(-12288 == stream->recv_window_size);
4156 CU_ASSERT(16384 == stream->recv_reduction);
4157 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
4159 CU_ASSERT(NGHTTP2_ERR_FLOW_CONTROL ==
4160 nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 2,
4161 NGHTTP2_MAX_WINDOW_SIZE));
4163 CU_ASSERT(0 == nghttp2_session_send(session));
4165 /* Check connection-level flow control */
4166 session->recv_window_size = 4096;
4167 CU_ASSERT(0 == nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 0,
4168 session->recv_window_size + 1));
4169 CU_ASSERT(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE + 1 ==
4170 session->local_window_size);
4171 CU_ASSERT(0 == session->recv_window_size);
4172 item = nghttp2_session_get_next_ob_item(session);
4173 CU_ASSERT(NGHTTP2_WINDOW_UPDATE == item->frame.hd.type);
4174 CU_ASSERT(4097 == item->frame.window_update.window_size_increment);
4176 CU_ASSERT(0 == nghttp2_session_send(session));
4178 /* Go decrement part */
4179 session->recv_window_size = 4096;
4180 CU_ASSERT(0 == nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 0,
4181 -session->local_window_size / 2));
4182 CU_ASSERT(32768 == session->local_window_size);
4183 CU_ASSERT(-28672 == session->recv_window_size);
4184 CU_ASSERT(32768 == session->recv_reduction);
4185 item = nghttp2_session_get_next_ob_item(session);
4186 CU_ASSERT(item == NULL);
4188 /* Increase local window size */
4190 nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 0, 16384));
4191 CU_ASSERT(49152 == session->local_window_size);
4192 CU_ASSERT(-12288 == session->recv_window_size);
4193 CU_ASSERT(16384 == session->recv_reduction);
4194 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
4196 CU_ASSERT(NGHTTP2_ERR_FLOW_CONTROL ==
4197 nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 0,
4198 NGHTTP2_MAX_WINDOW_SIZE));
4200 nghttp2_session_del(session);
4203 void test_nghttp2_submit_shutdown_notice(void) {
4204 nghttp2_session *session;
4205 nghttp2_session_callbacks callbacks;
4208 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4209 callbacks.send_callback = null_send_callback;
4210 callbacks.on_frame_send_callback = on_frame_send_callback;
4211 callbacks.on_frame_not_send_callback = on_frame_not_send_callback;
4213 nghttp2_session_server_new(&session, &callbacks, &ud);
4215 CU_ASSERT(0 == nghttp2_submit_shutdown_notice(session));
4217 ud.frame_send_cb_called = 0;
4219 nghttp2_session_send(session);
4221 CU_ASSERT(1 == ud.frame_send_cb_called);
4222 CU_ASSERT(NGHTTP2_GOAWAY == ud.sent_frame_type);
4223 CU_ASSERT((1u << 31) - 1 == session->local_last_stream_id);
4225 /* After another GOAWAY, nghttp2_submit_shutdown_notice() is
4227 CU_ASSERT(0 == nghttp2_session_terminate_session(session, NGHTTP2_NO_ERROR));
4229 ud.frame_send_cb_called = 0;
4231 nghttp2_session_send(session);
4233 CU_ASSERT(1 == ud.frame_send_cb_called);
4234 CU_ASSERT(NGHTTP2_GOAWAY == ud.sent_frame_type);
4235 CU_ASSERT(0 == session->local_last_stream_id);
4237 CU_ASSERT(0 == nghttp2_submit_shutdown_notice(session));
4239 ud.frame_send_cb_called = 0;
4240 ud.frame_not_send_cb_called = 0;
4242 nghttp2_session_send(session);
4244 CU_ASSERT(0 == ud.frame_send_cb_called);
4245 CU_ASSERT(0 == ud.frame_not_send_cb_called);
4247 nghttp2_session_del(session);
4249 /* Using nghttp2_submit_shutdown_notice() with client side session
4251 nghttp2_session_client_new(&session, &callbacks, NULL);
4253 CU_ASSERT(NGHTTP2_ERR_INVALID_STATE ==
4254 nghttp2_submit_shutdown_notice(session));
4256 nghttp2_session_del(session);
4259 void test_nghttp2_submit_invalid_nv(void) {
4260 nghttp2_session *session;
4261 nghttp2_session_callbacks callbacks;
4262 nghttp2_nv empty_name_nv[] = {MAKE_NV("Version", "HTTP/1.1"),
4263 MAKE_NV("", "empty name")};
4265 /* Now invalid header name/value pair in HTTP/1.1 is accepted in
4268 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4270 CU_ASSERT(0 == nghttp2_session_server_new(&session, &callbacks, NULL));
4272 /* nghttp2_submit_request */
4273 CU_ASSERT(0 < nghttp2_submit_request(session, NULL, empty_name_nv,
4274 ARRLEN(empty_name_nv), NULL, NULL));
4276 /* nghttp2_submit_response */
4277 CU_ASSERT(0 == nghttp2_submit_response(session, 2, empty_name_nv,
4278 ARRLEN(empty_name_nv), NULL));
4280 /* nghttp2_submit_headers */
4281 CU_ASSERT(0 < nghttp2_submit_headers(session, NGHTTP2_FLAG_NONE, -1, NULL,
4282 empty_name_nv, ARRLEN(empty_name_nv),
4285 /* nghttp2_submit_push_promise */
4286 open_stream(session, 1);
4288 CU_ASSERT(0 < nghttp2_submit_push_promise(session, NGHTTP2_FLAG_NONE, 1,
4290 ARRLEN(empty_name_nv), NULL));
4292 nghttp2_session_del(session);
4295 void test_nghttp2_session_open_stream(void) {
4296 nghttp2_session *session;
4297 nghttp2_session_callbacks callbacks;
4298 nghttp2_stream *stream;
4299 nghttp2_priority_spec pri_spec;
4301 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4302 nghttp2_session_server_new(&session, &callbacks, NULL);
4304 nghttp2_priority_spec_init(&pri_spec, 0, 245, 0);
4306 stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
4307 &pri_spec, NGHTTP2_STREAM_OPENED, NULL);
4308 CU_ASSERT(1 == session->num_incoming_streams);
4309 CU_ASSERT(0 == session->num_outgoing_streams);
4310 CU_ASSERT(NGHTTP2_STREAM_OPENED == stream->state);
4311 CU_ASSERT(245 == stream->weight);
4312 CU_ASSERT(NULL == stream->dep_prev);
4313 CU_ASSERT(NGHTTP2_SHUT_NONE == stream->shut_flags);
4315 stream = nghttp2_session_open_stream(session, 2, NGHTTP2_STREAM_FLAG_NONE,
4317 NGHTTP2_STREAM_OPENING, NULL);
4318 CU_ASSERT(1 == session->num_incoming_streams);
4319 CU_ASSERT(1 == session->num_outgoing_streams);
4320 CU_ASSERT(NULL == stream->dep_prev);
4321 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == stream->weight);
4322 CU_ASSERT(NGHTTP2_SHUT_NONE == stream->shut_flags);
4324 stream = nghttp2_session_open_stream(session, 4, NGHTTP2_STREAM_FLAG_NONE,
4326 NGHTTP2_STREAM_RESERVED, NULL);
4327 CU_ASSERT(1 == session->num_incoming_streams);
4328 CU_ASSERT(1 == session->num_outgoing_streams);
4329 CU_ASSERT(NULL == stream->dep_prev);
4330 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == stream->weight);
4331 CU_ASSERT(NGHTTP2_SHUT_RD == stream->shut_flags);
4333 nghttp2_priority_spec_init(&pri_spec, 1, 17, 1);
4335 stream = nghttp2_session_open_stream(session, 3, NGHTTP2_STREAM_FLAG_NONE,
4336 &pri_spec, NGHTTP2_STREAM_OPENED, NULL);
4337 CU_ASSERT(17 == stream->weight);
4338 CU_ASSERT(1 == stream->dep_prev->stream_id);
4340 /* Dependency to idle stream */
4341 nghttp2_priority_spec_init(&pri_spec, 1000000007, 240, 1);
4343 stream = nghttp2_session_open_stream(session, 5, NGHTTP2_STREAM_FLAG_NONE,
4344 &pri_spec, NGHTTP2_STREAM_OPENED, NULL);
4345 CU_ASSERT(240 == stream->weight);
4346 CU_ASSERT(1000000007 == stream->dep_prev->stream_id);
4348 stream = nghttp2_session_get_stream_raw(session, 1000000007);
4350 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == stream->weight);
4351 CU_ASSERT(NULL != stream->root_next);
4353 /* Dependency to closed stream which is not in dependency tree */
4354 session->last_recv_stream_id = 7;
4356 nghttp2_priority_spec_init(&pri_spec, 7, 10, 0);
4358 stream = nghttp2_session_open_stream(session, 9, NGHTTP2_FLAG_NONE, &pri_spec,
4359 NGHTTP2_STREAM_OPENED, NULL);
4361 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == stream->weight);
4363 nghttp2_session_del(session);
4365 nghttp2_session_client_new(&session, &callbacks, NULL);
4366 stream = nghttp2_session_open_stream(session, 4, NGHTTP2_STREAM_FLAG_NONE,
4368 NGHTTP2_STREAM_RESERVED, NULL);
4369 CU_ASSERT(0 == session->num_incoming_streams);
4370 CU_ASSERT(0 == session->num_outgoing_streams);
4371 CU_ASSERT(NULL == stream->dep_prev);
4372 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == stream->weight);
4373 CU_ASSERT(NGHTTP2_SHUT_WR == stream->shut_flags);
4375 nghttp2_session_del(session);
4378 void test_nghttp2_session_open_stream_with_idle_stream_dep(void) {
4379 nghttp2_session *session;
4380 nghttp2_session_callbacks callbacks;
4381 nghttp2_stream *stream;
4382 nghttp2_priority_spec pri_spec;
4384 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4385 nghttp2_session_server_new(&session, &callbacks, NULL);
4387 /* Dependency to idle stream */
4388 nghttp2_priority_spec_init(&pri_spec, 101, 245, 0);
4390 stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
4391 &pri_spec, NGHTTP2_STREAM_OPENED, NULL);
4393 CU_ASSERT(245 == stream->weight);
4394 CU_ASSERT(101 == stream->dep_prev->stream_id);
4396 stream = nghttp2_session_get_stream_raw(session, 101);
4398 CU_ASSERT(NGHTTP2_STREAM_IDLE == stream->state);
4399 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == stream->weight);
4401 nghttp2_priority_spec_init(&pri_spec, 211, 1, 0);
4403 /* stream 101 was already created as idle. */
4404 stream = nghttp2_session_open_stream(session, 101, NGHTTP2_STREAM_FLAG_NONE,
4405 &pri_spec, NGHTTP2_STREAM_OPENED, NULL);
4407 CU_ASSERT(1 == stream->weight);
4408 CU_ASSERT(211 == stream->dep_prev->stream_id);
4410 stream = nghttp2_session_get_stream_raw(session, 211);
4412 CU_ASSERT(NGHTTP2_STREAM_IDLE == stream->state);
4413 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == stream->weight);
4415 nghttp2_session_del(session);
4418 void test_nghttp2_session_get_next_ob_item(void) {
4419 nghttp2_session *session;
4420 nghttp2_session_callbacks callbacks;
4421 nghttp2_priority_spec pri_spec;
4423 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4424 callbacks.send_callback = null_send_callback;
4426 nghttp2_session_server_new(&session, &callbacks, NULL);
4427 session->remote_settings.max_concurrent_streams = 2;
4429 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
4430 nghttp2_submit_ping(session, NGHTTP2_FLAG_NONE, NULL);
4431 CU_ASSERT(NGHTTP2_PING ==
4432 nghttp2_session_get_next_ob_item(session)->frame.hd.type);
4434 nghttp2_submit_request(session, NULL, NULL, 0, NULL, NULL);
4435 CU_ASSERT(NGHTTP2_PING ==
4436 nghttp2_session_get_next_ob_item(session)->frame.hd.type);
4438 CU_ASSERT(0 == nghttp2_session_send(session));
4439 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
4441 /* Incoming stream does not affect the number of outgoing max
4442 concurrent streams. */
4443 nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
4444 &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL);
4446 nghttp2_priority_spec_init(&pri_spec, 0, NGHTTP2_MAX_WEIGHT, 0);
4448 nghttp2_submit_request(session, &pri_spec, NULL, 0, NULL, NULL);
4449 CU_ASSERT(NGHTTP2_HEADERS ==
4450 nghttp2_session_get_next_ob_item(session)->frame.hd.type);
4451 CU_ASSERT(0 == nghttp2_session_send(session));
4453 nghttp2_submit_request(session, &pri_spec, NULL, 0, NULL, NULL);
4454 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
4456 session->remote_settings.max_concurrent_streams = 3;
4458 CU_ASSERT(NGHTTP2_HEADERS ==
4459 nghttp2_session_get_next_ob_item(session)->frame.hd.type);
4461 nghttp2_session_del(session);
4464 void test_nghttp2_session_pop_next_ob_item(void) {
4465 nghttp2_session *session;
4466 nghttp2_session_callbacks callbacks;
4467 nghttp2_outbound_item *item;
4468 nghttp2_priority_spec pri_spec;
4469 nghttp2_stream *stream;
4472 mem = nghttp2_mem_default();
4473 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4474 callbacks.send_callback = null_send_callback;
4476 nghttp2_session_server_new(&session, &callbacks, NULL);
4477 session->remote_settings.max_concurrent_streams = 1;
4479 CU_ASSERT(NULL == nghttp2_session_pop_next_ob_item(session));
4481 nghttp2_submit_ping(session, NGHTTP2_FLAG_NONE, NULL);
4483 nghttp2_priority_spec_init(&pri_spec, 0, 254, 0);
4485 nghttp2_submit_request(session, &pri_spec, NULL, 0, NULL, NULL);
4487 item = nghttp2_session_pop_next_ob_item(session);
4488 CU_ASSERT(NGHTTP2_PING == item->frame.hd.type);
4489 nghttp2_outbound_item_free(item, mem);
4490 mem->free(item, NULL);
4492 item = nghttp2_session_pop_next_ob_item(session);
4493 CU_ASSERT(NGHTTP2_HEADERS == item->frame.hd.type);
4494 nghttp2_outbound_item_free(item, mem);
4495 mem->free(item, NULL);
4497 CU_ASSERT(NULL == nghttp2_session_pop_next_ob_item(session));
4499 /* Incoming stream does not affect the number of outgoing max
4500 concurrent streams. */
4501 nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
4502 &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL);
4503 /* In-flight outgoing stream */
4504 nghttp2_session_open_stream(session, 4, NGHTTP2_STREAM_FLAG_NONE,
4505 &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL);
4507 nghttp2_priority_spec_init(&pri_spec, 0, NGHTTP2_MAX_WEIGHT, 0);
4509 nghttp2_submit_request(session, &pri_spec, NULL, 0, NULL, NULL);
4510 nghttp2_submit_response(session, 1, NULL, 0, NULL);
4512 item = nghttp2_session_pop_next_ob_item(session);
4513 CU_ASSERT(NGHTTP2_HEADERS == item->frame.hd.type);
4514 CU_ASSERT(1 == item->frame.hd.stream_id);
4516 stream = nghttp2_session_get_stream(session, 1);
4518 nghttp2_stream_detach_item(stream, session);
4520 nghttp2_outbound_item_free(item, mem);
4521 mem->free(item, NULL);
4523 CU_ASSERT(NULL == nghttp2_session_pop_next_ob_item(session));
4525 session->remote_settings.max_concurrent_streams = 2;
4527 item = nghttp2_session_pop_next_ob_item(session);
4528 CU_ASSERT(NGHTTP2_HEADERS == item->frame.hd.type);
4529 nghttp2_outbound_item_free(item, mem);
4530 mem->free(item, NULL);
4532 nghttp2_session_del(session);
4534 /* Check that push reply HEADERS are queued into ob_ss_pq */
4535 nghttp2_session_server_new(&session, &callbacks, NULL);
4536 session->remote_settings.max_concurrent_streams = 0;
4537 nghttp2_session_open_stream(session, 2, NGHTTP2_STREAM_FLAG_NONE,
4538 &pri_spec_default, NGHTTP2_STREAM_RESERVED, NULL);
4539 CU_ASSERT(0 == nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, 2,
4540 NULL, NULL, 0, NULL));
4541 CU_ASSERT(NULL == nghttp2_session_pop_next_ob_item(session));
4542 CU_ASSERT(1 == nghttp2_outbound_queue_size(&session->ob_syn));
4543 nghttp2_session_del(session);
4546 void test_nghttp2_session_reply_fail(void) {
4547 nghttp2_session *session;
4548 nghttp2_session_callbacks callbacks;
4549 nghttp2_data_provider data_prd;
4552 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4553 callbacks.send_callback = fail_send_callback;
4555 data_prd.read_callback = fixed_length_data_source_read_callback;
4556 ud.data_source_length = 4 * 1024;
4557 CU_ASSERT(0 == nghttp2_session_server_new(&session, &callbacks, &ud));
4558 nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
4559 &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL);
4560 CU_ASSERT(0 == nghttp2_submit_response(session, 1, NULL, 0, &data_prd));
4561 CU_ASSERT(NGHTTP2_ERR_CALLBACK_FAILURE == nghttp2_session_send(session));
4562 nghttp2_session_del(session);
4565 void test_nghttp2_session_max_concurrent_streams(void) {
4566 nghttp2_session *session;
4567 nghttp2_session_callbacks callbacks;
4568 nghttp2_frame frame;
4569 nghttp2_outbound_item *item;
4572 mem = nghttp2_mem_default();
4573 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4574 callbacks.send_callback = null_send_callback;
4576 nghttp2_session_server_new(&session, &callbacks, NULL);
4577 nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
4578 &pri_spec_default, NGHTTP2_STREAM_OPENED, NULL);
4580 /* Check un-ACKed SETTINGS_MAX_CONCURRENT_STREAMS */
4581 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 3,
4582 NGHTTP2_HCAT_HEADERS, NULL, NULL, 0);
4583 session->pending_local_max_concurrent_stream = 1;
4585 CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
4586 nghttp2_session_on_request_headers_received(session, &frame));
4588 item = nghttp2_outbound_queue_top(&session->ob_reg);
4589 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
4590 CU_ASSERT(NGHTTP2_REFUSED_STREAM == item->frame.rst_stream.error_code);
4592 CU_ASSERT(0 == nghttp2_session_send(session));
4594 /* Check ACKed SETTINGS_MAX_CONCURRENT_STREAMS */
4595 session->local_settings.max_concurrent_streams = 1;
4596 frame.hd.stream_id = 5;
4598 CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
4599 nghttp2_session_on_request_headers_received(session, &frame));
4601 item = nghttp2_outbound_queue_top(&session->ob_reg);
4602 CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
4603 CU_ASSERT(NGHTTP2_PROTOCOL_ERROR == item->frame.goaway.error_code);
4605 nghttp2_frame_headers_free(&frame.headers, mem);
4606 nghttp2_session_del(session);
4610 * Check that on_stream_close_callback is called when server pushed
4611 * HEADERS have NGHTTP2_FLAG_END_STREAM.
4613 void test_nghttp2_session_stream_close_on_headers_push(void) {
4614 /* nghttp2_session *session; */
4615 /* nghttp2_session_callbacks callbacks; */
4616 /* const char *nv[] = { NULL }; */
4617 /* my_user_data ud; */
4618 /* nghttp2_frame frame; */
4620 /* memset(&callbacks, 0, sizeof(nghttp2_session_callbacks)); */
4621 /* callbacks.on_stream_close_callback = */
4622 /* no_stream_user_data_stream_close_callback; */
4623 /* ud.stream_close_cb_called = 0; */
4625 /* nghttp2_session_client_new(&session, NGHTTP2_PROTO_SPDY2, &callbacks, &ud);
4627 /* nghttp2_session_open_stream(session, 1, NGHTTP2_CTRL_FLAG_NONE, 3, */
4628 /* NGHTTP2_STREAM_OPENING, NULL); */
4629 /* nghttp2_frame_syn_stream_init(&frame.syn_stream, NGHTTP2_PROTO_SPDY2, */
4630 /* NGHTTP2_CTRL_FLAG_FIN | */
4631 /* NGHTTP2_CTRL_FLAG_UNIDIRECTIONAL, */
4632 /* 2, 1, 3, dup_nv(nv)); */
4634 /* CU_ASSERT(0 == nghttp2_session_on_request_headers_received(session,
4637 /* nghttp2_frame_syn_stream_free(&frame.syn_stream); */
4638 /* nghttp2_session_del(session); */
4641 void test_nghttp2_session_stop_data_with_rst_stream(void) {
4642 nghttp2_session *session;
4643 nghttp2_session_callbacks callbacks;
4645 nghttp2_data_provider data_prd;
4646 nghttp2_frame frame;
4648 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4649 callbacks.on_frame_send_callback = on_frame_send_callback;
4650 callbacks.send_callback = block_count_send_callback;
4651 data_prd.read_callback = fixed_length_data_source_read_callback;
4653 ud.frame_send_cb_called = 0;
4654 ud.data_source_length = NGHTTP2_DATA_PAYLOADLEN * 4;
4656 nghttp2_session_server_new(&session, &callbacks, &ud);
4657 nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
4658 &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL);
4659 nghttp2_submit_response(session, 1, NULL, 0, &data_prd);
4662 /* Sends response HEADERS + DATA[0] */
4663 CU_ASSERT(0 == nghttp2_session_send(session));
4664 CU_ASSERT(NGHTTP2_DATA == ud.sent_frame_type);
4665 /* data for DATA[1] is read from data_prd but it is not sent */
4666 CU_ASSERT(ud.data_source_length == NGHTTP2_DATA_PAYLOADLEN * 2);
4668 nghttp2_frame_rst_stream_init(&frame.rst_stream, 1, NGHTTP2_CANCEL);
4669 CU_ASSERT(0 == nghttp2_session_on_rst_stream_received(session, &frame));
4670 nghttp2_frame_rst_stream_free(&frame.rst_stream);
4672 /* Big enough number to send all DATA frames potentially. */
4673 ud.block_count = 100;
4674 /* Nothing will be sent in the following call. */
4675 CU_ASSERT(0 == nghttp2_session_send(session));
4676 /* With RST_STREAM, stream is canceled and further DATA on that
4677 stream are not sent. */
4678 CU_ASSERT(ud.data_source_length == NGHTTP2_DATA_PAYLOADLEN * 2);
4680 CU_ASSERT(NULL == nghttp2_session_get_stream(session, 1));
4682 nghttp2_session_del(session);
4685 void test_nghttp2_session_defer_data(void) {
4686 nghttp2_session *session;
4687 nghttp2_session_callbacks callbacks;
4689 nghttp2_data_provider data_prd;
4690 nghttp2_outbound_item *item;
4691 nghttp2_stream *stream;
4693 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4694 callbacks.on_frame_send_callback = on_frame_send_callback;
4695 callbacks.send_callback = block_count_send_callback;
4696 data_prd.read_callback = defer_data_source_read_callback;
4698 ud.frame_send_cb_called = 0;
4699 ud.data_source_length = NGHTTP2_DATA_PAYLOADLEN * 4;
4701 nghttp2_session_server_new(&session, &callbacks, &ud);
4702 stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
4704 NGHTTP2_STREAM_OPENING, NULL);
4706 session->remote_window_size = 1 << 20;
4707 stream->remote_window_size = 1 << 20;
4709 nghttp2_submit_response(session, 1, NULL, 0, &data_prd);
4712 /* Sends HEADERS reply */
4713 CU_ASSERT(0 == nghttp2_session_send(session));
4714 CU_ASSERT(NGHTTP2_HEADERS == ud.sent_frame_type);
4715 /* No data is read */
4716 CU_ASSERT(ud.data_source_length == NGHTTP2_DATA_PAYLOADLEN * 4);
4719 nghttp2_submit_ping(session, NGHTTP2_FLAG_NONE, NULL);
4721 CU_ASSERT(0 == nghttp2_session_send(session));
4722 CU_ASSERT(NGHTTP2_PING == ud.sent_frame_type);
4724 /* Resume deferred DATA */
4725 CU_ASSERT(0 == nghttp2_session_resume_data(session, 1));
4726 item = (nghttp2_outbound_item *)nghttp2_pq_top(&session->ob_da_pq);
4727 item->aux_data.data.data_prd.read_callback =
4728 fixed_length_data_source_read_callback;
4730 /* Reads 2 DATA chunks */
4731 CU_ASSERT(0 == nghttp2_session_send(session));
4732 CU_ASSERT(ud.data_source_length == NGHTTP2_DATA_PAYLOADLEN * 2);
4734 /* Deferred again */
4735 item->aux_data.data.data_prd.read_callback = defer_data_source_read_callback;
4736 /* This is needed since 16KiB block is already read and waiting to be
4737 sent. No read_callback invocation. */
4739 CU_ASSERT(0 == nghttp2_session_send(session));
4740 CU_ASSERT(ud.data_source_length == NGHTTP2_DATA_PAYLOADLEN * 2);
4742 /* Resume deferred DATA */
4743 CU_ASSERT(0 == nghttp2_session_resume_data(session, 1));
4744 item = (nghttp2_outbound_item *)nghttp2_pq_top(&session->ob_da_pq);
4745 item->aux_data.data.data_prd.read_callback =
4746 fixed_length_data_source_read_callback;
4748 /* Reads 2 16KiB blocks */
4749 CU_ASSERT(0 == nghttp2_session_send(session));
4750 CU_ASSERT(ud.data_source_length == 0);
4752 nghttp2_session_del(session);
4755 void test_nghttp2_session_flow_control(void) {
4756 nghttp2_session *session;
4757 nghttp2_session_callbacks callbacks;
4759 nghttp2_data_provider data_prd;
4760 nghttp2_frame frame;
4761 nghttp2_stream *stream;
4762 int32_t new_initial_window_size;
4763 nghttp2_settings_entry iv[1];
4764 nghttp2_frame settings_frame;
4767 mem = nghttp2_mem_default();
4768 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4769 callbacks.send_callback = fixed_bytes_send_callback;
4770 callbacks.on_frame_send_callback = on_frame_send_callback;
4771 data_prd.read_callback = fixed_length_data_source_read_callback;
4773 ud.frame_send_cb_called = 0;
4774 ud.data_source_length = 128 * 1024;
4775 /* Use smaller emission count so that we can check outbound flow
4776 control window calculation is correct. */
4777 ud.fixed_sendlen = 2 * 1024;
4779 /* Initial window size to 64KiB - 1*/
4780 nghttp2_session_client_new(&session, &callbacks, &ud);
4781 /* Change it to 64KiB for easy calculation */
4782 session->remote_window_size = 64 * 1024;
4783 session->remote_settings.initial_window_size = 64 * 1024;
4785 nghttp2_submit_request(session, NULL, NULL, 0, &data_prd, NULL);
4787 /* Sends 64KiB - 1 data */
4788 CU_ASSERT(0 == nghttp2_session_send(session));
4789 CU_ASSERT(64 * 1024 == ud.data_source_length);
4791 /* Back 32KiB in stream window */
4792 nghttp2_frame_window_update_init(&frame.window_update, NGHTTP2_FLAG_NONE, 1,
4794 nghttp2_session_on_window_update_received(session, &frame);
4796 /* Send nothing because of connection-level window */
4797 CU_ASSERT(0 == nghttp2_session_send(session));
4798 CU_ASSERT(64 * 1024 == ud.data_source_length);
4800 /* Back 32KiB in connection-level window */
4801 frame.hd.stream_id = 0;
4802 nghttp2_session_on_window_update_received(session, &frame);
4804 /* Sends another 32KiB data */
4805 CU_ASSERT(0 == nghttp2_session_send(session));
4806 CU_ASSERT(32 * 1024 == ud.data_source_length);
4808 stream = nghttp2_session_get_stream(session, 1);
4809 /* Change initial window size to 16KiB. The window_size becomes
4811 new_initial_window_size = 16 * 1024;
4812 stream->remote_window_size =
4813 new_initial_window_size - (session->remote_settings.initial_window_size -
4814 stream->remote_window_size);
4815 session->remote_settings.initial_window_size = new_initial_window_size;
4816 CU_ASSERT(-48 * 1024 == stream->remote_window_size);
4818 /* Back 48KiB to stream window */
4819 frame.hd.stream_id = 1;
4820 frame.window_update.window_size_increment = 48 * 1024;
4821 nghttp2_session_on_window_update_received(session, &frame);
4823 /* Nothing is sent because window_size is 0 */
4824 CU_ASSERT(0 == nghttp2_session_send(session));
4825 CU_ASSERT(32 * 1024 == ud.data_source_length);
4827 /* Back 16KiB in stream window */
4828 frame.hd.stream_id = 1;
4829 frame.window_update.window_size_increment = 16 * 1024;
4830 nghttp2_session_on_window_update_received(session, &frame);
4832 /* Back 24KiB in connection-level window */
4833 frame.hd.stream_id = 0;
4834 frame.window_update.window_size_increment = 24 * 1024;
4835 nghttp2_session_on_window_update_received(session, &frame);
4837 /* Sends another 16KiB data */
4838 CU_ASSERT(0 == nghttp2_session_send(session));
4839 CU_ASSERT(16 * 1024 == ud.data_source_length);
4841 /* Increase initial window size to 32KiB */
4842 iv[0].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
4843 iv[0].value = 32 * 1024;
4845 nghttp2_frame_settings_init(&settings_frame.settings, NGHTTP2_FLAG_NONE,
4847 nghttp2_session_on_settings_received(session, &settings_frame, 1);
4848 nghttp2_frame_settings_free(&settings_frame.settings, mem);
4850 /* Sends another 8KiB data */
4851 CU_ASSERT(0 == nghttp2_session_send(session));
4852 CU_ASSERT(8 * 1024 == ud.data_source_length);
4854 /* Back 8KiB in connection-level window */
4855 frame.hd.stream_id = 0;
4856 frame.window_update.window_size_increment = 8 * 1024;
4857 nghttp2_session_on_window_update_received(session, &frame);
4859 /* Sends last 8KiB data */
4860 CU_ASSERT(0 == nghttp2_session_send(session));
4861 CU_ASSERT(0 == ud.data_source_length);
4862 CU_ASSERT(nghttp2_session_get_stream(session, 1)->shut_flags &
4865 nghttp2_frame_window_update_free(&frame.window_update);
4866 nghttp2_session_del(session);
4869 void test_nghttp2_session_flow_control_data_recv(void) {
4870 nghttp2_session *session;
4871 nghttp2_session_callbacks callbacks;
4872 uint8_t data[64 * 1024 + 16];
4873 nghttp2_frame_hd hd;
4874 nghttp2_outbound_item *item;
4875 nghttp2_stream *stream;
4877 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4878 callbacks.send_callback = null_send_callback;
4880 /* Initial window size to 64KiB - 1*/
4881 nghttp2_session_client_new(&session, &callbacks, NULL);
4883 stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
4884 &pri_spec_default, NGHTTP2_STREAM_OPENED,
4887 session->next_stream_id = 3;
4889 nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_WR);
4891 session->local_window_size = NGHTTP2_MAX_PAYLOADLEN;
4892 stream->local_window_size = NGHTTP2_MAX_PAYLOADLEN;
4894 /* Create DATA frame */
4895 memset(data, 0, sizeof(data));
4896 nghttp2_frame_hd_init(&hd, NGHTTP2_MAX_PAYLOADLEN, NGHTTP2_DATA,
4897 NGHTTP2_FLAG_END_STREAM, 1);
4899 nghttp2_frame_pack_frame_hd(data, &hd);
4900 CU_ASSERT(NGHTTP2_MAX_PAYLOADLEN + NGHTTP2_FRAME_HDLEN ==
4901 nghttp2_session_mem_recv(session, data, NGHTTP2_MAX_PAYLOADLEN +
4902 NGHTTP2_FRAME_HDLEN));
4904 item = nghttp2_session_get_next_ob_item(session);
4905 /* Since this is the last frame, stream-level WINDOW_UPDATE is not
4906 issued, but connection-level is. */
4907 CU_ASSERT(NGHTTP2_WINDOW_UPDATE == item->frame.hd.type);
4908 CU_ASSERT(0 == item->frame.hd.stream_id);
4909 CU_ASSERT(NGHTTP2_MAX_PAYLOADLEN ==
4910 item->frame.window_update.window_size_increment);
4912 CU_ASSERT(0 == nghttp2_session_send(session));
4914 /* Receive DATA for closed stream. They are still subject to under
4915 connection-level flow control, since this situation arises when
4916 RST_STREAM is issued by the remote, but the local side keeps
4917 sending DATA frames. Without calculating connection-level window,
4918 the subsequent flow control gets confused. */
4919 CU_ASSERT(NGHTTP2_MAX_PAYLOADLEN + NGHTTP2_FRAME_HDLEN ==
4920 nghttp2_session_mem_recv(session, data, NGHTTP2_MAX_PAYLOADLEN +
4921 NGHTTP2_FRAME_HDLEN));
4923 item = nghttp2_session_get_next_ob_item(session);
4924 CU_ASSERT(NGHTTP2_WINDOW_UPDATE == item->frame.hd.type);
4925 CU_ASSERT(0 == item->frame.hd.stream_id);
4926 CU_ASSERT(NGHTTP2_MAX_PAYLOADLEN ==
4927 item->frame.window_update.window_size_increment);
4929 nghttp2_session_del(session);
4932 void test_nghttp2_session_flow_control_data_with_padding_recv(void) {
4933 nghttp2_session *session;
4934 nghttp2_session_callbacks callbacks;
4936 nghttp2_frame_hd hd;
4937 nghttp2_stream *stream;
4938 nghttp2_option *option;
4940 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4941 callbacks.send_callback = null_send_callback;
4943 nghttp2_option_new(&option);
4944 /* Disable auto window update so that we can check padding is
4945 consumed automatically */
4946 nghttp2_option_set_no_auto_window_update(option, 1);
4948 /* Initial window size to 64KiB - 1*/
4949 nghttp2_session_client_new2(&session, &callbacks, NULL, option);
4951 nghttp2_option_del(option);
4953 stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
4954 &pri_spec_default, NGHTTP2_STREAM_OPENED,
4957 /* Create DATA frame */
4958 memset(data, 0, sizeof(data));
4959 nghttp2_frame_hd_init(&hd, 357, NGHTTP2_DATA,
4960 NGHTTP2_FLAG_END_STREAM | NGHTTP2_FLAG_PADDED, 1);
4962 nghttp2_frame_pack_frame_hd(data, &hd);
4963 /* Set Pad Length field, which itself is padding */
4964 data[NGHTTP2_FRAME_HDLEN] = 255;
4967 (ssize_t)(NGHTTP2_FRAME_HDLEN + hd.length) ==
4968 nghttp2_session_mem_recv(session, data, NGHTTP2_FRAME_HDLEN + hd.length));
4970 CU_ASSERT((int32_t)hd.length == session->recv_window_size);
4971 CU_ASSERT((int32_t)hd.length == stream->recv_window_size);
4972 CU_ASSERT(256 == session->consumed_size);
4973 CU_ASSERT(256 == stream->consumed_size);
4975 nghttp2_session_del(session);
4978 void test_nghttp2_session_data_read_temporal_failure(void) {
4979 nghttp2_session *session;
4980 nghttp2_session_callbacks callbacks;
4982 nghttp2_data_provider data_prd;
4983 nghttp2_frame frame;
4984 nghttp2_stream *stream;
4985 size_t data_size = 128 * 1024;
4987 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4988 callbacks.send_callback = null_send_callback;
4989 callbacks.on_frame_send_callback = on_frame_send_callback;
4990 data_prd.read_callback = fixed_length_data_source_read_callback;
4992 ud.data_source_length = data_size;
4994 /* Initial window size is 64KiB - 1 */
4995 nghttp2_session_client_new(&session, &callbacks, &ud);
4996 nghttp2_submit_request(session, NULL, NULL, 0, &data_prd, NULL);
4998 /* Sends NGHTTP2_INITIAL_WINDOW_SIZE data, assuming, it is equal to
4999 or smaller than NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE */
5000 CU_ASSERT(0 == nghttp2_session_send(session));
5001 CU_ASSERT(data_size - NGHTTP2_INITIAL_WINDOW_SIZE == ud.data_source_length);
5003 stream = nghttp2_session_get_stream(session, 1);
5004 CU_ASSERT(nghttp2_stream_check_deferred_by_flow_control(stream));
5005 CU_ASSERT(NGHTTP2_DATA == stream->item->frame.hd.type);
5007 stream->item->aux_data.data.data_prd.read_callback =
5008 temporal_failure_data_source_read_callback;
5010 /* Back NGHTTP2_INITIAL_WINDOW_SIZE to both connection-level and
5011 stream-wise window */
5012 nghttp2_frame_window_update_init(&frame.window_update, NGHTTP2_FLAG_NONE, 1,
5013 NGHTTP2_INITIAL_WINDOW_SIZE);
5014 nghttp2_session_on_window_update_received(session, &frame);
5015 frame.hd.stream_id = 0;
5016 nghttp2_session_on_window_update_received(session, &frame);
5017 nghttp2_frame_window_update_free(&frame.window_update);
5019 /* Sending data will fail (soft fail) and treated as stream error */
5020 ud.frame_send_cb_called = 0;
5021 CU_ASSERT(0 == nghttp2_session_send(session));
5022 CU_ASSERT(data_size - NGHTTP2_INITIAL_WINDOW_SIZE == ud.data_source_length);
5024 CU_ASSERT(1 == ud.frame_send_cb_called);
5025 CU_ASSERT(NGHTTP2_RST_STREAM == ud.sent_frame_type);
5027 data_prd.read_callback = fail_data_source_read_callback;
5028 nghttp2_submit_request(session, NULL, NULL, 0, &data_prd, NULL);
5029 /* Sending data will fail (hard fail) and session tear down */
5030 CU_ASSERT(NGHTTP2_ERR_CALLBACK_FAILURE == nghttp2_session_send(session));
5032 nghttp2_session_del(session);
5035 void test_nghttp2_session_on_stream_close(void) {
5036 nghttp2_session *session;
5037 nghttp2_session_callbacks callbacks;
5038 my_user_data user_data;
5039 nghttp2_stream *stream;
5041 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
5042 callbacks.on_stream_close_callback = on_stream_close_callback;
5043 user_data.stream_close_cb_called = 0;
5045 nghttp2_session_client_new(&session, &callbacks, &user_data);
5046 stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
5047 &pri_spec_default, NGHTTP2_STREAM_OPENED,
5049 CU_ASSERT(stream != NULL);
5050 CU_ASSERT(nghttp2_session_close_stream(session, 1, NGHTTP2_NO_ERROR) == 0);
5051 CU_ASSERT(user_data.stream_close_cb_called == 1);
5052 nghttp2_session_del(session);
5055 void test_nghttp2_session_on_ctrl_not_send(void) {
5056 nghttp2_session *session;
5057 nghttp2_session_callbacks callbacks;
5058 my_user_data user_data;
5059 nghttp2_stream *stream;
5061 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
5062 callbacks.on_frame_not_send_callback = on_frame_not_send_callback;
5063 callbacks.send_callback = null_send_callback;
5064 user_data.frame_not_send_cb_called = 0;
5065 user_data.not_sent_frame_type = 0;
5066 user_data.not_sent_error = 0;
5068 nghttp2_session_server_new(&session, &callbacks, &user_data);
5069 stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
5071 NGHTTP2_STREAM_OPENING, &user_data);
5073 /* Check response HEADERS */
5074 /* Send bogus stream ID */
5075 CU_ASSERT(0 == nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, 3,
5076 NULL, NULL, 0, NULL));
5077 CU_ASSERT(0 == nghttp2_session_send(session));
5078 CU_ASSERT(1 == user_data.frame_not_send_cb_called);
5079 CU_ASSERT(NGHTTP2_HEADERS == user_data.not_sent_frame_type);
5080 CU_ASSERT(NGHTTP2_ERR_STREAM_CLOSED == user_data.not_sent_error);
5082 user_data.frame_not_send_cb_called = 0;
5083 /* Shutdown transmission */
5084 stream->shut_flags |= NGHTTP2_SHUT_WR;
5085 CU_ASSERT(0 == nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, 1,
5086 NULL, NULL, 0, NULL));
5087 CU_ASSERT(0 == nghttp2_session_send(session));
5088 CU_ASSERT(1 == user_data.frame_not_send_cb_called);
5089 CU_ASSERT(NGHTTP2_HEADERS == user_data.not_sent_frame_type);
5090 CU_ASSERT(NGHTTP2_ERR_STREAM_SHUT_WR == user_data.not_sent_error);
5092 stream->shut_flags = NGHTTP2_SHUT_NONE;
5093 user_data.frame_not_send_cb_called = 0;
5094 /* Queue RST_STREAM */
5095 CU_ASSERT(0 == nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, 1,
5096 NULL, NULL, 0, NULL));
5097 CU_ASSERT(0 == nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, 1,
5098 NGHTTP2_INTERNAL_ERROR));
5099 CU_ASSERT(0 == nghttp2_session_send(session));
5100 CU_ASSERT(1 == user_data.frame_not_send_cb_called);
5101 CU_ASSERT(NGHTTP2_HEADERS == user_data.not_sent_frame_type);
5102 CU_ASSERT(NGHTTP2_ERR_STREAM_CLOSING == user_data.not_sent_error);
5104 nghttp2_session_del(session);
5106 /* Check request HEADERS */
5107 user_data.frame_not_send_cb_called = 0;
5108 CU_ASSERT(nghttp2_session_client_new(&session, &callbacks, &user_data) == 0);
5109 /* Maximum Stream ID is reached */
5110 session->next_stream_id = (1u << 31) + 1;
5111 CU_ASSERT(NGHTTP2_ERR_STREAM_ID_NOT_AVAILABLE ==
5112 nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, -1, NULL,
5115 user_data.frame_not_send_cb_called = 0;
5116 /* GOAWAY received */
5117 session->goaway_flags |= NGHTTP2_GOAWAY_RECV;
5118 session->next_stream_id = 9;
5120 CU_ASSERT(0 < nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, -1,
5121 NULL, NULL, 0, NULL));
5122 CU_ASSERT(0 == nghttp2_session_send(session));
5123 CU_ASSERT(1 == user_data.frame_not_send_cb_called);
5124 CU_ASSERT(NGHTTP2_HEADERS == user_data.not_sent_frame_type);
5125 CU_ASSERT(NGHTTP2_ERR_START_STREAM_NOT_ALLOWED == user_data.not_sent_error);
5127 nghttp2_session_del(session);
5130 void test_nghttp2_session_get_outbound_queue_size(void) {
5131 nghttp2_session *session;
5132 nghttp2_session_callbacks callbacks;
5134 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
5135 CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, NULL));
5136 CU_ASSERT(0 == nghttp2_session_get_outbound_queue_size(session));
5138 CU_ASSERT(0 == nghttp2_submit_ping(session, NGHTTP2_FLAG_NONE, NULL));
5139 CU_ASSERT(1 == nghttp2_session_get_outbound_queue_size(session));
5141 CU_ASSERT(0 == nghttp2_submit_goaway(session, NGHTTP2_FLAG_NONE, 2,
5142 NGHTTP2_NO_ERROR, NULL, 0));
5143 CU_ASSERT(2 == nghttp2_session_get_outbound_queue_size(session));
5145 nghttp2_session_del(session);
5148 void test_nghttp2_session_get_effective_local_window_size(void) {
5149 nghttp2_session *session;
5150 nghttp2_session_callbacks callbacks;
5151 nghttp2_stream *stream;
5153 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
5154 CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, NULL));
5156 stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
5157 &pri_spec_default, NGHTTP2_STREAM_OPENED,
5160 CU_ASSERT(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE ==
5161 nghttp2_session_get_effective_local_window_size(session));
5162 CU_ASSERT(0 == nghttp2_session_get_effective_recv_data_length(session));
5164 CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE ==
5165 nghttp2_session_get_stream_effective_local_window_size(session, 1));
5167 nghttp2_session_get_stream_effective_recv_data_length(session, 1));
5169 /* Check connection flow control */
5170 session->recv_window_size = 100;
5171 nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 0, 1100);
5173 CU_ASSERT(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE + 1000 ==
5174 nghttp2_session_get_effective_local_window_size(session));
5175 CU_ASSERT(0 == nghttp2_session_get_effective_recv_data_length(session));
5177 nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 0, -50);
5178 /* Now session->recv_window_size = -50 */
5179 CU_ASSERT(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE + 950 ==
5180 nghttp2_session_get_effective_local_window_size(session));
5181 CU_ASSERT(0 == nghttp2_session_get_effective_recv_data_length(session));
5183 session->recv_window_size += 50;
5184 /* Now session->recv_window_size = 0 */
5185 nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 0, 100);
5186 CU_ASSERT(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE + 1050 ==
5187 nghttp2_session_get_effective_local_window_size(session));
5188 CU_ASSERT(50 == nghttp2_session_get_effective_recv_data_length(session));
5190 /* Check stream flow control */
5191 stream->recv_window_size = 100;
5192 nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 1, 1100);
5194 CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE + 1000 ==
5195 nghttp2_session_get_stream_effective_local_window_size(session, 1));
5197 nghttp2_session_get_stream_effective_recv_data_length(session, 1));
5199 nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 1, -50);
5200 /* Now stream->recv_window_size = -50 */
5201 CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE + 950 ==
5202 nghttp2_session_get_stream_effective_local_window_size(session, 1));
5204 nghttp2_session_get_stream_effective_recv_data_length(session, 1));
5206 stream->recv_window_size += 50;
5207 /* Now stream->recv_window_size = 0 */
5208 nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 1, 100);
5209 CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE + 1050 ==
5210 nghttp2_session_get_stream_effective_local_window_size(session, 1));
5212 nghttp2_session_get_stream_effective_recv_data_length(session, 1));
5214 nghttp2_session_del(session);
5217 void test_nghttp2_session_set_option(void) {
5218 nghttp2_session *session;
5219 nghttp2_session_callbacks callbacks;
5220 nghttp2_option *option;
5222 nghttp2_option_new(&option);
5224 nghttp2_option_set_no_auto_window_update(option, 1);
5226 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
5227 nghttp2_session_client_new2(&session, &callbacks, NULL, option);
5229 CU_ASSERT(session->opt_flags & NGHTTP2_OPTMASK_NO_AUTO_WINDOW_UPDATE);
5231 nghttp2_session_del(session);
5233 nghttp2_option_set_peer_max_concurrent_streams(option, 100);
5235 nghttp2_session_client_new2(&session, &callbacks, NULL, option);
5237 CU_ASSERT(100 == session->remote_settings.max_concurrent_streams);
5238 nghttp2_session_del(session);
5240 nghttp2_option_del(option);
5243 void test_nghttp2_session_data_backoff_by_high_pri_frame(void) {
5244 nghttp2_session *session;
5245 nghttp2_session_callbacks callbacks;
5247 nghttp2_data_provider data_prd;
5248 nghttp2_stream *stream;
5250 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
5251 callbacks.send_callback = block_count_send_callback;
5252 callbacks.on_frame_send_callback = on_frame_send_callback;
5253 data_prd.read_callback = fixed_length_data_source_read_callback;
5255 ud.frame_send_cb_called = 0;
5256 ud.data_source_length = NGHTTP2_DATA_PAYLOADLEN * 4;
5258 nghttp2_session_client_new(&session, &callbacks, &ud);
5259 nghttp2_submit_request(session, NULL, NULL, 0, &data_prd, NULL);
5261 session->remote_window_size = 1 << 20;
5264 /* Sends request HEADERS + DATA[0] */
5265 CU_ASSERT(0 == nghttp2_session_send(session));
5267 stream = nghttp2_session_get_stream(session, 1);
5268 stream->remote_window_size = 1 << 20;
5270 CU_ASSERT(NGHTTP2_DATA == ud.sent_frame_type);
5271 /* data for DATA[1] is read from data_prd but it is not sent */
5272 CU_ASSERT(ud.data_source_length == NGHTTP2_DATA_PAYLOADLEN * 2);
5274 nghttp2_submit_ping(session, NGHTTP2_FLAG_NONE, NULL);
5276 /* Sends DATA[1] + PING, PING is interleaved in DATA sequence */
5277 CU_ASSERT(0 == nghttp2_session_send(session));
5278 CU_ASSERT(NGHTTP2_PING == ud.sent_frame_type);
5279 /* data for DATA[2] is read from data_prd but it is not sent */
5280 CU_ASSERT(ud.data_source_length == NGHTTP2_DATA_PAYLOADLEN);
5283 /* Sends DATA[2..3] */
5284 CU_ASSERT(0 == nghttp2_session_send(session));
5286 CU_ASSERT(stream->shut_flags & NGHTTP2_SHUT_WR);
5288 nghttp2_session_del(session);
5291 static void check_session_recv_data_with_padding(nghttp2_bufs *bufs,
5294 nghttp2_session *session;
5296 nghttp2_session_callbacks callbacks;
5300 memset(&callbacks, 0, sizeof(callbacks));
5301 callbacks.on_frame_recv_callback = on_frame_recv_callback;
5302 callbacks.on_data_chunk_recv_callback = on_data_chunk_recv_callback;
5303 nghttp2_session_server_new(&session, &callbacks, &ud);
5305 nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
5306 &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL);
5308 inlen = nghttp2_bufs_remove(bufs, &in);
5310 ud.frame_recv_cb_called = 0;
5311 ud.data_chunk_len = 0;
5313 CU_ASSERT((ssize_t)inlen == nghttp2_session_mem_recv(session, in, inlen));
5315 CU_ASSERT(1 == ud.frame_recv_cb_called);
5316 CU_ASSERT(datalen == ud.data_chunk_len);
5318 mem->free(in, NULL);
5319 nghttp2_session_del(session);
5322 void test_nghttp2_session_pack_data_with_padding(void) {
5323 nghttp2_session *session;
5325 nghttp2_session_callbacks callbacks;
5326 nghttp2_data_provider data_prd;
5327 nghttp2_frame *frame;
5328 size_t datalen = 55;
5331 mem = nghttp2_mem_default();
5333 memset(&callbacks, 0, sizeof(callbacks));
5334 callbacks.send_callback = block_count_send_callback;
5335 callbacks.on_frame_send_callback = on_frame_send_callback;
5336 callbacks.select_padding_callback = select_padding_callback;
5338 data_prd.read_callback = fixed_length_data_source_read_callback;
5340 nghttp2_session_client_new(&session, &callbacks, &ud);
5344 nghttp2_submit_request(session, NULL, NULL, 0, &data_prd, NULL);
5346 ud.data_source_length = datalen;
5348 CU_ASSERT(0 == nghttp2_session_send(session));
5349 CU_ASSERT(NGHTTP2_HEADERS == ud.sent_frame_type);
5351 frame = &session->aob.item->frame;
5353 CU_ASSERT(ud.padlen == frame->data.padlen);
5354 CU_ASSERT(frame->hd.flags & NGHTTP2_FLAG_PADDED);
5356 /* Check reception of this DATA frame */
5357 check_session_recv_data_with_padding(&session->aob.framebufs, datalen, mem);
5359 nghttp2_session_del(session);
5362 void test_nghttp2_session_pack_headers_with_padding(void) {
5363 nghttp2_session *session, *sv_session;
5366 nghttp2_session_callbacks callbacks;
5368 memset(&callbacks, 0, sizeof(callbacks));
5369 callbacks.send_callback = accumulator_send_callback;
5370 callbacks.on_frame_send_callback = on_frame_send_callback;
5371 callbacks.select_padding_callback = select_padding_callback;
5372 callbacks.on_frame_recv_callback = on_frame_recv_callback;
5377 nghttp2_session_client_new(&session, &callbacks, &ud);
5378 nghttp2_session_server_new(&sv_session, &callbacks, &ud);
5382 CU_ASSERT(1 == nghttp2_submit_request(session, NULL, reqnv, ARRLEN(reqnv),
5384 CU_ASSERT(0 == nghttp2_session_send(session));
5386 CU_ASSERT(acc.length < NGHTTP2_MAX_PAYLOADLEN);
5387 ud.frame_recv_cb_called = 0;
5388 CU_ASSERT((ssize_t)acc.length ==
5389 nghttp2_session_mem_recv(sv_session, acc.buf, acc.length));
5390 CU_ASSERT(1 == ud.frame_recv_cb_called);
5391 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(sv_session));
5393 nghttp2_session_del(sv_session);
5394 nghttp2_session_del(session);
5397 void test_nghttp2_pack_settings_payload(void) {
5398 nghttp2_settings_entry iv[2];
5401 nghttp2_settings_entry *resiv;
5405 mem = nghttp2_mem_default();
5407 iv[0].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
5409 iv[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
5412 len = nghttp2_pack_settings_payload(buf, sizeof(buf), iv, 2);
5413 CU_ASSERT(2 * NGHTTP2_FRAME_SETTINGS_ENTRY_LENGTH == len);
5414 CU_ASSERT(0 == nghttp2_frame_unpack_settings_payload2(&resiv, &resniv, buf,
5416 CU_ASSERT(2 == resniv);
5417 CU_ASSERT(NGHTTP2_SETTINGS_HEADER_TABLE_SIZE == resiv[0].settings_id);
5418 CU_ASSERT(1023 == resiv[0].value);
5419 CU_ASSERT(NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE == resiv[1].settings_id);
5420 CU_ASSERT(4095 == resiv[1].value);
5422 mem->free(resiv, NULL);
5424 len = nghttp2_pack_settings_payload(buf, 9 /* too small */, iv, 2);
5425 CU_ASSERT(NGHTTP2_ERR_INSUFF_BUFSIZE == len);
5428 #define check_stream_dep_sib(STREAM, DEP_PREV, DEP_NEXT, SIB_PREV, SIB_NEXT) \
5430 CU_ASSERT(DEP_PREV == STREAM->dep_prev); \
5431 CU_ASSERT(DEP_NEXT == STREAM->dep_next); \
5432 CU_ASSERT(SIB_PREV == STREAM->sib_prev); \
5433 CU_ASSERT(SIB_NEXT == STREAM->sib_next); \
5436 /* nghttp2_stream_dep_add() and its families functions should be
5437 tested in nghttp2_stream_test.c, but it is easier to use
5438 nghttp2_session_open_stream(). Therefore, we test them here. */
5439 void test_nghttp2_session_stream_dep_add(void) {
5440 nghttp2_session *session;
5441 nghttp2_session_callbacks callbacks;
5442 nghttp2_stream *a, *b, *c, *d, *e;
5444 memset(&callbacks, 0, sizeof(callbacks));
5446 nghttp2_session_server_new(&session, &callbacks, NULL);
5448 a = open_stream(session, 1);
5450 c = open_stream_with_dep(session, 5, a);
5451 b = open_stream_with_dep(session, 3, a);
5452 d = open_stream_with_dep(session, 7, c);
5461 CU_ASSERT(4 == a->num_substreams);
5462 CU_ASSERT(1 == b->num_substreams);
5463 CU_ASSERT(2 == c->num_substreams);
5464 CU_ASSERT(1 == d->num_substreams);
5466 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 2 == a->sum_dep_weight);
5467 CU_ASSERT(0 == b->sum_dep_weight);
5468 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == c->sum_dep_weight);
5469 CU_ASSERT(0 == d->sum_dep_weight);
5471 check_stream_dep_sib(a, NULL, b, NULL, NULL);
5472 check_stream_dep_sib(b, a, NULL, NULL, c);
5473 check_stream_dep_sib(c, NULL, d, b, NULL);
5474 check_stream_dep_sib(d, c, NULL, NULL, NULL);
5476 CU_ASSERT(4 == session->roots.num_streams);
5477 CU_ASSERT(a == session->roots.head);
5478 CU_ASSERT(NULL == a->root_next);
5480 e = open_stream_with_dep_excl(session, 9, a);
5491 CU_ASSERT(5 == a->num_substreams);
5492 CU_ASSERT(4 == e->num_substreams);
5493 CU_ASSERT(1 == b->num_substreams);
5494 CU_ASSERT(2 == c->num_substreams);
5495 CU_ASSERT(1 == d->num_substreams);
5497 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == a->sum_dep_weight);
5498 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 2 == e->sum_dep_weight);
5499 CU_ASSERT(0 == b->sum_dep_weight);
5500 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == c->sum_dep_weight);
5501 CU_ASSERT(0 == d->sum_dep_weight);
5503 check_stream_dep_sib(a, NULL, e, NULL, NULL);
5504 check_stream_dep_sib(e, a, b, NULL, NULL);
5505 check_stream_dep_sib(b, e, NULL, NULL, c);
5506 check_stream_dep_sib(c, NULL, d, b, NULL);
5507 check_stream_dep_sib(d, c, NULL, NULL, NULL);
5509 CU_ASSERT(5 == session->roots.num_streams);
5510 CU_ASSERT(a == session->roots.head);
5511 CU_ASSERT(NULL == a->root_next);
5513 nghttp2_session_del(session);
5516 void test_nghttp2_session_stream_dep_remove(void) {
5517 nghttp2_session *session;
5518 nghttp2_session_callbacks callbacks;
5519 nghttp2_stream *a, *b, *c, *d, *e, *f;
5521 memset(&callbacks, 0, sizeof(callbacks));
5524 nghttp2_session_server_new(&session, &callbacks, NULL);
5526 a = open_stream(session, 1);
5527 b = open_stream_with_dep(session, 3, a);
5528 c = open_stream_with_dep(session, 5, a);
5529 d = open_stream_with_dep(session, 7, c);
5538 nghttp2_stream_dep_remove(a);
5546 CU_ASSERT(1 == a->num_substreams);
5547 CU_ASSERT(1 == b->num_substreams);
5548 CU_ASSERT(2 == c->num_substreams);
5549 CU_ASSERT(1 == d->num_substreams);
5551 CU_ASSERT(0 == a->sum_dep_weight);
5552 CU_ASSERT(0 == b->sum_dep_weight);
5553 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == c->sum_dep_weight);
5554 CU_ASSERT(0 == d->sum_dep_weight);
5556 check_stream_dep_sib(a, NULL, NULL, NULL, NULL);
5557 check_stream_dep_sib(b, NULL, NULL, NULL, NULL);
5558 check_stream_dep_sib(c, NULL, d, NULL, NULL);
5559 check_stream_dep_sib(d, c, NULL, NULL, NULL);
5561 CU_ASSERT(3 == session->roots.num_streams);
5562 CU_ASSERT(b == session->roots.head);
5563 CU_ASSERT(c == b->root_next);
5564 CU_ASSERT(NULL == c->root_next);
5566 nghttp2_session_del(session);
5568 /* Remove left most stream */
5569 nghttp2_session_server_new(&session, &callbacks, NULL);
5571 a = open_stream(session, 1);
5572 b = open_stream_with_dep(session, 3, a);
5573 c = open_stream_with_dep(session, 5, a);
5574 d = open_stream_with_dep(session, 7, c);
5583 nghttp2_stream_dep_remove(b);
5593 CU_ASSERT(3 == a->num_substreams);
5594 CU_ASSERT(1 == b->num_substreams);
5595 CU_ASSERT(2 == c->num_substreams);
5596 CU_ASSERT(1 == d->num_substreams);
5598 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == a->sum_dep_weight);
5599 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == c->sum_dep_weight);
5600 CU_ASSERT(0 == d->sum_dep_weight);
5601 CU_ASSERT(0 == b->sum_dep_weight);
5603 check_stream_dep_sib(a, NULL, c, NULL, NULL);
5604 check_stream_dep_sib(b, NULL, NULL, NULL, NULL);
5605 check_stream_dep_sib(c, a, d, NULL, NULL);
5606 check_stream_dep_sib(d, c, NULL, NULL, NULL);
5608 CU_ASSERT(3 == session->roots.num_streams);
5609 CU_ASSERT(a == session->roots.head);
5610 CU_ASSERT(NULL == a->root_next);
5612 nghttp2_session_del(session);
5614 /* Remove right most stream */
5615 nghttp2_session_server_new(&session, &callbacks, NULL);
5617 a = open_stream(session, 1);
5618 b = open_stream_with_dep(session, 3, a);
5619 c = open_stream_with_dep(session, 5, a);
5620 d = open_stream_with_dep(session, 7, c);
5629 nghttp2_stream_dep_remove(c);
5637 CU_ASSERT(3 == a->num_substreams);
5638 CU_ASSERT(1 == b->num_substreams);
5639 CU_ASSERT(1 == c->num_substreams);
5640 CU_ASSERT(1 == d->num_substreams);
5642 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 2 == a->sum_dep_weight);
5643 CU_ASSERT(0 == b->sum_dep_weight);
5644 CU_ASSERT(0 == d->sum_dep_weight);
5645 CU_ASSERT(0 == c->sum_dep_weight);
5647 check_stream_dep_sib(a, NULL, d, NULL, NULL);
5648 check_stream_dep_sib(b, NULL, NULL, d, NULL);
5649 check_stream_dep_sib(c, NULL, NULL, NULL, NULL);
5650 check_stream_dep_sib(d, a, NULL, NULL, b);
5652 nghttp2_session_del(session);
5654 /* Remove middle stream */
5655 nghttp2_session_server_new(&session, &callbacks, NULL);
5657 a = open_stream(session, 1);
5658 b = open_stream_with_dep(session, 3, a);
5659 c = open_stream_with_dep(session, 5, a);
5660 d = open_stream_with_dep(session, 7, a);
5661 e = open_stream_with_dep(session, 9, c);
5662 f = open_stream_with_dep(session, 11, c);
5671 CU_ASSERT(6 == a->num_substreams);
5672 CU_ASSERT(1 == b->num_substreams);
5673 CU_ASSERT(3 == c->num_substreams);
5674 CU_ASSERT(1 == d->num_substreams);
5675 CU_ASSERT(1 == e->num_substreams);
5676 CU_ASSERT(1 == f->num_substreams);
5678 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 3 == a->sum_dep_weight);
5679 CU_ASSERT(0 == b->sum_dep_weight);
5680 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 2 == c->sum_dep_weight);
5681 CU_ASSERT(0 == d->sum_dep_weight);
5682 CU_ASSERT(0 == e->sum_dep_weight);
5683 CU_ASSERT(0 == f->sum_dep_weight);
5685 nghttp2_stream_dep_remove(c);
5693 CU_ASSERT(5 == a->num_substreams);
5694 CU_ASSERT(1 == b->num_substreams);
5695 CU_ASSERT(1 == c->num_substreams);
5696 CU_ASSERT(1 == d->num_substreams);
5697 CU_ASSERT(1 == e->num_substreams);
5698 CU_ASSERT(1 == f->num_substreams);
5700 /* c's weight 16 is distributed evenly to e and f. Each weight of e
5702 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 2 + 8 * 2 == a->sum_dep_weight);
5703 CU_ASSERT(0 == b->sum_dep_weight);
5704 CU_ASSERT(0 == c->sum_dep_weight);
5705 CU_ASSERT(0 == d->sum_dep_weight);
5706 CU_ASSERT(0 == e->sum_dep_weight);
5707 CU_ASSERT(0 == f->sum_dep_weight);
5709 check_stream_dep_sib(a, NULL, d, NULL, NULL);
5710 check_stream_dep_sib(b, NULL, NULL, e, NULL);
5711 check_stream_dep_sib(c, NULL, NULL, NULL, NULL);
5712 check_stream_dep_sib(e, NULL, NULL, f, b);
5713 check_stream_dep_sib(f, NULL, NULL, d, e);
5714 check_stream_dep_sib(d, a, NULL, NULL, f);
5716 nghttp2_session_del(session);
5719 void test_nghttp2_session_stream_dep_add_subtree(void) {
5720 nghttp2_session *session;
5721 nghttp2_session_callbacks callbacks;
5722 nghttp2_stream *a, *b, *c, *d, *e, *f;
5724 memset(&callbacks, 0, sizeof(callbacks));
5726 /* dep_stream has dep_next */
5727 nghttp2_session_server_new(&session, &callbacks, NULL);
5729 a = open_stream(session, 1);
5730 b = open_stream_with_dep(session, 3, a);
5731 c = open_stream_with_dep(session, 5, a);
5732 d = open_stream_with_dep(session, 7, c);
5734 e = open_stream(session, 9);
5735 f = open_stream_with_dep(session, 11, e);
5744 nghttp2_stream_dep_add_subtree(a, e, session);
5754 CU_ASSERT(6 == a->num_substreams);
5755 CU_ASSERT(1 == b->num_substreams);
5756 CU_ASSERT(2 == c->num_substreams);
5757 CU_ASSERT(1 == d->num_substreams);
5758 CU_ASSERT(2 == e->num_substreams);
5759 CU_ASSERT(1 == f->num_substreams);
5761 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 3 == a->sum_dep_weight);
5762 CU_ASSERT(0 == b->sum_dep_weight);
5763 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == c->sum_dep_weight);
5764 CU_ASSERT(0 == d->sum_dep_weight);
5765 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == e->sum_dep_weight);
5766 CU_ASSERT(0 == f->sum_dep_weight);
5768 check_stream_dep_sib(a, NULL, e, NULL, NULL);
5769 check_stream_dep_sib(b, NULL, NULL, c, NULL);
5770 check_stream_dep_sib(c, NULL, d, e, b);
5771 check_stream_dep_sib(d, c, NULL, NULL, NULL);
5772 check_stream_dep_sib(e, a, f, NULL, c);
5773 check_stream_dep_sib(f, e, NULL, NULL, NULL);
5775 nghttp2_session_del(session);
5777 /* dep_stream has dep_next and now we insert subtree */
5778 nghttp2_session_server_new(&session, &callbacks, NULL);
5780 a = open_stream(session, 1);
5781 b = open_stream_with_dep(session, 3, a);
5782 c = open_stream_with_dep(session, 5, a);
5783 d = open_stream_with_dep(session, 7, c);
5785 e = open_stream(session, 9);
5786 f = open_stream_with_dep(session, 11, e);
5795 nghttp2_stream_dep_insert_subtree(a, e, session);
5807 CU_ASSERT(6 == a->num_substreams);
5808 CU_ASSERT(1 == b->num_substreams);
5809 CU_ASSERT(2 == c->num_substreams);
5810 CU_ASSERT(1 == d->num_substreams);
5811 CU_ASSERT(5 == e->num_substreams);
5812 CU_ASSERT(1 == f->num_substreams);
5814 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == a->sum_dep_weight);
5815 CU_ASSERT(0 == b->sum_dep_weight);
5816 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == c->sum_dep_weight);
5817 CU_ASSERT(0 == d->sum_dep_weight);
5818 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 3 == e->sum_dep_weight);
5819 CU_ASSERT(0 == f->sum_dep_weight);
5821 check_stream_dep_sib(a, NULL, e, NULL, NULL);
5822 check_stream_dep_sib(e, a, f, NULL, NULL);
5823 check_stream_dep_sib(f, e, NULL, NULL, c);
5824 check_stream_dep_sib(b, NULL, NULL, c, NULL);
5825 check_stream_dep_sib(c, NULL, d, f, b);
5826 check_stream_dep_sib(d, c, NULL, NULL, NULL);
5828 nghttp2_session_del(session);
5831 void test_nghttp2_session_stream_dep_remove_subtree(void) {
5832 nghttp2_session *session;
5833 nghttp2_session_callbacks callbacks;
5834 nghttp2_stream *a, *b, *c, *d, *e;
5836 memset(&callbacks, 0, sizeof(callbacks));
5838 /* Remove left most stream */
5839 nghttp2_session_server_new(&session, &callbacks, NULL);
5841 a = open_stream(session, 1);
5842 b = open_stream_with_dep(session, 3, a);
5843 c = open_stream_with_dep(session, 5, a);
5844 d = open_stream_with_dep(session, 7, c);
5853 nghttp2_stream_dep_remove_subtree(c);
5861 CU_ASSERT(2 == a->num_substreams);
5862 CU_ASSERT(1 == b->num_substreams);
5863 CU_ASSERT(2 == c->num_substreams);
5864 CU_ASSERT(1 == d->num_substreams);
5866 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == a->sum_dep_weight);
5867 CU_ASSERT(0 == b->sum_dep_weight);
5868 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == c->sum_dep_weight);
5869 CU_ASSERT(0 == d->sum_dep_weight);
5871 check_stream_dep_sib(a, NULL, b, NULL, NULL);
5872 check_stream_dep_sib(b, a, NULL, NULL, NULL);
5873 check_stream_dep_sib(c, NULL, d, NULL, NULL);
5874 check_stream_dep_sib(d, c, NULL, NULL, NULL);
5876 nghttp2_session_del(session);
5878 /* Remove right most stream */
5879 nghttp2_session_server_new(&session, &callbacks, NULL);
5881 a = open_stream(session, 1);
5882 b = open_stream_with_dep(session, 3, a);
5883 c = open_stream_with_dep(session, 5, a);
5884 d = open_stream_with_dep(session, 7, c);
5893 nghttp2_stream_dep_remove_subtree(b);
5903 CU_ASSERT(3 == a->num_substreams);
5904 CU_ASSERT(1 == b->num_substreams);
5905 CU_ASSERT(2 == c->num_substreams);
5906 CU_ASSERT(1 == d->num_substreams);
5908 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == a->sum_dep_weight);
5909 CU_ASSERT(0 == b->sum_dep_weight);
5910 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == c->sum_dep_weight);
5911 CU_ASSERT(0 == d->sum_dep_weight);
5913 check_stream_dep_sib(a, NULL, c, NULL, NULL);
5914 check_stream_dep_sib(c, a, d, NULL, NULL);
5915 check_stream_dep_sib(d, c, NULL, NULL, NULL);
5916 check_stream_dep_sib(b, NULL, NULL, NULL, NULL);
5918 nghttp2_session_del(session);
5920 /* Remove middle stream */
5921 nghttp2_session_server_new(&session, &callbacks, NULL);
5923 a = open_stream(session, 1);
5924 e = open_stream_with_dep(session, 9, a);
5925 c = open_stream_with_dep(session, 5, a);
5926 b = open_stream_with_dep(session, 3, a);
5927 d = open_stream_with_dep(session, 7, c);
5936 nghttp2_stream_dep_remove_subtree(c);
5944 CU_ASSERT(3 == a->num_substreams);
5945 CU_ASSERT(1 == b->num_substreams);
5946 CU_ASSERT(1 == e->num_substreams);
5947 CU_ASSERT(2 == c->num_substreams);
5948 CU_ASSERT(1 == d->num_substreams);
5950 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 2 == a->sum_dep_weight);
5951 CU_ASSERT(0 == b->sum_dep_weight);
5952 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == c->sum_dep_weight);
5953 CU_ASSERT(0 == d->sum_dep_weight);
5954 CU_ASSERT(0 == e->sum_dep_weight);
5956 check_stream_dep_sib(a, NULL, b, NULL, NULL);
5957 check_stream_dep_sib(b, a, NULL, NULL, e);
5958 check_stream_dep_sib(e, NULL, NULL, b, NULL);
5959 check_stream_dep_sib(c, NULL, d, NULL, NULL);
5960 check_stream_dep_sib(d, c, NULL, NULL, NULL);
5962 nghttp2_session_del(session);
5965 void test_nghttp2_session_stream_dep_all_your_stream_are_belong_to_us(void) {
5966 nghttp2_session *session;
5967 nghttp2_session_callbacks callbacks;
5968 nghttp2_stream *a, *b, *c, *d;
5970 memset(&callbacks, 0, sizeof(callbacks));
5972 nghttp2_session_server_new(&session, &callbacks, NULL);
5974 a = open_stream(session, 1);
5975 b = open_stream_with_dep(session, 3, a);
5977 c = open_stream(session, 5);
5984 nghttp2_stream_dep_remove_subtree(c);
5986 nghttp2_stream_dep_all_your_stream_are_belong_to_us(c, session));
5996 CU_ASSERT(3 == c->num_substreams);
5997 CU_ASSERT(2 == a->num_substreams);
5998 CU_ASSERT(1 == b->num_substreams);
6000 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == c->sum_dep_weight);
6001 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == a->sum_dep_weight);
6002 CU_ASSERT(0 == b->sum_dep_weight);
6004 check_stream_dep_sib(c, NULL, a, NULL, NULL);
6005 check_stream_dep_sib(a, c, b, NULL, NULL);
6006 check_stream_dep_sib(b, a, NULL, NULL, NULL);
6008 nghttp2_session_del(session);
6010 nghttp2_session_server_new(&session, &callbacks, NULL);
6012 a = open_stream(session, 1);
6014 b = open_stream(session, 3);
6016 c = open_stream(session, 5);
6022 nghttp2_stream_dep_remove_subtree(c);
6024 nghttp2_stream_dep_all_your_stream_are_belong_to_us(c, session));
6032 CU_ASSERT(3 == c->num_substreams);
6033 CU_ASSERT(1 == a->num_substreams);
6034 CU_ASSERT(1 == b->num_substreams);
6036 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 2 == c->sum_dep_weight);
6037 CU_ASSERT(0 == b->sum_dep_weight);
6038 CU_ASSERT(0 == a->sum_dep_weight);
6040 check_stream_dep_sib(c, NULL, b, NULL, NULL);
6041 check_stream_dep_sib(b, c, NULL, NULL, a);
6042 check_stream_dep_sib(a, NULL, NULL, b, NULL);
6044 nghttp2_session_del(session);
6046 nghttp2_session_server_new(&session, &callbacks, NULL);
6048 a = open_stream(session, 1);
6049 b = open_stream_with_dep(session, 3, a);
6051 c = open_stream(session, 5);
6052 d = open_stream_with_dep(session, 7, c);
6059 nghttp2_stream_dep_remove_subtree(c);
6061 nghttp2_stream_dep_all_your_stream_are_belong_to_us(c, session));
6071 CU_ASSERT(4 == c->num_substreams);
6072 CU_ASSERT(1 == d->num_substreams);
6073 CU_ASSERT(2 == a->num_substreams);
6074 CU_ASSERT(1 == b->num_substreams);
6076 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 2 == c->sum_dep_weight);
6077 CU_ASSERT(0 == d->sum_dep_weight);
6078 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == a->sum_dep_weight);
6079 CU_ASSERT(0 == b->sum_dep_weight);
6081 check_stream_dep_sib(c, NULL, a, NULL, NULL);
6082 check_stream_dep_sib(d, NULL, NULL, a, NULL);
6083 check_stream_dep_sib(a, c, b, NULL, d);
6084 check_stream_dep_sib(b, a, NULL, NULL, NULL);
6086 nghttp2_session_del(session);
6089 void test_nghttp2_session_stream_attach_item(void) {
6090 nghttp2_session *session;
6091 nghttp2_session_callbacks callbacks;
6092 nghttp2_stream *a, *b, *c, *d;
6093 nghttp2_outbound_item *da, *db, *dc, *dd;
6096 mem = nghttp2_mem_default();
6098 memset(&callbacks, 0, sizeof(callbacks));
6100 nghttp2_session_server_new(&session, &callbacks, NULL);
6102 a = open_stream(session, 1);
6103 b = open_stream_with_dep(session, 3, a);
6104 c = open_stream_with_dep(session, 5, a);
6105 d = open_stream_with_dep(session, 7, c);
6114 db = create_data_ob_item(mem);
6116 nghttp2_stream_attach_item(b, db, session);
6118 CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == a->dpri);
6119 CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == b->dpri);
6120 CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == c->dpri);
6121 CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == d->dpri);
6123 CU_ASSERT(16 == b->effective_weight);
6125 CU_ASSERT(16 == a->sum_norest_weight);
6127 CU_ASSERT(1 == db->queued);
6129 dc = create_data_ob_item(mem);
6131 nghttp2_stream_attach_item(c, dc, session);
6133 CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == a->dpri);
6134 CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == b->dpri);
6135 CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == c->dpri);
6136 CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == d->dpri);
6138 CU_ASSERT(16 * 16 / 32 == b->effective_weight);
6139 CU_ASSERT(16 * 16 / 32 == c->effective_weight);
6141 CU_ASSERT(32 == a->sum_norest_weight);
6143 CU_ASSERT(1 == dc->queued);
6145 da = create_data_ob_item(mem);
6147 nghttp2_stream_attach_item(a, da, session);
6149 CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == a->dpri);
6150 CU_ASSERT(NGHTTP2_STREAM_DPRI_REST == b->dpri);
6151 CU_ASSERT(NGHTTP2_STREAM_DPRI_REST == c->dpri);
6152 CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == d->dpri);
6154 CU_ASSERT(16 == a->effective_weight);
6156 CU_ASSERT(1 == da->queued);
6158 nghttp2_stream_detach_item(a, session);
6160 CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == a->dpri);
6161 CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == b->dpri);
6162 CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == c->dpri);
6163 CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == d->dpri);
6165 CU_ASSERT(16 * 16 / 32 == b->effective_weight);
6166 CU_ASSERT(16 * 16 / 32 == c->effective_weight);
6168 dd = create_data_ob_item(mem);
6170 nghttp2_stream_attach_item(d, dd, session);
6172 CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == a->dpri);
6173 CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == b->dpri);
6174 CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == c->dpri);
6175 CU_ASSERT(NGHTTP2_STREAM_DPRI_REST == d->dpri);
6177 CU_ASSERT(16 * 16 / 32 == b->effective_weight);
6178 CU_ASSERT(16 * 16 / 32 == c->effective_weight);
6180 CU_ASSERT(0 == dd->queued);
6182 nghttp2_stream_detach_item(c, session);
6184 CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == a->dpri);
6185 CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == b->dpri);
6186 CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == c->dpri);
6187 CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == d->dpri);
6189 CU_ASSERT(16 * 16 / 32 == b->effective_weight);
6190 CU_ASSERT(16 * 16 / 32 == d->effective_weight);
6192 CU_ASSERT(1 == dd->queued);
6194 nghttp2_stream_detach_item(b, session);
6196 CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == a->dpri);
6197 CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == b->dpri);
6198 CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == c->dpri);
6199 CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == d->dpri);
6201 CU_ASSERT(16 * 16 / 16 == d->effective_weight);
6203 CU_ASSERT(1 == dd->queued);
6205 nghttp2_session_del(session);
6208 void test_nghttp2_session_stream_attach_item_subtree(void) {
6209 nghttp2_session *session;
6210 nghttp2_session_callbacks callbacks;
6211 nghttp2_stream *a, *b, *c, *d, *e, *f;
6212 nghttp2_outbound_item *db, *dd, *de;
6215 mem = nghttp2_mem_default();
6217 memset(&callbacks, 0, sizeof(callbacks));
6219 nghttp2_session_server_new(&session, &callbacks, NULL);
6221 a = open_stream(session, 1);
6222 b = open_stream_with_dep(session, 3, a);
6223 c = open_stream_with_dep(session, 5, a);
6224 d = open_stream_with_dep(session, 7, c);
6226 e = open_stream(session, 9);
6227 f = open_stream_with_dep(session, 11, e);
6236 de = create_data_ob_item(mem);
6238 nghttp2_stream_attach_item(e, de, session);
6240 db = create_data_ob_item(mem);
6242 nghttp2_stream_attach_item(b, db, session);
6244 CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == a->dpri);
6245 CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == b->dpri);
6246 CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == c->dpri);
6247 CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == d->dpri);
6248 CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == e->dpri);
6249 CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == f->dpri);
6251 CU_ASSERT(16 == b->effective_weight);
6252 CU_ASSERT(16 == e->effective_weight);
6254 /* Insert subtree e under a */
6256 nghttp2_stream_dep_remove_subtree(e);
6257 nghttp2_stream_dep_insert_subtree(a, e, session);
6269 CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == a->dpri);
6270 CU_ASSERT(NGHTTP2_STREAM_DPRI_REST == b->dpri);
6271 CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == c->dpri);
6272 CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == d->dpri);
6273 CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == e->dpri);
6274 CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == f->dpri);
6276 CU_ASSERT(16 == e->effective_weight);
6278 /* Remove subtree b */
6280 nghttp2_stream_dep_remove_subtree(b);
6282 nghttp2_stream_dep_make_root(b, session);
6294 CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == a->dpri);
6295 CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == b->dpri);
6296 CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == c->dpri);
6297 CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == d->dpri);
6298 CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == e->dpri);
6299 CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == f->dpri);
6301 CU_ASSERT(16 == b->effective_weight);
6302 CU_ASSERT(16 == e->effective_weight);
6304 /* Remove subtree a */
6306 nghttp2_stream_dep_remove_subtree(a);
6308 nghttp2_stream_dep_make_root(a, session);
6310 CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == a->dpri);
6311 CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == b->dpri);
6312 CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == c->dpri);
6313 CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == d->dpri);
6314 CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == e->dpri);
6315 CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == f->dpri);
6317 /* Remove subtree c */
6319 nghttp2_stream_dep_remove_subtree(c);
6321 nghttp2_stream_dep_make_root(c, session);
6331 CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == a->dpri);
6332 CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == b->dpri);
6333 CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == c->dpri);
6334 CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == d->dpri);
6335 CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == e->dpri);
6336 CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == f->dpri);
6338 dd = create_data_ob_item(mem);
6340 nghttp2_stream_attach_item(d, dd, session);
6342 /* Add subtree c to a */
6344 nghttp2_stream_dep_remove_subtree(c);
6345 nghttp2_stream_dep_add_subtree(a, c, session);
6355 CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == a->dpri);
6356 CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == b->dpri);
6357 CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == c->dpri);
6358 CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == d->dpri);
6359 CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == e->dpri);
6360 CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == f->dpri);
6362 CU_ASSERT(16 == b->effective_weight);
6363 CU_ASSERT(16 * 16 / 32 == e->effective_weight);
6364 CU_ASSERT(16 * 16 / 32 == e->effective_weight);
6366 CU_ASSERT(32 == a->sum_norest_weight);
6367 CU_ASSERT(16 == c->sum_norest_weight);
6369 /* Insert b under a */
6371 nghttp2_stream_dep_remove_subtree(b);
6372 nghttp2_stream_dep_insert_subtree(a, b, session);
6384 CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == a->dpri);
6385 CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == b->dpri);
6386 CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == c->dpri);
6387 CU_ASSERT(NGHTTP2_STREAM_DPRI_REST == d->dpri);
6388 CU_ASSERT(NGHTTP2_STREAM_DPRI_REST == e->dpri);
6389 CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == f->dpri);
6391 CU_ASSERT(16 == b->effective_weight);
6393 CU_ASSERT(16 == a->sum_norest_weight);
6394 CU_ASSERT(0 == b->sum_norest_weight);
6396 /* Remove subtree b */
6398 nghttp2_stream_dep_remove_subtree(b);
6399 nghttp2_stream_dep_make_root(b, session);
6409 CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == a->dpri);
6410 CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == b->dpri);
6411 CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == c->dpri);
6412 CU_ASSERT(NGHTTP2_STREAM_DPRI_REST == d->dpri);
6413 CU_ASSERT(NGHTTP2_STREAM_DPRI_REST == e->dpri);
6414 CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == f->dpri);
6416 CU_ASSERT(0 == a->sum_norest_weight);
6417 CU_ASSERT(0 == b->sum_norest_weight);
6419 nghttp2_session_del(session);
6422 void test_nghttp2_session_keep_closed_stream(void) {
6423 nghttp2_session *session;
6424 nghttp2_session_callbacks callbacks;
6425 const size_t max_concurrent_streams = 5;
6426 nghttp2_settings_entry iv = {NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS,
6427 max_concurrent_streams};
6430 memset(&callbacks, 0, sizeof(callbacks));
6431 callbacks.send_callback = null_send_callback;
6433 nghttp2_session_server_new(&session, &callbacks, NULL);
6435 nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, &iv, 1);
6437 for (i = 0; i < max_concurrent_streams; ++i) {
6438 open_stream(session, (int)i * 2 + 1);
6441 CU_ASSERT(0 == session->num_closed_streams);
6443 nghttp2_session_close_stream(session, 1, NGHTTP2_NO_ERROR);
6445 CU_ASSERT(1 == session->num_closed_streams);
6446 CU_ASSERT(1 == session->closed_stream_tail->stream_id);
6447 CU_ASSERT(session->closed_stream_tail == session->closed_stream_head);
6449 nghttp2_session_close_stream(session, 5, NGHTTP2_NO_ERROR);
6451 CU_ASSERT(2 == session->num_closed_streams);
6452 CU_ASSERT(5 == session->closed_stream_tail->stream_id);
6453 CU_ASSERT(1 == session->closed_stream_head->stream_id);
6454 CU_ASSERT(session->closed_stream_head ==
6455 session->closed_stream_tail->closed_prev);
6456 CU_ASSERT(NULL == session->closed_stream_tail->closed_next);
6457 CU_ASSERT(session->closed_stream_tail ==
6458 session->closed_stream_head->closed_next);
6459 CU_ASSERT(NULL == session->closed_stream_head->closed_prev);
6461 open_stream(session, 11);
6463 CU_ASSERT(1 == session->num_closed_streams);
6464 CU_ASSERT(5 == session->closed_stream_tail->stream_id);
6465 CU_ASSERT(session->closed_stream_tail == session->closed_stream_head);
6466 CU_ASSERT(NULL == session->closed_stream_head->closed_prev);
6467 CU_ASSERT(NULL == session->closed_stream_head->closed_next);
6469 open_stream(session, 13);
6471 CU_ASSERT(0 == session->num_closed_streams);
6472 CU_ASSERT(NULL == session->closed_stream_tail);
6473 CU_ASSERT(NULL == session->closed_stream_head);
6475 nghttp2_session_del(session);
6478 void test_nghttp2_session_keep_idle_stream(void) {
6479 nghttp2_session *session;
6480 nghttp2_session_callbacks callbacks;
6481 const size_t max_concurrent_streams = 1;
6482 nghttp2_settings_entry iv = {NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS,
6483 max_concurrent_streams};
6486 memset(&callbacks, 0, sizeof(callbacks));
6487 callbacks.send_callback = null_send_callback;
6489 nghttp2_session_server_new(&session, &callbacks, NULL);
6491 nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, &iv, 1);
6493 /* We at least allow 2 idle streams even if max concurrent streams
6495 for (i = 0; i < 2; ++i) {
6496 nghttp2_session_open_stream(session, i * 2 + 1, NGHTTP2_STREAM_FLAG_NONE,
6497 &pri_spec_default, NGHTTP2_STREAM_IDLE, NULL);
6500 CU_ASSERT(2 == session->num_idle_streams);
6502 CU_ASSERT(1 == session->idle_stream_head->stream_id);
6503 CU_ASSERT(3 == session->idle_stream_tail->stream_id);
6505 nghttp2_session_open_stream(session, 5, NGHTTP2_FLAG_NONE, &pri_spec_default,
6506 NGHTTP2_STREAM_IDLE, NULL);
6508 CU_ASSERT(2 == session->num_idle_streams);
6510 CU_ASSERT(3 == session->idle_stream_head->stream_id);
6511 CU_ASSERT(5 == session->idle_stream_tail->stream_id);
6513 nghttp2_session_del(session);
6516 void test_nghttp2_session_detach_idle_stream(void) {
6517 nghttp2_session *session;
6518 nghttp2_session_callbacks callbacks;
6520 nghttp2_stream *stream;
6522 memset(&callbacks, 0, sizeof(callbacks));
6523 callbacks.send_callback = null_send_callback;
6525 nghttp2_session_server_new(&session, &callbacks, NULL);
6527 for (i = 1; i <= 3; ++i) {
6528 nghttp2_session_open_stream(session, i, NGHTTP2_STREAM_FLAG_NONE,
6529 &pri_spec_default, NGHTTP2_STREAM_IDLE, NULL);
6532 CU_ASSERT(3 == session->num_idle_streams);
6534 /* Detach middle stream */
6535 stream = nghttp2_session_get_stream_raw(session, 2);
6537 CU_ASSERT(session->idle_stream_head == stream->closed_prev);
6538 CU_ASSERT(session->idle_stream_tail == stream->closed_next);
6539 CU_ASSERT(stream == session->idle_stream_head->closed_next);
6540 CU_ASSERT(stream == session->idle_stream_tail->closed_prev);
6542 nghttp2_session_detach_idle_stream(session, stream);
6544 CU_ASSERT(2 == session->num_idle_streams);
6546 CU_ASSERT(NULL == stream->closed_prev);
6547 CU_ASSERT(NULL == stream->closed_next);
6549 CU_ASSERT(session->idle_stream_head ==
6550 session->idle_stream_tail->closed_prev);
6551 CU_ASSERT(session->idle_stream_tail ==
6552 session->idle_stream_head->closed_next);
6554 /* Detach head stream */
6555 stream = session->idle_stream_head;
6557 nghttp2_session_detach_idle_stream(session, stream);
6559 CU_ASSERT(1 == session->num_idle_streams);
6561 CU_ASSERT(session->idle_stream_head == session->idle_stream_tail);
6562 CU_ASSERT(NULL == session->idle_stream_head->closed_prev);
6563 CU_ASSERT(NULL == session->idle_stream_head->closed_next);
6565 /* Detach last stream */
6567 stream = session->idle_stream_head;
6569 nghttp2_session_detach_idle_stream(session, stream);
6571 CU_ASSERT(0 == session->num_idle_streams);
6573 CU_ASSERT(NULL == session->idle_stream_head);
6574 CU_ASSERT(NULL == session->idle_stream_tail);
6576 for (i = 4; i <= 5; ++i) {
6577 nghttp2_session_open_stream(session, i, NGHTTP2_STREAM_FLAG_NONE,
6578 &pri_spec_default, NGHTTP2_STREAM_IDLE, NULL);
6581 CU_ASSERT(2 == session->num_idle_streams);
6583 /* Detach tail stream */
6585 stream = session->idle_stream_tail;
6587 nghttp2_session_detach_idle_stream(session, stream);
6589 CU_ASSERT(1 == session->num_idle_streams);
6591 CU_ASSERT(session->idle_stream_head == session->idle_stream_tail);
6592 CU_ASSERT(NULL == session->idle_stream_head->closed_prev);
6593 CU_ASSERT(NULL == session->idle_stream_head->closed_next);
6595 nghttp2_session_del(session);
6598 void test_nghttp2_session_large_dep_tree(void) {
6599 nghttp2_session *session;
6600 nghttp2_session_callbacks callbacks;
6602 nghttp2_stream *dep_stream = NULL;
6603 nghttp2_stream *root_stream;
6606 memset(&callbacks, 0, sizeof(callbacks));
6607 callbacks.send_callback = null_send_callback;
6609 nghttp2_session_server_new(&session, &callbacks, NULL);
6612 for (i = 0; i < NGHTTP2_MAX_DEP_TREE_LENGTH; ++i) {
6613 dep_stream = open_stream_with_dep(session, stream_id, dep_stream);
6617 root_stream = nghttp2_session_get_stream(session, 1);
6619 /* Check that last dep_stream must be part of tree */
6620 CU_ASSERT(nghttp2_stream_dep_subtree_find(root_stream, dep_stream));
6622 dep_stream = open_stream_with_dep(session, stream_id, dep_stream);
6624 /* We exceeded NGHTTP2_MAX_DEP_TREE_LENGTH limit. dep_stream is now
6625 root node and has no descendants. */
6626 CU_ASSERT(!nghttp2_stream_dep_subtree_find(root_stream, dep_stream));
6627 CU_ASSERT(nghttp2_stream_in_dep_tree(dep_stream));
6629 nghttp2_session_del(session);
6632 void test_nghttp2_session_graceful_shutdown(void) {
6633 nghttp2_session *session;
6634 nghttp2_session_callbacks callbacks;
6637 memset(&callbacks, 0, sizeof(callbacks));
6638 callbacks.send_callback = null_send_callback;
6639 callbacks.on_frame_send_callback = on_frame_send_callback;
6640 callbacks.on_stream_close_callback = on_stream_close_callback;
6642 nghttp2_session_server_new(&session, &callbacks, &ud);
6644 open_stream(session, 301);
6645 open_stream(session, 302);
6646 open_stream(session, 309);
6647 open_stream(session, 311);
6648 open_stream(session, 319);
6650 CU_ASSERT(0 == nghttp2_submit_shutdown_notice(session));
6652 ud.frame_send_cb_called = 0;
6654 CU_ASSERT(0 == nghttp2_session_send(session));
6656 CU_ASSERT(1 == ud.frame_send_cb_called);
6657 CU_ASSERT((1u << 31) - 1 == session->local_last_stream_id);
6659 CU_ASSERT(0 == nghttp2_submit_goaway(session, NGHTTP2_FLAG_NONE, 311,
6660 NGHTTP2_NO_ERROR, NULL, 0));
6662 ud.frame_send_cb_called = 0;
6663 ud.stream_close_cb_called = 0;
6665 CU_ASSERT(0 == nghttp2_session_send(session));
6667 CU_ASSERT(1 == ud.frame_send_cb_called);
6668 CU_ASSERT(311 == session->local_last_stream_id);
6669 CU_ASSERT(1 == ud.stream_close_cb_called);
6672 nghttp2_session_terminate_session2(session, 301, NGHTTP2_NO_ERROR));
6674 ud.frame_send_cb_called = 0;
6675 ud.stream_close_cb_called = 0;
6677 CU_ASSERT(0 == nghttp2_session_send(session));
6679 CU_ASSERT(1 == ud.frame_send_cb_called);
6680 CU_ASSERT(301 == session->local_last_stream_id);
6681 CU_ASSERT(2 == ud.stream_close_cb_called);
6683 CU_ASSERT(NULL != nghttp2_session_get_stream(session, 301));
6684 CU_ASSERT(NULL != nghttp2_session_get_stream(session, 302));
6685 CU_ASSERT(NULL == nghttp2_session_get_stream(session, 309));
6686 CU_ASSERT(NULL == nghttp2_session_get_stream(session, 311));
6687 CU_ASSERT(NULL == nghttp2_session_get_stream(session, 319));
6689 nghttp2_session_del(session);
6692 void test_nghttp2_session_on_header_temporal_failure(void) {
6693 nghttp2_session *session;
6694 nghttp2_session_callbacks callbacks;
6698 nghttp2_hd_deflater deflater;
6699 nghttp2_nv nv[] = {MAKE_NV("alpha", "bravo"), MAKE_NV("charlie", "delta")};
6703 nghttp2_frame frame;
6704 nghttp2_frame_hd hd;
6705 nghttp2_outbound_item *item;
6708 mem = nghttp2_mem_default();
6709 memset(&callbacks, 0, sizeof(callbacks));
6710 callbacks.on_header_callback = temporal_failure_on_header_callback;
6712 nghttp2_session_server_new(&session, &callbacks, &ud);
6714 frame_pack_bufs_init(&bufs);
6716 nghttp2_hd_deflate_init(&deflater, mem);
6718 nghttp2_nv_array_copy(&nva, reqnv, ARRLEN(reqnv), mem);
6720 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_STREAM, 1,
6721 NGHTTP2_HCAT_REQUEST, NULL, nva, ARRLEN(reqnv));
6722 nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
6723 nghttp2_frame_headers_free(&frame.headers, mem);
6725 /* We are going to create CONTINUATION. First serialize header
6726 block, and then frame header. */
6727 hdpos = nghttp2_bufs_len(&bufs);
6729 buf = &bufs.head->buf;
6730 buf->last += NGHTTP2_FRAME_HDLEN;
6732 nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, &nv[1], 1);
6734 nghttp2_frame_hd_init(&hd,
6735 nghttp2_bufs_len(&bufs) - hdpos - NGHTTP2_FRAME_HDLEN,
6736 NGHTTP2_CONTINUATION, NGHTTP2_FLAG_END_HEADERS, 1);
6738 nghttp2_frame_pack_frame_hd(&buf->pos[hdpos], &hd);
6740 ud.header_cb_called = 0;
6741 rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_bufs_len(&bufs));
6743 CU_ASSERT(rv == nghttp2_bufs_len(&bufs));
6744 CU_ASSERT(1 == ud.header_cb_called);
6746 item = nghttp2_session_get_next_ob_item(session);
6748 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
6749 CU_ASSERT(1 == item->frame.hd.stream_id);
6751 /* Make sure no header decompression error occurred */
6752 CU_ASSERT(NGHTTP2_GOAWAY_NONE == session->goaway_flags);
6754 nghttp2_hd_deflate_free(&deflater);
6755 nghttp2_session_del(session);
6757 nghttp2_bufs_reset(&bufs);
6759 /* Check for PUSH_PROMISE */
6760 nghttp2_hd_deflate_init(&deflater, mem);
6761 nghttp2_session_client_new(&session, &callbacks, &ud);
6763 nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
6764 &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL);
6766 rv = pack_push_promise(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, 2,
6767 reqnv, ARRLEN(reqnv), mem);
6770 ud.header_cb_called = 0;
6771 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
6772 nghttp2_bufs_len(&bufs));
6773 CU_ASSERT(nghttp2_bufs_len(&bufs) == rv);
6774 CU_ASSERT(1 == ud.header_cb_called);
6776 item = nghttp2_session_get_next_ob_item(session);
6777 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
6778 CU_ASSERT(2 == item->frame.hd.stream_id);
6779 CU_ASSERT(NGHTTP2_INTERNAL_ERROR == item->frame.rst_stream.error_code);
6781 nghttp2_session_del(session);
6782 nghttp2_hd_deflate_free(&deflater);
6783 nghttp2_bufs_free(&bufs);
6786 void test_nghttp2_session_recv_client_magic(void) {
6787 nghttp2_session *session;
6788 nghttp2_session_callbacks callbacks;
6790 nghttp2_frame ping_frame;
6793 /* enable global nghttp2_enable_strict_preface here */
6794 nghttp2_enable_strict_preface = 1;
6796 memset(&callbacks, 0, sizeof(callbacks));
6798 /* Check success case */
6799 nghttp2_session_server_new(&session, &callbacks, NULL);
6801 rv = nghttp2_session_mem_recv(session, (const uint8_t *)NGHTTP2_CLIENT_MAGIC,
6802 NGHTTP2_CLIENT_MAGIC_LEN);
6804 CU_ASSERT(rv == NGHTTP2_CLIENT_MAGIC_LEN);
6805 CU_ASSERT(NGHTTP2_IB_READ_FIRST_SETTINGS == session->iframe.state);
6807 /* Receiving PING is error because we want SETTINGS. */
6808 nghttp2_frame_ping_init(&ping_frame.ping, NGHTTP2_FLAG_NONE, NULL);
6810 nghttp2_frame_pack_frame_hd(buf, &ping_frame.ping.hd);
6812 rv = nghttp2_session_mem_recv(session, buf, NGHTTP2_FRAME_HDLEN);
6813 CU_ASSERT(NGHTTP2_FRAME_HDLEN == rv);
6814 CU_ASSERT(NGHTTP2_IB_IGN_ALL == session->iframe.state);
6815 CU_ASSERT(0 == session->iframe.payloadleft);
6817 nghttp2_frame_ping_free(&ping_frame.ping);
6819 nghttp2_session_del(session);
6821 /* Check bad case */
6822 nghttp2_session_server_new(&session, &callbacks, NULL);
6824 /* Feed magic with one byte less */
6825 rv = nghttp2_session_mem_recv(session, (const uint8_t *)NGHTTP2_CLIENT_MAGIC,
6826 NGHTTP2_CLIENT_MAGIC_LEN - 1);
6828 CU_ASSERT(rv == NGHTTP2_CLIENT_MAGIC_LEN - 1);
6829 CU_ASSERT(NGHTTP2_IB_READ_CLIENT_MAGIC == session->iframe.state);
6830 CU_ASSERT(1 == session->iframe.payloadleft);
6832 rv = nghttp2_session_mem_recv(session, (const uint8_t *)"\0", 1);
6834 CU_ASSERT(NGHTTP2_ERR_BAD_CLIENT_MAGIC == rv);
6836 nghttp2_session_del(session);
6838 /* disable global nghttp2_enable_strict_preface here */
6839 nghttp2_enable_strict_preface = 0;
6842 void test_nghttp2_session_delete_data_item(void) {
6843 nghttp2_session *session;
6844 nghttp2_session_callbacks callbacks;
6846 nghttp2_data_provider prd;
6848 memset(&callbacks, 0, sizeof(callbacks));
6850 nghttp2_session_server_new(&session, &callbacks, NULL);
6852 a = open_stream(session, 1);
6853 open_stream_with_dep(session, 3, a);
6855 /* We don't care about these members, since we won't send data */
6856 prd.source.ptr = NULL;
6857 prd.read_callback = fail_data_source_read_callback;
6859 /* This data item will be marked as TOP */
6860 CU_ASSERT(0 == nghttp2_submit_data(session, NGHTTP2_FLAG_NONE, 1, &prd));
6861 /* This data item will be marked as REST */
6862 CU_ASSERT(0 == nghttp2_submit_data(session, NGHTTP2_FLAG_NONE, 3, &prd));
6864 nghttp2_session_del(session);
6867 void test_nghttp2_session_open_idle_stream(void) {
6868 nghttp2_session *session;
6869 nghttp2_session_callbacks callbacks;
6870 nghttp2_stream *stream;
6871 nghttp2_stream *opened_stream;
6872 nghttp2_priority_spec pri_spec;
6873 nghttp2_frame frame;
6875 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6877 nghttp2_session_server_new(&session, &callbacks, NULL);
6879 nghttp2_priority_spec_init(&pri_spec, 0, 3, 0);
6881 nghttp2_frame_priority_init(&frame.priority, 1, &pri_spec);
6883 CU_ASSERT(0 == nghttp2_session_on_priority_received(session, &frame));
6885 stream = nghttp2_session_get_stream_raw(session, 1);
6887 CU_ASSERT(NGHTTP2_STREAM_IDLE == stream->state);
6888 CU_ASSERT(NULL == stream->closed_prev);
6889 CU_ASSERT(NULL == stream->closed_next);
6890 CU_ASSERT(1 == session->num_idle_streams);
6891 CU_ASSERT(session->idle_stream_head == stream);
6892 CU_ASSERT(session->idle_stream_tail == stream);
6894 opened_stream = nghttp2_session_open_stream(
6895 session, 1, NGHTTP2_STREAM_FLAG_NONE, &pri_spec_default,
6896 NGHTTP2_STREAM_OPENING, NULL);
6898 CU_ASSERT(stream == opened_stream);
6899 CU_ASSERT(NGHTTP2_STREAM_OPENING == stream->state);
6900 CU_ASSERT(0 == session->num_idle_streams);
6901 CU_ASSERT(NULL == session->idle_stream_head);
6902 CU_ASSERT(NULL == session->idle_stream_tail);
6904 nghttp2_frame_priority_free(&frame.priority);
6906 nghttp2_session_del(session);
6909 void test_nghttp2_session_cancel_reserved_remote(void) {
6910 nghttp2_session *session;
6911 nghttp2_session_callbacks callbacks;
6912 nghttp2_stream *stream;
6913 nghttp2_frame frame;
6916 nghttp2_hd_deflater deflater;
6921 mem = nghttp2_mem_default();
6922 frame_pack_bufs_init(&bufs);
6924 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6925 callbacks.send_callback = null_send_callback;
6927 nghttp2_session_client_new(&session, &callbacks, NULL);
6929 nghttp2_hd_deflate_init(&deflater, mem);
6931 stream = nghttp2_session_open_stream(session, 2, NGHTTP2_STREAM_FLAG_NONE,
6933 NGHTTP2_STREAM_RESERVED, NULL);
6935 session->last_recv_stream_id = 2;
6937 nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, 2, NGHTTP2_CANCEL);
6939 CU_ASSERT(NGHTTP2_STREAM_CLOSING == stream->state);
6941 CU_ASSERT(0 == nghttp2_session_send(session));
6943 nvlen = ARRLEN(resnv);
6944 nghttp2_nv_array_copy(&nva, resnv, nvlen, mem);
6946 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 2,
6947 NGHTTP2_HCAT_PUSH_RESPONSE, NULL, nva, nvlen);
6948 rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
6952 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
6953 nghttp2_buf_len(&bufs.head->buf));
6955 CU_ASSERT(nghttp2_buf_len(&bufs.head->buf) == rv);
6957 /* stream is not dangling, so assign NULL */
6960 /* No RST_STREAM or GOAWAY is generated since stream should be in
6961 NGHTTP2_STREAM_CLOSING and push response should be ignored. */
6962 CU_ASSERT(0 == nghttp2_outbound_queue_size(&session->ob_reg));
6964 /* Check that we can receive push response HEADERS while RST_STREAM
6966 nghttp2_session_open_stream(session, 4, NGHTTP2_STREAM_FLAG_NONE,
6967 &pri_spec_default, NGHTTP2_STREAM_RESERVED, NULL);
6969 session->last_recv_stream_id = 4;
6971 nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, 2, NGHTTP2_CANCEL);
6973 nghttp2_bufs_reset(&bufs);
6975 frame.hd.stream_id = 4;
6976 rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
6980 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
6981 nghttp2_buf_len(&bufs.head->buf));
6983 CU_ASSERT(nghttp2_buf_len(&bufs.head->buf) == rv);
6985 CU_ASSERT(1 == nghttp2_outbound_queue_size(&session->ob_reg));
6987 nghttp2_frame_headers_free(&frame.headers, mem);
6989 nghttp2_hd_deflate_free(&deflater);
6991 nghttp2_session_del(session);
6993 nghttp2_bufs_free(&bufs);
6996 void test_nghttp2_session_reset_pending_headers(void) {
6997 nghttp2_session *session;
6998 nghttp2_session_callbacks callbacks;
6999 nghttp2_stream *stream;
7003 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7004 callbacks.send_callback = null_send_callback;
7005 callbacks.on_frame_send_callback = on_frame_send_callback;
7006 callbacks.on_frame_not_send_callback = on_frame_not_send_callback;
7007 callbacks.on_stream_close_callback = on_stream_close_callback;
7009 nghttp2_session_client_new(&session, &callbacks, &ud);
7011 stream_id = nghttp2_submit_request(session, NULL, NULL, 0, NULL, NULL);
7012 CU_ASSERT(stream_id >= 1);
7014 nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, stream_id,
7017 session->remote_settings.max_concurrent_streams = 0;
7019 /* RST_STREAM cancels pending HEADERS and is not actually sent. */
7020 ud.frame_send_cb_called = 0;
7021 CU_ASSERT(0 == nghttp2_session_send(session));
7023 CU_ASSERT(0 == ud.frame_send_cb_called);
7025 stream = nghttp2_session_get_stream(session, stream_id);
7027 CU_ASSERT(NULL == stream);
7029 /* See HEADERS is not sent. on_stream_close is called just like
7030 transmission failure. */
7031 session->remote_settings.max_concurrent_streams = 1;
7033 ud.frame_not_send_cb_called = 0;
7034 ud.stream_close_error_code = 0;
7035 CU_ASSERT(0 == nghttp2_session_send(session));
7037 CU_ASSERT(1 == ud.frame_not_send_cb_called);
7038 CU_ASSERT(NGHTTP2_HEADERS == ud.not_sent_frame_type);
7039 CU_ASSERT(NGHTTP2_CANCEL == ud.stream_close_error_code);
7041 stream = nghttp2_session_get_stream(session, stream_id);
7043 CU_ASSERT(NULL == stream);
7045 nghttp2_session_del(session);
7048 void test_nghttp2_session_send_data_callback(void) {
7049 nghttp2_session *session;
7050 nghttp2_session_callbacks callbacks;
7051 nghttp2_data_provider data_prd;
7054 nghttp2_frame_hd hd;
7056 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7057 callbacks.send_callback = accumulator_send_callback;
7058 callbacks.send_data_callback = send_data_callback;
7060 data_prd.read_callback = no_copy_data_source_read_callback;
7065 ud.data_source_length = NGHTTP2_DATA_PAYLOADLEN * 2;
7067 nghttp2_session_client_new(&session, &callbacks, &ud);
7069 nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
7070 &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL);
7072 nghttp2_submit_data(session, NGHTTP2_FLAG_END_STREAM, 1, &data_prd);
7074 CU_ASSERT(0 == nghttp2_session_send(session));
7076 CU_ASSERT((NGHTTP2_FRAME_HDLEN + NGHTTP2_DATA_PAYLOADLEN) * 2 == acc.length);
7078 nghttp2_frame_unpack_frame_hd(&hd, acc.buf);
7080 CU_ASSERT(16384 == hd.length);
7081 CU_ASSERT(NGHTTP2_DATA == hd.type);
7082 CU_ASSERT(NGHTTP2_FLAG_NONE == hd.flags);
7084 nghttp2_frame_unpack_frame_hd(&hd, acc.buf + NGHTTP2_FRAME_HDLEN + hd.length);
7086 CU_ASSERT(16384 == hd.length);
7087 CU_ASSERT(NGHTTP2_DATA == hd.type);
7088 CU_ASSERT(NGHTTP2_FLAG_END_STREAM == hd.flags);
7090 nghttp2_session_del(session);
7093 void test_nghttp2_session_on_begin_headers_temporal_failure(void) {
7094 nghttp2_session *session;
7095 nghttp2_session_callbacks callbacks;
7100 nghttp2_hd_deflater deflater;
7101 nghttp2_outbound_item *item;
7103 mem = nghttp2_mem_default();
7104 frame_pack_bufs_init(&bufs);
7105 nghttp2_hd_deflate_init(&deflater, mem);
7107 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7108 callbacks.on_begin_headers_callback =
7109 temporal_failure_on_begin_headers_callback;
7110 callbacks.on_header_callback = on_header_callback;
7111 callbacks.on_frame_recv_callback = on_frame_recv_callback;
7112 callbacks.send_callback = null_send_callback;
7113 nghttp2_session_server_new(&session, &callbacks, &ud);
7115 rv = pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, reqnv,
7116 ARRLEN(reqnv), mem);
7119 ud.header_cb_called = 0;
7120 ud.frame_recv_cb_called = 0;
7121 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
7122 nghttp2_bufs_len(&bufs));
7123 CU_ASSERT(nghttp2_bufs_len(&bufs) == rv);
7124 CU_ASSERT(0 == ud.header_cb_called);
7125 CU_ASSERT(0 == ud.frame_recv_cb_called);
7127 item = nghttp2_session_get_next_ob_item(session);
7128 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
7129 CU_ASSERT(1 == item->frame.hd.stream_id);
7130 CU_ASSERT(NGHTTP2_INTERNAL_ERROR == item->frame.rst_stream.error_code);
7132 nghttp2_session_del(session);
7133 nghttp2_hd_deflate_free(&deflater);
7135 nghttp2_bufs_reset(&bufs);
7136 /* check for PUSH_PROMISE */
7137 nghttp2_hd_deflate_init(&deflater, mem);
7138 nghttp2_session_client_new(&session, &callbacks, &ud);
7140 nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
7141 &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL);
7143 rv = pack_push_promise(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, 2,
7144 reqnv, ARRLEN(reqnv), mem);
7147 ud.header_cb_called = 0;
7148 ud.frame_recv_cb_called = 0;
7149 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
7150 nghttp2_bufs_len(&bufs));
7151 CU_ASSERT(nghttp2_bufs_len(&bufs) == rv);
7152 CU_ASSERT(0 == ud.header_cb_called);
7153 CU_ASSERT(0 == ud.frame_recv_cb_called);
7155 item = nghttp2_session_get_next_ob_item(session);
7156 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
7157 CU_ASSERT(2 == item->frame.hd.stream_id);
7158 CU_ASSERT(NGHTTP2_INTERNAL_ERROR == item->frame.rst_stream.error_code);
7160 nghttp2_session_del(session);
7161 nghttp2_hd_deflate_free(&deflater);
7162 nghttp2_bufs_free(&bufs);
7165 static void check_nghttp2_http_recv_headers_fail(
7166 nghttp2_session *session, nghttp2_hd_deflater *deflater, int32_t stream_id,
7167 int stream_state, const nghttp2_nv *nva, size_t nvlen) {
7170 nghttp2_outbound_item *item;
7174 mem = nghttp2_mem_default();
7175 frame_pack_bufs_init(&bufs);
7177 ud = session->user_data;
7179 if (stream_state != -1) {
7180 nghttp2_session_open_stream(session, stream_id, NGHTTP2_STREAM_FLAG_NONE,
7181 &pri_spec_default, stream_state, NULL);
7184 rv = pack_headers(&bufs, deflater, stream_id, NGHTTP2_FLAG_END_HEADERS, nva,
7188 ud->invalid_frame_recv_cb_called = 0;
7190 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
7191 nghttp2_buf_len(&bufs.head->buf));
7193 CU_ASSERT(nghttp2_buf_len(&bufs.head->buf) == rv);
7195 item = nghttp2_session_get_next_ob_item(session);
7197 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
7198 CU_ASSERT(1 == ud->invalid_frame_recv_cb_called);
7200 CU_ASSERT(0 == nghttp2_session_send(session));
7202 nghttp2_bufs_free(&bufs);
7205 static void check_nghttp2_http_recv_headers_ok(
7206 nghttp2_session *session, nghttp2_hd_deflater *deflater, int32_t stream_id,
7207 int stream_state, const nghttp2_nv *nva, size_t nvlen) {
7213 mem = nghttp2_mem_default();
7214 frame_pack_bufs_init(&bufs);
7216 ud = session->user_data;
7218 if (stream_state != -1) {
7219 nghttp2_session_open_stream(session, stream_id, NGHTTP2_STREAM_FLAG_NONE,
7220 &pri_spec_default, stream_state, NULL);
7223 rv = pack_headers(&bufs, deflater, stream_id, NGHTTP2_FLAG_END_HEADERS, nva,
7227 ud->frame_recv_cb_called = 0;
7229 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
7230 nghttp2_buf_len(&bufs.head->buf));
7232 CU_ASSERT(nghttp2_buf_len(&bufs.head->buf) == rv);
7233 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
7234 CU_ASSERT(1 == ud->frame_recv_cb_called);
7236 nghttp2_bufs_free(&bufs);
7239 void test_nghttp2_http_mandatory_headers(void) {
7240 nghttp2_session *session;
7241 nghttp2_session_callbacks callbacks;
7242 nghttp2_hd_deflater deflater;
7245 /* test case for response */
7246 const nghttp2_nv nostatus_resnv[] = {MAKE_NV("server", "foo")};
7247 const nghttp2_nv dupstatus_resnv[] = {MAKE_NV(":status", "200"),
7248 MAKE_NV(":status", "200")};
7249 const nghttp2_nv badpseudo_resnv[] = {MAKE_NV(":status", "200"),
7250 MAKE_NV(":scheme", "https")};
7251 const nghttp2_nv latepseudo_resnv[] = {MAKE_NV("server", "foo"),
7252 MAKE_NV(":status", "200")};
7253 const nghttp2_nv badstatus_resnv[] = {MAKE_NV(":status", "2000")};
7254 const nghttp2_nv badcl_resnv[] = {MAKE_NV(":status", "200"),
7255 MAKE_NV("content-length", "-1")};
7256 const nghttp2_nv dupcl_resnv[] = {MAKE_NV(":status", "200"),
7257 MAKE_NV("content-length", "0"),
7258 MAKE_NV("content-length", "0")};
7259 const nghttp2_nv badhd_resnv[] = {MAKE_NV(":status", "200"),
7260 MAKE_NV("connection", "close")};
7262 /* test case for request */
7263 const nghttp2_nv nopath_reqnv[] = {MAKE_NV(":scheme", "https"),
7264 MAKE_NV(":method", "GET"),
7265 MAKE_NV(":authority", "localhost")};
7266 const nghttp2_nv earlyconnect_reqnv[] = {
7267 MAKE_NV(":method", "CONNECT"), MAKE_NV(":scheme", "https"),
7268 MAKE_NV(":path", "/"), MAKE_NV(":authority", "localhost")};
7269 const nghttp2_nv lateconnect_reqnv[] = {
7270 MAKE_NV(":scheme", "https"), MAKE_NV(":path", "/"),
7271 MAKE_NV(":method", "CONNECT"), MAKE_NV(":authority", "localhost")};
7272 const nghttp2_nv duppath_reqnv[] = {
7273 MAKE_NV(":scheme", "https"), MAKE_NV(":method", "GET"),
7274 MAKE_NV(":authority", "localhost"), MAKE_NV(":path", "/"),
7275 MAKE_NV(":path", "/")};
7276 const nghttp2_nv badcl_reqnv[] = {
7277 MAKE_NV(":scheme", "https"), MAKE_NV(":method", "POST"),
7278 MAKE_NV(":authority", "localhost"), MAKE_NV(":path", "/"),
7279 MAKE_NV("content-length", "-1")};
7280 const nghttp2_nv dupcl_reqnv[] = {
7281 MAKE_NV(":scheme", "https"), MAKE_NV(":method", "POST"),
7282 MAKE_NV(":authority", "localhost"), MAKE_NV(":path", "/"),
7283 MAKE_NV("content-length", "0"), MAKE_NV("content-length", "0")};
7284 const nghttp2_nv badhd_reqnv[] = {
7285 MAKE_NV(":scheme", "https"), MAKE_NV(":method", "GET"),
7286 MAKE_NV(":authority", "localhost"), MAKE_NV(":path", "/"),
7287 MAKE_NV("connection", "close")};
7288 const nghttp2_nv badauthority_reqnv[] = {
7289 MAKE_NV(":scheme", "https"), MAKE_NV(":method", "GET"),
7290 MAKE_NV(":authority", "\x0d\x0alocalhost"), MAKE_NV(":path", "/")};
7291 const nghttp2_nv badhdbtw_reqnv[] = {
7292 MAKE_NV(":scheme", "https"), MAKE_NV(":method", "GET"),
7293 MAKE_NV("foo", "\x0d\x0a"), MAKE_NV(":authority", "localhost"),
7294 MAKE_NV(":path", "/")};
7295 const nghttp2_nv asteriskget1_reqnv[] = {
7296 MAKE_NV(":path", "*"), MAKE_NV(":scheme", "https"),
7297 MAKE_NV(":authority", "localhost"), MAKE_NV(":method", "GET")};
7298 const nghttp2_nv asteriskget2_reqnv[] = {
7299 MAKE_NV(":scheme", "https"), MAKE_NV(":authority", "localhost"),
7300 MAKE_NV(":method", "GET"), MAKE_NV(":path", "*")};
7301 const nghttp2_nv asteriskoptions1_reqnv[] = {
7302 MAKE_NV(":path", "*"), MAKE_NV(":scheme", "https"),
7303 MAKE_NV(":authority", "localhost"), MAKE_NV(":method", "OPTIONS")};
7304 const nghttp2_nv asteriskoptions2_reqnv[] = {
7305 MAKE_NV(":scheme", "https"), MAKE_NV(":authority", "localhost"),
7306 MAKE_NV(":method", "OPTIONS"), MAKE_NV(":path", "*")};
7308 mem = nghttp2_mem_default();
7310 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7311 callbacks.send_callback = null_send_callback;
7312 callbacks.on_frame_recv_callback = on_frame_recv_callback;
7313 callbacks.on_invalid_frame_recv_callback = on_invalid_frame_recv_callback;
7315 nghttp2_session_client_new(&session, &callbacks, &ud);
7317 nghttp2_hd_deflate_init(&deflater, mem);
7319 /* response header lacks :status */
7320 check_nghttp2_http_recv_headers_fail(session, &deflater, 1,
7321 NGHTTP2_STREAM_OPENING, nostatus_resnv,
7322 ARRLEN(nostatus_resnv));
7324 /* response header has 2 :status */
7325 check_nghttp2_http_recv_headers_fail(session, &deflater, 3,
7326 NGHTTP2_STREAM_OPENING, dupstatus_resnv,
7327 ARRLEN(dupstatus_resnv));
7329 /* response header has bad pseudo header :scheme */
7330 check_nghttp2_http_recv_headers_fail(session, &deflater, 5,
7331 NGHTTP2_STREAM_OPENING, badpseudo_resnv,
7332 ARRLEN(badpseudo_resnv));
7334 /* response header has :status after regular header field */
7335 check_nghttp2_http_recv_headers_fail(session, &deflater, 7,
7336 NGHTTP2_STREAM_OPENING, latepseudo_resnv,
7337 ARRLEN(latepseudo_resnv));
7339 /* response header has bad status code */
7340 check_nghttp2_http_recv_headers_fail(session, &deflater, 9,
7341 NGHTTP2_STREAM_OPENING, badstatus_resnv,
7342 ARRLEN(badstatus_resnv));
7344 /* response header has bad content-length */
7345 check_nghttp2_http_recv_headers_fail(session, &deflater, 11,
7346 NGHTTP2_STREAM_OPENING, badcl_resnv,
7347 ARRLEN(badcl_resnv));
7349 /* response header has multiple content-length */
7350 check_nghttp2_http_recv_headers_fail(session, &deflater, 13,
7351 NGHTTP2_STREAM_OPENING, dupcl_resnv,
7352 ARRLEN(dupcl_resnv));
7354 /* response header has disallowed header field */
7355 check_nghttp2_http_recv_headers_fail(session, &deflater, 15,
7356 NGHTTP2_STREAM_OPENING, badhd_resnv,
7357 ARRLEN(badhd_resnv));
7359 nghttp2_hd_deflate_free(&deflater);
7361 nghttp2_session_del(session);
7363 /* check server side */
7364 nghttp2_session_server_new(&session, &callbacks, &ud);
7366 nghttp2_hd_deflate_init(&deflater, mem);
7368 /* request header has no :path */
7369 check_nghttp2_http_recv_headers_fail(session, &deflater, 1, -1, nopath_reqnv,
7370 ARRLEN(nopath_reqnv));
7372 /* request header has CONNECT method, but followed by :path */
7373 check_nghttp2_http_recv_headers_fail(session, &deflater, 3, -1,
7375 ARRLEN(earlyconnect_reqnv));
7377 /* request header has CONNECT method following :path */
7378 check_nghttp2_http_recv_headers_fail(
7379 session, &deflater, 5, -1, lateconnect_reqnv, ARRLEN(lateconnect_reqnv));
7381 /* request header has multiple :path */
7382 check_nghttp2_http_recv_headers_fail(session, &deflater, 7, -1, duppath_reqnv,
7383 ARRLEN(duppath_reqnv));
7385 /* request header has bad content-length */
7386 check_nghttp2_http_recv_headers_fail(session, &deflater, 9, -1, badcl_reqnv,
7387 ARRLEN(badcl_reqnv));
7389 /* request header has multiple content-length */
7390 check_nghttp2_http_recv_headers_fail(session, &deflater, 11, -1, dupcl_reqnv,
7391 ARRLEN(dupcl_reqnv));
7393 /* request header has disallowed header field */
7394 check_nghttp2_http_recv_headers_fail(session, &deflater, 13, -1, badhd_reqnv,
7395 ARRLEN(badhd_reqnv));
7397 /* request header has :authority header field containing illegal
7399 check_nghttp2_http_recv_headers_fail(session, &deflater, 15, -1,
7401 ARRLEN(badauthority_reqnv));
7403 /* request header has regular header field containing illegal
7404 character before all mandatory header fields are seen. */
7405 check_nghttp2_http_recv_headers_fail(session, &deflater, 17, -1,
7406 badhdbtw_reqnv, ARRLEN(badhdbtw_reqnv));
7408 /* request header has "*" in :path header field while method is GET.
7409 :path is received before :method */
7410 check_nghttp2_http_recv_headers_fail(session, &deflater, 19, -1,
7412 ARRLEN(asteriskget1_reqnv));
7414 /* request header has "*" in :path header field while method is GET.
7415 :method is received before :path */
7416 check_nghttp2_http_recv_headers_fail(session, &deflater, 21, -1,
7418 ARRLEN(asteriskget2_reqnv));
7420 /* OPTIONS method can include "*" in :path header field. :path is
7421 received before :method. */
7422 check_nghttp2_http_recv_headers_ok(session, &deflater, 23, -1,
7423 asteriskoptions1_reqnv,
7424 ARRLEN(asteriskoptions1_reqnv));
7426 /* OPTIONS method can include "*" in :path header field. :method is
7427 received before :path. */
7428 check_nghttp2_http_recv_headers_ok(session, &deflater, 25, -1,
7429 asteriskoptions2_reqnv,
7430 ARRLEN(asteriskoptions2_reqnv));
7432 nghttp2_hd_deflate_free(&deflater);
7434 nghttp2_session_del(session);
7437 void test_nghttp2_http_content_length(void) {
7438 nghttp2_session *session;
7439 nghttp2_session_callbacks callbacks;
7440 nghttp2_hd_deflater deflater;
7444 nghttp2_stream *stream;
7445 const nghttp2_nv cl_resnv[] = {MAKE_NV(":status", "200"),
7446 MAKE_NV("te", "trailers"),
7447 MAKE_NV("content-length", "9000000000")};
7448 const nghttp2_nv cl_reqnv[] = {
7449 MAKE_NV(":path", "/"), MAKE_NV(":method", "PUT"),
7450 MAKE_NV(":scheme", "https"), MAKE_NV("te", "trailers"),
7451 MAKE_NV("host", "localhost"), MAKE_NV("content-length", "9000000000")};
7453 mem = nghttp2_mem_default();
7454 frame_pack_bufs_init(&bufs);
7456 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7457 callbacks.send_callback = null_send_callback;
7459 nghttp2_session_client_new(&session, &callbacks, NULL);
7461 nghttp2_hd_deflate_init(&deflater, mem);
7463 stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
7465 NGHTTP2_STREAM_OPENING, NULL);
7467 rv = pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, cl_resnv,
7468 ARRLEN(cl_resnv), mem);
7471 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
7472 nghttp2_buf_len(&bufs.head->buf));
7474 CU_ASSERT(nghttp2_buf_len(&bufs.head->buf) == rv);
7475 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
7476 CU_ASSERT(9000000000LL == stream->content_length);
7477 CU_ASSERT(200 == stream->status_code);
7479 nghttp2_hd_deflate_free(&deflater);
7481 nghttp2_session_del(session);
7483 nghttp2_bufs_reset(&bufs);
7485 /* check server side */
7486 nghttp2_session_server_new(&session, &callbacks, NULL);
7488 nghttp2_hd_deflate_init(&deflater, mem);
7490 rv = pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, cl_reqnv,
7491 ARRLEN(cl_reqnv), mem);
7494 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
7495 nghttp2_buf_len(&bufs.head->buf));
7497 CU_ASSERT(nghttp2_buf_len(&bufs.head->buf) == rv);
7499 stream = nghttp2_session_get_stream(session, 1);
7501 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
7502 CU_ASSERT(9000000000LL == stream->content_length);
7504 nghttp2_hd_deflate_free(&deflater);
7506 nghttp2_session_del(session);
7508 nghttp2_bufs_free(&bufs);
7511 void test_nghttp2_http_content_length_mismatch(void) {
7512 nghttp2_session *session;
7513 nghttp2_session_callbacks callbacks;
7514 nghttp2_hd_deflater deflater;
7518 const nghttp2_nv cl_reqnv[] = {
7519 MAKE_NV(":path", "/"), MAKE_NV(":method", "PUT"),
7520 MAKE_NV(":authority", "localhost"), MAKE_NV(":scheme", "https"),
7521 MAKE_NV("content-length", "20")};
7522 nghttp2_outbound_item *item;
7523 nghttp2_frame_hd hd;
7525 mem = nghttp2_mem_default();
7526 frame_pack_bufs_init(&bufs);
7528 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7529 callbacks.send_callback = null_send_callback;
7531 nghttp2_session_server_new(&session, &callbacks, NULL);
7533 nghttp2_hd_deflate_init(&deflater, mem);
7535 /* header says content-length: 20, but HEADERS has END_STREAM flag set */
7536 rv = pack_headers(&bufs, &deflater, 1,
7537 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM,
7538 cl_reqnv, ARRLEN(cl_reqnv), mem);
7541 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
7542 nghttp2_buf_len(&bufs.head->buf));
7544 CU_ASSERT(nghttp2_buf_len(&bufs.head->buf) == rv);
7546 item = nghttp2_session_get_next_ob_item(session);
7547 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
7549 CU_ASSERT(0 == nghttp2_session_send(session));
7551 nghttp2_bufs_reset(&bufs);
7553 /* header says content-length: 20, but DATA has 0 byte */
7554 rv = pack_headers(&bufs, &deflater, 3, NGHTTP2_FLAG_END_HEADERS, cl_reqnv,
7555 ARRLEN(cl_reqnv), mem);
7558 nghttp2_frame_hd_init(&hd, 0, NGHTTP2_DATA, NGHTTP2_FLAG_END_STREAM, 3);
7559 nghttp2_frame_pack_frame_hd(bufs.head->buf.last, &hd);
7560 bufs.head->buf.last += NGHTTP2_FRAME_HDLEN;
7562 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
7563 nghttp2_buf_len(&bufs.head->buf));
7565 CU_ASSERT(nghttp2_buf_len(&bufs.head->buf) == rv);
7567 item = nghttp2_session_get_next_ob_item(session);
7568 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
7570 CU_ASSERT(0 == nghttp2_session_send(session));
7572 nghttp2_bufs_reset(&bufs);
7574 /* header says content-length: 20, but DATA has 21 bytes */
7575 rv = pack_headers(&bufs, &deflater, 5, NGHTTP2_FLAG_END_HEADERS, cl_reqnv,
7576 ARRLEN(cl_reqnv), mem);
7579 nghttp2_frame_hd_init(&hd, 21, NGHTTP2_DATA, NGHTTP2_FLAG_END_STREAM, 5);
7580 nghttp2_frame_pack_frame_hd(bufs.head->buf.last, &hd);
7581 bufs.head->buf.last += NGHTTP2_FRAME_HDLEN + 21;
7583 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
7584 nghttp2_buf_len(&bufs.head->buf));
7586 CU_ASSERT(nghttp2_buf_len(&bufs.head->buf) == rv);
7588 item = nghttp2_session_get_next_ob_item(session);
7589 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
7591 CU_ASSERT(0 == nghttp2_session_send(session));
7593 nghttp2_bufs_reset(&bufs);
7595 nghttp2_hd_deflate_free(&deflater);
7597 nghttp2_session_del(session);
7599 nghttp2_bufs_free(&bufs);
7602 void test_nghttp2_http_non_final_response(void) {
7603 nghttp2_session *session;
7604 nghttp2_session_callbacks callbacks;
7605 nghttp2_hd_deflater deflater;
7609 const nghttp2_nv nonfinal_resnv[] = {
7610 MAKE_NV(":status", "100"),
7612 nghttp2_outbound_item *item;
7613 nghttp2_frame_hd hd;
7615 mem = nghttp2_mem_default();
7616 frame_pack_bufs_init(&bufs);
7618 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7619 callbacks.send_callback = null_send_callback;
7621 nghttp2_session_client_new(&session, &callbacks, NULL);
7623 nghttp2_hd_deflate_init(&deflater, mem);
7625 /* non-final HEADERS with END_STREAM is illegal */
7626 nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
7627 &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL);
7629 rv = pack_headers(&bufs, &deflater, 1,
7630 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM,
7631 nonfinal_resnv, ARRLEN(nonfinal_resnv), mem);
7634 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
7635 nghttp2_buf_len(&bufs.head->buf));
7637 CU_ASSERT(nghttp2_buf_len(&bufs.head->buf) == rv);
7639 item = nghttp2_session_get_next_ob_item(session);
7640 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
7642 CU_ASSERT(0 == nghttp2_session_send(session));
7644 nghttp2_bufs_reset(&bufs);
7646 /* non-final HEADERS followed by non-empty DATA is illegal */
7647 nghttp2_session_open_stream(session, 3, NGHTTP2_STREAM_FLAG_NONE,
7648 &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL);
7650 rv = pack_headers(&bufs, &deflater, 3, NGHTTP2_FLAG_END_HEADERS,
7651 nonfinal_resnv, ARRLEN(nonfinal_resnv), mem);
7654 nghttp2_frame_hd_init(&hd, 10, NGHTTP2_DATA, NGHTTP2_FLAG_END_STREAM, 3);
7655 nghttp2_frame_pack_frame_hd(bufs.head->buf.last, &hd);
7656 bufs.head->buf.last += NGHTTP2_FRAME_HDLEN + 10;
7658 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
7659 nghttp2_buf_len(&bufs.head->buf));
7661 CU_ASSERT(nghttp2_buf_len(&bufs.head->buf) == rv);
7663 item = nghttp2_session_get_next_ob_item(session);
7664 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
7666 CU_ASSERT(0 == nghttp2_session_send(session));
7668 nghttp2_bufs_reset(&bufs);
7670 /* non-final HEADERS followed by empty DATA (without END_STREAM) is
7672 nghttp2_session_open_stream(session, 5, NGHTTP2_STREAM_FLAG_NONE,
7673 &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL);
7675 rv = pack_headers(&bufs, &deflater, 5, NGHTTP2_FLAG_END_HEADERS,
7676 nonfinal_resnv, ARRLEN(nonfinal_resnv), mem);
7679 nghttp2_frame_hd_init(&hd, 0, NGHTTP2_DATA, NGHTTP2_FLAG_NONE, 5);
7680 nghttp2_frame_pack_frame_hd(bufs.head->buf.last, &hd);
7681 bufs.head->buf.last += NGHTTP2_FRAME_HDLEN;
7683 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
7684 nghttp2_buf_len(&bufs.head->buf));
7686 CU_ASSERT(nghttp2_buf_len(&bufs.head->buf) == rv);
7688 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
7690 nghttp2_bufs_reset(&bufs);
7692 /* non-final HEADERS followed by empty DATA (with END_STREAM) is
7694 nghttp2_session_open_stream(session, 7, NGHTTP2_STREAM_FLAG_NONE,
7695 &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL);
7697 rv = pack_headers(&bufs, &deflater, 7, NGHTTP2_FLAG_END_HEADERS,
7698 nonfinal_resnv, ARRLEN(nonfinal_resnv), mem);
7701 nghttp2_frame_hd_init(&hd, 0, NGHTTP2_DATA, NGHTTP2_FLAG_END_STREAM, 7);
7702 nghttp2_frame_pack_frame_hd(bufs.head->buf.last, &hd);
7703 bufs.head->buf.last += NGHTTP2_FRAME_HDLEN;
7705 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
7706 nghttp2_buf_len(&bufs.head->buf));
7708 CU_ASSERT(nghttp2_buf_len(&bufs.head->buf) == rv);
7710 item = nghttp2_session_get_next_ob_item(session);
7712 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
7714 CU_ASSERT(0 == nghttp2_session_send(session));
7716 nghttp2_bufs_reset(&bufs);
7718 /* non-final HEADERS followed by final HEADERS is OK */
7719 nghttp2_session_open_stream(session, 9, NGHTTP2_STREAM_FLAG_NONE,
7720 &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL);
7722 rv = pack_headers(&bufs, &deflater, 9, NGHTTP2_FLAG_END_HEADERS,
7723 nonfinal_resnv, ARRLEN(nonfinal_resnv), mem);
7726 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
7727 nghttp2_buf_len(&bufs.head->buf));
7729 CU_ASSERT(nghttp2_buf_len(&bufs.head->buf) == rv);
7731 nghttp2_bufs_reset(&bufs);
7733 rv = pack_headers(&bufs, &deflater, 9, NGHTTP2_FLAG_END_HEADERS, resnv,
7734 ARRLEN(resnv), mem);
7737 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
7738 nghttp2_buf_len(&bufs.head->buf));
7740 CU_ASSERT(nghttp2_buf_len(&bufs.head->buf) == rv);
7742 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
7744 nghttp2_bufs_reset(&bufs);
7746 nghttp2_hd_deflate_free(&deflater);
7748 nghttp2_session_del(session);
7750 nghttp2_bufs_free(&bufs);
7753 void test_nghttp2_http_trailer_headers(void) {
7754 nghttp2_session *session;
7755 nghttp2_session_callbacks callbacks;
7756 nghttp2_hd_deflater deflater;
7760 const nghttp2_nv trailer_reqnv[] = {
7761 MAKE_NV("foo", "bar"),
7763 nghttp2_outbound_item *item;
7765 mem = nghttp2_mem_default();
7766 frame_pack_bufs_init(&bufs);
7768 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7769 callbacks.send_callback = null_send_callback;
7771 nghttp2_session_server_new(&session, &callbacks, NULL);
7773 nghttp2_hd_deflate_init(&deflater, mem);
7775 /* good trailer header */
7776 rv = pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, reqnv,
7777 ARRLEN(reqnv), mem);
7780 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
7781 nghttp2_buf_len(&bufs.head->buf));
7783 CU_ASSERT(nghttp2_buf_len(&bufs.head->buf) == rv);
7785 nghttp2_bufs_reset(&bufs);
7787 rv = pack_headers(&bufs, &deflater, 1,
7788 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM,
7789 trailer_reqnv, ARRLEN(trailer_reqnv), mem);
7792 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
7793 nghttp2_buf_len(&bufs.head->buf));
7795 CU_ASSERT(nghttp2_buf_len(&bufs.head->buf) == rv);
7797 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
7799 nghttp2_bufs_reset(&bufs);
7801 /* trailer header without END_STREAM is illegal */
7802 rv = pack_headers(&bufs, &deflater, 3, NGHTTP2_FLAG_END_HEADERS, reqnv,
7803 ARRLEN(reqnv), mem);
7806 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
7807 nghttp2_buf_len(&bufs.head->buf));
7809 CU_ASSERT(nghttp2_buf_len(&bufs.head->buf) == rv);
7811 nghttp2_bufs_reset(&bufs);
7813 rv = pack_headers(&bufs, &deflater, 3, NGHTTP2_FLAG_END_HEADERS,
7814 trailer_reqnv, ARRLEN(trailer_reqnv), mem);
7817 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
7818 nghttp2_buf_len(&bufs.head->buf));
7820 CU_ASSERT(nghttp2_buf_len(&bufs.head->buf) == rv);
7822 item = nghttp2_session_get_next_ob_item(session);
7824 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
7826 CU_ASSERT(0 == nghttp2_session_send(session));
7828 nghttp2_bufs_reset(&bufs);
7830 /* trailer header including pseudo header field is illegal */
7831 rv = pack_headers(&bufs, &deflater, 5, NGHTTP2_FLAG_END_HEADERS, reqnv,
7832 ARRLEN(reqnv), mem);
7835 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
7836 nghttp2_buf_len(&bufs.head->buf));
7838 CU_ASSERT(nghttp2_buf_len(&bufs.head->buf) == rv);
7840 nghttp2_bufs_reset(&bufs);
7842 rv = pack_headers(&bufs, &deflater, 5, NGHTTP2_FLAG_END_HEADERS, reqnv,
7843 ARRLEN(reqnv), mem);
7846 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
7847 nghttp2_buf_len(&bufs.head->buf));
7849 CU_ASSERT(nghttp2_buf_len(&bufs.head->buf) == rv);
7851 item = nghttp2_session_get_next_ob_item(session);
7853 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
7855 CU_ASSERT(0 == nghttp2_session_send(session));
7857 nghttp2_bufs_reset(&bufs);
7859 nghttp2_hd_deflate_free(&deflater);
7861 nghttp2_session_del(session);
7863 nghttp2_bufs_free(&bufs);
7866 void test_nghttp2_http_ignore_regular_header(void) {
7867 nghttp2_session *session;
7868 nghttp2_session_callbacks callbacks;
7869 nghttp2_hd_deflater deflater;
7874 const nghttp2_nv bad_reqnv[] = {
7875 MAKE_NV(":authority", "localhost"), MAKE_NV(":scheme", "https"),
7876 MAKE_NV(":path", "/"), MAKE_NV(":method", "GET"),
7877 MAKE_NV("foo", "\x0zzz"), MAKE_NV("bar", "buzz"),
7879 const nghttp2_nv bad_ansnv[] = {
7880 MAKE_NV(":authority", "localhost"), MAKE_NV(":scheme", "https"),
7881 MAKE_NV(":path", "/"), MAKE_NV(":method", "GET"), MAKE_NV("bar", "buzz")};
7885 mem = nghttp2_mem_default();
7886 frame_pack_bufs_init(&bufs);
7888 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7889 callbacks.send_callback = null_send_callback;
7890 callbacks.on_header_callback = pause_on_header_callback;
7892 nghttp2_session_server_new(&session, &callbacks, &ud);
7893 nghttp2_hd_deflate_init(&deflater, mem);
7895 rv = pack_headers(&bufs, &deflater, 1,
7896 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM,
7897 bad_reqnv, ARRLEN(bad_reqnv), mem);
7899 CU_ASSERT_FATAL(0 == rv);
7903 for (i = 0; i < 4; ++i) {
7904 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos + proclen,
7905 nghttp2_buf_len(&bufs.head->buf) - proclen);
7906 CU_ASSERT_FATAL(rv > 0);
7908 CU_ASSERT(nghttp2_nv_equal(&bad_ansnv[i], &ud.nv));
7911 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos + proclen,
7912 nghttp2_buf_len(&bufs.head->buf) - proclen);
7913 CU_ASSERT_FATAL(rv > 0);
7914 /* header field "foo" must be ignored because it has illegal value.
7915 So we have "bar" header field for 5th header. */
7916 CU_ASSERT(nghttp2_nv_equal(&bad_ansnv[4], &ud.nv));
7919 CU_ASSERT(nghttp2_buf_len(&bufs.head->buf) == proclen);
7921 nghttp2_hd_deflate_free(&deflater);
7922 nghttp2_session_del(session);
7923 nghttp2_bufs_free(&bufs);
7926 void test_nghttp2_http_ignore_content_length(void) {
7927 nghttp2_session *session;
7928 nghttp2_session_callbacks callbacks;
7929 nghttp2_hd_deflater deflater;
7933 const nghttp2_nv cl_resnv[] = {MAKE_NV(":status", "304"),
7934 MAKE_NV("content-length", "20")};
7935 const nghttp2_nv conn_reqnv[] = {MAKE_NV(":authority", "localhost"),
7936 MAKE_NV(":method", "CONNECT"),
7937 MAKE_NV("content-length", "999999")};
7938 nghttp2_stream *stream;
7940 mem = nghttp2_mem_default();
7941 frame_pack_bufs_init(&bufs);
7943 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7944 callbacks.send_callback = null_send_callback;
7946 nghttp2_session_client_new(&session, &callbacks, NULL);
7948 nghttp2_hd_deflate_init(&deflater, mem);
7950 /* If status 304, content-length must be ignored */
7951 nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
7952 &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL);
7954 rv = pack_headers(&bufs, &deflater, 1,
7955 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM,
7956 cl_resnv, ARRLEN(cl_resnv), mem);
7959 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
7960 nghttp2_buf_len(&bufs.head->buf));
7962 CU_ASSERT(nghttp2_buf_len(&bufs.head->buf) == rv);
7964 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
7966 nghttp2_bufs_reset(&bufs);
7968 nghttp2_hd_deflate_free(&deflater);
7969 nghttp2_session_del(session);
7971 /* If request method is CONNECT, content-length must be ignored */
7972 nghttp2_session_server_new(&session, &callbacks, NULL);
7974 nghttp2_hd_deflate_init(&deflater, mem);
7976 rv = pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, conn_reqnv,
7977 ARRLEN(conn_reqnv), mem);
7981 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
7982 nghttp2_buf_len(&bufs.head->buf));
7984 CU_ASSERT(nghttp2_buf_len(&bufs.head->buf) == rv);
7986 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
7988 stream = nghttp2_session_get_stream(session, 1);
7990 CU_ASSERT(-1 == stream->content_length);
7991 CU_ASSERT((stream->http_flags & NGHTTP2_HTTP_FLAG_METH_CONNECT) > 0);
7993 nghttp2_hd_deflate_free(&deflater);
7994 nghttp2_session_del(session);
7995 nghttp2_bufs_free(&bufs);
7998 void test_nghttp2_http_record_request_method(void) {
7999 nghttp2_session *session;
8000 nghttp2_session_callbacks callbacks;
8001 const nghttp2_nv conn_reqnv[] = {MAKE_NV(":method", "CONNECT"),
8002 MAKE_NV(":authority", "localhost")};
8003 const nghttp2_nv conn_resnv[] = {MAKE_NV(":status", "200"),
8004 MAKE_NV("content-length", "9999")};
8005 nghttp2_stream *stream;
8008 nghttp2_hd_deflater deflater;
8011 mem = nghttp2_mem_default();
8012 frame_pack_bufs_init(&bufs);
8014 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
8015 callbacks.send_callback = null_send_callback;
8017 nghttp2_session_client_new(&session, &callbacks, NULL);
8019 nghttp2_hd_deflate_init(&deflater, mem);
8021 CU_ASSERT(1 == nghttp2_submit_request(session, NULL, conn_reqnv,
8022 ARRLEN(conn_reqnv), NULL, NULL));
8024 CU_ASSERT(0 == nghttp2_session_send(session));
8026 stream = nghttp2_session_get_stream(session, 1);
8028 CU_ASSERT(NGHTTP2_HTTP_FLAG_METH_CONNECT == stream->http_flags);
8030 rv = pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, conn_resnv,
8031 ARRLEN(conn_resnv), mem);
8034 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
8035 nghttp2_buf_len(&bufs.head->buf));
8037 CU_ASSERT(nghttp2_buf_len(&bufs.head->buf) == rv);
8039 CU_ASSERT((NGHTTP2_HTTP_FLAG_METH_CONNECT & stream->http_flags) > 0);
8040 CU_ASSERT(-1 == stream->content_length);
8042 nghttp2_hd_deflate_free(&deflater);
8043 nghttp2_session_del(session);
8044 nghttp2_bufs_free(&bufs);
8047 void test_nghttp2_http_push_promise(void) {
8048 nghttp2_session *session;
8049 nghttp2_session_callbacks callbacks;
8050 nghttp2_hd_deflater deflater;
8054 nghttp2_stream *stream;
8055 const nghttp2_nv bad_reqnv[] = {MAKE_NV(":method", "GET")};
8056 nghttp2_outbound_item *item;
8058 mem = nghttp2_mem_default();
8059 frame_pack_bufs_init(&bufs);
8061 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
8062 callbacks.send_callback = null_send_callback;
8064 /* good PUSH_PROMISE case */
8065 nghttp2_session_client_new(&session, &callbacks, NULL);
8067 nghttp2_hd_deflate_init(&deflater, mem);
8069 nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
8070 &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL);
8072 rv = pack_push_promise(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, 2,
8073 reqnv, ARRLEN(reqnv), mem);
8076 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
8077 nghttp2_buf_len(&bufs.head->buf));
8079 CU_ASSERT(nghttp2_buf_len(&bufs.head->buf) == rv);
8081 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
8083 stream = nghttp2_session_get_stream(session, 2);
8084 CU_ASSERT(NULL != stream);
8086 nghttp2_bufs_reset(&bufs);
8088 rv = pack_headers(&bufs, &deflater, 2, NGHTTP2_FLAG_END_HEADERS, resnv,
8089 ARRLEN(resnv), mem);
8093 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
8094 nghttp2_buf_len(&bufs.head->buf));
8096 CU_ASSERT(nghttp2_buf_len(&bufs.head->buf) == rv);
8098 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
8100 CU_ASSERT(200 == stream->status_code);
8102 nghttp2_bufs_reset(&bufs);
8104 /* PUSH_PROMISE lacks mandatory header */
8105 rv = pack_push_promise(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, 4,
8106 bad_reqnv, ARRLEN(bad_reqnv), mem);
8110 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
8111 nghttp2_buf_len(&bufs.head->buf));
8113 CU_ASSERT(nghttp2_buf_len(&bufs.head->buf) == rv);
8115 item = nghttp2_session_get_next_ob_item(session);
8117 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
8118 CU_ASSERT(4 == item->frame.hd.stream_id);
8120 nghttp2_bufs_reset(&bufs);
8122 nghttp2_hd_deflate_free(&deflater);
8123 nghttp2_session_del(session);
8124 nghttp2_bufs_free(&bufs);