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"
54 scripted_data_feed *df;
55 int frame_recv_cb_called, invalid_frame_recv_cb_called;
56 uint8_t recv_frame_type;
57 nghttp2_frame_hd recv_frame_hd;
58 int frame_send_cb_called;
59 uint8_t sent_frame_type;
60 int before_frame_send_cb_called;
61 int frame_not_send_cb_called;
62 uint8_t not_sent_frame_type;
64 int stream_close_cb_called;
65 uint32_t stream_close_error_code;
66 size_t data_source_length;
69 int data_chunk_recv_cb_called;
70 const nghttp2_frame *frame;
73 int invalid_header_cb_called;
74 int begin_headers_cb_called;
76 size_t data_chunk_len;
78 int begin_frame_cb_called;
79 nghttp2_buf scratchbuf;
80 size_t data_source_read_cb_paused;
83 static const nghttp2_nv reqnv[] = {
84 MAKE_NV(":method", "GET"),
85 MAKE_NV(":path", "/"),
86 MAKE_NV(":scheme", "https"),
87 MAKE_NV(":authority", "localhost"),
90 static const nghttp2_nv resnv[] = {
91 MAKE_NV(":status", "200"),
94 static const nghttp2_nv trailernv[] = {
95 // from http://tools.ietf.org/html/rfc6249#section-7
96 MAKE_NV("digest", "SHA-256="
97 "MWVkMWQxYTRiMzk5MDQ0MzI3NGU5NDEyZTk5OWY1ZGFmNzgyZTJlODYz"
98 "YjRjYzFhOTlmNTQwYzI2M2QwM2U2MQ=="),
101 static void scripted_data_feed_init2(scripted_data_feed *df,
102 nghttp2_bufs *bufs) {
103 nghttp2_buf_chain *ci;
108 memset(df, 0, sizeof(scripted_data_feed));
112 for (ci = bufs->head; ci; ci = ci->next) {
114 ptr = nghttp2_cpymem(ptr, buf->pos, nghttp2_buf_len(buf));
115 len += nghttp2_buf_len(buf);
118 df->datamark = df->data;
119 df->datalimit = df->data + len;
120 df->feedseq[0] = len;
123 static ssize_t null_send_callback(nghttp2_session *session, const uint8_t *data,
124 size_t len, int flags, void *user_data) {
133 static ssize_t fail_send_callback(nghttp2_session *session, const uint8_t *data,
134 size_t len, int flags, void *user_data) {
141 return NGHTTP2_ERR_CALLBACK_FAILURE;
144 static ssize_t fixed_bytes_send_callback(nghttp2_session *session,
145 const uint8_t *data, size_t len,
146 int flags, void *user_data) {
147 size_t fixed_sendlen = ((my_user_data *)user_data)->fixed_sendlen;
152 return (ssize_t)(fixed_sendlen < len ? fixed_sendlen : len);
155 static ssize_t scripted_recv_callback(nghttp2_session *session, uint8_t *data,
156 size_t len, int flags, void *user_data) {
157 scripted_data_feed *df = ((my_user_data *)user_data)->df;
158 size_t wlen = df->feedseq[df->seqidx] > len ? len : df->feedseq[df->seqidx];
162 memcpy(data, df->datamark, wlen);
163 df->datamark += wlen;
164 df->feedseq[df->seqidx] -= wlen;
165 if (df->feedseq[df->seqidx] == 0) {
168 return (ssize_t)wlen;
171 static ssize_t eof_recv_callback(nghttp2_session *session, uint8_t *data,
172 size_t len, int flags, void *user_data) {
179 return NGHTTP2_ERR_EOF;
182 static ssize_t accumulator_send_callback(nghttp2_session *session,
183 const uint8_t *buf, size_t len,
184 int flags, void *user_data) {
185 accumulator *acc = ((my_user_data *)user_data)->acc;
189 assert(acc->length + len < sizeof(acc->buf));
190 memcpy(acc->buf + acc->length, buf, len);
195 static int on_begin_frame_callback(nghttp2_session *session,
196 const nghttp2_frame_hd *hd,
198 my_user_data *ud = (my_user_data *)user_data;
202 ++ud->begin_frame_cb_called;
206 static int on_frame_recv_callback(nghttp2_session *session,
207 const nghttp2_frame *frame, void *user_data) {
208 my_user_data *ud = (my_user_data *)user_data;
211 ++ud->frame_recv_cb_called;
212 ud->recv_frame_type = frame->hd.type;
213 ud->recv_frame_hd = frame->hd;
218 static int on_invalid_frame_recv_callback(nghttp2_session *session,
219 const nghttp2_frame *frame,
220 int lib_error_code, void *user_data) {
221 my_user_data *ud = (my_user_data *)user_data;
224 (void)lib_error_code;
226 ++ud->invalid_frame_recv_cb_called;
230 static int on_frame_send_callback(nghttp2_session *session,
231 const nghttp2_frame *frame, void *user_data) {
232 my_user_data *ud = (my_user_data *)user_data;
235 ++ud->frame_send_cb_called;
236 ud->sent_frame_type = frame->hd.type;
240 static int on_frame_not_send_callback(nghttp2_session *session,
241 const nghttp2_frame *frame, int lib_error,
243 my_user_data *ud = (my_user_data *)user_data;
246 ++ud->frame_not_send_cb_called;
247 ud->not_sent_frame_type = frame->hd.type;
248 ud->not_sent_error = lib_error;
252 static int cancel_before_frame_send_callback(nghttp2_session *session,
253 const nghttp2_frame *frame,
255 my_user_data *ud = (my_user_data *)user_data;
259 ++ud->before_frame_send_cb_called;
260 return NGHTTP2_ERR_CANCEL;
263 static int on_data_chunk_recv_callback(nghttp2_session *session, uint8_t flags,
264 int32_t stream_id, const uint8_t *data,
265 size_t len, void *user_data) {
266 my_user_data *ud = (my_user_data *)user_data;
272 ++ud->data_chunk_recv_cb_called;
273 ud->data_chunk_len = len;
277 static int pause_on_data_chunk_recv_callback(nghttp2_session *session,
278 uint8_t flags, int32_t stream_id,
279 const uint8_t *data, size_t len,
281 my_user_data *ud = (my_user_data *)user_data;
288 ++ud->data_chunk_recv_cb_called;
289 return NGHTTP2_ERR_PAUSE;
292 static ssize_t select_padding_callback(nghttp2_session *session,
293 const nghttp2_frame *frame,
294 size_t max_payloadlen, void *user_data) {
295 my_user_data *ud = (my_user_data *)user_data;
298 return (ssize_t)nghttp2_min(max_payloadlen, frame->hd.length + ud->padlen);
301 static ssize_t too_large_data_source_length_callback(
302 nghttp2_session *session, uint8_t frame_type, int32_t stream_id,
303 int32_t session_remote_window_size, int32_t stream_remote_window_size,
304 uint32_t remote_max_frame_size, void *user_data) {
308 (void)session_remote_window_size;
309 (void)stream_remote_window_size;
310 (void)remote_max_frame_size;
313 return NGHTTP2_MAX_FRAME_SIZE_MAX + 1;
316 static ssize_t smallest_length_data_source_length_callback(
317 nghttp2_session *session, uint8_t frame_type, int32_t stream_id,
318 int32_t session_remote_window_size, int32_t stream_remote_window_size,
319 uint32_t remote_max_frame_size, void *user_data) {
323 (void)session_remote_window_size;
324 (void)stream_remote_window_size;
325 (void)remote_max_frame_size;
331 static ssize_t fixed_length_data_source_read_callback(
332 nghttp2_session *session, int32_t stream_id, uint8_t *buf, size_t len,
333 uint32_t *data_flags, nghttp2_data_source *source, void *user_data) {
334 my_user_data *ud = (my_user_data *)user_data;
341 if (len < ud->data_source_length) {
344 wlen = ud->data_source_length;
346 ud->data_source_length -= wlen;
347 if (ud->data_source_length == 0) {
348 *data_flags |= NGHTTP2_DATA_FLAG_EOF;
350 return (ssize_t)wlen;
353 static ssize_t temporal_failure_data_source_read_callback(
354 nghttp2_session *session, int32_t stream_id, uint8_t *buf, size_t len,
355 uint32_t *data_flags, nghttp2_data_source *source, void *user_data) {
364 return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
367 static ssize_t fail_data_source_read_callback(nghttp2_session *session,
368 int32_t stream_id, uint8_t *buf,
369 size_t len, uint32_t *data_flags,
370 nghttp2_data_source *source,
380 return NGHTTP2_ERR_CALLBACK_FAILURE;
383 static ssize_t no_end_stream_data_source_read_callback(
384 nghttp2_session *session, int32_t stream_id, uint8_t *buf, size_t len,
385 uint32_t *data_flags, nghttp2_data_source *source, void *user_data) {
393 *data_flags |= NGHTTP2_DATA_FLAG_EOF | NGHTTP2_DATA_FLAG_NO_END_STREAM;
397 static ssize_t no_copy_data_source_read_callback(
398 nghttp2_session *session, int32_t stream_id, uint8_t *buf, size_t len,
399 uint32_t *data_flags, nghttp2_data_source *source, void *user_data) {
400 my_user_data *ud = (my_user_data *)user_data;
407 if (len < ud->data_source_length) {
410 wlen = ud->data_source_length;
413 ud->data_source_length -= wlen;
415 *data_flags |= NGHTTP2_DATA_FLAG_NO_COPY;
417 if (ud->data_source_length == 0) {
418 *data_flags |= NGHTTP2_DATA_FLAG_EOF;
420 return (ssize_t)wlen;
423 static int send_data_callback(nghttp2_session *session, nghttp2_frame *frame,
424 const uint8_t *framehd, size_t length,
425 nghttp2_data_source *source, void *user_data) {
426 accumulator *acc = ((my_user_data *)user_data)->acc;
430 memcpy(acc->buf + acc->length, framehd, NGHTTP2_FRAME_HDLEN);
431 acc->length += NGHTTP2_FRAME_HDLEN;
433 if (frame->data.padlen) {
434 *(acc->buf + acc->length++) = (uint8_t)(frame->data.padlen - 1);
437 acc->length += length;
439 if (frame->data.padlen) {
440 acc->length += frame->data.padlen - 1;
446 static ssize_t block_count_send_callback(nghttp2_session *session,
447 const uint8_t *data, size_t len,
448 int flags, void *user_data) {
449 my_user_data *ud = (my_user_data *)user_data;
454 if (ud->block_count == 0) {
455 return NGHTTP2_ERR_WOULDBLOCK;
462 static int on_header_callback(nghttp2_session *session,
463 const nghttp2_frame *frame, const uint8_t *name,
464 size_t namelen, const uint8_t *value,
465 size_t valuelen, uint8_t flags, void *user_data) {
466 my_user_data *ud = (my_user_data *)user_data;
470 ++ud->header_cb_called;
471 ud->nv.name = (uint8_t *)name;
472 ud->nv.namelen = namelen;
473 ud->nv.value = (uint8_t *)value;
474 ud->nv.valuelen = valuelen;
480 static int pause_on_header_callback(nghttp2_session *session,
481 const nghttp2_frame *frame,
482 const uint8_t *name, size_t namelen,
483 const uint8_t *value, size_t valuelen,
484 uint8_t flags, void *user_data) {
485 on_header_callback(session, frame, name, namelen, value, valuelen, flags,
487 return NGHTTP2_ERR_PAUSE;
490 static int temporal_failure_on_header_callback(
491 nghttp2_session *session, const nghttp2_frame *frame, const uint8_t *name,
492 size_t namelen, const uint8_t *value, size_t valuelen, uint8_t flags,
494 on_header_callback(session, frame, name, namelen, value, valuelen, flags,
496 return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
499 static int on_invalid_header_callback(nghttp2_session *session,
500 const nghttp2_frame *frame,
501 const uint8_t *name, size_t namelen,
502 const uint8_t *value, size_t valuelen,
503 uint8_t flags, void *user_data) {
504 my_user_data *ud = (my_user_data *)user_data;
508 ++ud->invalid_header_cb_called;
509 ud->nv.name = (uint8_t *)name;
510 ud->nv.namelen = namelen;
511 ud->nv.value = (uint8_t *)value;
512 ud->nv.valuelen = valuelen;
518 static int pause_on_invalid_header_callback(nghttp2_session *session,
519 const nghttp2_frame *frame,
520 const uint8_t *name, size_t namelen,
521 const uint8_t *value,
522 size_t valuelen, uint8_t flags,
524 on_invalid_header_callback(session, frame, name, namelen, value, valuelen,
526 return NGHTTP2_ERR_PAUSE;
529 static int reset_on_invalid_header_callback(nghttp2_session *session,
530 const nghttp2_frame *frame,
531 const uint8_t *name, size_t namelen,
532 const uint8_t *value,
533 size_t valuelen, uint8_t flags,
535 on_invalid_header_callback(session, frame, name, namelen, value, valuelen,
537 return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
540 static int on_begin_headers_callback(nghttp2_session *session,
541 const nghttp2_frame *frame,
543 my_user_data *ud = (my_user_data *)user_data;
547 ++ud->begin_headers_cb_called;
551 static int temporal_failure_on_begin_headers_callback(
552 nghttp2_session *session, const nghttp2_frame *frame, void *user_data) {
553 on_begin_headers_callback(session, frame, user_data);
554 return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
557 static ssize_t defer_data_source_read_callback(nghttp2_session *session,
558 int32_t stream_id, uint8_t *buf,
559 size_t len, uint32_t *data_flags,
560 nghttp2_data_source *source,
570 return NGHTTP2_ERR_DEFERRED;
573 static int on_stream_close_callback(nghttp2_session *session, int32_t stream_id,
574 nghttp2_error_code error_code,
576 my_user_data *my_data = (my_user_data *)user_data;
581 ++my_data->stream_close_cb_called;
582 my_data->stream_close_error_code = error_code;
587 static ssize_t pack_extension_callback(nghttp2_session *session, uint8_t *buf,
588 size_t len, const nghttp2_frame *frame,
590 nghttp2_buf *p = frame->ext.payload;
595 memcpy(buf, p->pos, nghttp2_buf_len(p));
597 return (ssize_t)nghttp2_buf_len(p);
600 static int on_extension_chunk_recv_callback(nghttp2_session *session,
601 const nghttp2_frame_hd *hd,
602 const uint8_t *data, size_t len,
604 my_user_data *my_data = (my_user_data *)user_data;
605 nghttp2_buf *buf = &my_data->scratchbuf;
609 buf->last = nghttp2_cpymem(buf->last, data, len);
614 static int cancel_on_extension_chunk_recv_callback(nghttp2_session *session,
615 const nghttp2_frame_hd *hd,
625 return NGHTTP2_ERR_CANCEL;
628 static int unpack_extension_callback(nghttp2_session *session, void **payload,
629 const nghttp2_frame_hd *hd,
631 my_user_data *my_data = (my_user_data *)user_data;
632 nghttp2_buf *buf = &my_data->scratchbuf;
641 static int cancel_unpack_extension_callback(nghttp2_session *session,
643 const nghttp2_frame_hd *hd,
650 return NGHTTP2_ERR_CANCEL;
653 static nghttp2_settings_entry *dup_iv(const nghttp2_settings_entry *iv,
655 return nghttp2_frame_iv_copy(iv, niv, nghttp2_mem_default());
658 static nghttp2_priority_spec pri_spec_default = {0, NGHTTP2_DEFAULT_WEIGHT, 0};
660 void test_nghttp2_session_recv(void) {
661 nghttp2_session *session;
662 nghttp2_session_callbacks callbacks;
663 scripted_data_feed df;
664 my_user_data user_data;
669 nghttp2_outbound_item *item;
672 nghttp2_hd_deflater deflater;
676 mem = nghttp2_mem_default();
677 frame_pack_bufs_init(&bufs);
679 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
680 callbacks.send_callback = null_send_callback;
681 callbacks.recv_callback = scripted_recv_callback;
682 callbacks.on_frame_recv_callback = on_frame_recv_callback;
683 callbacks.on_begin_frame_callback = on_begin_frame_callback;
687 nghttp2_session_server_new(&session, &callbacks, &user_data);
688 nghttp2_hd_deflate_init(&deflater, mem);
690 nvlen = ARRLEN(reqnv);
691 nghttp2_nv_array_copy(&nva, reqnv, nvlen, mem);
692 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 1,
693 NGHTTP2_HCAT_HEADERS, NULL, nva, nvlen);
694 rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
698 scripted_data_feed_init2(&df, &bufs);
700 framelen = nghttp2_bufs_len(&bufs);
702 /* Send 1 byte per each read */
703 for (i = 0; i < framelen; ++i) {
707 nghttp2_frame_headers_free(&frame.headers, mem);
709 user_data.frame_recv_cb_called = 0;
710 user_data.begin_frame_cb_called = 0;
712 while (df.seqidx < framelen) {
713 CU_ASSERT(0 == nghttp2_session_recv(session));
715 CU_ASSERT(1 == user_data.frame_recv_cb_called);
716 CU_ASSERT(1 == user_data.begin_frame_cb_called);
718 nghttp2_bufs_reset(&bufs);
720 /* Receive PRIORITY */
721 nghttp2_frame_priority_init(&frame.priority, 5, &pri_spec_default);
723 rv = nghttp2_frame_pack_priority(&bufs, &frame.priority);
727 nghttp2_frame_priority_free(&frame.priority);
729 scripted_data_feed_init2(&df, &bufs);
731 user_data.frame_recv_cb_called = 0;
732 user_data.begin_frame_cb_called = 0;
734 CU_ASSERT(0 == nghttp2_session_recv(session));
735 CU_ASSERT(1 == user_data.frame_recv_cb_called);
736 CU_ASSERT(1 == user_data.begin_frame_cb_called);
738 nghttp2_bufs_reset(&bufs);
740 nghttp2_hd_deflate_free(&deflater);
741 nghttp2_session_del(session);
743 /* Some tests for frame too large */
744 nghttp2_session_server_new(&session, &callbacks, &user_data);
746 /* Receive PING with too large payload */
747 nghttp2_frame_ping_init(&frame.ping, NGHTTP2_FLAG_NONE, NULL);
749 rv = nghttp2_frame_pack_ping(&bufs, &frame.ping);
753 /* Add extra 16 bytes */
754 nghttp2_bufs_seek_last_present(&bufs);
755 assert(nghttp2_buf_len(&bufs.cur->buf) >= 16);
757 bufs.cur->buf.last += 16;
758 nghttp2_put_uint32be(
760 (uint32_t)(((frame.hd.length + 16) << 8) + bufs.cur->buf.pos[3]));
762 nghttp2_frame_ping_free(&frame.ping);
764 scripted_data_feed_init2(&df, &bufs);
765 user_data.frame_recv_cb_called = 0;
766 user_data.begin_frame_cb_called = 0;
768 CU_ASSERT(0 == nghttp2_session_recv(session));
769 CU_ASSERT(0 == user_data.frame_recv_cb_called);
770 CU_ASSERT(0 == user_data.begin_frame_cb_called);
772 item = nghttp2_session_get_next_ob_item(session);
773 CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
774 CU_ASSERT(NGHTTP2_FRAME_SIZE_ERROR == item->frame.goaway.error_code);
775 CU_ASSERT(0 == nghttp2_session_send(session));
777 nghttp2_bufs_free(&bufs);
778 nghttp2_session_del(session);
781 void test_nghttp2_session_recv_invalid_stream_id(void) {
782 nghttp2_session *session;
783 nghttp2_session_callbacks callbacks;
784 scripted_data_feed df;
785 my_user_data user_data;
788 nghttp2_hd_deflater deflater;
794 mem = nghttp2_mem_default();
795 frame_pack_bufs_init(&bufs);
797 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
798 callbacks.recv_callback = scripted_recv_callback;
799 callbacks.on_invalid_frame_recv_callback = on_invalid_frame_recv_callback;
802 user_data.invalid_frame_recv_cb_called = 0;
803 nghttp2_session_server_new(&session, &callbacks, &user_data);
804 nghttp2_hd_deflate_init(&deflater, mem);
806 nvlen = ARRLEN(reqnv);
807 nghttp2_nv_array_copy(&nva, reqnv, nvlen, mem);
808 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 2,
809 NGHTTP2_HCAT_HEADERS, NULL, nva, nvlen);
810 rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
813 CU_ASSERT(nghttp2_bufs_len(&bufs) > 0);
815 scripted_data_feed_init2(&df, &bufs);
816 nghttp2_frame_headers_free(&frame.headers, mem);
818 CU_ASSERT(0 == nghttp2_session_recv(session));
819 CU_ASSERT(1 == user_data.invalid_frame_recv_cb_called);
821 nghttp2_bufs_free(&bufs);
822 nghttp2_hd_deflate_free(&deflater);
823 nghttp2_session_del(session);
826 void test_nghttp2_session_recv_invalid_frame(void) {
827 nghttp2_session *session;
828 nghttp2_session_callbacks callbacks;
829 scripted_data_feed df;
830 my_user_data user_data;
835 nghttp2_hd_deflater deflater;
839 mem = nghttp2_mem_default();
840 frame_pack_bufs_init(&bufs);
842 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
843 callbacks.recv_callback = scripted_recv_callback;
844 callbacks.send_callback = null_send_callback;
845 callbacks.on_frame_send_callback = on_frame_send_callback;
848 user_data.frame_send_cb_called = 0;
849 nghttp2_session_server_new(&session, &callbacks, &user_data);
850 nghttp2_hd_deflate_init(&deflater, mem);
851 nvlen = ARRLEN(reqnv);
852 nghttp2_nv_array_copy(&nva, reqnv, nvlen, mem);
853 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 1,
854 NGHTTP2_HCAT_HEADERS, NULL, nva, nvlen);
855 rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
858 CU_ASSERT(nghttp2_bufs_len(&bufs) > 0);
860 scripted_data_feed_init2(&df, &bufs);
862 CU_ASSERT(0 == nghttp2_session_recv(session));
863 CU_ASSERT(0 == nghttp2_session_send(session));
864 CU_ASSERT(0 == user_data.frame_send_cb_called);
866 /* Receive exactly same bytes of HEADERS is treated as error, because it has
867 * pseudo headers and without END_STREAM flag set */
868 scripted_data_feed_init2(&df, &bufs);
870 CU_ASSERT(0 == nghttp2_session_recv(session));
871 CU_ASSERT(0 == nghttp2_session_send(session));
872 CU_ASSERT(1 == user_data.frame_send_cb_called);
873 CU_ASSERT(NGHTTP2_RST_STREAM == user_data.sent_frame_type);
875 nghttp2_bufs_free(&bufs);
876 nghttp2_frame_headers_free(&frame.headers, mem);
878 nghttp2_hd_deflate_free(&deflater);
879 nghttp2_session_del(session);
882 void test_nghttp2_session_recv_eof(void) {
883 nghttp2_session *session;
884 nghttp2_session_callbacks callbacks;
886 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
887 callbacks.send_callback = null_send_callback;
888 callbacks.recv_callback = eof_recv_callback;
890 nghttp2_session_client_new(&session, &callbacks, NULL);
891 CU_ASSERT(NGHTTP2_ERR_EOF == nghttp2_session_recv(session));
893 nghttp2_session_del(session);
896 void test_nghttp2_session_recv_data(void) {
897 nghttp2_session *session;
898 nghttp2_session_callbacks callbacks;
902 nghttp2_outbound_item *item;
903 nghttp2_stream *stream;
907 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
908 callbacks.send_callback = null_send_callback;
909 callbacks.on_data_chunk_recv_callback = on_data_chunk_recv_callback;
910 callbacks.on_frame_recv_callback = on_frame_recv_callback;
911 callbacks.on_frame_send_callback = on_frame_send_callback;
913 nghttp2_session_client_new(&session, &callbacks, &ud);
915 /* Create DATA frame with length 4KiB */
916 memset(data, 0, sizeof(data));
918 hd.type = NGHTTP2_DATA;
919 hd.flags = NGHTTP2_FLAG_NONE;
921 nghttp2_frame_pack_frame_hd(data, &hd);
923 /* stream 1 is not opened, so it must be responded with connection
924 error. This is not mandated by the spec */
925 ud.data_chunk_recv_cb_called = 0;
926 ud.frame_recv_cb_called = 0;
927 rv = nghttp2_session_mem_recv(session, data, NGHTTP2_FRAME_HDLEN + 4096);
928 CU_ASSERT(NGHTTP2_FRAME_HDLEN + 4096 == rv);
930 CU_ASSERT(0 == ud.data_chunk_recv_cb_called);
931 CU_ASSERT(0 == ud.frame_recv_cb_called);
932 item = nghttp2_session_get_next_ob_item(session);
933 CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
935 nghttp2_session_del(session);
937 nghttp2_session_client_new(&session, &callbacks, &ud);
939 /* Create stream 1 with CLOSING state. DATA is ignored. */
940 stream = open_sent_stream2(session, 1, NGHTTP2_STREAM_CLOSING);
942 /* Set initial window size 16383 to check stream flow control,
943 isolating it from the connection flow control */
944 stream->local_window_size = 16383;
946 ud.data_chunk_recv_cb_called = 0;
947 ud.frame_recv_cb_called = 0;
948 rv = nghttp2_session_mem_recv(session, data, NGHTTP2_FRAME_HDLEN + 4096);
949 CU_ASSERT(NGHTTP2_FRAME_HDLEN + 4096 == rv);
951 CU_ASSERT(0 == ud.data_chunk_recv_cb_called);
952 CU_ASSERT(0 == ud.frame_recv_cb_called);
953 item = nghttp2_session_get_next_ob_item(session);
954 CU_ASSERT(NULL == item);
956 /* This is normal case. DATA is acceptable. */
957 stream->state = NGHTTP2_STREAM_OPENED;
959 ud.data_chunk_recv_cb_called = 0;
960 ud.frame_recv_cb_called = 0;
961 rv = nghttp2_session_mem_recv(session, data, NGHTTP2_FRAME_HDLEN + 4096);
962 CU_ASSERT(NGHTTP2_FRAME_HDLEN + 4096 == rv);
964 CU_ASSERT(1 == ud.data_chunk_recv_cb_called);
965 CU_ASSERT(1 == ud.frame_recv_cb_called);
967 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
969 ud.data_chunk_recv_cb_called = 0;
970 ud.frame_recv_cb_called = 0;
971 rv = nghttp2_session_mem_recv(session, data, NGHTTP2_FRAME_HDLEN + 4096);
972 CU_ASSERT(NGHTTP2_FRAME_HDLEN + 4096 == rv);
974 /* Now we got data more than initial-window-size / 2, WINDOW_UPDATE
976 CU_ASSERT(1 == ud.data_chunk_recv_cb_called);
977 CU_ASSERT(1 == ud.frame_recv_cb_called);
978 item = nghttp2_session_get_next_ob_item(session);
979 CU_ASSERT(NGHTTP2_WINDOW_UPDATE == item->frame.hd.type);
980 CU_ASSERT(1 == item->frame.window_update.hd.stream_id);
981 CU_ASSERT(0 == nghttp2_session_send(session));
983 /* Set initial window size to 1MiB, so that we can check connection
984 flow control individually */
985 stream->local_window_size = 1 << 20;
986 /* Connection flow control takes into account DATA which is received
987 in the error condition. We have received 4096 * 4 bytes of
988 DATA. Additional 4 DATA frames, connection flow control will kick
990 for (i = 0; i < 5; ++i) {
991 rv = nghttp2_session_mem_recv(session, data, NGHTTP2_FRAME_HDLEN + 4096);
992 CU_ASSERT(NGHTTP2_FRAME_HDLEN + 4096 == rv);
994 item = nghttp2_session_get_next_ob_item(session);
995 CU_ASSERT(NGHTTP2_WINDOW_UPDATE == item->frame.hd.type);
996 CU_ASSERT(0 == item->frame.window_update.hd.stream_id);
997 CU_ASSERT(0 == nghttp2_session_send(session));
999 /* Reception of DATA with stream ID = 0 causes connection error */
1001 hd.type = NGHTTP2_DATA;
1002 hd.flags = NGHTTP2_FLAG_NONE;
1004 nghttp2_frame_pack_frame_hd(data, &hd);
1006 ud.data_chunk_recv_cb_called = 0;
1007 ud.frame_recv_cb_called = 0;
1008 rv = nghttp2_session_mem_recv(session, data, NGHTTP2_FRAME_HDLEN + 4096);
1009 CU_ASSERT(NGHTTP2_FRAME_HDLEN + 4096 == rv);
1011 CU_ASSERT(0 == ud.data_chunk_recv_cb_called);
1012 CU_ASSERT(0 == ud.frame_recv_cb_called);
1013 item = nghttp2_session_get_next_ob_item(session);
1014 CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
1015 CU_ASSERT(NGHTTP2_PROTOCOL_ERROR == item->frame.goaway.error_code);
1017 nghttp2_session_del(session);
1019 /* Check window_update_queued flag in both session and stream */
1020 nghttp2_session_server_new(&session, &callbacks, &ud);
1023 hd.type = NGHTTP2_DATA;
1024 hd.flags = NGHTTP2_FLAG_NONE;
1026 nghttp2_frame_pack_frame_hd(data, &hd);
1028 stream = open_recv_stream(session, 1);
1030 /* Send 32767 bytes of DATA. In our current flow control algorithm,
1031 it triggers first WINDOW_UPDATE of window_size_increment
1033 for (i = 0; i < 7; ++i) {
1034 rv = nghttp2_session_mem_recv(session, data, NGHTTP2_FRAME_HDLEN + 4096);
1035 CU_ASSERT(NGHTTP2_FRAME_HDLEN + 4096 == rv);
1039 nghttp2_frame_pack_frame_hd(data, &hd);
1040 rv = nghttp2_session_mem_recv(session, data, NGHTTP2_FRAME_HDLEN + 4095);
1041 CU_ASSERT(NGHTTP2_FRAME_HDLEN + 4095 == rv);
1043 /* Now 2 WINDOW_UPDATEs for session and stream should be queued. */
1044 CU_ASSERT(0 == stream->recv_window_size);
1045 CU_ASSERT(0 == session->recv_window_size);
1046 CU_ASSERT(1 == stream->window_update_queued);
1047 CU_ASSERT(1 == session->window_update_queued);
1049 /* Then send 32768 bytes of DATA. Since we have not sent queued
1050 WINDOW_UDPATE frame, recv_window_size should not be decreased */
1052 nghttp2_frame_pack_frame_hd(data, &hd);
1054 for (i = 0; i < 8; ++i) {
1055 rv = nghttp2_session_mem_recv(session, data, NGHTTP2_FRAME_HDLEN + 4096);
1056 CU_ASSERT(NGHTTP2_FRAME_HDLEN + 4096 == rv);
1059 /* WINDOW_UPDATE is blocked for session and stream, so
1060 recv_window_size must not be decreased. */
1061 CU_ASSERT(32768 == stream->recv_window_size);
1062 CU_ASSERT(32768 == session->recv_window_size);
1063 CU_ASSERT(1 == stream->window_update_queued);
1064 CU_ASSERT(1 == session->window_update_queued);
1066 ud.frame_send_cb_called = 0;
1068 /* This sends queued WINDOW_UPDATES. And then check
1069 recv_window_size, and queue WINDOW_UPDATEs for both session and
1070 stream, and send them at once. */
1071 CU_ASSERT(0 == nghttp2_session_send(session));
1073 CU_ASSERT(4 == ud.frame_send_cb_called);
1074 CU_ASSERT(0 == stream->recv_window_size);
1075 CU_ASSERT(0 == session->recv_window_size);
1076 CU_ASSERT(0 == stream->window_update_queued);
1077 CU_ASSERT(0 == session->window_update_queued);
1079 nghttp2_session_del(session);
1082 void test_nghttp2_session_recv_data_no_auto_flow_control(void) {
1083 nghttp2_session *session;
1084 nghttp2_session_callbacks callbacks;
1086 nghttp2_option *option;
1087 nghttp2_frame_hd hd;
1092 nghttp2_stream *stream;
1095 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
1096 callbacks.send_callback = null_send_callback;
1097 callbacks.on_frame_send_callback = on_frame_send_callback;
1099 nghttp2_option_new(&option);
1100 nghttp2_option_set_no_auto_window_update(option, 1);
1102 nghttp2_session_server_new2(&session, &callbacks, &ud, option);
1104 /* Create DATA frame with length 4KiB + 11 bytes padding*/
1106 memset(data, 0, sizeof(data));
1107 hd.length = 4096 + 1 + padlen;
1108 hd.type = NGHTTP2_DATA;
1109 hd.flags = NGHTTP2_FLAG_PADDED;
1111 nghttp2_frame_pack_frame_hd(data, &hd);
1112 data[NGHTTP2_FRAME_HDLEN] = (uint8_t)padlen;
1114 /* First create stream 1, then close it. Check that data is
1115 consumed for connection in this situation */
1116 open_recv_stream(session, 1);
1118 /* Receive first 100 bytes */
1120 rv = nghttp2_session_mem_recv(session, data, sendlen);
1121 CU_ASSERT((ssize_t)sendlen == rv);
1123 /* We consumed pad length field (1 byte) */
1124 CU_ASSERT(1 == session->consumed_size);
1126 /* close stream here */
1127 nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, 1, NGHTTP2_NO_ERROR);
1128 nghttp2_session_send(session);
1130 /* stream 1 has been closed, and we disabled auto flow-control, so
1131 data must be immediately consumed for connection. */
1132 rv = nghttp2_session_mem_recv(session, data + sendlen,
1133 NGHTTP2_FRAME_HDLEN + hd.length - sendlen);
1134 CU_ASSERT((ssize_t)(NGHTTP2_FRAME_HDLEN + hd.length - sendlen) == rv);
1136 /* We already consumed pad length field (1 byte), so do +1 here */
1137 CU_ASSERT((int32_t)(NGHTTP2_FRAME_HDLEN + hd.length - sendlen + 1) ==
1138 session->consumed_size);
1140 nghttp2_session_del(session);
1142 /* Reuse DATA created previously. */
1144 nghttp2_session_server_new2(&session, &callbacks, &ud, option);
1146 /* Now we are expecting final response header, which means receiving
1147 DATA for that stream is illegal. */
1148 stream = open_recv_stream(session, 1);
1149 stream->http_flags |= NGHTTP2_HTTP_FLAG_EXPECT_FINAL_RESPONSE;
1151 rv = nghttp2_session_mem_recv(session, data, NGHTTP2_FRAME_HDLEN + hd.length);
1152 CU_ASSERT((ssize_t)(NGHTTP2_FRAME_HDLEN + hd.length) == rv);
1154 /* Whole payload must be consumed now because HTTP messaging rule
1156 CU_ASSERT((int32_t)hd.length == session->consumed_size);
1158 nghttp2_session_del(session);
1160 /* Check window_update_queued flag in both session and stream */
1161 nghttp2_session_server_new2(&session, &callbacks, &ud, option);
1163 stream = open_recv_stream(session, 1);
1166 hd.type = NGHTTP2_DATA;
1167 hd.flags = NGHTTP2_FLAG_NONE;
1169 nghttp2_frame_pack_frame_hd(data, &hd);
1171 /* Receive up to 65535 bytes of DATA */
1172 for (i = 0; i < 15; ++i) {
1173 rv = nghttp2_session_mem_recv(session, data, NGHTTP2_FRAME_HDLEN + 4096);
1174 CU_ASSERT(NGHTTP2_FRAME_HDLEN + 4096 == rv);
1178 nghttp2_frame_pack_frame_hd(data, &hd);
1180 rv = nghttp2_session_mem_recv(session, data, NGHTTP2_FRAME_HDLEN + 4095);
1181 CU_ASSERT(NGHTTP2_FRAME_HDLEN + 4095 == rv);
1183 CU_ASSERT(65535 == session->recv_window_size);
1184 CU_ASSERT(65535 == stream->recv_window_size);
1186 /* The first call of nghttp2_session_consume_connection() will queue
1187 WINDOW_UPDATE. Next call does not. */
1188 nghttp2_session_consume_connection(session, 32767);
1189 nghttp2_session_consume_connection(session, 32768);
1191 CU_ASSERT(32768 == session->recv_window_size);
1192 CU_ASSERT(65535 == stream->recv_window_size);
1193 CU_ASSERT(1 == session->window_update_queued);
1194 CU_ASSERT(0 == stream->window_update_queued);
1196 ud.frame_send_cb_called = 0;
1198 /* This will send WINDOW_UPDATE, and check whether we should send
1199 WINDOW_UPDATE, and queue and send it at once. */
1200 CU_ASSERT(0 == nghttp2_session_send(session));
1201 CU_ASSERT(0 == session->recv_window_size);
1202 CU_ASSERT(65535 == stream->recv_window_size);
1203 CU_ASSERT(0 == session->window_update_queued);
1204 CU_ASSERT(0 == stream->window_update_queued);
1205 CU_ASSERT(2 == ud.frame_send_cb_called);
1207 /* Do the same for stream */
1208 nghttp2_session_consume_stream(session, 1, 32767);
1209 nghttp2_session_consume_stream(session, 1, 32768);
1211 CU_ASSERT(0 == session->recv_window_size);
1212 CU_ASSERT(32768 == stream->recv_window_size);
1213 CU_ASSERT(0 == session->window_update_queued);
1214 CU_ASSERT(1 == stream->window_update_queued);
1216 ud.frame_send_cb_called = 0;
1218 CU_ASSERT(0 == nghttp2_session_send(session));
1219 CU_ASSERT(0 == session->recv_window_size);
1220 CU_ASSERT(0 == stream->recv_window_size);
1221 CU_ASSERT(0 == session->window_update_queued);
1222 CU_ASSERT(0 == stream->window_update_queued);
1223 CU_ASSERT(2 == ud.frame_send_cb_called);
1225 nghttp2_session_del(session);
1226 nghttp2_option_del(option);
1229 void test_nghttp2_session_recv_continuation(void) {
1230 nghttp2_session *session;
1231 nghttp2_session_callbacks callbacks;
1234 nghttp2_frame frame;
1239 nghttp2_hd_deflater deflater;
1242 nghttp2_frame_hd cont_hd;
1243 nghttp2_priority_spec pri_spec;
1246 mem = nghttp2_mem_default();
1247 frame_pack_bufs_init(&bufs);
1249 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
1250 callbacks.on_header_callback = on_header_callback;
1251 callbacks.on_begin_headers_callback = on_begin_headers_callback;
1252 callbacks.on_begin_frame_callback = on_begin_frame_callback;
1254 nghttp2_session_server_new(&session, &callbacks, &ud);
1256 nghttp2_hd_deflate_init(&deflater, mem);
1258 /* Make 1 HEADERS and insert CONTINUATION header */
1259 nvlen = ARRLEN(reqnv);
1260 nghttp2_nv_array_copy(&nva, reqnv, nvlen, mem);
1261 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_NONE, 1,
1262 NGHTTP2_HCAT_HEADERS, NULL, nva, nvlen);
1263 rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
1266 CU_ASSERT(nghttp2_bufs_len(&bufs) > 0);
1268 /* make sure that all data is in the first buf */
1269 buf = &bufs.head->buf;
1270 assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
1272 nghttp2_frame_headers_free(&frame.headers, mem);
1274 /* HEADERS's payload is 1 byte */
1275 memcpy(data, buf->pos, NGHTTP2_FRAME_HDLEN + 1);
1276 datalen = NGHTTP2_FRAME_HDLEN + 1;
1277 buf->pos += NGHTTP2_FRAME_HDLEN + 1;
1279 nghttp2_put_uint32be(data, (uint32_t)((1 << 8) + data[3]));
1281 /* First CONTINUATION, 2 bytes */
1282 nghttp2_frame_hd_init(&cont_hd, 2, NGHTTP2_CONTINUATION, NGHTTP2_FLAG_NONE,
1285 nghttp2_frame_pack_frame_hd(data + datalen, &cont_hd);
1286 datalen += NGHTTP2_FRAME_HDLEN;
1288 memcpy(data + datalen, buf->pos, cont_hd.length);
1289 datalen += cont_hd.length;
1290 buf->pos += cont_hd.length;
1292 /* Second CONTINUATION, rest of the bytes */
1293 nghttp2_frame_hd_init(&cont_hd, nghttp2_buf_len(buf), NGHTTP2_CONTINUATION,
1294 NGHTTP2_FLAG_END_HEADERS, 1);
1296 nghttp2_frame_pack_frame_hd(data + datalen, &cont_hd);
1297 datalen += NGHTTP2_FRAME_HDLEN;
1299 memcpy(data + datalen, buf->pos, cont_hd.length);
1300 datalen += cont_hd.length;
1301 buf->pos += cont_hd.length;
1303 CU_ASSERT(0 == nghttp2_buf_len(buf));
1305 ud.header_cb_called = 0;
1306 ud.begin_frame_cb_called = 0;
1308 rv = nghttp2_session_mem_recv(session, data, datalen);
1309 CU_ASSERT((ssize_t)datalen == rv);
1310 CU_ASSERT(4 == ud.header_cb_called);
1311 CU_ASSERT(3 == ud.begin_frame_cb_called);
1313 nghttp2_hd_deflate_free(&deflater);
1314 nghttp2_session_del(session);
1316 /* HEADERS with padding followed by CONTINUATION */
1317 nghttp2_session_server_new(&session, &callbacks, &ud);
1319 nghttp2_hd_deflate_init(&deflater, mem);
1321 nvlen = ARRLEN(reqnv);
1322 nghttp2_nv_array_copy(&nva, reqnv, nvlen, mem);
1323 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_NONE, 1,
1324 NGHTTP2_HCAT_HEADERS, NULL, nva, nvlen);
1326 nghttp2_bufs_reset(&bufs);
1327 rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
1331 nghttp2_frame_headers_free(&frame.headers, mem);
1333 /* make sure that all data is in the first buf */
1334 buf = &bufs.head->buf;
1335 assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
1337 /* HEADERS payload is 3 byte (1 for padding field, 1 for padding) */
1338 memcpy(data, buf->pos, NGHTTP2_FRAME_HDLEN);
1339 nghttp2_put_uint32be(data, (uint32_t)((3 << 8) + data[3]));
1340 data[4] |= NGHTTP2_FLAG_PADDED;
1342 data[NGHTTP2_FRAME_HDLEN] = 1;
1343 data[NGHTTP2_FRAME_HDLEN + 1] = buf->pos[NGHTTP2_FRAME_HDLEN];
1345 data[NGHTTP2_FRAME_HDLEN + 2] = 0;
1346 datalen = NGHTTP2_FRAME_HDLEN + 3;
1347 buf->pos += NGHTTP2_FRAME_HDLEN + 1;
1349 /* CONTINUATION, rest of the bytes */
1350 nghttp2_frame_hd_init(&cont_hd, nghttp2_buf_len(buf), NGHTTP2_CONTINUATION,
1351 NGHTTP2_FLAG_END_HEADERS, 1);
1352 nghttp2_frame_pack_frame_hd(data + datalen, &cont_hd);
1353 datalen += NGHTTP2_FRAME_HDLEN;
1355 memcpy(data + datalen, buf->pos, cont_hd.length);
1356 datalen += cont_hd.length;
1357 buf->pos += cont_hd.length;
1359 CU_ASSERT(0 == nghttp2_buf_len(buf));
1361 ud.header_cb_called = 0;
1362 ud.begin_frame_cb_called = 0;
1364 rv = nghttp2_session_mem_recv(session, data, datalen);
1366 CU_ASSERT((ssize_t)datalen == rv);
1367 CU_ASSERT(4 == ud.header_cb_called);
1368 CU_ASSERT(2 == ud.begin_frame_cb_called);
1370 nghttp2_hd_deflate_free(&deflater);
1371 nghttp2_session_del(session);
1373 /* Expecting CONTINUATION, but get the other frame */
1374 nghttp2_session_server_new(&session, &callbacks, &ud);
1376 nghttp2_hd_deflate_init(&deflater, mem);
1378 /* HEADERS without END_HEADERS flag */
1379 nvlen = ARRLEN(reqnv);
1380 nghttp2_nv_array_copy(&nva, reqnv, nvlen, mem);
1381 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_NONE, 1,
1382 NGHTTP2_HCAT_HEADERS, NULL, nva, nvlen);
1383 nghttp2_bufs_reset(&bufs);
1384 rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
1387 CU_ASSERT(nghttp2_bufs_len(&bufs) > 0);
1389 nghttp2_frame_headers_free(&frame.headers, mem);
1391 /* make sure that all data is in the first buf */
1392 buf = &bufs.head->buf;
1393 assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
1395 memcpy(data, buf->pos, nghttp2_buf_len(buf));
1396 datalen = nghttp2_buf_len(buf);
1398 /* Followed by PRIORITY */
1399 nghttp2_priority_spec_default_init(&pri_spec);
1401 nghttp2_frame_priority_init(&frame.priority, 1, &pri_spec);
1402 nghttp2_bufs_reset(&bufs);
1404 rv = nghttp2_frame_pack_priority(&bufs, &frame.priority);
1407 CU_ASSERT(nghttp2_bufs_len(&bufs) > 0);
1409 memcpy(data + datalen, buf->pos, nghttp2_buf_len(buf));
1410 datalen += nghttp2_buf_len(buf);
1412 ud.begin_headers_cb_called = 0;
1413 rv = nghttp2_session_mem_recv(session, data, datalen);
1414 CU_ASSERT((ssize_t)datalen == rv);
1416 CU_ASSERT(1 == ud.begin_headers_cb_called);
1417 CU_ASSERT(NGHTTP2_GOAWAY ==
1418 nghttp2_session_get_next_ob_item(session)->frame.hd.type);
1420 nghttp2_bufs_free(&bufs);
1421 nghttp2_hd_deflate_free(&deflater);
1422 nghttp2_session_del(session);
1425 void test_nghttp2_session_recv_headers_with_priority(void) {
1426 nghttp2_session *session;
1427 nghttp2_session_callbacks callbacks;
1430 nghttp2_frame frame;
1435 nghttp2_hd_deflater deflater;
1436 nghttp2_outbound_item *item;
1437 nghttp2_priority_spec pri_spec;
1438 nghttp2_stream *stream;
1441 mem = nghttp2_mem_default();
1442 frame_pack_bufs_init(&bufs);
1444 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
1445 callbacks.on_frame_recv_callback = on_frame_recv_callback;
1447 nghttp2_session_server_new(&session, &callbacks, &ud);
1449 nghttp2_hd_deflate_init(&deflater, mem);
1451 open_recv_stream(session, 1);
1453 /* With NGHTTP2_FLAG_PRIORITY without exclusive flag set */
1454 nvlen = ARRLEN(reqnv);
1455 nghttp2_nv_array_copy(&nva, reqnv, nvlen, mem);
1457 nghttp2_priority_spec_init(&pri_spec, 1, 99, 0);
1459 nghttp2_frame_headers_init(&frame.headers,
1460 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PRIORITY,
1461 3, NGHTTP2_HCAT_HEADERS, &pri_spec, nva, nvlen);
1463 rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
1466 CU_ASSERT(nghttp2_bufs_len(&bufs) > 0);
1468 nghttp2_frame_headers_free(&frame.headers, mem);
1470 buf = &bufs.head->buf;
1471 assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
1473 ud.frame_recv_cb_called = 0;
1475 rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
1477 CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv);
1478 CU_ASSERT(1 == ud.frame_recv_cb_called);
1480 stream = nghttp2_session_get_stream(session, 3);
1482 CU_ASSERT(99 == stream->weight);
1483 CU_ASSERT(1 == stream->dep_prev->stream_id);
1485 nghttp2_bufs_reset(&bufs);
1487 /* With NGHTTP2_FLAG_PRIORITY, but cut last 1 byte to make it
1489 nvlen = ARRLEN(reqnv);
1490 nghttp2_nv_array_copy(&nva, reqnv, nvlen, mem);
1492 nghttp2_priority_spec_init(&pri_spec, 0, 99, 0);
1494 nghttp2_frame_headers_init(&frame.headers,
1495 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PRIORITY,
1496 5, NGHTTP2_HCAT_HEADERS, &pri_spec, nva, nvlen);
1498 rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
1501 CU_ASSERT(nghttp2_bufs_len(&bufs) > NGHTTP2_FRAME_HDLEN + 5);
1503 nghttp2_frame_headers_free(&frame.headers, mem);
1505 buf = &bufs.head->buf;
1506 /* Make payload shorter than required length to store priority
1508 nghttp2_put_uint32be(buf->pos, (uint32_t)((4 << 8) + buf->pos[3]));
1510 ud.frame_recv_cb_called = 0;
1512 rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
1514 CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv);
1515 CU_ASSERT(0 == ud.frame_recv_cb_called);
1517 stream = nghttp2_session_get_stream(session, 5);
1519 CU_ASSERT(NULL == stream);
1521 item = nghttp2_session_get_next_ob_item(session);
1522 CU_ASSERT(NULL != item);
1523 CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
1524 CU_ASSERT(NGHTTP2_FRAME_SIZE_ERROR == item->frame.goaway.error_code);
1526 nghttp2_bufs_reset(&bufs);
1528 nghttp2_hd_deflate_free(&deflater);
1529 nghttp2_session_del(session);
1531 /* Check dep_stream_id == stream_id */
1532 nghttp2_session_server_new(&session, &callbacks, &ud);
1534 nghttp2_hd_deflate_init(&deflater, mem);
1536 nvlen = ARRLEN(reqnv);
1537 nghttp2_nv_array_copy(&nva, reqnv, nvlen, mem);
1539 nghttp2_priority_spec_init(&pri_spec, 1, 0, 0);
1541 nghttp2_frame_headers_init(&frame.headers,
1542 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PRIORITY,
1543 1, NGHTTP2_HCAT_HEADERS, &pri_spec, nva, nvlen);
1545 rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
1548 CU_ASSERT(nghttp2_bufs_len(&bufs) > 0);
1550 nghttp2_frame_headers_free(&frame.headers, mem);
1552 buf = &bufs.head->buf;
1553 assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
1555 ud.frame_recv_cb_called = 0;
1557 rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
1559 CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv);
1560 CU_ASSERT(0 == ud.frame_recv_cb_called);
1562 stream = nghttp2_session_get_stream(session, 1);
1564 CU_ASSERT(NULL == stream);
1566 item = nghttp2_session_get_next_ob_item(session);
1567 CU_ASSERT(NULL != item);
1568 CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
1569 CU_ASSERT(NGHTTP2_PROTOCOL_ERROR == item->frame.goaway.error_code);
1571 nghttp2_bufs_reset(&bufs);
1573 nghttp2_bufs_free(&bufs);
1574 nghttp2_hd_deflate_free(&deflater);
1575 nghttp2_session_del(session);
1578 void test_nghttp2_session_recv_headers_with_padding(void) {
1579 nghttp2_session *session;
1580 nghttp2_session_callbacks callbacks;
1583 nghttp2_frame_hd hd;
1584 nghttp2_outbound_item *item;
1588 frame_pack_bufs_init(&bufs);
1590 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
1591 callbacks.on_frame_recv_callback = on_frame_recv_callback;
1592 callbacks.send_callback = null_send_callback;
1594 /* HEADERS: Wrong padding length */
1595 nghttp2_session_server_new(&session, &callbacks, &ud);
1596 nghttp2_session_send(session);
1598 nghttp2_frame_hd_init(&hd, 10, NGHTTP2_HEADERS,
1599 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PRIORITY |
1600 NGHTTP2_FLAG_PADDED,
1602 buf = &bufs.head->buf;
1603 nghttp2_frame_pack_frame_hd(buf->last, &hd);
1604 buf->last += NGHTTP2_FRAME_HDLEN;
1605 /* padding is 6 bytes */
1607 /* priority field */
1608 nghttp2_put_uint32be(buf->last, 3);
1609 buf->last += sizeof(uint32_t);
1611 /* rest is garbage */
1612 memset(buf->last, 0, 4);
1615 ud.frame_recv_cb_called = 0;
1617 rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
1619 CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv);
1620 CU_ASSERT(0 == ud.frame_recv_cb_called);
1622 item = nghttp2_session_get_next_ob_item(session);
1624 CU_ASSERT(NULL != item);
1625 CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
1627 nghttp2_bufs_reset(&bufs);
1628 nghttp2_session_del(session);
1630 /* PUSH_PROMISE: Wrong padding length */
1631 nghttp2_session_client_new(&session, &callbacks, &ud);
1632 nghttp2_session_send(session);
1634 open_sent_stream(session, 1);
1636 nghttp2_frame_hd_init(&hd, 9, NGHTTP2_PUSH_PROMISE,
1637 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PADDED, 1);
1638 buf = &bufs.head->buf;
1639 nghttp2_frame_pack_frame_hd(buf->last, &hd);
1640 buf->last += NGHTTP2_FRAME_HDLEN;
1641 /* padding is 6 bytes */
1643 /* promised stream ID field */
1644 nghttp2_put_uint32be(buf->last, 2);
1645 buf->last += sizeof(uint32_t);
1646 /* rest is garbage */
1647 memset(buf->last, 0, 4);
1650 ud.frame_recv_cb_called = 0;
1652 rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
1654 CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv);
1655 CU_ASSERT(0 == ud.frame_recv_cb_called);
1657 item = nghttp2_session_get_next_ob_item(session);
1659 CU_ASSERT(NULL != item);
1660 CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
1662 nghttp2_bufs_free(&bufs);
1663 nghttp2_session_del(session);
1666 static int response_on_begin_frame_callback(nghttp2_session *session,
1667 const nghttp2_frame_hd *hd,
1672 if (hd->type != NGHTTP2_HEADERS) {
1676 rv = nghttp2_submit_response(session, hd->stream_id, resnv, ARRLEN(resnv),
1684 void test_nghttp2_session_recv_headers_early_response(void) {
1685 nghttp2_session *session;
1686 nghttp2_session_callbacks callbacks;
1689 nghttp2_hd_deflater deflater;
1693 nghttp2_frame frame;
1695 nghttp2_stream *stream;
1697 mem = nghttp2_mem_default();
1698 frame_pack_bufs_init(&bufs);
1700 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
1701 callbacks.send_callback = null_send_callback;
1702 callbacks.on_begin_frame_callback = response_on_begin_frame_callback;
1704 nghttp2_session_server_new(&session, &callbacks, NULL);
1706 nghttp2_hd_deflate_init(&deflater, mem);
1708 nvlen = ARRLEN(reqnv);
1709 nghttp2_nv_array_copy(&nva, reqnv, nvlen, mem);
1710 nghttp2_frame_headers_init(&frame.headers,
1711 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM,
1712 1, NGHTTP2_HCAT_REQUEST, NULL, nva, nvlen);
1714 rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
1718 nghttp2_frame_headers_free(&frame.headers, mem);
1720 buf = &bufs.head->buf;
1722 /* Only receive 9 bytes headers, and invoke
1723 on_begin_frame_callback */
1724 rv = nghttp2_session_mem_recv(session, buf->pos, 9);
1728 rv = nghttp2_session_send(session);
1733 nghttp2_session_mem_recv(session, buf->pos + 9, nghttp2_buf_len(buf) - 9);
1735 CU_ASSERT((ssize_t)nghttp2_buf_len(buf) - 9 == rv);
1737 stream = nghttp2_session_get_stream_raw(session, 1);
1739 CU_ASSERT(stream->flags & NGHTTP2_STREAM_FLAG_CLOSED);
1741 nghttp2_hd_deflate_free(&deflater);
1742 nghttp2_session_del(session);
1743 nghttp2_bufs_free(&bufs);
1746 void test_nghttp2_session_recv_headers_for_closed_stream(void) {
1747 nghttp2_session *session;
1748 nghttp2_session_callbacks callbacks;
1751 nghttp2_frame frame;
1756 nghttp2_hd_deflater deflater;
1757 nghttp2_stream *stream;
1759 const uint8_t *data;
1761 mem = nghttp2_mem_default();
1762 frame_pack_bufs_init(&bufs);
1764 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
1765 callbacks.on_frame_recv_callback = on_frame_recv_callback;
1766 callbacks.on_header_callback = on_header_callback;
1768 nghttp2_session_server_new(&session, &callbacks, &ud);
1770 nghttp2_hd_deflate_init(&deflater, mem);
1772 /* Make sure that on_header callback never be invoked for closed
1774 nvlen = ARRLEN(reqnv);
1775 nghttp2_nv_array_copy(&nva, reqnv, nvlen, mem);
1777 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 1,
1778 NGHTTP2_HCAT_HEADERS, NULL, nva, nvlen);
1780 rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
1783 CU_ASSERT(nghttp2_bufs_len(&bufs) > 0);
1785 nghttp2_frame_headers_free(&frame.headers, mem);
1787 buf = &bufs.head->buf;
1788 assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
1790 ud.header_cb_called = 0;
1791 ud.frame_recv_cb_called = 0;
1793 rv = nghttp2_session_mem_recv(session, buf->pos, NGHTTP2_FRAME_HDLEN);
1795 CU_ASSERT(NGHTTP2_FRAME_HDLEN == rv);
1796 CU_ASSERT(0 == ud.header_cb_called);
1797 CU_ASSERT(0 == ud.frame_recv_cb_called);
1799 stream = nghttp2_session_get_stream(session, 1);
1801 CU_ASSERT(NULL != stream);
1803 rv = nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, 1,
1808 rv = nghttp2_session_mem_send(session, &data);
1812 stream = nghttp2_session_get_stream(session, 1);
1814 CU_ASSERT(NULL == stream);
1816 ud.header_cb_called = 0;
1817 ud.frame_recv_cb_called = 0;
1819 rv = nghttp2_session_mem_recv(session, buf->pos + NGHTTP2_FRAME_HDLEN,
1820 nghttp2_buf_len(buf) - NGHTTP2_FRAME_HDLEN);
1822 CU_ASSERT((ssize_t)nghttp2_buf_len(buf) - NGHTTP2_FRAME_HDLEN == rv);
1823 CU_ASSERT(0 == ud.header_cb_called);
1824 CU_ASSERT(0 == ud.frame_recv_cb_called);
1826 nghttp2_bufs_free(&bufs);
1827 nghttp2_hd_deflate_free(&deflater);
1828 nghttp2_session_del(session);
1831 void test_nghttp2_session_server_recv_push_response(void) {
1832 nghttp2_session *session;
1833 nghttp2_session_callbacks callbacks;
1839 nghttp2_frame frame;
1840 nghttp2_hd_deflater deflater;
1844 mem = nghttp2_mem_default();
1845 frame_pack_bufs_init(&bufs);
1847 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
1848 callbacks.on_invalid_frame_recv_callback = on_invalid_frame_recv_callback;
1850 nghttp2_session_server_new(&session, &callbacks, &ud);
1852 nghttp2_hd_deflate_init(&deflater, mem);
1854 open_sent_stream2(session, 2, NGHTTP2_STREAM_RESERVED);
1856 nvlen = ARRLEN(resnv);
1857 nghttp2_nv_array_copy(&nva, resnv, nvlen, mem);
1858 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 2,
1859 NGHTTP2_HCAT_HEADERS, &pri_spec_default, nva,
1861 rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
1864 CU_ASSERT(nghttp2_bufs_len(&bufs) > 0);
1866 nghttp2_frame_headers_free(&frame.headers, mem);
1868 buf = &bufs.head->buf;
1870 ud.invalid_frame_recv_cb_called = 0;
1872 rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
1874 CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv);
1875 CU_ASSERT(1 == ud.invalid_frame_recv_cb_called);
1877 nghttp2_bufs_free(&bufs);
1878 nghttp2_hd_deflate_free(&deflater);
1879 nghttp2_session_del(session);
1882 void test_nghttp2_session_recv_premature_headers(void) {
1883 nghttp2_session *session;
1884 nghttp2_session_callbacks callbacks;
1889 nghttp2_hd_deflater deflater;
1890 nghttp2_outbound_item *item;
1892 uint32_t payloadlen;
1894 mem = nghttp2_mem_default();
1895 frame_pack_bufs_init(&bufs);
1897 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
1898 callbacks.send_callback = null_send_callback;
1900 nghttp2_session_server_new(&session, &callbacks, &ud);
1902 nghttp2_hd_deflate_init(&deflater, mem);
1904 pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, reqnv,
1905 ARRLEN(reqnv), mem);
1907 buf = &bufs.head->buf;
1908 /* Intentionally feed payload cutting last 1 byte off */
1909 payloadlen = nghttp2_get_uint32(buf->pos) >> 8;
1910 nghttp2_put_uint32be(buf->pos, ((payloadlen - 1) << 8) + buf->pos[3]);
1911 rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf) - 1);
1913 CU_ASSERT((ssize_t)(nghttp2_buf_len(buf) - 1) == rv);
1915 item = nghttp2_session_get_next_ob_item(session);
1917 CU_ASSERT(NULL != item);
1918 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
1919 CU_ASSERT(NGHTTP2_COMPRESSION_ERROR == item->frame.rst_stream.error_code);
1920 CU_ASSERT(1 == item->frame.hd.stream_id);
1921 CU_ASSERT(0 == nghttp2_session_send(session));
1923 nghttp2_bufs_reset(&bufs);
1924 nghttp2_hd_deflate_free(&deflater);
1925 nghttp2_session_del(session);
1927 /* Test for PUSH_PROMISE */
1928 nghttp2_session_client_new(&session, &callbacks, &ud);
1929 nghttp2_hd_deflate_init(&deflater, mem);
1931 open_sent_stream3(session, 1, NGHTTP2_STREAM_FLAG_NONE, &pri_spec_default,
1932 NGHTTP2_STREAM_OPENING, NULL);
1934 rv = pack_push_promise(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, 2,
1935 reqnv, ARRLEN(reqnv), mem);
1939 buf = &bufs.head->buf;
1940 payloadlen = nghttp2_get_uint32(buf->pos) >> 8;
1941 /* Intentionally feed payload cutting last 1 byte off */
1942 nghttp2_put_uint32be(buf->pos, ((payloadlen - 1) << 8) + buf->pos[3]);
1943 rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf) - 1);
1945 CU_ASSERT((ssize_t)(nghttp2_buf_len(buf) - 1) == rv);
1947 item = nghttp2_session_get_next_ob_item(session);
1949 CU_ASSERT(NULL != item);
1950 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
1951 CU_ASSERT(NGHTTP2_COMPRESSION_ERROR == item->frame.rst_stream.error_code);
1952 CU_ASSERT(2 == item->frame.hd.stream_id);
1953 CU_ASSERT(0 == nghttp2_session_send(session));
1955 nghttp2_hd_deflate_free(&deflater);
1956 nghttp2_session_del(session);
1957 nghttp2_bufs_free(&bufs);
1960 void test_nghttp2_session_recv_unknown_frame(void) {
1961 nghttp2_session *session;
1962 nghttp2_session_callbacks callbacks;
1964 uint8_t data[16384];
1966 nghttp2_frame_hd hd;
1969 nghttp2_frame_hd_init(&hd, 16000, 99, NGHTTP2_FLAG_NONE, 0);
1971 nghttp2_frame_pack_frame_hd(data, &hd);
1972 datalen = NGHTTP2_FRAME_HDLEN + hd.length;
1974 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
1975 callbacks.on_frame_recv_callback = on_frame_recv_callback;
1977 nghttp2_session_server_new(&session, &callbacks, &ud);
1979 ud.frame_recv_cb_called = 0;
1981 /* Unknown frame must be ignored */
1982 rv = nghttp2_session_mem_recv(session, data, datalen);
1984 CU_ASSERT(rv == (ssize_t)datalen);
1985 CU_ASSERT(0 == ud.frame_recv_cb_called);
1986 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
1988 nghttp2_session_del(session);
1991 void test_nghttp2_session_recv_unexpected_continuation(void) {
1992 nghttp2_session *session;
1993 nghttp2_session_callbacks callbacks;
1995 uint8_t data[16384];
1997 nghttp2_frame_hd hd;
1999 nghttp2_outbound_item *item;
2001 nghttp2_frame_hd_init(&hd, 16000, NGHTTP2_CONTINUATION,
2002 NGHTTP2_FLAG_END_HEADERS, 1);
2004 nghttp2_frame_pack_frame_hd(data, &hd);
2005 datalen = NGHTTP2_FRAME_HDLEN + hd.length;
2007 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
2008 callbacks.on_frame_recv_callback = on_frame_recv_callback;
2010 nghttp2_session_server_new(&session, &callbacks, &ud);
2012 open_recv_stream(session, 1);
2014 ud.frame_recv_cb_called = 0;
2016 /* unexpected CONTINUATION must be treated as connection error */
2017 rv = nghttp2_session_mem_recv(session, data, datalen);
2019 CU_ASSERT(rv == (ssize_t)datalen);
2020 CU_ASSERT(0 == ud.frame_recv_cb_called);
2022 item = nghttp2_session_get_next_ob_item(session);
2024 CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
2026 nghttp2_session_del(session);
2029 void test_nghttp2_session_recv_settings_header_table_size(void) {
2030 nghttp2_session *session;
2031 nghttp2_session_callbacks callbacks;
2032 nghttp2_frame frame;
2037 nghttp2_settings_entry iv[3];
2038 nghttp2_nv nv = MAKE_NV(":authority", "example.org");
2041 mem = nghttp2_mem_default();
2042 frame_pack_bufs_init(&bufs);
2044 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
2045 callbacks.on_frame_recv_callback = on_frame_recv_callback;
2046 callbacks.send_callback = null_send_callback;
2048 nghttp2_session_client_new(&session, &callbacks, &ud);
2050 iv[0].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
2053 iv[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
2054 iv[1].value = 16384;
2056 nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE, dup_iv(iv, 2),
2059 rv = nghttp2_frame_pack_settings(&bufs, &frame.settings);
2062 CU_ASSERT(nghttp2_bufs_len(&bufs) > 0);
2064 nghttp2_frame_settings_free(&frame.settings, mem);
2066 buf = &bufs.head->buf;
2067 assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
2069 ud.frame_recv_cb_called = 0;
2071 rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
2073 CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv);
2074 CU_ASSERT(1 == ud.frame_recv_cb_called);
2076 CU_ASSERT(3000 == session->remote_settings.header_table_size);
2077 CU_ASSERT(16384 == session->remote_settings.initial_window_size);
2079 nghttp2_bufs_reset(&bufs);
2081 /* 2 SETTINGS_HEADER_TABLE_SIZE */
2082 iv[0].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
2085 iv[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
2086 iv[1].value = 16383;
2088 iv[2].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
2091 nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE, dup_iv(iv, 3),
2094 rv = nghttp2_frame_pack_settings(&bufs, &frame.settings);
2097 CU_ASSERT(nghttp2_bufs_len(&bufs) > 0);
2099 nghttp2_frame_settings_free(&frame.settings, mem);
2101 buf = &bufs.head->buf;
2102 assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
2104 ud.frame_recv_cb_called = 0;
2106 rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
2108 CU_ASSERT((ssize_t)(nghttp2_buf_len(buf)) == rv);
2109 CU_ASSERT(1 == ud.frame_recv_cb_called);
2111 CU_ASSERT(3001 == session->remote_settings.header_table_size);
2112 CU_ASSERT(16383 == session->remote_settings.initial_window_size);
2114 nghttp2_bufs_reset(&bufs);
2116 /* 2 SETTINGS_HEADER_TABLE_SIZE; first entry clears dynamic header
2119 nghttp2_submit_request(session, NULL, &nv, 1, NULL, NULL);
2120 nghttp2_session_send(session);
2122 CU_ASSERT(0 < session->hd_deflater.ctx.hd_table.len);
2124 iv[0].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
2127 iv[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
2128 iv[1].value = 16382;
2130 iv[2].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
2133 nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE, dup_iv(iv, 3),
2136 rv = nghttp2_frame_pack_settings(&bufs, &frame.settings);
2139 CU_ASSERT(nghttp2_bufs_len(&bufs) > 0);
2141 nghttp2_frame_settings_free(&frame.settings, mem);
2143 buf = &bufs.head->buf;
2144 assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
2146 ud.frame_recv_cb_called = 0;
2148 rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
2150 CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv);
2151 CU_ASSERT(1 == ud.frame_recv_cb_called);
2153 CU_ASSERT(4096 == session->remote_settings.header_table_size);
2154 CU_ASSERT(16382 == session->remote_settings.initial_window_size);
2155 CU_ASSERT(0 == session->hd_deflater.ctx.hd_table.len);
2157 nghttp2_bufs_reset(&bufs);
2159 /* 2 SETTINGS_HEADER_TABLE_SIZE; second entry clears dynamic header
2162 nghttp2_submit_request(session, NULL, &nv, 1, NULL, NULL);
2163 nghttp2_session_send(session);
2165 CU_ASSERT(0 < session->hd_deflater.ctx.hd_table.len);
2167 iv[0].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
2170 iv[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
2171 iv[1].value = 16381;
2173 iv[2].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
2176 nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE, dup_iv(iv, 3),
2179 rv = nghttp2_frame_pack_settings(&bufs, &frame.settings);
2182 CU_ASSERT(nghttp2_bufs_len(&bufs) > 0);
2184 nghttp2_frame_settings_free(&frame.settings, mem);
2186 buf = &bufs.head->buf;
2187 assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
2189 ud.frame_recv_cb_called = 0;
2191 rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
2193 CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv);
2194 CU_ASSERT(1 == ud.frame_recv_cb_called);
2196 CU_ASSERT(0 == session->remote_settings.header_table_size);
2197 CU_ASSERT(16381 == session->remote_settings.initial_window_size);
2198 CU_ASSERT(0 == session->hd_deflater.ctx.hd_table.len);
2200 nghttp2_bufs_reset(&bufs);
2202 nghttp2_bufs_free(&bufs);
2203 nghttp2_session_del(session);
2206 void test_nghttp2_session_recv_too_large_frame_length(void) {
2207 nghttp2_session *session;
2208 nghttp2_session_callbacks callbacks;
2209 uint8_t buf[NGHTTP2_FRAME_HDLEN];
2210 nghttp2_outbound_item *item;
2211 nghttp2_frame_hd hd;
2213 /* Initial max frame size is NGHTTP2_MAX_FRAME_SIZE_MIN */
2214 nghttp2_frame_hd_init(&hd, NGHTTP2_MAX_FRAME_SIZE_MIN + 1, NGHTTP2_HEADERS,
2215 NGHTTP2_FLAG_NONE, 1);
2217 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
2219 nghttp2_session_server_new(&session, &callbacks, NULL);
2221 nghttp2_frame_pack_frame_hd(buf, &hd);
2223 CU_ASSERT(sizeof(buf) == nghttp2_session_mem_recv(session, buf, sizeof(buf)));
2225 item = nghttp2_session_get_next_ob_item(session);
2227 CU_ASSERT(item != NULL);
2228 CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
2230 nghttp2_session_del(session);
2233 void test_nghttp2_session_recv_extension(void) {
2234 nghttp2_session *session;
2235 nghttp2_session_callbacks callbacks;
2238 nghttp2_frame_hd hd;
2240 const char data[] = "Hello World!";
2242 nghttp2_option *option;
2244 mem = nghttp2_mem_default();
2246 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
2248 callbacks.on_extension_chunk_recv_callback = on_extension_chunk_recv_callback;
2249 callbacks.unpack_extension_callback = unpack_extension_callback;
2250 callbacks.on_frame_recv_callback = on_frame_recv_callback;
2252 nghttp2_option_new(&option);
2253 nghttp2_option_set_user_recv_extension_type(option, 111);
2255 nghttp2_buf_init2(&ud.scratchbuf, 4096, mem);
2256 nghttp2_buf_init2(&buf, 4096, mem);
2258 nghttp2_frame_hd_init(&hd, sizeof(data), 111, 0xab, 1000000007);
2259 nghttp2_frame_pack_frame_hd(buf.last, &hd);
2260 buf.last += NGHTTP2_FRAME_HDLEN;
2261 buf.last = nghttp2_cpymem(buf.last, data, sizeof(data));
2263 nghttp2_session_client_new2(&session, &callbacks, &ud, option);
2265 nghttp2_frame_hd_init(&ud.recv_frame_hd, 0, 0, 0, 0);
2266 rv = nghttp2_session_mem_recv(session, buf.pos, nghttp2_buf_len(&buf));
2268 CU_ASSERT(NGHTTP2_FRAME_HDLEN + hd.length == (size_t)rv);
2269 CU_ASSERT(111 == ud.recv_frame_hd.type);
2270 CU_ASSERT(0xab == ud.recv_frame_hd.flags);
2271 CU_ASSERT(1000000007 == ud.recv_frame_hd.stream_id);
2272 CU_ASSERT(0 == memcmp(data, ud.scratchbuf.pos, sizeof(data)));
2274 nghttp2_session_del(session);
2276 /* cancel in on_extension_chunk_recv_callback */
2277 nghttp2_buf_reset(&ud.scratchbuf);
2279 callbacks.on_extension_chunk_recv_callback =
2280 cancel_on_extension_chunk_recv_callback;
2282 nghttp2_session_server_new2(&session, &callbacks, &ud, option);
2284 ud.frame_recv_cb_called = 0;
2285 rv = nghttp2_session_mem_recv(session, buf.pos, nghttp2_buf_len(&buf));
2287 CU_ASSERT(NGHTTP2_FRAME_HDLEN + hd.length == (size_t)rv);
2288 CU_ASSERT(0 == ud.frame_recv_cb_called);
2290 nghttp2_session_del(session);
2292 /* cancel in unpack_extension_callback */
2293 nghttp2_buf_reset(&ud.scratchbuf);
2295 callbacks.on_extension_chunk_recv_callback = on_extension_chunk_recv_callback;
2296 callbacks.unpack_extension_callback = cancel_unpack_extension_callback;
2298 nghttp2_session_server_new2(&session, &callbacks, &ud, option);
2300 ud.frame_recv_cb_called = 0;
2301 rv = nghttp2_session_mem_recv(session, buf.pos, nghttp2_buf_len(&buf));
2303 CU_ASSERT(NGHTTP2_FRAME_HDLEN + hd.length == (size_t)rv);
2304 CU_ASSERT(0 == ud.frame_recv_cb_called);
2306 nghttp2_session_del(session);
2308 nghttp2_buf_free(&buf, mem);
2309 nghttp2_buf_free(&ud.scratchbuf, mem);
2311 nghttp2_option_del(option);
2314 void test_nghttp2_session_recv_altsvc(void) {
2315 nghttp2_session *session;
2316 nghttp2_session_callbacks callbacks;
2319 nghttp2_frame_hd hd;
2322 nghttp2_option *option;
2323 static const uint8_t origin[] = "nghttp2.org";
2324 static const uint8_t field_value[] = "h2=\":443\"";
2326 mem = nghttp2_mem_default();
2328 nghttp2_buf_init2(&buf, NGHTTP2_FRAME_HDLEN + NGHTTP2_MAX_FRAME_SIZE_MIN,
2331 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
2333 callbacks.on_frame_recv_callback = on_frame_recv_callback;
2334 callbacks.on_invalid_frame_recv_callback = on_invalid_frame_recv_callback;
2336 nghttp2_option_new(&option);
2337 nghttp2_option_set_builtin_recv_extension_type(option, NGHTTP2_ALTSVC);
2339 nghttp2_session_client_new2(&session, &callbacks, &ud, option);
2341 nghttp2_frame_hd_init(&hd, 2 + sizeof(origin) - 1 + sizeof(field_value) - 1,
2342 NGHTTP2_ALTSVC, NGHTTP2_FLAG_NONE, 0);
2343 nghttp2_frame_pack_frame_hd(buf.last, &hd);
2344 buf.last += NGHTTP2_FRAME_HDLEN;
2345 nghttp2_put_uint16be(buf.last, sizeof(origin) - 1);
2347 buf.last = nghttp2_cpymem(buf.last, origin, sizeof(origin) - 1);
2348 buf.last = nghttp2_cpymem(buf.last, field_value, sizeof(field_value) - 1);
2350 ud.frame_recv_cb_called = 0;
2351 rv = nghttp2_session_mem_recv(session, buf.pos, nghttp2_buf_len(&buf));
2353 CU_ASSERT((ssize_t)nghttp2_buf_len(&buf) == rv);
2354 CU_ASSERT(1 == ud.frame_recv_cb_called);
2355 CU_ASSERT(NGHTTP2_ALTSVC == ud.recv_frame_hd.type);
2356 CU_ASSERT(NGHTTP2_FLAG_NONE == ud.recv_frame_hd.flags);
2357 CU_ASSERT(0 == ud.recv_frame_hd.stream_id);
2359 nghttp2_session_del(session);
2361 /* size of origin is larger than frame length */
2362 nghttp2_buf_reset(&buf);
2364 nghttp2_session_client_new2(&session, &callbacks, &ud, option);
2366 nghttp2_frame_hd_init(&hd, 2 + sizeof(origin) - 1 - 1, NGHTTP2_ALTSVC,
2367 NGHTTP2_FLAG_NONE, 0);
2368 nghttp2_frame_pack_frame_hd(buf.last, &hd);
2369 buf.last += NGHTTP2_FRAME_HDLEN;
2370 nghttp2_put_uint16be(buf.last, sizeof(origin) - 1);
2372 buf.last = nghttp2_cpymem(buf.last, origin, sizeof(origin) - 1 - 1);
2374 ud.frame_recv_cb_called = 0;
2375 rv = nghttp2_session_mem_recv(session, buf.pos, nghttp2_buf_len(&buf));
2377 CU_ASSERT((ssize_t)nghttp2_buf_len(&buf) == rv);
2378 CU_ASSERT(0 == ud.frame_recv_cb_called);
2380 nghttp2_session_del(session);
2382 /* zero-length value */
2383 nghttp2_buf_reset(&buf);
2385 nghttp2_session_client_new2(&session, &callbacks, &ud, option);
2387 nghttp2_frame_hd_init(&hd, 2 + sizeof(origin) - 1, NGHTTP2_ALTSVC,
2388 NGHTTP2_FLAG_NONE, 0);
2389 nghttp2_frame_pack_frame_hd(buf.last, &hd);
2390 buf.last += NGHTTP2_FRAME_HDLEN;
2391 nghttp2_put_uint16be(buf.last, sizeof(origin) - 1);
2393 buf.last = nghttp2_cpymem(buf.last, origin, sizeof(origin) - 1);
2395 ud.invalid_frame_recv_cb_called = 0;
2396 rv = nghttp2_session_mem_recv(session, buf.pos, nghttp2_buf_len(&buf));
2398 CU_ASSERT((ssize_t)nghttp2_buf_len(&buf) == rv);
2399 CU_ASSERT(1 == ud.invalid_frame_recv_cb_called);
2401 nghttp2_session_del(session);
2403 /* non-empty origin to a stream other than 0 */
2404 nghttp2_buf_reset(&buf);
2406 nghttp2_session_client_new2(&session, &callbacks, &ud, option);
2408 open_sent_stream(session, 1);
2410 nghttp2_frame_hd_init(&hd, 2 + sizeof(origin) - 1 + sizeof(field_value) - 1,
2411 NGHTTP2_ALTSVC, NGHTTP2_FLAG_NONE, 1);
2412 nghttp2_frame_pack_frame_hd(buf.last, &hd);
2413 buf.last += NGHTTP2_FRAME_HDLEN;
2414 nghttp2_put_uint16be(buf.last, sizeof(origin) - 1);
2416 buf.last = nghttp2_cpymem(buf.last, origin, sizeof(origin) - 1);
2417 buf.last = nghttp2_cpymem(buf.last, field_value, sizeof(field_value) - 1);
2419 ud.invalid_frame_recv_cb_called = 0;
2420 rv = nghttp2_session_mem_recv(session, buf.pos, nghttp2_buf_len(&buf));
2422 CU_ASSERT((ssize_t)nghttp2_buf_len(&buf) == rv);
2423 CU_ASSERT(1 == ud.invalid_frame_recv_cb_called);
2425 nghttp2_session_del(session);
2427 /* empty origin to stream 0 */
2428 nghttp2_buf_reset(&buf);
2430 nghttp2_session_client_new2(&session, &callbacks, &ud, option);
2432 nghttp2_frame_hd_init(&hd, 2 + sizeof(field_value) - 1, NGHTTP2_ALTSVC,
2433 NGHTTP2_FLAG_NONE, 0);
2434 nghttp2_frame_pack_frame_hd(buf.last, &hd);
2435 buf.last += NGHTTP2_FRAME_HDLEN;
2436 nghttp2_put_uint16be(buf.last, 0);
2438 buf.last = nghttp2_cpymem(buf.last, field_value, sizeof(field_value) - 1);
2440 ud.invalid_frame_recv_cb_called = 0;
2441 rv = nghttp2_session_mem_recv(session, buf.pos, nghttp2_buf_len(&buf));
2443 CU_ASSERT((ssize_t)nghttp2_buf_len(&buf) == rv);
2444 CU_ASSERT(1 == ud.invalid_frame_recv_cb_called);
2446 nghttp2_session_del(session);
2448 /* send large frame (16KiB) */
2449 nghttp2_buf_reset(&buf);
2451 nghttp2_session_client_new2(&session, &callbacks, &ud, option);
2453 nghttp2_frame_hd_init(&hd, NGHTTP2_MAX_FRAME_SIZE_MIN, NGHTTP2_ALTSVC,
2454 NGHTTP2_FLAG_NONE, 0);
2455 nghttp2_frame_pack_frame_hd(buf.last, &hd);
2456 buf.last += NGHTTP2_FRAME_HDLEN;
2457 nghttp2_put_uint16be(buf.last, sizeof(origin) - 1);
2459 buf.last = nghttp2_cpymem(buf.last, origin, sizeof(origin) - 1);
2460 memset(buf.last, 0, nghttp2_buf_avail(&buf));
2461 buf.last += nghttp2_buf_avail(&buf);
2463 ud.frame_recv_cb_called = 0;
2464 rv = nghttp2_session_mem_recv(session, buf.pos, nghttp2_buf_len(&buf));
2466 CU_ASSERT((ssize_t)nghttp2_buf_len(&buf) == rv);
2467 CU_ASSERT(1 == ud.frame_recv_cb_called);
2468 CU_ASSERT(NGHTTP2_ALTSVC == ud.recv_frame_hd.type);
2469 CU_ASSERT(NGHTTP2_MAX_FRAME_SIZE_MIN == ud.recv_frame_hd.length);
2471 nghttp2_session_del(session);
2473 /* send too large frame */
2474 nghttp2_buf_reset(&buf);
2476 nghttp2_session_client_new2(&session, &callbacks, &ud, option);
2478 session->local_settings.max_frame_size = NGHTTP2_MAX_FRAME_SIZE_MIN - 1;
2480 nghttp2_frame_hd_init(&hd, NGHTTP2_MAX_FRAME_SIZE_MIN + 1, NGHTTP2_ALTSVC,
2481 NGHTTP2_FLAG_NONE, 0);
2482 nghttp2_frame_pack_frame_hd(buf.last, &hd);
2483 buf.last += NGHTTP2_FRAME_HDLEN;
2484 nghttp2_put_uint16be(buf.last, sizeof(origin) - 1);
2486 buf.last = nghttp2_cpymem(buf.last, origin, sizeof(origin) - 1);
2487 memset(buf.last, 0, nghttp2_buf_avail(&buf));
2488 buf.last += nghttp2_buf_avail(&buf);
2490 ud.frame_recv_cb_called = 0;
2491 rv = nghttp2_session_mem_recv(session, buf.pos, nghttp2_buf_len(&buf));
2493 CU_ASSERT((ssize_t)nghttp2_buf_len(&buf) == rv);
2494 CU_ASSERT(0 == ud.frame_recv_cb_called);
2496 nghttp2_session_del(session);
2498 /* received by server */
2499 nghttp2_buf_reset(&buf);
2501 nghttp2_session_server_new2(&session, &callbacks, &ud, option);
2503 nghttp2_frame_hd_init(&hd, 2 + sizeof(origin) - 1 + sizeof(field_value) - 1,
2504 NGHTTP2_ALTSVC, NGHTTP2_FLAG_NONE, 0);
2505 nghttp2_frame_pack_frame_hd(buf.last, &hd);
2506 buf.last += NGHTTP2_FRAME_HDLEN;
2507 nghttp2_put_uint16be(buf.last, sizeof(origin) - 1);
2509 buf.last = nghttp2_cpymem(buf.last, origin, sizeof(origin) - 1);
2510 buf.last = nghttp2_cpymem(buf.last, field_value, sizeof(field_value) - 1);
2512 ud.frame_recv_cb_called = 0;
2513 rv = nghttp2_session_mem_recv(session, buf.pos, nghttp2_buf_len(&buf));
2515 CU_ASSERT((ssize_t)nghttp2_buf_len(&buf) == rv);
2516 CU_ASSERT(0 == ud.frame_recv_cb_called);
2518 nghttp2_session_del(session);
2520 nghttp2_buf_free(&buf, mem);
2521 nghttp2_option_del(option);
2524 void test_nghttp2_session_recv_origin(void) {
2525 nghttp2_session *session;
2526 nghttp2_session_callbacks callbacks;
2530 nghttp2_option *option;
2531 nghttp2_extension frame;
2532 nghttp2_ext_origin origin;
2533 nghttp2_origin_entry ov;
2534 static const uint8_t nghttp2[] = "https://nghttp2.org";
2536 frame_pack_bufs_init(&bufs);
2538 frame.payload = &origin;
2540 ov.origin = (uint8_t *)nghttp2;
2541 ov.origin_len = sizeof(nghttp2) - 1;
2543 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
2545 callbacks.on_frame_recv_callback = on_frame_recv_callback;
2547 nghttp2_option_new(&option);
2548 nghttp2_option_set_builtin_recv_extension_type(option, NGHTTP2_ORIGIN);
2550 nghttp2_session_client_new2(&session, &callbacks, &ud, option);
2552 nghttp2_frame_origin_init(&frame, &ov, 1);
2554 rv = nghttp2_frame_pack_origin(&bufs, &frame);
2558 ud.frame_recv_cb_called = 0;
2559 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
2560 nghttp2_bufs_len(&bufs));
2562 CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == rv);
2563 CU_ASSERT(1 == ud.frame_recv_cb_called);
2564 CU_ASSERT(NGHTTP2_ORIGIN == ud.recv_frame_hd.type);
2565 CU_ASSERT(NGHTTP2_FLAG_NONE == ud.recv_frame_hd.flags);
2566 CU_ASSERT(0 == ud.recv_frame_hd.stream_id);
2568 nghttp2_session_del(session);
2569 nghttp2_bufs_reset(&bufs);
2571 /* The length of origin is larger than payload length. */
2572 nghttp2_session_client_new2(&session, &callbacks, &ud, option);
2574 nghttp2_frame_origin_init(&frame, &ov, 1);
2575 rv = nghttp2_frame_pack_origin(&bufs, &frame);
2579 nghttp2_put_uint16be(bufs.head->buf.pos + NGHTTP2_FRAME_HDLEN,
2580 (uint16_t)sizeof(nghttp2));
2582 ud.frame_recv_cb_called = 0;
2583 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
2584 nghttp2_bufs_len(&bufs));
2586 CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == rv);
2587 CU_ASSERT(0 == ud.frame_recv_cb_called);
2589 nghttp2_session_del(session);
2590 nghttp2_bufs_reset(&bufs);
2592 /* A frame should be ignored if it is sent to a stream other than
2594 nghttp2_session_client_new2(&session, &callbacks, &ud, option);
2596 nghttp2_frame_origin_init(&frame, &ov, 1);
2597 frame.hd.stream_id = 1;
2598 rv = nghttp2_frame_pack_origin(&bufs, &frame);
2602 ud.frame_recv_cb_called = 0;
2603 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
2604 nghttp2_bufs_len(&bufs));
2606 CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == rv);
2607 CU_ASSERT(0 == ud.frame_recv_cb_called);
2609 nghttp2_session_del(session);
2610 nghttp2_bufs_reset(&bufs);
2612 /* A frame should be ignored if the reserved flag is set */
2613 nghttp2_session_client_new2(&session, &callbacks, &ud, option);
2615 nghttp2_frame_origin_init(&frame, &ov, 1);
2616 frame.hd.flags = 0xf0;
2617 rv = nghttp2_frame_pack_origin(&bufs, &frame);
2621 ud.frame_recv_cb_called = 0;
2622 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
2623 nghttp2_bufs_len(&bufs));
2625 CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == rv);
2626 CU_ASSERT(0 == ud.frame_recv_cb_called);
2628 nghttp2_session_del(session);
2629 nghttp2_bufs_reset(&bufs);
2631 /* A frame should be ignored if it is received by a server. */
2632 nghttp2_session_server_new2(&session, &callbacks, &ud, option);
2634 nghttp2_frame_origin_init(&frame, &ov, 1);
2635 rv = nghttp2_frame_pack_origin(&bufs, &frame);
2639 ud.frame_recv_cb_called = 0;
2640 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
2641 nghttp2_bufs_len(&bufs));
2643 CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == rv);
2644 CU_ASSERT(0 == ud.frame_recv_cb_called);
2646 nghttp2_session_del(session);
2647 nghttp2_bufs_reset(&bufs);
2649 /* Receiving empty ORIGIN frame */
2650 nghttp2_session_client_new2(&session, &callbacks, &ud, option);
2652 nghttp2_frame_origin_init(&frame, NULL, 0);
2653 rv = nghttp2_frame_pack_origin(&bufs, &frame);
2657 ud.frame_recv_cb_called = 0;
2658 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
2659 nghttp2_bufs_len(&bufs));
2661 CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == rv);
2662 CU_ASSERT(1 == ud.frame_recv_cb_called);
2663 CU_ASSERT(NGHTTP2_ORIGIN == ud.recv_frame_hd.type);
2665 nghttp2_session_del(session);
2667 nghttp2_option_del(option);
2668 nghttp2_bufs_free(&bufs);
2671 void test_nghttp2_session_continue(void) {
2672 nghttp2_session *session;
2673 nghttp2_session_callbacks callbacks;
2674 my_user_data user_data;
2675 const nghttp2_nv nv1[] = {MAKE_NV(":method", "GET"), MAKE_NV(":path", "/")};
2676 const nghttp2_nv nv2[] = {MAKE_NV("user-agent", "nghttp2/1.0.0"),
2677 MAKE_NV("alpha", "bravo")};
2680 size_t framelen1, framelen2;
2682 uint8_t buffer[4096];
2683 nghttp2_buf databuf;
2684 nghttp2_frame frame;
2687 const nghttp2_frame *recv_frame;
2688 nghttp2_frame_hd data_hd;
2689 nghttp2_hd_deflater deflater;
2692 mem = nghttp2_mem_default();
2693 frame_pack_bufs_init(&bufs);
2694 nghttp2_buf_wrap_init(&databuf, buffer, sizeof(buffer));
2696 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
2697 callbacks.send_callback = null_send_callback;
2698 callbacks.on_frame_recv_callback = on_frame_recv_callback;
2699 callbacks.on_data_chunk_recv_callback = pause_on_data_chunk_recv_callback;
2700 callbacks.on_header_callback = pause_on_header_callback;
2701 callbacks.on_begin_headers_callback = on_begin_headers_callback;
2703 nghttp2_session_server_new(&session, &callbacks, &user_data);
2704 /* disable strict HTTP layering checks */
2705 session->opt_flags |= NGHTTP2_OPTMASK_NO_HTTP_MESSAGING;
2707 nghttp2_hd_deflate_init(&deflater, mem);
2709 /* Make 2 HEADERS frames */
2710 nvlen = ARRLEN(nv1);
2711 nghttp2_nv_array_copy(&nva, nv1, nvlen, mem);
2712 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 1,
2713 NGHTTP2_HCAT_HEADERS, NULL, nva, nvlen);
2714 rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
2717 CU_ASSERT(nghttp2_bufs_len(&bufs) > 0);
2719 nghttp2_frame_headers_free(&frame.headers, mem);
2721 buf = &bufs.head->buf;
2722 assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
2724 framelen1 = nghttp2_buf_len(buf);
2725 databuf.last = nghttp2_cpymem(databuf.last, buf->pos, nghttp2_buf_len(buf));
2727 nvlen = ARRLEN(nv2);
2728 nghttp2_nv_array_copy(&nva, nv2, nvlen, mem);
2729 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 3,
2730 NGHTTP2_HCAT_HEADERS, NULL, nva, nvlen);
2731 nghttp2_bufs_reset(&bufs);
2732 rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
2735 CU_ASSERT(nghttp2_bufs_len(&bufs) > 0);
2737 nghttp2_frame_headers_free(&frame.headers, mem);
2739 assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
2741 framelen2 = nghttp2_buf_len(buf);
2742 databuf.last = nghttp2_cpymem(databuf.last, buf->pos, nghttp2_buf_len(buf));
2744 /* Receive 1st HEADERS and pause */
2745 user_data.begin_headers_cb_called = 0;
2746 user_data.header_cb_called = 0;
2748 nghttp2_session_mem_recv(session, databuf.pos, nghttp2_buf_len(&databuf));
2753 recv_frame = user_data.frame;
2754 CU_ASSERT(NGHTTP2_HEADERS == recv_frame->hd.type);
2755 CU_ASSERT(framelen1 - NGHTTP2_FRAME_HDLEN == recv_frame->hd.length);
2757 CU_ASSERT(1 == user_data.begin_headers_cb_called);
2758 CU_ASSERT(1 == user_data.header_cb_called);
2760 CU_ASSERT(nghttp2_nv_equal(&nv1[0], &user_data.nv));
2762 /* get 2nd header field */
2763 user_data.begin_headers_cb_called = 0;
2764 user_data.header_cb_called = 0;
2766 nghttp2_session_mem_recv(session, databuf.pos, nghttp2_buf_len(&databuf));
2771 CU_ASSERT(0 == user_data.begin_headers_cb_called);
2772 CU_ASSERT(1 == user_data.header_cb_called);
2774 CU_ASSERT(nghttp2_nv_equal(&nv1[1], &user_data.nv));
2776 /* will call end_headers_callback and receive 2nd HEADERS and pause */
2777 user_data.begin_headers_cb_called = 0;
2778 user_data.header_cb_called = 0;
2780 nghttp2_session_mem_recv(session, databuf.pos, nghttp2_buf_len(&databuf));
2785 recv_frame = user_data.frame;
2786 CU_ASSERT(NGHTTP2_HEADERS == recv_frame->hd.type);
2787 CU_ASSERT(framelen2 - NGHTTP2_FRAME_HDLEN == recv_frame->hd.length);
2789 CU_ASSERT(1 == user_data.begin_headers_cb_called);
2790 CU_ASSERT(1 == user_data.header_cb_called);
2792 CU_ASSERT(nghttp2_nv_equal(&nv2[0], &user_data.nv));
2794 /* get 2nd header field */
2795 user_data.begin_headers_cb_called = 0;
2796 user_data.header_cb_called = 0;
2798 nghttp2_session_mem_recv(session, databuf.pos, nghttp2_buf_len(&databuf));
2803 CU_ASSERT(0 == user_data.begin_headers_cb_called);
2804 CU_ASSERT(1 == user_data.header_cb_called);
2806 CU_ASSERT(nghttp2_nv_equal(&nv2[1], &user_data.nv));
2808 /* No input data, frame_recv_callback is called */
2809 user_data.begin_headers_cb_called = 0;
2810 user_data.header_cb_called = 0;
2811 user_data.frame_recv_cb_called = 0;
2813 nghttp2_session_mem_recv(session, databuf.pos, nghttp2_buf_len(&databuf));
2818 CU_ASSERT(0 == user_data.begin_headers_cb_called);
2819 CU_ASSERT(0 == user_data.header_cb_called);
2820 CU_ASSERT(1 == user_data.frame_recv_cb_called);
2823 nghttp2_frame_hd_init(&data_hd, 16, NGHTTP2_DATA, NGHTTP2_FLAG_NONE, 1);
2825 nghttp2_buf_reset(&databuf);
2826 nghttp2_frame_pack_frame_hd(databuf.pos, &data_hd);
2828 /* Intentionally specify larger buffer size to see pause is kicked
2830 databuf.last = databuf.end;
2832 user_data.frame_recv_cb_called = 0;
2834 nghttp2_session_mem_recv(session, databuf.pos, nghttp2_buf_len(&databuf));
2836 CU_ASSERT(16 + NGHTTP2_FRAME_HDLEN == rv);
2837 CU_ASSERT(0 == user_data.frame_recv_cb_called);
2839 /* Next nghttp2_session_mem_recv invokes on_frame_recv_callback and
2840 pause again in on_data_chunk_recv_callback since we pass same
2842 user_data.frame_recv_cb_called = 0;
2844 nghttp2_session_mem_recv(session, databuf.pos, nghttp2_buf_len(&databuf));
2845 CU_ASSERT(16 + NGHTTP2_FRAME_HDLEN == rv);
2846 CU_ASSERT(1 == user_data.frame_recv_cb_called);
2848 /* And finally call on_frame_recv_callback with 0 size input */
2849 user_data.frame_recv_cb_called = 0;
2850 rv = nghttp2_session_mem_recv(session, NULL, 0);
2852 CU_ASSERT(1 == user_data.frame_recv_cb_called);
2854 nghttp2_bufs_free(&bufs);
2855 nghttp2_hd_deflate_free(&deflater);
2856 nghttp2_session_del(session);
2859 void test_nghttp2_session_add_frame(void) {
2860 nghttp2_session *session;
2861 nghttp2_session_callbacks callbacks;
2863 my_user_data user_data;
2864 nghttp2_outbound_item *item;
2865 nghttp2_frame *frame;
2870 mem = nghttp2_mem_default();
2871 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
2872 callbacks.send_callback = accumulator_send_callback;
2875 user_data.acc = &acc;
2877 CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, &user_data));
2879 item = mem->malloc(sizeof(nghttp2_outbound_item), NULL);
2881 nghttp2_outbound_item_init(item);
2883 frame = &item->frame;
2885 nvlen = ARRLEN(reqnv);
2886 nghttp2_nv_array_copy(&nva, reqnv, nvlen, mem);
2888 nghttp2_frame_headers_init(
2889 &frame->headers, NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PRIORITY,
2890 (int32_t)session->next_stream_id, NGHTTP2_HCAT_REQUEST, NULL, nva, nvlen);
2892 session->next_stream_id += 2;
2894 CU_ASSERT(0 == nghttp2_session_add_item(session, item));
2895 CU_ASSERT(NULL != nghttp2_outbound_queue_top(&session->ob_syn));
2896 CU_ASSERT(0 == nghttp2_session_send(session));
2897 CU_ASSERT(NGHTTP2_HEADERS == acc.buf[3]);
2898 CU_ASSERT((NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PRIORITY) == acc.buf[4]);
2899 /* check stream id */
2900 CU_ASSERT(1 == nghttp2_get_uint32(&acc.buf[5]));
2902 nghttp2_session_del(session);
2905 void test_nghttp2_session_on_request_headers_received(void) {
2906 nghttp2_session *session;
2907 nghttp2_session_callbacks callbacks;
2908 my_user_data user_data;
2909 nghttp2_frame frame;
2910 nghttp2_stream *stream;
2911 int32_t stream_id = 1;
2912 nghttp2_nv malformed_nva[] = {MAKE_NV(":path", "\x01")};
2915 nghttp2_priority_spec pri_spec;
2918 mem = nghttp2_mem_default();
2919 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
2920 callbacks.on_begin_headers_callback = on_begin_headers_callback;
2921 callbacks.on_invalid_frame_recv_callback = on_invalid_frame_recv_callback;
2923 nghttp2_session_server_new(&session, &callbacks, &user_data);
2925 nghttp2_priority_spec_init(&pri_spec, 0, 255, 0);
2927 nghttp2_frame_headers_init(
2928 &frame.headers, NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PRIORITY,
2929 stream_id, NGHTTP2_HCAT_REQUEST, &pri_spec, NULL, 0);
2931 user_data.begin_headers_cb_called = 0;
2932 user_data.invalid_frame_recv_cb_called = 0;
2934 CU_ASSERT(0 == nghttp2_session_on_request_headers_received(session, &frame));
2935 CU_ASSERT(1 == user_data.begin_headers_cb_called);
2936 stream = nghttp2_session_get_stream(session, stream_id);
2937 CU_ASSERT(NGHTTP2_STREAM_OPENING == stream->state);
2938 CU_ASSERT(255 == stream->weight);
2940 nghttp2_frame_headers_free(&frame.headers, mem);
2942 /* More than un-ACKed max concurrent streams leads REFUSED_STREAM */
2943 session->pending_local_max_concurrent_stream = 1;
2944 nghttp2_frame_headers_init(&frame.headers,
2945 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PRIORITY,
2946 3, NGHTTP2_HCAT_HEADERS, NULL, NULL, 0);
2947 user_data.invalid_frame_recv_cb_called = 0;
2948 CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
2949 nghttp2_session_on_request_headers_received(session, &frame));
2950 CU_ASSERT(1 == user_data.invalid_frame_recv_cb_called);
2951 CU_ASSERT(0 == (session->goaway_flags & NGHTTP2_GOAWAY_TERM_ON_SEND));
2953 nghttp2_frame_headers_free(&frame.headers, mem);
2954 session->local_settings.max_concurrent_streams =
2955 NGHTTP2_DEFAULT_MAX_CONCURRENT_STREAMS;
2957 /* Stream ID less than or equal to the previouly received request
2958 HEADERS is just ignored due to race condition */
2959 nghttp2_frame_headers_init(&frame.headers,
2960 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PRIORITY,
2961 3, NGHTTP2_HCAT_HEADERS, NULL, NULL, 0);
2962 user_data.invalid_frame_recv_cb_called = 0;
2963 CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
2964 nghttp2_session_on_request_headers_received(session, &frame));
2965 CU_ASSERT(0 == user_data.invalid_frame_recv_cb_called);
2966 CU_ASSERT(0 == (session->goaway_flags & NGHTTP2_GOAWAY_TERM_ON_SEND));
2968 nghttp2_frame_headers_free(&frame.headers, mem);
2970 /* Stream ID is our side and it is idle stream ID, then treat it as
2972 nghttp2_frame_headers_init(&frame.headers,
2973 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PRIORITY,
2974 2, NGHTTP2_HCAT_HEADERS, NULL, NULL, 0);
2975 user_data.invalid_frame_recv_cb_called = 0;
2976 CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
2977 nghttp2_session_on_request_headers_received(session, &frame));
2978 CU_ASSERT(1 == user_data.invalid_frame_recv_cb_called);
2979 CU_ASSERT(session->goaway_flags & NGHTTP2_GOAWAY_TERM_ON_SEND);
2981 nghttp2_frame_headers_free(&frame.headers, mem);
2983 nghttp2_session_del(session);
2985 /* Check malformed headers. The library accept it. */
2986 nghttp2_session_server_new(&session, &callbacks, &user_data);
2988 nvlen = ARRLEN(malformed_nva);
2989 nghttp2_nv_array_copy(&nva, malformed_nva, nvlen, mem);
2990 nghttp2_frame_headers_init(&frame.headers,
2991 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PRIORITY,
2992 1, NGHTTP2_HCAT_HEADERS, NULL, nva, nvlen);
2993 user_data.begin_headers_cb_called = 0;
2994 user_data.invalid_frame_recv_cb_called = 0;
2995 CU_ASSERT(0 == nghttp2_session_on_request_headers_received(session, &frame));
2996 CU_ASSERT(1 == user_data.begin_headers_cb_called);
2997 CU_ASSERT(0 == user_data.invalid_frame_recv_cb_called);
2999 nghttp2_frame_headers_free(&frame.headers, mem);
3001 nghttp2_session_del(session);
3003 /* Check client side */
3004 nghttp2_session_client_new(&session, &callbacks, &user_data);
3006 /* Receiving peer's idle stream ID is subject to connection error */
3007 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 2,
3008 NGHTTP2_HCAT_REQUEST, NULL, NULL, 0);
3010 user_data.invalid_frame_recv_cb_called = 0;
3011 CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
3012 nghttp2_session_on_request_headers_received(session, &frame));
3013 CU_ASSERT(1 == user_data.invalid_frame_recv_cb_called);
3014 CU_ASSERT(session->goaway_flags & NGHTTP2_GOAWAY_TERM_ON_SEND);
3016 nghttp2_frame_headers_free(&frame.headers, mem);
3018 nghttp2_session_del(session);
3020 nghttp2_session_client_new(&session, &callbacks, &user_data);
3022 /* Receiving our's idle stream ID is subject to connection error */
3023 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 1,
3024 NGHTTP2_HCAT_REQUEST, NULL, NULL, 0);
3026 user_data.invalid_frame_recv_cb_called = 0;
3027 CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
3028 nghttp2_session_on_request_headers_received(session, &frame));
3029 CU_ASSERT(1 == user_data.invalid_frame_recv_cb_called);
3030 CU_ASSERT(session->goaway_flags & NGHTTP2_GOAWAY_TERM_ON_SEND);
3032 nghttp2_frame_headers_free(&frame.headers, mem);
3034 nghttp2_session_del(session);
3036 nghttp2_session_client_new(&session, &callbacks, &user_data);
3038 session->next_stream_id = 5;
3039 session->last_sent_stream_id = 3;
3041 /* Stream ID which is not idle and not in stream map is just
3043 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 3,
3044 NGHTTP2_HCAT_REQUEST, NULL, NULL, 0);
3046 user_data.invalid_frame_recv_cb_called = 0;
3047 CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
3048 nghttp2_session_on_request_headers_received(session, &frame));
3049 CU_ASSERT(0 == user_data.invalid_frame_recv_cb_called);
3050 CU_ASSERT(0 == (session->goaway_flags & NGHTTP2_GOAWAY_TERM_ON_SEND));
3052 nghttp2_frame_headers_free(&frame.headers, mem);
3054 nghttp2_session_del(session);
3056 nghttp2_session_server_new(&session, &callbacks, &user_data);
3058 /* Stream ID which is equal to local_last_stream_id is ok. */
3059 session->local_last_stream_id = 3;
3061 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 3,
3062 NGHTTP2_HCAT_REQUEST, NULL, NULL, 0);
3064 CU_ASSERT(0 == nghttp2_session_on_request_headers_received(session, &frame));
3066 nghttp2_frame_headers_free(&frame.headers, mem);
3068 /* If GOAWAY has been sent, new stream is ignored */
3069 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 5,
3070 NGHTTP2_HCAT_REQUEST, NULL, NULL, 0);
3072 session->goaway_flags |= NGHTTP2_GOAWAY_SENT;
3073 user_data.invalid_frame_recv_cb_called = 0;
3074 CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
3075 nghttp2_session_on_request_headers_received(session, &frame));
3076 CU_ASSERT(0 == user_data.invalid_frame_recv_cb_called);
3077 CU_ASSERT(0 == (session->goaway_flags & NGHTTP2_GOAWAY_TERM_ON_SEND));
3079 nghttp2_frame_headers_free(&frame.headers, mem);
3081 nghttp2_session_del(session);
3083 nghttp2_session_server_new(&session, &callbacks, &user_data);
3085 /* HEADERS to closed stream */
3086 stream = open_recv_stream(session, 1);
3087 nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_RD);
3088 nghttp2_session_close_stream(session, 1, NGHTTP2_NO_ERROR);
3090 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 1,
3091 NGHTTP2_HCAT_REQUEST, NULL, NULL, 0);
3093 CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
3094 nghttp2_session_on_request_headers_received(session, &frame));
3095 CU_ASSERT(session->goaway_flags & NGHTTP2_GOAWAY_TERM_ON_SEND);
3097 nghttp2_frame_headers_free(&frame.headers, mem);
3099 nghttp2_session_del(session);
3102 void test_nghttp2_session_on_response_headers_received(void) {
3103 nghttp2_session *session;
3104 nghttp2_session_callbacks callbacks;
3105 my_user_data user_data;
3106 nghttp2_frame frame;
3107 nghttp2_stream *stream;
3110 mem = nghttp2_mem_default();
3111 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
3112 callbacks.on_begin_headers_callback = on_begin_headers_callback;
3113 callbacks.on_invalid_frame_recv_callback = on_invalid_frame_recv_callback;
3115 nghttp2_session_client_new(&session, &callbacks, &user_data);
3116 stream = open_sent_stream2(session, 1, NGHTTP2_STREAM_OPENING);
3117 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 1,
3118 NGHTTP2_HCAT_HEADERS, NULL, NULL, 0);
3120 user_data.begin_headers_cb_called = 0;
3121 user_data.invalid_frame_recv_cb_called = 0;
3123 CU_ASSERT(0 == nghttp2_session_on_response_headers_received(session, &frame,
3125 CU_ASSERT(1 == user_data.begin_headers_cb_called);
3126 CU_ASSERT(NGHTTP2_STREAM_OPENED == stream->state);
3128 nghttp2_frame_headers_free(&frame.headers, mem);
3129 nghttp2_session_del(session);
3132 void test_nghttp2_session_on_headers_received(void) {
3133 nghttp2_session *session;
3134 nghttp2_session_callbacks callbacks;
3135 my_user_data user_data;
3136 nghttp2_frame frame;
3137 nghttp2_stream *stream;
3140 mem = nghttp2_mem_default();
3141 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
3142 callbacks.on_begin_headers_callback = on_begin_headers_callback;
3143 callbacks.on_invalid_frame_recv_callback = on_invalid_frame_recv_callback;
3145 nghttp2_session_client_new(&session, &callbacks, &user_data);
3146 stream = open_sent_stream2(session, 1, NGHTTP2_STREAM_OPENED);
3147 nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_WR);
3148 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 1,
3149 NGHTTP2_HCAT_HEADERS, NULL, NULL, 0);
3151 user_data.begin_headers_cb_called = 0;
3152 user_data.invalid_frame_recv_cb_called = 0;
3154 CU_ASSERT(0 == nghttp2_session_on_headers_received(session, &frame, stream));
3155 CU_ASSERT(1 == user_data.begin_headers_cb_called);
3156 CU_ASSERT(NGHTTP2_STREAM_OPENED == stream->state);
3159 frame.hd.flags |= NGHTTP2_FLAG_END_STREAM;
3161 CU_ASSERT(0 == nghttp2_session_on_headers_received(session, &frame, stream));
3162 CU_ASSERT(2 == user_data.begin_headers_cb_called);
3164 /* Check to see when NGHTTP2_STREAM_CLOSING, incoming HEADERS is
3166 stream = open_sent_stream2(session, 3, NGHTTP2_STREAM_CLOSING);
3167 frame.hd.stream_id = 3;
3168 frame.hd.flags = NGHTTP2_FLAG_END_HEADERS;
3169 CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
3170 nghttp2_session_on_headers_received(session, &frame, stream));
3171 /* See no counters are updated */
3172 CU_ASSERT(2 == user_data.begin_headers_cb_called);
3173 CU_ASSERT(0 == user_data.invalid_frame_recv_cb_called);
3175 /* Server initiated stream */
3176 stream = open_recv_stream(session, 2);
3178 frame.hd.flags = NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM;
3179 frame.hd.stream_id = 2;
3181 CU_ASSERT(0 == nghttp2_session_on_headers_received(session, &frame, stream));
3182 CU_ASSERT(3 == user_data.begin_headers_cb_called);
3183 CU_ASSERT(NGHTTP2_STREAM_OPENED == stream->state);
3185 nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_RD);
3187 /* Further reception of HEADERS is subject to stream error */
3188 CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
3189 nghttp2_session_on_headers_received(session, &frame, stream));
3190 CU_ASSERT(1 == user_data.invalid_frame_recv_cb_called);
3192 nghttp2_frame_headers_free(&frame.headers, mem);
3194 nghttp2_session_del(session);
3197 void test_nghttp2_session_on_push_response_headers_received(void) {
3198 nghttp2_session *session;
3199 nghttp2_session_callbacks callbacks;
3200 my_user_data user_data;
3201 nghttp2_frame frame;
3202 nghttp2_stream *stream;
3203 nghttp2_outbound_item *item;
3206 mem = nghttp2_mem_default();
3207 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
3208 callbacks.send_callback = null_send_callback;
3209 callbacks.on_begin_headers_callback = on_begin_headers_callback;
3210 callbacks.on_invalid_frame_recv_callback = on_invalid_frame_recv_callback;
3212 nghttp2_session_client_new(&session, &callbacks, &user_data);
3213 stream = open_recv_stream2(session, 2, NGHTTP2_STREAM_RESERVED);
3214 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 2,
3215 NGHTTP2_HCAT_HEADERS, NULL, NULL, 0);
3216 /* nghttp2_session_on_push_response_headers_received assumes
3217 stream's state is NGHTTP2_STREAM_RESERVED and session->server is
3220 user_data.begin_headers_cb_called = 0;
3221 user_data.invalid_frame_recv_cb_called = 0;
3223 CU_ASSERT(1 == session->num_incoming_reserved_streams);
3224 CU_ASSERT(0 == nghttp2_session_on_push_response_headers_received(
3225 session, &frame, stream));
3226 CU_ASSERT(1 == user_data.begin_headers_cb_called);
3227 CU_ASSERT(0 == session->num_incoming_reserved_streams);
3228 CU_ASSERT(NGHTTP2_STREAM_OPENED == stream->state);
3229 CU_ASSERT(1 == session->num_incoming_streams);
3230 CU_ASSERT(0 == (stream->flags & NGHTTP2_STREAM_FLAG_PUSH));
3232 /* If un-ACKed max concurrent streams limit is exceeded,
3234 session->pending_local_max_concurrent_stream = 1;
3235 stream = open_recv_stream2(session, 4, NGHTTP2_STREAM_RESERVED);
3236 frame.hd.stream_id = 4;
3237 CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
3238 nghttp2_session_on_push_response_headers_received(session, &frame,
3240 item = nghttp2_session_get_next_ob_item(session);
3241 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
3242 CU_ASSERT(NGHTTP2_REFUSED_STREAM == item->frame.rst_stream.error_code);
3243 CU_ASSERT(1 == session->num_incoming_streams);
3244 CU_ASSERT(1 == session->num_incoming_reserved_streams);
3246 CU_ASSERT(0 == nghttp2_session_send(session));
3247 CU_ASSERT(1 == session->num_incoming_streams);
3249 /* If ACKed max concurrent streams limit is exceeded, GOAWAY is
3251 session->local_settings.max_concurrent_streams = 1;
3253 stream = open_recv_stream2(session, 6, NGHTTP2_STREAM_RESERVED);
3254 frame.hd.stream_id = 6;
3256 CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
3257 nghttp2_session_on_push_response_headers_received(session, &frame,
3259 item = nghttp2_session_get_next_ob_item(session);
3260 CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
3261 CU_ASSERT(NGHTTP2_PROTOCOL_ERROR == item->frame.goaway.error_code);
3262 CU_ASSERT(1 == session->num_incoming_streams);
3263 CU_ASSERT(1 == session->num_incoming_reserved_streams);
3265 nghttp2_frame_headers_free(&frame.headers, mem);
3266 nghttp2_session_del(session);
3269 void test_nghttp2_session_on_priority_received(void) {
3270 nghttp2_session *session;
3271 nghttp2_session_callbacks callbacks;
3272 my_user_data user_data;
3273 nghttp2_frame frame;
3274 nghttp2_stream *stream, *dep_stream;
3275 nghttp2_priority_spec pri_spec;
3276 nghttp2_outbound_item *item;
3278 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
3279 callbacks.on_frame_recv_callback = on_frame_recv_callback;
3280 callbacks.on_invalid_frame_recv_callback = on_invalid_frame_recv_callback;
3282 nghttp2_session_server_new(&session, &callbacks, &user_data);
3283 stream = open_recv_stream(session, 1);
3285 nghttp2_priority_spec_init(&pri_spec, 0, 2, 0);
3287 nghttp2_frame_priority_init(&frame.priority, 1, &pri_spec);
3289 /* depend on stream 0 */
3290 CU_ASSERT(0 == nghttp2_session_on_priority_received(session, &frame));
3292 CU_ASSERT(2 == stream->weight);
3294 stream = open_sent_stream(session, 2);
3295 dep_stream = open_recv_stream(session, 3);
3297 frame.hd.stream_id = 2;
3299 /* using dependency stream */
3300 nghttp2_priority_spec_init(&frame.priority.pri_spec, 3, 1, 0);
3302 CU_ASSERT(0 == nghttp2_session_on_priority_received(session, &frame));
3303 CU_ASSERT(dep_stream == stream->dep_prev);
3305 /* PRIORITY against idle stream */
3307 frame.hd.stream_id = 100;
3309 CU_ASSERT(0 == nghttp2_session_on_priority_received(session, &frame));
3311 stream = nghttp2_session_get_stream_raw(session, frame.hd.stream_id);
3313 CU_ASSERT(NGHTTP2_STREAM_IDLE == stream->state);
3314 CU_ASSERT(dep_stream == stream->dep_prev);
3316 nghttp2_frame_priority_free(&frame.priority);
3317 nghttp2_session_del(session);
3319 /* Check dep_stream_id == stream_id case */
3320 nghttp2_session_server_new(&session, &callbacks, &user_data);
3321 open_recv_stream(session, 1);
3323 nghttp2_priority_spec_init(&pri_spec, 1, 0, 0);
3325 nghttp2_frame_priority_init(&frame.priority, 1, &pri_spec);
3327 CU_ASSERT(0 == nghttp2_session_on_priority_received(session, &frame));
3329 item = nghttp2_session_get_next_ob_item(session);
3331 CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
3333 nghttp2_frame_priority_free(&frame.priority);
3334 nghttp2_session_del(session);
3336 /* Check again dep_stream_id == stream_id, and stream_id is idle */
3337 nghttp2_session_server_new(&session, &callbacks, &user_data);
3339 nghttp2_priority_spec_init(&pri_spec, 1, 16, 0);
3341 nghttp2_frame_priority_init(&frame.priority, 1, &pri_spec);
3343 CU_ASSERT(0 == nghttp2_session_on_priority_received(session, &frame));
3345 item = nghttp2_session_get_next_ob_item(session);
3347 CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
3349 nghttp2_frame_priority_free(&frame.priority);
3350 nghttp2_session_del(session);
3353 void test_nghttp2_session_on_rst_stream_received(void) {
3354 nghttp2_session *session;
3355 nghttp2_session_callbacks callbacks;
3356 my_user_data user_data;
3357 nghttp2_frame frame;
3358 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
3359 nghttp2_session_server_new(&session, &callbacks, &user_data);
3360 open_recv_stream(session, 1);
3362 nghttp2_frame_rst_stream_init(&frame.rst_stream, 1, NGHTTP2_PROTOCOL_ERROR);
3364 CU_ASSERT(0 == nghttp2_session_on_rst_stream_received(session, &frame));
3365 CU_ASSERT(NULL == nghttp2_session_get_stream(session, 1));
3367 nghttp2_frame_rst_stream_free(&frame.rst_stream);
3368 nghttp2_session_del(session);
3371 void test_nghttp2_session_on_settings_received(void) {
3372 nghttp2_session *session;
3373 nghttp2_session_callbacks callbacks;
3374 my_user_data user_data;
3375 nghttp2_stream *stream1, *stream2;
3376 nghttp2_frame frame;
3377 const size_t niv = 5;
3378 nghttp2_settings_entry iv[255];
3379 nghttp2_outbound_item *item;
3380 nghttp2_nv nv = MAKE_NV(":authority", "example.org");
3382 nghttp2_option *option;
3384 mem = nghttp2_mem_default();
3386 iv[0].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS;
3389 iv[1].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS;
3390 iv[1].value = 1000000009;
3392 iv[2].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
3393 iv[2].value = 64 * 1024;
3395 iv[3].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
3398 iv[4].settings_id = NGHTTP2_SETTINGS_ENABLE_PUSH;
3401 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
3402 callbacks.send_callback = null_send_callback;
3404 nghttp2_session_client_new(&session, &callbacks, &user_data);
3405 session->remote_settings.initial_window_size = 16 * 1024;
3407 stream1 = open_sent_stream(session, 1);
3408 stream2 = open_recv_stream(session, 2);
3410 /* Set window size for each streams and will see how settings
3411 updates these values */
3412 stream1->remote_window_size = 16 * 1024;
3413 stream2->remote_window_size = -48 * 1024;
3415 nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE,
3416 dup_iv(iv, niv), niv);
3418 CU_ASSERT(0 == nghttp2_session_on_settings_received(session, &frame, 0));
3419 CU_ASSERT(1000000009 == session->remote_settings.max_concurrent_streams);
3420 CU_ASSERT(64 * 1024 == session->remote_settings.initial_window_size);
3421 CU_ASSERT(1024 == session->remote_settings.header_table_size);
3422 CU_ASSERT(0 == session->remote_settings.enable_push);
3424 CU_ASSERT(64 * 1024 == stream1->remote_window_size);
3425 CU_ASSERT(0 == stream2->remote_window_size);
3427 frame.settings.iv[2].value = 16 * 1024;
3429 CU_ASSERT(0 == nghttp2_session_on_settings_received(session, &frame, 0));
3431 CU_ASSERT(16 * 1024 == stream1->remote_window_size);
3432 CU_ASSERT(-48 * 1024 == stream2->remote_window_size);
3434 CU_ASSERT(16 * 1024 == nghttp2_session_get_stream_remote_window_size(
3435 session, stream1->stream_id));
3436 CU_ASSERT(0 == nghttp2_session_get_stream_remote_window_size(
3437 session, stream2->stream_id));
3439 nghttp2_frame_settings_free(&frame.settings, mem);
3441 nghttp2_session_del(session);
3443 /* Check ACK with niv > 0 */
3444 nghttp2_session_server_new(&session, &callbacks, NULL);
3445 nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_ACK, dup_iv(iv, 1),
3447 CU_ASSERT(0 == nghttp2_session_on_settings_received(session, &frame, 0));
3448 item = nghttp2_session_get_next_ob_item(session);
3449 CU_ASSERT(item != NULL);
3450 CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
3452 nghttp2_frame_settings_free(&frame.settings, mem);
3453 nghttp2_session_del(session);
3455 /* Check ACK against no inflight SETTINGS */
3456 nghttp2_session_server_new(&session, &callbacks, NULL);
3457 nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_ACK, NULL, 0);
3459 CU_ASSERT(0 == nghttp2_session_on_settings_received(session, &frame, 0));
3460 item = nghttp2_session_get_next_ob_item(session);
3461 CU_ASSERT(item != NULL);
3462 CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
3464 nghttp2_frame_settings_free(&frame.settings, mem);
3465 nghttp2_session_del(session);
3467 /* Check that 2 SETTINGS_HEADER_TABLE_SIZE 0 and 4096 are included
3468 and header table size is once cleared to 0. */
3469 nghttp2_session_client_new(&session, &callbacks, NULL);
3471 nghttp2_submit_request(session, NULL, &nv, 1, NULL, NULL);
3473 nghttp2_session_send(session);
3475 CU_ASSERT(session->hd_deflater.ctx.hd_table.len > 0);
3477 iv[0].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
3480 iv[1].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
3483 nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE, dup_iv(iv, 2),
3486 CU_ASSERT(0 == nghttp2_session_on_settings_received(session, &frame, 0));
3488 CU_ASSERT(0 == session->hd_deflater.ctx.hd_table.len);
3489 CU_ASSERT(2048 == session->hd_deflater.ctx.hd_table_bufsize_max);
3490 CU_ASSERT(2048 == session->remote_settings.header_table_size);
3492 nghttp2_frame_settings_free(&frame.settings, mem);
3493 nghttp2_session_del(session);
3495 /* Check that remote SETTINGS_MAX_CONCURRENT_STREAMS is set to a value set by
3496 nghttp2_option_set_peer_max_concurrent_streams() and reset to the default
3497 value (unlimited) after receiving initial SETTINGS frame from the peer. */
3498 nghttp2_option_new(&option);
3499 nghttp2_option_set_peer_max_concurrent_streams(option, 1000);
3500 nghttp2_session_client_new2(&session, &callbacks, NULL, option);
3501 CU_ASSERT(1000 == session->remote_settings.max_concurrent_streams);
3503 nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE, NULL, 0);
3504 CU_ASSERT(0 == nghttp2_session_on_settings_received(session, &frame, 0));
3505 CU_ASSERT(NGHTTP2_DEFAULT_MAX_CONCURRENT_STREAMS ==
3506 session->remote_settings.max_concurrent_streams);
3508 nghttp2_frame_settings_free(&frame.settings, mem);
3509 nghttp2_session_del(session);
3510 nghttp2_option_del(option);
3512 /* Check too large SETTINGS_MAX_FRAME_SIZE */
3513 nghttp2_session_server_new(&session, &callbacks, NULL);
3515 iv[0].settings_id = NGHTTP2_SETTINGS_MAX_FRAME_SIZE;
3516 iv[0].value = NGHTTP2_MAX_FRAME_SIZE_MAX + 1;
3518 nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE, dup_iv(iv, 1),
3521 CU_ASSERT(0 == nghttp2_session_on_settings_received(session, &frame, 0));
3523 item = nghttp2_session_get_next_ob_item(session);
3525 CU_ASSERT(item != NULL);
3526 CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
3528 nghttp2_frame_settings_free(&frame.settings, mem);
3529 nghttp2_session_del(session);
3531 /* Check the case where stream window size overflows */
3532 nghttp2_session_server_new(&session, &callbacks, NULL);
3534 stream1 = open_recv_stream(session, 1);
3536 /* This will increment window size by 1 */
3537 nghttp2_frame_window_update_init(&frame.window_update, NGHTTP2_FLAG_NONE, 1,
3540 CU_ASSERT(0 == nghttp2_session_on_window_update_received(session, &frame));
3542 nghttp2_frame_window_update_free(&frame.window_update);
3544 iv[0].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
3545 iv[0].value = NGHTTP2_MAX_WINDOW_SIZE;
3547 nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE, dup_iv(iv, 1),
3550 /* Now window size gets NGHTTP2_MAX_WINDOW_SIZE + 1, which is
3551 unacceptable situation in protocol spec. */
3552 CU_ASSERT(0 == nghttp2_session_on_settings_received(session, &frame, 0));
3554 nghttp2_frame_settings_free(&frame.settings, mem);
3556 item = nghttp2_session_get_next_ob_item(session);
3558 CU_ASSERT(NULL != item);
3559 CU_ASSERT(NGHTTP2_SETTINGS == item->frame.hd.type);
3561 item = nghttp2_outbound_queue_top(&session->ob_reg);
3563 CU_ASSERT(NULL != item);
3564 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
3565 CU_ASSERT(NGHTTP2_STREAM_CLOSING == stream1->state);
3567 nghttp2_session_del(session);
3569 /* It is invalid that peer disables ENABLE_CONNECT_PROTOCOL once it
3570 has been enabled. */
3571 nghttp2_session_client_new(&session, &callbacks, NULL);
3573 session->remote_settings.enable_connect_protocol = 1;
3575 iv[0].settings_id = NGHTTP2_SETTINGS_ENABLE_CONNECT_PROTOCOL;
3578 nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE, dup_iv(iv, 1),
3581 CU_ASSERT(0 == nghttp2_session_on_settings_received(session, &frame, 0));
3583 nghttp2_frame_settings_free(&frame.settings, mem);
3585 item = nghttp2_session_get_next_ob_item(session);
3587 CU_ASSERT(NULL != item);
3588 CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
3590 nghttp2_session_del(session);
3593 void test_nghttp2_session_on_push_promise_received(void) {
3594 nghttp2_session *session;
3595 nghttp2_session_callbacks callbacks;
3596 my_user_data user_data;
3597 nghttp2_frame frame;
3598 nghttp2_stream *stream, *promised_stream;
3599 nghttp2_outbound_item *item;
3600 nghttp2_nv malformed_nva[] = {MAKE_NV(":path", "\x01")};
3604 nghttp2_settings_entry iv = {NGHTTP2_SETTINGS_ENABLE_PUSH, 0};
3606 mem = nghttp2_mem_default();
3607 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
3608 callbacks.send_callback = null_send_callback;
3609 callbacks.on_begin_headers_callback = on_begin_headers_callback;
3610 callbacks.on_invalid_frame_recv_callback = on_invalid_frame_recv_callback;
3612 nghttp2_session_client_new(&session, &callbacks, &user_data);
3614 stream = open_sent_stream(session, 1);
3616 nghttp2_frame_push_promise_init(&frame.push_promise, NGHTTP2_FLAG_END_HEADERS,
3619 user_data.begin_headers_cb_called = 0;
3620 user_data.invalid_frame_recv_cb_called = 0;
3622 CU_ASSERT(0 == nghttp2_session_on_push_promise_received(session, &frame));
3624 CU_ASSERT(1 == user_data.begin_headers_cb_called);
3625 CU_ASSERT(1 == session->num_incoming_reserved_streams);
3626 promised_stream = nghttp2_session_get_stream(session, 2);
3627 CU_ASSERT(NGHTTP2_STREAM_RESERVED == promised_stream->state);
3628 CU_ASSERT(2 == session->last_recv_stream_id);
3630 /* Attempt to PUSH_PROMISE against half close (remote) */
3631 nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_RD);
3632 frame.push_promise.promised_stream_id = 4;
3634 user_data.begin_headers_cb_called = 0;
3635 user_data.invalid_frame_recv_cb_called = 0;
3636 CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
3637 nghttp2_session_on_push_promise_received(session, &frame));
3639 CU_ASSERT(0 == user_data.begin_headers_cb_called);
3640 CU_ASSERT(1 == user_data.invalid_frame_recv_cb_called);
3641 CU_ASSERT(1 == session->num_incoming_reserved_streams);
3642 CU_ASSERT(NULL == nghttp2_session_get_stream(session, 4));
3643 item = nghttp2_session_get_next_ob_item(session);
3644 CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
3645 CU_ASSERT(NGHTTP2_STREAM_CLOSED == item->frame.goaway.error_code);
3646 CU_ASSERT(0 == nghttp2_session_send(session));
3647 CU_ASSERT(4 == session->last_recv_stream_id);
3649 nghttp2_session_del(session);
3651 nghttp2_session_client_new(&session, &callbacks, &user_data);
3653 stream = open_sent_stream(session, 1);
3655 /* Attempt to PUSH_PROMISE against stream in closing state */
3656 stream->state = NGHTTP2_STREAM_CLOSING;
3657 frame.push_promise.promised_stream_id = 6;
3659 user_data.begin_headers_cb_called = 0;
3660 user_data.invalid_frame_recv_cb_called = 0;
3661 CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
3662 nghttp2_session_on_push_promise_received(session, &frame));
3664 CU_ASSERT(0 == user_data.begin_headers_cb_called);
3665 CU_ASSERT(0 == session->num_incoming_reserved_streams);
3666 CU_ASSERT(NULL == nghttp2_session_get_stream(session, 6));
3667 item = nghttp2_session_get_next_ob_item(session);
3668 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
3669 CU_ASSERT(6 == item->frame.hd.stream_id);
3670 CU_ASSERT(NGHTTP2_CANCEL == item->frame.rst_stream.error_code);
3671 CU_ASSERT(0 == nghttp2_session_send(session));
3673 /* Attempt to PUSH_PROMISE against idle stream */
3674 frame.hd.stream_id = 3;
3675 frame.push_promise.promised_stream_id = 8;
3677 user_data.begin_headers_cb_called = 0;
3678 user_data.invalid_frame_recv_cb_called = 0;
3679 CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
3680 nghttp2_session_on_push_promise_received(session, &frame));
3682 CU_ASSERT(0 == user_data.begin_headers_cb_called);
3683 CU_ASSERT(0 == session->num_incoming_reserved_streams);
3684 CU_ASSERT(NULL == nghttp2_session_get_stream(session, 8));
3685 item = nghttp2_session_get_next_ob_item(session);
3686 CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
3687 CU_ASSERT(0 == item->frame.hd.stream_id);
3688 CU_ASSERT(NGHTTP2_PROTOCOL_ERROR == item->frame.goaway.error_code);
3689 CU_ASSERT(0 == nghttp2_session_send(session));
3691 nghttp2_session_del(session);
3693 nghttp2_session_client_new(&session, &callbacks, &user_data);
3695 stream = open_sent_stream(session, 1);
3698 frame.hd.stream_id = 1;
3699 frame.push_promise.promised_stream_id = 2;
3701 user_data.begin_headers_cb_called = 0;
3702 user_data.invalid_frame_recv_cb_called = 0;
3703 CU_ASSERT(0 == nghttp2_session_on_push_promise_received(session, &frame));
3705 CU_ASSERT(1 == user_data.begin_headers_cb_called);
3706 CU_ASSERT(1 == session->num_incoming_reserved_streams);
3707 CU_ASSERT(NULL != nghttp2_session_get_stream(session, 2));
3709 user_data.begin_headers_cb_called = 0;
3710 user_data.invalid_frame_recv_cb_called = 0;
3711 CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
3712 nghttp2_session_on_push_promise_received(session, &frame));
3714 CU_ASSERT(0 == user_data.begin_headers_cb_called);
3715 CU_ASSERT(1 == session->num_incoming_reserved_streams);
3716 CU_ASSERT(NULL == nghttp2_session_get_stream(session, 8));
3717 item = nghttp2_session_get_next_ob_item(session);
3718 CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
3719 CU_ASSERT(NGHTTP2_PROTOCOL_ERROR == item->frame.goaway.error_code);
3720 CU_ASSERT(0 == nghttp2_session_send(session));
3722 /* After GOAWAY, PUSH_PROMISE will be discarded */
3723 frame.push_promise.promised_stream_id = 10;
3725 user_data.begin_headers_cb_called = 0;
3726 user_data.invalid_frame_recv_cb_called = 0;
3727 CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
3728 nghttp2_session_on_push_promise_received(session, &frame));
3730 CU_ASSERT(0 == user_data.begin_headers_cb_called);
3731 CU_ASSERT(1 == session->num_incoming_reserved_streams);
3732 CU_ASSERT(NULL == nghttp2_session_get_stream(session, 10));
3733 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
3735 nghttp2_frame_push_promise_free(&frame.push_promise, mem);
3736 nghttp2_session_del(session);
3738 nghttp2_session_client_new(&session, &callbacks, &user_data);
3740 open_recv_stream2(session, 2, NGHTTP2_STREAM_RESERVED);
3742 /* Attempt to PUSH_PROMISE against reserved (remote) stream */
3743 nghttp2_frame_push_promise_init(&frame.push_promise, NGHTTP2_FLAG_END_HEADERS,
3746 user_data.begin_headers_cb_called = 0;
3747 user_data.invalid_frame_recv_cb_called = 0;
3748 CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
3749 nghttp2_session_on_push_promise_received(session, &frame));
3751 CU_ASSERT(0 == user_data.begin_headers_cb_called);
3752 CU_ASSERT(1 == user_data.invalid_frame_recv_cb_called);
3753 CU_ASSERT(1 == session->num_incoming_reserved_streams);
3755 nghttp2_frame_push_promise_free(&frame.push_promise, mem);
3756 nghttp2_session_del(session);
3759 nghttp2_session_client_new(&session, &callbacks, &user_data);
3761 open_sent_stream(session, 1);
3763 session->local_settings.enable_push = 0;
3765 nghttp2_frame_push_promise_init(&frame.push_promise, NGHTTP2_FLAG_END_HEADERS,
3768 user_data.begin_headers_cb_called = 0;
3769 user_data.invalid_frame_recv_cb_called = 0;
3770 CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
3771 nghttp2_session_on_push_promise_received(session, &frame));
3773 CU_ASSERT(0 == user_data.begin_headers_cb_called);
3774 CU_ASSERT(1 == user_data.invalid_frame_recv_cb_called);
3775 CU_ASSERT(0 == session->num_incoming_reserved_streams);
3777 nghttp2_frame_push_promise_free(&frame.push_promise, mem);
3778 nghttp2_session_del(session);
3780 /* Check malformed headers. We accept malformed headers */
3781 nghttp2_session_client_new(&session, &callbacks, &user_data);
3783 open_sent_stream(session, 1);
3785 nvlen = ARRLEN(malformed_nva);
3786 nghttp2_nv_array_copy(&nva, malformed_nva, nvlen, mem);
3787 nghttp2_frame_push_promise_init(&frame.push_promise, NGHTTP2_FLAG_END_HEADERS,
3789 user_data.begin_headers_cb_called = 0;
3790 user_data.invalid_frame_recv_cb_called = 0;
3791 CU_ASSERT(0 == nghttp2_session_on_push_promise_received(session, &frame));
3793 CU_ASSERT(1 == user_data.begin_headers_cb_called);
3794 CU_ASSERT(0 == user_data.invalid_frame_recv_cb_called);
3796 nghttp2_frame_push_promise_free(&frame.push_promise, mem);
3797 nghttp2_session_del(session);
3799 /* If local_settings.enable_push = 0 is pending, but not acked from
3800 peer, incoming PUSH_PROMISE is rejected */
3801 nghttp2_session_client_new(&session, &callbacks, &user_data);
3803 open_sent_stream(session, 1);
3805 /* Submit settings with ENABLE_PUSH = 0 (thus disabling push) */
3806 nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, &iv, 1);
3808 nghttp2_frame_push_promise_init(&frame.push_promise, NGHTTP2_FLAG_END_HEADERS,
3811 CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
3812 nghttp2_session_on_push_promise_received(session, &frame));
3814 CU_ASSERT(0 == session->num_incoming_reserved_streams);
3816 nghttp2_frame_push_promise_free(&frame.push_promise, mem);
3817 nghttp2_session_del(session);
3819 /* Check max_incoming_reserved_streams */
3820 nghttp2_session_client_new(&session, &callbacks, &user_data);
3821 session->max_incoming_reserved_streams = 1;
3823 open_sent_stream(session, 1);
3824 open_recv_stream2(session, 2, NGHTTP2_STREAM_RESERVED);
3826 CU_ASSERT(1 == session->num_incoming_reserved_streams);
3828 nghttp2_frame_push_promise_init(&frame.push_promise, NGHTTP2_FLAG_END_HEADERS,
3831 CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
3832 nghttp2_session_on_push_promise_received(session, &frame));
3834 CU_ASSERT(1 == session->num_incoming_reserved_streams);
3836 item = nghttp2_session_get_next_ob_item(session);
3838 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
3839 CU_ASSERT(NGHTTP2_CANCEL == item->frame.rst_stream.error_code);
3841 nghttp2_frame_push_promise_free(&frame.push_promise, mem);
3842 nghttp2_session_del(session);
3845 void test_nghttp2_session_on_ping_received(void) {
3846 nghttp2_session *session;
3847 nghttp2_session_callbacks callbacks;
3848 my_user_data user_data;
3849 nghttp2_frame frame;
3850 nghttp2_outbound_item *top;
3851 const uint8_t opaque_data[] = "01234567";
3852 nghttp2_option *option;
3854 user_data.frame_recv_cb_called = 0;
3855 user_data.invalid_frame_recv_cb_called = 0;
3857 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
3858 callbacks.on_frame_recv_callback = on_frame_recv_callback;
3859 callbacks.on_invalid_frame_recv_callback = on_invalid_frame_recv_callback;
3861 nghttp2_session_client_new(&session, &callbacks, &user_data);
3862 nghttp2_frame_ping_init(&frame.ping, NGHTTP2_FLAG_ACK, opaque_data);
3864 CU_ASSERT(0 == nghttp2_session_on_ping_received(session, &frame));
3865 CU_ASSERT(1 == user_data.frame_recv_cb_called);
3867 /* Since this ping frame has ACK flag set, no further action is
3869 CU_ASSERT(NULL == nghttp2_outbound_queue_top(&session->ob_urgent));
3871 /* Clear the flag, and receive it again */
3872 frame.hd.flags = NGHTTP2_FLAG_NONE;
3874 CU_ASSERT(0 == nghttp2_session_on_ping_received(session, &frame));
3875 CU_ASSERT(2 == user_data.frame_recv_cb_called);
3876 top = nghttp2_outbound_queue_top(&session->ob_urgent);
3877 CU_ASSERT(NGHTTP2_PING == top->frame.hd.type);
3878 CU_ASSERT(NGHTTP2_FLAG_ACK == top->frame.hd.flags);
3879 CU_ASSERT(memcmp(opaque_data, top->frame.ping.opaque_data, 8) == 0);
3881 nghttp2_frame_ping_free(&frame.ping);
3882 nghttp2_session_del(session);
3884 /* Use nghttp2_option_set_no_auto_ping_ack() */
3885 nghttp2_option_new(&option);
3886 nghttp2_option_set_no_auto_ping_ack(option, 1);
3888 nghttp2_session_server_new2(&session, &callbacks, &user_data, option);
3889 nghttp2_frame_ping_init(&frame.ping, NGHTTP2_FLAG_NONE, NULL);
3891 user_data.frame_recv_cb_called = 0;
3893 CU_ASSERT(0 == nghttp2_session_on_ping_received(session, &frame));
3894 CU_ASSERT(1 == user_data.frame_recv_cb_called);
3895 CU_ASSERT(NULL == nghttp2_outbound_queue_top(&session->ob_urgent));
3897 nghttp2_frame_ping_free(&frame.ping);
3898 nghttp2_session_del(session);
3899 nghttp2_option_del(option);
3902 void test_nghttp2_session_on_goaway_received(void) {
3903 nghttp2_session *session;
3904 nghttp2_session_callbacks callbacks;
3905 my_user_data user_data;
3906 nghttp2_frame frame;
3910 mem = nghttp2_mem_default();
3911 user_data.frame_recv_cb_called = 0;
3912 user_data.invalid_frame_recv_cb_called = 0;
3914 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
3915 callbacks.on_frame_recv_callback = on_frame_recv_callback;
3916 callbacks.on_invalid_frame_recv_callback = on_invalid_frame_recv_callback;
3917 callbacks.on_stream_close_callback = on_stream_close_callback;
3919 nghttp2_session_client_new(&session, &callbacks, &user_data);
3921 for (i = 1; i <= 7; ++i) {
3922 if (nghttp2_session_is_my_stream_id(session, i)) {
3923 open_sent_stream(session, i);
3925 open_recv_stream(session, i);
3929 nghttp2_frame_goaway_init(&frame.goaway, 3, NGHTTP2_PROTOCOL_ERROR, NULL, 0);
3931 user_data.stream_close_cb_called = 0;
3933 CU_ASSERT(0 == nghttp2_session_on_goaway_received(session, &frame));
3935 CU_ASSERT(1 == user_data.frame_recv_cb_called);
3936 CU_ASSERT(3 == session->remote_last_stream_id);
3937 /* on_stream_close should be callsed for 2 times (stream 5 and 7) */
3938 CU_ASSERT(2 == user_data.stream_close_cb_called);
3940 CU_ASSERT(NULL != nghttp2_session_get_stream(session, 1));
3941 CU_ASSERT(NULL != nghttp2_session_get_stream(session, 2));
3942 CU_ASSERT(NULL != nghttp2_session_get_stream(session, 3));
3943 CU_ASSERT(NULL != nghttp2_session_get_stream(session, 4));
3944 CU_ASSERT(NULL == nghttp2_session_get_stream(session, 5));
3945 CU_ASSERT(NULL != nghttp2_session_get_stream(session, 6));
3946 CU_ASSERT(NULL == nghttp2_session_get_stream(session, 7));
3948 nghttp2_frame_goaway_free(&frame.goaway, mem);
3949 nghttp2_session_del(session);
3952 void test_nghttp2_session_on_window_update_received(void) {
3953 nghttp2_session *session;
3954 nghttp2_session_callbacks callbacks;
3955 my_user_data user_data;
3956 nghttp2_frame frame;
3957 nghttp2_stream *stream;
3958 nghttp2_outbound_item *data_item;
3961 mem = nghttp2_mem_default();
3963 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
3964 callbacks.on_frame_recv_callback = on_frame_recv_callback;
3965 callbacks.on_invalid_frame_recv_callback = on_invalid_frame_recv_callback;
3966 user_data.frame_recv_cb_called = 0;
3967 user_data.invalid_frame_recv_cb_called = 0;
3969 nghttp2_session_client_new(&session, &callbacks, &user_data);
3971 stream = open_sent_stream(session, 1);
3973 data_item = create_data_ob_item(mem);
3975 CU_ASSERT(0 == nghttp2_stream_attach_item(stream, data_item));
3977 nghttp2_frame_window_update_init(&frame.window_update, NGHTTP2_FLAG_NONE, 1,
3980 CU_ASSERT(0 == nghttp2_session_on_window_update_received(session, &frame));
3981 CU_ASSERT(1 == user_data.frame_recv_cb_called);
3982 CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE + 16 * 1024 ==
3983 stream->remote_window_size);
3985 CU_ASSERT(0 == nghttp2_stream_defer_item(
3986 stream, NGHTTP2_STREAM_FLAG_DEFERRED_FLOW_CONTROL));
3988 CU_ASSERT(0 == nghttp2_session_on_window_update_received(session, &frame));
3989 CU_ASSERT(2 == user_data.frame_recv_cb_called);
3990 CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE + 16 * 1024 * 2 ==
3991 stream->remote_window_size);
3992 CU_ASSERT(0 == (stream->flags & NGHTTP2_STREAM_FLAG_DEFERRED_ALL));
3994 nghttp2_frame_window_update_free(&frame.window_update);
3996 /* Receiving WINDOW_UPDATE on reserved (remote) stream is a
3998 open_recv_stream2(session, 2, NGHTTP2_STREAM_RESERVED);
4000 nghttp2_frame_window_update_init(&frame.window_update, NGHTTP2_FLAG_NONE, 2,
4003 CU_ASSERT(!(session->goaway_flags & NGHTTP2_GOAWAY_TERM_ON_SEND));
4004 CU_ASSERT(0 == nghttp2_session_on_window_update_received(session, &frame));
4005 CU_ASSERT(session->goaway_flags & NGHTTP2_GOAWAY_TERM_ON_SEND);
4007 nghttp2_frame_window_update_free(&frame.window_update);
4009 nghttp2_session_del(session);
4011 /* Receiving WINDOW_UPDATE on reserved (local) stream is allowed */
4012 nghttp2_session_server_new(&session, &callbacks, &user_data);
4014 stream = open_sent_stream2(session, 2, NGHTTP2_STREAM_RESERVED);
4016 nghttp2_frame_window_update_init(&frame.window_update, NGHTTP2_FLAG_NONE, 2,
4019 CU_ASSERT(0 == nghttp2_session_on_window_update_received(session, &frame));
4020 CU_ASSERT(!(session->goaway_flags & NGHTTP2_GOAWAY_TERM_ON_SEND));
4022 CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE + 4096 == stream->remote_window_size);
4024 nghttp2_frame_window_update_free(&frame.window_update);
4026 nghttp2_session_del(session);
4029 void test_nghttp2_session_on_data_received(void) {
4030 nghttp2_session *session;
4031 nghttp2_session_callbacks callbacks;
4032 my_user_data user_data;
4033 nghttp2_outbound_item *top;
4034 nghttp2_stream *stream;
4035 nghttp2_frame frame;
4037 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4039 nghttp2_session_client_new(&session, &callbacks, &user_data);
4040 stream = open_recv_stream(session, 2);
4042 nghttp2_frame_hd_init(&frame.hd, 4096, NGHTTP2_DATA, NGHTTP2_FLAG_NONE, 2);
4044 CU_ASSERT(0 == nghttp2_session_on_data_received(session, &frame));
4045 CU_ASSERT(0 == stream->shut_flags);
4047 frame.hd.flags = NGHTTP2_FLAG_END_STREAM;
4049 CU_ASSERT(0 == nghttp2_session_on_data_received(session, &frame));
4050 CU_ASSERT(NGHTTP2_SHUT_RD == stream->shut_flags);
4052 /* If NGHTTP2_STREAM_CLOSING state, DATA frame is discarded. */
4053 open_sent_stream2(session, 1, NGHTTP2_STREAM_CLOSING);
4055 frame.hd.flags = NGHTTP2_FLAG_NONE;
4056 frame.hd.stream_id = 1;
4058 CU_ASSERT(0 == nghttp2_session_on_data_received(session, &frame));
4059 CU_ASSERT(NULL == nghttp2_outbound_queue_top(&session->ob_reg));
4061 /* Check INVALID_STREAM case: DATA frame with stream ID which does
4064 frame.hd.stream_id = 3;
4066 CU_ASSERT(0 == nghttp2_session_on_data_received(session, &frame));
4067 top = nghttp2_outbound_queue_top(&session->ob_reg);
4068 /* DATA against nonexistent stream is just ignored for now. */
4069 CU_ASSERT(top == NULL);
4071 nghttp2_session_del(session);
4074 void test_nghttp2_session_on_data_received_fail_fast(void) {
4075 nghttp2_session *session;
4076 nghttp2_session_callbacks callbacks;
4078 nghttp2_stream *stream;
4079 nghttp2_frame_hd hd;
4080 nghttp2_outbound_item *item;
4082 memset(&callbacks, 0, sizeof(callbacks));
4084 nghttp2_frame_hd_init(&hd, 0, NGHTTP2_DATA, NGHTTP2_FLAG_NONE, 1);
4085 nghttp2_frame_pack_frame_hd(buf, &hd);
4087 nghttp2_session_server_new(&session, &callbacks, NULL);
4089 /* DATA to closed (remote) */
4090 stream = open_recv_stream(session, 1);
4091 nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_RD);
4093 CU_ASSERT((ssize_t)sizeof(buf) ==
4094 nghttp2_session_mem_recv(session, buf, sizeof(buf)));
4096 item = nghttp2_session_get_next_ob_item(session);
4098 CU_ASSERT(NULL != item);
4099 CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
4101 nghttp2_session_del(session);
4103 nghttp2_session_server_new(&session, &callbacks, NULL);
4105 /* DATA to closed stream with explicit closed (remote) */
4106 stream = open_recv_stream(session, 1);
4107 nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_RD);
4108 nghttp2_session_close_stream(session, 1, NGHTTP2_NO_ERROR);
4110 CU_ASSERT((ssize_t)sizeof(buf) ==
4111 nghttp2_session_mem_recv(session, buf, sizeof(buf)));
4113 item = nghttp2_session_get_next_ob_item(session);
4115 CU_ASSERT(NULL != item);
4116 CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
4118 nghttp2_session_del(session);
4121 void test_nghttp2_session_on_altsvc_received(void) {
4122 nghttp2_session *session;
4123 nghttp2_session_callbacks callbacks;
4125 nghttp2_frame frame;
4126 nghttp2_option *option;
4127 uint8_t origin[] = "nghttp2.org";
4128 uint8_t field_value[] = "h2=\":443\"";
4131 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4132 callbacks.on_frame_recv_callback = on_frame_recv_callback;
4134 nghttp2_option_new(&option);
4135 nghttp2_option_set_builtin_recv_extension_type(option, NGHTTP2_ALTSVC);
4137 nghttp2_session_client_new2(&session, &callbacks, &ud, option);
4139 frame.ext.payload = &session->iframe.ext_frame_payload;
4141 /* We just pass the strings without making a copy. This is OK,
4142 since we never call nghttp2_frame_altsvc_free(). */
4143 nghttp2_frame_altsvc_init(&frame.ext, 0, origin, sizeof(origin) - 1,
4144 field_value, sizeof(field_value) - 1);
4146 ud.frame_recv_cb_called = 0;
4147 rv = nghttp2_session_on_altsvc_received(session, &frame);
4150 CU_ASSERT(1 == ud.frame_recv_cb_called);
4152 nghttp2_session_del(session);
4154 /* Receiving empty origin with stream ID == 0 */
4155 nghttp2_session_client_new2(&session, &callbacks, &ud, option);
4157 frame.ext.payload = &session->iframe.ext_frame_payload;
4159 nghttp2_frame_altsvc_init(&frame.ext, 0, origin, 0, field_value,
4160 sizeof(field_value) - 1);
4162 ud.frame_recv_cb_called = 0;
4163 rv = nghttp2_session_on_altsvc_received(session, &frame);
4166 CU_ASSERT(0 == ud.frame_recv_cb_called);
4168 nghttp2_session_del(session);
4170 /* Receiving non-empty origin with stream ID != 0 */
4171 nghttp2_session_client_new2(&session, &callbacks, &ud, option);
4173 frame.ext.payload = &session->iframe.ext_frame_payload;
4175 open_sent_stream(session, 1);
4177 nghttp2_frame_altsvc_init(&frame.ext, 1, origin, sizeof(origin) - 1,
4178 field_value, sizeof(field_value) - 1);
4180 ud.frame_recv_cb_called = 0;
4181 rv = nghttp2_session_on_altsvc_received(session, &frame);
4184 CU_ASSERT(0 == ud.frame_recv_cb_called);
4186 nghttp2_session_del(session);
4188 /* Receiving empty origin with stream ID != 0; this is OK */
4189 nghttp2_session_client_new2(&session, &callbacks, &ud, option);
4191 frame.ext.payload = &session->iframe.ext_frame_payload;
4193 open_sent_stream(session, 1);
4195 nghttp2_frame_altsvc_init(&frame.ext, 1, origin, 0, field_value,
4196 sizeof(field_value) - 1);
4198 ud.frame_recv_cb_called = 0;
4199 rv = nghttp2_session_on_altsvc_received(session, &frame);
4202 CU_ASSERT(1 == ud.frame_recv_cb_called);
4204 nghttp2_session_del(session);
4206 /* Stream does not exist; ALTSVC will be ignored. */
4207 nghttp2_session_client_new2(&session, &callbacks, &ud, option);
4209 frame.ext.payload = &session->iframe.ext_frame_payload;
4211 nghttp2_frame_altsvc_init(&frame.ext, 1, origin, 0, field_value,
4212 sizeof(field_value) - 1);
4214 ud.frame_recv_cb_called = 0;
4215 rv = nghttp2_session_on_altsvc_received(session, &frame);
4218 CU_ASSERT(0 == ud.frame_recv_cb_called);
4220 nghttp2_session_del(session);
4222 nghttp2_option_del(option);
4225 void test_nghttp2_session_send_headers_start_stream(void) {
4226 nghttp2_session *session;
4227 nghttp2_session_callbacks callbacks;
4228 nghttp2_outbound_item *item;
4229 nghttp2_frame *frame;
4230 nghttp2_stream *stream;
4233 mem = nghttp2_mem_default();
4235 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4236 callbacks.send_callback = null_send_callback;
4238 nghttp2_session_client_new(&session, &callbacks, NULL);
4240 item = mem->malloc(sizeof(nghttp2_outbound_item), NULL);
4242 nghttp2_outbound_item_init(item);
4244 frame = &item->frame;
4246 nghttp2_frame_headers_init(&frame->headers, NGHTTP2_FLAG_END_HEADERS,
4247 (int32_t)session->next_stream_id,
4248 NGHTTP2_HCAT_REQUEST, NULL, NULL, 0);
4249 session->next_stream_id += 2;
4251 nghttp2_session_add_item(session, item);
4252 CU_ASSERT(0 == nghttp2_session_send(session));
4253 stream = nghttp2_session_get_stream(session, 1);
4254 CU_ASSERT(NGHTTP2_STREAM_OPENING == stream->state);
4256 nghttp2_session_del(session);
4259 void test_nghttp2_session_send_headers_reply(void) {
4260 nghttp2_session *session;
4261 nghttp2_session_callbacks callbacks;
4262 nghttp2_outbound_item *item;
4263 nghttp2_frame *frame;
4264 nghttp2_stream *stream;
4267 mem = nghttp2_mem_default();
4269 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4270 callbacks.send_callback = null_send_callback;
4272 CU_ASSERT(0 == nghttp2_session_server_new(&session, &callbacks, NULL));
4273 open_recv_stream2(session, 1, NGHTTP2_STREAM_OPENING);
4275 item = mem->malloc(sizeof(nghttp2_outbound_item), NULL);
4277 nghttp2_outbound_item_init(item);
4279 frame = &item->frame;
4281 nghttp2_frame_headers_init(&frame->headers, NGHTTP2_FLAG_END_HEADERS, 1,
4282 NGHTTP2_HCAT_HEADERS, NULL, NULL, 0);
4283 nghttp2_session_add_item(session, item);
4284 CU_ASSERT(0 == nghttp2_session_send(session));
4285 stream = nghttp2_session_get_stream(session, 1);
4286 CU_ASSERT(NGHTTP2_STREAM_OPENED == stream->state);
4288 nghttp2_session_del(session);
4291 void test_nghttp2_session_send_headers_frame_size_error(void) {
4292 nghttp2_session *session;
4293 nghttp2_session_callbacks callbacks;
4294 nghttp2_outbound_item *item;
4295 nghttp2_frame *frame;
4298 size_t vallen = NGHTTP2_HD_MAX_NV;
4300 size_t nnv = ARRLEN(nv);
4305 mem = nghttp2_mem_default();
4307 for (i = 0; i < nnv; ++i) {
4308 nv[i].name = (uint8_t *)"header";
4309 nv[i].namelen = strlen((const char *)nv[i].name);
4310 nv[i].value = mem->malloc(vallen + 1, NULL);
4311 memset(nv[i].value, '0' + (int)i, vallen);
4312 nv[i].value[vallen] = '\0';
4313 nv[i].valuelen = vallen;
4314 nv[i].flags = NGHTTP2_NV_FLAG_NONE;
4317 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4318 callbacks.send_callback = null_send_callback;
4319 callbacks.on_frame_not_send_callback = on_frame_not_send_callback;
4321 nghttp2_session_client_new(&session, &callbacks, &ud);
4323 nghttp2_nv_array_copy(&nva, nv, nvlen, mem);
4325 item = mem->malloc(sizeof(nghttp2_outbound_item), NULL);
4327 nghttp2_outbound_item_init(item);
4329 frame = &item->frame;
4331 nghttp2_frame_headers_init(&frame->headers, NGHTTP2_FLAG_END_HEADERS,
4332 (int32_t)session->next_stream_id,
4333 NGHTTP2_HCAT_REQUEST, NULL, nva, nvlen);
4335 session->next_stream_id += 2;
4337 nghttp2_session_add_item(session, item);
4339 ud.frame_not_send_cb_called = 0;
4341 CU_ASSERT(0 == nghttp2_session_send(session));
4343 CU_ASSERT(1 == ud.frame_not_send_cb_called);
4344 CU_ASSERT(NGHTTP2_HEADERS == ud.not_sent_frame_type);
4345 CU_ASSERT(NGHTTP2_ERR_FRAME_SIZE_ERROR == ud.not_sent_error);
4347 for (i = 0; i < nnv; ++i) {
4348 mem->free(nv[i].value, NULL);
4350 nghttp2_session_del(session);
4353 void test_nghttp2_session_send_headers_push_reply(void) {
4354 nghttp2_session *session;
4355 nghttp2_session_callbacks callbacks;
4356 nghttp2_outbound_item *item;
4357 nghttp2_frame *frame;
4358 nghttp2_stream *stream;
4361 mem = nghttp2_mem_default();
4363 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4364 callbacks.send_callback = null_send_callback;
4366 CU_ASSERT(0 == nghttp2_session_server_new(&session, &callbacks, NULL));
4367 open_sent_stream2(session, 2, NGHTTP2_STREAM_RESERVED);
4369 item = mem->malloc(sizeof(nghttp2_outbound_item), NULL);
4371 nghttp2_outbound_item_init(item);
4373 frame = &item->frame;
4375 nghttp2_frame_headers_init(&frame->headers, NGHTTP2_FLAG_END_HEADERS, 2,
4376 NGHTTP2_HCAT_HEADERS, NULL, NULL, 0);
4377 nghttp2_session_add_item(session, item);
4378 CU_ASSERT(0 == session->num_outgoing_streams);
4379 CU_ASSERT(0 == nghttp2_session_send(session));
4380 CU_ASSERT(1 == session->num_outgoing_streams);
4381 stream = nghttp2_session_get_stream(session, 2);
4382 CU_ASSERT(NGHTTP2_STREAM_OPENED == stream->state);
4383 CU_ASSERT(0 == (stream->flags & NGHTTP2_STREAM_FLAG_PUSH));
4384 nghttp2_session_del(session);
4387 void test_nghttp2_session_send_rst_stream(void) {
4388 nghttp2_session *session;
4389 nghttp2_session_callbacks callbacks;
4390 my_user_data user_data;
4391 nghttp2_outbound_item *item;
4392 nghttp2_frame *frame;
4395 mem = nghttp2_mem_default();
4397 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4398 callbacks.send_callback = null_send_callback;
4399 nghttp2_session_client_new(&session, &callbacks, &user_data);
4400 open_sent_stream(session, 1);
4402 item = mem->malloc(sizeof(nghttp2_outbound_item), NULL);
4404 nghttp2_outbound_item_init(item);
4406 frame = &item->frame;
4408 nghttp2_frame_rst_stream_init(&frame->rst_stream, 1, NGHTTP2_PROTOCOL_ERROR);
4409 nghttp2_session_add_item(session, item);
4410 CU_ASSERT(0 == nghttp2_session_send(session));
4412 CU_ASSERT(NULL == nghttp2_session_get_stream(session, 1));
4414 nghttp2_session_del(session);
4417 void test_nghttp2_session_send_push_promise(void) {
4418 nghttp2_session *session;
4419 nghttp2_session_callbacks callbacks;
4420 nghttp2_outbound_item *item;
4421 nghttp2_frame *frame;
4422 nghttp2_stream *stream;
4423 nghttp2_settings_entry iv;
4427 mem = nghttp2_mem_default();
4428 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4429 callbacks.send_callback = null_send_callback;
4430 callbacks.on_frame_not_send_callback = on_frame_not_send_callback;
4432 nghttp2_session_server_new(&session, &callbacks, &ud);
4433 open_recv_stream(session, 1);
4435 item = mem->malloc(sizeof(nghttp2_outbound_item), NULL);
4437 nghttp2_outbound_item_init(item);
4439 frame = &item->frame;
4441 nghttp2_frame_push_promise_init(&frame->push_promise,
4442 NGHTTP2_FLAG_END_HEADERS, 1,
4443 (int32_t)session->next_stream_id, NULL, 0);
4445 session->next_stream_id += 2;
4447 nghttp2_session_add_item(session, item);
4449 CU_ASSERT(0 == nghttp2_session_send(session));
4450 stream = nghttp2_session_get_stream(session, 2);
4451 CU_ASSERT(NGHTTP2_STREAM_RESERVED == stream->state);
4453 /* Received ENABLE_PUSH = 0 */
4454 iv.settings_id = NGHTTP2_SETTINGS_ENABLE_PUSH;
4456 frame = mem->malloc(sizeof(nghttp2_frame), NULL);
4457 nghttp2_frame_settings_init(&frame->settings, NGHTTP2_FLAG_NONE,
4459 nghttp2_session_on_settings_received(session, frame, 1);
4460 nghttp2_frame_settings_free(&frame->settings, mem);
4461 mem->free(frame, NULL);
4463 item = mem->malloc(sizeof(nghttp2_outbound_item), NULL);
4465 nghttp2_outbound_item_init(item);
4467 frame = &item->frame;
4469 nghttp2_frame_push_promise_init(&frame->push_promise,
4470 NGHTTP2_FLAG_END_HEADERS, 1, -1, NULL, 0);
4471 nghttp2_session_add_item(session, item);
4473 ud.frame_not_send_cb_called = 0;
4474 CU_ASSERT(0 == nghttp2_session_send(session));
4476 CU_ASSERT(1 == ud.frame_not_send_cb_called);
4477 CU_ASSERT(NGHTTP2_PUSH_PROMISE == ud.not_sent_frame_type);
4478 CU_ASSERT(NGHTTP2_ERR_PUSH_DISABLED == ud.not_sent_error);
4480 nghttp2_session_del(session);
4482 /* PUSH_PROMISE from client is error */
4483 nghttp2_session_client_new(&session, &callbacks, &ud);
4484 open_sent_stream(session, 1);
4485 item = mem->malloc(sizeof(nghttp2_outbound_item), NULL);
4487 nghttp2_outbound_item_init(item);
4489 frame = &item->frame;
4491 nghttp2_frame_push_promise_init(&frame->push_promise,
4492 NGHTTP2_FLAG_END_HEADERS, 1, -1, NULL, 0);
4493 nghttp2_session_add_item(session, item);
4495 CU_ASSERT(0 == nghttp2_session_send(session));
4496 CU_ASSERT(NULL == nghttp2_session_get_stream(session, 3));
4498 nghttp2_session_del(session);
4501 void test_nghttp2_session_is_my_stream_id(void) {
4502 nghttp2_session *session;
4503 nghttp2_session_callbacks callbacks;
4504 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4505 nghttp2_session_server_new(&session, &callbacks, NULL);
4507 CU_ASSERT(0 == nghttp2_session_is_my_stream_id(session, 0));
4508 CU_ASSERT(0 == nghttp2_session_is_my_stream_id(session, 1));
4509 CU_ASSERT(1 == nghttp2_session_is_my_stream_id(session, 2));
4511 nghttp2_session_del(session);
4513 nghttp2_session_client_new(&session, &callbacks, NULL);
4515 CU_ASSERT(0 == nghttp2_session_is_my_stream_id(session, 0));
4516 CU_ASSERT(1 == nghttp2_session_is_my_stream_id(session, 1));
4517 CU_ASSERT(0 == nghttp2_session_is_my_stream_id(session, 2));
4519 nghttp2_session_del(session);
4522 void test_nghttp2_session_upgrade2(void) {
4523 nghttp2_session *session;
4524 nghttp2_session_callbacks callbacks;
4525 uint8_t settings_payload[128];
4526 size_t settings_payloadlen;
4527 nghttp2_settings_entry iv[16];
4528 nghttp2_stream *stream;
4529 nghttp2_outbound_item *item;
4533 nghttp2_hd_deflater deflater;
4536 mem = nghttp2_mem_default();
4537 frame_pack_bufs_init(&bufs);
4539 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4540 callbacks.send_callback = null_send_callback;
4541 iv[0].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS;
4543 iv[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
4545 settings_payloadlen = (size_t)nghttp2_pack_settings_payload(
4546 settings_payload, sizeof(settings_payload), iv, 2);
4548 /* Check client side */
4549 nghttp2_session_client_new(&session, &callbacks, NULL);
4550 CU_ASSERT(0 == nghttp2_session_upgrade2(session, settings_payload,
4551 settings_payloadlen, 0, &callbacks));
4552 CU_ASSERT(1 == session->last_sent_stream_id);
4553 stream = nghttp2_session_get_stream(session, 1);
4554 CU_ASSERT(stream != NULL);
4555 CU_ASSERT(&callbacks == stream->stream_user_data);
4556 CU_ASSERT(NGHTTP2_SHUT_WR == stream->shut_flags);
4557 item = nghttp2_session_get_next_ob_item(session);
4558 CU_ASSERT(NGHTTP2_SETTINGS == item->frame.hd.type);
4559 CU_ASSERT(2 == item->frame.settings.niv);
4560 CU_ASSERT(NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS ==
4561 item->frame.settings.iv[0].settings_id);
4562 CU_ASSERT(1 == item->frame.settings.iv[0].value);
4563 CU_ASSERT(NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE ==
4564 item->frame.settings.iv[1].settings_id);
4565 CU_ASSERT(4095 == item->frame.settings.iv[1].value);
4567 /* Call nghttp2_session_upgrade2() again is error */
4568 CU_ASSERT(NGHTTP2_ERR_PROTO ==
4569 nghttp2_session_upgrade2(session, settings_payload,
4570 settings_payloadlen, 0, &callbacks));
4571 nghttp2_session_del(session);
4573 /* Make sure that response from server can be received */
4574 nghttp2_session_client_new(&session, &callbacks, NULL);
4576 CU_ASSERT(0 == nghttp2_session_upgrade2(session, settings_payload,
4577 settings_payloadlen, 0, &callbacks));
4579 stream = nghttp2_session_get_stream(session, 1);
4581 CU_ASSERT(NGHTTP2_STREAM_OPENING == stream->state);
4583 nghttp2_hd_deflate_init(&deflater, mem);
4584 rv = pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, resnv,
4585 ARRLEN(resnv), mem);
4589 buf = &bufs.head->buf;
4591 rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
4593 CU_ASSERT(rv == (ssize_t)nghttp2_buf_len(buf));
4594 CU_ASSERT(NGHTTP2_STREAM_OPENED == stream->state);
4596 nghttp2_hd_deflate_free(&deflater);
4597 nghttp2_session_del(session);
4599 nghttp2_bufs_reset(&bufs);
4601 /* Check server side */
4602 nghttp2_session_server_new(&session, &callbacks, NULL);
4603 CU_ASSERT(0 == nghttp2_session_upgrade2(session, settings_payload,
4604 settings_payloadlen, 0, &callbacks));
4605 CU_ASSERT(1 == session->last_recv_stream_id);
4606 stream = nghttp2_session_get_stream(session, 1);
4607 CU_ASSERT(stream != NULL);
4608 CU_ASSERT(NULL == stream->stream_user_data);
4609 CU_ASSERT(NGHTTP2_SHUT_RD == stream->shut_flags);
4610 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
4611 CU_ASSERT(1 == session->remote_settings.max_concurrent_streams);
4612 CU_ASSERT(4095 == session->remote_settings.initial_window_size);
4613 /* Call nghttp2_session_upgrade2() again is error */
4614 CU_ASSERT(NGHTTP2_ERR_PROTO ==
4615 nghttp2_session_upgrade2(session, settings_payload,
4616 settings_payloadlen, 0, &callbacks));
4617 nghttp2_session_del(session);
4619 /* Empty SETTINGS is OK */
4620 settings_payloadlen = (size_t)nghttp2_pack_settings_payload(
4621 settings_payload, sizeof(settings_payload), NULL, 0);
4623 nghttp2_session_client_new(&session, &callbacks, NULL);
4624 CU_ASSERT(0 == nghttp2_session_upgrade2(session, settings_payload,
4625 settings_payloadlen, 0, NULL));
4626 nghttp2_session_del(session);
4627 nghttp2_bufs_free(&bufs);
4630 void test_nghttp2_session_reprioritize_stream(void) {
4631 nghttp2_session *session;
4632 nghttp2_session_callbacks callbacks;
4633 nghttp2_stream *stream;
4634 nghttp2_stream *dep_stream;
4635 nghttp2_priority_spec pri_spec;
4638 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4639 callbacks.send_callback = block_count_send_callback;
4641 nghttp2_session_server_new(&session, &callbacks, NULL);
4643 stream = open_recv_stream(session, 1);
4645 nghttp2_priority_spec_init(&pri_spec, 0, 10, 0);
4647 rv = nghttp2_session_reprioritize_stream(session, stream, &pri_spec);
4650 CU_ASSERT(10 == stream->weight);
4651 CU_ASSERT(&session->root == stream->dep_prev);
4653 /* If depenency to idle stream which is not in depdenency tree yet */
4655 nghttp2_priority_spec_init(&pri_spec, 3, 99, 0);
4657 rv = nghttp2_session_reprioritize_stream(session, stream, &pri_spec);
4660 CU_ASSERT(99 == stream->weight);
4661 CU_ASSERT(3 == stream->dep_prev->stream_id);
4663 dep_stream = nghttp2_session_get_stream_raw(session, 3);
4665 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == dep_stream->weight);
4667 dep_stream = open_recv_stream(session, 3);
4670 pri_spec.weight = 128;
4672 rv = nghttp2_session_reprioritize_stream(session, stream, &pri_spec);
4675 CU_ASSERT(128 == stream->weight);
4676 CU_ASSERT(dep_stream == stream->dep_prev);
4678 /* Change weight again to test short-path case */
4679 pri_spec.weight = 100;
4681 rv = nghttp2_session_reprioritize_stream(session, stream, &pri_spec);
4684 CU_ASSERT(100 == stream->weight);
4685 CU_ASSERT(dep_stream == stream->dep_prev);
4686 CU_ASSERT(100 == dep_stream->sum_dep_weight);
4688 /* Test circular dependency; stream 1 is first removed and becomes
4689 root. Then stream 3 depends on it. */
4690 nghttp2_priority_spec_init(&pri_spec, 1, 1, 0);
4692 rv = nghttp2_session_reprioritize_stream(session, dep_stream, &pri_spec);
4695 CU_ASSERT(1 == dep_stream->weight);
4696 CU_ASSERT(stream == dep_stream->dep_prev);
4698 /* Making priority to closed stream will result in default
4700 session->last_recv_stream_id = 9;
4702 nghttp2_priority_spec_init(&pri_spec, 5, 5, 0);
4704 rv = nghttp2_session_reprioritize_stream(session, stream, &pri_spec);
4707 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == stream->weight);
4709 nghttp2_session_del(session);
4711 nghttp2_session_server_new(&session, &callbacks, NULL);
4713 /* circular dependency; in case of stream which is not a direct
4714 descendant of root. Use exclusive dependency. */
4715 stream = open_recv_stream(session, 1);
4716 stream = open_recv_stream_with_dep(session, 3, stream);
4717 stream = open_recv_stream_with_dep(session, 5, stream);
4718 stream = open_recv_stream_with_dep(session, 7, stream);
4719 open_recv_stream_with_dep(session, 9, stream);
4721 nghttp2_priority_spec_init(&pri_spec, 7, 1, 1);
4723 stream = nghttp2_session_get_stream(session, 3);
4724 rv = nghttp2_session_reprioritize_stream(session, stream, &pri_spec);
4727 CU_ASSERT(7 == stream->dep_prev->stream_id);
4729 stream = nghttp2_session_get_stream(session, 7);
4731 CU_ASSERT(1 == stream->dep_prev->stream_id);
4733 stream = nghttp2_session_get_stream(session, 9);
4735 CU_ASSERT(3 == stream->dep_prev->stream_id);
4737 stream = nghttp2_session_get_stream(session, 5);
4739 CU_ASSERT(3 == stream->dep_prev->stream_id);
4741 nghttp2_session_del(session);
4743 nghttp2_session_server_new(&session, &callbacks, NULL);
4745 /* circular dependency; in case of stream which is not a direct
4746 descendant of root. Without exclusive dependency. */
4747 stream = open_recv_stream(session, 1);
4748 stream = open_recv_stream_with_dep(session, 3, stream);
4749 stream = open_recv_stream_with_dep(session, 5, stream);
4750 stream = open_recv_stream_with_dep(session, 7, stream);
4751 open_recv_stream_with_dep(session, 9, stream);
4753 nghttp2_priority_spec_init(&pri_spec, 7, 1, 0);
4755 stream = nghttp2_session_get_stream(session, 3);
4756 rv = nghttp2_session_reprioritize_stream(session, stream, &pri_spec);
4759 CU_ASSERT(7 == stream->dep_prev->stream_id);
4761 stream = nghttp2_session_get_stream(session, 7);
4763 CU_ASSERT(1 == stream->dep_prev->stream_id);
4765 stream = nghttp2_session_get_stream(session, 9);
4767 CU_ASSERT(7 == stream->dep_prev->stream_id);
4769 stream = nghttp2_session_get_stream(session, 5);
4771 CU_ASSERT(3 == stream->dep_prev->stream_id);
4773 nghttp2_session_del(session);
4776 void test_nghttp2_session_reprioritize_stream_with_idle_stream_dep(void) {
4777 nghttp2_session *session;
4778 nghttp2_session_callbacks callbacks;
4779 nghttp2_stream *stream;
4780 nghttp2_priority_spec pri_spec;
4782 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4783 callbacks.send_callback = block_count_send_callback;
4785 nghttp2_session_server_new(&session, &callbacks, NULL);
4787 stream = open_recv_stream(session, 1);
4789 session->pending_local_max_concurrent_stream = 1;
4791 nghttp2_priority_spec_init(&pri_spec, 101, 10, 0);
4793 nghttp2_session_reprioritize_stream(session, stream, &pri_spec);
4795 /* idle stream is not counteed to max concurrent streams */
4797 CU_ASSERT(10 == stream->weight);
4798 CU_ASSERT(101 == stream->dep_prev->stream_id);
4800 stream = nghttp2_session_get_stream_raw(session, 101);
4802 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == stream->weight);
4804 nghttp2_session_del(session);
4807 void test_nghttp2_submit_data(void) {
4808 nghttp2_session *session;
4809 nghttp2_session_callbacks callbacks;
4810 nghttp2_data_provider data_prd;
4812 nghttp2_frame *frame;
4813 nghttp2_frame_hd hd;
4814 nghttp2_active_outbound_item *aob;
4815 nghttp2_bufs *framebufs;
4818 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4819 callbacks.send_callback = block_count_send_callback;
4821 data_prd.read_callback = fixed_length_data_source_read_callback;
4822 ud.data_source_length = NGHTTP2_DATA_PAYLOADLEN * 2;
4823 CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, &ud));
4824 aob = &session->aob;
4825 framebufs = &aob->framebufs;
4827 open_sent_stream(session, 1);
4830 0 == nghttp2_submit_data(session, NGHTTP2_FLAG_END_STREAM, 1, &data_prd));
4833 CU_ASSERT(0 == nghttp2_session_send(session));
4834 frame = &aob->item->frame;
4836 buf = &framebufs->head->buf;
4837 nghttp2_frame_unpack_frame_hd(&hd, buf->pos);
4839 CU_ASSERT(NGHTTP2_FLAG_NONE == hd.flags);
4840 CU_ASSERT(NGHTTP2_FLAG_NONE == frame->hd.flags);
4841 /* aux_data.data.flags has these flags */
4842 CU_ASSERT(NGHTTP2_FLAG_END_STREAM == aob->item->aux_data.data.flags);
4844 nghttp2_session_del(session);
4847 void test_nghttp2_submit_data_read_length_too_large(void) {
4848 nghttp2_session *session;
4849 nghttp2_session_callbacks callbacks;
4850 nghttp2_data_provider data_prd;
4852 nghttp2_frame *frame;
4853 nghttp2_frame_hd hd;
4854 nghttp2_active_outbound_item *aob;
4855 nghttp2_bufs *framebufs;
4859 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4860 callbacks.send_callback = block_count_send_callback;
4861 callbacks.read_length_callback = too_large_data_source_length_callback;
4863 data_prd.read_callback = fixed_length_data_source_read_callback;
4864 ud.data_source_length = NGHTTP2_DATA_PAYLOADLEN * 2;
4865 CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, &ud));
4866 aob = &session->aob;
4867 framebufs = &aob->framebufs;
4869 open_sent_stream(session, 1);
4872 0 == nghttp2_submit_data(session, NGHTTP2_FLAG_END_STREAM, 1, &data_prd));
4875 CU_ASSERT(0 == nghttp2_session_send(session));
4876 frame = &aob->item->frame;
4878 buf = &framebufs->head->buf;
4879 nghttp2_frame_unpack_frame_hd(&hd, buf->pos);
4881 CU_ASSERT(NGHTTP2_FLAG_NONE == hd.flags);
4882 CU_ASSERT(NGHTTP2_FLAG_NONE == frame->hd.flags);
4883 CU_ASSERT(16384 == hd.length)
4884 /* aux_data.data.flags has these flags */
4885 CU_ASSERT(NGHTTP2_FLAG_END_STREAM == aob->item->aux_data.data.flags);
4887 nghttp2_session_del(session);
4889 /* Check that buffers are expanded */
4890 CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, &ud));
4892 ud.data_source_length = NGHTTP2_MAX_FRAME_SIZE_MAX;
4894 session->remote_settings.max_frame_size = NGHTTP2_MAX_FRAME_SIZE_MAX;
4896 open_sent_stream(session, 1);
4899 0 == nghttp2_submit_data(session, NGHTTP2_FLAG_END_STREAM, 1, &data_prd));
4902 CU_ASSERT(0 == nghttp2_session_send(session));
4904 aob = &session->aob;
4906 frame = &aob->item->frame;
4908 framebufs = &aob->framebufs;
4910 buf = &framebufs->head->buf;
4911 nghttp2_frame_unpack_frame_hd(&hd, buf->pos);
4913 payloadlen = nghttp2_min(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE,
4914 NGHTTP2_INITIAL_WINDOW_SIZE);
4916 CU_ASSERT(NGHTTP2_FRAME_HDLEN + 1 + payloadlen ==
4917 (size_t)nghttp2_buf_cap(buf));
4918 CU_ASSERT(NGHTTP2_FLAG_NONE == hd.flags);
4919 CU_ASSERT(NGHTTP2_FLAG_NONE == frame->hd.flags);
4920 CU_ASSERT(payloadlen == hd.length);
4921 /* aux_data.data.flags has these flags */
4922 CU_ASSERT(NGHTTP2_FLAG_END_STREAM == aob->item->aux_data.data.flags);
4924 nghttp2_session_del(session);
4927 void test_nghttp2_submit_data_read_length_smallest(void) {
4928 nghttp2_session *session;
4929 nghttp2_session_callbacks callbacks;
4930 nghttp2_data_provider data_prd;
4932 nghttp2_frame *frame;
4933 nghttp2_frame_hd hd;
4934 nghttp2_active_outbound_item *aob;
4935 nghttp2_bufs *framebufs;
4938 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4939 callbacks.send_callback = block_count_send_callback;
4940 callbacks.read_length_callback = smallest_length_data_source_length_callback;
4942 data_prd.read_callback = fixed_length_data_source_read_callback;
4943 ud.data_source_length = NGHTTP2_DATA_PAYLOADLEN * 2;
4944 CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, &ud));
4945 aob = &session->aob;
4946 framebufs = &aob->framebufs;
4948 open_sent_stream(session, 1);
4951 0 == nghttp2_submit_data(session, NGHTTP2_FLAG_END_STREAM, 1, &data_prd));
4954 CU_ASSERT(0 == nghttp2_session_send(session));
4955 frame = &aob->item->frame;
4957 buf = &framebufs->head->buf;
4958 nghttp2_frame_unpack_frame_hd(&hd, buf->pos);
4960 CU_ASSERT(NGHTTP2_FLAG_NONE == hd.flags);
4961 CU_ASSERT(NGHTTP2_FLAG_NONE == frame->hd.flags);
4962 CU_ASSERT(1 == hd.length)
4963 /* aux_data.data.flags has these flags */
4964 CU_ASSERT(NGHTTP2_FLAG_END_STREAM == aob->item->aux_data.data.flags);
4966 nghttp2_session_del(session);
4969 static ssize_t submit_data_twice_data_source_read_callback(
4970 nghttp2_session *session, int32_t stream_id, uint8_t *buf, size_t len,
4971 uint32_t *data_flags, nghttp2_data_source *source, void *user_data) {
4978 *data_flags |= NGHTTP2_DATA_FLAG_EOF;
4979 return (ssize_t)nghttp2_min(len, 16);
4982 static int submit_data_twice_on_frame_send_callback(nghttp2_session *session,
4983 const nghttp2_frame *frame,
4985 static int called = 0;
4987 nghttp2_data_provider data_prd;
4993 data_prd.read_callback = submit_data_twice_data_source_read_callback;
4995 rv = nghttp2_submit_data(session, NGHTTP2_FLAG_END_STREAM,
4996 frame->hd.stream_id, &data_prd);
5003 void test_nghttp2_submit_data_twice(void) {
5004 nghttp2_session *session;
5005 nghttp2_session_callbacks callbacks;
5006 nghttp2_data_provider data_prd;
5010 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
5011 callbacks.send_callback = accumulator_send_callback;
5012 callbacks.on_frame_send_callback = submit_data_twice_on_frame_send_callback;
5014 data_prd.read_callback = submit_data_twice_data_source_read_callback;
5019 CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, &ud));
5021 open_sent_stream(session, 1);
5023 CU_ASSERT(0 == nghttp2_submit_data(session, NGHTTP2_FLAG_NONE, 1, &data_prd));
5024 CU_ASSERT(0 == nghttp2_session_send(session));
5026 /* We should have sent 2 DATA frame with 16 bytes payload each */
5027 CU_ASSERT(NGHTTP2_FRAME_HDLEN * 2 + 16 * 2 == acc.length);
5029 nghttp2_session_del(session);
5032 void test_nghttp2_submit_request_with_data(void) {
5033 nghttp2_session *session;
5034 nghttp2_session_callbacks callbacks;
5035 nghttp2_data_provider data_prd;
5037 nghttp2_outbound_item *item;
5040 mem = nghttp2_mem_default();
5042 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
5043 callbacks.send_callback = null_send_callback;
5045 data_prd.read_callback = fixed_length_data_source_read_callback;
5046 ud.data_source_length = 64 * 1024 - 1;
5047 CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, &ud));
5048 CU_ASSERT(1 == nghttp2_submit_request(session, NULL, reqnv, ARRLEN(reqnv),
5050 item = nghttp2_session_get_next_ob_item(session);
5051 CU_ASSERT(ARRLEN(reqnv) == item->frame.headers.nvlen);
5052 assert_nv_equal(reqnv, item->frame.headers.nva, item->frame.headers.nvlen,
5054 CU_ASSERT(0 == nghttp2_session_send(session));
5055 CU_ASSERT(0 == ud.data_source_length);
5057 nghttp2_session_del(session);
5059 /* nghttp2_submit_request() with server session is error */
5060 nghttp2_session_server_new(&session, &callbacks, NULL);
5062 CU_ASSERT(NGHTTP2_ERR_PROTO == nghttp2_submit_request(session, NULL, reqnv,
5063 ARRLEN(reqnv), NULL,
5066 nghttp2_session_del(session);
5069 void test_nghttp2_submit_request_without_data(void) {
5070 nghttp2_session *session;
5071 nghttp2_session_callbacks callbacks;
5073 nghttp2_data_provider data_prd = {{-1}, NULL};
5074 nghttp2_outbound_item *item;
5076 nghttp2_frame frame;
5077 nghttp2_hd_inflater inflater;
5081 nghttp2_priority_spec pri_spec;
5083 mem = nghttp2_mem_default();
5084 frame_pack_bufs_init(&bufs);
5089 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
5090 callbacks.send_callback = accumulator_send_callback;
5091 CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, &ud));
5093 nghttp2_hd_inflate_init(&inflater, mem);
5094 CU_ASSERT(1 == nghttp2_submit_request(session, NULL, reqnv, ARRLEN(reqnv),
5096 item = nghttp2_session_get_next_ob_item(session);
5097 CU_ASSERT(ARRLEN(reqnv) == item->frame.headers.nvlen);
5098 assert_nv_equal(reqnv, item->frame.headers.nva, item->frame.headers.nvlen,
5100 CU_ASSERT(item->frame.hd.flags & NGHTTP2_FLAG_END_STREAM);
5102 CU_ASSERT(0 == nghttp2_session_send(session));
5103 CU_ASSERT(0 == unpack_frame(&frame, acc.buf, acc.length));
5105 nghttp2_bufs_add(&bufs, acc.buf, acc.length);
5106 inflate_hd(&inflater, &out, &bufs, NGHTTP2_FRAME_HDLEN, mem);
5108 CU_ASSERT(ARRLEN(reqnv) == out.nvlen);
5109 assert_nv_equal(reqnv, out.nva, out.nvlen, mem);
5110 nghttp2_frame_headers_free(&frame.headers, mem);
5111 nva_out_reset(&out, mem);
5113 nghttp2_bufs_free(&bufs);
5114 nghttp2_hd_inflate_free(&inflater);
5116 /* Try to depend on itself is error */
5117 nghttp2_priority_spec_init(&pri_spec, (int32_t)session->next_stream_id, 16,
5120 CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT ==
5121 nghttp2_submit_request(session, &pri_spec, reqnv, ARRLEN(reqnv),
5124 nghttp2_session_del(session);
5127 void test_nghttp2_submit_response_with_data(void) {
5128 nghttp2_session *session;
5129 nghttp2_session_callbacks callbacks;
5130 nghttp2_data_provider data_prd;
5132 nghttp2_outbound_item *item;
5135 mem = nghttp2_mem_default();
5137 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
5138 callbacks.send_callback = null_send_callback;
5140 data_prd.read_callback = fixed_length_data_source_read_callback;
5141 ud.data_source_length = 64 * 1024 - 1;
5142 CU_ASSERT(0 == nghttp2_session_server_new(&session, &callbacks, &ud));
5143 open_recv_stream2(session, 1, NGHTTP2_STREAM_OPENING);
5144 CU_ASSERT(0 == nghttp2_submit_response(session, 1, resnv, ARRLEN(resnv),
5146 item = nghttp2_session_get_next_ob_item(session);
5147 CU_ASSERT(ARRLEN(resnv) == item->frame.headers.nvlen);
5148 assert_nv_equal(resnv, item->frame.headers.nva, item->frame.headers.nvlen,
5150 CU_ASSERT(0 == nghttp2_session_send(session));
5151 CU_ASSERT(0 == ud.data_source_length);
5153 nghttp2_session_del(session);
5155 /* Various error cases */
5156 nghttp2_session_client_new(&session, &callbacks, NULL);
5158 /* Calling nghttp2_submit_response() with client session is error */
5159 CU_ASSERT(NGHTTP2_ERR_PROTO ==
5160 nghttp2_submit_response(session, 1, resnv, ARRLEN(resnv), NULL));
5162 /* Stream ID <= 0 is error */
5163 CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT ==
5164 nghttp2_submit_response(session, 0, resnv, ARRLEN(resnv), NULL));
5166 nghttp2_session_del(session);
5169 void test_nghttp2_submit_response_without_data(void) {
5170 nghttp2_session *session;
5171 nghttp2_session_callbacks callbacks;
5173 nghttp2_data_provider data_prd = {{-1}, NULL};
5174 nghttp2_outbound_item *item;
5176 nghttp2_frame frame;
5177 nghttp2_hd_inflater inflater;
5182 mem = nghttp2_mem_default();
5183 frame_pack_bufs_init(&bufs);
5188 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
5189 callbacks.send_callback = accumulator_send_callback;
5190 CU_ASSERT(0 == nghttp2_session_server_new(&session, &callbacks, &ud));
5192 nghttp2_hd_inflate_init(&inflater, mem);
5193 open_recv_stream2(session, 1, NGHTTP2_STREAM_OPENING);
5194 CU_ASSERT(0 == nghttp2_submit_response(session, 1, resnv, ARRLEN(resnv),
5196 item = nghttp2_session_get_next_ob_item(session);
5197 CU_ASSERT(ARRLEN(resnv) == item->frame.headers.nvlen);
5198 assert_nv_equal(resnv, item->frame.headers.nva, item->frame.headers.nvlen,
5200 CU_ASSERT(item->frame.hd.flags & NGHTTP2_FLAG_END_STREAM);
5202 CU_ASSERT(0 == nghttp2_session_send(session));
5203 CU_ASSERT(0 == unpack_frame(&frame, acc.buf, acc.length));
5205 nghttp2_bufs_add(&bufs, acc.buf, acc.length);
5206 inflate_hd(&inflater, &out, &bufs, NGHTTP2_FRAME_HDLEN, mem);
5208 CU_ASSERT(ARRLEN(resnv) == out.nvlen);
5209 assert_nv_equal(resnv, out.nva, out.nvlen, mem);
5211 nva_out_reset(&out, mem);
5212 nghttp2_bufs_free(&bufs);
5213 nghttp2_frame_headers_free(&frame.headers, mem);
5214 nghttp2_hd_inflate_free(&inflater);
5215 nghttp2_session_del(session);
5218 void test_nghttp2_submit_response_push_response(void) {
5219 nghttp2_session *session;
5220 nghttp2_session_callbacks callbacks;
5223 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
5224 callbacks.send_callback = null_send_callback;
5225 callbacks.on_frame_not_send_callback = on_frame_not_send_callback;
5227 nghttp2_session_server_new(&session, &callbacks, &ud);
5229 open_sent_stream2(session, 2, NGHTTP2_STREAM_RESERVED);
5231 session->goaway_flags |= NGHTTP2_GOAWAY_RECV;
5234 nghttp2_submit_response(session, 2, resnv, ARRLEN(resnv), NULL));
5236 ud.frame_not_send_cb_called = 0;
5238 CU_ASSERT(0 == nghttp2_session_send(session));
5239 CU_ASSERT(1 == ud.frame_not_send_cb_called);
5241 nghttp2_session_del(session);
5244 void test_nghttp2_submit_trailer(void) {
5245 nghttp2_session *session;
5246 nghttp2_session_callbacks callbacks;
5248 nghttp2_data_provider data_prd;
5249 nghttp2_outbound_item *item;
5251 nghttp2_frame frame;
5252 nghttp2_hd_inflater inflater;
5257 mem = nghttp2_mem_default();
5258 frame_pack_bufs_init(&bufs);
5260 data_prd.read_callback = no_end_stream_data_source_read_callback;
5264 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
5265 callbacks.send_callback = null_send_callback;
5266 CU_ASSERT(0 == nghttp2_session_server_new(&session, &callbacks, &ud));
5268 nghttp2_hd_inflate_init(&inflater, mem);
5269 open_recv_stream2(session, 1, NGHTTP2_STREAM_OPENING);
5270 CU_ASSERT(0 == nghttp2_submit_response(session, 1, resnv, ARRLEN(resnv),
5272 CU_ASSERT(0 == nghttp2_session_send(session));
5275 nghttp2_submit_trailer(session, 1, trailernv, ARRLEN(trailernv)));
5277 session->callbacks.send_callback = accumulator_send_callback;
5279 item = nghttp2_session_get_next_ob_item(session);
5280 CU_ASSERT(NGHTTP2_HEADERS == item->frame.hd.type);
5281 CU_ASSERT(NGHTTP2_HCAT_HEADERS == item->frame.headers.cat);
5282 CU_ASSERT(item->frame.hd.flags & NGHTTP2_FLAG_END_STREAM);
5284 CU_ASSERT(0 == nghttp2_session_send(session));
5285 CU_ASSERT(0 == unpack_frame(&frame, acc.buf, acc.length));
5287 nghttp2_bufs_add(&bufs, acc.buf, acc.length);
5288 inflate_hd(&inflater, &out, &bufs, NGHTTP2_FRAME_HDLEN, mem);
5290 CU_ASSERT(ARRLEN(trailernv) == out.nvlen);
5291 assert_nv_equal(trailernv, out.nva, out.nvlen, mem);
5293 nva_out_reset(&out, mem);
5294 nghttp2_bufs_free(&bufs);
5295 nghttp2_frame_headers_free(&frame.headers, mem);
5296 nghttp2_hd_inflate_free(&inflater);
5297 nghttp2_session_del(session);
5299 /* Specifying stream ID <= 0 is error */
5300 nghttp2_session_server_new(&session, &callbacks, NULL);
5301 open_recv_stream(session, 1);
5303 CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT ==
5304 nghttp2_submit_trailer(session, 0, trailernv, ARRLEN(trailernv)));
5306 CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT ==
5307 nghttp2_submit_trailer(session, -1, trailernv, ARRLEN(trailernv)));
5309 nghttp2_session_del(session);
5312 void test_nghttp2_submit_headers_start_stream(void) {
5313 nghttp2_session *session;
5314 nghttp2_session_callbacks callbacks;
5315 nghttp2_outbound_item *item;
5318 mem = nghttp2_mem_default();
5320 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
5321 CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, NULL));
5322 CU_ASSERT(1 == nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, -1,
5323 NULL, reqnv, ARRLEN(reqnv), NULL));
5324 item = nghttp2_session_get_next_ob_item(session);
5325 CU_ASSERT(ARRLEN(reqnv) == item->frame.headers.nvlen);
5326 assert_nv_equal(reqnv, item->frame.headers.nva, item->frame.headers.nvlen,
5328 CU_ASSERT((NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM) ==
5329 item->frame.hd.flags);
5330 CU_ASSERT(0 == (item->frame.hd.flags & NGHTTP2_FLAG_PRIORITY));
5332 nghttp2_session_del(session);
5335 void test_nghttp2_submit_headers_reply(void) {
5336 nghttp2_session *session;
5337 nghttp2_session_callbacks callbacks;
5339 nghttp2_outbound_item *item;
5340 nghttp2_stream *stream;
5343 mem = nghttp2_mem_default();
5345 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
5346 callbacks.send_callback = null_send_callback;
5347 callbacks.on_frame_send_callback = on_frame_send_callback;
5349 CU_ASSERT(0 == nghttp2_session_server_new(&session, &callbacks, &ud));
5350 CU_ASSERT(0 == nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, 1,
5351 NULL, resnv, ARRLEN(resnv), NULL));
5352 item = nghttp2_session_get_next_ob_item(session);
5353 CU_ASSERT(ARRLEN(resnv) == item->frame.headers.nvlen);
5354 assert_nv_equal(resnv, item->frame.headers.nva, item->frame.headers.nvlen,
5356 CU_ASSERT((NGHTTP2_FLAG_END_STREAM | NGHTTP2_FLAG_END_HEADERS) ==
5357 item->frame.hd.flags);
5359 ud.frame_send_cb_called = 0;
5360 ud.sent_frame_type = 0;
5361 /* The transimission will be canceled because the stream 1 is not
5363 CU_ASSERT(0 == nghttp2_session_send(session));
5364 CU_ASSERT(0 == ud.frame_send_cb_called);
5366 stream = open_recv_stream2(session, 1, NGHTTP2_STREAM_OPENING);
5368 CU_ASSERT(0 == nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, 1,
5369 NULL, resnv, ARRLEN(resnv), NULL));
5370 CU_ASSERT(0 == nghttp2_session_send(session));
5371 CU_ASSERT(1 == ud.frame_send_cb_called);
5372 CU_ASSERT(NGHTTP2_HEADERS == ud.sent_frame_type);
5373 CU_ASSERT(stream->shut_flags & NGHTTP2_SHUT_WR);
5375 nghttp2_session_del(session);
5378 void test_nghttp2_submit_headers_push_reply(void) {
5379 nghttp2_session *session;
5380 nghttp2_session_callbacks callbacks;
5382 nghttp2_stream *stream;
5385 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
5386 callbacks.send_callback = null_send_callback;
5387 callbacks.on_frame_send_callback = on_frame_send_callback;
5389 CU_ASSERT(0 == nghttp2_session_server_new(&session, &callbacks, &ud));
5390 stream = open_sent_stream2(session, 2, NGHTTP2_STREAM_RESERVED);
5391 CU_ASSERT(0 == nghttp2_submit_headers(session, NGHTTP2_FLAG_NONE, 2, NULL,
5392 resnv, ARRLEN(resnv), &foo));
5394 ud.frame_send_cb_called = 0;
5395 ud.sent_frame_type = 0;
5396 CU_ASSERT(0 == nghttp2_session_send(session));
5397 CU_ASSERT(1 == ud.frame_send_cb_called);
5398 CU_ASSERT(NGHTTP2_HEADERS == ud.sent_frame_type);
5399 CU_ASSERT(NGHTTP2_STREAM_OPENED == stream->state);
5400 CU_ASSERT(&foo == stream->stream_user_data);
5402 nghttp2_session_del(session);
5404 /* Sending HEADERS from client against stream in reserved state is
5406 CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, &ud));
5407 open_recv_stream2(session, 2, NGHTTP2_STREAM_RESERVED);
5408 CU_ASSERT(0 == nghttp2_submit_headers(session, NGHTTP2_FLAG_NONE, 2, NULL,
5409 reqnv, ARRLEN(reqnv), NULL));
5411 ud.frame_send_cb_called = 0;
5412 ud.sent_frame_type = 0;
5413 CU_ASSERT(0 == nghttp2_session_send(session));
5414 CU_ASSERT(0 == ud.frame_send_cb_called);
5416 nghttp2_session_del(session);
5419 void test_nghttp2_submit_headers(void) {
5420 nghttp2_session *session;
5421 nghttp2_session_callbacks callbacks;
5423 nghttp2_outbound_item *item;
5424 nghttp2_stream *stream;
5426 nghttp2_frame frame;
5427 nghttp2_hd_inflater inflater;
5431 nghttp2_priority_spec pri_spec;
5433 mem = nghttp2_mem_default();
5434 frame_pack_bufs_init(&bufs);
5439 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
5440 callbacks.send_callback = accumulator_send_callback;
5441 callbacks.on_frame_send_callback = on_frame_send_callback;
5443 CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, &ud));
5445 nghttp2_hd_inflate_init(&inflater, mem);
5446 CU_ASSERT(0 == nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, 1,
5447 NULL, reqnv, ARRLEN(reqnv), NULL));
5448 item = nghttp2_session_get_next_ob_item(session);
5449 CU_ASSERT(ARRLEN(reqnv) == item->frame.headers.nvlen);
5450 assert_nv_equal(reqnv, item->frame.headers.nva, item->frame.headers.nvlen,
5452 CU_ASSERT((NGHTTP2_FLAG_END_STREAM | NGHTTP2_FLAG_END_HEADERS) ==
5453 item->frame.hd.flags);
5455 ud.frame_send_cb_called = 0;
5456 ud.sent_frame_type = 0;
5457 /* The transimission will be canceled because the stream 1 is not
5459 CU_ASSERT(0 == nghttp2_session_send(session));
5460 CU_ASSERT(0 == ud.frame_send_cb_called);
5462 stream = open_sent_stream(session, 1);
5464 CU_ASSERT(0 == nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, 1,
5465 NULL, reqnv, ARRLEN(reqnv), NULL));
5466 CU_ASSERT(0 == nghttp2_session_send(session));
5467 CU_ASSERT(1 == ud.frame_send_cb_called);
5468 CU_ASSERT(NGHTTP2_HEADERS == ud.sent_frame_type);
5469 CU_ASSERT(stream->shut_flags & NGHTTP2_SHUT_WR);
5471 CU_ASSERT(0 == unpack_frame(&frame, acc.buf, acc.length));
5473 nghttp2_bufs_add(&bufs, acc.buf, acc.length);
5474 inflate_hd(&inflater, &out, &bufs, NGHTTP2_FRAME_HDLEN, mem);
5476 CU_ASSERT(ARRLEN(reqnv) == out.nvlen);
5477 assert_nv_equal(reqnv, out.nva, out.nvlen, mem);
5479 nva_out_reset(&out, mem);
5480 nghttp2_bufs_free(&bufs);
5481 nghttp2_frame_headers_free(&frame.headers, mem);
5483 nghttp2_hd_inflate_free(&inflater);
5485 /* Try to depend on itself */
5486 nghttp2_priority_spec_init(&pri_spec, 3, 16, 0);
5488 CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT ==
5489 nghttp2_submit_headers(session, NGHTTP2_FLAG_NONE, 3, &pri_spec,
5490 reqnv, ARRLEN(reqnv), NULL));
5492 session->next_stream_id = 5;
5493 nghttp2_priority_spec_init(&pri_spec, 5, 16, 0);
5495 CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT ==
5496 nghttp2_submit_headers(session, NGHTTP2_FLAG_NONE, -1, &pri_spec,
5497 reqnv, ARRLEN(reqnv), NULL));
5499 nghttp2_session_del(session);
5501 /* Error cases with invalid stream ID */
5502 nghttp2_session_server_new(&session, &callbacks, NULL);
5504 /* Sending nghttp2_submit_headers() with stream_id == 1 and server
5506 CU_ASSERT(NGHTTP2_ERR_PROTO ==
5507 nghttp2_submit_headers(session, NGHTTP2_FLAG_NONE, -1, NULL, reqnv,
5508 ARRLEN(reqnv), NULL));
5510 /* Sending stream ID <= 0 is error */
5511 CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT ==
5512 nghttp2_submit_headers(session, NGHTTP2_FLAG_NONE, 0, NULL, resnv,
5513 ARRLEN(resnv), NULL));
5515 nghttp2_session_del(session);
5518 void test_nghttp2_submit_headers_continuation(void) {
5519 nghttp2_session *session;
5520 nghttp2_session_callbacks callbacks;
5522 MAKE_NV("h1", ""), MAKE_NV("h1", ""), MAKE_NV("h1", ""),
5523 MAKE_NV("h1", ""), MAKE_NV("h1", ""), MAKE_NV("h1", ""),
5526 nghttp2_outbound_item *item;
5531 memset(data, '0', sizeof(data));
5532 for (i = 0; i < ARRLEN(nv); ++i) {
5533 nv[i].valuelen = sizeof(data);
5537 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
5538 callbacks.send_callback = null_send_callback;
5539 callbacks.on_frame_send_callback = on_frame_send_callback;
5541 CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, &ud));
5542 CU_ASSERT(1 == nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, -1,
5543 NULL, nv, ARRLEN(nv), NULL));
5544 item = nghttp2_session_get_next_ob_item(session);
5545 CU_ASSERT(NGHTTP2_HEADERS == item->frame.hd.type);
5546 CU_ASSERT((NGHTTP2_FLAG_END_STREAM | NGHTTP2_FLAG_END_HEADERS) ==
5547 item->frame.hd.flags);
5548 CU_ASSERT(0 == (item->frame.hd.flags & NGHTTP2_FLAG_PRIORITY));
5550 ud.frame_send_cb_called = 0;
5551 CU_ASSERT(0 == nghttp2_session_send(session));
5552 CU_ASSERT(1 == ud.frame_send_cb_called);
5554 nghttp2_session_del(session);
5557 void test_nghttp2_submit_headers_continuation_extra_large(void) {
5558 nghttp2_session *session;
5559 nghttp2_session_callbacks callbacks;
5561 MAKE_NV("h1", ""), MAKE_NV("h1", ""), MAKE_NV("h1", ""),
5562 MAKE_NV("h1", ""), MAKE_NV("h1", ""), MAKE_NV("h1", ""),
5564 nghttp2_outbound_item *item;
5565 uint8_t data[16384];
5568 nghttp2_option *opt;
5570 memset(data, '0', sizeof(data));
5571 for (i = 0; i < ARRLEN(nv); ++i) {
5572 nv[i].valuelen = sizeof(data);
5576 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
5577 callbacks.send_callback = null_send_callback;
5578 callbacks.on_frame_send_callback = on_frame_send_callback;
5580 /* The default size of max send header block length is too small to
5581 send these header fields. Expand it. */
5582 nghttp2_option_new(&opt);
5583 nghttp2_option_set_max_send_header_block_length(opt, 102400);
5585 CU_ASSERT(0 == nghttp2_session_client_new2(&session, &callbacks, &ud, opt));
5586 CU_ASSERT(1 == nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, -1,
5587 NULL, nv, ARRLEN(nv), NULL));
5588 item = nghttp2_session_get_next_ob_item(session);
5589 CU_ASSERT(NGHTTP2_HEADERS == item->frame.hd.type);
5590 CU_ASSERT((NGHTTP2_FLAG_END_STREAM | NGHTTP2_FLAG_END_HEADERS) ==
5591 item->frame.hd.flags);
5592 CU_ASSERT(0 == (item->frame.hd.flags & NGHTTP2_FLAG_PRIORITY));
5594 ud.frame_send_cb_called = 0;
5595 CU_ASSERT(0 == nghttp2_session_send(session));
5596 CU_ASSERT(1 == ud.frame_send_cb_called);
5598 nghttp2_session_del(session);
5599 nghttp2_option_del(opt);
5602 void test_nghttp2_submit_priority(void) {
5603 nghttp2_session *session;
5604 nghttp2_session_callbacks callbacks;
5605 nghttp2_stream *stream;
5607 nghttp2_priority_spec pri_spec;
5609 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
5610 callbacks.send_callback = null_send_callback;
5611 callbacks.on_frame_send_callback = on_frame_send_callback;
5613 nghttp2_session_client_new(&session, &callbacks, &ud);
5614 stream = open_sent_stream(session, 1);
5616 nghttp2_priority_spec_init(&pri_spec, 0, 3, 0);
5618 /* depends on stream 0 */
5620 nghttp2_submit_priority(session, NGHTTP2_FLAG_NONE, 1, &pri_spec));
5621 CU_ASSERT(0 == nghttp2_session_send(session));
5622 CU_ASSERT(3 == stream->weight);
5624 /* submit against idle stream */
5626 nghttp2_submit_priority(session, NGHTTP2_FLAG_NONE, 3, &pri_spec));
5628 ud.frame_send_cb_called = 0;
5629 CU_ASSERT(0 == nghttp2_session_send(session));
5630 CU_ASSERT(1 == ud.frame_send_cb_called);
5632 nghttp2_session_del(session);
5635 void test_nghttp2_submit_settings(void) {
5636 nghttp2_session *session;
5637 nghttp2_session_callbacks callbacks;
5639 nghttp2_outbound_item *item;
5640 nghttp2_frame *frame;
5641 nghttp2_settings_entry iv[7];
5642 nghttp2_frame ack_frame;
5643 const int32_t UNKNOWN_ID = 1000000007;
5646 mem = nghttp2_mem_default();
5648 iv[0].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS;
5651 iv[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
5652 iv[1].value = 16 * 1024;
5654 iv[2].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS;
5657 iv[3].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
5660 iv[4].settings_id = UNKNOWN_ID;
5663 iv[5].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
5666 iv[6].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
5667 iv[6].value = (uint32_t)NGHTTP2_MAX_WINDOW_SIZE + 1;
5669 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
5670 callbacks.send_callback = null_send_callback;
5671 callbacks.on_frame_send_callback = on_frame_send_callback;
5672 nghttp2_session_server_new(&session, &callbacks, &ud);
5674 CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT ==
5675 nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, iv, 7));
5677 /* Make sure that local settings are not changed */
5678 CU_ASSERT(NGHTTP2_DEFAULT_MAX_CONCURRENT_STREAMS ==
5679 session->local_settings.max_concurrent_streams);
5680 CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE ==
5681 session->local_settings.initial_window_size);
5683 /* Now sends without 6th one */
5684 CU_ASSERT(0 == nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, iv, 6));
5686 item = nghttp2_session_get_next_ob_item(session);
5688 CU_ASSERT(NGHTTP2_SETTINGS == item->frame.hd.type);
5690 frame = &item->frame;
5691 CU_ASSERT(6 == frame->settings.niv);
5692 CU_ASSERT(5 == frame->settings.iv[0].value);
5693 CU_ASSERT(NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS ==
5694 frame->settings.iv[0].settings_id);
5696 CU_ASSERT(16 * 1024 == frame->settings.iv[1].value);
5697 CU_ASSERT(NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE ==
5698 frame->settings.iv[1].settings_id);
5700 CU_ASSERT(UNKNOWN_ID == frame->settings.iv[4].settings_id);
5701 CU_ASSERT(999 == frame->settings.iv[4].value);
5703 ud.frame_send_cb_called = 0;
5704 CU_ASSERT(0 == nghttp2_session_send(session));
5705 CU_ASSERT(1 == ud.frame_send_cb_called);
5707 CU_ASSERT(50 == session->pending_local_max_concurrent_stream);
5709 /* before receiving SETTINGS ACK, local settings have still default
5711 CU_ASSERT(NGHTTP2_DEFAULT_MAX_CONCURRENT_STREAMS ==
5712 nghttp2_session_get_local_settings(
5713 session, NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS));
5714 CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE ==
5715 nghttp2_session_get_local_settings(
5716 session, NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE));
5718 nghttp2_frame_settings_init(&ack_frame.settings, NGHTTP2_FLAG_ACK, NULL, 0);
5719 CU_ASSERT(0 == nghttp2_session_on_settings_received(session, &ack_frame, 0));
5720 nghttp2_frame_settings_free(&ack_frame.settings, mem);
5722 CU_ASSERT(16 * 1024 == session->local_settings.initial_window_size);
5723 CU_ASSERT(1023 == session->hd_inflater.ctx.hd_table_bufsize_max);
5724 CU_ASSERT(111 == session->hd_inflater.min_hd_table_bufsize_max);
5725 CU_ASSERT(50 == session->local_settings.max_concurrent_streams);
5727 CU_ASSERT(50 == nghttp2_session_get_local_settings(
5728 session, NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS));
5729 CU_ASSERT(16 * 1024 == nghttp2_session_get_local_settings(
5730 session, NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE));
5732 /* We just keep the last seen value */
5733 CU_ASSERT(50 == session->pending_local_max_concurrent_stream);
5735 nghttp2_session_del(session);
5738 void test_nghttp2_submit_settings_update_local_window_size(void) {
5739 nghttp2_session *session;
5740 nghttp2_session_callbacks callbacks;
5741 nghttp2_outbound_item *item;
5742 nghttp2_settings_entry iv[4];
5743 nghttp2_stream *stream;
5744 nghttp2_frame ack_frame;
5746 nghttp2_option *option;
5748 mem = nghttp2_mem_default();
5749 nghttp2_frame_settings_init(&ack_frame.settings, NGHTTP2_FLAG_ACK, NULL, 0);
5751 iv[0].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
5752 iv[0].value = 16 * 1024;
5754 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
5755 callbacks.send_callback = null_send_callback;
5757 nghttp2_session_server_new(&session, &callbacks, NULL);
5759 stream = open_recv_stream(session, 1);
5760 stream->local_window_size = NGHTTP2_INITIAL_WINDOW_SIZE + 100;
5761 stream->recv_window_size = 32768;
5763 open_recv_stream(session, 3);
5765 CU_ASSERT(0 == nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, iv, 1));
5766 CU_ASSERT(0 == nghttp2_session_send(session));
5767 CU_ASSERT(0 == nghttp2_session_on_settings_received(session, &ack_frame, 0));
5769 stream = nghttp2_session_get_stream(session, 1);
5770 CU_ASSERT(0 == stream->recv_window_size);
5771 CU_ASSERT(16 * 1024 + 100 == stream->local_window_size);
5773 stream = nghttp2_session_get_stream(session, 3);
5774 CU_ASSERT(16 * 1024 == stream->local_window_size);
5776 item = nghttp2_session_get_next_ob_item(session);
5777 CU_ASSERT(NGHTTP2_WINDOW_UPDATE == item->frame.hd.type);
5778 CU_ASSERT(32768 == item->frame.window_update.window_size_increment);
5780 nghttp2_session_del(session);
5782 /* Without auto-window update */
5783 nghttp2_option_new(&option);
5784 nghttp2_option_set_no_auto_window_update(option, 1);
5786 nghttp2_session_server_new2(&session, &callbacks, NULL, option);
5788 nghttp2_option_del(option);
5790 stream = open_recv_stream(session, 1);
5791 stream->local_window_size = NGHTTP2_INITIAL_WINDOW_SIZE + 100;
5792 stream->recv_window_size = 32768;
5794 CU_ASSERT(0 == nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, iv, 1));
5795 CU_ASSERT(0 == nghttp2_session_send(session));
5796 CU_ASSERT(0 == nghttp2_session_on_settings_received(session, &ack_frame, 0));
5798 stream = nghttp2_session_get_stream(session, 1);
5800 CU_ASSERT(32768 == stream->recv_window_size);
5801 CU_ASSERT(16 * 1024 + 100 == stream->local_window_size);
5802 /* Check that we can handle the case where local_window_size <
5804 CU_ASSERT(0 == nghttp2_session_get_stream_local_window_size(session, 1));
5806 nghttp2_session_del(session);
5808 /* Check overflow case */
5809 iv[0].value = 128 * 1024;
5810 nghttp2_session_server_new(&session, &callbacks, NULL);
5811 stream = open_recv_stream(session, 1);
5812 stream->local_window_size = NGHTTP2_MAX_WINDOW_SIZE;
5814 CU_ASSERT(0 == nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, iv, 1));
5815 CU_ASSERT(0 == nghttp2_session_send(session));
5816 CU_ASSERT(0 == nghttp2_session_on_settings_received(session, &ack_frame, 0));
5818 item = nghttp2_session_get_next_ob_item(session);
5819 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
5820 CU_ASSERT(NGHTTP2_FLOW_CONTROL_ERROR == item->frame.rst_stream.error_code);
5822 nghttp2_session_del(session);
5823 nghttp2_frame_settings_free(&ack_frame.settings, mem);
5826 void test_nghttp2_submit_settings_multiple_times(void) {
5827 nghttp2_session *session;
5828 nghttp2_session_callbacks callbacks;
5829 nghttp2_settings_entry iv[4];
5830 nghttp2_frame frame;
5831 nghttp2_inflight_settings *inflight_settings;
5833 memset(&callbacks, 0, sizeof(callbacks));
5834 callbacks.send_callback = null_send_callback;
5836 nghttp2_session_client_new(&session, &callbacks, NULL);
5838 /* first SETTINGS */
5839 iv[0].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS;
5842 iv[1].settings_id = NGHTTP2_SETTINGS_ENABLE_PUSH;
5845 CU_ASSERT(0 == nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, iv, 2));
5847 inflight_settings = session->inflight_settings_head;
5849 CU_ASSERT(NULL != inflight_settings);
5850 CU_ASSERT(NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS ==
5851 inflight_settings->iv[0].settings_id);
5852 CU_ASSERT(100 == inflight_settings->iv[0].value);
5853 CU_ASSERT(2 == inflight_settings->niv);
5854 CU_ASSERT(NULL == inflight_settings->next);
5856 CU_ASSERT(100 == session->pending_local_max_concurrent_stream);
5857 CU_ASSERT(0 == session->pending_enable_push);
5859 /* second SETTINGS */
5860 iv[0].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS;
5863 CU_ASSERT(0 == nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, iv, 1));
5865 inflight_settings = session->inflight_settings_head->next;
5867 CU_ASSERT(NULL != inflight_settings);
5868 CU_ASSERT(NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS ==
5869 inflight_settings->iv[0].settings_id);
5870 CU_ASSERT(99 == inflight_settings->iv[0].value);
5871 CU_ASSERT(1 == inflight_settings->niv);
5872 CU_ASSERT(NULL == inflight_settings->next);
5874 CU_ASSERT(99 == session->pending_local_max_concurrent_stream);
5875 CU_ASSERT(0 == session->pending_enable_push);
5877 nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_ACK, NULL, 0);
5879 /* receive SETTINGS ACK */
5880 CU_ASSERT(0 == nghttp2_session_on_settings_received(session, &frame, 0));
5882 inflight_settings = session->inflight_settings_head;
5884 /* first inflight SETTINGS was removed */
5885 CU_ASSERT(NULL != inflight_settings);
5886 CU_ASSERT(NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS ==
5887 inflight_settings->iv[0].settings_id);
5888 CU_ASSERT(99 == inflight_settings->iv[0].value);
5889 CU_ASSERT(1 == inflight_settings->niv);
5890 CU_ASSERT(NULL == inflight_settings->next);
5892 CU_ASSERT(100 == session->local_settings.max_concurrent_streams);
5894 /* receive SETTINGS ACK again */
5895 CU_ASSERT(0 == nghttp2_session_on_settings_received(session, &frame, 0));
5897 CU_ASSERT(NULL == session->inflight_settings_head);
5898 CU_ASSERT(99 == session->local_settings.max_concurrent_streams);
5900 nghttp2_session_del(session);
5903 void test_nghttp2_submit_push_promise(void) {
5904 nghttp2_session *session;
5905 nghttp2_session_callbacks callbacks;
5907 nghttp2_stream *stream;
5909 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
5910 callbacks.send_callback = null_send_callback;
5911 callbacks.on_frame_send_callback = on_frame_send_callback;
5912 callbacks.on_frame_not_send_callback = on_frame_not_send_callback;
5914 CU_ASSERT(0 == nghttp2_session_server_new(&session, &callbacks, &ud));
5915 open_recv_stream(session, 1);
5916 CU_ASSERT(2 == nghttp2_submit_push_promise(session, NGHTTP2_FLAG_NONE, 1,
5917 reqnv, ARRLEN(reqnv), &ud));
5919 stream = nghttp2_session_get_stream(session, 2);
5921 CU_ASSERT(NULL != stream);
5922 CU_ASSERT(NGHTTP2_STREAM_RESERVED == stream->state);
5923 CU_ASSERT(&ud == nghttp2_session_get_stream_user_data(session, 2));
5925 ud.frame_send_cb_called = 0;
5926 ud.sent_frame_type = 0;
5928 CU_ASSERT(0 == nghttp2_session_send(session));
5929 CU_ASSERT(1 == ud.frame_send_cb_called);
5930 CU_ASSERT(NGHTTP2_PUSH_PROMISE == ud.sent_frame_type);
5932 stream = nghttp2_session_get_stream(session, 2);
5934 CU_ASSERT(NGHTTP2_STREAM_RESERVED == stream->state);
5935 CU_ASSERT(&ud == nghttp2_session_get_stream_user_data(session, 2));
5937 /* submit PUSH_PROMISE while associated stream is not opened */
5938 CU_ASSERT(NGHTTP2_ERR_STREAM_CLOSED ==
5939 nghttp2_submit_push_promise(session, NGHTTP2_FLAG_NONE, 3, reqnv,
5940 ARRLEN(reqnv), NULL));
5942 /* Stream ID <= 0 is error */
5943 CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT ==
5944 nghttp2_submit_push_promise(session, NGHTTP2_FLAG_NONE, 0, reqnv,
5945 ARRLEN(reqnv), NULL));
5947 nghttp2_session_del(session);
5950 void test_nghttp2_submit_window_update(void) {
5951 nghttp2_session *session;
5952 nghttp2_session_callbacks callbacks;
5954 nghttp2_outbound_item *item;
5955 nghttp2_stream *stream;
5957 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
5958 callbacks.send_callback = null_send_callback;
5960 nghttp2_session_client_new(&session, &callbacks, &ud);
5961 stream = open_recv_stream(session, 2);
5962 stream->recv_window_size = 4096;
5965 nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 2, 1024));
5966 item = nghttp2_session_get_next_ob_item(session);
5967 CU_ASSERT(NGHTTP2_WINDOW_UPDATE == item->frame.hd.type);
5968 CU_ASSERT(1024 == item->frame.window_update.window_size_increment);
5969 CU_ASSERT(0 == nghttp2_session_send(session));
5970 CU_ASSERT(3072 == stream->recv_window_size);
5973 nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 2, 4096));
5974 item = nghttp2_session_get_next_ob_item(session);
5975 CU_ASSERT(NGHTTP2_WINDOW_UPDATE == item->frame.hd.type);
5976 CU_ASSERT(4096 == item->frame.window_update.window_size_increment);
5977 CU_ASSERT(0 == nghttp2_session_send(session));
5978 CU_ASSERT(0 == stream->recv_window_size);
5981 nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 2, 4096));
5982 item = nghttp2_session_get_next_ob_item(session);
5983 CU_ASSERT(NGHTTP2_WINDOW_UPDATE == item->frame.hd.type);
5984 CU_ASSERT(4096 == item->frame.window_update.window_size_increment);
5985 CU_ASSERT(0 == nghttp2_session_send(session));
5986 CU_ASSERT(0 == stream->recv_window_size);
5989 nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 2, 0));
5990 /* It is ok if stream is closed or does not exist at the call
5993 nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 4, 4096));
5995 nghttp2_session_del(session);
5998 void test_nghttp2_submit_window_update_local_window_size(void) {
5999 nghttp2_session *session;
6000 nghttp2_session_callbacks callbacks;
6001 nghttp2_outbound_item *item;
6002 nghttp2_stream *stream;
6004 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6005 callbacks.send_callback = null_send_callback;
6007 nghttp2_session_client_new(&session, &callbacks, NULL);
6008 stream = open_recv_stream(session, 2);
6009 stream->recv_window_size = 4096;
6011 CU_ASSERT(0 == nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 2,
6012 stream->recv_window_size + 1));
6013 CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE + 1 == stream->local_window_size);
6014 CU_ASSERT(0 == stream->recv_window_size);
6015 item = nghttp2_session_get_next_ob_item(session);
6016 CU_ASSERT(NGHTTP2_WINDOW_UPDATE == item->frame.hd.type);
6017 CU_ASSERT(4097 == item->frame.window_update.window_size_increment);
6019 CU_ASSERT(0 == nghttp2_session_send(session));
6021 /* Let's decrement local window size */
6022 stream->recv_window_size = 4096;
6023 CU_ASSERT(0 == nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 2,
6024 -stream->local_window_size / 2));
6025 CU_ASSERT(32768 == stream->local_window_size);
6026 CU_ASSERT(-28672 == stream->recv_window_size);
6027 CU_ASSERT(32768 == stream->recv_reduction);
6029 item = nghttp2_session_get_next_ob_item(session);
6030 CU_ASSERT(item == NULL);
6032 /* Increase local window size */
6034 nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 2, 16384));
6035 CU_ASSERT(49152 == stream->local_window_size);
6036 CU_ASSERT(-12288 == stream->recv_window_size);
6037 CU_ASSERT(16384 == stream->recv_reduction);
6038 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
6040 CU_ASSERT(NGHTTP2_ERR_FLOW_CONTROL ==
6041 nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 2,
6042 NGHTTP2_MAX_WINDOW_SIZE));
6044 CU_ASSERT(0 == nghttp2_session_send(session));
6046 /* Check connection-level flow control */
6047 session->recv_window_size = 4096;
6048 CU_ASSERT(0 == nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 0,
6049 session->recv_window_size + 1));
6050 CU_ASSERT(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE + 1 ==
6051 session->local_window_size);
6052 CU_ASSERT(0 == session->recv_window_size);
6053 item = nghttp2_session_get_next_ob_item(session);
6054 CU_ASSERT(NGHTTP2_WINDOW_UPDATE == item->frame.hd.type);
6055 CU_ASSERT(4097 == item->frame.window_update.window_size_increment);
6057 CU_ASSERT(0 == nghttp2_session_send(session));
6059 /* Go decrement part */
6060 session->recv_window_size = 4096;
6061 CU_ASSERT(0 == nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 0,
6062 -session->local_window_size / 2));
6063 CU_ASSERT(32768 == session->local_window_size);
6064 CU_ASSERT(-28672 == session->recv_window_size);
6065 CU_ASSERT(32768 == session->recv_reduction);
6066 item = nghttp2_session_get_next_ob_item(session);
6067 CU_ASSERT(item == NULL);
6069 /* Increase local window size */
6071 nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 0, 16384));
6072 CU_ASSERT(49152 == session->local_window_size);
6073 CU_ASSERT(-12288 == session->recv_window_size);
6074 CU_ASSERT(16384 == session->recv_reduction);
6075 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
6077 CU_ASSERT(NGHTTP2_ERR_FLOW_CONTROL ==
6078 nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 0,
6079 NGHTTP2_MAX_WINDOW_SIZE));
6081 nghttp2_session_del(session);
6084 void test_nghttp2_submit_shutdown_notice(void) {
6085 nghttp2_session *session;
6086 nghttp2_session_callbacks callbacks;
6089 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6090 callbacks.send_callback = null_send_callback;
6091 callbacks.on_frame_send_callback = on_frame_send_callback;
6092 callbacks.on_frame_not_send_callback = on_frame_not_send_callback;
6094 nghttp2_session_server_new(&session, &callbacks, &ud);
6096 CU_ASSERT(0 == nghttp2_submit_shutdown_notice(session));
6098 ud.frame_send_cb_called = 0;
6100 nghttp2_session_send(session);
6102 CU_ASSERT(1 == ud.frame_send_cb_called);
6103 CU_ASSERT(NGHTTP2_GOAWAY == ud.sent_frame_type);
6104 CU_ASSERT((1u << 31) - 1 == session->local_last_stream_id);
6106 /* After another GOAWAY, nghttp2_submit_shutdown_notice() is
6108 CU_ASSERT(0 == nghttp2_session_terminate_session(session, NGHTTP2_NO_ERROR));
6110 ud.frame_send_cb_called = 0;
6112 nghttp2_session_send(session);
6114 CU_ASSERT(1 == ud.frame_send_cb_called);
6115 CU_ASSERT(NGHTTP2_GOAWAY == ud.sent_frame_type);
6116 CU_ASSERT(0 == session->local_last_stream_id);
6118 CU_ASSERT(0 == nghttp2_submit_shutdown_notice(session));
6120 ud.frame_send_cb_called = 0;
6121 ud.frame_not_send_cb_called = 0;
6123 nghttp2_session_send(session);
6125 CU_ASSERT(0 == ud.frame_send_cb_called);
6126 CU_ASSERT(0 == ud.frame_not_send_cb_called);
6128 nghttp2_session_del(session);
6130 /* Using nghttp2_submit_shutdown_notice() with client side session
6132 nghttp2_session_client_new(&session, &callbacks, NULL);
6134 CU_ASSERT(NGHTTP2_ERR_INVALID_STATE ==
6135 nghttp2_submit_shutdown_notice(session));
6137 nghttp2_session_del(session);
6140 void test_nghttp2_submit_invalid_nv(void) {
6141 nghttp2_session *session;
6142 nghttp2_session_callbacks callbacks;
6143 nghttp2_nv empty_name_nv[] = {MAKE_NV("Version", "HTTP/1.1"),
6144 MAKE_NV("", "empty name")};
6146 /* Now invalid header name/value pair in HTTP/1.1 is accepted in
6149 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6151 CU_ASSERT(0 == nghttp2_session_server_new(&session, &callbacks, NULL));
6153 /* nghttp2_submit_response */
6154 CU_ASSERT(0 == nghttp2_submit_response(session, 2, empty_name_nv,
6155 ARRLEN(empty_name_nv), NULL));
6157 /* nghttp2_submit_push_promise */
6158 open_recv_stream(session, 1);
6160 CU_ASSERT(0 < nghttp2_submit_push_promise(session, NGHTTP2_FLAG_NONE, 1,
6162 ARRLEN(empty_name_nv), NULL));
6164 nghttp2_session_del(session);
6166 CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, NULL));
6168 /* nghttp2_submit_request */
6169 CU_ASSERT(0 < nghttp2_submit_request(session, NULL, empty_name_nv,
6170 ARRLEN(empty_name_nv), NULL, NULL));
6172 /* nghttp2_submit_headers */
6173 CU_ASSERT(0 < nghttp2_submit_headers(session, NGHTTP2_FLAG_NONE, -1, NULL,
6174 empty_name_nv, ARRLEN(empty_name_nv),
6177 nghttp2_session_del(session);
6180 void test_nghttp2_submit_extension(void) {
6181 nghttp2_session *session;
6182 nghttp2_session_callbacks callbacks;
6186 const char data[] = "Hello World!";
6191 mem = nghttp2_mem_default();
6193 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6195 callbacks.pack_extension_callback = pack_extension_callback;
6196 callbacks.send_callback = accumulator_send_callback;
6198 nghttp2_buf_init2(&ud.scratchbuf, 4096, mem);
6200 nghttp2_session_client_new(&session, &callbacks, &ud);
6202 ud.scratchbuf.last = nghttp2_cpymem(ud.scratchbuf.last, data, sizeof(data));
6205 rv = nghttp2_submit_extension(session, 211, 0x01, 3, &ud.scratchbuf);
6211 rv = nghttp2_session_send(session);
6214 CU_ASSERT(NGHTTP2_FRAME_HDLEN + sizeof(data) == acc.length);
6216 len = nghttp2_get_uint32(acc.buf) >> 8;
6218 CU_ASSERT(sizeof(data) == len);
6219 CU_ASSERT(211 == acc.buf[3]);
6220 CU_ASSERT(0x01 == acc.buf[4]);
6222 stream_id = (int32_t)nghttp2_get_uint32(acc.buf + 5);
6224 CU_ASSERT(3 == stream_id);
6225 CU_ASSERT(0 == memcmp(data, &acc.buf[NGHTTP2_FRAME_HDLEN], sizeof(data)));
6227 nghttp2_session_del(session);
6229 /* submitting standard HTTP/2 frame is error */
6230 nghttp2_session_server_new(&session, &callbacks, &ud);
6232 rv = nghttp2_submit_extension(session, NGHTTP2_GOAWAY, NGHTTP2_FLAG_NONE, 0,
6235 CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT == rv);
6237 nghttp2_session_del(session);
6238 nghttp2_buf_free(&ud.scratchbuf, mem);
6241 void test_nghttp2_submit_altsvc(void) {
6242 nghttp2_session *session;
6243 nghttp2_session_callbacks callbacks;
6247 const uint8_t *data;
6248 nghttp2_frame_hd hd;
6250 const uint8_t origin[] = "nghttp2.org";
6251 const uint8_t field_value[] = "h2=\":443\"";
6253 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6255 nghttp2_session_server_new(&session, &callbacks, &ud);
6257 rv = nghttp2_submit_altsvc(session, NGHTTP2_FLAG_NONE, 0, origin,
6258 sizeof(origin) - 1, field_value,
6259 sizeof(field_value) - 1);
6263 ud.frame_send_cb_called = 0;
6265 len = nghttp2_session_mem_send(session, &data);
6267 CU_ASSERT(len == NGHTTP2_FRAME_HDLEN + 2 + sizeof(origin) - 1 +
6268 sizeof(field_value) - 1);
6270 nghttp2_frame_unpack_frame_hd(&hd, data);
6272 CU_ASSERT(2 + sizeof(origin) - 1 + sizeof(field_value) - 1 == hd.length);
6273 CU_ASSERT(NGHTTP2_ALTSVC == hd.type);
6274 CU_ASSERT(NGHTTP2_FLAG_NONE == hd.flags);
6276 origin_len = nghttp2_get_uint16(data + NGHTTP2_FRAME_HDLEN);
6278 CU_ASSERT(sizeof(origin) - 1 == origin_len);
6280 memcmp(origin, data + NGHTTP2_FRAME_HDLEN + 2, sizeof(origin) - 1));
6281 CU_ASSERT(0 == memcmp(field_value,
6282 data + NGHTTP2_FRAME_HDLEN + 2 + sizeof(origin) - 1,
6283 hd.length - (sizeof(origin) - 1) - 2));
6285 /* submitting empty origin with stream_id == 0 is error */
6286 rv = nghttp2_submit_altsvc(session, NGHTTP2_FLAG_NONE, 0, NULL, 0,
6287 field_value, sizeof(field_value) - 1);
6289 CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT == rv);
6291 /* submitting non-empty origin with stream_id != 0 is error */
6292 rv = nghttp2_submit_altsvc(session, NGHTTP2_FLAG_NONE, 1, origin,
6293 sizeof(origin) - 1, field_value,
6294 sizeof(field_value) - 1);
6296 CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT == rv);
6298 nghttp2_session_del(session);
6300 /* submitting from client side session is error */
6301 nghttp2_session_client_new(&session, &callbacks, NULL);
6303 rv = nghttp2_submit_altsvc(session, NGHTTP2_FLAG_NONE, 0, origin,
6304 sizeof(origin) - 1, field_value,
6305 sizeof(field_value) - 1);
6307 CU_ASSERT(NGHTTP2_ERR_INVALID_STATE == rv);
6309 nghttp2_session_del(session);
6312 void test_nghttp2_submit_origin(void) {
6313 nghttp2_session *session;
6314 nghttp2_session_callbacks callbacks;
6318 const uint8_t *data;
6319 static const uint8_t nghttp2[] = "https://nghttp2.org";
6320 static const uint8_t examples[] = "https://examples.com";
6321 static const nghttp2_origin_entry ov[] = {
6324 sizeof(nghttp2) - 1,
6327 (uint8_t *)examples,
6328 sizeof(examples) - 1,
6331 nghttp2_frame frame;
6332 nghttp2_ext_origin origin;
6335 mem = nghttp2_mem_default();
6337 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6338 callbacks.on_frame_send_callback = on_frame_send_callback;
6340 frame.ext.payload = &origin;
6342 nghttp2_session_server_new(&session, &callbacks, &ud);
6344 rv = nghttp2_submit_origin(session, NGHTTP2_FLAG_NONE, ov, 2);
6348 ud.frame_send_cb_called = 0;
6349 len = nghttp2_session_mem_send(session, &data);
6352 CU_ASSERT(1 == ud.frame_send_cb_called);
6354 nghttp2_frame_unpack_frame_hd(&frame.hd, data);
6355 rv = nghttp2_frame_unpack_origin_payload(
6356 &frame.ext, data + NGHTTP2_FRAME_HDLEN, (size_t)len - NGHTTP2_FRAME_HDLEN,
6360 CU_ASSERT(0 == frame.hd.stream_id);
6361 CU_ASSERT(NGHTTP2_ORIGIN == frame.hd.type);
6362 CU_ASSERT(2 == origin.nov);
6363 CU_ASSERT(0 == memcmp(nghttp2, origin.ov[0].origin, sizeof(nghttp2) - 1));
6364 CU_ASSERT(sizeof(nghttp2) - 1 == origin.ov[0].origin_len);
6365 CU_ASSERT(0 == memcmp(examples, origin.ov[1].origin, sizeof(examples) - 1));
6366 CU_ASSERT(sizeof(examples) - 1 == origin.ov[1].origin_len);
6368 nghttp2_frame_origin_free(&frame.ext, mem);
6370 nghttp2_session_del(session);
6372 /* Submitting ORIGIN frame from client session is error */
6373 nghttp2_session_client_new(&session, &callbacks, NULL);
6375 rv = nghttp2_submit_origin(session, NGHTTP2_FLAG_NONE, ov, 1);
6377 CU_ASSERT(NGHTTP2_ERR_INVALID_STATE == rv);
6379 nghttp2_session_del(session);
6381 /* Submitting empty ORIGIN frame */
6382 nghttp2_session_server_new(&session, &callbacks, &ud);
6384 rv = nghttp2_submit_origin(session, NGHTTP2_FLAG_NONE, NULL, 0);
6388 ud.frame_send_cb_called = 0;
6389 len = nghttp2_session_mem_send(session, &data);
6391 CU_ASSERT(len == NGHTTP2_FRAME_HDLEN);
6392 CU_ASSERT(1 == ud.frame_send_cb_called);
6394 nghttp2_frame_unpack_frame_hd(&frame.hd, data);
6396 CU_ASSERT(NGHTTP2_ORIGIN == frame.hd.type);
6398 nghttp2_session_del(session);
6401 void test_nghttp2_submit_rst_stream(void) {
6402 nghttp2_session *session;
6403 nghttp2_session_callbacks callbacks;
6404 nghttp2_outbound_item *item;
6408 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6410 /* Sending RST_STREAM to idle stream (local) is ignored */
6411 nghttp2_session_client_new(&session, &callbacks, NULL);
6413 rv = nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, 1,
6418 item = nghttp2_outbound_queue_top(&session->ob_reg);
6420 CU_ASSERT(NULL == item);
6422 nghttp2_session_del(session);
6424 /* Sending RST_STREAM to idle stream (remote) is ignored */
6425 nghttp2_session_client_new(&session, &callbacks, NULL);
6427 rv = nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, 2,
6432 item = nghttp2_outbound_queue_top(&session->ob_reg);
6434 CU_ASSERT(NULL == item);
6436 nghttp2_session_del(session);
6438 /* Sending RST_STREAM to non-idle stream (local) */
6439 nghttp2_session_client_new(&session, &callbacks, NULL);
6441 open_sent_stream(session, 1);
6443 rv = nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, 1,
6448 item = nghttp2_outbound_queue_top(&session->ob_reg);
6450 CU_ASSERT(NULL != item);
6451 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
6452 CU_ASSERT(1 == item->frame.hd.stream_id);
6454 nghttp2_session_del(session);
6456 /* Sending RST_STREAM to non-idle stream (remote) */
6457 nghttp2_session_client_new(&session, &callbacks, NULL);
6459 open_recv_stream(session, 2);
6461 rv = nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, 2,
6466 item = nghttp2_outbound_queue_top(&session->ob_reg);
6468 CU_ASSERT(NULL != item);
6469 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
6470 CU_ASSERT(2 == item->frame.hd.stream_id);
6472 nghttp2_session_del(session);
6474 /* Sending RST_STREAM to pending stream */
6475 nghttp2_session_client_new(&session, &callbacks, NULL);
6478 nghttp2_submit_request(session, NULL, reqnv, ARRLEN(reqnv), NULL, NULL);
6480 CU_ASSERT(stream_id > 0);
6482 item = nghttp2_outbound_queue_top(&session->ob_syn);
6484 CU_ASSERT(NULL != item);
6485 CU_ASSERT(NGHTTP2_HEADERS == item->frame.hd.type);
6486 CU_ASSERT(0 == item->aux_data.headers.canceled);
6488 rv = nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, stream_id,
6493 item = nghttp2_outbound_queue_top(&session->ob_syn);
6495 CU_ASSERT(NULL != item);
6496 CU_ASSERT(NGHTTP2_HEADERS == item->frame.hd.type);
6497 CU_ASSERT(1 == item->aux_data.headers.canceled);
6499 nghttp2_session_del(session);
6502 void test_nghttp2_session_open_stream(void) {
6503 nghttp2_session *session;
6504 nghttp2_session_callbacks callbacks;
6505 nghttp2_stream *stream;
6506 nghttp2_priority_spec pri_spec;
6508 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6509 nghttp2_session_server_new(&session, &callbacks, NULL);
6511 nghttp2_priority_spec_init(&pri_spec, 0, 245, 0);
6513 stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
6514 &pri_spec, NGHTTP2_STREAM_OPENED, NULL);
6515 CU_ASSERT(1 == session->num_incoming_streams);
6516 CU_ASSERT(0 == session->num_outgoing_streams);
6517 CU_ASSERT(NGHTTP2_STREAM_OPENED == stream->state);
6518 CU_ASSERT(245 == stream->weight);
6519 CU_ASSERT(&session->root == stream->dep_prev);
6520 CU_ASSERT(NGHTTP2_SHUT_NONE == stream->shut_flags);
6522 stream = nghttp2_session_open_stream(session, 2, NGHTTP2_STREAM_FLAG_NONE,
6524 NGHTTP2_STREAM_OPENING, NULL);
6525 CU_ASSERT(1 == session->num_incoming_streams);
6526 CU_ASSERT(1 == session->num_outgoing_streams);
6527 CU_ASSERT(&session->root == stream->dep_prev);
6528 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == stream->weight);
6529 CU_ASSERT(NGHTTP2_SHUT_NONE == stream->shut_flags);
6531 stream = nghttp2_session_open_stream(session, 4, NGHTTP2_STREAM_FLAG_NONE,
6533 NGHTTP2_STREAM_RESERVED, NULL);
6534 CU_ASSERT(1 == session->num_incoming_streams);
6535 CU_ASSERT(1 == session->num_outgoing_streams);
6536 CU_ASSERT(&session->root == stream->dep_prev);
6537 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == stream->weight);
6538 CU_ASSERT(NGHTTP2_SHUT_RD == stream->shut_flags);
6540 nghttp2_priority_spec_init(&pri_spec, 1, 17, 1);
6542 stream = nghttp2_session_open_stream(session, 3, NGHTTP2_STREAM_FLAG_NONE,
6543 &pri_spec, NGHTTP2_STREAM_OPENED, NULL);
6544 CU_ASSERT(17 == stream->weight);
6545 CU_ASSERT(1 == stream->dep_prev->stream_id);
6547 /* Dependency to idle stream */
6548 nghttp2_priority_spec_init(&pri_spec, 1000000007, 240, 1);
6550 stream = nghttp2_session_open_stream(session, 5, NGHTTP2_STREAM_FLAG_NONE,
6551 &pri_spec, NGHTTP2_STREAM_OPENED, NULL);
6552 CU_ASSERT(240 == stream->weight);
6553 CU_ASSERT(1000000007 == stream->dep_prev->stream_id);
6555 stream = nghttp2_session_get_stream_raw(session, 1000000007);
6557 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == stream->weight);
6558 CU_ASSERT(&session->root == stream->dep_prev);
6560 /* Dependency to closed stream which is not in dependency tree */
6561 session->last_recv_stream_id = 7;
6563 nghttp2_priority_spec_init(&pri_spec, 7, 10, 0);
6565 stream = nghttp2_session_open_stream(session, 9, NGHTTP2_FLAG_NONE, &pri_spec,
6566 NGHTTP2_STREAM_OPENED, NULL);
6568 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == stream->weight);
6569 CU_ASSERT(&session->root == stream->dep_prev);
6571 nghttp2_session_del(session);
6573 nghttp2_session_client_new(&session, &callbacks, NULL);
6574 stream = nghttp2_session_open_stream(session, 4, NGHTTP2_STREAM_FLAG_NONE,
6576 NGHTTP2_STREAM_RESERVED, NULL);
6577 CU_ASSERT(0 == session->num_incoming_streams);
6578 CU_ASSERT(0 == session->num_outgoing_streams);
6579 CU_ASSERT(&session->root == stream->dep_prev);
6580 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == stream->weight);
6581 CU_ASSERT(NGHTTP2_SHUT_WR == stream->shut_flags);
6583 nghttp2_session_del(session);
6586 void test_nghttp2_session_open_stream_with_idle_stream_dep(void) {
6587 nghttp2_session *session;
6588 nghttp2_session_callbacks callbacks;
6589 nghttp2_stream *stream;
6590 nghttp2_priority_spec pri_spec;
6592 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6593 nghttp2_session_server_new(&session, &callbacks, NULL);
6595 /* Dependency to idle stream */
6596 nghttp2_priority_spec_init(&pri_spec, 101, 245, 0);
6598 stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
6599 &pri_spec, NGHTTP2_STREAM_OPENED, NULL);
6601 CU_ASSERT(245 == stream->weight);
6602 CU_ASSERT(101 == stream->dep_prev->stream_id);
6604 stream = nghttp2_session_get_stream_raw(session, 101);
6606 CU_ASSERT(NGHTTP2_STREAM_IDLE == stream->state);
6607 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == stream->weight);
6609 nghttp2_priority_spec_init(&pri_spec, 211, 1, 0);
6611 /* stream 101 was already created as idle. */
6612 stream = nghttp2_session_open_stream(session, 101, NGHTTP2_STREAM_FLAG_NONE,
6613 &pri_spec, NGHTTP2_STREAM_OPENED, NULL);
6615 CU_ASSERT(1 == stream->weight);
6616 CU_ASSERT(211 == stream->dep_prev->stream_id);
6618 stream = nghttp2_session_get_stream_raw(session, 211);
6620 CU_ASSERT(NGHTTP2_STREAM_IDLE == stream->state);
6621 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == stream->weight);
6623 nghttp2_session_del(session);
6626 void test_nghttp2_session_get_next_ob_item(void) {
6627 nghttp2_session *session;
6628 nghttp2_session_callbacks callbacks;
6629 nghttp2_priority_spec pri_spec;
6631 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6632 callbacks.send_callback = null_send_callback;
6634 nghttp2_session_client_new(&session, &callbacks, NULL);
6635 session->remote_settings.max_concurrent_streams = 2;
6637 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
6638 nghttp2_submit_ping(session, NGHTTP2_FLAG_NONE, NULL);
6639 CU_ASSERT(NGHTTP2_PING ==
6640 nghttp2_session_get_next_ob_item(session)->frame.hd.type);
6642 CU_ASSERT(1 == nghttp2_submit_request(session, NULL, NULL, 0, NULL, NULL));
6643 CU_ASSERT(NGHTTP2_PING ==
6644 nghttp2_session_get_next_ob_item(session)->frame.hd.type);
6646 CU_ASSERT(0 == nghttp2_session_send(session));
6647 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
6649 /* Incoming stream does not affect the number of outgoing max
6650 concurrent streams. */
6651 open_recv_stream(session, 2);
6653 nghttp2_priority_spec_init(&pri_spec, 0, NGHTTP2_MAX_WEIGHT, 0);
6656 nghttp2_submit_request(session, &pri_spec, NULL, 0, NULL, NULL));
6657 CU_ASSERT(NGHTTP2_HEADERS ==
6658 nghttp2_session_get_next_ob_item(session)->frame.hd.type);
6659 CU_ASSERT(0 == nghttp2_session_send(session));
6662 nghttp2_submit_request(session, &pri_spec, NULL, 0, NULL, NULL));
6663 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
6665 session->remote_settings.max_concurrent_streams = 3;
6667 CU_ASSERT(NGHTTP2_HEADERS ==
6668 nghttp2_session_get_next_ob_item(session)->frame.hd.type);
6670 nghttp2_session_del(session);
6672 /* Check that push reply HEADERS are queued into ob_ss_pq */
6673 nghttp2_session_server_new(&session, &callbacks, NULL);
6674 session->remote_settings.max_concurrent_streams = 0;
6675 open_sent_stream2(session, 2, NGHTTP2_STREAM_RESERVED);
6676 CU_ASSERT(0 == nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, 2,
6677 NULL, NULL, 0, NULL));
6678 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
6679 CU_ASSERT(1 == nghttp2_outbound_queue_size(&session->ob_syn));
6680 nghttp2_session_del(session);
6683 void test_nghttp2_session_pop_next_ob_item(void) {
6684 nghttp2_session *session;
6685 nghttp2_session_callbacks callbacks;
6686 nghttp2_outbound_item *item;
6687 nghttp2_priority_spec pri_spec;
6690 mem = nghttp2_mem_default();
6691 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6692 callbacks.send_callback = null_send_callback;
6694 nghttp2_session_client_new(&session, &callbacks, NULL);
6695 session->remote_settings.max_concurrent_streams = 1;
6697 CU_ASSERT(NULL == nghttp2_session_pop_next_ob_item(session));
6699 nghttp2_submit_ping(session, NGHTTP2_FLAG_NONE, NULL);
6701 nghttp2_priority_spec_init(&pri_spec, 0, 254, 0);
6703 nghttp2_submit_request(session, &pri_spec, NULL, 0, NULL, NULL);
6705 item = nghttp2_session_pop_next_ob_item(session);
6706 CU_ASSERT(NGHTTP2_PING == item->frame.hd.type);
6707 nghttp2_outbound_item_free(item, mem);
6708 mem->free(item, NULL);
6710 item = nghttp2_session_pop_next_ob_item(session);
6711 CU_ASSERT(NGHTTP2_HEADERS == item->frame.hd.type);
6712 nghttp2_outbound_item_free(item, mem);
6713 mem->free(item, NULL);
6715 CU_ASSERT(NULL == nghttp2_session_pop_next_ob_item(session));
6717 /* Incoming stream does not affect the number of outgoing max
6718 concurrent streams. */
6719 open_recv_stream(session, 4);
6720 /* In-flight outgoing stream */
6721 open_sent_stream(session, 1);
6723 nghttp2_priority_spec_init(&pri_spec, 0, NGHTTP2_MAX_WEIGHT, 0);
6725 nghttp2_submit_request(session, &pri_spec, NULL, 0, NULL, NULL);
6727 CU_ASSERT(NULL == nghttp2_session_pop_next_ob_item(session));
6729 session->remote_settings.max_concurrent_streams = 2;
6731 item = nghttp2_session_pop_next_ob_item(session);
6732 CU_ASSERT(NGHTTP2_HEADERS == item->frame.hd.type);
6733 nghttp2_outbound_item_free(item, mem);
6734 mem->free(item, NULL);
6736 nghttp2_session_del(session);
6738 /* Check that push reply HEADERS are queued into ob_ss_pq */
6739 nghttp2_session_server_new(&session, &callbacks, NULL);
6740 session->remote_settings.max_concurrent_streams = 0;
6741 open_sent_stream2(session, 2, NGHTTP2_STREAM_RESERVED);
6742 CU_ASSERT(0 == nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, 2,
6743 NULL, NULL, 0, NULL));
6744 CU_ASSERT(NULL == nghttp2_session_pop_next_ob_item(session));
6745 CU_ASSERT(1 == nghttp2_outbound_queue_size(&session->ob_syn));
6746 nghttp2_session_del(session);
6749 void test_nghttp2_session_reply_fail(void) {
6750 nghttp2_session *session;
6751 nghttp2_session_callbacks callbacks;
6752 nghttp2_data_provider data_prd;
6755 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6756 callbacks.send_callback = fail_send_callback;
6758 data_prd.read_callback = fixed_length_data_source_read_callback;
6759 ud.data_source_length = 4 * 1024;
6760 CU_ASSERT(0 == nghttp2_session_server_new(&session, &callbacks, &ud));
6761 open_recv_stream2(session, 1, NGHTTP2_STREAM_OPENING);
6762 CU_ASSERT(0 == nghttp2_submit_response(session, 1, NULL, 0, &data_prd));
6763 CU_ASSERT(NGHTTP2_ERR_CALLBACK_FAILURE == nghttp2_session_send(session));
6764 nghttp2_session_del(session);
6767 void test_nghttp2_session_max_concurrent_streams(void) {
6768 nghttp2_session *session;
6769 nghttp2_session_callbacks callbacks;
6770 nghttp2_frame frame;
6771 nghttp2_outbound_item *item;
6774 mem = nghttp2_mem_default();
6775 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6776 callbacks.send_callback = null_send_callback;
6778 nghttp2_session_server_new(&session, &callbacks, NULL);
6779 open_recv_stream(session, 1);
6781 /* Check un-ACKed SETTINGS_MAX_CONCURRENT_STREAMS */
6782 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 3,
6783 NGHTTP2_HCAT_HEADERS, NULL, NULL, 0);
6784 session->pending_local_max_concurrent_stream = 1;
6786 CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
6787 nghttp2_session_on_request_headers_received(session, &frame));
6789 item = nghttp2_outbound_queue_top(&session->ob_reg);
6790 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
6791 CU_ASSERT(NGHTTP2_REFUSED_STREAM == item->frame.rst_stream.error_code);
6793 CU_ASSERT(0 == nghttp2_session_send(session));
6795 /* Check ACKed SETTINGS_MAX_CONCURRENT_STREAMS */
6796 session->local_settings.max_concurrent_streams = 1;
6797 frame.hd.stream_id = 5;
6799 CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
6800 nghttp2_session_on_request_headers_received(session, &frame));
6802 item = nghttp2_outbound_queue_top(&session->ob_reg);
6803 CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
6804 CU_ASSERT(NGHTTP2_PROTOCOL_ERROR == item->frame.goaway.error_code);
6806 nghttp2_frame_headers_free(&frame.headers, mem);
6807 nghttp2_session_del(session);
6810 void test_nghttp2_session_stop_data_with_rst_stream(void) {
6811 nghttp2_session *session;
6812 nghttp2_session_callbacks callbacks;
6814 nghttp2_data_provider data_prd;
6815 nghttp2_frame frame;
6817 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6818 callbacks.on_frame_send_callback = on_frame_send_callback;
6819 callbacks.send_callback = block_count_send_callback;
6820 data_prd.read_callback = fixed_length_data_source_read_callback;
6822 ud.frame_send_cb_called = 0;
6823 ud.data_source_length = NGHTTP2_DATA_PAYLOADLEN * 4;
6825 nghttp2_session_server_new(&session, &callbacks, &ud);
6826 open_recv_stream2(session, 1, NGHTTP2_STREAM_OPENING);
6827 nghttp2_submit_response(session, 1, NULL, 0, &data_prd);
6830 /* Sends response HEADERS + DATA[0] */
6831 CU_ASSERT(0 == nghttp2_session_send(session));
6832 CU_ASSERT(NGHTTP2_DATA == ud.sent_frame_type);
6833 /* data for DATA[1] is read from data_prd but it is not sent */
6834 CU_ASSERT(ud.data_source_length == NGHTTP2_DATA_PAYLOADLEN * 2);
6836 nghttp2_frame_rst_stream_init(&frame.rst_stream, 1, NGHTTP2_CANCEL);
6837 CU_ASSERT(0 == nghttp2_session_on_rst_stream_received(session, &frame));
6838 nghttp2_frame_rst_stream_free(&frame.rst_stream);
6840 /* Big enough number to send all DATA frames potentially. */
6841 ud.block_count = 100;
6842 /* Nothing will be sent in the following call. */
6843 CU_ASSERT(0 == nghttp2_session_send(session));
6844 /* With RST_STREAM, stream is canceled and further DATA on that
6845 stream are not sent. */
6846 CU_ASSERT(ud.data_source_length == NGHTTP2_DATA_PAYLOADLEN * 2);
6848 CU_ASSERT(NULL == nghttp2_session_get_stream(session, 1));
6850 nghttp2_session_del(session);
6853 void test_nghttp2_session_defer_data(void) {
6854 nghttp2_session *session;
6855 nghttp2_session_callbacks callbacks;
6857 nghttp2_data_provider data_prd;
6858 nghttp2_outbound_item *item;
6859 nghttp2_stream *stream;
6861 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6862 callbacks.on_frame_send_callback = on_frame_send_callback;
6863 callbacks.send_callback = block_count_send_callback;
6864 data_prd.read_callback = defer_data_source_read_callback;
6866 ud.frame_send_cb_called = 0;
6867 ud.data_source_length = NGHTTP2_DATA_PAYLOADLEN * 4;
6869 nghttp2_session_server_new(&session, &callbacks, &ud);
6870 stream = open_recv_stream2(session, 1, NGHTTP2_STREAM_OPENING);
6872 session->remote_window_size = 1 << 20;
6873 stream->remote_window_size = 1 << 20;
6875 nghttp2_submit_response(session, 1, NULL, 0, &data_prd);
6878 /* Sends HEADERS reply */
6879 CU_ASSERT(0 == nghttp2_session_send(session));
6880 CU_ASSERT(NGHTTP2_HEADERS == ud.sent_frame_type);
6881 /* No data is read */
6882 CU_ASSERT(ud.data_source_length == NGHTTP2_DATA_PAYLOADLEN * 4);
6885 nghttp2_submit_ping(session, NGHTTP2_FLAG_NONE, NULL);
6887 CU_ASSERT(0 == nghttp2_session_send(session));
6888 CU_ASSERT(NGHTTP2_PING == ud.sent_frame_type);
6890 /* Resume deferred DATA */
6891 CU_ASSERT(0 == nghttp2_session_resume_data(session, 1));
6892 item = stream->item;
6893 item->aux_data.data.data_prd.read_callback =
6894 fixed_length_data_source_read_callback;
6896 /* Reads 2 DATA chunks */
6897 CU_ASSERT(0 == nghttp2_session_send(session));
6898 CU_ASSERT(ud.data_source_length == NGHTTP2_DATA_PAYLOADLEN * 2);
6900 /* Deferred again */
6901 item->aux_data.data.data_prd.read_callback = defer_data_source_read_callback;
6902 /* This is needed since 16KiB block is already read and waiting to be
6903 sent. No read_callback invocation. */
6905 CU_ASSERT(0 == nghttp2_session_send(session));
6906 CU_ASSERT(ud.data_source_length == NGHTTP2_DATA_PAYLOADLEN * 2);
6908 /* Resume deferred DATA */
6909 CU_ASSERT(0 == nghttp2_session_resume_data(session, 1));
6910 item->aux_data.data.data_prd.read_callback =
6911 fixed_length_data_source_read_callback;
6913 /* Reads 2 16KiB blocks */
6914 CU_ASSERT(0 == nghttp2_session_send(session));
6915 CU_ASSERT(ud.data_source_length == 0);
6917 nghttp2_session_del(session);
6920 void test_nghttp2_session_flow_control(void) {
6921 nghttp2_session *session;
6922 nghttp2_session_callbacks callbacks;
6924 nghttp2_data_provider data_prd;
6925 nghttp2_frame frame;
6926 nghttp2_stream *stream;
6927 int32_t new_initial_window_size;
6928 nghttp2_settings_entry iv[1];
6929 nghttp2_frame settings_frame;
6932 mem = nghttp2_mem_default();
6933 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6934 callbacks.send_callback = fixed_bytes_send_callback;
6935 callbacks.on_frame_send_callback = on_frame_send_callback;
6936 data_prd.read_callback = fixed_length_data_source_read_callback;
6938 ud.frame_send_cb_called = 0;
6939 ud.data_source_length = 128 * 1024;
6940 /* Use smaller emission count so that we can check outbound flow
6941 control window calculation is correct. */
6942 ud.fixed_sendlen = 2 * 1024;
6944 /* Initial window size to 64KiB - 1*/
6945 nghttp2_session_client_new(&session, &callbacks, &ud);
6946 /* Change it to 64KiB for easy calculation */
6947 session->remote_window_size = 64 * 1024;
6948 session->remote_settings.initial_window_size = 64 * 1024;
6950 nghttp2_submit_request(session, NULL, NULL, 0, &data_prd, NULL);
6952 /* Sends 64KiB - 1 data */
6953 CU_ASSERT(0 == nghttp2_session_send(session));
6954 CU_ASSERT(64 * 1024 == ud.data_source_length);
6956 /* Back 32KiB in stream window */
6957 nghttp2_frame_window_update_init(&frame.window_update, NGHTTP2_FLAG_NONE, 1,
6959 nghttp2_session_on_window_update_received(session, &frame);
6961 /* Send nothing because of connection-level window */
6962 CU_ASSERT(0 == nghttp2_session_send(session));
6963 CU_ASSERT(64 * 1024 == ud.data_source_length);
6965 /* Back 32KiB in connection-level window */
6966 frame.hd.stream_id = 0;
6967 nghttp2_session_on_window_update_received(session, &frame);
6969 /* Sends another 32KiB data */
6970 CU_ASSERT(0 == nghttp2_session_send(session));
6971 CU_ASSERT(32 * 1024 == ud.data_source_length);
6973 stream = nghttp2_session_get_stream(session, 1);
6974 /* Change initial window size to 16KiB. The window_size becomes
6976 new_initial_window_size = 16 * 1024;
6977 stream->remote_window_size =
6978 new_initial_window_size -
6979 ((int32_t)session->remote_settings.initial_window_size -
6980 stream->remote_window_size);
6981 session->remote_settings.initial_window_size =
6982 (uint32_t)new_initial_window_size;
6983 CU_ASSERT(-48 * 1024 == stream->remote_window_size);
6985 /* Back 48KiB to stream window */
6986 frame.hd.stream_id = 1;
6987 frame.window_update.window_size_increment = 48 * 1024;
6988 nghttp2_session_on_window_update_received(session, &frame);
6990 /* Nothing is sent because window_size is 0 */
6991 CU_ASSERT(0 == nghttp2_session_send(session));
6992 CU_ASSERT(32 * 1024 == ud.data_source_length);
6994 /* Back 16KiB in stream window */
6995 frame.hd.stream_id = 1;
6996 frame.window_update.window_size_increment = 16 * 1024;
6997 nghttp2_session_on_window_update_received(session, &frame);
6999 /* Back 24KiB in connection-level window */
7000 frame.hd.stream_id = 0;
7001 frame.window_update.window_size_increment = 24 * 1024;
7002 nghttp2_session_on_window_update_received(session, &frame);
7004 /* Sends another 16KiB data */
7005 CU_ASSERT(0 == nghttp2_session_send(session));
7006 CU_ASSERT(16 * 1024 == ud.data_source_length);
7008 /* Increase initial window size to 32KiB */
7009 iv[0].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
7010 iv[0].value = 32 * 1024;
7012 nghttp2_frame_settings_init(&settings_frame.settings, NGHTTP2_FLAG_NONE,
7014 nghttp2_session_on_settings_received(session, &settings_frame, 1);
7015 nghttp2_frame_settings_free(&settings_frame.settings, mem);
7017 /* Sends another 8KiB data */
7018 CU_ASSERT(0 == nghttp2_session_send(session));
7019 CU_ASSERT(8 * 1024 == ud.data_source_length);
7021 /* Back 8KiB in connection-level window */
7022 frame.hd.stream_id = 0;
7023 frame.window_update.window_size_increment = 8 * 1024;
7024 nghttp2_session_on_window_update_received(session, &frame);
7026 /* Sends last 8KiB data */
7027 CU_ASSERT(0 == nghttp2_session_send(session));
7028 CU_ASSERT(0 == ud.data_source_length);
7029 CU_ASSERT(nghttp2_session_get_stream(session, 1)->shut_flags &
7032 nghttp2_frame_window_update_free(&frame.window_update);
7033 nghttp2_session_del(session);
7036 void test_nghttp2_session_flow_control_data_recv(void) {
7037 nghttp2_session *session;
7038 nghttp2_session_callbacks callbacks;
7039 uint8_t data[64 * 1024 + 16];
7040 nghttp2_frame_hd hd;
7041 nghttp2_outbound_item *item;
7042 nghttp2_stream *stream;
7044 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7045 callbacks.send_callback = null_send_callback;
7047 /* Initial window size to 64KiB - 1*/
7048 nghttp2_session_client_new(&session, &callbacks, NULL);
7050 stream = open_sent_stream(session, 1);
7052 nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_WR);
7054 session->local_window_size = NGHTTP2_MAX_PAYLOADLEN;
7055 stream->local_window_size = NGHTTP2_MAX_PAYLOADLEN;
7057 /* Create DATA frame */
7058 memset(data, 0, sizeof(data));
7059 nghttp2_frame_hd_init(&hd, NGHTTP2_MAX_PAYLOADLEN, NGHTTP2_DATA,
7060 NGHTTP2_FLAG_END_STREAM, 1);
7062 nghttp2_frame_pack_frame_hd(data, &hd);
7063 CU_ASSERT(NGHTTP2_MAX_PAYLOADLEN + NGHTTP2_FRAME_HDLEN ==
7064 nghttp2_session_mem_recv(
7065 session, data, NGHTTP2_MAX_PAYLOADLEN + NGHTTP2_FRAME_HDLEN));
7067 item = nghttp2_session_get_next_ob_item(session);
7068 /* Since this is the last frame, stream-level WINDOW_UPDATE is not
7069 issued, but connection-level is. */
7070 CU_ASSERT(NGHTTP2_WINDOW_UPDATE == item->frame.hd.type);
7071 CU_ASSERT(0 == item->frame.hd.stream_id);
7072 CU_ASSERT(NGHTTP2_MAX_PAYLOADLEN ==
7073 item->frame.window_update.window_size_increment);
7075 CU_ASSERT(0 == nghttp2_session_send(session));
7077 /* Receive DATA for closed stream. They are still subject to under
7078 connection-level flow control, since this situation arises when
7079 RST_STREAM is issued by the remote, but the local side keeps
7080 sending DATA frames. Without calculating connection-level window,
7081 the subsequent flow control gets confused. */
7082 CU_ASSERT(NGHTTP2_MAX_PAYLOADLEN + NGHTTP2_FRAME_HDLEN ==
7083 nghttp2_session_mem_recv(
7084 session, data, NGHTTP2_MAX_PAYLOADLEN + NGHTTP2_FRAME_HDLEN));
7086 item = nghttp2_session_get_next_ob_item(session);
7087 CU_ASSERT(NGHTTP2_WINDOW_UPDATE == item->frame.hd.type);
7088 CU_ASSERT(0 == item->frame.hd.stream_id);
7089 CU_ASSERT(NGHTTP2_MAX_PAYLOADLEN ==
7090 item->frame.window_update.window_size_increment);
7092 nghttp2_session_del(session);
7095 void test_nghttp2_session_flow_control_data_with_padding_recv(void) {
7096 nghttp2_session *session;
7097 nghttp2_session_callbacks callbacks;
7099 nghttp2_frame_hd hd;
7100 nghttp2_stream *stream;
7101 nghttp2_option *option;
7103 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7104 callbacks.send_callback = null_send_callback;
7106 nghttp2_option_new(&option);
7107 /* Disable auto window update so that we can check padding is
7108 consumed automatically */
7109 nghttp2_option_set_no_auto_window_update(option, 1);
7111 /* Initial window size to 64KiB - 1*/
7112 nghttp2_session_client_new2(&session, &callbacks, NULL, option);
7114 nghttp2_option_del(option);
7116 stream = open_sent_stream(session, 1);
7118 /* Create DATA frame */
7119 memset(data, 0, sizeof(data));
7120 nghttp2_frame_hd_init(&hd, 357, NGHTTP2_DATA, NGHTTP2_FLAG_PADDED, 1);
7122 nghttp2_frame_pack_frame_hd(data, &hd);
7123 /* Set Pad Length field, which itself is padding */
7124 data[NGHTTP2_FRAME_HDLEN] = 255;
7127 (ssize_t)(NGHTTP2_FRAME_HDLEN + hd.length) ==
7128 nghttp2_session_mem_recv(session, data, NGHTTP2_FRAME_HDLEN + hd.length));
7130 CU_ASSERT((int32_t)hd.length == session->recv_window_size);
7131 CU_ASSERT((int32_t)hd.length == stream->recv_window_size);
7132 CU_ASSERT(256 == session->consumed_size);
7133 CU_ASSERT(256 == stream->consumed_size);
7134 CU_ASSERT(357 == session->recv_window_size);
7135 CU_ASSERT(357 == stream->recv_window_size);
7137 /* Receive the same DATA frame, but in 2 parts: first 9 + 1 + 102
7138 bytes which includes 1st padding byte, and remainder */
7139 CU_ASSERT((ssize_t)(NGHTTP2_FRAME_HDLEN + 103) ==
7140 nghttp2_session_mem_recv(session, data, NGHTTP2_FRAME_HDLEN + 103));
7141 CU_ASSERT(258 == session->consumed_size);
7142 CU_ASSERT(258 == stream->consumed_size);
7143 CU_ASSERT(460 == session->recv_window_size);
7144 CU_ASSERT(460 == stream->recv_window_size);
7146 /* 357 - 103 = 254 bytes left */
7147 CU_ASSERT(254 == nghttp2_session_mem_recv(session, data, 254));
7148 CU_ASSERT(512 == session->consumed_size);
7149 CU_ASSERT(512 == stream->consumed_size);
7150 CU_ASSERT(714 == session->recv_window_size);
7151 CU_ASSERT(714 == stream->recv_window_size);
7153 /* Receive the same DATA frame, but in 2 parts: first 9 = 1 + 101
7154 bytes which only includes data without padding, 2nd part is
7156 CU_ASSERT((ssize_t)(NGHTTP2_FRAME_HDLEN + 102) ==
7157 nghttp2_session_mem_recv(session, data, NGHTTP2_FRAME_HDLEN + 102));
7158 CU_ASSERT(513 == session->consumed_size);
7159 CU_ASSERT(513 == stream->consumed_size);
7160 CU_ASSERT(816 == session->recv_window_size);
7161 CU_ASSERT(816 == stream->recv_window_size);
7163 /* 357 - 102 = 255 bytes left */
7164 CU_ASSERT(255 == nghttp2_session_mem_recv(session, data, 255));
7165 CU_ASSERT(768 == session->consumed_size);
7166 CU_ASSERT(768 == stream->consumed_size);
7167 CU_ASSERT(1071 == session->recv_window_size);
7168 CU_ASSERT(1071 == stream->recv_window_size);
7170 /* Receive the same DATA frame, but in 2 parts: first 9 = 1 + 50
7171 bytes which includes byte up to middle of data, 2nd part is the
7173 CU_ASSERT((ssize_t)(NGHTTP2_FRAME_HDLEN + 51) ==
7174 nghttp2_session_mem_recv(session, data, NGHTTP2_FRAME_HDLEN + 51));
7175 CU_ASSERT(769 == session->consumed_size);
7176 CU_ASSERT(769 == stream->consumed_size);
7177 CU_ASSERT(1122 == session->recv_window_size);
7178 CU_ASSERT(1122 == stream->recv_window_size);
7180 /* 357 - 51 = 306 bytes left */
7181 CU_ASSERT(306 == nghttp2_session_mem_recv(session, data, 306));
7182 CU_ASSERT(1024 == session->consumed_size);
7183 CU_ASSERT(1024 == stream->consumed_size);
7184 CU_ASSERT(1428 == session->recv_window_size);
7185 CU_ASSERT(1428 == stream->recv_window_size);
7187 nghttp2_session_del(session);
7190 void test_nghttp2_session_data_read_temporal_failure(void) {
7191 nghttp2_session *session;
7192 nghttp2_session_callbacks callbacks;
7194 nghttp2_data_provider data_prd;
7195 nghttp2_frame frame;
7196 nghttp2_stream *stream;
7197 size_t data_size = 128 * 1024;
7199 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7200 callbacks.send_callback = null_send_callback;
7201 callbacks.on_frame_send_callback = on_frame_send_callback;
7202 data_prd.read_callback = fixed_length_data_source_read_callback;
7204 ud.data_source_length = data_size;
7206 /* Initial window size is 64KiB - 1 */
7207 nghttp2_session_client_new(&session, &callbacks, &ud);
7208 nghttp2_submit_request(session, NULL, NULL, 0, &data_prd, NULL);
7210 /* Sends NGHTTP2_INITIAL_WINDOW_SIZE data, assuming, it is equal to
7211 or smaller than NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE */
7212 CU_ASSERT(0 == nghttp2_session_send(session));
7213 CU_ASSERT(data_size - NGHTTP2_INITIAL_WINDOW_SIZE == ud.data_source_length);
7215 stream = nghttp2_session_get_stream(session, 1);
7216 CU_ASSERT(NGHTTP2_DATA == stream->item->frame.hd.type);
7218 stream->item->aux_data.data.data_prd.read_callback =
7219 temporal_failure_data_source_read_callback;
7221 /* Back NGHTTP2_INITIAL_WINDOW_SIZE to both connection-level and
7222 stream-wise window */
7223 nghttp2_frame_window_update_init(&frame.window_update, NGHTTP2_FLAG_NONE, 1,
7224 NGHTTP2_INITIAL_WINDOW_SIZE);
7225 nghttp2_session_on_window_update_received(session, &frame);
7226 frame.hd.stream_id = 0;
7227 nghttp2_session_on_window_update_received(session, &frame);
7228 nghttp2_frame_window_update_free(&frame.window_update);
7230 /* Sending data will fail (soft fail) and treated as stream error */
7231 ud.frame_send_cb_called = 0;
7232 CU_ASSERT(0 == nghttp2_session_send(session));
7233 CU_ASSERT(data_size - NGHTTP2_INITIAL_WINDOW_SIZE == ud.data_source_length);
7235 CU_ASSERT(1 == ud.frame_send_cb_called);
7236 CU_ASSERT(NGHTTP2_RST_STREAM == ud.sent_frame_type);
7238 data_prd.read_callback = fail_data_source_read_callback;
7239 nghttp2_submit_request(session, NULL, NULL, 0, &data_prd, NULL);
7240 /* Sending data will fail (hard fail) and session tear down */
7241 CU_ASSERT(NGHTTP2_ERR_CALLBACK_FAILURE == nghttp2_session_send(session));
7243 nghttp2_session_del(session);
7246 void test_nghttp2_session_on_stream_close(void) {
7247 nghttp2_session *session;
7248 nghttp2_session_callbacks callbacks;
7249 my_user_data user_data;
7250 nghttp2_stream *stream;
7252 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7253 callbacks.on_stream_close_callback = on_stream_close_callback;
7254 user_data.stream_close_cb_called = 0;
7256 nghttp2_session_client_new(&session, &callbacks, &user_data);
7258 open_sent_stream3(session, 1, NGHTTP2_STREAM_FLAG_NONE, &pri_spec_default,
7259 NGHTTP2_STREAM_OPENED, &user_data);
7260 CU_ASSERT(stream != NULL);
7261 CU_ASSERT(nghttp2_session_close_stream(session, 1, NGHTTP2_NO_ERROR) == 0);
7262 CU_ASSERT(user_data.stream_close_cb_called == 1);
7263 nghttp2_session_del(session);
7266 void test_nghttp2_session_on_ctrl_not_send(void) {
7267 nghttp2_session *session;
7268 nghttp2_session_callbacks callbacks;
7269 my_user_data user_data;
7270 nghttp2_stream *stream;
7272 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7273 callbacks.on_frame_not_send_callback = on_frame_not_send_callback;
7274 callbacks.send_callback = null_send_callback;
7275 user_data.frame_not_send_cb_called = 0;
7276 user_data.not_sent_frame_type = 0;
7277 user_data.not_sent_error = 0;
7279 nghttp2_session_server_new(&session, &callbacks, &user_data);
7281 open_recv_stream3(session, 1, NGHTTP2_STREAM_FLAG_NONE, &pri_spec_default,
7282 NGHTTP2_STREAM_OPENING, &user_data);
7284 /* Check response HEADERS */
7285 /* Send bogus stream ID */
7286 CU_ASSERT(0 == nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, 3,
7287 NULL, NULL, 0, NULL));
7288 CU_ASSERT(0 == nghttp2_session_send(session));
7289 CU_ASSERT(1 == user_data.frame_not_send_cb_called);
7290 CU_ASSERT(NGHTTP2_HEADERS == user_data.not_sent_frame_type);
7291 CU_ASSERT(NGHTTP2_ERR_STREAM_CLOSED == user_data.not_sent_error);
7293 user_data.frame_not_send_cb_called = 0;
7294 /* Shutdown transmission */
7295 stream->shut_flags |= NGHTTP2_SHUT_WR;
7296 CU_ASSERT(0 == nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, 1,
7297 NULL, NULL, 0, NULL));
7298 CU_ASSERT(0 == nghttp2_session_send(session));
7299 CU_ASSERT(1 == user_data.frame_not_send_cb_called);
7300 CU_ASSERT(NGHTTP2_HEADERS == user_data.not_sent_frame_type);
7301 CU_ASSERT(NGHTTP2_ERR_STREAM_SHUT_WR == user_data.not_sent_error);
7303 stream->shut_flags = NGHTTP2_SHUT_NONE;
7304 user_data.frame_not_send_cb_called = 0;
7305 /* Queue RST_STREAM */
7306 CU_ASSERT(0 == nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, 1,
7307 NULL, NULL, 0, NULL));
7308 CU_ASSERT(0 == nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, 1,
7309 NGHTTP2_INTERNAL_ERROR));
7310 CU_ASSERT(0 == nghttp2_session_send(session));
7311 CU_ASSERT(1 == user_data.frame_not_send_cb_called);
7312 CU_ASSERT(NGHTTP2_HEADERS == user_data.not_sent_frame_type);
7313 CU_ASSERT(NGHTTP2_ERR_STREAM_CLOSING == user_data.not_sent_error);
7315 nghttp2_session_del(session);
7317 /* Check request HEADERS */
7318 user_data.frame_not_send_cb_called = 0;
7319 CU_ASSERT(nghttp2_session_client_new(&session, &callbacks, &user_data) == 0);
7320 /* Maximum Stream ID is reached */
7321 session->next_stream_id = (1u << 31) + 1;
7322 CU_ASSERT(NGHTTP2_ERR_STREAM_ID_NOT_AVAILABLE ==
7323 nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, -1, NULL,
7326 user_data.frame_not_send_cb_called = 0;
7327 /* GOAWAY received */
7328 session->goaway_flags |= NGHTTP2_GOAWAY_RECV;
7329 session->next_stream_id = 9;
7331 CU_ASSERT(0 < nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, -1,
7332 NULL, NULL, 0, NULL));
7333 CU_ASSERT(0 == nghttp2_session_send(session));
7334 CU_ASSERT(1 == user_data.frame_not_send_cb_called);
7335 CU_ASSERT(NGHTTP2_HEADERS == user_data.not_sent_frame_type);
7336 CU_ASSERT(NGHTTP2_ERR_START_STREAM_NOT_ALLOWED == user_data.not_sent_error);
7338 nghttp2_session_del(session);
7341 void test_nghttp2_session_get_outbound_queue_size(void) {
7342 nghttp2_session *session;
7343 nghttp2_session_callbacks callbacks;
7345 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7346 CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, NULL));
7347 CU_ASSERT(0 == nghttp2_session_get_outbound_queue_size(session));
7349 CU_ASSERT(0 == nghttp2_submit_ping(session, NGHTTP2_FLAG_NONE, NULL));
7350 CU_ASSERT(1 == nghttp2_session_get_outbound_queue_size(session));
7352 CU_ASSERT(0 == nghttp2_submit_goaway(session, NGHTTP2_FLAG_NONE, 2,
7353 NGHTTP2_NO_ERROR, NULL, 0));
7354 CU_ASSERT(2 == nghttp2_session_get_outbound_queue_size(session));
7356 nghttp2_session_del(session);
7359 void test_nghttp2_session_get_effective_local_window_size(void) {
7360 nghttp2_session *session;
7361 nghttp2_session_callbacks callbacks;
7362 nghttp2_stream *stream;
7364 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7365 CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, NULL));
7367 stream = open_sent_stream(session, 1);
7369 CU_ASSERT(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE ==
7370 nghttp2_session_get_effective_local_window_size(session));
7371 CU_ASSERT(0 == nghttp2_session_get_effective_recv_data_length(session));
7373 CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE ==
7374 nghttp2_session_get_stream_effective_local_window_size(session, 1));
7376 nghttp2_session_get_stream_effective_recv_data_length(session, 1));
7378 /* Check connection flow control */
7379 session->recv_window_size = 100;
7380 nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 0, 1100);
7382 CU_ASSERT(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE + 1000 ==
7383 nghttp2_session_get_effective_local_window_size(session));
7384 CU_ASSERT(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE + 1000 ==
7385 nghttp2_session_get_local_window_size(session));
7386 CU_ASSERT(0 == nghttp2_session_get_effective_recv_data_length(session));
7388 nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 0, -50);
7389 /* Now session->recv_window_size = -50 */
7390 CU_ASSERT(-50 == session->recv_window_size);
7391 CU_ASSERT(50 == session->recv_reduction);
7392 CU_ASSERT(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE + 950 ==
7393 nghttp2_session_get_effective_local_window_size(session));
7394 CU_ASSERT(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE + 1000 ==
7395 nghttp2_session_get_local_window_size(session));
7396 CU_ASSERT(0 == nghttp2_session_get_effective_recv_data_length(session));
7398 session->recv_window_size += 50;
7400 /* Now session->recv_window_size = 0 */
7402 CU_ASSERT(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE + 950 ==
7403 nghttp2_session_get_local_window_size(session));
7405 nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 0, 100);
7406 CU_ASSERT(50 == session->recv_window_size);
7407 CU_ASSERT(0 == session->recv_reduction);
7408 CU_ASSERT(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE + 1050 ==
7409 nghttp2_session_get_effective_local_window_size(session));
7410 CU_ASSERT(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE + 1000 ==
7411 nghttp2_session_get_local_window_size(session));
7412 CU_ASSERT(50 == nghttp2_session_get_effective_recv_data_length(session));
7414 /* Check stream flow control */
7415 stream->recv_window_size = 100;
7416 nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 1, 1100);
7418 CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE + 1000 ==
7419 nghttp2_session_get_stream_effective_local_window_size(session, 1));
7420 CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE + 1000 ==
7421 nghttp2_session_get_stream_local_window_size(session, 1));
7423 nghttp2_session_get_stream_effective_recv_data_length(session, 1));
7425 nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 1, -50);
7426 /* Now stream->recv_window_size = -50 */
7427 CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE + 950 ==
7428 nghttp2_session_get_stream_effective_local_window_size(session, 1));
7429 CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE + 1000 ==
7430 nghttp2_session_get_stream_local_window_size(session, 1));
7432 nghttp2_session_get_stream_effective_recv_data_length(session, 1));
7434 stream->recv_window_size += 50;
7435 /* Now stream->recv_window_size = 0 */
7436 nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 1, 100);
7437 CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE + 1050 ==
7438 nghttp2_session_get_stream_effective_local_window_size(session, 1));
7439 CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE + 1000 ==
7440 nghttp2_session_get_stream_local_window_size(session, 1));
7442 nghttp2_session_get_stream_effective_recv_data_length(session, 1));
7444 nghttp2_session_del(session);
7447 void test_nghttp2_session_set_option(void) {
7448 nghttp2_session *session;
7449 nghttp2_session_callbacks callbacks;
7450 nghttp2_option *option;
7451 nghttp2_hd_deflater *deflater;
7454 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7455 callbacks.send_callback = null_send_callback;
7457 /* Test for nghttp2_option_set_no_auto_window_update */
7458 nghttp2_option_new(&option);
7459 nghttp2_option_set_no_auto_window_update(option, 1);
7461 nghttp2_session_client_new2(&session, &callbacks, NULL, option);
7463 CU_ASSERT(session->opt_flags & NGHTTP2_OPTMASK_NO_AUTO_WINDOW_UPDATE);
7465 nghttp2_session_del(session);
7466 nghttp2_option_del(option);
7468 /* Test for nghttp2_option_set_peer_max_concurrent_streams */
7469 nghttp2_option_new(&option);
7470 nghttp2_option_set_peer_max_concurrent_streams(option, 100);
7472 nghttp2_session_client_new2(&session, &callbacks, NULL, option);
7474 CU_ASSERT(100 == session->remote_settings.max_concurrent_streams);
7475 nghttp2_session_del(session);
7476 nghttp2_option_del(option);
7478 /* Test for nghttp2_option_set_max_reserved_remote_streams */
7479 nghttp2_option_new(&option);
7480 nghttp2_option_set_max_reserved_remote_streams(option, 99);
7482 nghttp2_session_client_new2(&session, &callbacks, NULL, option);
7484 CU_ASSERT(99 == session->max_incoming_reserved_streams);
7485 nghttp2_session_del(session);
7486 nghttp2_option_del(option);
7488 /* Test for nghttp2_option_set_no_auto_ping_ack */
7489 nghttp2_option_new(&option);
7490 nghttp2_option_set_no_auto_ping_ack(option, 1);
7492 nghttp2_session_client_new2(&session, &callbacks, NULL, option);
7494 CU_ASSERT(session->opt_flags & NGHTTP2_OPTMASK_NO_AUTO_PING_ACK);
7496 nghttp2_session_del(session);
7497 nghttp2_option_del(option);
7499 /* Test for nghttp2_option_set_max_deflate_dynamic_table_size */
7500 nghttp2_option_new(&option);
7501 nghttp2_option_set_max_deflate_dynamic_table_size(option, 0);
7503 nghttp2_session_client_new2(&session, &callbacks, NULL, option);
7505 deflater = &session->hd_deflater;
7507 rv = nghttp2_submit_request(session, NULL, reqnv, ARRLEN(reqnv), NULL, NULL);
7511 rv = nghttp2_session_send(session);
7514 CU_ASSERT(0 == deflater->deflate_hd_table_bufsize_max);
7515 CU_ASSERT(0 == deflater->ctx.hd_table_bufsize);
7517 nghttp2_session_del(session);
7518 nghttp2_option_del(option);
7521 void test_nghttp2_session_data_backoff_by_high_pri_frame(void) {
7522 nghttp2_session *session;
7523 nghttp2_session_callbacks callbacks;
7525 nghttp2_data_provider data_prd;
7526 nghttp2_stream *stream;
7528 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7529 callbacks.send_callback = block_count_send_callback;
7530 callbacks.on_frame_send_callback = on_frame_send_callback;
7531 data_prd.read_callback = fixed_length_data_source_read_callback;
7533 ud.frame_send_cb_called = 0;
7534 ud.data_source_length = NGHTTP2_DATA_PAYLOADLEN * 4;
7536 nghttp2_session_client_new(&session, &callbacks, &ud);
7537 nghttp2_submit_request(session, NULL, NULL, 0, &data_prd, NULL);
7539 session->remote_window_size = 1 << 20;
7542 /* Sends request HEADERS + DATA[0] */
7543 CU_ASSERT(0 == nghttp2_session_send(session));
7545 stream = nghttp2_session_get_stream(session, 1);
7546 stream->remote_window_size = 1 << 20;
7548 CU_ASSERT(NGHTTP2_DATA == ud.sent_frame_type);
7549 /* data for DATA[1] is read from data_prd but it is not sent */
7550 CU_ASSERT(ud.data_source_length == NGHTTP2_DATA_PAYLOADLEN * 2);
7552 nghttp2_submit_ping(session, NGHTTP2_FLAG_NONE, NULL);
7554 /* Sends DATA[1] + PING, PING is interleaved in DATA sequence */
7555 CU_ASSERT(0 == nghttp2_session_send(session));
7556 CU_ASSERT(NGHTTP2_PING == ud.sent_frame_type);
7557 /* data for DATA[2] is read from data_prd but it is not sent */
7558 CU_ASSERT(ud.data_source_length == NGHTTP2_DATA_PAYLOADLEN);
7561 /* Sends DATA[2..3] */
7562 CU_ASSERT(0 == nghttp2_session_send(session));
7564 CU_ASSERT(stream->shut_flags & NGHTTP2_SHUT_WR);
7566 nghttp2_session_del(session);
7569 static void check_session_recv_data_with_padding(nghttp2_bufs *bufs,
7572 nghttp2_session *session;
7574 nghttp2_session_callbacks callbacks;
7578 memset(&callbacks, 0, sizeof(callbacks));
7579 callbacks.on_frame_recv_callback = on_frame_recv_callback;
7580 callbacks.on_data_chunk_recv_callback = on_data_chunk_recv_callback;
7581 nghttp2_session_server_new(&session, &callbacks, &ud);
7583 open_recv_stream(session, 1);
7585 inlen = (size_t)nghttp2_bufs_remove(bufs, &in);
7587 ud.frame_recv_cb_called = 0;
7588 ud.data_chunk_len = 0;
7590 CU_ASSERT((ssize_t)inlen == nghttp2_session_mem_recv(session, in, inlen));
7592 CU_ASSERT(1 == ud.frame_recv_cb_called);
7593 CU_ASSERT(datalen == ud.data_chunk_len);
7595 mem->free(in, NULL);
7596 nghttp2_session_del(session);
7599 void test_nghttp2_session_pack_data_with_padding(void) {
7600 nghttp2_session *session;
7602 nghttp2_session_callbacks callbacks;
7603 nghttp2_data_provider data_prd;
7604 nghttp2_frame *frame;
7605 size_t datalen = 55;
7608 mem = nghttp2_mem_default();
7610 memset(&callbacks, 0, sizeof(callbacks));
7611 callbacks.send_callback = block_count_send_callback;
7612 callbacks.on_frame_send_callback = on_frame_send_callback;
7613 callbacks.select_padding_callback = select_padding_callback;
7615 data_prd.read_callback = fixed_length_data_source_read_callback;
7617 nghttp2_session_client_new(&session, &callbacks, &ud);
7621 nghttp2_submit_request(session, NULL, NULL, 0, &data_prd, NULL);
7623 ud.data_source_length = datalen;
7625 CU_ASSERT(0 == nghttp2_session_send(session));
7626 CU_ASSERT(NGHTTP2_HEADERS == ud.sent_frame_type);
7628 frame = &session->aob.item->frame;
7630 CU_ASSERT(ud.padlen == frame->data.padlen);
7631 CU_ASSERT(frame->hd.flags & NGHTTP2_FLAG_PADDED);
7633 /* Check reception of this DATA frame */
7634 check_session_recv_data_with_padding(&session->aob.framebufs, datalen, mem);
7636 nghttp2_session_del(session);
7639 void test_nghttp2_session_pack_headers_with_padding(void) {
7640 nghttp2_session *session, *sv_session;
7643 nghttp2_session_callbacks callbacks;
7645 memset(&callbacks, 0, sizeof(callbacks));
7646 callbacks.send_callback = accumulator_send_callback;
7647 callbacks.on_frame_send_callback = on_frame_send_callback;
7648 callbacks.select_padding_callback = select_padding_callback;
7649 callbacks.on_frame_recv_callback = on_frame_recv_callback;
7654 nghttp2_session_client_new(&session, &callbacks, &ud);
7655 nghttp2_session_server_new(&sv_session, &callbacks, &ud);
7659 CU_ASSERT(1 == nghttp2_submit_request(session, NULL, reqnv, ARRLEN(reqnv),
7661 CU_ASSERT(0 == nghttp2_session_send(session));
7663 CU_ASSERT(acc.length < NGHTTP2_MAX_PAYLOADLEN);
7664 ud.frame_recv_cb_called = 0;
7665 CU_ASSERT((ssize_t)acc.length ==
7666 nghttp2_session_mem_recv(sv_session, acc.buf, acc.length));
7667 CU_ASSERT(1 == ud.frame_recv_cb_called);
7668 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(sv_session));
7670 nghttp2_session_del(sv_session);
7671 nghttp2_session_del(session);
7674 void test_nghttp2_pack_settings_payload(void) {
7675 nghttp2_settings_entry iv[2];
7678 nghttp2_settings_entry *resiv;
7682 mem = nghttp2_mem_default();
7684 iv[0].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
7686 iv[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
7689 len = nghttp2_pack_settings_payload(buf, sizeof(buf), iv, 2);
7690 CU_ASSERT(2 * NGHTTP2_FRAME_SETTINGS_ENTRY_LENGTH == len);
7691 CU_ASSERT(0 == nghttp2_frame_unpack_settings_payload2(&resiv, &resniv, buf,
7693 CU_ASSERT(2 == resniv);
7694 CU_ASSERT(NGHTTP2_SETTINGS_HEADER_TABLE_SIZE == resiv[0].settings_id);
7695 CU_ASSERT(1023 == resiv[0].value);
7696 CU_ASSERT(NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE == resiv[1].settings_id);
7697 CU_ASSERT(4095 == resiv[1].value);
7699 mem->free(resiv, NULL);
7701 len = nghttp2_pack_settings_payload(buf, 9 /* too small */, iv, 2);
7702 CU_ASSERT(NGHTTP2_ERR_INSUFF_BUFSIZE == len);
7705 #define check_stream_dep_sib(STREAM, DEP_PREV, DEP_NEXT, SIB_PREV, SIB_NEXT) \
7707 CU_ASSERT(DEP_PREV == STREAM->dep_prev); \
7708 CU_ASSERT(DEP_NEXT == STREAM->dep_next); \
7709 CU_ASSERT(SIB_PREV == STREAM->sib_prev); \
7710 CU_ASSERT(SIB_NEXT == STREAM->sib_next); \
7713 /* nghttp2_stream_dep_add() and its families functions should be
7714 tested in nghttp2_stream_test.c, but it is easier to use
7715 nghttp2_session_open_stream(). Therefore, we test them here. */
7716 void test_nghttp2_session_stream_dep_add(void) {
7717 nghttp2_session *session;
7718 nghttp2_session_callbacks callbacks;
7719 nghttp2_stream *a, *b, *c, *d, *e, *root;
7721 memset(&callbacks, 0, sizeof(callbacks));
7723 nghttp2_session_server_new(&session, &callbacks, NULL);
7725 root = &session->root;
7727 a = open_stream(session, 1);
7729 c = open_stream_with_dep(session, 5, a);
7730 b = open_stream_with_dep(session, 3, a);
7731 d = open_stream_with_dep(session, 7, c);
7740 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 2 == a->sum_dep_weight);
7741 CU_ASSERT(0 == b->sum_dep_weight);
7742 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == c->sum_dep_weight);
7743 CU_ASSERT(0 == d->sum_dep_weight);
7745 check_stream_dep_sib(a, root, b, NULL, NULL);
7746 check_stream_dep_sib(b, a, NULL, NULL, c);
7747 check_stream_dep_sib(c, a, d, b, NULL);
7748 check_stream_dep_sib(d, c, NULL, NULL, NULL);
7750 CU_ASSERT(a == session->root.dep_next);
7752 e = open_stream_with_dep_excl(session, 9, a);
7763 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == a->sum_dep_weight);
7764 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 2 == e->sum_dep_weight);
7765 CU_ASSERT(0 == b->sum_dep_weight);
7766 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == c->sum_dep_weight);
7767 CU_ASSERT(0 == d->sum_dep_weight);
7769 check_stream_dep_sib(a, root, e, NULL, NULL);
7770 check_stream_dep_sib(e, a, b, NULL, NULL);
7771 check_stream_dep_sib(b, e, NULL, NULL, c);
7772 check_stream_dep_sib(c, e, d, b, NULL);
7773 check_stream_dep_sib(d, c, NULL, NULL, NULL);
7775 CU_ASSERT(a == session->root.dep_next);
7777 nghttp2_session_del(session);
7780 void test_nghttp2_session_stream_dep_remove(void) {
7781 nghttp2_session *session;
7782 nghttp2_session_callbacks callbacks;
7783 nghttp2_stream *a, *b, *c, *d, *e, *f, *root;
7785 memset(&callbacks, 0, sizeof(callbacks));
7788 nghttp2_session_server_new(&session, &callbacks, NULL);
7790 root = &session->root;
7792 a = open_stream(session, 1);
7793 b = open_stream_with_dep(session, 3, a);
7794 c = open_stream_with_dep(session, 5, a);
7795 d = open_stream_with_dep(session, 7, c);
7804 nghttp2_stream_dep_remove(a);
7812 CU_ASSERT(0 == a->sum_dep_weight);
7813 CU_ASSERT(0 == b->sum_dep_weight);
7814 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == c->sum_dep_weight);
7815 CU_ASSERT(0 == d->sum_dep_weight);
7817 check_stream_dep_sib(a, NULL, NULL, NULL, NULL);
7818 check_stream_dep_sib(b, root, NULL, c, NULL);
7819 check_stream_dep_sib(c, root, d, NULL, b);
7820 check_stream_dep_sib(d, c, NULL, NULL, NULL);
7822 CU_ASSERT(c == session->root.dep_next);
7824 nghttp2_session_del(session);
7826 /* Remove right most stream */
7827 nghttp2_session_server_new(&session, &callbacks, NULL);
7829 root = &session->root;
7831 a = open_stream(session, 1);
7832 b = open_stream_with_dep(session, 3, a);
7833 c = open_stream_with_dep(session, 5, a);
7834 d = open_stream_with_dep(session, 7, c);
7843 nghttp2_stream_dep_remove(b);
7853 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == a->sum_dep_weight);
7854 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == c->sum_dep_weight);
7855 CU_ASSERT(0 == d->sum_dep_weight);
7856 CU_ASSERT(0 == b->sum_dep_weight);
7858 check_stream_dep_sib(a, root, c, NULL, NULL);
7859 check_stream_dep_sib(b, NULL, NULL, NULL, NULL);
7860 check_stream_dep_sib(c, a, d, NULL, NULL);
7861 check_stream_dep_sib(d, c, NULL, NULL, NULL);
7863 CU_ASSERT(a == session->root.dep_next);
7865 nghttp2_session_del(session);
7867 /* Remove left most stream */
7868 nghttp2_session_server_new(&session, &callbacks, NULL);
7870 root = &session->root;
7872 a = open_stream(session, 1);
7873 b = open_stream_with_dep(session, 3, a);
7874 c = open_stream_with_dep(session, 5, a);
7875 d = open_stream_with_dep(session, 7, c);
7876 e = open_stream_with_dep(session, 9, c);
7885 nghttp2_stream_dep_remove(c);
7893 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 2 == a->sum_dep_weight);
7894 CU_ASSERT(0 == b->sum_dep_weight);
7895 CU_ASSERT(0 == d->sum_dep_weight);
7896 CU_ASSERT(0 == c->sum_dep_weight);
7897 CU_ASSERT(0 == e->sum_dep_weight);
7899 check_stream_dep_sib(a, root, e, NULL, NULL);
7900 check_stream_dep_sib(b, a, NULL, d, NULL);
7901 check_stream_dep_sib(c, NULL, NULL, NULL, NULL);
7902 check_stream_dep_sib(d, a, NULL, e, b);
7903 check_stream_dep_sib(e, a, NULL, NULL, d);
7905 nghttp2_session_del(session);
7907 /* Remove middle stream */
7908 nghttp2_session_server_new(&session, &callbacks, NULL);
7910 root = &session->root;
7912 a = open_stream(session, 1);
7913 b = open_stream_with_dep(session, 3, a);
7914 c = open_stream_with_dep(session, 5, a);
7915 d = open_stream_with_dep(session, 7, a);
7916 e = open_stream_with_dep(session, 9, c);
7917 f = open_stream_with_dep(session, 11, c);
7926 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 3 == a->sum_dep_weight);
7927 CU_ASSERT(0 == b->sum_dep_weight);
7928 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 2 == c->sum_dep_weight);
7929 CU_ASSERT(0 == d->sum_dep_weight);
7930 CU_ASSERT(0 == e->sum_dep_weight);
7931 CU_ASSERT(0 == f->sum_dep_weight);
7933 nghttp2_stream_dep_remove(c);
7941 /* c's weight 16 is distributed evenly to e and f. Each weight of e
7943 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 2 + 8 * 2 == a->sum_dep_weight);
7944 CU_ASSERT(0 == b->sum_dep_weight);
7945 CU_ASSERT(0 == c->sum_dep_weight);
7946 CU_ASSERT(0 == d->sum_dep_weight);
7947 CU_ASSERT(0 == e->sum_dep_weight);
7948 CU_ASSERT(0 == f->sum_dep_weight);
7950 check_stream_dep_sib(a, root, d, NULL, NULL);
7951 check_stream_dep_sib(b, a, NULL, e, NULL);
7952 check_stream_dep_sib(c, NULL, NULL, NULL, NULL);
7953 check_stream_dep_sib(e, a, NULL, f, b);
7954 check_stream_dep_sib(f, a, NULL, d, e);
7955 check_stream_dep_sib(d, a, NULL, NULL, f);
7957 nghttp2_session_del(session);
7960 void test_nghttp2_session_stream_dep_add_subtree(void) {
7961 nghttp2_session *session;
7962 nghttp2_session_callbacks callbacks;
7963 nghttp2_stream *a, *b, *c, *d, *e, *f, *root;
7965 memset(&callbacks, 0, sizeof(callbacks));
7967 /* dep_stream has dep_next */
7968 nghttp2_session_server_new(&session, &callbacks, NULL);
7970 root = &session->root;
7972 a = open_stream(session, 1);
7973 b = open_stream_with_dep(session, 3, a);
7974 c = open_stream_with_dep(session, 5, a);
7975 d = open_stream_with_dep(session, 7, c);
7977 e = open_stream(session, 9);
7978 f = open_stream_with_dep(session, 11, e);
7987 nghttp2_stream_dep_remove_subtree(e);
7988 nghttp2_stream_dep_add_subtree(a, e);
7998 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 3 == a->sum_dep_weight);
7999 CU_ASSERT(0 == b->sum_dep_weight);
8000 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == c->sum_dep_weight);
8001 CU_ASSERT(0 == d->sum_dep_weight);
8002 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == e->sum_dep_weight);
8003 CU_ASSERT(0 == f->sum_dep_weight);
8005 check_stream_dep_sib(a, root, e, NULL, NULL);
8006 check_stream_dep_sib(b, a, NULL, c, NULL);
8007 check_stream_dep_sib(c, a, d, e, b);
8008 check_stream_dep_sib(d, c, NULL, NULL, NULL);
8009 check_stream_dep_sib(e, a, f, NULL, c);
8010 check_stream_dep_sib(f, e, NULL, NULL, NULL);
8012 nghttp2_session_del(session);
8014 /* dep_stream has dep_next and now we insert subtree */
8015 nghttp2_session_server_new(&session, &callbacks, NULL);
8017 root = &session->root;
8019 a = open_stream(session, 1);
8020 b = open_stream_with_dep(session, 3, a);
8021 c = open_stream_with_dep(session, 5, a);
8022 d = open_stream_with_dep(session, 7, c);
8024 e = open_stream(session, 9);
8025 f = open_stream_with_dep(session, 11, e);
8034 nghttp2_stream_dep_remove_subtree(e);
8035 nghttp2_stream_dep_insert_subtree(a, e);
8047 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == a->sum_dep_weight);
8048 CU_ASSERT(0 == b->sum_dep_weight);
8049 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == c->sum_dep_weight);
8050 CU_ASSERT(0 == d->sum_dep_weight);
8051 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 3 == e->sum_dep_weight);
8052 CU_ASSERT(0 == f->sum_dep_weight);
8054 check_stream_dep_sib(a, root, e, NULL, NULL);
8055 check_stream_dep_sib(e, a, f, NULL, NULL);
8056 check_stream_dep_sib(f, e, NULL, NULL, c);
8057 check_stream_dep_sib(b, e, NULL, c, NULL);
8058 check_stream_dep_sib(c, e, d, f, b);
8059 check_stream_dep_sib(d, c, NULL, NULL, NULL);
8061 nghttp2_session_del(session);
8064 void test_nghttp2_session_stream_dep_remove_subtree(void) {
8065 nghttp2_session *session;
8066 nghttp2_session_callbacks callbacks;
8067 nghttp2_stream *a, *b, *c, *d, *e, *root;
8069 memset(&callbacks, 0, sizeof(callbacks));
8071 /* Remove left most stream */
8072 nghttp2_session_server_new(&session, &callbacks, NULL);
8074 root = &session->root;
8076 a = open_stream(session, 1);
8077 b = open_stream_with_dep(session, 3, a);
8078 c = open_stream_with_dep(session, 5, a);
8079 d = open_stream_with_dep(session, 7, c);
8088 nghttp2_stream_dep_remove_subtree(c);
8096 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == a->sum_dep_weight);
8097 CU_ASSERT(0 == b->sum_dep_weight);
8098 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == c->sum_dep_weight);
8099 CU_ASSERT(0 == d->sum_dep_weight);
8101 check_stream_dep_sib(a, root, b, NULL, NULL);
8102 check_stream_dep_sib(b, a, NULL, NULL, NULL);
8103 check_stream_dep_sib(c, NULL, d, NULL, NULL);
8104 check_stream_dep_sib(d, c, NULL, NULL, NULL);
8106 nghttp2_session_del(session);
8108 /* Remove right most stream */
8109 nghttp2_session_server_new(&session, &callbacks, NULL);
8111 root = &session->root;
8113 a = open_stream(session, 1);
8114 b = open_stream_with_dep(session, 3, a);
8115 c = open_stream_with_dep(session, 5, a);
8116 d = open_stream_with_dep(session, 7, c);
8125 nghttp2_stream_dep_remove_subtree(b);
8135 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == a->sum_dep_weight);
8136 CU_ASSERT(0 == b->sum_dep_weight);
8137 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == c->sum_dep_weight);
8138 CU_ASSERT(0 == d->sum_dep_weight);
8140 check_stream_dep_sib(a, root, c, NULL, NULL);
8141 check_stream_dep_sib(c, a, d, NULL, NULL);
8142 check_stream_dep_sib(d, c, NULL, NULL, NULL);
8143 check_stream_dep_sib(b, NULL, NULL, NULL, NULL);
8145 nghttp2_session_del(session);
8147 /* Remove middle stream */
8148 nghttp2_session_server_new(&session, &callbacks, NULL);
8150 root = &session->root;
8152 a = open_stream(session, 1);
8153 e = open_stream_with_dep(session, 9, a);
8154 c = open_stream_with_dep(session, 5, a);
8155 b = open_stream_with_dep(session, 3, a);
8156 d = open_stream_with_dep(session, 7, c);
8165 nghttp2_stream_dep_remove_subtree(c);
8173 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 2 == a->sum_dep_weight);
8174 CU_ASSERT(0 == b->sum_dep_weight);
8175 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == c->sum_dep_weight);
8176 CU_ASSERT(0 == d->sum_dep_weight);
8177 CU_ASSERT(0 == e->sum_dep_weight);
8179 check_stream_dep_sib(a, root, b, NULL, NULL);
8180 check_stream_dep_sib(b, a, NULL, NULL, e);
8181 check_stream_dep_sib(e, a, NULL, b, NULL);
8182 check_stream_dep_sib(c, NULL, d, NULL, NULL);
8183 check_stream_dep_sib(d, c, NULL, NULL, NULL);
8185 nghttp2_session_del(session);
8188 void test_nghttp2_session_stream_dep_all_your_stream_are_belong_to_us(void) {
8189 nghttp2_session *session;
8190 nghttp2_session_callbacks callbacks;
8191 nghttp2_stream *a, *b, *c, *d, *root;
8192 nghttp2_outbound_item *db, *dc;
8195 mem = nghttp2_mem_default();
8197 memset(&callbacks, 0, sizeof(callbacks));
8199 nghttp2_session_server_new(&session, &callbacks, NULL);
8201 root = &session->root;
8203 a = open_stream(session, 1);
8204 b = open_stream_with_dep(session, 3, a);
8206 c = open_stream(session, 5);
8213 nghttp2_stream_dep_remove_subtree(c);
8214 CU_ASSERT(0 == nghttp2_stream_dep_insert_subtree(&session->root, c));
8224 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == c->sum_dep_weight);
8225 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == a->sum_dep_weight);
8226 CU_ASSERT(0 == b->sum_dep_weight);
8228 CU_ASSERT(nghttp2_pq_empty(&a->obq));
8229 CU_ASSERT(nghttp2_pq_empty(&b->obq));
8230 CU_ASSERT(nghttp2_pq_empty(&c->obq));
8232 check_stream_dep_sib(c, root, a, NULL, NULL);
8233 check_stream_dep_sib(a, c, b, NULL, NULL);
8234 check_stream_dep_sib(b, a, NULL, NULL, NULL);
8236 nghttp2_session_del(session);
8238 nghttp2_session_server_new(&session, &callbacks, NULL);
8240 root = &session->root;
8242 a = open_stream(session, 1);
8243 b = open_stream(session, 3);
8244 c = open_stream(session, 5);
8250 nghttp2_stream_dep_remove_subtree(c);
8251 CU_ASSERT(0 == nghttp2_stream_dep_insert_subtree(&session->root, c));
8259 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 2 == c->sum_dep_weight);
8260 CU_ASSERT(0 == b->sum_dep_weight);
8261 CU_ASSERT(0 == a->sum_dep_weight);
8263 CU_ASSERT(nghttp2_pq_empty(&a->obq));
8264 CU_ASSERT(nghttp2_pq_empty(&b->obq));
8265 CU_ASSERT(nghttp2_pq_empty(&c->obq));
8267 check_stream_dep_sib(c, root, b, NULL, NULL);
8268 check_stream_dep_sib(b, c, NULL, NULL, a);
8269 check_stream_dep_sib(a, c, NULL, b, NULL);
8271 nghttp2_session_del(session);
8273 nghttp2_session_server_new(&session, &callbacks, NULL);
8275 root = &session->root;
8277 a = open_stream(session, 1);
8278 b = open_stream_with_dep(session, 3, a);
8280 c = open_stream(session, 5);
8281 d = open_stream_with_dep(session, 7, c);
8288 nghttp2_stream_dep_remove_subtree(c);
8289 CU_ASSERT(0 == nghttp2_stream_dep_insert_subtree(&session->root, c));
8299 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 2 == c->sum_dep_weight);
8300 CU_ASSERT(0 == d->sum_dep_weight);
8301 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == a->sum_dep_weight);
8302 CU_ASSERT(0 == b->sum_dep_weight);
8304 CU_ASSERT(nghttp2_pq_empty(&a->obq));
8305 CU_ASSERT(nghttp2_pq_empty(&b->obq));
8306 CU_ASSERT(nghttp2_pq_empty(&c->obq));
8307 CU_ASSERT(nghttp2_pq_empty(&d->obq));
8309 check_stream_dep_sib(c, root, d, NULL, NULL);
8310 check_stream_dep_sib(d, c, NULL, NULL, a);
8311 check_stream_dep_sib(a, c, b, d, NULL);
8312 check_stream_dep_sib(b, a, NULL, NULL, NULL);
8314 nghttp2_session_del(session);
8316 nghttp2_session_server_new(&session, &callbacks, NULL);
8318 root = &session->root;
8320 a = open_stream(session, 1);
8321 b = open_stream_with_dep(session, 3, a);
8323 c = open_stream(session, 5);
8324 d = open_stream_with_dep(session, 7, c);
8331 db = create_data_ob_item(mem);
8333 nghttp2_stream_attach_item(b, db);
8335 nghttp2_stream_dep_remove_subtree(c);
8336 CU_ASSERT(0 == nghttp2_stream_dep_insert_subtree(&session->root, c));
8346 CU_ASSERT(c->queued);
8347 CU_ASSERT(a->queued);
8348 CU_ASSERT(b->queued);
8349 CU_ASSERT(!d->queued);
8351 CU_ASSERT(1 == nghttp2_pq_size(&a->obq));
8352 CU_ASSERT(1 == nghttp2_pq_size(&c->obq));
8353 CU_ASSERT(nghttp2_pq_empty(&d->obq));
8355 check_stream_dep_sib(c, root, d, NULL, NULL);
8356 check_stream_dep_sib(d, c, NULL, NULL, a);
8357 check_stream_dep_sib(a, c, b, d, NULL);
8358 check_stream_dep_sib(b, a, NULL, NULL, NULL);
8360 nghttp2_session_del(session);
8362 nghttp2_session_server_new(&session, &callbacks, NULL);
8364 root = &session->root;
8366 a = open_stream(session, 1);
8367 b = open_stream_with_dep(session, 3, a);
8369 c = open_stream(session, 5);
8370 d = open_stream_with_dep(session, 7, c);
8377 db = create_data_ob_item(mem);
8378 dc = create_data_ob_item(mem);
8380 nghttp2_stream_attach_item(b, db);
8381 nghttp2_stream_attach_item(c, dc);
8383 nghttp2_stream_dep_remove_subtree(c);
8384 CU_ASSERT(0 == nghttp2_stream_dep_insert_subtree(&session->root, c));
8394 CU_ASSERT(c->queued);
8395 CU_ASSERT(a->queued);
8396 CU_ASSERT(b->queued);
8397 CU_ASSERT(!d->queued);
8399 check_stream_dep_sib(c, root, d, NULL, NULL);
8400 check_stream_dep_sib(d, c, NULL, NULL, a);
8401 check_stream_dep_sib(a, c, b, d, NULL);
8402 check_stream_dep_sib(b, a, NULL, NULL, NULL);
8404 nghttp2_session_del(session);
8407 void test_nghttp2_session_stream_attach_item(void) {
8408 nghttp2_session *session;
8409 nghttp2_session_callbacks callbacks;
8410 nghttp2_stream *a, *b, *c, *d, *e;
8411 nghttp2_outbound_item *da, *db, *dc, *dd;
8414 mem = nghttp2_mem_default();
8416 memset(&callbacks, 0, sizeof(callbacks));
8418 nghttp2_session_server_new(&session, &callbacks, NULL);
8420 a = open_stream(session, 1);
8421 b = open_stream_with_dep(session, 3, a);
8422 c = open_stream_with_dep(session, 5, a);
8423 d = open_stream_with_dep(session, 7, c);
8432 db = create_data_ob_item(mem);
8434 nghttp2_stream_attach_item(b, db);
8436 CU_ASSERT(a->queued);
8437 CU_ASSERT(b->queued);
8438 CU_ASSERT(!c->queued);
8439 CU_ASSERT(!d->queued);
8441 CU_ASSERT(1 == nghttp2_pq_size(&a->obq));
8443 /* Attach item to c */
8444 dc = create_data_ob_item(mem);
8446 nghttp2_stream_attach_item(c, dc);
8448 CU_ASSERT(a->queued);
8449 CU_ASSERT(b->queued);
8450 CU_ASSERT(c->queued);
8451 CU_ASSERT(!d->queued);
8453 CU_ASSERT(2 == nghttp2_pq_size(&a->obq));
8455 /* Attach item to a */
8456 da = create_data_ob_item(mem);
8458 nghttp2_stream_attach_item(a, da);
8460 CU_ASSERT(a->queued);
8461 CU_ASSERT(b->queued);
8462 CU_ASSERT(c->queued);
8463 CU_ASSERT(!d->queued);
8465 CU_ASSERT(2 == nghttp2_pq_size(&a->obq));
8467 /* Detach item from a */
8468 nghttp2_stream_detach_item(a);
8470 CU_ASSERT(a->queued);
8471 CU_ASSERT(b->queued);
8472 CU_ASSERT(c->queued);
8473 CU_ASSERT(!d->queued);
8475 CU_ASSERT(2 == nghttp2_pq_size(&a->obq));
8477 /* Attach item to d */
8478 dd = create_data_ob_item(mem);
8480 nghttp2_stream_attach_item(d, dd);
8482 CU_ASSERT(a->queued);
8483 CU_ASSERT(b->queued);
8484 CU_ASSERT(c->queued);
8485 CU_ASSERT(d->queued);
8487 CU_ASSERT(2 == nghttp2_pq_size(&a->obq));
8488 CU_ASSERT(1 == nghttp2_pq_size(&c->obq));
8490 /* Detach item from c */
8491 nghttp2_stream_detach_item(c);
8493 CU_ASSERT(a->queued);
8494 CU_ASSERT(b->queued);
8495 CU_ASSERT(c->queued);
8496 CU_ASSERT(d->queued);
8498 CU_ASSERT(2 == nghttp2_pq_size(&a->obq));
8499 CU_ASSERT(1 == nghttp2_pq_size(&c->obq));
8501 /* Detach item from b */
8502 nghttp2_stream_detach_item(b);
8504 CU_ASSERT(a->queued);
8505 CU_ASSERT(!b->queued);
8506 CU_ASSERT(c->queued);
8507 CU_ASSERT(d->queued);
8509 CU_ASSERT(1 == nghttp2_pq_size(&a->obq));
8511 /* exercises insertion */
8512 e = open_stream_with_dep_excl(session, 9, a);
8523 CU_ASSERT(a->queued);
8524 CU_ASSERT(e->queued);
8525 CU_ASSERT(!b->queued);
8526 CU_ASSERT(c->queued);
8527 CU_ASSERT(d->queued);
8529 CU_ASSERT(1 == nghttp2_pq_size(&a->obq));
8530 CU_ASSERT(1 == nghttp2_pq_size(&e->obq));
8531 CU_ASSERT(nghttp2_pq_empty(&b->obq));
8532 CU_ASSERT(1 == nghttp2_pq_size(&c->obq));
8533 CU_ASSERT(nghttp2_pq_empty(&d->obq));
8535 /* exercises deletion */
8536 nghttp2_stream_dep_remove(e);
8545 CU_ASSERT(a->queued);
8546 CU_ASSERT(!b->queued);
8547 CU_ASSERT(c->queued);
8548 CU_ASSERT(d->queued);
8550 CU_ASSERT(1 == nghttp2_pq_size(&a->obq));
8551 CU_ASSERT(nghttp2_pq_empty(&b->obq));
8552 CU_ASSERT(1 == nghttp2_pq_size(&c->obq));
8553 CU_ASSERT(nghttp2_pq_empty(&d->obq));
8555 /* e's weight 16 is distributed equally among c and b, both now have
8557 CU_ASSERT(8 == b->weight);
8558 CU_ASSERT(8 == c->weight);
8560 /* da, db, dc have been detached */
8561 nghttp2_outbound_item_free(da, mem);
8562 nghttp2_outbound_item_free(db, mem);
8563 nghttp2_outbound_item_free(dc, mem);
8568 nghttp2_session_del(session);
8570 nghttp2_session_server_new(&session, &callbacks, NULL);
8572 a = open_stream(session, 1);
8573 b = open_stream_with_dep(session, 3, a);
8574 c = open_stream_with_dep(session, 5, a);
8575 d = open_stream_with_dep(session, 7, c);
8584 da = create_data_ob_item(mem);
8585 db = create_data_ob_item(mem);
8586 dc = create_data_ob_item(mem);
8588 nghttp2_stream_attach_item(a, da);
8589 nghttp2_stream_attach_item(b, db);
8590 nghttp2_stream_attach_item(c, dc);
8592 CU_ASSERT(a->queued);
8593 CU_ASSERT(b->queued);
8594 CU_ASSERT(c->queued);
8595 CU_ASSERT(!d->queued);
8597 CU_ASSERT(2 == nghttp2_pq_size(&a->obq));
8598 CU_ASSERT(nghttp2_pq_empty(&b->obq));
8599 CU_ASSERT(nghttp2_pq_empty(&c->obq));
8600 CU_ASSERT(nghttp2_pq_empty(&d->obq));
8602 /* Detach item from a */
8603 nghttp2_stream_detach_item(a);
8605 CU_ASSERT(a->queued);
8606 CU_ASSERT(b->queued);
8607 CU_ASSERT(c->queued);
8608 CU_ASSERT(!d->queued);
8610 CU_ASSERT(2 == nghttp2_pq_size(&a->obq));
8611 CU_ASSERT(nghttp2_pq_empty(&b->obq));
8612 CU_ASSERT(nghttp2_pq_empty(&c->obq));
8613 CU_ASSERT(nghttp2_pq_empty(&d->obq));
8615 /* da has been detached */
8616 nghttp2_outbound_item_free(da, mem);
8619 nghttp2_session_del(session);
8622 void test_nghttp2_session_stream_attach_item_subtree(void) {
8623 nghttp2_session *session;
8624 nghttp2_session_callbacks callbacks;
8625 nghttp2_stream *a, *b, *c, *d, *e, *f;
8626 nghttp2_outbound_item *da, *db, *dd, *de;
8629 mem = nghttp2_mem_default();
8631 memset(&callbacks, 0, sizeof(callbacks));
8633 nghttp2_session_server_new(&session, &callbacks, NULL);
8635 a = open_stream(session, 1);
8636 b = open_stream_with_dep(session, 3, a);
8637 c = open_stream_with_dep(session, 5, a);
8638 d = open_stream_with_dep(session, 7, c);
8640 e = open_stream_with_dep_weight(session, 9, 32, &session->root);
8641 f = open_stream_with_dep(session, 11, e);
8651 de = create_data_ob_item(mem);
8653 nghttp2_stream_attach_item(e, de);
8655 db = create_data_ob_item(mem);
8657 nghttp2_stream_attach_item(b, db);
8659 CU_ASSERT(a->queued);
8660 CU_ASSERT(b->queued);
8661 CU_ASSERT(!c->queued);
8662 CU_ASSERT(!d->queued);
8663 CU_ASSERT(e->queued);
8664 CU_ASSERT(!f->queued);
8666 CU_ASSERT(1 == nghttp2_pq_size(&a->obq));
8667 CU_ASSERT(nghttp2_pq_empty(&b->obq));
8668 CU_ASSERT(nghttp2_pq_empty(&c->obq));
8669 CU_ASSERT(nghttp2_pq_empty(&d->obq));
8670 CU_ASSERT(nghttp2_pq_empty(&e->obq));
8671 CU_ASSERT(nghttp2_pq_empty(&f->obq));
8673 /* Insert subtree e under a */
8675 nghttp2_stream_dep_remove_subtree(e);
8676 nghttp2_stream_dep_insert_subtree(a, e);
8688 CU_ASSERT(a->queued);
8689 CU_ASSERT(b->queued);
8690 CU_ASSERT(!c->queued);
8691 CU_ASSERT(!d->queued);
8692 CU_ASSERT(e->queued);
8693 CU_ASSERT(!f->queued);
8695 CU_ASSERT(1 == nghttp2_pq_size(&a->obq));
8696 CU_ASSERT(nghttp2_pq_empty(&b->obq));
8697 CU_ASSERT(nghttp2_pq_empty(&c->obq));
8698 CU_ASSERT(nghttp2_pq_empty(&d->obq));
8699 CU_ASSERT(1 == nghttp2_pq_size(&e->obq));
8700 CU_ASSERT(nghttp2_pq_empty(&f->obq));
8702 /* Remove subtree b */
8704 nghttp2_stream_dep_remove_subtree(b);
8706 CU_ASSERT(0 == nghttp2_stream_dep_add_subtree(&session->root, b));
8718 CU_ASSERT(a->queued);
8719 CU_ASSERT(b->queued);
8720 CU_ASSERT(!c->queued);
8721 CU_ASSERT(!d->queued);
8722 CU_ASSERT(e->queued);
8723 CU_ASSERT(!f->queued);
8725 CU_ASSERT(1 == nghttp2_pq_size(&a->obq));
8726 CU_ASSERT(nghttp2_pq_empty(&b->obq));
8727 CU_ASSERT(nghttp2_pq_empty(&c->obq));
8728 CU_ASSERT(nghttp2_pq_empty(&d->obq));
8729 CU_ASSERT(nghttp2_pq_empty(&e->obq));
8730 CU_ASSERT(nghttp2_pq_empty(&f->obq));
8732 /* Remove subtree a, and add it to root again */
8734 nghttp2_stream_dep_remove_subtree(a);
8736 CU_ASSERT(0 == nghttp2_stream_dep_add_subtree(&session->root, a));
8738 CU_ASSERT(a->queued);
8739 CU_ASSERT(b->queued);
8740 CU_ASSERT(!c->queued);
8741 CU_ASSERT(!d->queued);
8742 CU_ASSERT(e->queued);
8743 CU_ASSERT(!f->queued);
8745 CU_ASSERT(1 == nghttp2_pq_size(&a->obq));
8746 CU_ASSERT(nghttp2_pq_empty(&b->obq));
8747 CU_ASSERT(nghttp2_pq_empty(&c->obq));
8748 CU_ASSERT(nghttp2_pq_empty(&d->obq));
8749 CU_ASSERT(nghttp2_pq_empty(&e->obq));
8750 CU_ASSERT(nghttp2_pq_empty(&f->obq));
8752 /* Remove subtree c */
8754 nghttp2_stream_dep_remove_subtree(c);
8756 CU_ASSERT(0 == nghttp2_stream_dep_add_subtree(&session->root, c));
8766 CU_ASSERT(a->queued);
8767 CU_ASSERT(b->queued);
8768 CU_ASSERT(!c->queued);
8769 CU_ASSERT(!d->queued);
8770 CU_ASSERT(e->queued);
8771 CU_ASSERT(!f->queued);
8773 CU_ASSERT(1 == nghttp2_pq_size(&a->obq));
8774 CU_ASSERT(nghttp2_pq_empty(&b->obq));
8775 CU_ASSERT(nghttp2_pq_empty(&c->obq));
8776 CU_ASSERT(nghttp2_pq_empty(&d->obq));
8777 CU_ASSERT(nghttp2_pq_empty(&e->obq));
8778 CU_ASSERT(nghttp2_pq_empty(&f->obq));
8780 dd = create_data_ob_item(mem);
8782 nghttp2_stream_attach_item(d, dd);
8784 /* Add subtree c to a */
8786 nghttp2_stream_dep_remove_subtree(c);
8787 nghttp2_stream_dep_add_subtree(a, c);
8797 CU_ASSERT(a->queued);
8798 CU_ASSERT(b->queued);
8799 CU_ASSERT(c->queued);
8800 CU_ASSERT(d->queued);
8801 CU_ASSERT(e->queued);
8802 CU_ASSERT(!f->queued);
8804 CU_ASSERT(2 == nghttp2_pq_size(&a->obq));
8805 CU_ASSERT(nghttp2_pq_empty(&b->obq));
8806 CU_ASSERT(1 == nghttp2_pq_size(&c->obq));
8807 CU_ASSERT(nghttp2_pq_empty(&d->obq));
8808 CU_ASSERT(nghttp2_pq_empty(&e->obq));
8809 CU_ASSERT(nghttp2_pq_empty(&f->obq));
8811 /* Insert b under a */
8813 nghttp2_stream_dep_remove_subtree(b);
8814 nghttp2_stream_dep_insert_subtree(a, b);
8826 CU_ASSERT(a->queued);
8827 CU_ASSERT(b->queued);
8828 CU_ASSERT(c->queued);
8829 CU_ASSERT(d->queued);
8830 CU_ASSERT(e->queued);
8831 CU_ASSERT(!f->queued);
8833 CU_ASSERT(1 == nghttp2_pq_size(&a->obq));
8834 CU_ASSERT(2 == nghttp2_pq_size(&b->obq));
8835 CU_ASSERT(1 == nghttp2_pq_size(&c->obq));
8836 CU_ASSERT(nghttp2_pq_empty(&d->obq));
8837 CU_ASSERT(nghttp2_pq_empty(&e->obq));
8838 CU_ASSERT(nghttp2_pq_empty(&f->obq));
8840 /* Remove subtree b */
8842 nghttp2_stream_dep_remove_subtree(b);
8843 CU_ASSERT(0 == nghttp2_stream_dep_add_subtree(&session->root, b));
8853 CU_ASSERT(!a->queued);
8854 CU_ASSERT(b->queued);
8855 CU_ASSERT(c->queued);
8856 CU_ASSERT(d->queued);
8857 CU_ASSERT(e->queued);
8858 CU_ASSERT(!f->queued);
8860 CU_ASSERT(nghttp2_pq_empty(&a->obq));
8861 CU_ASSERT(2 == nghttp2_pq_size(&b->obq));
8862 CU_ASSERT(1 == nghttp2_pq_size(&c->obq));
8863 CU_ASSERT(nghttp2_pq_empty(&d->obq));
8864 CU_ASSERT(nghttp2_pq_empty(&e->obq));
8865 CU_ASSERT(nghttp2_pq_empty(&f->obq));
8867 /* Remove subtree c, and detach item from b, and then re-add
8868 subtree c under b */
8870 nghttp2_stream_dep_remove_subtree(c);
8871 nghttp2_stream_detach_item(b);
8872 nghttp2_stream_dep_add_subtree(b, c);
8882 CU_ASSERT(!a->queued);
8883 CU_ASSERT(b->queued);
8884 CU_ASSERT(c->queued);
8885 CU_ASSERT(d->queued);
8886 CU_ASSERT(e->queued);
8887 CU_ASSERT(!f->queued);
8889 CU_ASSERT(nghttp2_pq_empty(&a->obq));
8890 CU_ASSERT(2 == nghttp2_pq_size(&b->obq));
8891 CU_ASSERT(1 == nghttp2_pq_size(&c->obq));
8892 CU_ASSERT(nghttp2_pq_empty(&d->obq));
8893 CU_ASSERT(nghttp2_pq_empty(&e->obq));
8894 CU_ASSERT(nghttp2_pq_empty(&f->obq));
8896 /* Attach data to a, and add subtree a under b */
8898 da = create_data_ob_item(mem);
8899 nghttp2_stream_attach_item(a, da);
8900 nghttp2_stream_dep_remove_subtree(a);
8901 nghttp2_stream_dep_add_subtree(b, a);
8911 CU_ASSERT(a->queued);
8912 CU_ASSERT(b->queued);
8913 CU_ASSERT(c->queued);
8914 CU_ASSERT(d->queued);
8915 CU_ASSERT(e->queued);
8916 CU_ASSERT(!f->queued);
8918 CU_ASSERT(nghttp2_pq_empty(&a->obq));
8919 CU_ASSERT(3 == nghttp2_pq_size(&b->obq));
8920 CU_ASSERT(1 == nghttp2_pq_size(&c->obq));
8921 CU_ASSERT(nghttp2_pq_empty(&d->obq));
8922 CU_ASSERT(nghttp2_pq_empty(&e->obq));
8923 CU_ASSERT(nghttp2_pq_empty(&f->obq));
8925 /* Remove subtree c, and add under f */
8926 nghttp2_stream_dep_remove_subtree(c);
8927 nghttp2_stream_dep_insert_subtree(f, c);
8941 CU_ASSERT(a->queued);
8942 CU_ASSERT(b->queued);
8943 CU_ASSERT(c->queued);
8944 CU_ASSERT(d->queued);
8945 CU_ASSERT(e->queued);
8946 CU_ASSERT(f->queued);
8948 CU_ASSERT(nghttp2_pq_empty(&a->obq));
8949 CU_ASSERT(2 == nghttp2_pq_size(&b->obq));
8950 CU_ASSERT(1 == nghttp2_pq_size(&c->obq));
8951 CU_ASSERT(nghttp2_pq_empty(&d->obq));
8952 CU_ASSERT(1 == nghttp2_pq_size(&e->obq));
8953 CU_ASSERT(1 == nghttp2_pq_size(&f->obq));
8955 /* db has been detached */
8956 nghttp2_outbound_item_free(db, mem);
8959 nghttp2_session_del(session);
8962 void test_nghttp2_session_stream_get_state(void) {
8963 nghttp2_session *session;
8964 nghttp2_session_callbacks callbacks;
8966 nghttp2_hd_deflater deflater;
8969 nghttp2_stream *stream;
8971 nghttp2_data_provider data_prd;
8972 nghttp2_frame frame;
8974 mem = nghttp2_mem_default();
8975 frame_pack_bufs_init(&bufs);
8976 memset(&data_prd, 0, sizeof(data_prd));
8978 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
8979 callbacks.send_callback = null_send_callback;
8981 nghttp2_session_server_new(&session, &callbacks, NULL);
8982 nghttp2_hd_deflate_init(&deflater, mem);
8984 CU_ASSERT(NGHTTP2_STREAM_STATE_IDLE ==
8985 nghttp2_stream_get_state(nghttp2_session_get_root_stream(session)));
8987 /* stream 1 HEADERS; without END_STREAM flag set */
8988 pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, reqnv,
8989 ARRLEN(reqnv), mem);
8991 buf = &bufs.head->buf;
8992 rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
8994 CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv);
8996 stream = nghttp2_session_find_stream(session, 1);
8998 CU_ASSERT(NULL != stream);
8999 CU_ASSERT(1 == stream->stream_id);
9000 CU_ASSERT(NGHTTP2_STREAM_STATE_OPEN == nghttp2_stream_get_state(stream));
9002 nghttp2_bufs_reset(&bufs);
9004 /* stream 3 HEADERS; with END_STREAM flag set */
9005 pack_headers(&bufs, &deflater, 3,
9006 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM, reqnv,
9007 ARRLEN(reqnv), mem);
9009 buf = &bufs.head->buf;
9010 rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
9012 CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv);
9014 stream = nghttp2_session_find_stream(session, 3);
9016 CU_ASSERT(NULL != stream);
9017 CU_ASSERT(3 == stream->stream_id);
9018 CU_ASSERT(NGHTTP2_STREAM_STATE_HALF_CLOSED_REMOTE ==
9019 nghttp2_stream_get_state(stream));
9021 nghttp2_bufs_reset(&bufs);
9023 /* Respond to stream 1 */
9024 nghttp2_submit_response(session, 1, resnv, ARRLEN(resnv), NULL);
9026 rv = nghttp2_session_send(session);
9030 stream = nghttp2_session_find_stream(session, 1);
9032 CU_ASSERT(NGHTTP2_STREAM_STATE_HALF_CLOSED_LOCAL ==
9033 nghttp2_stream_get_state(stream));
9035 /* Respond to stream 3 */
9036 nghttp2_submit_response(session, 3, resnv, ARRLEN(resnv), NULL);
9038 rv = nghttp2_session_send(session);
9042 stream = nghttp2_session_find_stream(session, 3);
9044 CU_ASSERT(NGHTTP2_STREAM_STATE_CLOSED == nghttp2_stream_get_state(stream));
9046 /* stream 5 HEADERS; with END_STREAM flag set */
9047 pack_headers(&bufs, &deflater, 5,
9048 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM, reqnv,
9049 ARRLEN(reqnv), mem);
9051 buf = &bufs.head->buf;
9052 rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
9054 CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv);
9056 nghttp2_bufs_reset(&bufs);
9058 /* Push stream 2 associated to stream 5 */
9059 rv = nghttp2_submit_push_promise(session, NGHTTP2_FLAG_NONE, 5, reqnv,
9060 ARRLEN(reqnv), NULL);
9064 rv = nghttp2_session_send(session);
9068 stream = nghttp2_session_find_stream(session, 2);
9070 CU_ASSERT(NGHTTP2_STREAM_STATE_RESERVED_LOCAL ==
9071 nghttp2_stream_get_state(stream));
9073 /* Send resposne to push stream 2 with END_STREAM set */
9074 nghttp2_submit_response(session, 2, resnv, ARRLEN(resnv), NULL);
9076 rv = nghttp2_session_send(session);
9080 stream = nghttp2_session_find_stream(session, 2);
9082 /* At server, pushed stream object is not retained after closed */
9083 CU_ASSERT(NULL == stream);
9085 /* Push stream 4 associated to stream 5 */
9086 rv = nghttp2_submit_push_promise(session, NGHTTP2_FLAG_NONE, 5, reqnv,
9087 ARRLEN(reqnv), NULL);
9091 rv = nghttp2_session_send(session);
9095 stream = nghttp2_session_find_stream(session, 4);
9097 CU_ASSERT(NGHTTP2_STREAM_STATE_RESERVED_LOCAL ==
9098 nghttp2_stream_get_state(stream));
9100 /* Send response to push stream 4 without closing */
9101 data_prd.read_callback = defer_data_source_read_callback;
9103 nghttp2_submit_response(session, 4, resnv, ARRLEN(resnv), &data_prd);
9105 rv = nghttp2_session_send(session);
9109 stream = nghttp2_session_find_stream(session, 4);
9111 CU_ASSERT(NGHTTP2_STREAM_STATE_HALF_CLOSED_REMOTE ==
9112 nghttp2_stream_get_state(stream));
9114 /* Create idle stream by PRIORITY frame */
9115 nghttp2_frame_priority_init(&frame.priority, 7, &pri_spec_default);
9117 rv = nghttp2_frame_pack_priority(&bufs, &frame.priority);
9121 nghttp2_frame_priority_free(&frame.priority);
9123 buf = &bufs.head->buf;
9124 rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
9126 CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv);
9128 stream = nghttp2_session_find_stream(session, 7);
9130 CU_ASSERT(NGHTTP2_STREAM_STATE_IDLE == nghttp2_stream_get_state(stream));
9132 nghttp2_bufs_reset(&bufs);
9134 nghttp2_hd_deflate_free(&deflater);
9135 nghttp2_session_del(session);
9137 /* Test for client side */
9139 nghttp2_session_client_new(&session, &callbacks, NULL);
9140 nghttp2_hd_deflate_init(&deflater, mem);
9142 nghttp2_submit_request(session, NULL, reqnv, ARRLEN(reqnv), NULL, NULL);
9144 rv = nghttp2_session_send(session);
9148 /* Receive PUSH_PROMISE 2 associated to stream 1 */
9149 pack_push_promise(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, 2, reqnv,
9150 ARRLEN(reqnv), mem);
9152 buf = &bufs.head->buf;
9153 rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
9155 CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv);
9157 stream = nghttp2_session_find_stream(session, 2);
9159 CU_ASSERT(NGHTTP2_STREAM_STATE_RESERVED_REMOTE ==
9160 nghttp2_stream_get_state(stream));
9162 nghttp2_bufs_reset(&bufs);
9164 /* Receive push response for stream 2 without END_STREAM set */
9165 pack_headers(&bufs, &deflater, 2, NGHTTP2_FLAG_END_HEADERS, resnv,
9166 ARRLEN(resnv), mem);
9168 buf = &bufs.head->buf;
9169 rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
9171 CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv);
9173 stream = nghttp2_session_find_stream(session, 2);
9175 CU_ASSERT(NGHTTP2_STREAM_STATE_HALF_CLOSED_LOCAL ==
9176 nghttp2_stream_get_state(stream));
9178 nghttp2_bufs_reset(&bufs);
9180 nghttp2_hd_deflate_free(&deflater);
9181 nghttp2_session_del(session);
9183 nghttp2_bufs_free(&bufs);
9186 void test_nghttp2_session_stream_get_something(void) {
9187 nghttp2_session *session;
9188 nghttp2_session_callbacks callbacks;
9189 nghttp2_stream *a, *b, *c;
9191 memset(&callbacks, 0, sizeof(callbacks));
9193 nghttp2_session_server_new(&session, &callbacks, NULL);
9195 a = open_stream(session, 1);
9197 CU_ASSERT(nghttp2_session_get_root_stream(session) ==
9198 nghttp2_stream_get_parent(a));
9199 CU_ASSERT(NULL == nghttp2_stream_get_previous_sibling(a));
9200 CU_ASSERT(NULL == nghttp2_stream_get_next_sibling(a));
9201 CU_ASSERT(NULL == nghttp2_stream_get_first_child(a));
9203 b = open_stream_with_dep(session, 3, a);
9204 c = open_stream_with_dep_weight(session, 5, 11, a);
9206 CU_ASSERT(a == nghttp2_stream_get_parent(c));
9207 CU_ASSERT(a == nghttp2_stream_get_parent(b));
9209 CU_ASSERT(c == nghttp2_stream_get_first_child(a));
9211 CU_ASSERT(b == nghttp2_stream_get_next_sibling(c));
9212 CU_ASSERT(c == nghttp2_stream_get_previous_sibling(b));
9214 CU_ASSERT(27 == nghttp2_stream_get_sum_dependency_weight(a));
9216 CU_ASSERT(11 == nghttp2_stream_get_weight(c));
9217 CU_ASSERT(5 == nghttp2_stream_get_stream_id(c));
9218 CU_ASSERT(0 == nghttp2_stream_get_stream_id(&session->root));
9220 nghttp2_session_del(session);
9223 void test_nghttp2_session_find_stream(void) {
9224 nghttp2_session *session;
9225 nghttp2_session_callbacks callbacks;
9226 nghttp2_stream *stream;
9228 memset(&callbacks, 0, sizeof(callbacks));
9230 nghttp2_session_server_new(&session, &callbacks, NULL);
9232 open_recv_stream(session, 1);
9234 stream = nghttp2_session_find_stream(session, 1);
9236 CU_ASSERT(NULL != stream);
9237 CU_ASSERT(1 == stream->stream_id);
9239 stream = nghttp2_session_find_stream(session, 0);
9241 CU_ASSERT(&session->root == stream);
9242 CU_ASSERT(0 == stream->stream_id);
9244 stream = nghttp2_session_find_stream(session, 2);
9246 CU_ASSERT(NULL == stream);
9248 nghttp2_session_del(session);
9251 void test_nghttp2_session_keep_closed_stream(void) {
9252 nghttp2_session *session;
9253 nghttp2_session_callbacks callbacks;
9254 const size_t max_concurrent_streams = 5;
9255 nghttp2_settings_entry iv = {NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS,
9256 (uint32_t)max_concurrent_streams};
9259 memset(&callbacks, 0, sizeof(callbacks));
9260 callbacks.send_callback = null_send_callback;
9262 nghttp2_session_server_new(&session, &callbacks, NULL);
9264 nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, &iv, 1);
9266 for (i = 0; i < max_concurrent_streams; ++i) {
9267 open_recv_stream(session, (int32_t)i * 2 + 1);
9270 CU_ASSERT(0 == session->num_closed_streams);
9272 nghttp2_session_close_stream(session, 1, NGHTTP2_NO_ERROR);
9274 CU_ASSERT(1 == session->num_closed_streams);
9275 CU_ASSERT(1 == session->closed_stream_tail->stream_id);
9276 CU_ASSERT(session->closed_stream_tail == session->closed_stream_head);
9278 nghttp2_session_close_stream(session, 5, NGHTTP2_NO_ERROR);
9280 CU_ASSERT(2 == session->num_closed_streams);
9281 CU_ASSERT(5 == session->closed_stream_tail->stream_id);
9282 CU_ASSERT(1 == session->closed_stream_head->stream_id);
9283 CU_ASSERT(session->closed_stream_head ==
9284 session->closed_stream_tail->closed_prev);
9285 CU_ASSERT(NULL == session->closed_stream_tail->closed_next);
9286 CU_ASSERT(session->closed_stream_tail ==
9287 session->closed_stream_head->closed_next);
9288 CU_ASSERT(NULL == session->closed_stream_head->closed_prev);
9290 open_recv_stream(session, 11);
9291 nghttp2_session_adjust_closed_stream(session);
9293 CU_ASSERT(1 == session->num_closed_streams);
9294 CU_ASSERT(5 == session->closed_stream_tail->stream_id);
9295 CU_ASSERT(session->closed_stream_tail == session->closed_stream_head);
9296 CU_ASSERT(NULL == session->closed_stream_head->closed_prev);
9297 CU_ASSERT(NULL == session->closed_stream_head->closed_next);
9299 open_recv_stream(session, 13);
9300 nghttp2_session_adjust_closed_stream(session);
9302 CU_ASSERT(0 == session->num_closed_streams);
9303 CU_ASSERT(NULL == session->closed_stream_tail);
9304 CU_ASSERT(NULL == session->closed_stream_head);
9306 nghttp2_session_close_stream(session, 3, NGHTTP2_NO_ERROR);
9308 CU_ASSERT(1 == session->num_closed_streams);
9309 CU_ASSERT(3 == session->closed_stream_head->stream_id);
9311 /* server initiated stream is not counted to max concurrent limit */
9312 open_sent_stream(session, 2);
9313 nghttp2_session_adjust_closed_stream(session);
9315 CU_ASSERT(1 == session->num_closed_streams);
9316 CU_ASSERT(3 == session->closed_stream_head->stream_id);
9318 nghttp2_session_close_stream(session, 2, NGHTTP2_NO_ERROR);
9320 CU_ASSERT(1 == session->num_closed_streams);
9321 CU_ASSERT(3 == session->closed_stream_head->stream_id);
9323 nghttp2_session_del(session);
9326 void test_nghttp2_session_keep_idle_stream(void) {
9327 nghttp2_session *session;
9328 nghttp2_session_callbacks callbacks;
9329 const size_t max_concurrent_streams = 1;
9330 nghttp2_settings_entry iv = {NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS,
9331 (uint32_t)max_concurrent_streams};
9335 memset(&callbacks, 0, sizeof(callbacks));
9336 callbacks.send_callback = null_send_callback;
9338 nghttp2_session_server_new(&session, &callbacks, NULL);
9340 nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, &iv, 1);
9342 /* We at least allow NGHTTP2_MIN_IDLE_STREAM idle streams even if
9343 max concurrent streams is very low. */
9344 for (i = 0; i < NGHTTP2_MIN_IDLE_STREAMS; ++i) {
9345 open_recv_stream2(session, i * 2 + 1, NGHTTP2_STREAM_IDLE);
9346 nghttp2_session_adjust_idle_stream(session);
9349 CU_ASSERT(NGHTTP2_MIN_IDLE_STREAMS == session->num_idle_streams);
9351 stream_id = (NGHTTP2_MIN_IDLE_STREAMS - 1) * 2 + 1;
9352 CU_ASSERT(1 == session->idle_stream_head->stream_id);
9353 CU_ASSERT(stream_id == session->idle_stream_tail->stream_id);
9357 open_recv_stream2(session, stream_id, NGHTTP2_STREAM_IDLE);
9358 nghttp2_session_adjust_idle_stream(session);
9360 CU_ASSERT(NGHTTP2_MIN_IDLE_STREAMS == session->num_idle_streams);
9361 CU_ASSERT(3 == session->idle_stream_head->stream_id);
9362 CU_ASSERT(stream_id == session->idle_stream_tail->stream_id);
9364 nghttp2_session_del(session);
9367 void test_nghttp2_session_detach_idle_stream(void) {
9368 nghttp2_session *session;
9369 nghttp2_session_callbacks callbacks;
9371 nghttp2_stream *stream;
9373 memset(&callbacks, 0, sizeof(callbacks));
9374 callbacks.send_callback = null_send_callback;
9376 nghttp2_session_server_new(&session, &callbacks, NULL);
9378 for (i = 1; i <= 3; ++i) {
9379 nghttp2_session_open_stream(session, i, NGHTTP2_STREAM_FLAG_NONE,
9380 &pri_spec_default, NGHTTP2_STREAM_IDLE, NULL);
9383 CU_ASSERT(3 == session->num_idle_streams);
9385 /* Detach middle stream */
9386 stream = nghttp2_session_get_stream_raw(session, 2);
9388 CU_ASSERT(session->idle_stream_head == stream->closed_prev);
9389 CU_ASSERT(session->idle_stream_tail == stream->closed_next);
9390 CU_ASSERT(stream == session->idle_stream_head->closed_next);
9391 CU_ASSERT(stream == session->idle_stream_tail->closed_prev);
9393 nghttp2_session_detach_idle_stream(session, stream);
9395 CU_ASSERT(2 == session->num_idle_streams);
9397 CU_ASSERT(NULL == stream->closed_prev);
9398 CU_ASSERT(NULL == stream->closed_next);
9400 CU_ASSERT(session->idle_stream_head ==
9401 session->idle_stream_tail->closed_prev);
9402 CU_ASSERT(session->idle_stream_tail ==
9403 session->idle_stream_head->closed_next);
9405 /* Detach head stream */
9406 stream = session->idle_stream_head;
9408 nghttp2_session_detach_idle_stream(session, stream);
9410 CU_ASSERT(1 == session->num_idle_streams);
9412 CU_ASSERT(session->idle_stream_head == session->idle_stream_tail);
9413 CU_ASSERT(NULL == session->idle_stream_head->closed_prev);
9414 CU_ASSERT(NULL == session->idle_stream_head->closed_next);
9416 /* Detach last stream */
9418 stream = session->idle_stream_head;
9420 nghttp2_session_detach_idle_stream(session, stream);
9422 CU_ASSERT(0 == session->num_idle_streams);
9424 CU_ASSERT(NULL == session->idle_stream_head);
9425 CU_ASSERT(NULL == session->idle_stream_tail);
9427 for (i = 4; i <= 5; ++i) {
9428 nghttp2_session_open_stream(session, i, NGHTTP2_STREAM_FLAG_NONE,
9429 &pri_spec_default, NGHTTP2_STREAM_IDLE, NULL);
9432 CU_ASSERT(2 == session->num_idle_streams);
9434 /* Detach tail stream */
9436 stream = session->idle_stream_tail;
9438 nghttp2_session_detach_idle_stream(session, stream);
9440 CU_ASSERT(1 == session->num_idle_streams);
9442 CU_ASSERT(session->idle_stream_head == session->idle_stream_tail);
9443 CU_ASSERT(NULL == session->idle_stream_head->closed_prev);
9444 CU_ASSERT(NULL == session->idle_stream_head->closed_next);
9446 nghttp2_session_del(session);
9449 void test_nghttp2_session_large_dep_tree(void) {
9450 nghttp2_session *session;
9451 nghttp2_session_callbacks callbacks;
9453 nghttp2_stream *dep_stream = NULL;
9454 nghttp2_stream *stream;
9457 memset(&callbacks, 0, sizeof(callbacks));
9458 callbacks.send_callback = null_send_callback;
9460 nghttp2_session_server_new(&session, &callbacks, NULL);
9463 for (i = 0; i < 250; ++i, stream_id += 2) {
9464 dep_stream = open_stream_with_dep(session, stream_id, dep_stream);
9468 for (i = 0; i < 250; ++i, stream_id += 2) {
9469 stream = nghttp2_session_get_stream(session, stream_id);
9470 CU_ASSERT(nghttp2_stream_dep_find_ancestor(stream, &session->root));
9471 CU_ASSERT(nghttp2_stream_in_dep_tree(stream));
9474 nghttp2_session_del(session);
9477 void test_nghttp2_session_graceful_shutdown(void) {
9478 nghttp2_session *session;
9479 nghttp2_session_callbacks callbacks;
9482 memset(&callbacks, 0, sizeof(callbacks));
9483 callbacks.send_callback = null_send_callback;
9484 callbacks.on_frame_send_callback = on_frame_send_callback;
9485 callbacks.on_stream_close_callback = on_stream_close_callback;
9487 nghttp2_session_server_new(&session, &callbacks, &ud);
9489 open_recv_stream(session, 301);
9490 open_sent_stream(session, 302);
9491 open_recv_stream(session, 309);
9492 open_recv_stream(session, 311);
9493 open_recv_stream(session, 319);
9495 CU_ASSERT(0 == nghttp2_submit_shutdown_notice(session));
9497 ud.frame_send_cb_called = 0;
9499 CU_ASSERT(0 == nghttp2_session_send(session));
9501 CU_ASSERT(1 == ud.frame_send_cb_called);
9502 CU_ASSERT((1u << 31) - 1 == session->local_last_stream_id);
9504 CU_ASSERT(0 == nghttp2_submit_goaway(session, NGHTTP2_FLAG_NONE, 311,
9505 NGHTTP2_NO_ERROR, NULL, 0));
9507 ud.frame_send_cb_called = 0;
9508 ud.stream_close_cb_called = 0;
9510 CU_ASSERT(0 == nghttp2_session_send(session));
9512 CU_ASSERT(1 == ud.frame_send_cb_called);
9513 CU_ASSERT(311 == session->local_last_stream_id);
9514 CU_ASSERT(1 == ud.stream_close_cb_called);
9517 nghttp2_session_terminate_session2(session, 301, NGHTTP2_NO_ERROR));
9519 ud.frame_send_cb_called = 0;
9520 ud.stream_close_cb_called = 0;
9522 CU_ASSERT(0 == nghttp2_session_send(session));
9524 CU_ASSERT(1 == ud.frame_send_cb_called);
9525 CU_ASSERT(301 == session->local_last_stream_id);
9526 CU_ASSERT(2 == ud.stream_close_cb_called);
9528 CU_ASSERT(NULL != nghttp2_session_get_stream(session, 301));
9529 CU_ASSERT(NULL != nghttp2_session_get_stream(session, 302));
9530 CU_ASSERT(NULL == nghttp2_session_get_stream(session, 309));
9531 CU_ASSERT(NULL == nghttp2_session_get_stream(session, 311));
9532 CU_ASSERT(NULL == nghttp2_session_get_stream(session, 319));
9534 nghttp2_session_del(session);
9537 void test_nghttp2_session_on_header_temporal_failure(void) {
9538 nghttp2_session *session;
9539 nghttp2_session_callbacks callbacks;
9543 nghttp2_hd_deflater deflater;
9544 nghttp2_nv nv[] = {MAKE_NV("alpha", "bravo"), MAKE_NV("charlie", "delta")};
9548 nghttp2_frame frame;
9549 nghttp2_frame_hd hd;
9550 nghttp2_outbound_item *item;
9553 mem = nghttp2_mem_default();
9554 memset(&callbacks, 0, sizeof(callbacks));
9555 callbacks.on_header_callback = temporal_failure_on_header_callback;
9557 nghttp2_session_server_new(&session, &callbacks, &ud);
9559 frame_pack_bufs_init(&bufs);
9561 nghttp2_hd_deflate_init(&deflater, mem);
9563 nghttp2_nv_array_copy(&nva, reqnv, ARRLEN(reqnv), mem);
9565 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_STREAM, 1,
9566 NGHTTP2_HCAT_REQUEST, NULL, nva, ARRLEN(reqnv));
9567 nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
9568 nghttp2_frame_headers_free(&frame.headers, mem);
9570 /* We are going to create CONTINUATION. First serialize header
9571 block, and then frame header. */
9572 hdpos = nghttp2_bufs_len(&bufs);
9574 buf = &bufs.head->buf;
9575 buf->last += NGHTTP2_FRAME_HDLEN;
9577 nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, &nv[1], 1);
9579 nghttp2_frame_hd_init(&hd,
9580 nghttp2_bufs_len(&bufs) - hdpos - NGHTTP2_FRAME_HDLEN,
9581 NGHTTP2_CONTINUATION, NGHTTP2_FLAG_END_HEADERS, 1);
9583 nghttp2_frame_pack_frame_hd(&buf->pos[hdpos], &hd);
9585 ud.header_cb_called = 0;
9586 rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_bufs_len(&bufs));
9588 CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == rv);
9589 CU_ASSERT(1 == ud.header_cb_called);
9591 item = nghttp2_session_get_next_ob_item(session);
9593 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
9594 CU_ASSERT(1 == item->frame.hd.stream_id);
9596 /* Make sure no header decompression error occurred */
9597 CU_ASSERT(NGHTTP2_GOAWAY_NONE == session->goaway_flags);
9599 nghttp2_hd_deflate_free(&deflater);
9600 nghttp2_session_del(session);
9602 nghttp2_bufs_reset(&bufs);
9604 /* Check for PUSH_PROMISE */
9605 nghttp2_hd_deflate_init(&deflater, mem);
9606 nghttp2_session_client_new(&session, &callbacks, &ud);
9608 open_sent_stream(session, 1);
9610 rv = pack_push_promise(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, 2,
9611 reqnv, ARRLEN(reqnv), mem);
9614 ud.header_cb_called = 0;
9615 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
9616 nghttp2_bufs_len(&bufs));
9617 CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == rv);
9618 CU_ASSERT(1 == ud.header_cb_called);
9620 item = nghttp2_session_get_next_ob_item(session);
9621 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
9622 CU_ASSERT(2 == item->frame.hd.stream_id);
9623 CU_ASSERT(NGHTTP2_INTERNAL_ERROR == item->frame.rst_stream.error_code);
9625 nghttp2_session_del(session);
9626 nghttp2_hd_deflate_free(&deflater);
9627 nghttp2_bufs_free(&bufs);
9630 void test_nghttp2_session_recv_client_magic(void) {
9631 nghttp2_session *session;
9632 nghttp2_session_callbacks callbacks;
9634 nghttp2_frame ping_frame;
9637 /* enable global nghttp2_enable_strict_preface here */
9638 nghttp2_enable_strict_preface = 1;
9640 memset(&callbacks, 0, sizeof(callbacks));
9642 /* Check success case */
9643 nghttp2_session_server_new(&session, &callbacks, NULL);
9645 rv = nghttp2_session_mem_recv(session, (const uint8_t *)NGHTTP2_CLIENT_MAGIC,
9646 NGHTTP2_CLIENT_MAGIC_LEN);
9648 CU_ASSERT(rv == NGHTTP2_CLIENT_MAGIC_LEN);
9649 CU_ASSERT(NGHTTP2_IB_READ_FIRST_SETTINGS == session->iframe.state);
9651 /* Receiving PING is error because we want SETTINGS. */
9652 nghttp2_frame_ping_init(&ping_frame.ping, NGHTTP2_FLAG_NONE, NULL);
9654 nghttp2_frame_pack_frame_hd(buf, &ping_frame.ping.hd);
9656 rv = nghttp2_session_mem_recv(session, buf, NGHTTP2_FRAME_HDLEN);
9657 CU_ASSERT(NGHTTP2_FRAME_HDLEN == rv);
9658 CU_ASSERT(NGHTTP2_IB_IGN_ALL == session->iframe.state);
9659 CU_ASSERT(0 == session->iframe.payloadleft);
9661 nghttp2_frame_ping_free(&ping_frame.ping);
9663 nghttp2_session_del(session);
9665 /* Check bad case */
9666 nghttp2_session_server_new(&session, &callbacks, NULL);
9668 /* Feed magic with one byte less */
9669 rv = nghttp2_session_mem_recv(session, (const uint8_t *)NGHTTP2_CLIENT_MAGIC,
9670 NGHTTP2_CLIENT_MAGIC_LEN - 1);
9672 CU_ASSERT(rv == NGHTTP2_CLIENT_MAGIC_LEN - 1);
9673 CU_ASSERT(NGHTTP2_IB_READ_CLIENT_MAGIC == session->iframe.state);
9674 CU_ASSERT(1 == session->iframe.payloadleft);
9676 rv = nghttp2_session_mem_recv(session, (const uint8_t *)"\0", 1);
9678 CU_ASSERT(NGHTTP2_ERR_BAD_CLIENT_MAGIC == rv);
9680 nghttp2_session_del(session);
9682 /* disable global nghttp2_enable_strict_preface here */
9683 nghttp2_enable_strict_preface = 0;
9686 void test_nghttp2_session_delete_data_item(void) {
9687 nghttp2_session *session;
9688 nghttp2_session_callbacks callbacks;
9690 nghttp2_data_provider prd;
9692 memset(&callbacks, 0, sizeof(callbacks));
9694 nghttp2_session_server_new(&session, &callbacks, NULL);
9696 a = open_recv_stream(session, 1);
9697 open_recv_stream_with_dep(session, 3, a);
9699 /* We don't care about these members, since we won't send data */
9700 prd.source.ptr = NULL;
9701 prd.read_callback = fail_data_source_read_callback;
9703 CU_ASSERT(0 == nghttp2_submit_data(session, NGHTTP2_FLAG_NONE, 1, &prd));
9704 CU_ASSERT(0 == nghttp2_submit_data(session, NGHTTP2_FLAG_NONE, 3, &prd));
9706 nghttp2_session_del(session);
9709 void test_nghttp2_session_open_idle_stream(void) {
9710 nghttp2_session *session;
9711 nghttp2_session_callbacks callbacks;
9712 nghttp2_stream *stream;
9713 nghttp2_stream *opened_stream;
9714 nghttp2_priority_spec pri_spec;
9715 nghttp2_frame frame;
9717 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
9719 nghttp2_session_server_new(&session, &callbacks, NULL);
9721 nghttp2_priority_spec_init(&pri_spec, 0, 3, 0);
9723 nghttp2_frame_priority_init(&frame.priority, 1, &pri_spec);
9725 CU_ASSERT(0 == nghttp2_session_on_priority_received(session, &frame));
9727 stream = nghttp2_session_get_stream_raw(session, 1);
9729 CU_ASSERT(NGHTTP2_STREAM_IDLE == stream->state);
9730 CU_ASSERT(NULL == stream->closed_prev);
9731 CU_ASSERT(NULL == stream->closed_next);
9732 CU_ASSERT(1 == session->num_idle_streams);
9733 CU_ASSERT(session->idle_stream_head == stream);
9734 CU_ASSERT(session->idle_stream_tail == stream);
9736 opened_stream = open_recv_stream2(session, 1, NGHTTP2_STREAM_OPENING);
9738 CU_ASSERT(stream == opened_stream);
9739 CU_ASSERT(NGHTTP2_STREAM_OPENING == stream->state);
9740 CU_ASSERT(0 == session->num_idle_streams);
9741 CU_ASSERT(NULL == session->idle_stream_head);
9742 CU_ASSERT(NULL == session->idle_stream_tail);
9744 nghttp2_frame_priority_free(&frame.priority);
9746 nghttp2_session_del(session);
9749 void test_nghttp2_session_cancel_reserved_remote(void) {
9750 nghttp2_session *session;
9751 nghttp2_session_callbacks callbacks;
9752 nghttp2_stream *stream;
9753 nghttp2_frame frame;
9756 nghttp2_hd_deflater deflater;
9761 mem = nghttp2_mem_default();
9762 frame_pack_bufs_init(&bufs);
9764 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
9765 callbacks.send_callback = null_send_callback;
9767 nghttp2_session_client_new(&session, &callbacks, NULL);
9769 nghttp2_hd_deflate_init(&deflater, mem);
9771 stream = open_recv_stream2(session, 2, NGHTTP2_STREAM_RESERVED);
9773 nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, 2, NGHTTP2_CANCEL);
9775 CU_ASSERT(NGHTTP2_STREAM_CLOSING == stream->state);
9777 CU_ASSERT(0 == nghttp2_session_send(session));
9779 nvlen = ARRLEN(resnv);
9780 nghttp2_nv_array_copy(&nva, resnv, nvlen, mem);
9782 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 2,
9783 NGHTTP2_HCAT_PUSH_RESPONSE, NULL, nva, nvlen);
9784 rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
9788 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
9789 nghttp2_buf_len(&bufs.head->buf));
9791 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
9793 /* stream is not dangling, so assign NULL */
9796 /* No RST_STREAM or GOAWAY is generated since stream should be in
9797 NGHTTP2_STREAM_CLOSING and push response should be ignored. */
9798 CU_ASSERT(0 == nghttp2_outbound_queue_size(&session->ob_reg));
9800 /* Check that we can receive push response HEADERS while RST_STREAM
9802 open_recv_stream2(session, 4, NGHTTP2_STREAM_RESERVED);
9804 nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, 2, NGHTTP2_CANCEL);
9806 nghttp2_bufs_reset(&bufs);
9808 frame.hd.stream_id = 4;
9809 rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
9813 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
9814 nghttp2_buf_len(&bufs.head->buf));
9816 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
9818 CU_ASSERT(1 == nghttp2_outbound_queue_size(&session->ob_reg));
9820 nghttp2_frame_headers_free(&frame.headers, mem);
9822 nghttp2_hd_deflate_free(&deflater);
9824 nghttp2_session_del(session);
9826 nghttp2_bufs_free(&bufs);
9829 void test_nghttp2_session_reset_pending_headers(void) {
9830 nghttp2_session *session;
9831 nghttp2_session_callbacks callbacks;
9832 nghttp2_stream *stream;
9836 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
9837 callbacks.send_callback = null_send_callback;
9838 callbacks.on_frame_send_callback = on_frame_send_callback;
9839 callbacks.on_frame_not_send_callback = on_frame_not_send_callback;
9840 callbacks.on_stream_close_callback = on_stream_close_callback;
9842 nghttp2_session_client_new(&session, &callbacks, &ud);
9844 stream_id = nghttp2_submit_request(session, NULL, NULL, 0, NULL, NULL);
9845 CU_ASSERT(stream_id >= 1);
9847 nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, stream_id,
9850 session->remote_settings.max_concurrent_streams = 0;
9852 /* RST_STREAM cancels pending HEADERS and is not actually sent. */
9853 ud.frame_send_cb_called = 0;
9854 CU_ASSERT(0 == nghttp2_session_send(session));
9856 CU_ASSERT(0 == ud.frame_send_cb_called);
9858 stream = nghttp2_session_get_stream(session, stream_id);
9860 CU_ASSERT(NULL == stream);
9862 /* See HEADERS is not sent. on_stream_close is called just like
9863 transmission failure. */
9864 session->remote_settings.max_concurrent_streams = 1;
9866 ud.frame_not_send_cb_called = 0;
9867 ud.stream_close_error_code = 0;
9868 CU_ASSERT(0 == nghttp2_session_send(session));
9870 CU_ASSERT(1 == ud.frame_not_send_cb_called);
9871 CU_ASSERT(NGHTTP2_HEADERS == ud.not_sent_frame_type);
9872 CU_ASSERT(NGHTTP2_CANCEL == ud.stream_close_error_code);
9874 stream = nghttp2_session_get_stream(session, stream_id);
9876 CU_ASSERT(NULL == stream);
9878 nghttp2_session_del(session);
9881 void test_nghttp2_session_send_data_callback(void) {
9882 nghttp2_session *session;
9883 nghttp2_session_callbacks callbacks;
9884 nghttp2_data_provider data_prd;
9887 nghttp2_frame_hd hd;
9889 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
9890 callbacks.send_callback = accumulator_send_callback;
9891 callbacks.send_data_callback = send_data_callback;
9893 data_prd.read_callback = no_copy_data_source_read_callback;
9898 ud.data_source_length = NGHTTP2_DATA_PAYLOADLEN * 2;
9900 nghttp2_session_client_new(&session, &callbacks, &ud);
9902 open_sent_stream(session, 1);
9904 nghttp2_submit_data(session, NGHTTP2_FLAG_END_STREAM, 1, &data_prd);
9906 CU_ASSERT(0 == nghttp2_session_send(session));
9908 CU_ASSERT((NGHTTP2_FRAME_HDLEN + NGHTTP2_DATA_PAYLOADLEN) * 2 == acc.length);
9910 nghttp2_frame_unpack_frame_hd(&hd, acc.buf);
9912 CU_ASSERT(16384 == hd.length);
9913 CU_ASSERT(NGHTTP2_DATA == hd.type);
9914 CU_ASSERT(NGHTTP2_FLAG_NONE == hd.flags);
9916 nghttp2_frame_unpack_frame_hd(&hd, acc.buf + NGHTTP2_FRAME_HDLEN + hd.length);
9918 CU_ASSERT(16384 == hd.length);
9919 CU_ASSERT(NGHTTP2_DATA == hd.type);
9920 CU_ASSERT(NGHTTP2_FLAG_END_STREAM == hd.flags);
9922 nghttp2_session_del(session);
9925 void test_nghttp2_session_on_begin_headers_temporal_failure(void) {
9926 nghttp2_session *session;
9927 nghttp2_session_callbacks callbacks;
9932 nghttp2_hd_deflater deflater;
9933 nghttp2_outbound_item *item;
9935 mem = nghttp2_mem_default();
9936 frame_pack_bufs_init(&bufs);
9937 nghttp2_hd_deflate_init(&deflater, mem);
9939 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
9940 callbacks.on_begin_headers_callback =
9941 temporal_failure_on_begin_headers_callback;
9942 callbacks.on_header_callback = on_header_callback;
9943 callbacks.on_frame_recv_callback = on_frame_recv_callback;
9944 callbacks.send_callback = null_send_callback;
9945 nghttp2_session_server_new(&session, &callbacks, &ud);
9947 rv = pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, reqnv,
9948 ARRLEN(reqnv), mem);
9951 ud.header_cb_called = 0;
9952 ud.frame_recv_cb_called = 0;
9953 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
9954 nghttp2_bufs_len(&bufs));
9955 CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == rv);
9956 CU_ASSERT(0 == ud.header_cb_called);
9957 CU_ASSERT(0 == ud.frame_recv_cb_called);
9959 item = nghttp2_session_get_next_ob_item(session);
9960 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
9961 CU_ASSERT(1 == item->frame.hd.stream_id);
9962 CU_ASSERT(NGHTTP2_INTERNAL_ERROR == item->frame.rst_stream.error_code);
9964 nghttp2_session_del(session);
9965 nghttp2_hd_deflate_free(&deflater);
9967 nghttp2_bufs_reset(&bufs);
9968 /* check for PUSH_PROMISE */
9969 nghttp2_hd_deflate_init(&deflater, mem);
9970 nghttp2_session_client_new(&session, &callbacks, &ud);
9972 open_sent_stream(session, 1);
9974 rv = pack_push_promise(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, 2,
9975 reqnv, ARRLEN(reqnv), mem);
9978 ud.header_cb_called = 0;
9979 ud.frame_recv_cb_called = 0;
9980 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
9981 nghttp2_bufs_len(&bufs));
9982 CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == rv);
9983 CU_ASSERT(0 == ud.header_cb_called);
9984 CU_ASSERT(0 == ud.frame_recv_cb_called);
9986 item = nghttp2_session_get_next_ob_item(session);
9987 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
9988 CU_ASSERT(2 == item->frame.hd.stream_id);
9989 CU_ASSERT(NGHTTP2_INTERNAL_ERROR == item->frame.rst_stream.error_code);
9991 nghttp2_session_del(session);
9992 nghttp2_hd_deflate_free(&deflater);
9993 nghttp2_bufs_free(&bufs);
9996 void test_nghttp2_session_defer_then_close(void) {
9997 nghttp2_session *session;
9998 nghttp2_session_callbacks callbacks;
9999 nghttp2_data_provider prd;
10001 const uint8_t *datap;
10003 nghttp2_frame frame;
10005 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
10006 callbacks.send_callback = null_send_callback;
10008 nghttp2_session_client_new(&session, &callbacks, NULL);
10010 prd.read_callback = defer_data_source_read_callback;
10012 rv = nghttp2_submit_request(session, NULL, reqnv, ARRLEN(reqnv), &prd, NULL);
10015 /* This sends HEADERS */
10016 datalen = nghttp2_session_mem_send(session, &datap);
10018 CU_ASSERT(datalen > 0);
10020 /* This makes DATA item deferred */
10021 datalen = nghttp2_session_mem_send(session, &datap);
10023 CU_ASSERT(datalen == 0);
10025 nghttp2_frame_rst_stream_init(&frame.rst_stream, 1, NGHTTP2_CANCEL);
10027 /* Assertion failure; GH-264 */
10028 rv = nghttp2_session_on_rst_stream_received(session, &frame);
10030 CU_ASSERT(rv == 0);
10032 nghttp2_session_del(session);
10035 static int submit_response_on_stream_close(nghttp2_session *session,
10037 uint32_t error_code,
10039 nghttp2_data_provider data_prd;
10043 data_prd.read_callback = temporal_failure_data_source_read_callback;
10045 // Attempt to submit response or data to the stream being closed
10046 switch (stream_id) {
10048 CU_ASSERT(0 == nghttp2_submit_response(session, stream_id, resnv,
10049 ARRLEN(resnv), &data_prd));
10052 CU_ASSERT(0 == nghttp2_submit_data(session, NGHTTP2_FLAG_NONE, stream_id,
10060 void test_nghttp2_session_detach_item_from_closed_stream(void) {
10061 nghttp2_session *session;
10062 nghttp2_session_callbacks callbacks;
10064 memset(&callbacks, 0, sizeof(callbacks));
10066 callbacks.send_callback = null_send_callback;
10067 callbacks.on_stream_close_callback = submit_response_on_stream_close;
10069 nghttp2_session_server_new(&session, &callbacks, NULL);
10071 open_recv_stream(session, 1);
10072 open_recv_stream(session, 3);
10074 nghttp2_session_close_stream(session, 1, NGHTTP2_NO_ERROR);
10075 nghttp2_session_close_stream(session, 3, NGHTTP2_NO_ERROR);
10077 CU_ASSERT(0 == nghttp2_session_send(session));
10079 nghttp2_session_del(session);
10082 void test_nghttp2_session_flooding(void) {
10083 nghttp2_session *session;
10084 nghttp2_session_callbacks callbacks;
10087 nghttp2_frame frame;
10091 mem = nghttp2_mem_default();
10093 frame_pack_bufs_init(&bufs);
10095 memset(&callbacks, 0, sizeof(callbacks));
10098 nghttp2_session_server_new(&session, &callbacks, NULL);
10100 nghttp2_frame_ping_init(&frame.ping, NGHTTP2_FLAG_NONE, NULL);
10101 nghttp2_frame_pack_ping(&bufs, &frame.ping);
10102 nghttp2_frame_ping_free(&frame.ping);
10104 buf = &bufs.head->buf;
10106 for (i = 0; i < NGHTTP2_DEFAULT_MAX_OBQ_FLOOD_ITEM; ++i) {
10108 (ssize_t)nghttp2_buf_len(buf) ==
10109 nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf)));
10112 CU_ASSERT(NGHTTP2_ERR_FLOODED ==
10113 nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf)));
10115 nghttp2_session_del(session);
10118 nghttp2_bufs_reset(&bufs);
10120 nghttp2_session_server_new(&session, &callbacks, NULL);
10122 nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE, NULL, 0);
10123 nghttp2_frame_pack_settings(&bufs, &frame.settings);
10124 nghttp2_frame_settings_free(&frame.settings, mem);
10126 buf = &bufs.head->buf;
10128 for (i = 0; i < NGHTTP2_DEFAULT_MAX_OBQ_FLOOD_ITEM; ++i) {
10130 (ssize_t)nghttp2_buf_len(buf) ==
10131 nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf)));
10134 CU_ASSERT(NGHTTP2_ERR_FLOODED ==
10135 nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf)));
10137 nghttp2_session_del(session);
10138 nghttp2_bufs_free(&bufs);
10141 void test_nghttp2_session_change_stream_priority(void) {
10142 nghttp2_session *session;
10143 nghttp2_session_callbacks callbacks;
10144 nghttp2_stream *stream1, *stream2, *stream3, *stream5;
10145 nghttp2_priority_spec pri_spec;
10148 memset(&callbacks, 0, sizeof(callbacks));
10150 nghttp2_session_server_new(&session, &callbacks, NULL);
10152 stream1 = open_recv_stream(session, 1);
10153 stream3 = open_recv_stream_with_dep_weight(session, 3, 199, stream1);
10154 stream2 = open_sent_stream_with_dep_weight(session, 2, 101, stream3);
10156 nghttp2_priority_spec_init(&pri_spec, 1, 256, 0);
10158 rv = nghttp2_session_change_stream_priority(session, 2, &pri_spec);
10160 CU_ASSERT(0 == rv);
10162 CU_ASSERT(stream1 == stream2->dep_prev);
10163 CU_ASSERT(256 == stream2->weight);
10165 /* Cannot change stream which does not exist */
10166 rv = nghttp2_session_change_stream_priority(session, 5, &pri_spec);
10167 CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT == rv);
10169 /* It is an error to depend on itself */
10170 rv = nghttp2_session_change_stream_priority(session, 1, &pri_spec);
10171 CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT == rv);
10173 /* It is an error to change priority of root stream (0) */
10174 rv = nghttp2_session_change_stream_priority(session, 0, &pri_spec);
10175 CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT == rv);
10177 /* Depends on the non-existing idle stream. This creates that idle
10179 nghttp2_priority_spec_init(&pri_spec, 5, 9, 1);
10181 rv = nghttp2_session_change_stream_priority(session, 2, &pri_spec);
10183 CU_ASSERT(0 == rv);
10185 stream5 = nghttp2_session_get_stream_raw(session, 5);
10187 CU_ASSERT(NULL != stream5);
10188 CU_ASSERT(&session->root == stream5->dep_prev);
10189 CU_ASSERT(stream5 == stream2->dep_prev);
10190 CU_ASSERT(9 == stream2->weight);
10192 nghttp2_session_del(session);
10194 /* Check that this works in client session too */
10195 nghttp2_session_client_new(&session, &callbacks, NULL);
10197 stream1 = open_sent_stream(session, 1);
10199 nghttp2_priority_spec_init(&pri_spec, 5, 9, 1);
10201 rv = nghttp2_session_change_stream_priority(session, 1, &pri_spec);
10203 CU_ASSERT(0 == rv);
10205 stream5 = nghttp2_session_get_stream_raw(session, 5);
10207 CU_ASSERT(NULL != stream5);
10208 CU_ASSERT(&session->root == stream5->dep_prev);
10209 CU_ASSERT(stream5 == stream1->dep_prev);
10210 CU_ASSERT(9 == stream1->weight);
10212 nghttp2_session_del(session);
10215 void test_nghttp2_session_create_idle_stream(void) {
10216 nghttp2_session *session;
10217 nghttp2_session_callbacks callbacks;
10218 nghttp2_stream *stream2, *stream4, *stream8, *stream10;
10219 nghttp2_priority_spec pri_spec;
10223 memset(&callbacks, 0, sizeof(callbacks));
10224 callbacks.send_callback = null_send_callback;
10226 nghttp2_session_server_new(&session, &callbacks, NULL);
10228 stream2 = open_sent_stream(session, 2);
10230 nghttp2_priority_spec_init(&pri_spec, 2, 111, 1);
10232 rv = nghttp2_session_create_idle_stream(session, 4, &pri_spec);
10234 CU_ASSERT(0 == rv);
10236 stream4 = nghttp2_session_get_stream_raw(session, 4);
10238 CU_ASSERT(4 == stream4->stream_id);
10239 CU_ASSERT(111 == stream4->weight);
10240 CU_ASSERT(stream2 == stream4->dep_prev);
10241 CU_ASSERT(stream4 == stream2->dep_next);
10243 /* If pri_spec->stream_id does not exist, and it is idle stream, it
10245 nghttp2_priority_spec_init(&pri_spec, 10, 109, 0);
10247 rv = nghttp2_session_create_idle_stream(session, 8, &pri_spec);
10249 CU_ASSERT(0 == rv);
10251 stream8 = nghttp2_session_get_stream_raw(session, 8);
10252 stream10 = nghttp2_session_get_stream_raw(session, 10);
10254 CU_ASSERT(8 == stream8->stream_id);
10255 CU_ASSERT(109 == stream8->weight);
10256 CU_ASSERT(10 == stream10->stream_id);
10257 CU_ASSERT(16 == stream10->weight);
10258 CU_ASSERT(stream10 == stream8->dep_prev);
10259 CU_ASSERT(&session->root == stream10->dep_prev);
10261 /* It is an error to attempt to create already existing idle
10263 rv = nghttp2_session_create_idle_stream(session, 4, &pri_spec);
10265 CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT == rv);
10267 /* It is an error to depend on itself */
10268 pri_spec.stream_id = 6;
10270 rv = nghttp2_session_create_idle_stream(session, 6, &pri_spec);
10271 CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT == rv);
10273 /* It is an error to create root stream (0) as idle stream */
10274 rv = nghttp2_session_create_idle_stream(session, 0, &pri_spec);
10275 CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT == rv);
10277 /* It is an error to create non-idle stream */
10278 session->last_sent_stream_id = 20;
10279 pri_spec.stream_id = 2;
10281 rv = nghttp2_session_create_idle_stream(session, 18, &pri_spec);
10283 CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT == rv);
10285 nghttp2_session_del(session);
10287 /* Check that this works in client session too */
10288 nghttp2_session_client_new(&session, &callbacks, NULL);
10290 nghttp2_priority_spec_init(&pri_spec, 4, 99, 1);
10292 rv = nghttp2_session_create_idle_stream(session, 2, &pri_spec);
10294 CU_ASSERT(0 == rv);
10296 stream4 = nghttp2_session_get_stream_raw(session, 4);
10297 stream2 = nghttp2_session_get_stream_raw(session, 2);
10299 CU_ASSERT(NULL != stream4);
10300 CU_ASSERT(NULL != stream2);
10301 CU_ASSERT(&session->root == stream4->dep_prev);
10302 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == stream4->weight);
10303 CU_ASSERT(stream4 == stream2->dep_prev);
10304 CU_ASSERT(99 == stream2->weight);
10306 nghttp2_session_del(session);
10308 /* Check that idle stream is reduced when nghttp2_session_send() is
10310 nghttp2_session_server_new(&session, &callbacks, NULL);
10312 session->local_settings.max_concurrent_streams = 30;
10314 nghttp2_priority_spec_init(&pri_spec, 0, 16, 0);
10315 for (i = 0; i < 100; ++i) {
10316 rv = nghttp2_session_create_idle_stream(session, i * 2 + 1, &pri_spec);
10318 CU_ASSERT(0 == rv);
10320 nghttp2_priority_spec_init(&pri_spec, i * 2 + 1, 16, 0);
10323 CU_ASSERT(100 == session->num_idle_streams);
10324 CU_ASSERT(0 == nghttp2_session_send(session));
10325 CU_ASSERT(30 == session->num_idle_streams);
10326 CU_ASSERT(141 == session->idle_stream_head->stream_id);
10328 nghttp2_session_del(session);
10330 /* Check that idle stream is reduced when nghttp2_session_mem_recv() is
10332 nghttp2_session_client_new(&session, &callbacks, NULL);
10334 session->local_settings.max_concurrent_streams = 30;
10336 nghttp2_priority_spec_init(&pri_spec, 0, 16, 0);
10337 for (i = 0; i < 100; ++i) {
10338 rv = nghttp2_session_create_idle_stream(session, i * 2 + 1, &pri_spec);
10340 CU_ASSERT(0 == rv);
10342 nghttp2_priority_spec_init(&pri_spec, i * 2 + 1, 16, 0);
10345 CU_ASSERT(100 == session->num_idle_streams);
10346 CU_ASSERT(0 == nghttp2_session_mem_recv(session, NULL, 0));
10347 CU_ASSERT(30 == session->num_idle_streams);
10348 CU_ASSERT(141 == session->idle_stream_head->stream_id);
10350 nghttp2_session_del(session);
10353 void test_nghttp2_session_repeated_priority_change(void) {
10354 nghttp2_session *session;
10355 nghttp2_session_callbacks callbacks;
10356 nghttp2_frame frame;
10357 nghttp2_priority_spec pri_spec;
10358 int32_t stream_id, last_stream_id;
10359 int32_t max_streams = 20;
10361 memset(&callbacks, 0, sizeof(callbacks));
10363 nghttp2_session_server_new(&session, &callbacks, NULL);
10365 session->local_settings.max_concurrent_streams = (uint32_t)max_streams;
10368 nghttp2_priority_spec_init(&pri_spec, 0, 16, 0);
10369 nghttp2_frame_priority_init(&frame.priority, 1, &pri_spec);
10371 CU_ASSERT(0 == nghttp2_session_on_priority_received(session, &frame));
10373 nghttp2_frame_priority_free(&frame.priority);
10375 last_stream_id = max_streams * 2 + 1;
10377 for (stream_id = 3; stream_id < last_stream_id; stream_id += 2) {
10378 /* 1 -> stream_id */
10379 nghttp2_priority_spec_init(&pri_spec, stream_id, 16, 0);
10380 nghttp2_frame_priority_init(&frame.priority, 1, &pri_spec);
10382 CU_ASSERT(0 == nghttp2_session_on_priority_received(session, &frame));
10384 nghttp2_frame_priority_free(&frame.priority);
10387 CU_ASSERT(20 == session->num_idle_streams);
10388 CU_ASSERT(1 == session->idle_stream_head->stream_id);
10390 /* 1 -> last_stream_id */
10391 nghttp2_priority_spec_init(&pri_spec, last_stream_id, 16, 0);
10392 nghttp2_frame_priority_init(&frame.priority, 1, &pri_spec);
10394 CU_ASSERT(0 == nghttp2_session_on_priority_received(session, &frame));
10396 nghttp2_frame_priority_free(&frame.priority);
10398 CU_ASSERT(20 == session->num_idle_streams);
10399 CU_ASSERT(3 == session->idle_stream_head->stream_id);
10401 nghttp2_session_del(session);
10404 void test_nghttp2_session_repeated_priority_submission(void) {
10405 nghttp2_session *session;
10406 nghttp2_session_callbacks callbacks;
10407 nghttp2_priority_spec pri_spec;
10408 int32_t stream_id, last_stream_id;
10409 uint32_t max_streams = NGHTTP2_MIN_IDLE_STREAMS;
10411 memset(&callbacks, 0, sizeof(callbacks));
10413 callbacks.send_callback = null_send_callback;
10415 nghttp2_session_client_new(&session, &callbacks, NULL);
10417 session->local_settings.max_concurrent_streams = max_streams;
10420 nghttp2_priority_spec_init(&pri_spec, 0, 16, 0);
10423 nghttp2_submit_priority(session, NGHTTP2_FLAG_NONE, 1, &pri_spec));
10425 last_stream_id = (int32_t)(max_streams * 2 + 1);
10427 for (stream_id = 3; stream_id < last_stream_id; stream_id += 2) {
10428 /* 1 -> stream_id */
10429 nghttp2_priority_spec_init(&pri_spec, stream_id, 16, 0);
10432 0 == nghttp2_submit_priority(session, NGHTTP2_FLAG_NONE, 1, &pri_spec));
10435 CU_ASSERT(0 == nghttp2_session_send(session));
10436 CU_ASSERT(max_streams == session->num_idle_streams);
10437 CU_ASSERT(1 == session->idle_stream_head->stream_id);
10439 /* 1 -> last_stream_id */
10440 nghttp2_priority_spec_init(&pri_spec, last_stream_id, 16, 0);
10443 nghttp2_submit_priority(session, NGHTTP2_FLAG_NONE, 1, &pri_spec));
10445 CU_ASSERT(0 == nghttp2_session_send(session));
10446 CU_ASSERT(max_streams == session->num_idle_streams);
10447 CU_ASSERT(3 == session->idle_stream_head->stream_id);
10449 nghttp2_session_del(session);
10452 void test_nghttp2_session_set_local_window_size(void) {
10453 nghttp2_session *session;
10454 nghttp2_session_callbacks callbacks;
10455 nghttp2_outbound_item *item;
10456 nghttp2_stream *stream;
10458 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
10459 callbacks.send_callback = null_send_callback;
10461 nghttp2_session_client_new(&session, &callbacks, NULL);
10462 stream = open_sent_stream(session, 1);
10463 stream->recv_window_size = 4096;
10465 CU_ASSERT(0 == nghttp2_session_set_local_window_size(
10466 session, NGHTTP2_FLAG_NONE, 1, 65536));
10467 CU_ASSERT(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE + 1 ==
10468 stream->local_window_size);
10469 CU_ASSERT(4096 == stream->recv_window_size);
10470 CU_ASSERT(65536 - 4096 ==
10471 nghttp2_session_get_stream_local_window_size(session, 1));
10473 item = nghttp2_session_get_next_ob_item(session);
10475 CU_ASSERT(NGHTTP2_WINDOW_UPDATE == item->frame.hd.type);
10476 CU_ASSERT(1 == item->frame.window_update.hd.stream_id);
10477 CU_ASSERT(1 == item->frame.window_update.window_size_increment);
10479 CU_ASSERT(0 == nghttp2_session_send(session));
10481 /* Go decrement part */
10482 CU_ASSERT(0 == nghttp2_session_set_local_window_size(
10483 session, NGHTTP2_FLAG_NONE, 1, 32768));
10484 CU_ASSERT(32768 == stream->local_window_size);
10485 CU_ASSERT(-28672 == stream->recv_window_size);
10486 CU_ASSERT(32768 == stream->recv_reduction);
10487 CU_ASSERT(65536 - 4096 ==
10488 nghttp2_session_get_stream_local_window_size(session, 1));
10490 item = nghttp2_session_get_next_ob_item(session);
10492 CU_ASSERT(item == NULL);
10494 /* Increase local window size */
10495 CU_ASSERT(0 == nghttp2_session_set_local_window_size(
10496 session, NGHTTP2_FLAG_NONE, 1, 49152));
10497 CU_ASSERT(49152 == stream->local_window_size);
10498 CU_ASSERT(-12288 == stream->recv_window_size);
10499 CU_ASSERT(16384 == stream->recv_reduction);
10500 CU_ASSERT(65536 - 4096 ==
10501 nghttp2_session_get_stream_local_window_size(session, 1));
10502 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
10504 /* Increase local window again */
10505 CU_ASSERT(0 == nghttp2_session_set_local_window_size(
10506 session, NGHTTP2_FLAG_NONE, 1, 65537));
10507 CU_ASSERT(65537 == stream->local_window_size);
10508 CU_ASSERT(4096 == stream->recv_window_size);
10509 CU_ASSERT(0 == stream->recv_reduction);
10510 CU_ASSERT(65537 - 4096 ==
10511 nghttp2_session_get_stream_local_window_size(session, 1));
10513 item = nghttp2_session_get_next_ob_item(session);
10515 CU_ASSERT(1 == item->frame.window_update.window_size_increment);
10517 CU_ASSERT(0 == nghttp2_session_send(session));
10519 /* Check connection-level flow control */
10520 session->recv_window_size = 4096;
10521 CU_ASSERT(0 == nghttp2_session_set_local_window_size(
10522 session, NGHTTP2_FLAG_NONE, 0, 65536));
10523 CU_ASSERT(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE + 1 ==
10524 session->local_window_size);
10525 CU_ASSERT(4096 == session->recv_window_size);
10526 CU_ASSERT(65536 - 4096 == nghttp2_session_get_local_window_size(session));
10528 item = nghttp2_session_get_next_ob_item(session);
10530 CU_ASSERT(NGHTTP2_WINDOW_UPDATE == item->frame.hd.type);
10531 CU_ASSERT(0 == item->frame.window_update.hd.stream_id);
10532 CU_ASSERT(1 == item->frame.window_update.window_size_increment);
10534 CU_ASSERT(0 == nghttp2_session_send(session));
10536 /* Go decrement part */
10537 CU_ASSERT(0 == nghttp2_session_set_local_window_size(
10538 session, NGHTTP2_FLAG_NONE, 0, 32768));
10539 CU_ASSERT(32768 == session->local_window_size);
10540 CU_ASSERT(-28672 == session->recv_window_size);
10541 CU_ASSERT(32768 == session->recv_reduction);
10542 CU_ASSERT(65536 - 4096 == nghttp2_session_get_local_window_size(session));
10544 item = nghttp2_session_get_next_ob_item(session);
10546 CU_ASSERT(item == NULL);
10548 /* Increase local window size */
10549 CU_ASSERT(0 == nghttp2_session_set_local_window_size(
10550 session, NGHTTP2_FLAG_NONE, 0, 49152));
10551 CU_ASSERT(49152 == session->local_window_size);
10552 CU_ASSERT(-12288 == session->recv_window_size);
10553 CU_ASSERT(16384 == session->recv_reduction);
10554 CU_ASSERT(65536 - 4096 == nghttp2_session_get_local_window_size(session));
10555 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
10557 /* Increase local window again */
10558 CU_ASSERT(0 == nghttp2_session_set_local_window_size(
10559 session, NGHTTP2_FLAG_NONE, 0, 65537));
10560 CU_ASSERT(65537 == session->local_window_size);
10561 CU_ASSERT(4096 == session->recv_window_size);
10562 CU_ASSERT(0 == session->recv_reduction);
10563 CU_ASSERT(65537 - 4096 == nghttp2_session_get_local_window_size(session));
10565 item = nghttp2_session_get_next_ob_item(session);
10567 CU_ASSERT(1 == item->frame.window_update.window_size_increment);
10569 CU_ASSERT(0 == nghttp2_session_send(session));
10571 nghttp2_session_del(session);
10573 /* Make sure that nghttp2_session_set_local_window_size submits
10574 WINDOW_UPDATE if necessary to increase stream-level window. */
10575 nghttp2_session_client_new(&session, &callbacks, NULL);
10576 stream = open_sent_stream(session, 1);
10577 stream->recv_window_size = NGHTTP2_INITIAL_WINDOW_SIZE;
10579 CU_ASSERT(0 == nghttp2_session_set_local_window_size(
10580 session, NGHTTP2_FLAG_NONE, 1, 0));
10581 CU_ASSERT(0 == stream->recv_window_size);
10582 CU_ASSERT(0 == nghttp2_session_get_stream_local_window_size(session, 1));
10583 /* This should submit WINDOW_UPDATE frame because stream-level
10584 receiving window is now full. */
10586 nghttp2_session_set_local_window_size(session, NGHTTP2_FLAG_NONE, 1,
10587 NGHTTP2_INITIAL_WINDOW_SIZE));
10588 CU_ASSERT(0 == stream->recv_window_size);
10589 CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE ==
10590 nghttp2_session_get_stream_local_window_size(session, 1));
10592 item = nghttp2_session_get_next_ob_item(session);
10594 CU_ASSERT(NGHTTP2_WINDOW_UPDATE == item->frame.hd.type);
10595 CU_ASSERT(1 == item->frame.hd.stream_id);
10596 CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE ==
10597 item->frame.window_update.window_size_increment);
10599 nghttp2_session_del(session);
10601 /* Make sure that nghttp2_session_set_local_window_size submits
10602 WINDOW_UPDATE if necessary to increase connection-level
10604 nghttp2_session_client_new(&session, &callbacks, NULL);
10605 session->recv_window_size = NGHTTP2_INITIAL_WINDOW_SIZE;
10607 CU_ASSERT(0 == nghttp2_session_set_local_window_size(
10608 session, NGHTTP2_FLAG_NONE, 0, 0));
10609 CU_ASSERT(0 == session->recv_window_size);
10610 CU_ASSERT(0 == nghttp2_session_get_local_window_size(session));
10611 /* This should submit WINDOW_UPDATE frame because connection-level
10612 receiving window is now full. */
10614 nghttp2_session_set_local_window_size(session, NGHTTP2_FLAG_NONE, 0,
10615 NGHTTP2_INITIAL_WINDOW_SIZE));
10616 CU_ASSERT(0 == session->recv_window_size);
10617 CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE ==
10618 nghttp2_session_get_local_window_size(session));
10620 item = nghttp2_session_get_next_ob_item(session);
10622 CU_ASSERT(NGHTTP2_WINDOW_UPDATE == item->frame.hd.type);
10623 CU_ASSERT(0 == item->frame.hd.stream_id);
10624 CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE ==
10625 item->frame.window_update.window_size_increment);
10627 nghttp2_session_del(session);
10630 void test_nghttp2_session_cancel_from_before_frame_send(void) {
10632 nghttp2_session *session;
10633 nghttp2_session_callbacks callbacks;
10635 nghttp2_settings_entry iv;
10636 nghttp2_data_provider data_prd;
10638 nghttp2_stream *stream;
10640 memset(&callbacks, 0, sizeof(callbacks));
10642 callbacks.before_frame_send_callback = cancel_before_frame_send_callback;
10643 callbacks.on_frame_not_send_callback = on_frame_not_send_callback;
10644 callbacks.send_callback = null_send_callback;
10646 nghttp2_session_client_new(&session, &callbacks, &ud);
10648 iv.settings_id = 0;
10649 iv.value = 1000000009;
10651 rv = nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, &iv, 1);
10653 CU_ASSERT(0 == rv);
10655 ud.frame_send_cb_called = 0;
10656 ud.before_frame_send_cb_called = 0;
10657 ud.frame_not_send_cb_called = 0;
10659 rv = nghttp2_session_send(session);
10661 CU_ASSERT(0 == rv);
10662 CU_ASSERT(0 == ud.frame_send_cb_called);
10663 CU_ASSERT(1 == ud.before_frame_send_cb_called);
10664 CU_ASSERT(1 == ud.frame_not_send_cb_called);
10666 data_prd.source.ptr = NULL;
10667 data_prd.read_callback = temporal_failure_data_source_read_callback;
10669 stream_id = nghttp2_submit_request(session, NULL, reqnv, ARRLEN(reqnv),
10672 CU_ASSERT(stream_id > 0);
10674 ud.frame_send_cb_called = 0;
10675 ud.before_frame_send_cb_called = 0;
10676 ud.frame_not_send_cb_called = 0;
10678 rv = nghttp2_session_send(session);
10680 CU_ASSERT(0 == rv);
10681 CU_ASSERT(0 == ud.frame_send_cb_called);
10682 CU_ASSERT(1 == ud.before_frame_send_cb_called);
10683 CU_ASSERT(1 == ud.frame_not_send_cb_called);
10685 stream = nghttp2_session_get_stream_raw(session, stream_id);
10687 CU_ASSERT(NULL == stream);
10689 nghttp2_session_del(session);
10691 nghttp2_session_server_new(&session, &callbacks, &ud);
10693 open_recv_stream(session, 1);
10695 stream_id = nghttp2_submit_push_promise(session, NGHTTP2_FLAG_NONE, 1, reqnv,
10696 ARRLEN(reqnv), NULL);
10698 CU_ASSERT(stream_id > 0);
10700 ud.frame_send_cb_called = 0;
10701 ud.before_frame_send_cb_called = 0;
10702 ud.frame_not_send_cb_called = 0;
10704 rv = nghttp2_session_send(session);
10706 CU_ASSERT(0 == rv);
10707 CU_ASSERT(0 == ud.frame_send_cb_called);
10708 CU_ASSERT(1 == ud.before_frame_send_cb_called);
10709 CU_ASSERT(1 == ud.frame_not_send_cb_called);
10711 stream = nghttp2_session_get_stream_raw(session, stream_id);
10713 CU_ASSERT(NULL == stream);
10715 nghttp2_session_del(session);
10718 void test_nghttp2_session_too_many_settings(void) {
10719 nghttp2_session *session;
10720 nghttp2_option *option;
10721 nghttp2_session_callbacks callbacks;
10722 nghttp2_frame frame;
10727 nghttp2_settings_entry iv[3];
10729 nghttp2_outbound_item *item;
10731 mem = nghttp2_mem_default();
10732 frame_pack_bufs_init(&bufs);
10734 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
10735 callbacks.on_frame_recv_callback = on_frame_recv_callback;
10736 callbacks.send_callback = null_send_callback;
10738 nghttp2_option_new(&option);
10739 nghttp2_option_set_max_settings(option, 1);
10741 nghttp2_session_client_new2(&session, &callbacks, &ud, option);
10743 CU_ASSERT(1 == session->max_settings);
10745 nghttp2_option_del(option);
10747 iv[0].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
10748 iv[0].value = 3000;
10750 iv[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
10751 iv[1].value = 16384;
10753 nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE, dup_iv(iv, 2),
10756 rv = nghttp2_frame_pack_settings(&bufs, &frame.settings);
10758 CU_ASSERT(0 == rv);
10759 CU_ASSERT(nghttp2_bufs_len(&bufs) > 0);
10761 nghttp2_frame_settings_free(&frame.settings, mem);
10763 buf = &bufs.head->buf;
10764 assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
10766 ud.frame_recv_cb_called = 0;
10768 rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
10769 CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv);
10771 item = nghttp2_session_get_next_ob_item(session);
10772 CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
10774 nghttp2_bufs_reset(&bufs);
10775 nghttp2_bufs_free(&bufs);
10776 nghttp2_session_del(session);
10780 prepare_session_removed_closed_stream(nghttp2_session *session,
10781 nghttp2_hd_deflater *deflater) {
10783 nghttp2_settings_entry iv;
10788 nghttp2_stream *stream;
10789 nghttp2_frame_hd hd;
10791 mem = nghttp2_mem_default();
10793 frame_pack_bufs_init(&bufs);
10795 iv.settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS;
10798 rv = nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, &iv, 1);
10800 CU_ASSERT(0 == rv);
10802 rv = nghttp2_session_send(session);
10804 CU_ASSERT(0 == rv);
10806 for (i = 1; i <= 3; i += 2) {
10807 rv = pack_headers(&bufs, deflater, i,
10808 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM, reqnv,
10809 ARRLEN(reqnv), mem);
10811 CU_ASSERT(0 == rv);
10813 nread = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
10814 nghttp2_bufs_len(&bufs));
10816 CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == nread);
10818 nghttp2_bufs_reset(&bufs);
10821 nghttp2_session_close_stream(session, 3, NGHTTP2_NO_ERROR);
10823 rv = pack_headers(&bufs, deflater, 5,
10824 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM, reqnv,
10825 ARRLEN(reqnv), mem);
10827 CU_ASSERT(0 == rv);
10829 /* Receiving stream 5 will erase stream 3 from closed stream list */
10830 nread = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
10831 nghttp2_bufs_len(&bufs));
10833 CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == nread);
10835 stream = nghttp2_session_get_stream_raw(session, 3);
10837 CU_ASSERT(NULL == stream);
10839 /* Since the current max concurrent streams is
10840 NGHTTP2_DEFAULT_MAX_CONCURRENT_STREAMS, receiving frame on stream
10842 nghttp2_bufs_reset(&bufs);
10843 rv = pack_headers(&bufs, deflater, 3,
10844 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM,
10845 trailernv, ARRLEN(trailernv), mem);
10847 CU_ASSERT(0 == rv);
10849 nread = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
10850 nghttp2_bufs_len(&bufs));
10852 CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == nread);
10853 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
10855 nghttp2_frame_hd_init(&hd, 0, NGHTTP2_DATA, NGHTTP2_FLAG_NONE, 3);
10856 nghttp2_bufs_reset(&bufs);
10857 nghttp2_frame_pack_frame_hd(bufs.head->buf.last, &hd);
10858 bufs.head->buf.last += NGHTTP2_FRAME_HDLEN;
10860 nread = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
10861 nghttp2_bufs_len(&bufs));
10863 CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == nread);
10864 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
10866 /* Now server receives SETTINGS ACK */
10867 nghttp2_frame_hd_init(&hd, 0, NGHTTP2_SETTINGS, NGHTTP2_FLAG_ACK, 0);
10868 nghttp2_bufs_reset(&bufs);
10869 nghttp2_frame_pack_frame_hd(bufs.head->buf.last, &hd);
10870 bufs.head->buf.last += NGHTTP2_FRAME_HDLEN;
10872 nread = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
10873 nghttp2_bufs_len(&bufs));
10875 CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == nread);
10877 nghttp2_bufs_free(&bufs);
10880 void test_nghttp2_session_removed_closed_stream(void) {
10881 nghttp2_session *session;
10882 nghttp2_session_callbacks callbacks;
10884 nghttp2_hd_deflater deflater;
10888 nghttp2_frame_hd hd;
10889 nghttp2_outbound_item *item;
10891 mem = nghttp2_mem_default();
10893 frame_pack_bufs_init(&bufs);
10895 memset(&callbacks, 0, sizeof(callbacks));
10897 callbacks.send_callback = null_send_callback;
10899 nghttp2_session_server_new(&session, &callbacks, NULL);
10901 /* Now local max concurrent streams is still unlimited, pending max
10902 concurrent streams is now 2. */
10904 nghttp2_hd_deflate_init(&deflater, mem);
10906 prepare_session_removed_closed_stream(session, &deflater);
10908 /* Now current max concurrent streams is 2. Receiving frame on
10909 stream 3 is ignored because we have no stream object for stream
10911 nghttp2_bufs_reset(&bufs);
10912 rv = pack_headers(&bufs, &deflater, 3,
10913 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM,
10914 trailernv, ARRLEN(trailernv), mem);
10916 CU_ASSERT(0 == rv);
10918 nread = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
10919 nghttp2_bufs_len(&bufs));
10921 CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == nread);
10923 item = nghttp2_session_get_next_ob_item(session);
10925 CU_ASSERT(NULL == item);
10927 nghttp2_hd_deflate_free(&deflater);
10928 nghttp2_session_del(session);
10930 nghttp2_session_server_new(&session, &callbacks, NULL);
10931 nghttp2_hd_deflate_init(&deflater, mem);
10932 /* Same setup, and then receive DATA instead of HEADERS */
10934 prepare_session_removed_closed_stream(session, &deflater);
10936 nghttp2_frame_hd_init(&hd, 0, NGHTTP2_DATA, NGHTTP2_FLAG_NONE, 3);
10937 nghttp2_bufs_reset(&bufs);
10938 nghttp2_frame_pack_frame_hd(bufs.head->buf.last, &hd);
10939 bufs.head->buf.last += NGHTTP2_FRAME_HDLEN;
10941 nread = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
10942 nghttp2_bufs_len(&bufs));
10944 CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == nread);
10946 item = nghttp2_session_get_next_ob_item(session);
10948 CU_ASSERT(NULL == item);
10950 nghttp2_hd_deflate_free(&deflater);
10951 nghttp2_session_del(session);
10953 nghttp2_bufs_free(&bufs);
10956 static ssize_t pause_once_data_source_read_callback(
10957 nghttp2_session *session, int32_t stream_id, uint8_t *buf, size_t len,
10958 uint32_t *data_flags, nghttp2_data_source *source, void *user_data) {
10959 my_user_data *ud = user_data;
10960 if (ud->data_source_read_cb_paused == 0) {
10961 ++ud->data_source_read_cb_paused;
10962 return NGHTTP2_ERR_PAUSE;
10965 return fixed_length_data_source_read_callback(session, stream_id, buf, len,
10966 data_flags, source, user_data);
10969 void test_nghttp2_session_pause_data(void) {
10970 nghttp2_session *session;
10971 nghttp2_session_callbacks callbacks;
10972 nghttp2_data_provider data_prd;
10975 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
10976 callbacks.send_callback = null_send_callback;
10977 callbacks.on_frame_send_callback = on_frame_send_callback;
10979 data_prd.read_callback = pause_once_data_source_read_callback;
10980 ud.data_source_length = NGHTTP2_DATA_PAYLOADLEN;
10982 nghttp2_session_server_new(&session, &callbacks, &ud);
10984 open_recv_stream(session, 1);
10987 0 == nghttp2_submit_data(session, NGHTTP2_FLAG_END_STREAM, 1, &data_prd));
10989 ud.frame_send_cb_called = 0;
10990 ud.data_source_read_cb_paused = 0;
10992 CU_ASSERT(0 == nghttp2_session_send(session));
10993 CU_ASSERT(0 == ud.frame_send_cb_called);
10994 CU_ASSERT(NULL == session->aob.item);
10995 CU_ASSERT(0 == nghttp2_session_send(session));
10996 CU_ASSERT(1 == ud.frame_send_cb_called);
10997 CU_ASSERT(NGHTTP2_DATA == ud.sent_frame_type);
10998 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
11000 nghttp2_session_del(session);
11003 void test_nghttp2_session_no_closed_streams(void) {
11004 nghttp2_session *session;
11005 nghttp2_session_callbacks callbacks;
11006 nghttp2_option *option;
11008 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
11010 nghttp2_option_new(&option);
11011 nghttp2_option_set_no_closed_streams(option, 1);
11013 nghttp2_session_server_new2(&session, &callbacks, NULL, option);
11015 open_recv_stream(session, 1);
11017 nghttp2_session_close_stream(session, 1, NGHTTP2_NO_ERROR);
11019 CU_ASSERT(0 == session->num_closed_streams);
11021 nghttp2_session_del(session);
11022 nghttp2_option_del(option);
11025 void test_nghttp2_session_set_stream_user_data(void) {
11026 nghttp2_session *session;
11027 nghttp2_session_callbacks callbacks;
11029 int user_data1, user_data2;
11031 const uint8_t *datap;
11034 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
11036 nghttp2_session_client_new(&session, &callbacks, NULL);
11038 stream_id = nghttp2_submit_request(session, NULL, reqnv, ARRLEN(reqnv), NULL,
11041 rv = nghttp2_session_set_stream_user_data(session, stream_id, &user_data2);
11043 CU_ASSERT(0 == rv);
11045 datalen = nghttp2_session_mem_send(session, &datap);
11047 CU_ASSERT(datalen > 0);
11049 CU_ASSERT(&user_data2 ==
11050 nghttp2_session_get_stream_user_data(session, stream_id));
11052 CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT ==
11053 nghttp2_session_set_stream_user_data(session, 2, NULL));
11055 nghttp2_session_del(session);
11058 static void check_nghttp2_http_recv_headers_fail(
11059 nghttp2_session *session, nghttp2_hd_deflater *deflater, int32_t stream_id,
11060 int stream_state, const nghttp2_nv *nva, size_t nvlen) {
11063 nghttp2_outbound_item *item;
11067 mem = nghttp2_mem_default();
11068 frame_pack_bufs_init(&bufs);
11070 ud = session->user_data;
11072 if (stream_state != -1) {
11073 if (nghttp2_session_is_my_stream_id(session, stream_id)) {
11074 open_sent_stream2(session, stream_id, (nghttp2_stream_state)stream_state);
11076 open_recv_stream2(session, stream_id, (nghttp2_stream_state)stream_state);
11080 rv = pack_headers(&bufs, deflater, stream_id, NGHTTP2_FLAG_END_HEADERS, nva,
11082 CU_ASSERT(0 == rv);
11084 ud->invalid_frame_recv_cb_called = 0;
11086 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11087 nghttp2_buf_len(&bufs.head->buf));
11089 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
11091 item = nghttp2_session_get_next_ob_item(session);
11093 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
11094 CU_ASSERT(1 == ud->invalid_frame_recv_cb_called);
11096 CU_ASSERT(0 == nghttp2_session_send(session));
11098 nghttp2_bufs_free(&bufs);
11101 static void check_nghttp2_http_recv_headers_ok(
11102 nghttp2_session *session, nghttp2_hd_deflater *deflater, int32_t stream_id,
11103 int stream_state, const nghttp2_nv *nva, size_t nvlen) {
11109 mem = nghttp2_mem_default();
11110 frame_pack_bufs_init(&bufs);
11112 ud = session->user_data;
11114 if (stream_state != -1) {
11115 if (nghttp2_session_is_my_stream_id(session, stream_id)) {
11116 open_sent_stream2(session, stream_id, (nghttp2_stream_state)stream_state);
11118 open_recv_stream2(session, stream_id, (nghttp2_stream_state)stream_state);
11122 rv = pack_headers(&bufs, deflater, stream_id, NGHTTP2_FLAG_END_HEADERS, nva,
11124 CU_ASSERT(0 == rv);
11126 ud->frame_recv_cb_called = 0;
11128 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11129 nghttp2_buf_len(&bufs.head->buf));
11131 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
11132 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
11133 CU_ASSERT(1 == ud->frame_recv_cb_called);
11135 nghttp2_bufs_free(&bufs);
11138 void test_nghttp2_http_mandatory_headers(void) {
11139 nghttp2_session *session;
11140 nghttp2_session_callbacks callbacks;
11141 nghttp2_hd_deflater deflater;
11144 /* test case for response */
11145 const nghttp2_nv nostatus_resnv[] = {MAKE_NV("server", "foo")};
11146 const nghttp2_nv dupstatus_resnv[] = {MAKE_NV(":status", "200"),
11147 MAKE_NV(":status", "200")};
11148 const nghttp2_nv badpseudo_resnv[] = {MAKE_NV(":status", "200"),
11149 MAKE_NV(":scheme", "https")};
11150 const nghttp2_nv latepseudo_resnv[] = {MAKE_NV("server", "foo"),
11151 MAKE_NV(":status", "200")};
11152 const nghttp2_nv badstatus_resnv[] = {MAKE_NV(":status", "2000")};
11153 const nghttp2_nv badcl_resnv[] = {MAKE_NV(":status", "200"),
11154 MAKE_NV("content-length", "-1")};
11155 const nghttp2_nv dupcl_resnv[] = {MAKE_NV(":status", "200"),
11156 MAKE_NV("content-length", "0"),
11157 MAKE_NV("content-length", "0")};
11158 const nghttp2_nv badhd_resnv[] = {MAKE_NV(":status", "200"),
11159 MAKE_NV("connection", "close")};
11160 const nghttp2_nv cl1xx_resnv[] = {MAKE_NV(":status", "100"),
11161 MAKE_NV("content-length", "0")};
11162 const nghttp2_nv cl204_resnv[] = {MAKE_NV(":status", "204"),
11163 MAKE_NV("content-length", "0")};
11164 const nghttp2_nv clnonzero204_resnv[] = {MAKE_NV(":status", "204"),
11165 MAKE_NV("content-length", "100")};
11166 const nghttp2_nv status101_resnv[] = {MAKE_NV(":status", "101")};
11168 /* test case for request */
11169 const nghttp2_nv nopath_reqnv[] = {MAKE_NV(":scheme", "https"),
11170 MAKE_NV(":method", "GET"),
11171 MAKE_NV(":authority", "localhost")};
11172 const nghttp2_nv earlyconnect_reqnv[] = {
11173 MAKE_NV(":method", "CONNECT"), MAKE_NV(":scheme", "https"),
11174 MAKE_NV(":path", "/"), MAKE_NV(":authority", "localhost")};
11175 const nghttp2_nv lateconnect_reqnv[] = {
11176 MAKE_NV(":scheme", "https"), MAKE_NV(":path", "/"),
11177 MAKE_NV(":method", "CONNECT"), MAKE_NV(":authority", "localhost")};
11178 const nghttp2_nv duppath_reqnv[] = {
11179 MAKE_NV(":scheme", "https"), MAKE_NV(":method", "GET"),
11180 MAKE_NV(":authority", "localhost"), MAKE_NV(":path", "/"),
11181 MAKE_NV(":path", "/")};
11182 const nghttp2_nv badcl_reqnv[] = {
11183 MAKE_NV(":scheme", "https"), MAKE_NV(":method", "POST"),
11184 MAKE_NV(":authority", "localhost"), MAKE_NV(":path", "/"),
11185 MAKE_NV("content-length", "-1")};
11186 const nghttp2_nv dupcl_reqnv[] = {
11187 MAKE_NV(":scheme", "https"), MAKE_NV(":method", "POST"),
11188 MAKE_NV(":authority", "localhost"), MAKE_NV(":path", "/"),
11189 MAKE_NV("content-length", "0"), MAKE_NV("content-length", "0")};
11190 const nghttp2_nv badhd_reqnv[] = {
11191 MAKE_NV(":scheme", "https"), MAKE_NV(":method", "GET"),
11192 MAKE_NV(":authority", "localhost"), MAKE_NV(":path", "/"),
11193 MAKE_NV("connection", "close")};
11194 const nghttp2_nv badauthority_reqnv[] = {
11195 MAKE_NV(":scheme", "https"), MAKE_NV(":method", "GET"),
11196 MAKE_NV(":authority", "\x0d\x0alocalhost"), MAKE_NV(":path", "/")};
11197 const nghttp2_nv badhdbtw_reqnv[] = {
11198 MAKE_NV(":scheme", "https"), MAKE_NV(":method", "GET"),
11199 MAKE_NV("foo", "\x0d\x0a"), MAKE_NV(":authority", "localhost"),
11200 MAKE_NV(":path", "/")};
11201 const nghttp2_nv asteriskget1_reqnv[] = {
11202 MAKE_NV(":path", "*"), MAKE_NV(":scheme", "https"),
11203 MAKE_NV(":authority", "localhost"), MAKE_NV(":method", "GET")};
11204 const nghttp2_nv asteriskget2_reqnv[] = {
11205 MAKE_NV(":scheme", "https"), MAKE_NV(":authority", "localhost"),
11206 MAKE_NV(":method", "GET"), MAKE_NV(":path", "*")};
11207 const nghttp2_nv asteriskoptions1_reqnv[] = {
11208 MAKE_NV(":path", "*"), MAKE_NV(":scheme", "https"),
11209 MAKE_NV(":authority", "localhost"), MAKE_NV(":method", "OPTIONS")};
11210 const nghttp2_nv asteriskoptions2_reqnv[] = {
11211 MAKE_NV(":scheme", "https"), MAKE_NV(":authority", "localhost"),
11212 MAKE_NV(":method", "OPTIONS"), MAKE_NV(":path", "*")};
11213 const nghttp2_nv connectproto_reqnv[] = {
11214 MAKE_NV(":scheme", "https"), MAKE_NV(":path", "/"),
11215 MAKE_NV(":method", "CONNECT"), MAKE_NV(":authority", "localhost"),
11216 MAKE_NV(":protocol", "websocket")};
11217 const nghttp2_nv connectprotoget_reqnv[] = {
11218 MAKE_NV(":scheme", "https"), MAKE_NV(":path", "/"),
11219 MAKE_NV(":method", "GET"), MAKE_NV(":authority", "localhost"),
11220 MAKE_NV(":protocol", "websocket")};
11221 const nghttp2_nv connectprotonopath_reqnv[] = {
11222 MAKE_NV(":scheme", "https"), MAKE_NV(":method", "CONNECT"),
11223 MAKE_NV(":authority", "localhost"), MAKE_NV(":protocol", "websocket")};
11224 const nghttp2_nv connectprotonoauth_reqnv[] = {
11225 MAKE_NV(":scheme", "http"), MAKE_NV(":path", "/"),
11226 MAKE_NV(":method", "CONNECT"), MAKE_NV("host", "localhost"),
11227 MAKE_NV(":protocol", "websocket")};
11228 const nghttp2_nv regularconnect_reqnv[] = {
11229 MAKE_NV(":method", "CONNECT"), MAKE_NV(":authority", "localhost")};
11231 mem = nghttp2_mem_default();
11233 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
11234 callbacks.send_callback = null_send_callback;
11235 callbacks.on_frame_recv_callback = on_frame_recv_callback;
11236 callbacks.on_invalid_frame_recv_callback = on_invalid_frame_recv_callback;
11238 nghttp2_session_client_new(&session, &callbacks, &ud);
11240 nghttp2_hd_deflate_init(&deflater, mem);
11242 /* response header lacks :status */
11243 check_nghttp2_http_recv_headers_fail(session, &deflater, 1,
11244 NGHTTP2_STREAM_OPENING, nostatus_resnv,
11245 ARRLEN(nostatus_resnv));
11247 /* response header has 2 :status */
11248 check_nghttp2_http_recv_headers_fail(session, &deflater, 3,
11249 NGHTTP2_STREAM_OPENING, dupstatus_resnv,
11250 ARRLEN(dupstatus_resnv));
11252 /* response header has bad pseudo header :scheme */
11253 check_nghttp2_http_recv_headers_fail(session, &deflater, 5,
11254 NGHTTP2_STREAM_OPENING, badpseudo_resnv,
11255 ARRLEN(badpseudo_resnv));
11257 /* response header has :status after regular header field */
11258 check_nghttp2_http_recv_headers_fail(session, &deflater, 7,
11259 NGHTTP2_STREAM_OPENING, latepseudo_resnv,
11260 ARRLEN(latepseudo_resnv));
11262 /* response header has bad status code */
11263 check_nghttp2_http_recv_headers_fail(session, &deflater, 9,
11264 NGHTTP2_STREAM_OPENING, badstatus_resnv,
11265 ARRLEN(badstatus_resnv));
11267 /* response header has bad content-length */
11268 check_nghttp2_http_recv_headers_fail(session, &deflater, 11,
11269 NGHTTP2_STREAM_OPENING, badcl_resnv,
11270 ARRLEN(badcl_resnv));
11272 /* response header has multiple content-length */
11273 check_nghttp2_http_recv_headers_fail(session, &deflater, 13,
11274 NGHTTP2_STREAM_OPENING, dupcl_resnv,
11275 ARRLEN(dupcl_resnv));
11277 /* response header has disallowed header field */
11278 check_nghttp2_http_recv_headers_fail(session, &deflater, 15,
11279 NGHTTP2_STREAM_OPENING, badhd_resnv,
11280 ARRLEN(badhd_resnv));
11282 /* response header has content-length with 100 status code */
11283 check_nghttp2_http_recv_headers_fail(session, &deflater, 17,
11284 NGHTTP2_STREAM_OPENING, cl1xx_resnv,
11285 ARRLEN(cl1xx_resnv));
11287 /* response header has 0 content-length with 204 status code */
11288 check_nghttp2_http_recv_headers_ok(session, &deflater, 19,
11289 NGHTTP2_STREAM_OPENING, cl204_resnv,
11290 ARRLEN(cl204_resnv));
11292 /* response header has nonzero content-length with 204 status
11294 check_nghttp2_http_recv_headers_fail(
11295 session, &deflater, 21, NGHTTP2_STREAM_OPENING, clnonzero204_resnv,
11296 ARRLEN(clnonzero204_resnv));
11298 /* status code 101 should not be used in HTTP/2 because it is used
11299 for HTTP Upgrade which HTTP/2 removes. */
11300 check_nghttp2_http_recv_headers_fail(session, &deflater, 23,
11301 NGHTTP2_STREAM_OPENING, status101_resnv,
11302 ARRLEN(status101_resnv));
11304 nghttp2_hd_deflate_free(&deflater);
11306 nghttp2_session_del(session);
11308 /* check server side */
11309 nghttp2_session_server_new(&session, &callbacks, &ud);
11311 nghttp2_hd_deflate_init(&deflater, mem);
11313 /* request header has no :path */
11314 check_nghttp2_http_recv_headers_fail(session, &deflater, 1, -1, nopath_reqnv,
11315 ARRLEN(nopath_reqnv));
11317 /* request header has CONNECT method, but followed by :path */
11318 check_nghttp2_http_recv_headers_fail(session, &deflater, 3, -1,
11319 earlyconnect_reqnv,
11320 ARRLEN(earlyconnect_reqnv));
11322 /* request header has CONNECT method following :path */
11323 check_nghttp2_http_recv_headers_fail(
11324 session, &deflater, 5, -1, lateconnect_reqnv, ARRLEN(lateconnect_reqnv));
11326 /* request header has multiple :path */
11327 check_nghttp2_http_recv_headers_fail(session, &deflater, 7, -1, duppath_reqnv,
11328 ARRLEN(duppath_reqnv));
11330 /* request header has bad content-length */
11331 check_nghttp2_http_recv_headers_fail(session, &deflater, 9, -1, badcl_reqnv,
11332 ARRLEN(badcl_reqnv));
11334 /* request header has multiple content-length */
11335 check_nghttp2_http_recv_headers_fail(session, &deflater, 11, -1, dupcl_reqnv,
11336 ARRLEN(dupcl_reqnv));
11338 /* request header has disallowed header field */
11339 check_nghttp2_http_recv_headers_fail(session, &deflater, 13, -1, badhd_reqnv,
11340 ARRLEN(badhd_reqnv));
11342 /* request header has :authority header field containing illegal
11344 check_nghttp2_http_recv_headers_fail(session, &deflater, 15, -1,
11345 badauthority_reqnv,
11346 ARRLEN(badauthority_reqnv));
11348 /* request header has regular header field containing illegal
11349 character before all mandatory header fields are seen. */
11350 check_nghttp2_http_recv_headers_fail(session, &deflater, 17, -1,
11351 badhdbtw_reqnv, ARRLEN(badhdbtw_reqnv));
11353 /* request header has "*" in :path header field while method is GET.
11354 :path is received before :method */
11355 check_nghttp2_http_recv_headers_fail(session, &deflater, 19, -1,
11356 asteriskget1_reqnv,
11357 ARRLEN(asteriskget1_reqnv));
11359 /* request header has "*" in :path header field while method is GET.
11360 :method is received before :path */
11361 check_nghttp2_http_recv_headers_fail(session, &deflater, 21, -1,
11362 asteriskget2_reqnv,
11363 ARRLEN(asteriskget2_reqnv));
11365 /* OPTIONS method can include "*" in :path header field. :path is
11366 received before :method. */
11367 check_nghttp2_http_recv_headers_ok(session, &deflater, 23, -1,
11368 asteriskoptions1_reqnv,
11369 ARRLEN(asteriskoptions1_reqnv));
11371 /* OPTIONS method can include "*" in :path header field. :method is
11372 received before :path. */
11373 check_nghttp2_http_recv_headers_ok(session, &deflater, 25, -1,
11374 asteriskoptions2_reqnv,
11375 ARRLEN(asteriskoptions2_reqnv));
11377 /* :protocol is not allowed unless it is enabled by the local
11379 check_nghttp2_http_recv_headers_fail(session, &deflater, 27, -1,
11380 connectproto_reqnv,
11381 ARRLEN(connectproto_reqnv));
11383 nghttp2_hd_deflate_free(&deflater);
11385 nghttp2_session_del(session);
11387 /* enable SETTINGS_CONNECT_PROTOCOL */
11388 nghttp2_session_server_new(&session, &callbacks, &ud);
11390 session->pending_enable_connect_protocol = 1;
11392 nghttp2_hd_deflate_init(&deflater, mem);
11394 /* :protocol is allowed if SETTINGS_CONNECT_PROTOCOL is enabled by
11395 the local endpoint. */
11396 check_nghttp2_http_recv_headers_ok(session, &deflater, 1, -1,
11397 connectproto_reqnv,
11398 ARRLEN(connectproto_reqnv));
11400 /* :protocol is only allowed with CONNECT method. */
11401 check_nghttp2_http_recv_headers_fail(session, &deflater, 3, -1,
11402 connectprotoget_reqnv,
11403 ARRLEN(connectprotoget_reqnv));
11405 /* CONNECT method with :protocol requires :path. */
11406 check_nghttp2_http_recv_headers_fail(session, &deflater, 5, -1,
11407 connectprotonopath_reqnv,
11408 ARRLEN(connectprotonopath_reqnv));
11410 /* CONNECT method with :protocol requires :authority. */
11411 check_nghttp2_http_recv_headers_fail(session, &deflater, 7, -1,
11412 connectprotonoauth_reqnv,
11413 ARRLEN(connectprotonoauth_reqnv));
11415 /* regular CONNECT method should succeed with
11416 SETTINGS_CONNECT_PROTOCOL */
11417 check_nghttp2_http_recv_headers_ok(session, &deflater, 9, -1,
11418 regularconnect_reqnv,
11419 ARRLEN(regularconnect_reqnv));
11421 nghttp2_hd_deflate_free(&deflater);
11423 nghttp2_session_del(session);
11426 void test_nghttp2_http_content_length(void) {
11427 nghttp2_session *session;
11428 nghttp2_session_callbacks callbacks;
11429 nghttp2_hd_deflater deflater;
11433 nghttp2_stream *stream;
11434 const nghttp2_nv cl_resnv[] = {MAKE_NV(":status", "200"),
11435 MAKE_NV("te", "trailers"),
11436 MAKE_NV("content-length", "9000000000")};
11437 const nghttp2_nv cl_reqnv[] = {
11438 MAKE_NV(":path", "/"), MAKE_NV(":method", "PUT"),
11439 MAKE_NV(":scheme", "https"), MAKE_NV("te", "trailers"),
11440 MAKE_NV("host", "localhost"), MAKE_NV("content-length", "9000000000")};
11442 mem = nghttp2_mem_default();
11443 frame_pack_bufs_init(&bufs);
11445 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
11446 callbacks.send_callback = null_send_callback;
11448 nghttp2_session_client_new(&session, &callbacks, NULL);
11450 nghttp2_hd_deflate_init(&deflater, mem);
11452 stream = open_sent_stream2(session, 1, NGHTTP2_STREAM_OPENING);
11454 rv = pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, cl_resnv,
11455 ARRLEN(cl_resnv), mem);
11456 CU_ASSERT(0 == rv);
11458 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11459 nghttp2_buf_len(&bufs.head->buf));
11461 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
11462 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
11463 CU_ASSERT(9000000000LL == stream->content_length);
11464 CU_ASSERT(200 == stream->status_code);
11466 nghttp2_hd_deflate_free(&deflater);
11468 nghttp2_session_del(session);
11470 nghttp2_bufs_reset(&bufs);
11472 /* check server side */
11473 nghttp2_session_server_new(&session, &callbacks, NULL);
11475 nghttp2_hd_deflate_init(&deflater, mem);
11477 rv = pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, cl_reqnv,
11478 ARRLEN(cl_reqnv), mem);
11479 CU_ASSERT(0 == rv);
11481 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11482 nghttp2_buf_len(&bufs.head->buf));
11484 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
11486 stream = nghttp2_session_get_stream(session, 1);
11488 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
11489 CU_ASSERT(9000000000LL == stream->content_length);
11491 nghttp2_hd_deflate_free(&deflater);
11493 nghttp2_session_del(session);
11495 nghttp2_bufs_free(&bufs);
11498 void test_nghttp2_http_content_length_mismatch(void) {
11499 nghttp2_session *session;
11500 nghttp2_session_callbacks callbacks;
11501 nghttp2_hd_deflater deflater;
11505 const nghttp2_nv cl_reqnv[] = {
11506 MAKE_NV(":path", "/"), MAKE_NV(":method", "PUT"),
11507 MAKE_NV(":authority", "localhost"), MAKE_NV(":scheme", "https"),
11508 MAKE_NV("content-length", "20")};
11509 const nghttp2_nv cl_resnv[] = {MAKE_NV(":status", "200"),
11510 MAKE_NV("content-length", "20")};
11511 nghttp2_outbound_item *item;
11512 nghttp2_frame_hd hd;
11514 mem = nghttp2_mem_default();
11515 frame_pack_bufs_init(&bufs);
11517 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
11518 callbacks.send_callback = null_send_callback;
11520 nghttp2_session_server_new(&session, &callbacks, NULL);
11522 nghttp2_hd_deflate_init(&deflater, mem);
11524 /* header says content-length: 20, but HEADERS has END_STREAM flag set */
11525 rv = pack_headers(&bufs, &deflater, 1,
11526 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM,
11527 cl_reqnv, ARRLEN(cl_reqnv), mem);
11528 CU_ASSERT(0 == rv);
11530 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11531 nghttp2_buf_len(&bufs.head->buf));
11533 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
11535 item = nghttp2_session_get_next_ob_item(session);
11536 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
11538 CU_ASSERT(0 == nghttp2_session_send(session));
11540 nghttp2_bufs_reset(&bufs);
11542 /* header says content-length: 20, but DATA has 0 byte */
11543 rv = pack_headers(&bufs, &deflater, 3, NGHTTP2_FLAG_END_HEADERS, cl_reqnv,
11544 ARRLEN(cl_reqnv), mem);
11545 CU_ASSERT(0 == rv);
11547 nghttp2_frame_hd_init(&hd, 0, NGHTTP2_DATA, NGHTTP2_FLAG_END_STREAM, 3);
11548 nghttp2_frame_pack_frame_hd(bufs.head->buf.last, &hd);
11549 bufs.head->buf.last += NGHTTP2_FRAME_HDLEN;
11551 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11552 nghttp2_buf_len(&bufs.head->buf));
11554 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
11556 item = nghttp2_session_get_next_ob_item(session);
11557 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
11559 CU_ASSERT(0 == nghttp2_session_send(session));
11561 nghttp2_bufs_reset(&bufs);
11563 /* header says content-length: 20, but DATA has 21 bytes */
11564 rv = pack_headers(&bufs, &deflater, 5, NGHTTP2_FLAG_END_HEADERS, cl_reqnv,
11565 ARRLEN(cl_reqnv), mem);
11566 CU_ASSERT(0 == rv);
11568 nghttp2_frame_hd_init(&hd, 21, NGHTTP2_DATA, NGHTTP2_FLAG_END_STREAM, 5);
11569 nghttp2_frame_pack_frame_hd(bufs.head->buf.last, &hd);
11570 bufs.head->buf.last += NGHTTP2_FRAME_HDLEN + 21;
11572 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11573 nghttp2_buf_len(&bufs.head->buf));
11575 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
11577 item = nghttp2_session_get_next_ob_item(session);
11578 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
11580 CU_ASSERT(0 == nghttp2_session_send(session));
11582 nghttp2_bufs_reset(&bufs);
11584 nghttp2_hd_deflate_free(&deflater);
11586 nghttp2_session_del(session);
11588 /* Check for client */
11589 nghttp2_session_client_new(&session, &callbacks, NULL);
11591 nghttp2_hd_deflate_init(&deflater, mem);
11593 /* header says content-length: 20, but HEADERS has END_STREAM flag set */
11594 nghttp2_submit_request(session, NULL, reqnv, ARRLEN(reqnv), NULL, NULL);
11596 CU_ASSERT(0 == nghttp2_session_send(session));
11598 rv = pack_headers(&bufs, &deflater, 1,
11599 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM,
11600 cl_resnv, ARRLEN(cl_resnv), mem);
11601 CU_ASSERT(0 == rv);
11603 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11604 nghttp2_buf_len(&bufs.head->buf));
11606 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
11608 item = nghttp2_session_get_next_ob_item(session);
11609 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
11611 CU_ASSERT(NULL != nghttp2_session_get_stream(session, 1));
11612 CU_ASSERT(0 == nghttp2_session_send(session));
11613 /* After sending RST_STREAM, stream must be closed */
11614 CU_ASSERT(NULL == nghttp2_session_get_stream(session, 1));
11616 nghttp2_bufs_reset(&bufs);
11618 /* header says content-length: 20, but DATA has 0 byte */
11619 nghttp2_submit_request(session, NULL, reqnv, ARRLEN(reqnv), NULL, NULL);
11621 CU_ASSERT(0 == nghttp2_session_send(session));
11623 rv = pack_headers(&bufs, &deflater, 3, NGHTTP2_FLAG_END_HEADERS, cl_resnv,
11624 ARRLEN(cl_resnv), mem);
11625 CU_ASSERT(0 == rv);
11627 nghttp2_frame_hd_init(&hd, 0, NGHTTP2_DATA, NGHTTP2_FLAG_END_STREAM, 3);
11628 nghttp2_frame_pack_frame_hd(bufs.head->buf.last, &hd);
11629 bufs.head->buf.last += NGHTTP2_FRAME_HDLEN;
11631 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11632 nghttp2_buf_len(&bufs.head->buf));
11634 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
11636 item = nghttp2_session_get_next_ob_item(session);
11637 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
11639 CU_ASSERT(NULL != nghttp2_session_get_stream(session, 3));
11640 CU_ASSERT(0 == nghttp2_session_send(session));
11641 /* After sending RST_STREAM, stream must be closed */
11642 CU_ASSERT(NULL == nghttp2_session_get_stream(session, 3));
11644 nghttp2_bufs_reset(&bufs);
11646 /* header says content-length: 20, but DATA has 21 bytes */
11647 nghttp2_submit_request(session, NULL, reqnv, ARRLEN(reqnv), NULL, NULL);
11649 CU_ASSERT(0 == nghttp2_session_send(session));
11651 rv = pack_headers(&bufs, &deflater, 5, NGHTTP2_FLAG_END_HEADERS, cl_resnv,
11652 ARRLEN(cl_resnv), mem);
11653 CU_ASSERT(0 == rv);
11655 nghttp2_frame_hd_init(&hd, 21, NGHTTP2_DATA, NGHTTP2_FLAG_END_STREAM, 5);
11656 nghttp2_frame_pack_frame_hd(bufs.head->buf.last, &hd);
11657 bufs.head->buf.last += NGHTTP2_FRAME_HDLEN + 21;
11659 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11660 nghttp2_buf_len(&bufs.head->buf));
11662 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
11664 item = nghttp2_session_get_next_ob_item(session);
11665 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
11667 CU_ASSERT(NULL != nghttp2_session_get_stream(session, 5));
11668 CU_ASSERT(0 == nghttp2_session_send(session));
11669 /* After sending RST_STREAM, stream must be closed */
11670 CU_ASSERT(NULL == nghttp2_session_get_stream(session, 5));
11672 nghttp2_bufs_reset(&bufs);
11674 nghttp2_bufs_free(&bufs);
11676 nghttp2_hd_deflate_free(&deflater);
11678 nghttp2_session_del(session);
11681 void test_nghttp2_http_non_final_response(void) {
11682 nghttp2_session *session;
11683 nghttp2_session_callbacks callbacks;
11684 nghttp2_hd_deflater deflater;
11688 const nghttp2_nv nonfinal_resnv[] = {
11689 MAKE_NV(":status", "100"),
11691 nghttp2_outbound_item *item;
11692 nghttp2_frame_hd hd;
11694 mem = nghttp2_mem_default();
11695 frame_pack_bufs_init(&bufs);
11697 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
11698 callbacks.send_callback = null_send_callback;
11700 nghttp2_session_client_new(&session, &callbacks, NULL);
11702 nghttp2_hd_deflate_init(&deflater, mem);
11704 /* non-final HEADERS with END_STREAM is illegal */
11705 open_sent_stream2(session, 1, NGHTTP2_STREAM_OPENING);
11707 rv = pack_headers(&bufs, &deflater, 1,
11708 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM,
11709 nonfinal_resnv, ARRLEN(nonfinal_resnv), mem);
11710 CU_ASSERT(0 == rv);
11712 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11713 nghttp2_buf_len(&bufs.head->buf));
11715 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
11717 item = nghttp2_session_get_next_ob_item(session);
11718 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
11720 CU_ASSERT(0 == nghttp2_session_send(session));
11722 nghttp2_bufs_reset(&bufs);
11724 /* non-final HEADERS followed by non-empty DATA is illegal */
11725 open_sent_stream2(session, 3, NGHTTP2_STREAM_OPENING);
11727 rv = pack_headers(&bufs, &deflater, 3, NGHTTP2_FLAG_END_HEADERS,
11728 nonfinal_resnv, ARRLEN(nonfinal_resnv), mem);
11729 CU_ASSERT(0 == rv);
11731 nghttp2_frame_hd_init(&hd, 10, NGHTTP2_DATA, NGHTTP2_FLAG_END_STREAM, 3);
11732 nghttp2_frame_pack_frame_hd(bufs.head->buf.last, &hd);
11733 bufs.head->buf.last += NGHTTP2_FRAME_HDLEN + 10;
11735 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11736 nghttp2_buf_len(&bufs.head->buf));
11738 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
11740 item = nghttp2_session_get_next_ob_item(session);
11741 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
11743 CU_ASSERT(0 == nghttp2_session_send(session));
11745 nghttp2_bufs_reset(&bufs);
11747 /* non-final HEADERS followed by empty DATA (without END_STREAM) is
11749 open_sent_stream2(session, 5, NGHTTP2_STREAM_OPENING);
11751 rv = pack_headers(&bufs, &deflater, 5, NGHTTP2_FLAG_END_HEADERS,
11752 nonfinal_resnv, ARRLEN(nonfinal_resnv), mem);
11753 CU_ASSERT(0 == rv);
11755 nghttp2_frame_hd_init(&hd, 0, NGHTTP2_DATA, NGHTTP2_FLAG_NONE, 5);
11756 nghttp2_frame_pack_frame_hd(bufs.head->buf.last, &hd);
11757 bufs.head->buf.last += NGHTTP2_FRAME_HDLEN;
11759 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11760 nghttp2_buf_len(&bufs.head->buf));
11762 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
11764 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
11766 nghttp2_bufs_reset(&bufs);
11768 /* non-final HEADERS followed by empty DATA (with END_STREAM) is
11770 open_sent_stream2(session, 7, NGHTTP2_STREAM_OPENING);
11772 rv = pack_headers(&bufs, &deflater, 7, NGHTTP2_FLAG_END_HEADERS,
11773 nonfinal_resnv, ARRLEN(nonfinal_resnv), mem);
11774 CU_ASSERT(0 == rv);
11776 nghttp2_frame_hd_init(&hd, 0, NGHTTP2_DATA, NGHTTP2_FLAG_END_STREAM, 7);
11777 nghttp2_frame_pack_frame_hd(bufs.head->buf.last, &hd);
11778 bufs.head->buf.last += NGHTTP2_FRAME_HDLEN;
11780 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11781 nghttp2_buf_len(&bufs.head->buf));
11783 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
11785 item = nghttp2_session_get_next_ob_item(session);
11787 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
11789 CU_ASSERT(0 == nghttp2_session_send(session));
11791 nghttp2_bufs_reset(&bufs);
11793 /* non-final HEADERS followed by final HEADERS is OK */
11794 open_sent_stream2(session, 9, NGHTTP2_STREAM_OPENING);
11796 rv = pack_headers(&bufs, &deflater, 9, NGHTTP2_FLAG_END_HEADERS,
11797 nonfinal_resnv, ARRLEN(nonfinal_resnv), mem);
11798 CU_ASSERT(0 == rv);
11800 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11801 nghttp2_buf_len(&bufs.head->buf));
11803 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
11805 nghttp2_bufs_reset(&bufs);
11807 rv = pack_headers(&bufs, &deflater, 9, NGHTTP2_FLAG_END_HEADERS, resnv,
11808 ARRLEN(resnv), mem);
11809 CU_ASSERT(0 == rv);
11811 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11812 nghttp2_buf_len(&bufs.head->buf));
11814 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
11816 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
11818 nghttp2_bufs_reset(&bufs);
11820 nghttp2_hd_deflate_free(&deflater);
11822 nghttp2_session_del(session);
11824 nghttp2_bufs_free(&bufs);
11827 void test_nghttp2_http_trailer_headers(void) {
11828 nghttp2_session *session;
11829 nghttp2_session_callbacks callbacks;
11830 nghttp2_hd_deflater deflater;
11834 const nghttp2_nv trailer_reqnv[] = {
11835 MAKE_NV("foo", "bar"),
11837 nghttp2_outbound_item *item;
11839 mem = nghttp2_mem_default();
11840 frame_pack_bufs_init(&bufs);
11842 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
11843 callbacks.send_callback = null_send_callback;
11845 nghttp2_session_server_new(&session, &callbacks, NULL);
11847 nghttp2_hd_deflate_init(&deflater, mem);
11849 /* good trailer header */
11850 rv = pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, reqnv,
11851 ARRLEN(reqnv), mem);
11852 CU_ASSERT(0 == rv);
11854 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11855 nghttp2_buf_len(&bufs.head->buf));
11857 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
11859 nghttp2_bufs_reset(&bufs);
11861 rv = pack_headers(&bufs, &deflater, 1,
11862 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM,
11863 trailer_reqnv, ARRLEN(trailer_reqnv), mem);
11864 CU_ASSERT(0 == rv);
11866 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11867 nghttp2_buf_len(&bufs.head->buf));
11869 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
11871 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
11873 nghttp2_bufs_reset(&bufs);
11875 /* trailer header without END_STREAM is illegal */
11876 rv = pack_headers(&bufs, &deflater, 3, NGHTTP2_FLAG_END_HEADERS, reqnv,
11877 ARRLEN(reqnv), mem);
11878 CU_ASSERT(0 == rv);
11880 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11881 nghttp2_buf_len(&bufs.head->buf));
11883 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
11885 nghttp2_bufs_reset(&bufs);
11887 rv = pack_headers(&bufs, &deflater, 3, NGHTTP2_FLAG_END_HEADERS,
11888 trailer_reqnv, ARRLEN(trailer_reqnv), mem);
11889 CU_ASSERT(0 == rv);
11891 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11892 nghttp2_buf_len(&bufs.head->buf));
11894 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
11896 item = nghttp2_session_get_next_ob_item(session);
11898 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
11900 CU_ASSERT(0 == nghttp2_session_send(session));
11902 nghttp2_bufs_reset(&bufs);
11904 /* trailer header including pseudo header field is illegal */
11905 rv = pack_headers(&bufs, &deflater, 5, NGHTTP2_FLAG_END_HEADERS, reqnv,
11906 ARRLEN(reqnv), mem);
11907 CU_ASSERT(0 == rv);
11909 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11910 nghttp2_buf_len(&bufs.head->buf));
11912 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
11914 nghttp2_bufs_reset(&bufs);
11916 rv = pack_headers(&bufs, &deflater, 5, NGHTTP2_FLAG_END_HEADERS, reqnv,
11917 ARRLEN(reqnv), mem);
11918 CU_ASSERT(0 == rv);
11920 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11921 nghttp2_buf_len(&bufs.head->buf));
11923 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
11925 item = nghttp2_session_get_next_ob_item(session);
11927 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
11929 CU_ASSERT(0 == nghttp2_session_send(session));
11931 nghttp2_bufs_reset(&bufs);
11933 nghttp2_hd_deflate_free(&deflater);
11935 nghttp2_session_del(session);
11937 nghttp2_bufs_free(&bufs);
11940 void test_nghttp2_http_ignore_regular_header(void) {
11941 nghttp2_session *session;
11942 nghttp2_session_callbacks callbacks;
11943 nghttp2_hd_deflater deflater;
11948 const nghttp2_nv bad_reqnv[] = {
11949 MAKE_NV(":authority", "localhost"),
11950 MAKE_NV(":scheme", "https"),
11951 MAKE_NV(":path", "/"),
11952 MAKE_NV(":method", "GET"),
11953 MAKE_NV("foo", "\x0zzz"),
11954 MAKE_NV("bar", "buzz"),
11956 const nghttp2_nv bad_ansnv[] = {
11957 MAKE_NV(":authority", "localhost"), MAKE_NV(":scheme", "https"),
11958 MAKE_NV(":path", "/"), MAKE_NV(":method", "GET"), MAKE_NV("bar", "buzz")};
11961 nghttp2_outbound_item *item;
11963 mem = nghttp2_mem_default();
11964 frame_pack_bufs_init(&bufs);
11966 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
11967 callbacks.send_callback = null_send_callback;
11968 callbacks.on_header_callback = pause_on_header_callback;
11970 nghttp2_session_server_new(&session, &callbacks, &ud);
11971 nghttp2_hd_deflate_init(&deflater, mem);
11973 rv = pack_headers(&bufs, &deflater, 1,
11974 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM,
11975 bad_reqnv, ARRLEN(bad_reqnv), mem);
11977 CU_ASSERT_FATAL(0 == rv);
11979 nghttp2_hd_deflate_free(&deflater);
11983 for (i = 0; i < 4; ++i) {
11984 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos + proclen,
11985 nghttp2_buf_len(&bufs.head->buf) - proclen);
11986 CU_ASSERT_FATAL(rv > 0);
11987 proclen += (size_t)rv;
11988 CU_ASSERT(nghttp2_nv_equal(&bad_ansnv[i], &ud.nv));
11991 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos + proclen,
11992 nghttp2_buf_len(&bufs.head->buf) - proclen);
11993 CU_ASSERT_FATAL(rv > 0);
11994 /* Without on_invalid_frame_recv_callback, bad header causes stream
11996 item = nghttp2_session_get_next_ob_item(session);
11998 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
12000 proclen += (size_t)rv;
12002 CU_ASSERT(nghttp2_buf_len(&bufs.head->buf) == proclen);
12004 nghttp2_session_del(session);
12006 /* use on_invalid_header_callback */
12007 callbacks.on_invalid_header_callback = pause_on_invalid_header_callback;
12009 nghttp2_session_server_new(&session, &callbacks, &ud);
12013 ud.invalid_header_cb_called = 0;
12015 for (i = 0; i < 4; ++i) {
12016 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos + proclen,
12017 nghttp2_buf_len(&bufs.head->buf) - proclen);
12018 CU_ASSERT_FATAL(rv > 0);
12019 proclen += (size_t)rv;
12020 CU_ASSERT(nghttp2_nv_equal(&bad_ansnv[i], &ud.nv));
12023 CU_ASSERT(0 == ud.invalid_header_cb_called);
12025 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos + proclen,
12026 nghttp2_buf_len(&bufs.head->buf) - proclen);
12028 CU_ASSERT_FATAL(rv > 0);
12029 CU_ASSERT(1 == ud.invalid_header_cb_called);
12030 CU_ASSERT(nghttp2_nv_equal(&bad_reqnv[4], &ud.nv));
12032 proclen += (size_t)rv;
12034 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos + proclen,
12035 nghttp2_buf_len(&bufs.head->buf) - proclen);
12038 CU_ASSERT(nghttp2_nv_equal(&bad_ansnv[4], &ud.nv));
12040 nghttp2_session_del(session);
12042 /* make sure that we can reset stream from
12043 on_invalid_header_callback */
12044 callbacks.on_header_callback = on_header_callback;
12045 callbacks.on_invalid_header_callback = reset_on_invalid_header_callback;
12047 nghttp2_session_server_new(&session, &callbacks, &ud);
12049 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
12050 nghttp2_buf_len(&bufs.head->buf));
12052 CU_ASSERT(rv == (ssize_t)nghttp2_buf_len(&bufs.head->buf));
12054 item = nghttp2_session_get_next_ob_item(session);
12056 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
12057 CU_ASSERT(1 == item->frame.hd.stream_id);
12059 nghttp2_session_del(session);
12060 nghttp2_bufs_free(&bufs);
12063 void test_nghttp2_http_ignore_content_length(void) {
12064 nghttp2_session *session;
12065 nghttp2_session_callbacks callbacks;
12066 nghttp2_hd_deflater deflater;
12070 const nghttp2_nv cl_resnv[] = {MAKE_NV(":status", "304"),
12071 MAKE_NV("content-length", "20")};
12072 const nghttp2_nv conn_reqnv[] = {MAKE_NV(":authority", "localhost"),
12073 MAKE_NV(":method", "CONNECT"),
12074 MAKE_NV("content-length", "999999")};
12075 const nghttp2_nv conn_cl_resnv[] = {MAKE_NV(":status", "200"),
12076 MAKE_NV("content-length", "0")};
12077 nghttp2_stream *stream;
12079 mem = nghttp2_mem_default();
12080 frame_pack_bufs_init(&bufs);
12082 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
12083 callbacks.send_callback = null_send_callback;
12085 nghttp2_session_client_new(&session, &callbacks, NULL);
12087 nghttp2_hd_deflate_init(&deflater, mem);
12089 /* If status 304, content-length must be ignored */
12090 open_sent_stream2(session, 1, NGHTTP2_STREAM_OPENING);
12092 rv = pack_headers(&bufs, &deflater, 1,
12093 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM,
12094 cl_resnv, ARRLEN(cl_resnv), mem);
12095 CU_ASSERT(0 == rv);
12097 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
12098 nghttp2_buf_len(&bufs.head->buf));
12100 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
12102 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
12104 nghttp2_bufs_reset(&bufs);
12106 /* Content-Length in 200 response to CONNECT is ignored */
12107 stream = open_sent_stream2(session, 3, NGHTTP2_STREAM_OPENING);
12108 stream->http_flags |= NGHTTP2_HTTP_FLAG_METH_CONNECT;
12110 rv = pack_headers(&bufs, &deflater, 3, NGHTTP2_FLAG_END_HEADERS,
12111 conn_cl_resnv, ARRLEN(conn_cl_resnv), mem);
12112 CU_ASSERT(0 == rv);
12114 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
12115 nghttp2_buf_len(&bufs.head->buf));
12117 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
12119 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
12120 CU_ASSERT(-1 == stream->content_length);
12122 nghttp2_bufs_reset(&bufs);
12124 nghttp2_hd_deflate_free(&deflater);
12125 nghttp2_session_del(session);
12127 /* If request method is CONNECT, content-length must be ignored */
12128 nghttp2_session_server_new(&session, &callbacks, NULL);
12130 nghttp2_hd_deflate_init(&deflater, mem);
12132 rv = pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, conn_reqnv,
12133 ARRLEN(conn_reqnv), mem);
12135 CU_ASSERT(0 == rv);
12137 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
12138 nghttp2_buf_len(&bufs.head->buf));
12140 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
12142 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
12144 stream = nghttp2_session_get_stream(session, 1);
12146 CU_ASSERT(-1 == stream->content_length);
12147 CU_ASSERT((stream->http_flags & NGHTTP2_HTTP_FLAG_METH_CONNECT) > 0);
12149 nghttp2_hd_deflate_free(&deflater);
12150 nghttp2_session_del(session);
12151 nghttp2_bufs_free(&bufs);
12154 void test_nghttp2_http_record_request_method(void) {
12155 nghttp2_session *session;
12156 nghttp2_session_callbacks callbacks;
12157 const nghttp2_nv conn_reqnv[] = {MAKE_NV(":method", "CONNECT"),
12158 MAKE_NV(":authority", "localhost")};
12159 const nghttp2_nv conn_resnv[] = {MAKE_NV(":status", "200"),
12160 MAKE_NV("content-length", "9999")};
12161 nghttp2_stream *stream;
12164 nghttp2_hd_deflater deflater;
12166 nghttp2_outbound_item *item;
12168 mem = nghttp2_mem_default();
12169 frame_pack_bufs_init(&bufs);
12171 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
12172 callbacks.send_callback = null_send_callback;
12174 nghttp2_session_client_new(&session, &callbacks, NULL);
12176 nghttp2_hd_deflate_init(&deflater, mem);
12178 CU_ASSERT(1 == nghttp2_submit_request(session, NULL, conn_reqnv,
12179 ARRLEN(conn_reqnv), NULL, NULL));
12181 CU_ASSERT(0 == nghttp2_session_send(session));
12183 stream = nghttp2_session_get_stream(session, 1);
12185 CU_ASSERT(NGHTTP2_HTTP_FLAG_METH_CONNECT == stream->http_flags);
12187 rv = pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, conn_resnv,
12188 ARRLEN(conn_resnv), mem);
12189 CU_ASSERT(0 == rv);
12191 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
12192 nghttp2_buf_len(&bufs.head->buf));
12194 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
12196 CU_ASSERT((NGHTTP2_HTTP_FLAG_METH_CONNECT & stream->http_flags) > 0);
12197 CU_ASSERT(-1 == stream->content_length);
12199 /* content-length is ignored in 200 response to a CONNECT request */
12200 item = nghttp2_session_get_next_ob_item(session);
12202 CU_ASSERT(NULL == item);
12204 nghttp2_hd_deflate_free(&deflater);
12205 nghttp2_session_del(session);
12206 nghttp2_bufs_free(&bufs);
12209 void test_nghttp2_http_push_promise(void) {
12210 nghttp2_session *session;
12211 nghttp2_session_callbacks callbacks;
12212 nghttp2_hd_deflater deflater;
12216 nghttp2_stream *stream;
12217 const nghttp2_nv bad_reqnv[] = {MAKE_NV(":method", "GET")};
12218 nghttp2_outbound_item *item;
12220 mem = nghttp2_mem_default();
12221 frame_pack_bufs_init(&bufs);
12223 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
12224 callbacks.send_callback = null_send_callback;
12226 /* good PUSH_PROMISE case */
12227 nghttp2_session_client_new(&session, &callbacks, NULL);
12229 nghttp2_hd_deflate_init(&deflater, mem);
12231 open_sent_stream2(session, 1, NGHTTP2_STREAM_OPENING);
12233 rv = pack_push_promise(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, 2,
12234 reqnv, ARRLEN(reqnv), mem);
12235 CU_ASSERT(0 == rv);
12237 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
12238 nghttp2_buf_len(&bufs.head->buf));
12240 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
12242 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
12244 stream = nghttp2_session_get_stream(session, 2);
12245 CU_ASSERT(NULL != stream);
12247 nghttp2_bufs_reset(&bufs);
12249 rv = pack_headers(&bufs, &deflater, 2, NGHTTP2_FLAG_END_HEADERS, resnv,
12250 ARRLEN(resnv), mem);
12252 CU_ASSERT(0 == rv);
12254 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
12255 nghttp2_buf_len(&bufs.head->buf));
12257 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
12259 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
12261 CU_ASSERT(200 == stream->status_code);
12263 nghttp2_bufs_reset(&bufs);
12265 /* PUSH_PROMISE lacks mandatory header */
12266 rv = pack_push_promise(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, 4,
12267 bad_reqnv, ARRLEN(bad_reqnv), mem);
12269 CU_ASSERT(0 == rv);
12271 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
12272 nghttp2_buf_len(&bufs.head->buf));
12274 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
12276 item = nghttp2_session_get_next_ob_item(session);
12278 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
12279 CU_ASSERT(4 == item->frame.hd.stream_id);
12281 nghttp2_bufs_reset(&bufs);
12283 nghttp2_hd_deflate_free(&deflater);
12284 nghttp2_session_del(session);
12285 nghttp2_bufs_free(&bufs);
12288 void test_nghttp2_http_head_method_upgrade_workaround(void) {
12289 nghttp2_session *session;
12290 nghttp2_session_callbacks callbacks;
12291 const nghttp2_nv cl_resnv[] = {MAKE_NV(":status", "200"),
12292 MAKE_NV("content-length", "1000000007")};
12294 nghttp2_hd_deflater deflater;
12297 nghttp2_stream *stream;
12299 mem = nghttp2_mem_default();
12300 frame_pack_bufs_init(&bufs);
12302 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
12303 callbacks.send_callback = null_send_callback;
12305 nghttp2_session_client_new(&session, &callbacks, NULL);
12307 nghttp2_hd_deflate_init(&deflater, mem);
12309 nghttp2_session_upgrade(session, NULL, 0, NULL);
12311 rv = pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, cl_resnv,
12312 ARRLEN(cl_resnv), mem);
12314 CU_ASSERT(0 == rv);
12316 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
12317 nghttp2_buf_len(&bufs.head->buf));
12319 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
12321 stream = nghttp2_session_get_stream(session, 1);
12323 CU_ASSERT(-1 == stream->content_length);
12325 nghttp2_hd_deflate_free(&deflater);
12326 nghttp2_session_del(session);
12327 nghttp2_bufs_free(&bufs);