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_session_open_stream(void) {
6402 nghttp2_session *session;
6403 nghttp2_session_callbacks callbacks;
6404 nghttp2_stream *stream;
6405 nghttp2_priority_spec pri_spec;
6407 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6408 nghttp2_session_server_new(&session, &callbacks, NULL);
6410 nghttp2_priority_spec_init(&pri_spec, 0, 245, 0);
6412 stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
6413 &pri_spec, NGHTTP2_STREAM_OPENED, NULL);
6414 CU_ASSERT(1 == session->num_incoming_streams);
6415 CU_ASSERT(0 == session->num_outgoing_streams);
6416 CU_ASSERT(NGHTTP2_STREAM_OPENED == stream->state);
6417 CU_ASSERT(245 == stream->weight);
6418 CU_ASSERT(&session->root == stream->dep_prev);
6419 CU_ASSERT(NGHTTP2_SHUT_NONE == stream->shut_flags);
6421 stream = nghttp2_session_open_stream(session, 2, NGHTTP2_STREAM_FLAG_NONE,
6423 NGHTTP2_STREAM_OPENING, NULL);
6424 CU_ASSERT(1 == session->num_incoming_streams);
6425 CU_ASSERT(1 == session->num_outgoing_streams);
6426 CU_ASSERT(&session->root == stream->dep_prev);
6427 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == stream->weight);
6428 CU_ASSERT(NGHTTP2_SHUT_NONE == stream->shut_flags);
6430 stream = nghttp2_session_open_stream(session, 4, NGHTTP2_STREAM_FLAG_NONE,
6432 NGHTTP2_STREAM_RESERVED, NULL);
6433 CU_ASSERT(1 == session->num_incoming_streams);
6434 CU_ASSERT(1 == session->num_outgoing_streams);
6435 CU_ASSERT(&session->root == stream->dep_prev);
6436 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == stream->weight);
6437 CU_ASSERT(NGHTTP2_SHUT_RD == stream->shut_flags);
6439 nghttp2_priority_spec_init(&pri_spec, 1, 17, 1);
6441 stream = nghttp2_session_open_stream(session, 3, NGHTTP2_STREAM_FLAG_NONE,
6442 &pri_spec, NGHTTP2_STREAM_OPENED, NULL);
6443 CU_ASSERT(17 == stream->weight);
6444 CU_ASSERT(1 == stream->dep_prev->stream_id);
6446 /* Dependency to idle stream */
6447 nghttp2_priority_spec_init(&pri_spec, 1000000007, 240, 1);
6449 stream = nghttp2_session_open_stream(session, 5, NGHTTP2_STREAM_FLAG_NONE,
6450 &pri_spec, NGHTTP2_STREAM_OPENED, NULL);
6451 CU_ASSERT(240 == stream->weight);
6452 CU_ASSERT(1000000007 == stream->dep_prev->stream_id);
6454 stream = nghttp2_session_get_stream_raw(session, 1000000007);
6456 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == stream->weight);
6457 CU_ASSERT(&session->root == stream->dep_prev);
6459 /* Dependency to closed stream which is not in dependency tree */
6460 session->last_recv_stream_id = 7;
6462 nghttp2_priority_spec_init(&pri_spec, 7, 10, 0);
6464 stream = nghttp2_session_open_stream(session, 9, NGHTTP2_FLAG_NONE, &pri_spec,
6465 NGHTTP2_STREAM_OPENED, NULL);
6467 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == stream->weight);
6468 CU_ASSERT(&session->root == stream->dep_prev);
6470 nghttp2_session_del(session);
6472 nghttp2_session_client_new(&session, &callbacks, NULL);
6473 stream = nghttp2_session_open_stream(session, 4, NGHTTP2_STREAM_FLAG_NONE,
6475 NGHTTP2_STREAM_RESERVED, NULL);
6476 CU_ASSERT(0 == session->num_incoming_streams);
6477 CU_ASSERT(0 == session->num_outgoing_streams);
6478 CU_ASSERT(&session->root == stream->dep_prev);
6479 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == stream->weight);
6480 CU_ASSERT(NGHTTP2_SHUT_WR == stream->shut_flags);
6482 nghttp2_session_del(session);
6485 void test_nghttp2_session_open_stream_with_idle_stream_dep(void) {
6486 nghttp2_session *session;
6487 nghttp2_session_callbacks callbacks;
6488 nghttp2_stream *stream;
6489 nghttp2_priority_spec pri_spec;
6491 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6492 nghttp2_session_server_new(&session, &callbacks, NULL);
6494 /* Dependency to idle stream */
6495 nghttp2_priority_spec_init(&pri_spec, 101, 245, 0);
6497 stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
6498 &pri_spec, NGHTTP2_STREAM_OPENED, NULL);
6500 CU_ASSERT(245 == stream->weight);
6501 CU_ASSERT(101 == stream->dep_prev->stream_id);
6503 stream = nghttp2_session_get_stream_raw(session, 101);
6505 CU_ASSERT(NGHTTP2_STREAM_IDLE == stream->state);
6506 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == stream->weight);
6508 nghttp2_priority_spec_init(&pri_spec, 211, 1, 0);
6510 /* stream 101 was already created as idle. */
6511 stream = nghttp2_session_open_stream(session, 101, NGHTTP2_STREAM_FLAG_NONE,
6512 &pri_spec, NGHTTP2_STREAM_OPENED, NULL);
6514 CU_ASSERT(1 == stream->weight);
6515 CU_ASSERT(211 == stream->dep_prev->stream_id);
6517 stream = nghttp2_session_get_stream_raw(session, 211);
6519 CU_ASSERT(NGHTTP2_STREAM_IDLE == stream->state);
6520 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == stream->weight);
6522 nghttp2_session_del(session);
6525 void test_nghttp2_session_get_next_ob_item(void) {
6526 nghttp2_session *session;
6527 nghttp2_session_callbacks callbacks;
6528 nghttp2_priority_spec pri_spec;
6530 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6531 callbacks.send_callback = null_send_callback;
6533 nghttp2_session_client_new(&session, &callbacks, NULL);
6534 session->remote_settings.max_concurrent_streams = 2;
6536 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
6537 nghttp2_submit_ping(session, NGHTTP2_FLAG_NONE, NULL);
6538 CU_ASSERT(NGHTTP2_PING ==
6539 nghttp2_session_get_next_ob_item(session)->frame.hd.type);
6541 CU_ASSERT(1 == nghttp2_submit_request(session, NULL, NULL, 0, NULL, NULL));
6542 CU_ASSERT(NGHTTP2_PING ==
6543 nghttp2_session_get_next_ob_item(session)->frame.hd.type);
6545 CU_ASSERT(0 == nghttp2_session_send(session));
6546 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
6548 /* Incoming stream does not affect the number of outgoing max
6549 concurrent streams. */
6550 open_recv_stream(session, 2);
6552 nghttp2_priority_spec_init(&pri_spec, 0, NGHTTP2_MAX_WEIGHT, 0);
6555 nghttp2_submit_request(session, &pri_spec, NULL, 0, NULL, NULL));
6556 CU_ASSERT(NGHTTP2_HEADERS ==
6557 nghttp2_session_get_next_ob_item(session)->frame.hd.type);
6558 CU_ASSERT(0 == nghttp2_session_send(session));
6561 nghttp2_submit_request(session, &pri_spec, NULL, 0, NULL, NULL));
6562 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
6564 session->remote_settings.max_concurrent_streams = 3;
6566 CU_ASSERT(NGHTTP2_HEADERS ==
6567 nghttp2_session_get_next_ob_item(session)->frame.hd.type);
6569 nghttp2_session_del(session);
6571 /* Check that push reply HEADERS are queued into ob_ss_pq */
6572 nghttp2_session_server_new(&session, &callbacks, NULL);
6573 session->remote_settings.max_concurrent_streams = 0;
6574 open_sent_stream2(session, 2, NGHTTP2_STREAM_RESERVED);
6575 CU_ASSERT(0 == nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, 2,
6576 NULL, NULL, 0, NULL));
6577 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
6578 CU_ASSERT(1 == nghttp2_outbound_queue_size(&session->ob_syn));
6579 nghttp2_session_del(session);
6582 void test_nghttp2_session_pop_next_ob_item(void) {
6583 nghttp2_session *session;
6584 nghttp2_session_callbacks callbacks;
6585 nghttp2_outbound_item *item;
6586 nghttp2_priority_spec pri_spec;
6589 mem = nghttp2_mem_default();
6590 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6591 callbacks.send_callback = null_send_callback;
6593 nghttp2_session_client_new(&session, &callbacks, NULL);
6594 session->remote_settings.max_concurrent_streams = 1;
6596 CU_ASSERT(NULL == nghttp2_session_pop_next_ob_item(session));
6598 nghttp2_submit_ping(session, NGHTTP2_FLAG_NONE, NULL);
6600 nghttp2_priority_spec_init(&pri_spec, 0, 254, 0);
6602 nghttp2_submit_request(session, &pri_spec, NULL, 0, NULL, NULL);
6604 item = nghttp2_session_pop_next_ob_item(session);
6605 CU_ASSERT(NGHTTP2_PING == item->frame.hd.type);
6606 nghttp2_outbound_item_free(item, mem);
6607 mem->free(item, NULL);
6609 item = nghttp2_session_pop_next_ob_item(session);
6610 CU_ASSERT(NGHTTP2_HEADERS == item->frame.hd.type);
6611 nghttp2_outbound_item_free(item, mem);
6612 mem->free(item, NULL);
6614 CU_ASSERT(NULL == nghttp2_session_pop_next_ob_item(session));
6616 /* Incoming stream does not affect the number of outgoing max
6617 concurrent streams. */
6618 open_recv_stream(session, 4);
6619 /* In-flight outgoing stream */
6620 open_sent_stream(session, 1);
6622 nghttp2_priority_spec_init(&pri_spec, 0, NGHTTP2_MAX_WEIGHT, 0);
6624 nghttp2_submit_request(session, &pri_spec, NULL, 0, NULL, NULL);
6626 CU_ASSERT(NULL == nghttp2_session_pop_next_ob_item(session));
6628 session->remote_settings.max_concurrent_streams = 2;
6630 item = nghttp2_session_pop_next_ob_item(session);
6631 CU_ASSERT(NGHTTP2_HEADERS == item->frame.hd.type);
6632 nghttp2_outbound_item_free(item, mem);
6633 mem->free(item, NULL);
6635 nghttp2_session_del(session);
6637 /* Check that push reply HEADERS are queued into ob_ss_pq */
6638 nghttp2_session_server_new(&session, &callbacks, NULL);
6639 session->remote_settings.max_concurrent_streams = 0;
6640 open_sent_stream2(session, 2, NGHTTP2_STREAM_RESERVED);
6641 CU_ASSERT(0 == nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, 2,
6642 NULL, NULL, 0, NULL));
6643 CU_ASSERT(NULL == nghttp2_session_pop_next_ob_item(session));
6644 CU_ASSERT(1 == nghttp2_outbound_queue_size(&session->ob_syn));
6645 nghttp2_session_del(session);
6648 void test_nghttp2_session_reply_fail(void) {
6649 nghttp2_session *session;
6650 nghttp2_session_callbacks callbacks;
6651 nghttp2_data_provider data_prd;
6654 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6655 callbacks.send_callback = fail_send_callback;
6657 data_prd.read_callback = fixed_length_data_source_read_callback;
6658 ud.data_source_length = 4 * 1024;
6659 CU_ASSERT(0 == nghttp2_session_server_new(&session, &callbacks, &ud));
6660 open_recv_stream2(session, 1, NGHTTP2_STREAM_OPENING);
6661 CU_ASSERT(0 == nghttp2_submit_response(session, 1, NULL, 0, &data_prd));
6662 CU_ASSERT(NGHTTP2_ERR_CALLBACK_FAILURE == nghttp2_session_send(session));
6663 nghttp2_session_del(session);
6666 void test_nghttp2_session_max_concurrent_streams(void) {
6667 nghttp2_session *session;
6668 nghttp2_session_callbacks callbacks;
6669 nghttp2_frame frame;
6670 nghttp2_outbound_item *item;
6673 mem = nghttp2_mem_default();
6674 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6675 callbacks.send_callback = null_send_callback;
6677 nghttp2_session_server_new(&session, &callbacks, NULL);
6678 open_recv_stream(session, 1);
6680 /* Check un-ACKed SETTINGS_MAX_CONCURRENT_STREAMS */
6681 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 3,
6682 NGHTTP2_HCAT_HEADERS, NULL, NULL, 0);
6683 session->pending_local_max_concurrent_stream = 1;
6685 CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
6686 nghttp2_session_on_request_headers_received(session, &frame));
6688 item = nghttp2_outbound_queue_top(&session->ob_reg);
6689 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
6690 CU_ASSERT(NGHTTP2_REFUSED_STREAM == item->frame.rst_stream.error_code);
6692 CU_ASSERT(0 == nghttp2_session_send(session));
6694 /* Check ACKed SETTINGS_MAX_CONCURRENT_STREAMS */
6695 session->local_settings.max_concurrent_streams = 1;
6696 frame.hd.stream_id = 5;
6698 CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
6699 nghttp2_session_on_request_headers_received(session, &frame));
6701 item = nghttp2_outbound_queue_top(&session->ob_reg);
6702 CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
6703 CU_ASSERT(NGHTTP2_PROTOCOL_ERROR == item->frame.goaway.error_code);
6705 nghttp2_frame_headers_free(&frame.headers, mem);
6706 nghttp2_session_del(session);
6709 void test_nghttp2_session_stop_data_with_rst_stream(void) {
6710 nghttp2_session *session;
6711 nghttp2_session_callbacks callbacks;
6713 nghttp2_data_provider data_prd;
6714 nghttp2_frame frame;
6716 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6717 callbacks.on_frame_send_callback = on_frame_send_callback;
6718 callbacks.send_callback = block_count_send_callback;
6719 data_prd.read_callback = fixed_length_data_source_read_callback;
6721 ud.frame_send_cb_called = 0;
6722 ud.data_source_length = NGHTTP2_DATA_PAYLOADLEN * 4;
6724 nghttp2_session_server_new(&session, &callbacks, &ud);
6725 open_recv_stream2(session, 1, NGHTTP2_STREAM_OPENING);
6726 nghttp2_submit_response(session, 1, NULL, 0, &data_prd);
6729 /* Sends response HEADERS + DATA[0] */
6730 CU_ASSERT(0 == nghttp2_session_send(session));
6731 CU_ASSERT(NGHTTP2_DATA == ud.sent_frame_type);
6732 /* data for DATA[1] is read from data_prd but it is not sent */
6733 CU_ASSERT(ud.data_source_length == NGHTTP2_DATA_PAYLOADLEN * 2);
6735 nghttp2_frame_rst_stream_init(&frame.rst_stream, 1, NGHTTP2_CANCEL);
6736 CU_ASSERT(0 == nghttp2_session_on_rst_stream_received(session, &frame));
6737 nghttp2_frame_rst_stream_free(&frame.rst_stream);
6739 /* Big enough number to send all DATA frames potentially. */
6740 ud.block_count = 100;
6741 /* Nothing will be sent in the following call. */
6742 CU_ASSERT(0 == nghttp2_session_send(session));
6743 /* With RST_STREAM, stream is canceled and further DATA on that
6744 stream are not sent. */
6745 CU_ASSERT(ud.data_source_length == NGHTTP2_DATA_PAYLOADLEN * 2);
6747 CU_ASSERT(NULL == nghttp2_session_get_stream(session, 1));
6749 nghttp2_session_del(session);
6752 void test_nghttp2_session_defer_data(void) {
6753 nghttp2_session *session;
6754 nghttp2_session_callbacks callbacks;
6756 nghttp2_data_provider data_prd;
6757 nghttp2_outbound_item *item;
6758 nghttp2_stream *stream;
6760 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6761 callbacks.on_frame_send_callback = on_frame_send_callback;
6762 callbacks.send_callback = block_count_send_callback;
6763 data_prd.read_callback = defer_data_source_read_callback;
6765 ud.frame_send_cb_called = 0;
6766 ud.data_source_length = NGHTTP2_DATA_PAYLOADLEN * 4;
6768 nghttp2_session_server_new(&session, &callbacks, &ud);
6769 stream = open_recv_stream2(session, 1, NGHTTP2_STREAM_OPENING);
6771 session->remote_window_size = 1 << 20;
6772 stream->remote_window_size = 1 << 20;
6774 nghttp2_submit_response(session, 1, NULL, 0, &data_prd);
6777 /* Sends HEADERS reply */
6778 CU_ASSERT(0 == nghttp2_session_send(session));
6779 CU_ASSERT(NGHTTP2_HEADERS == ud.sent_frame_type);
6780 /* No data is read */
6781 CU_ASSERT(ud.data_source_length == NGHTTP2_DATA_PAYLOADLEN * 4);
6784 nghttp2_submit_ping(session, NGHTTP2_FLAG_NONE, NULL);
6786 CU_ASSERT(0 == nghttp2_session_send(session));
6787 CU_ASSERT(NGHTTP2_PING == ud.sent_frame_type);
6789 /* Resume deferred DATA */
6790 CU_ASSERT(0 == nghttp2_session_resume_data(session, 1));
6791 item = stream->item;
6792 item->aux_data.data.data_prd.read_callback =
6793 fixed_length_data_source_read_callback;
6795 /* Reads 2 DATA chunks */
6796 CU_ASSERT(0 == nghttp2_session_send(session));
6797 CU_ASSERT(ud.data_source_length == NGHTTP2_DATA_PAYLOADLEN * 2);
6799 /* Deferred again */
6800 item->aux_data.data.data_prd.read_callback = defer_data_source_read_callback;
6801 /* This is needed since 16KiB block is already read and waiting to be
6802 sent. No read_callback invocation. */
6804 CU_ASSERT(0 == nghttp2_session_send(session));
6805 CU_ASSERT(ud.data_source_length == NGHTTP2_DATA_PAYLOADLEN * 2);
6807 /* Resume deferred DATA */
6808 CU_ASSERT(0 == nghttp2_session_resume_data(session, 1));
6809 item->aux_data.data.data_prd.read_callback =
6810 fixed_length_data_source_read_callback;
6812 /* Reads 2 16KiB blocks */
6813 CU_ASSERT(0 == nghttp2_session_send(session));
6814 CU_ASSERT(ud.data_source_length == 0);
6816 nghttp2_session_del(session);
6819 void test_nghttp2_session_flow_control(void) {
6820 nghttp2_session *session;
6821 nghttp2_session_callbacks callbacks;
6823 nghttp2_data_provider data_prd;
6824 nghttp2_frame frame;
6825 nghttp2_stream *stream;
6826 int32_t new_initial_window_size;
6827 nghttp2_settings_entry iv[1];
6828 nghttp2_frame settings_frame;
6831 mem = nghttp2_mem_default();
6832 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6833 callbacks.send_callback = fixed_bytes_send_callback;
6834 callbacks.on_frame_send_callback = on_frame_send_callback;
6835 data_prd.read_callback = fixed_length_data_source_read_callback;
6837 ud.frame_send_cb_called = 0;
6838 ud.data_source_length = 128 * 1024;
6839 /* Use smaller emission count so that we can check outbound flow
6840 control window calculation is correct. */
6841 ud.fixed_sendlen = 2 * 1024;
6843 /* Initial window size to 64KiB - 1*/
6844 nghttp2_session_client_new(&session, &callbacks, &ud);
6845 /* Change it to 64KiB for easy calculation */
6846 session->remote_window_size = 64 * 1024;
6847 session->remote_settings.initial_window_size = 64 * 1024;
6849 nghttp2_submit_request(session, NULL, NULL, 0, &data_prd, NULL);
6851 /* Sends 64KiB - 1 data */
6852 CU_ASSERT(0 == nghttp2_session_send(session));
6853 CU_ASSERT(64 * 1024 == ud.data_source_length);
6855 /* Back 32KiB in stream window */
6856 nghttp2_frame_window_update_init(&frame.window_update, NGHTTP2_FLAG_NONE, 1,
6858 nghttp2_session_on_window_update_received(session, &frame);
6860 /* Send nothing because of connection-level window */
6861 CU_ASSERT(0 == nghttp2_session_send(session));
6862 CU_ASSERT(64 * 1024 == ud.data_source_length);
6864 /* Back 32KiB in connection-level window */
6865 frame.hd.stream_id = 0;
6866 nghttp2_session_on_window_update_received(session, &frame);
6868 /* Sends another 32KiB data */
6869 CU_ASSERT(0 == nghttp2_session_send(session));
6870 CU_ASSERT(32 * 1024 == ud.data_source_length);
6872 stream = nghttp2_session_get_stream(session, 1);
6873 /* Change initial window size to 16KiB. The window_size becomes
6875 new_initial_window_size = 16 * 1024;
6876 stream->remote_window_size =
6877 new_initial_window_size -
6878 ((int32_t)session->remote_settings.initial_window_size -
6879 stream->remote_window_size);
6880 session->remote_settings.initial_window_size =
6881 (uint32_t)new_initial_window_size;
6882 CU_ASSERT(-48 * 1024 == stream->remote_window_size);
6884 /* Back 48KiB to stream window */
6885 frame.hd.stream_id = 1;
6886 frame.window_update.window_size_increment = 48 * 1024;
6887 nghttp2_session_on_window_update_received(session, &frame);
6889 /* Nothing is sent because window_size is 0 */
6890 CU_ASSERT(0 == nghttp2_session_send(session));
6891 CU_ASSERT(32 * 1024 == ud.data_source_length);
6893 /* Back 16KiB in stream window */
6894 frame.hd.stream_id = 1;
6895 frame.window_update.window_size_increment = 16 * 1024;
6896 nghttp2_session_on_window_update_received(session, &frame);
6898 /* Back 24KiB in connection-level window */
6899 frame.hd.stream_id = 0;
6900 frame.window_update.window_size_increment = 24 * 1024;
6901 nghttp2_session_on_window_update_received(session, &frame);
6903 /* Sends another 16KiB data */
6904 CU_ASSERT(0 == nghttp2_session_send(session));
6905 CU_ASSERT(16 * 1024 == ud.data_source_length);
6907 /* Increase initial window size to 32KiB */
6908 iv[0].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
6909 iv[0].value = 32 * 1024;
6911 nghttp2_frame_settings_init(&settings_frame.settings, NGHTTP2_FLAG_NONE,
6913 nghttp2_session_on_settings_received(session, &settings_frame, 1);
6914 nghttp2_frame_settings_free(&settings_frame.settings, mem);
6916 /* Sends another 8KiB data */
6917 CU_ASSERT(0 == nghttp2_session_send(session));
6918 CU_ASSERT(8 * 1024 == ud.data_source_length);
6920 /* Back 8KiB in connection-level window */
6921 frame.hd.stream_id = 0;
6922 frame.window_update.window_size_increment = 8 * 1024;
6923 nghttp2_session_on_window_update_received(session, &frame);
6925 /* Sends last 8KiB data */
6926 CU_ASSERT(0 == nghttp2_session_send(session));
6927 CU_ASSERT(0 == ud.data_source_length);
6928 CU_ASSERT(nghttp2_session_get_stream(session, 1)->shut_flags &
6931 nghttp2_frame_window_update_free(&frame.window_update);
6932 nghttp2_session_del(session);
6935 void test_nghttp2_session_flow_control_data_recv(void) {
6936 nghttp2_session *session;
6937 nghttp2_session_callbacks callbacks;
6938 uint8_t data[64 * 1024 + 16];
6939 nghttp2_frame_hd hd;
6940 nghttp2_outbound_item *item;
6941 nghttp2_stream *stream;
6943 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6944 callbacks.send_callback = null_send_callback;
6946 /* Initial window size to 64KiB - 1*/
6947 nghttp2_session_client_new(&session, &callbacks, NULL);
6949 stream = open_sent_stream(session, 1);
6951 nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_WR);
6953 session->local_window_size = NGHTTP2_MAX_PAYLOADLEN;
6954 stream->local_window_size = NGHTTP2_MAX_PAYLOADLEN;
6956 /* Create DATA frame */
6957 memset(data, 0, sizeof(data));
6958 nghttp2_frame_hd_init(&hd, NGHTTP2_MAX_PAYLOADLEN, NGHTTP2_DATA,
6959 NGHTTP2_FLAG_END_STREAM, 1);
6961 nghttp2_frame_pack_frame_hd(data, &hd);
6962 CU_ASSERT(NGHTTP2_MAX_PAYLOADLEN + NGHTTP2_FRAME_HDLEN ==
6963 nghttp2_session_mem_recv(
6964 session, data, NGHTTP2_MAX_PAYLOADLEN + NGHTTP2_FRAME_HDLEN));
6966 item = nghttp2_session_get_next_ob_item(session);
6967 /* Since this is the last frame, stream-level WINDOW_UPDATE is not
6968 issued, but connection-level is. */
6969 CU_ASSERT(NGHTTP2_WINDOW_UPDATE == item->frame.hd.type);
6970 CU_ASSERT(0 == item->frame.hd.stream_id);
6971 CU_ASSERT(NGHTTP2_MAX_PAYLOADLEN ==
6972 item->frame.window_update.window_size_increment);
6974 CU_ASSERT(0 == nghttp2_session_send(session));
6976 /* Receive DATA for closed stream. They are still subject to under
6977 connection-level flow control, since this situation arises when
6978 RST_STREAM is issued by the remote, but the local side keeps
6979 sending DATA frames. Without calculating connection-level window,
6980 the subsequent flow control gets confused. */
6981 CU_ASSERT(NGHTTP2_MAX_PAYLOADLEN + NGHTTP2_FRAME_HDLEN ==
6982 nghttp2_session_mem_recv(
6983 session, data, NGHTTP2_MAX_PAYLOADLEN + NGHTTP2_FRAME_HDLEN));
6985 item = nghttp2_session_get_next_ob_item(session);
6986 CU_ASSERT(NGHTTP2_WINDOW_UPDATE == item->frame.hd.type);
6987 CU_ASSERT(0 == item->frame.hd.stream_id);
6988 CU_ASSERT(NGHTTP2_MAX_PAYLOADLEN ==
6989 item->frame.window_update.window_size_increment);
6991 nghttp2_session_del(session);
6994 void test_nghttp2_session_flow_control_data_with_padding_recv(void) {
6995 nghttp2_session *session;
6996 nghttp2_session_callbacks callbacks;
6998 nghttp2_frame_hd hd;
6999 nghttp2_stream *stream;
7000 nghttp2_option *option;
7002 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7003 callbacks.send_callback = null_send_callback;
7005 nghttp2_option_new(&option);
7006 /* Disable auto window update so that we can check padding is
7007 consumed automatically */
7008 nghttp2_option_set_no_auto_window_update(option, 1);
7010 /* Initial window size to 64KiB - 1*/
7011 nghttp2_session_client_new2(&session, &callbacks, NULL, option);
7013 nghttp2_option_del(option);
7015 stream = open_sent_stream(session, 1);
7017 /* Create DATA frame */
7018 memset(data, 0, sizeof(data));
7019 nghttp2_frame_hd_init(&hd, 357, NGHTTP2_DATA, NGHTTP2_FLAG_PADDED, 1);
7021 nghttp2_frame_pack_frame_hd(data, &hd);
7022 /* Set Pad Length field, which itself is padding */
7023 data[NGHTTP2_FRAME_HDLEN] = 255;
7026 (ssize_t)(NGHTTP2_FRAME_HDLEN + hd.length) ==
7027 nghttp2_session_mem_recv(session, data, NGHTTP2_FRAME_HDLEN + hd.length));
7029 CU_ASSERT((int32_t)hd.length == session->recv_window_size);
7030 CU_ASSERT((int32_t)hd.length == stream->recv_window_size);
7031 CU_ASSERT(256 == session->consumed_size);
7032 CU_ASSERT(256 == stream->consumed_size);
7033 CU_ASSERT(357 == session->recv_window_size);
7034 CU_ASSERT(357 == stream->recv_window_size);
7036 /* Receive the same DATA frame, but in 2 parts: first 9 + 1 + 102
7037 bytes which includes 1st padding byte, and remainder */
7038 CU_ASSERT((ssize_t)(NGHTTP2_FRAME_HDLEN + 103) ==
7039 nghttp2_session_mem_recv(session, data, NGHTTP2_FRAME_HDLEN + 103));
7040 CU_ASSERT(258 == session->consumed_size);
7041 CU_ASSERT(258 == stream->consumed_size);
7042 CU_ASSERT(460 == session->recv_window_size);
7043 CU_ASSERT(460 == stream->recv_window_size);
7045 /* 357 - 103 = 254 bytes left */
7046 CU_ASSERT(254 == nghttp2_session_mem_recv(session, data, 254));
7047 CU_ASSERT(512 == session->consumed_size);
7048 CU_ASSERT(512 == stream->consumed_size);
7049 CU_ASSERT(714 == session->recv_window_size);
7050 CU_ASSERT(714 == stream->recv_window_size);
7052 /* Receive the same DATA frame, but in 2 parts: first 9 = 1 + 101
7053 bytes which only includes data without padding, 2nd part is
7055 CU_ASSERT((ssize_t)(NGHTTP2_FRAME_HDLEN + 102) ==
7056 nghttp2_session_mem_recv(session, data, NGHTTP2_FRAME_HDLEN + 102));
7057 CU_ASSERT(513 == session->consumed_size);
7058 CU_ASSERT(513 == stream->consumed_size);
7059 CU_ASSERT(816 == session->recv_window_size);
7060 CU_ASSERT(816 == stream->recv_window_size);
7062 /* 357 - 102 = 255 bytes left */
7063 CU_ASSERT(255 == nghttp2_session_mem_recv(session, data, 255));
7064 CU_ASSERT(768 == session->consumed_size);
7065 CU_ASSERT(768 == stream->consumed_size);
7066 CU_ASSERT(1071 == session->recv_window_size);
7067 CU_ASSERT(1071 == stream->recv_window_size);
7069 /* Receive the same DATA frame, but in 2 parts: first 9 = 1 + 50
7070 bytes which includes byte up to middle of data, 2nd part is the
7072 CU_ASSERT((ssize_t)(NGHTTP2_FRAME_HDLEN + 51) ==
7073 nghttp2_session_mem_recv(session, data, NGHTTP2_FRAME_HDLEN + 51));
7074 CU_ASSERT(769 == session->consumed_size);
7075 CU_ASSERT(769 == stream->consumed_size);
7076 CU_ASSERT(1122 == session->recv_window_size);
7077 CU_ASSERT(1122 == stream->recv_window_size);
7079 /* 357 - 51 = 306 bytes left */
7080 CU_ASSERT(306 == nghttp2_session_mem_recv(session, data, 306));
7081 CU_ASSERT(1024 == session->consumed_size);
7082 CU_ASSERT(1024 == stream->consumed_size);
7083 CU_ASSERT(1428 == session->recv_window_size);
7084 CU_ASSERT(1428 == stream->recv_window_size);
7086 nghttp2_session_del(session);
7089 void test_nghttp2_session_data_read_temporal_failure(void) {
7090 nghttp2_session *session;
7091 nghttp2_session_callbacks callbacks;
7093 nghttp2_data_provider data_prd;
7094 nghttp2_frame frame;
7095 nghttp2_stream *stream;
7096 size_t data_size = 128 * 1024;
7098 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7099 callbacks.send_callback = null_send_callback;
7100 callbacks.on_frame_send_callback = on_frame_send_callback;
7101 data_prd.read_callback = fixed_length_data_source_read_callback;
7103 ud.data_source_length = data_size;
7105 /* Initial window size is 64KiB - 1 */
7106 nghttp2_session_client_new(&session, &callbacks, &ud);
7107 nghttp2_submit_request(session, NULL, NULL, 0, &data_prd, NULL);
7109 /* Sends NGHTTP2_INITIAL_WINDOW_SIZE data, assuming, it is equal to
7110 or smaller than NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE */
7111 CU_ASSERT(0 == nghttp2_session_send(session));
7112 CU_ASSERT(data_size - NGHTTP2_INITIAL_WINDOW_SIZE == ud.data_source_length);
7114 stream = nghttp2_session_get_stream(session, 1);
7115 CU_ASSERT(NGHTTP2_DATA == stream->item->frame.hd.type);
7117 stream->item->aux_data.data.data_prd.read_callback =
7118 temporal_failure_data_source_read_callback;
7120 /* Back NGHTTP2_INITIAL_WINDOW_SIZE to both connection-level and
7121 stream-wise window */
7122 nghttp2_frame_window_update_init(&frame.window_update, NGHTTP2_FLAG_NONE, 1,
7123 NGHTTP2_INITIAL_WINDOW_SIZE);
7124 nghttp2_session_on_window_update_received(session, &frame);
7125 frame.hd.stream_id = 0;
7126 nghttp2_session_on_window_update_received(session, &frame);
7127 nghttp2_frame_window_update_free(&frame.window_update);
7129 /* Sending data will fail (soft fail) and treated as stream error */
7130 ud.frame_send_cb_called = 0;
7131 CU_ASSERT(0 == nghttp2_session_send(session));
7132 CU_ASSERT(data_size - NGHTTP2_INITIAL_WINDOW_SIZE == ud.data_source_length);
7134 CU_ASSERT(1 == ud.frame_send_cb_called);
7135 CU_ASSERT(NGHTTP2_RST_STREAM == ud.sent_frame_type);
7137 data_prd.read_callback = fail_data_source_read_callback;
7138 nghttp2_submit_request(session, NULL, NULL, 0, &data_prd, NULL);
7139 /* Sending data will fail (hard fail) and session tear down */
7140 CU_ASSERT(NGHTTP2_ERR_CALLBACK_FAILURE == nghttp2_session_send(session));
7142 nghttp2_session_del(session);
7145 void test_nghttp2_session_on_stream_close(void) {
7146 nghttp2_session *session;
7147 nghttp2_session_callbacks callbacks;
7148 my_user_data user_data;
7149 nghttp2_stream *stream;
7151 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7152 callbacks.on_stream_close_callback = on_stream_close_callback;
7153 user_data.stream_close_cb_called = 0;
7155 nghttp2_session_client_new(&session, &callbacks, &user_data);
7157 open_sent_stream3(session, 1, NGHTTP2_STREAM_FLAG_NONE, &pri_spec_default,
7158 NGHTTP2_STREAM_OPENED, &user_data);
7159 CU_ASSERT(stream != NULL);
7160 CU_ASSERT(nghttp2_session_close_stream(session, 1, NGHTTP2_NO_ERROR) == 0);
7161 CU_ASSERT(user_data.stream_close_cb_called == 1);
7162 nghttp2_session_del(session);
7165 void test_nghttp2_session_on_ctrl_not_send(void) {
7166 nghttp2_session *session;
7167 nghttp2_session_callbacks callbacks;
7168 my_user_data user_data;
7169 nghttp2_stream *stream;
7171 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7172 callbacks.on_frame_not_send_callback = on_frame_not_send_callback;
7173 callbacks.send_callback = null_send_callback;
7174 user_data.frame_not_send_cb_called = 0;
7175 user_data.not_sent_frame_type = 0;
7176 user_data.not_sent_error = 0;
7178 nghttp2_session_server_new(&session, &callbacks, &user_data);
7180 open_recv_stream3(session, 1, NGHTTP2_STREAM_FLAG_NONE, &pri_spec_default,
7181 NGHTTP2_STREAM_OPENING, &user_data);
7183 /* Check response HEADERS */
7184 /* Send bogus stream ID */
7185 CU_ASSERT(0 == nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, 3,
7186 NULL, NULL, 0, NULL));
7187 CU_ASSERT(0 == nghttp2_session_send(session));
7188 CU_ASSERT(1 == user_data.frame_not_send_cb_called);
7189 CU_ASSERT(NGHTTP2_HEADERS == user_data.not_sent_frame_type);
7190 CU_ASSERT(NGHTTP2_ERR_STREAM_CLOSED == user_data.not_sent_error);
7192 user_data.frame_not_send_cb_called = 0;
7193 /* Shutdown transmission */
7194 stream->shut_flags |= NGHTTP2_SHUT_WR;
7195 CU_ASSERT(0 == nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, 1,
7196 NULL, NULL, 0, NULL));
7197 CU_ASSERT(0 == nghttp2_session_send(session));
7198 CU_ASSERT(1 == user_data.frame_not_send_cb_called);
7199 CU_ASSERT(NGHTTP2_HEADERS == user_data.not_sent_frame_type);
7200 CU_ASSERT(NGHTTP2_ERR_STREAM_SHUT_WR == user_data.not_sent_error);
7202 stream->shut_flags = NGHTTP2_SHUT_NONE;
7203 user_data.frame_not_send_cb_called = 0;
7204 /* Queue RST_STREAM */
7205 CU_ASSERT(0 == nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, 1,
7206 NULL, NULL, 0, NULL));
7207 CU_ASSERT(0 == nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, 1,
7208 NGHTTP2_INTERNAL_ERROR));
7209 CU_ASSERT(0 == nghttp2_session_send(session));
7210 CU_ASSERT(1 == user_data.frame_not_send_cb_called);
7211 CU_ASSERT(NGHTTP2_HEADERS == user_data.not_sent_frame_type);
7212 CU_ASSERT(NGHTTP2_ERR_STREAM_CLOSING == user_data.not_sent_error);
7214 nghttp2_session_del(session);
7216 /* Check request HEADERS */
7217 user_data.frame_not_send_cb_called = 0;
7218 CU_ASSERT(nghttp2_session_client_new(&session, &callbacks, &user_data) == 0);
7219 /* Maximum Stream ID is reached */
7220 session->next_stream_id = (1u << 31) + 1;
7221 CU_ASSERT(NGHTTP2_ERR_STREAM_ID_NOT_AVAILABLE ==
7222 nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, -1, NULL,
7225 user_data.frame_not_send_cb_called = 0;
7226 /* GOAWAY received */
7227 session->goaway_flags |= NGHTTP2_GOAWAY_RECV;
7228 session->next_stream_id = 9;
7230 CU_ASSERT(0 < nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, -1,
7231 NULL, NULL, 0, NULL));
7232 CU_ASSERT(0 == nghttp2_session_send(session));
7233 CU_ASSERT(1 == user_data.frame_not_send_cb_called);
7234 CU_ASSERT(NGHTTP2_HEADERS == user_data.not_sent_frame_type);
7235 CU_ASSERT(NGHTTP2_ERR_START_STREAM_NOT_ALLOWED == user_data.not_sent_error);
7237 nghttp2_session_del(session);
7240 void test_nghttp2_session_get_outbound_queue_size(void) {
7241 nghttp2_session *session;
7242 nghttp2_session_callbacks callbacks;
7244 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7245 CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, NULL));
7246 CU_ASSERT(0 == nghttp2_session_get_outbound_queue_size(session));
7248 CU_ASSERT(0 == nghttp2_submit_ping(session, NGHTTP2_FLAG_NONE, NULL));
7249 CU_ASSERT(1 == nghttp2_session_get_outbound_queue_size(session));
7251 CU_ASSERT(0 == nghttp2_submit_goaway(session, NGHTTP2_FLAG_NONE, 2,
7252 NGHTTP2_NO_ERROR, NULL, 0));
7253 CU_ASSERT(2 == nghttp2_session_get_outbound_queue_size(session));
7255 nghttp2_session_del(session);
7258 void test_nghttp2_session_get_effective_local_window_size(void) {
7259 nghttp2_session *session;
7260 nghttp2_session_callbacks callbacks;
7261 nghttp2_stream *stream;
7263 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7264 CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, NULL));
7266 stream = open_sent_stream(session, 1);
7268 CU_ASSERT(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE ==
7269 nghttp2_session_get_effective_local_window_size(session));
7270 CU_ASSERT(0 == nghttp2_session_get_effective_recv_data_length(session));
7272 CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE ==
7273 nghttp2_session_get_stream_effective_local_window_size(session, 1));
7275 nghttp2_session_get_stream_effective_recv_data_length(session, 1));
7277 /* Check connection flow control */
7278 session->recv_window_size = 100;
7279 nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 0, 1100);
7281 CU_ASSERT(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE + 1000 ==
7282 nghttp2_session_get_effective_local_window_size(session));
7283 CU_ASSERT(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE + 1000 ==
7284 nghttp2_session_get_local_window_size(session));
7285 CU_ASSERT(0 == nghttp2_session_get_effective_recv_data_length(session));
7287 nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 0, -50);
7288 /* Now session->recv_window_size = -50 */
7289 CU_ASSERT(-50 == session->recv_window_size);
7290 CU_ASSERT(50 == session->recv_reduction);
7291 CU_ASSERT(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE + 950 ==
7292 nghttp2_session_get_effective_local_window_size(session));
7293 CU_ASSERT(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE + 1000 ==
7294 nghttp2_session_get_local_window_size(session));
7295 CU_ASSERT(0 == nghttp2_session_get_effective_recv_data_length(session));
7297 session->recv_window_size += 50;
7299 /* Now session->recv_window_size = 0 */
7301 CU_ASSERT(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE + 950 ==
7302 nghttp2_session_get_local_window_size(session));
7304 nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 0, 100);
7305 CU_ASSERT(50 == session->recv_window_size);
7306 CU_ASSERT(0 == session->recv_reduction);
7307 CU_ASSERT(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE + 1050 ==
7308 nghttp2_session_get_effective_local_window_size(session));
7309 CU_ASSERT(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE + 1000 ==
7310 nghttp2_session_get_local_window_size(session));
7311 CU_ASSERT(50 == nghttp2_session_get_effective_recv_data_length(session));
7313 /* Check stream flow control */
7314 stream->recv_window_size = 100;
7315 nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 1, 1100);
7317 CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE + 1000 ==
7318 nghttp2_session_get_stream_effective_local_window_size(session, 1));
7319 CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE + 1000 ==
7320 nghttp2_session_get_stream_local_window_size(session, 1));
7322 nghttp2_session_get_stream_effective_recv_data_length(session, 1));
7324 nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 1, -50);
7325 /* Now stream->recv_window_size = -50 */
7326 CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE + 950 ==
7327 nghttp2_session_get_stream_effective_local_window_size(session, 1));
7328 CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE + 1000 ==
7329 nghttp2_session_get_stream_local_window_size(session, 1));
7331 nghttp2_session_get_stream_effective_recv_data_length(session, 1));
7333 stream->recv_window_size += 50;
7334 /* Now stream->recv_window_size = 0 */
7335 nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 1, 100);
7336 CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE + 1050 ==
7337 nghttp2_session_get_stream_effective_local_window_size(session, 1));
7338 CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE + 1000 ==
7339 nghttp2_session_get_stream_local_window_size(session, 1));
7341 nghttp2_session_get_stream_effective_recv_data_length(session, 1));
7343 nghttp2_session_del(session);
7346 void test_nghttp2_session_set_option(void) {
7347 nghttp2_session *session;
7348 nghttp2_session_callbacks callbacks;
7349 nghttp2_option *option;
7350 nghttp2_hd_deflater *deflater;
7353 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7354 callbacks.send_callback = null_send_callback;
7356 /* Test for nghttp2_option_set_no_auto_window_update */
7357 nghttp2_option_new(&option);
7358 nghttp2_option_set_no_auto_window_update(option, 1);
7360 nghttp2_session_client_new2(&session, &callbacks, NULL, option);
7362 CU_ASSERT(session->opt_flags & NGHTTP2_OPTMASK_NO_AUTO_WINDOW_UPDATE);
7364 nghttp2_session_del(session);
7365 nghttp2_option_del(option);
7367 /* Test for nghttp2_option_set_peer_max_concurrent_streams */
7368 nghttp2_option_new(&option);
7369 nghttp2_option_set_peer_max_concurrent_streams(option, 100);
7371 nghttp2_session_client_new2(&session, &callbacks, NULL, option);
7373 CU_ASSERT(100 == session->remote_settings.max_concurrent_streams);
7374 nghttp2_session_del(session);
7375 nghttp2_option_del(option);
7377 /* Test for nghttp2_option_set_max_reserved_remote_streams */
7378 nghttp2_option_new(&option);
7379 nghttp2_option_set_max_reserved_remote_streams(option, 99);
7381 nghttp2_session_client_new2(&session, &callbacks, NULL, option);
7383 CU_ASSERT(99 == session->max_incoming_reserved_streams);
7384 nghttp2_session_del(session);
7385 nghttp2_option_del(option);
7387 /* Test for nghttp2_option_set_no_auto_ping_ack */
7388 nghttp2_option_new(&option);
7389 nghttp2_option_set_no_auto_ping_ack(option, 1);
7391 nghttp2_session_client_new2(&session, &callbacks, NULL, option);
7393 CU_ASSERT(session->opt_flags & NGHTTP2_OPTMASK_NO_AUTO_PING_ACK);
7395 nghttp2_session_del(session);
7396 nghttp2_option_del(option);
7398 /* Test for nghttp2_option_set_max_deflate_dynamic_table_size */
7399 nghttp2_option_new(&option);
7400 nghttp2_option_set_max_deflate_dynamic_table_size(option, 0);
7402 nghttp2_session_client_new2(&session, &callbacks, NULL, option);
7404 deflater = &session->hd_deflater;
7406 rv = nghttp2_submit_request(session, NULL, reqnv, ARRLEN(reqnv), NULL, NULL);
7410 rv = nghttp2_session_send(session);
7413 CU_ASSERT(0 == deflater->deflate_hd_table_bufsize_max);
7414 CU_ASSERT(0 == deflater->ctx.hd_table_bufsize);
7416 nghttp2_session_del(session);
7417 nghttp2_option_del(option);
7420 void test_nghttp2_session_data_backoff_by_high_pri_frame(void) {
7421 nghttp2_session *session;
7422 nghttp2_session_callbacks callbacks;
7424 nghttp2_data_provider data_prd;
7425 nghttp2_stream *stream;
7427 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7428 callbacks.send_callback = block_count_send_callback;
7429 callbacks.on_frame_send_callback = on_frame_send_callback;
7430 data_prd.read_callback = fixed_length_data_source_read_callback;
7432 ud.frame_send_cb_called = 0;
7433 ud.data_source_length = NGHTTP2_DATA_PAYLOADLEN * 4;
7435 nghttp2_session_client_new(&session, &callbacks, &ud);
7436 nghttp2_submit_request(session, NULL, NULL, 0, &data_prd, NULL);
7438 session->remote_window_size = 1 << 20;
7441 /* Sends request HEADERS + DATA[0] */
7442 CU_ASSERT(0 == nghttp2_session_send(session));
7444 stream = nghttp2_session_get_stream(session, 1);
7445 stream->remote_window_size = 1 << 20;
7447 CU_ASSERT(NGHTTP2_DATA == ud.sent_frame_type);
7448 /* data for DATA[1] is read from data_prd but it is not sent */
7449 CU_ASSERT(ud.data_source_length == NGHTTP2_DATA_PAYLOADLEN * 2);
7451 nghttp2_submit_ping(session, NGHTTP2_FLAG_NONE, NULL);
7453 /* Sends DATA[1] + PING, PING is interleaved in DATA sequence */
7454 CU_ASSERT(0 == nghttp2_session_send(session));
7455 CU_ASSERT(NGHTTP2_PING == ud.sent_frame_type);
7456 /* data for DATA[2] is read from data_prd but it is not sent */
7457 CU_ASSERT(ud.data_source_length == NGHTTP2_DATA_PAYLOADLEN);
7460 /* Sends DATA[2..3] */
7461 CU_ASSERT(0 == nghttp2_session_send(session));
7463 CU_ASSERT(stream->shut_flags & NGHTTP2_SHUT_WR);
7465 nghttp2_session_del(session);
7468 static void check_session_recv_data_with_padding(nghttp2_bufs *bufs,
7471 nghttp2_session *session;
7473 nghttp2_session_callbacks callbacks;
7477 memset(&callbacks, 0, sizeof(callbacks));
7478 callbacks.on_frame_recv_callback = on_frame_recv_callback;
7479 callbacks.on_data_chunk_recv_callback = on_data_chunk_recv_callback;
7480 nghttp2_session_server_new(&session, &callbacks, &ud);
7482 open_recv_stream(session, 1);
7484 inlen = (size_t)nghttp2_bufs_remove(bufs, &in);
7486 ud.frame_recv_cb_called = 0;
7487 ud.data_chunk_len = 0;
7489 CU_ASSERT((ssize_t)inlen == nghttp2_session_mem_recv(session, in, inlen));
7491 CU_ASSERT(1 == ud.frame_recv_cb_called);
7492 CU_ASSERT(datalen == ud.data_chunk_len);
7494 mem->free(in, NULL);
7495 nghttp2_session_del(session);
7498 void test_nghttp2_session_pack_data_with_padding(void) {
7499 nghttp2_session *session;
7501 nghttp2_session_callbacks callbacks;
7502 nghttp2_data_provider data_prd;
7503 nghttp2_frame *frame;
7504 size_t datalen = 55;
7507 mem = nghttp2_mem_default();
7509 memset(&callbacks, 0, sizeof(callbacks));
7510 callbacks.send_callback = block_count_send_callback;
7511 callbacks.on_frame_send_callback = on_frame_send_callback;
7512 callbacks.select_padding_callback = select_padding_callback;
7514 data_prd.read_callback = fixed_length_data_source_read_callback;
7516 nghttp2_session_client_new(&session, &callbacks, &ud);
7520 nghttp2_submit_request(session, NULL, NULL, 0, &data_prd, NULL);
7522 ud.data_source_length = datalen;
7524 CU_ASSERT(0 == nghttp2_session_send(session));
7525 CU_ASSERT(NGHTTP2_HEADERS == ud.sent_frame_type);
7527 frame = &session->aob.item->frame;
7529 CU_ASSERT(ud.padlen == frame->data.padlen);
7530 CU_ASSERT(frame->hd.flags & NGHTTP2_FLAG_PADDED);
7532 /* Check reception of this DATA frame */
7533 check_session_recv_data_with_padding(&session->aob.framebufs, datalen, mem);
7535 nghttp2_session_del(session);
7538 void test_nghttp2_session_pack_headers_with_padding(void) {
7539 nghttp2_session *session, *sv_session;
7542 nghttp2_session_callbacks callbacks;
7544 memset(&callbacks, 0, sizeof(callbacks));
7545 callbacks.send_callback = accumulator_send_callback;
7546 callbacks.on_frame_send_callback = on_frame_send_callback;
7547 callbacks.select_padding_callback = select_padding_callback;
7548 callbacks.on_frame_recv_callback = on_frame_recv_callback;
7553 nghttp2_session_client_new(&session, &callbacks, &ud);
7554 nghttp2_session_server_new(&sv_session, &callbacks, &ud);
7558 CU_ASSERT(1 == nghttp2_submit_request(session, NULL, reqnv, ARRLEN(reqnv),
7560 CU_ASSERT(0 == nghttp2_session_send(session));
7562 CU_ASSERT(acc.length < NGHTTP2_MAX_PAYLOADLEN);
7563 ud.frame_recv_cb_called = 0;
7564 CU_ASSERT((ssize_t)acc.length ==
7565 nghttp2_session_mem_recv(sv_session, acc.buf, acc.length));
7566 CU_ASSERT(1 == ud.frame_recv_cb_called);
7567 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(sv_session));
7569 nghttp2_session_del(sv_session);
7570 nghttp2_session_del(session);
7573 void test_nghttp2_pack_settings_payload(void) {
7574 nghttp2_settings_entry iv[2];
7577 nghttp2_settings_entry *resiv;
7581 mem = nghttp2_mem_default();
7583 iv[0].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
7585 iv[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
7588 len = nghttp2_pack_settings_payload(buf, sizeof(buf), iv, 2);
7589 CU_ASSERT(2 * NGHTTP2_FRAME_SETTINGS_ENTRY_LENGTH == len);
7590 CU_ASSERT(0 == nghttp2_frame_unpack_settings_payload2(&resiv, &resniv, buf,
7592 CU_ASSERT(2 == resniv);
7593 CU_ASSERT(NGHTTP2_SETTINGS_HEADER_TABLE_SIZE == resiv[0].settings_id);
7594 CU_ASSERT(1023 == resiv[0].value);
7595 CU_ASSERT(NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE == resiv[1].settings_id);
7596 CU_ASSERT(4095 == resiv[1].value);
7598 mem->free(resiv, NULL);
7600 len = nghttp2_pack_settings_payload(buf, 9 /* too small */, iv, 2);
7601 CU_ASSERT(NGHTTP2_ERR_INSUFF_BUFSIZE == len);
7604 #define check_stream_dep_sib(STREAM, DEP_PREV, DEP_NEXT, SIB_PREV, SIB_NEXT) \
7606 CU_ASSERT(DEP_PREV == STREAM->dep_prev); \
7607 CU_ASSERT(DEP_NEXT == STREAM->dep_next); \
7608 CU_ASSERT(SIB_PREV == STREAM->sib_prev); \
7609 CU_ASSERT(SIB_NEXT == STREAM->sib_next); \
7612 /* nghttp2_stream_dep_add() and its families functions should be
7613 tested in nghttp2_stream_test.c, but it is easier to use
7614 nghttp2_session_open_stream(). Therefore, we test them here. */
7615 void test_nghttp2_session_stream_dep_add(void) {
7616 nghttp2_session *session;
7617 nghttp2_session_callbacks callbacks;
7618 nghttp2_stream *a, *b, *c, *d, *e, *root;
7620 memset(&callbacks, 0, sizeof(callbacks));
7622 nghttp2_session_server_new(&session, &callbacks, NULL);
7624 root = &session->root;
7626 a = open_stream(session, 1);
7628 c = open_stream_with_dep(session, 5, a);
7629 b = open_stream_with_dep(session, 3, a);
7630 d = open_stream_with_dep(session, 7, c);
7639 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 2 == a->sum_dep_weight);
7640 CU_ASSERT(0 == b->sum_dep_weight);
7641 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == c->sum_dep_weight);
7642 CU_ASSERT(0 == d->sum_dep_weight);
7644 check_stream_dep_sib(a, root, b, NULL, NULL);
7645 check_stream_dep_sib(b, a, NULL, NULL, c);
7646 check_stream_dep_sib(c, a, d, b, NULL);
7647 check_stream_dep_sib(d, c, NULL, NULL, NULL);
7649 CU_ASSERT(a == session->root.dep_next);
7651 e = open_stream_with_dep_excl(session, 9, a);
7662 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == a->sum_dep_weight);
7663 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 2 == e->sum_dep_weight);
7664 CU_ASSERT(0 == b->sum_dep_weight);
7665 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == c->sum_dep_weight);
7666 CU_ASSERT(0 == d->sum_dep_weight);
7668 check_stream_dep_sib(a, root, e, NULL, NULL);
7669 check_stream_dep_sib(e, a, b, NULL, NULL);
7670 check_stream_dep_sib(b, e, NULL, NULL, c);
7671 check_stream_dep_sib(c, e, d, b, NULL);
7672 check_stream_dep_sib(d, c, NULL, NULL, NULL);
7674 CU_ASSERT(a == session->root.dep_next);
7676 nghttp2_session_del(session);
7679 void test_nghttp2_session_stream_dep_remove(void) {
7680 nghttp2_session *session;
7681 nghttp2_session_callbacks callbacks;
7682 nghttp2_stream *a, *b, *c, *d, *e, *f, *root;
7684 memset(&callbacks, 0, sizeof(callbacks));
7687 nghttp2_session_server_new(&session, &callbacks, NULL);
7689 root = &session->root;
7691 a = open_stream(session, 1);
7692 b = open_stream_with_dep(session, 3, a);
7693 c = open_stream_with_dep(session, 5, a);
7694 d = open_stream_with_dep(session, 7, c);
7703 nghttp2_stream_dep_remove(a);
7711 CU_ASSERT(0 == a->sum_dep_weight);
7712 CU_ASSERT(0 == b->sum_dep_weight);
7713 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == c->sum_dep_weight);
7714 CU_ASSERT(0 == d->sum_dep_weight);
7716 check_stream_dep_sib(a, NULL, NULL, NULL, NULL);
7717 check_stream_dep_sib(b, root, NULL, c, NULL);
7718 check_stream_dep_sib(c, root, d, NULL, b);
7719 check_stream_dep_sib(d, c, NULL, NULL, NULL);
7721 CU_ASSERT(c == session->root.dep_next);
7723 nghttp2_session_del(session);
7725 /* Remove right most stream */
7726 nghttp2_session_server_new(&session, &callbacks, NULL);
7728 root = &session->root;
7730 a = open_stream(session, 1);
7731 b = open_stream_with_dep(session, 3, a);
7732 c = open_stream_with_dep(session, 5, a);
7733 d = open_stream_with_dep(session, 7, c);
7742 nghttp2_stream_dep_remove(b);
7752 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == a->sum_dep_weight);
7753 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == c->sum_dep_weight);
7754 CU_ASSERT(0 == d->sum_dep_weight);
7755 CU_ASSERT(0 == b->sum_dep_weight);
7757 check_stream_dep_sib(a, root, c, NULL, NULL);
7758 check_stream_dep_sib(b, NULL, NULL, NULL, NULL);
7759 check_stream_dep_sib(c, a, d, NULL, NULL);
7760 check_stream_dep_sib(d, c, NULL, NULL, NULL);
7762 CU_ASSERT(a == session->root.dep_next);
7764 nghttp2_session_del(session);
7766 /* Remove left most stream */
7767 nghttp2_session_server_new(&session, &callbacks, NULL);
7769 root = &session->root;
7771 a = open_stream(session, 1);
7772 b = open_stream_with_dep(session, 3, a);
7773 c = open_stream_with_dep(session, 5, a);
7774 d = open_stream_with_dep(session, 7, c);
7775 e = open_stream_with_dep(session, 9, c);
7784 nghttp2_stream_dep_remove(c);
7792 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 2 == a->sum_dep_weight);
7793 CU_ASSERT(0 == b->sum_dep_weight);
7794 CU_ASSERT(0 == d->sum_dep_weight);
7795 CU_ASSERT(0 == c->sum_dep_weight);
7796 CU_ASSERT(0 == e->sum_dep_weight);
7798 check_stream_dep_sib(a, root, e, NULL, NULL);
7799 check_stream_dep_sib(b, a, NULL, d, NULL);
7800 check_stream_dep_sib(c, NULL, NULL, NULL, NULL);
7801 check_stream_dep_sib(d, a, NULL, e, b);
7802 check_stream_dep_sib(e, a, NULL, NULL, d);
7804 nghttp2_session_del(session);
7806 /* Remove middle stream */
7807 nghttp2_session_server_new(&session, &callbacks, NULL);
7809 root = &session->root;
7811 a = open_stream(session, 1);
7812 b = open_stream_with_dep(session, 3, a);
7813 c = open_stream_with_dep(session, 5, a);
7814 d = open_stream_with_dep(session, 7, a);
7815 e = open_stream_with_dep(session, 9, c);
7816 f = open_stream_with_dep(session, 11, c);
7825 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 3 == a->sum_dep_weight);
7826 CU_ASSERT(0 == b->sum_dep_weight);
7827 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 2 == c->sum_dep_weight);
7828 CU_ASSERT(0 == d->sum_dep_weight);
7829 CU_ASSERT(0 == e->sum_dep_weight);
7830 CU_ASSERT(0 == f->sum_dep_weight);
7832 nghttp2_stream_dep_remove(c);
7840 /* c's weight 16 is distributed evenly to e and f. Each weight of e
7842 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 2 + 8 * 2 == a->sum_dep_weight);
7843 CU_ASSERT(0 == b->sum_dep_weight);
7844 CU_ASSERT(0 == c->sum_dep_weight);
7845 CU_ASSERT(0 == d->sum_dep_weight);
7846 CU_ASSERT(0 == e->sum_dep_weight);
7847 CU_ASSERT(0 == f->sum_dep_weight);
7849 check_stream_dep_sib(a, root, d, NULL, NULL);
7850 check_stream_dep_sib(b, a, NULL, e, NULL);
7851 check_stream_dep_sib(c, NULL, NULL, NULL, NULL);
7852 check_stream_dep_sib(e, a, NULL, f, b);
7853 check_stream_dep_sib(f, a, NULL, d, e);
7854 check_stream_dep_sib(d, a, NULL, NULL, f);
7856 nghttp2_session_del(session);
7859 void test_nghttp2_session_stream_dep_add_subtree(void) {
7860 nghttp2_session *session;
7861 nghttp2_session_callbacks callbacks;
7862 nghttp2_stream *a, *b, *c, *d, *e, *f, *root;
7864 memset(&callbacks, 0, sizeof(callbacks));
7866 /* dep_stream has dep_next */
7867 nghttp2_session_server_new(&session, &callbacks, NULL);
7869 root = &session->root;
7871 a = open_stream(session, 1);
7872 b = open_stream_with_dep(session, 3, a);
7873 c = open_stream_with_dep(session, 5, a);
7874 d = open_stream_with_dep(session, 7, c);
7876 e = open_stream(session, 9);
7877 f = open_stream_with_dep(session, 11, e);
7886 nghttp2_stream_dep_remove_subtree(e);
7887 nghttp2_stream_dep_add_subtree(a, e);
7897 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 3 == a->sum_dep_weight);
7898 CU_ASSERT(0 == b->sum_dep_weight);
7899 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == c->sum_dep_weight);
7900 CU_ASSERT(0 == d->sum_dep_weight);
7901 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == e->sum_dep_weight);
7902 CU_ASSERT(0 == f->sum_dep_weight);
7904 check_stream_dep_sib(a, root, e, NULL, NULL);
7905 check_stream_dep_sib(b, a, NULL, c, NULL);
7906 check_stream_dep_sib(c, a, d, e, b);
7907 check_stream_dep_sib(d, c, NULL, NULL, NULL);
7908 check_stream_dep_sib(e, a, f, NULL, c);
7909 check_stream_dep_sib(f, e, NULL, NULL, NULL);
7911 nghttp2_session_del(session);
7913 /* dep_stream has dep_next and now we insert subtree */
7914 nghttp2_session_server_new(&session, &callbacks, NULL);
7916 root = &session->root;
7918 a = open_stream(session, 1);
7919 b = open_stream_with_dep(session, 3, a);
7920 c = open_stream_with_dep(session, 5, a);
7921 d = open_stream_with_dep(session, 7, c);
7923 e = open_stream(session, 9);
7924 f = open_stream_with_dep(session, 11, e);
7933 nghttp2_stream_dep_remove_subtree(e);
7934 nghttp2_stream_dep_insert_subtree(a, e);
7946 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == a->sum_dep_weight);
7947 CU_ASSERT(0 == b->sum_dep_weight);
7948 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == c->sum_dep_weight);
7949 CU_ASSERT(0 == d->sum_dep_weight);
7950 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 3 == e->sum_dep_weight);
7951 CU_ASSERT(0 == f->sum_dep_weight);
7953 check_stream_dep_sib(a, root, e, NULL, NULL);
7954 check_stream_dep_sib(e, a, f, NULL, NULL);
7955 check_stream_dep_sib(f, e, NULL, NULL, c);
7956 check_stream_dep_sib(b, e, NULL, c, NULL);
7957 check_stream_dep_sib(c, e, d, f, b);
7958 check_stream_dep_sib(d, c, NULL, NULL, NULL);
7960 nghttp2_session_del(session);
7963 void test_nghttp2_session_stream_dep_remove_subtree(void) {
7964 nghttp2_session *session;
7965 nghttp2_session_callbacks callbacks;
7966 nghttp2_stream *a, *b, *c, *d, *e, *root;
7968 memset(&callbacks, 0, sizeof(callbacks));
7970 /* Remove left most stream */
7971 nghttp2_session_server_new(&session, &callbacks, NULL);
7973 root = &session->root;
7975 a = open_stream(session, 1);
7976 b = open_stream_with_dep(session, 3, a);
7977 c = open_stream_with_dep(session, 5, a);
7978 d = open_stream_with_dep(session, 7, c);
7987 nghttp2_stream_dep_remove_subtree(c);
7995 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == a->sum_dep_weight);
7996 CU_ASSERT(0 == b->sum_dep_weight);
7997 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == c->sum_dep_weight);
7998 CU_ASSERT(0 == d->sum_dep_weight);
8000 check_stream_dep_sib(a, root, b, NULL, NULL);
8001 check_stream_dep_sib(b, a, NULL, NULL, NULL);
8002 check_stream_dep_sib(c, NULL, d, NULL, NULL);
8003 check_stream_dep_sib(d, c, NULL, NULL, NULL);
8005 nghttp2_session_del(session);
8007 /* Remove right most stream */
8008 nghttp2_session_server_new(&session, &callbacks, NULL);
8010 root = &session->root;
8012 a = open_stream(session, 1);
8013 b = open_stream_with_dep(session, 3, a);
8014 c = open_stream_with_dep(session, 5, a);
8015 d = open_stream_with_dep(session, 7, c);
8024 nghttp2_stream_dep_remove_subtree(b);
8034 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == a->sum_dep_weight);
8035 CU_ASSERT(0 == b->sum_dep_weight);
8036 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == c->sum_dep_weight);
8037 CU_ASSERT(0 == d->sum_dep_weight);
8039 check_stream_dep_sib(a, root, c, NULL, NULL);
8040 check_stream_dep_sib(c, a, d, NULL, NULL);
8041 check_stream_dep_sib(d, c, NULL, NULL, NULL);
8042 check_stream_dep_sib(b, NULL, NULL, NULL, NULL);
8044 nghttp2_session_del(session);
8046 /* Remove middle stream */
8047 nghttp2_session_server_new(&session, &callbacks, NULL);
8049 root = &session->root;
8051 a = open_stream(session, 1);
8052 e = open_stream_with_dep(session, 9, a);
8053 c = open_stream_with_dep(session, 5, a);
8054 b = open_stream_with_dep(session, 3, a);
8055 d = open_stream_with_dep(session, 7, c);
8064 nghttp2_stream_dep_remove_subtree(c);
8072 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 2 == a->sum_dep_weight);
8073 CU_ASSERT(0 == b->sum_dep_weight);
8074 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == c->sum_dep_weight);
8075 CU_ASSERT(0 == d->sum_dep_weight);
8076 CU_ASSERT(0 == e->sum_dep_weight);
8078 check_stream_dep_sib(a, root, b, NULL, NULL);
8079 check_stream_dep_sib(b, a, NULL, NULL, e);
8080 check_stream_dep_sib(e, a, NULL, b, NULL);
8081 check_stream_dep_sib(c, NULL, d, NULL, NULL);
8082 check_stream_dep_sib(d, c, NULL, NULL, NULL);
8084 nghttp2_session_del(session);
8087 void test_nghttp2_session_stream_dep_all_your_stream_are_belong_to_us(void) {
8088 nghttp2_session *session;
8089 nghttp2_session_callbacks callbacks;
8090 nghttp2_stream *a, *b, *c, *d, *root;
8091 nghttp2_outbound_item *db, *dc;
8094 mem = nghttp2_mem_default();
8096 memset(&callbacks, 0, sizeof(callbacks));
8098 nghttp2_session_server_new(&session, &callbacks, NULL);
8100 root = &session->root;
8102 a = open_stream(session, 1);
8103 b = open_stream_with_dep(session, 3, a);
8105 c = open_stream(session, 5);
8112 nghttp2_stream_dep_remove_subtree(c);
8113 CU_ASSERT(0 == nghttp2_stream_dep_insert_subtree(&session->root, c));
8123 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == c->sum_dep_weight);
8124 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == a->sum_dep_weight);
8125 CU_ASSERT(0 == b->sum_dep_weight);
8127 CU_ASSERT(nghttp2_pq_empty(&a->obq));
8128 CU_ASSERT(nghttp2_pq_empty(&b->obq));
8129 CU_ASSERT(nghttp2_pq_empty(&c->obq));
8131 check_stream_dep_sib(c, root, a, NULL, NULL);
8132 check_stream_dep_sib(a, c, b, NULL, NULL);
8133 check_stream_dep_sib(b, a, NULL, NULL, NULL);
8135 nghttp2_session_del(session);
8137 nghttp2_session_server_new(&session, &callbacks, NULL);
8139 root = &session->root;
8141 a = open_stream(session, 1);
8142 b = open_stream(session, 3);
8143 c = open_stream(session, 5);
8149 nghttp2_stream_dep_remove_subtree(c);
8150 CU_ASSERT(0 == nghttp2_stream_dep_insert_subtree(&session->root, c));
8158 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 2 == c->sum_dep_weight);
8159 CU_ASSERT(0 == b->sum_dep_weight);
8160 CU_ASSERT(0 == a->sum_dep_weight);
8162 CU_ASSERT(nghttp2_pq_empty(&a->obq));
8163 CU_ASSERT(nghttp2_pq_empty(&b->obq));
8164 CU_ASSERT(nghttp2_pq_empty(&c->obq));
8166 check_stream_dep_sib(c, root, b, NULL, NULL);
8167 check_stream_dep_sib(b, c, NULL, NULL, a);
8168 check_stream_dep_sib(a, c, NULL, b, NULL);
8170 nghttp2_session_del(session);
8172 nghttp2_session_server_new(&session, &callbacks, NULL);
8174 root = &session->root;
8176 a = open_stream(session, 1);
8177 b = open_stream_with_dep(session, 3, a);
8179 c = open_stream(session, 5);
8180 d = open_stream_with_dep(session, 7, c);
8187 nghttp2_stream_dep_remove_subtree(c);
8188 CU_ASSERT(0 == nghttp2_stream_dep_insert_subtree(&session->root, c));
8198 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 2 == c->sum_dep_weight);
8199 CU_ASSERT(0 == d->sum_dep_weight);
8200 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == a->sum_dep_weight);
8201 CU_ASSERT(0 == b->sum_dep_weight);
8203 CU_ASSERT(nghttp2_pq_empty(&a->obq));
8204 CU_ASSERT(nghttp2_pq_empty(&b->obq));
8205 CU_ASSERT(nghttp2_pq_empty(&c->obq));
8206 CU_ASSERT(nghttp2_pq_empty(&d->obq));
8208 check_stream_dep_sib(c, root, d, NULL, NULL);
8209 check_stream_dep_sib(d, c, NULL, NULL, a);
8210 check_stream_dep_sib(a, c, b, d, NULL);
8211 check_stream_dep_sib(b, a, NULL, NULL, NULL);
8213 nghttp2_session_del(session);
8215 nghttp2_session_server_new(&session, &callbacks, NULL);
8217 root = &session->root;
8219 a = open_stream(session, 1);
8220 b = open_stream_with_dep(session, 3, a);
8222 c = open_stream(session, 5);
8223 d = open_stream_with_dep(session, 7, c);
8230 db = create_data_ob_item(mem);
8232 nghttp2_stream_attach_item(b, db);
8234 nghttp2_stream_dep_remove_subtree(c);
8235 CU_ASSERT(0 == nghttp2_stream_dep_insert_subtree(&session->root, c));
8245 CU_ASSERT(c->queued);
8246 CU_ASSERT(a->queued);
8247 CU_ASSERT(b->queued);
8248 CU_ASSERT(!d->queued);
8250 CU_ASSERT(1 == nghttp2_pq_size(&a->obq));
8251 CU_ASSERT(1 == nghttp2_pq_size(&c->obq));
8252 CU_ASSERT(nghttp2_pq_empty(&d->obq));
8254 check_stream_dep_sib(c, root, d, NULL, NULL);
8255 check_stream_dep_sib(d, c, NULL, NULL, a);
8256 check_stream_dep_sib(a, c, b, d, NULL);
8257 check_stream_dep_sib(b, a, NULL, NULL, NULL);
8259 nghttp2_session_del(session);
8261 nghttp2_session_server_new(&session, &callbacks, NULL);
8263 root = &session->root;
8265 a = open_stream(session, 1);
8266 b = open_stream_with_dep(session, 3, a);
8268 c = open_stream(session, 5);
8269 d = open_stream_with_dep(session, 7, c);
8276 db = create_data_ob_item(mem);
8277 dc = create_data_ob_item(mem);
8279 nghttp2_stream_attach_item(b, db);
8280 nghttp2_stream_attach_item(c, dc);
8282 nghttp2_stream_dep_remove_subtree(c);
8283 CU_ASSERT(0 == nghttp2_stream_dep_insert_subtree(&session->root, c));
8293 CU_ASSERT(c->queued);
8294 CU_ASSERT(a->queued);
8295 CU_ASSERT(b->queued);
8296 CU_ASSERT(!d->queued);
8298 check_stream_dep_sib(c, root, d, NULL, NULL);
8299 check_stream_dep_sib(d, c, NULL, NULL, a);
8300 check_stream_dep_sib(a, c, b, d, NULL);
8301 check_stream_dep_sib(b, a, NULL, NULL, NULL);
8303 nghttp2_session_del(session);
8306 void test_nghttp2_session_stream_attach_item(void) {
8307 nghttp2_session *session;
8308 nghttp2_session_callbacks callbacks;
8309 nghttp2_stream *a, *b, *c, *d, *e;
8310 nghttp2_outbound_item *da, *db, *dc, *dd;
8313 mem = nghttp2_mem_default();
8315 memset(&callbacks, 0, sizeof(callbacks));
8317 nghttp2_session_server_new(&session, &callbacks, NULL);
8319 a = open_stream(session, 1);
8320 b = open_stream_with_dep(session, 3, a);
8321 c = open_stream_with_dep(session, 5, a);
8322 d = open_stream_with_dep(session, 7, c);
8331 db = create_data_ob_item(mem);
8333 nghttp2_stream_attach_item(b, db);
8335 CU_ASSERT(a->queued);
8336 CU_ASSERT(b->queued);
8337 CU_ASSERT(!c->queued);
8338 CU_ASSERT(!d->queued);
8340 CU_ASSERT(1 == nghttp2_pq_size(&a->obq));
8342 /* Attach item to c */
8343 dc = create_data_ob_item(mem);
8345 nghttp2_stream_attach_item(c, dc);
8347 CU_ASSERT(a->queued);
8348 CU_ASSERT(b->queued);
8349 CU_ASSERT(c->queued);
8350 CU_ASSERT(!d->queued);
8352 CU_ASSERT(2 == nghttp2_pq_size(&a->obq));
8354 /* Attach item to a */
8355 da = create_data_ob_item(mem);
8357 nghttp2_stream_attach_item(a, da);
8359 CU_ASSERT(a->queued);
8360 CU_ASSERT(b->queued);
8361 CU_ASSERT(c->queued);
8362 CU_ASSERT(!d->queued);
8364 CU_ASSERT(2 == nghttp2_pq_size(&a->obq));
8366 /* Detach item from a */
8367 nghttp2_stream_detach_item(a);
8369 CU_ASSERT(a->queued);
8370 CU_ASSERT(b->queued);
8371 CU_ASSERT(c->queued);
8372 CU_ASSERT(!d->queued);
8374 CU_ASSERT(2 == nghttp2_pq_size(&a->obq));
8376 /* Attach item to d */
8377 dd = create_data_ob_item(mem);
8379 nghttp2_stream_attach_item(d, dd);
8381 CU_ASSERT(a->queued);
8382 CU_ASSERT(b->queued);
8383 CU_ASSERT(c->queued);
8384 CU_ASSERT(d->queued);
8386 CU_ASSERT(2 == nghttp2_pq_size(&a->obq));
8387 CU_ASSERT(1 == nghttp2_pq_size(&c->obq));
8389 /* Detach item from c */
8390 nghttp2_stream_detach_item(c);
8392 CU_ASSERT(a->queued);
8393 CU_ASSERT(b->queued);
8394 CU_ASSERT(c->queued);
8395 CU_ASSERT(d->queued);
8397 CU_ASSERT(2 == nghttp2_pq_size(&a->obq));
8398 CU_ASSERT(1 == nghttp2_pq_size(&c->obq));
8400 /* Detach item from b */
8401 nghttp2_stream_detach_item(b);
8403 CU_ASSERT(a->queued);
8404 CU_ASSERT(!b->queued);
8405 CU_ASSERT(c->queued);
8406 CU_ASSERT(d->queued);
8408 CU_ASSERT(1 == nghttp2_pq_size(&a->obq));
8410 /* exercises insertion */
8411 e = open_stream_with_dep_excl(session, 9, a);
8422 CU_ASSERT(a->queued);
8423 CU_ASSERT(e->queued);
8424 CU_ASSERT(!b->queued);
8425 CU_ASSERT(c->queued);
8426 CU_ASSERT(d->queued);
8428 CU_ASSERT(1 == nghttp2_pq_size(&a->obq));
8429 CU_ASSERT(1 == nghttp2_pq_size(&e->obq));
8430 CU_ASSERT(nghttp2_pq_empty(&b->obq));
8431 CU_ASSERT(1 == nghttp2_pq_size(&c->obq));
8432 CU_ASSERT(nghttp2_pq_empty(&d->obq));
8434 /* exercises deletion */
8435 nghttp2_stream_dep_remove(e);
8444 CU_ASSERT(a->queued);
8445 CU_ASSERT(!b->queued);
8446 CU_ASSERT(c->queued);
8447 CU_ASSERT(d->queued);
8449 CU_ASSERT(1 == nghttp2_pq_size(&a->obq));
8450 CU_ASSERT(nghttp2_pq_empty(&b->obq));
8451 CU_ASSERT(1 == nghttp2_pq_size(&c->obq));
8452 CU_ASSERT(nghttp2_pq_empty(&d->obq));
8454 /* e's weight 16 is distributed equally among c and b, both now have
8456 CU_ASSERT(8 == b->weight);
8457 CU_ASSERT(8 == c->weight);
8459 /* da, db, dc have been detached */
8460 nghttp2_outbound_item_free(da, mem);
8461 nghttp2_outbound_item_free(db, mem);
8462 nghttp2_outbound_item_free(dc, mem);
8467 nghttp2_session_del(session);
8469 nghttp2_session_server_new(&session, &callbacks, NULL);
8471 a = open_stream(session, 1);
8472 b = open_stream_with_dep(session, 3, a);
8473 c = open_stream_with_dep(session, 5, a);
8474 d = open_stream_with_dep(session, 7, c);
8483 da = create_data_ob_item(mem);
8484 db = create_data_ob_item(mem);
8485 dc = create_data_ob_item(mem);
8487 nghttp2_stream_attach_item(a, da);
8488 nghttp2_stream_attach_item(b, db);
8489 nghttp2_stream_attach_item(c, dc);
8491 CU_ASSERT(a->queued);
8492 CU_ASSERT(b->queued);
8493 CU_ASSERT(c->queued);
8494 CU_ASSERT(!d->queued);
8496 CU_ASSERT(2 == nghttp2_pq_size(&a->obq));
8497 CU_ASSERT(nghttp2_pq_empty(&b->obq));
8498 CU_ASSERT(nghttp2_pq_empty(&c->obq));
8499 CU_ASSERT(nghttp2_pq_empty(&d->obq));
8501 /* Detach item from a */
8502 nghttp2_stream_detach_item(a);
8504 CU_ASSERT(a->queued);
8505 CU_ASSERT(b->queued);
8506 CU_ASSERT(c->queued);
8507 CU_ASSERT(!d->queued);
8509 CU_ASSERT(2 == nghttp2_pq_size(&a->obq));
8510 CU_ASSERT(nghttp2_pq_empty(&b->obq));
8511 CU_ASSERT(nghttp2_pq_empty(&c->obq));
8512 CU_ASSERT(nghttp2_pq_empty(&d->obq));
8514 /* da has been detached */
8515 nghttp2_outbound_item_free(da, mem);
8518 nghttp2_session_del(session);
8521 void test_nghttp2_session_stream_attach_item_subtree(void) {
8522 nghttp2_session *session;
8523 nghttp2_session_callbacks callbacks;
8524 nghttp2_stream *a, *b, *c, *d, *e, *f;
8525 nghttp2_outbound_item *da, *db, *dd, *de;
8528 mem = nghttp2_mem_default();
8530 memset(&callbacks, 0, sizeof(callbacks));
8532 nghttp2_session_server_new(&session, &callbacks, NULL);
8534 a = open_stream(session, 1);
8535 b = open_stream_with_dep(session, 3, a);
8536 c = open_stream_with_dep(session, 5, a);
8537 d = open_stream_with_dep(session, 7, c);
8539 e = open_stream_with_dep_weight(session, 9, 32, &session->root);
8540 f = open_stream_with_dep(session, 11, e);
8550 de = create_data_ob_item(mem);
8552 nghttp2_stream_attach_item(e, de);
8554 db = create_data_ob_item(mem);
8556 nghttp2_stream_attach_item(b, db);
8558 CU_ASSERT(a->queued);
8559 CU_ASSERT(b->queued);
8560 CU_ASSERT(!c->queued);
8561 CU_ASSERT(!d->queued);
8562 CU_ASSERT(e->queued);
8563 CU_ASSERT(!f->queued);
8565 CU_ASSERT(1 == nghttp2_pq_size(&a->obq));
8566 CU_ASSERT(nghttp2_pq_empty(&b->obq));
8567 CU_ASSERT(nghttp2_pq_empty(&c->obq));
8568 CU_ASSERT(nghttp2_pq_empty(&d->obq));
8569 CU_ASSERT(nghttp2_pq_empty(&e->obq));
8570 CU_ASSERT(nghttp2_pq_empty(&f->obq));
8572 /* Insert subtree e under a */
8574 nghttp2_stream_dep_remove_subtree(e);
8575 nghttp2_stream_dep_insert_subtree(a, e);
8587 CU_ASSERT(a->queued);
8588 CU_ASSERT(b->queued);
8589 CU_ASSERT(!c->queued);
8590 CU_ASSERT(!d->queued);
8591 CU_ASSERT(e->queued);
8592 CU_ASSERT(!f->queued);
8594 CU_ASSERT(1 == nghttp2_pq_size(&a->obq));
8595 CU_ASSERT(nghttp2_pq_empty(&b->obq));
8596 CU_ASSERT(nghttp2_pq_empty(&c->obq));
8597 CU_ASSERT(nghttp2_pq_empty(&d->obq));
8598 CU_ASSERT(1 == nghttp2_pq_size(&e->obq));
8599 CU_ASSERT(nghttp2_pq_empty(&f->obq));
8601 /* Remove subtree b */
8603 nghttp2_stream_dep_remove_subtree(b);
8605 CU_ASSERT(0 == nghttp2_stream_dep_add_subtree(&session->root, b));
8617 CU_ASSERT(a->queued);
8618 CU_ASSERT(b->queued);
8619 CU_ASSERT(!c->queued);
8620 CU_ASSERT(!d->queued);
8621 CU_ASSERT(e->queued);
8622 CU_ASSERT(!f->queued);
8624 CU_ASSERT(1 == nghttp2_pq_size(&a->obq));
8625 CU_ASSERT(nghttp2_pq_empty(&b->obq));
8626 CU_ASSERT(nghttp2_pq_empty(&c->obq));
8627 CU_ASSERT(nghttp2_pq_empty(&d->obq));
8628 CU_ASSERT(nghttp2_pq_empty(&e->obq));
8629 CU_ASSERT(nghttp2_pq_empty(&f->obq));
8631 /* Remove subtree a, and add it to root again */
8633 nghttp2_stream_dep_remove_subtree(a);
8635 CU_ASSERT(0 == nghttp2_stream_dep_add_subtree(&session->root, a));
8637 CU_ASSERT(a->queued);
8638 CU_ASSERT(b->queued);
8639 CU_ASSERT(!c->queued);
8640 CU_ASSERT(!d->queued);
8641 CU_ASSERT(e->queued);
8642 CU_ASSERT(!f->queued);
8644 CU_ASSERT(1 == nghttp2_pq_size(&a->obq));
8645 CU_ASSERT(nghttp2_pq_empty(&b->obq));
8646 CU_ASSERT(nghttp2_pq_empty(&c->obq));
8647 CU_ASSERT(nghttp2_pq_empty(&d->obq));
8648 CU_ASSERT(nghttp2_pq_empty(&e->obq));
8649 CU_ASSERT(nghttp2_pq_empty(&f->obq));
8651 /* Remove subtree c */
8653 nghttp2_stream_dep_remove_subtree(c);
8655 CU_ASSERT(0 == nghttp2_stream_dep_add_subtree(&session->root, c));
8665 CU_ASSERT(a->queued);
8666 CU_ASSERT(b->queued);
8667 CU_ASSERT(!c->queued);
8668 CU_ASSERT(!d->queued);
8669 CU_ASSERT(e->queued);
8670 CU_ASSERT(!f->queued);
8672 CU_ASSERT(1 == nghttp2_pq_size(&a->obq));
8673 CU_ASSERT(nghttp2_pq_empty(&b->obq));
8674 CU_ASSERT(nghttp2_pq_empty(&c->obq));
8675 CU_ASSERT(nghttp2_pq_empty(&d->obq));
8676 CU_ASSERT(nghttp2_pq_empty(&e->obq));
8677 CU_ASSERT(nghttp2_pq_empty(&f->obq));
8679 dd = create_data_ob_item(mem);
8681 nghttp2_stream_attach_item(d, dd);
8683 /* Add subtree c to a */
8685 nghttp2_stream_dep_remove_subtree(c);
8686 nghttp2_stream_dep_add_subtree(a, c);
8696 CU_ASSERT(a->queued);
8697 CU_ASSERT(b->queued);
8698 CU_ASSERT(c->queued);
8699 CU_ASSERT(d->queued);
8700 CU_ASSERT(e->queued);
8701 CU_ASSERT(!f->queued);
8703 CU_ASSERT(2 == nghttp2_pq_size(&a->obq));
8704 CU_ASSERT(nghttp2_pq_empty(&b->obq));
8705 CU_ASSERT(1 == nghttp2_pq_size(&c->obq));
8706 CU_ASSERT(nghttp2_pq_empty(&d->obq));
8707 CU_ASSERT(nghttp2_pq_empty(&e->obq));
8708 CU_ASSERT(nghttp2_pq_empty(&f->obq));
8710 /* Insert b under a */
8712 nghttp2_stream_dep_remove_subtree(b);
8713 nghttp2_stream_dep_insert_subtree(a, b);
8725 CU_ASSERT(a->queued);
8726 CU_ASSERT(b->queued);
8727 CU_ASSERT(c->queued);
8728 CU_ASSERT(d->queued);
8729 CU_ASSERT(e->queued);
8730 CU_ASSERT(!f->queued);
8732 CU_ASSERT(1 == nghttp2_pq_size(&a->obq));
8733 CU_ASSERT(2 == nghttp2_pq_size(&b->obq));
8734 CU_ASSERT(1 == nghttp2_pq_size(&c->obq));
8735 CU_ASSERT(nghttp2_pq_empty(&d->obq));
8736 CU_ASSERT(nghttp2_pq_empty(&e->obq));
8737 CU_ASSERT(nghttp2_pq_empty(&f->obq));
8739 /* Remove subtree b */
8741 nghttp2_stream_dep_remove_subtree(b);
8742 CU_ASSERT(0 == nghttp2_stream_dep_add_subtree(&session->root, b));
8752 CU_ASSERT(!a->queued);
8753 CU_ASSERT(b->queued);
8754 CU_ASSERT(c->queued);
8755 CU_ASSERT(d->queued);
8756 CU_ASSERT(e->queued);
8757 CU_ASSERT(!f->queued);
8759 CU_ASSERT(nghttp2_pq_empty(&a->obq));
8760 CU_ASSERT(2 == nghttp2_pq_size(&b->obq));
8761 CU_ASSERT(1 == nghttp2_pq_size(&c->obq));
8762 CU_ASSERT(nghttp2_pq_empty(&d->obq));
8763 CU_ASSERT(nghttp2_pq_empty(&e->obq));
8764 CU_ASSERT(nghttp2_pq_empty(&f->obq));
8766 /* Remove subtree c, and detach item from b, and then re-add
8767 subtree c under b */
8769 nghttp2_stream_dep_remove_subtree(c);
8770 nghttp2_stream_detach_item(b);
8771 nghttp2_stream_dep_add_subtree(b, c);
8781 CU_ASSERT(!a->queued);
8782 CU_ASSERT(b->queued);
8783 CU_ASSERT(c->queued);
8784 CU_ASSERT(d->queued);
8785 CU_ASSERT(e->queued);
8786 CU_ASSERT(!f->queued);
8788 CU_ASSERT(nghttp2_pq_empty(&a->obq));
8789 CU_ASSERT(2 == nghttp2_pq_size(&b->obq));
8790 CU_ASSERT(1 == nghttp2_pq_size(&c->obq));
8791 CU_ASSERT(nghttp2_pq_empty(&d->obq));
8792 CU_ASSERT(nghttp2_pq_empty(&e->obq));
8793 CU_ASSERT(nghttp2_pq_empty(&f->obq));
8795 /* Attach data to a, and add subtree a under b */
8797 da = create_data_ob_item(mem);
8798 nghttp2_stream_attach_item(a, da);
8799 nghttp2_stream_dep_remove_subtree(a);
8800 nghttp2_stream_dep_add_subtree(b, a);
8810 CU_ASSERT(a->queued);
8811 CU_ASSERT(b->queued);
8812 CU_ASSERT(c->queued);
8813 CU_ASSERT(d->queued);
8814 CU_ASSERT(e->queued);
8815 CU_ASSERT(!f->queued);
8817 CU_ASSERT(nghttp2_pq_empty(&a->obq));
8818 CU_ASSERT(3 == nghttp2_pq_size(&b->obq));
8819 CU_ASSERT(1 == nghttp2_pq_size(&c->obq));
8820 CU_ASSERT(nghttp2_pq_empty(&d->obq));
8821 CU_ASSERT(nghttp2_pq_empty(&e->obq));
8822 CU_ASSERT(nghttp2_pq_empty(&f->obq));
8824 /* Remove subtree c, and add under f */
8825 nghttp2_stream_dep_remove_subtree(c);
8826 nghttp2_stream_dep_insert_subtree(f, c);
8840 CU_ASSERT(a->queued);
8841 CU_ASSERT(b->queued);
8842 CU_ASSERT(c->queued);
8843 CU_ASSERT(d->queued);
8844 CU_ASSERT(e->queued);
8845 CU_ASSERT(f->queued);
8847 CU_ASSERT(nghttp2_pq_empty(&a->obq));
8848 CU_ASSERT(2 == nghttp2_pq_size(&b->obq));
8849 CU_ASSERT(1 == nghttp2_pq_size(&c->obq));
8850 CU_ASSERT(nghttp2_pq_empty(&d->obq));
8851 CU_ASSERT(1 == nghttp2_pq_size(&e->obq));
8852 CU_ASSERT(1 == nghttp2_pq_size(&f->obq));
8854 /* db has been detached */
8855 nghttp2_outbound_item_free(db, mem);
8858 nghttp2_session_del(session);
8861 void test_nghttp2_session_stream_get_state(void) {
8862 nghttp2_session *session;
8863 nghttp2_session_callbacks callbacks;
8865 nghttp2_hd_deflater deflater;
8868 nghttp2_stream *stream;
8870 nghttp2_data_provider data_prd;
8871 nghttp2_frame frame;
8873 mem = nghttp2_mem_default();
8874 frame_pack_bufs_init(&bufs);
8875 memset(&data_prd, 0, sizeof(data_prd));
8877 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
8878 callbacks.send_callback = null_send_callback;
8880 nghttp2_session_server_new(&session, &callbacks, NULL);
8881 nghttp2_hd_deflate_init(&deflater, mem);
8883 CU_ASSERT(NGHTTP2_STREAM_STATE_IDLE ==
8884 nghttp2_stream_get_state(nghttp2_session_get_root_stream(session)));
8886 /* stream 1 HEADERS; without END_STREAM flag set */
8887 pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, reqnv,
8888 ARRLEN(reqnv), mem);
8890 buf = &bufs.head->buf;
8891 rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
8893 CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv);
8895 stream = nghttp2_session_find_stream(session, 1);
8897 CU_ASSERT(NULL != stream);
8898 CU_ASSERT(1 == stream->stream_id);
8899 CU_ASSERT(NGHTTP2_STREAM_STATE_OPEN == nghttp2_stream_get_state(stream));
8901 nghttp2_bufs_reset(&bufs);
8903 /* stream 3 HEADERS; with END_STREAM flag set */
8904 pack_headers(&bufs, &deflater, 3,
8905 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM, reqnv,
8906 ARRLEN(reqnv), mem);
8908 buf = &bufs.head->buf;
8909 rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
8911 CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv);
8913 stream = nghttp2_session_find_stream(session, 3);
8915 CU_ASSERT(NULL != stream);
8916 CU_ASSERT(3 == stream->stream_id);
8917 CU_ASSERT(NGHTTP2_STREAM_STATE_HALF_CLOSED_REMOTE ==
8918 nghttp2_stream_get_state(stream));
8920 nghttp2_bufs_reset(&bufs);
8922 /* Respond to stream 1 */
8923 nghttp2_submit_response(session, 1, resnv, ARRLEN(resnv), NULL);
8925 rv = nghttp2_session_send(session);
8929 stream = nghttp2_session_find_stream(session, 1);
8931 CU_ASSERT(NGHTTP2_STREAM_STATE_HALF_CLOSED_LOCAL ==
8932 nghttp2_stream_get_state(stream));
8934 /* Respond to stream 3 */
8935 nghttp2_submit_response(session, 3, resnv, ARRLEN(resnv), NULL);
8937 rv = nghttp2_session_send(session);
8941 stream = nghttp2_session_find_stream(session, 3);
8943 CU_ASSERT(NGHTTP2_STREAM_STATE_CLOSED == nghttp2_stream_get_state(stream));
8945 /* stream 5 HEADERS; with END_STREAM flag set */
8946 pack_headers(&bufs, &deflater, 5,
8947 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM, reqnv,
8948 ARRLEN(reqnv), mem);
8950 buf = &bufs.head->buf;
8951 rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
8953 CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv);
8955 nghttp2_bufs_reset(&bufs);
8957 /* Push stream 2 associated to stream 5 */
8958 rv = nghttp2_submit_push_promise(session, NGHTTP2_FLAG_NONE, 5, reqnv,
8959 ARRLEN(reqnv), NULL);
8963 rv = nghttp2_session_send(session);
8967 stream = nghttp2_session_find_stream(session, 2);
8969 CU_ASSERT(NGHTTP2_STREAM_STATE_RESERVED_LOCAL ==
8970 nghttp2_stream_get_state(stream));
8972 /* Send resposne to push stream 2 with END_STREAM set */
8973 nghttp2_submit_response(session, 2, resnv, ARRLEN(resnv), NULL);
8975 rv = nghttp2_session_send(session);
8979 stream = nghttp2_session_find_stream(session, 2);
8981 /* At server, pushed stream object is not retained after closed */
8982 CU_ASSERT(NULL == stream);
8984 /* Push stream 4 associated to stream 5 */
8985 rv = nghttp2_submit_push_promise(session, NGHTTP2_FLAG_NONE, 5, reqnv,
8986 ARRLEN(reqnv), NULL);
8990 rv = nghttp2_session_send(session);
8994 stream = nghttp2_session_find_stream(session, 4);
8996 CU_ASSERT(NGHTTP2_STREAM_STATE_RESERVED_LOCAL ==
8997 nghttp2_stream_get_state(stream));
8999 /* Send response to push stream 4 without closing */
9000 data_prd.read_callback = defer_data_source_read_callback;
9002 nghttp2_submit_response(session, 4, resnv, ARRLEN(resnv), &data_prd);
9004 rv = nghttp2_session_send(session);
9008 stream = nghttp2_session_find_stream(session, 4);
9010 CU_ASSERT(NGHTTP2_STREAM_STATE_HALF_CLOSED_REMOTE ==
9011 nghttp2_stream_get_state(stream));
9013 /* Create idle stream by PRIORITY frame */
9014 nghttp2_frame_priority_init(&frame.priority, 7, &pri_spec_default);
9016 rv = nghttp2_frame_pack_priority(&bufs, &frame.priority);
9020 nghttp2_frame_priority_free(&frame.priority);
9022 buf = &bufs.head->buf;
9023 rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
9025 CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv);
9027 stream = nghttp2_session_find_stream(session, 7);
9029 CU_ASSERT(NGHTTP2_STREAM_STATE_IDLE == nghttp2_stream_get_state(stream));
9031 nghttp2_bufs_reset(&bufs);
9033 nghttp2_hd_deflate_free(&deflater);
9034 nghttp2_session_del(session);
9036 /* Test for client side */
9038 nghttp2_session_client_new(&session, &callbacks, NULL);
9039 nghttp2_hd_deflate_init(&deflater, mem);
9041 nghttp2_submit_request(session, NULL, reqnv, ARRLEN(reqnv), NULL, NULL);
9043 rv = nghttp2_session_send(session);
9047 /* Receive PUSH_PROMISE 2 associated to stream 1 */
9048 pack_push_promise(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, 2, 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 stream = nghttp2_session_find_stream(session, 2);
9058 CU_ASSERT(NGHTTP2_STREAM_STATE_RESERVED_REMOTE ==
9059 nghttp2_stream_get_state(stream));
9061 nghttp2_bufs_reset(&bufs);
9063 /* Receive push response for stream 2 without END_STREAM set */
9064 pack_headers(&bufs, &deflater, 2, NGHTTP2_FLAG_END_HEADERS, resnv,
9065 ARRLEN(resnv), mem);
9067 buf = &bufs.head->buf;
9068 rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
9070 CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv);
9072 stream = nghttp2_session_find_stream(session, 2);
9074 CU_ASSERT(NGHTTP2_STREAM_STATE_HALF_CLOSED_LOCAL ==
9075 nghttp2_stream_get_state(stream));
9077 nghttp2_bufs_reset(&bufs);
9079 nghttp2_hd_deflate_free(&deflater);
9080 nghttp2_session_del(session);
9082 nghttp2_bufs_free(&bufs);
9085 void test_nghttp2_session_stream_get_something(void) {
9086 nghttp2_session *session;
9087 nghttp2_session_callbacks callbacks;
9088 nghttp2_stream *a, *b, *c;
9090 memset(&callbacks, 0, sizeof(callbacks));
9092 nghttp2_session_server_new(&session, &callbacks, NULL);
9094 a = open_stream(session, 1);
9096 CU_ASSERT(nghttp2_session_get_root_stream(session) ==
9097 nghttp2_stream_get_parent(a));
9098 CU_ASSERT(NULL == nghttp2_stream_get_previous_sibling(a));
9099 CU_ASSERT(NULL == nghttp2_stream_get_next_sibling(a));
9100 CU_ASSERT(NULL == nghttp2_stream_get_first_child(a));
9102 b = open_stream_with_dep(session, 3, a);
9103 c = open_stream_with_dep_weight(session, 5, 11, a);
9105 CU_ASSERT(a == nghttp2_stream_get_parent(c));
9106 CU_ASSERT(a == nghttp2_stream_get_parent(b));
9108 CU_ASSERT(c == nghttp2_stream_get_first_child(a));
9110 CU_ASSERT(b == nghttp2_stream_get_next_sibling(c));
9111 CU_ASSERT(c == nghttp2_stream_get_previous_sibling(b));
9113 CU_ASSERT(27 == nghttp2_stream_get_sum_dependency_weight(a));
9115 CU_ASSERT(11 == nghttp2_stream_get_weight(c));
9116 CU_ASSERT(5 == nghttp2_stream_get_stream_id(c));
9117 CU_ASSERT(0 == nghttp2_stream_get_stream_id(&session->root));
9119 nghttp2_session_del(session);
9122 void test_nghttp2_session_find_stream(void) {
9123 nghttp2_session *session;
9124 nghttp2_session_callbacks callbacks;
9125 nghttp2_stream *stream;
9127 memset(&callbacks, 0, sizeof(callbacks));
9129 nghttp2_session_server_new(&session, &callbacks, NULL);
9131 open_recv_stream(session, 1);
9133 stream = nghttp2_session_find_stream(session, 1);
9135 CU_ASSERT(NULL != stream);
9136 CU_ASSERT(1 == stream->stream_id);
9138 stream = nghttp2_session_find_stream(session, 0);
9140 CU_ASSERT(&session->root == stream);
9141 CU_ASSERT(0 == stream->stream_id);
9143 stream = nghttp2_session_find_stream(session, 2);
9145 CU_ASSERT(NULL == stream);
9147 nghttp2_session_del(session);
9150 void test_nghttp2_session_keep_closed_stream(void) {
9151 nghttp2_session *session;
9152 nghttp2_session_callbacks callbacks;
9153 const size_t max_concurrent_streams = 5;
9154 nghttp2_settings_entry iv = {NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS,
9155 (uint32_t)max_concurrent_streams};
9158 memset(&callbacks, 0, sizeof(callbacks));
9159 callbacks.send_callback = null_send_callback;
9161 nghttp2_session_server_new(&session, &callbacks, NULL);
9163 nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, &iv, 1);
9165 for (i = 0; i < max_concurrent_streams; ++i) {
9166 open_recv_stream(session, (int32_t)i * 2 + 1);
9169 CU_ASSERT(0 == session->num_closed_streams);
9171 nghttp2_session_close_stream(session, 1, NGHTTP2_NO_ERROR);
9173 CU_ASSERT(1 == session->num_closed_streams);
9174 CU_ASSERT(1 == session->closed_stream_tail->stream_id);
9175 CU_ASSERT(session->closed_stream_tail == session->closed_stream_head);
9177 nghttp2_session_close_stream(session, 5, NGHTTP2_NO_ERROR);
9179 CU_ASSERT(2 == session->num_closed_streams);
9180 CU_ASSERT(5 == session->closed_stream_tail->stream_id);
9181 CU_ASSERT(1 == session->closed_stream_head->stream_id);
9182 CU_ASSERT(session->closed_stream_head ==
9183 session->closed_stream_tail->closed_prev);
9184 CU_ASSERT(NULL == session->closed_stream_tail->closed_next);
9185 CU_ASSERT(session->closed_stream_tail ==
9186 session->closed_stream_head->closed_next);
9187 CU_ASSERT(NULL == session->closed_stream_head->closed_prev);
9189 open_recv_stream(session, 11);
9190 nghttp2_session_adjust_closed_stream(session);
9192 CU_ASSERT(1 == session->num_closed_streams);
9193 CU_ASSERT(5 == session->closed_stream_tail->stream_id);
9194 CU_ASSERT(session->closed_stream_tail == session->closed_stream_head);
9195 CU_ASSERT(NULL == session->closed_stream_head->closed_prev);
9196 CU_ASSERT(NULL == session->closed_stream_head->closed_next);
9198 open_recv_stream(session, 13);
9199 nghttp2_session_adjust_closed_stream(session);
9201 CU_ASSERT(0 == session->num_closed_streams);
9202 CU_ASSERT(NULL == session->closed_stream_tail);
9203 CU_ASSERT(NULL == session->closed_stream_head);
9205 nghttp2_session_close_stream(session, 3, NGHTTP2_NO_ERROR);
9207 CU_ASSERT(1 == session->num_closed_streams);
9208 CU_ASSERT(3 == session->closed_stream_head->stream_id);
9210 /* server initiated stream is not counted to max concurrent limit */
9211 open_sent_stream(session, 2);
9212 nghttp2_session_adjust_closed_stream(session);
9214 CU_ASSERT(1 == session->num_closed_streams);
9215 CU_ASSERT(3 == session->closed_stream_head->stream_id);
9217 nghttp2_session_close_stream(session, 2, NGHTTP2_NO_ERROR);
9219 CU_ASSERT(1 == session->num_closed_streams);
9220 CU_ASSERT(3 == session->closed_stream_head->stream_id);
9222 nghttp2_session_del(session);
9225 void test_nghttp2_session_keep_idle_stream(void) {
9226 nghttp2_session *session;
9227 nghttp2_session_callbacks callbacks;
9228 const size_t max_concurrent_streams = 1;
9229 nghttp2_settings_entry iv = {NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS,
9230 (uint32_t)max_concurrent_streams};
9234 memset(&callbacks, 0, sizeof(callbacks));
9235 callbacks.send_callback = null_send_callback;
9237 nghttp2_session_server_new(&session, &callbacks, NULL);
9239 nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, &iv, 1);
9241 /* We at least allow NGHTTP2_MIN_IDLE_STREAM idle streams even if
9242 max concurrent streams is very low. */
9243 for (i = 0; i < NGHTTP2_MIN_IDLE_STREAMS; ++i) {
9244 open_recv_stream2(session, i * 2 + 1, NGHTTP2_STREAM_IDLE);
9245 nghttp2_session_adjust_idle_stream(session);
9248 CU_ASSERT(NGHTTP2_MIN_IDLE_STREAMS == session->num_idle_streams);
9250 stream_id = (NGHTTP2_MIN_IDLE_STREAMS - 1) * 2 + 1;
9251 CU_ASSERT(1 == session->idle_stream_head->stream_id);
9252 CU_ASSERT(stream_id == session->idle_stream_tail->stream_id);
9256 open_recv_stream2(session, stream_id, NGHTTP2_STREAM_IDLE);
9257 nghttp2_session_adjust_idle_stream(session);
9259 CU_ASSERT(NGHTTP2_MIN_IDLE_STREAMS == session->num_idle_streams);
9260 CU_ASSERT(3 == session->idle_stream_head->stream_id);
9261 CU_ASSERT(stream_id == session->idle_stream_tail->stream_id);
9263 nghttp2_session_del(session);
9266 void test_nghttp2_session_detach_idle_stream(void) {
9267 nghttp2_session *session;
9268 nghttp2_session_callbacks callbacks;
9270 nghttp2_stream *stream;
9272 memset(&callbacks, 0, sizeof(callbacks));
9273 callbacks.send_callback = null_send_callback;
9275 nghttp2_session_server_new(&session, &callbacks, NULL);
9277 for (i = 1; i <= 3; ++i) {
9278 nghttp2_session_open_stream(session, i, NGHTTP2_STREAM_FLAG_NONE,
9279 &pri_spec_default, NGHTTP2_STREAM_IDLE, NULL);
9282 CU_ASSERT(3 == session->num_idle_streams);
9284 /* Detach middle stream */
9285 stream = nghttp2_session_get_stream_raw(session, 2);
9287 CU_ASSERT(session->idle_stream_head == stream->closed_prev);
9288 CU_ASSERT(session->idle_stream_tail == stream->closed_next);
9289 CU_ASSERT(stream == session->idle_stream_head->closed_next);
9290 CU_ASSERT(stream == session->idle_stream_tail->closed_prev);
9292 nghttp2_session_detach_idle_stream(session, stream);
9294 CU_ASSERT(2 == session->num_idle_streams);
9296 CU_ASSERT(NULL == stream->closed_prev);
9297 CU_ASSERT(NULL == stream->closed_next);
9299 CU_ASSERT(session->idle_stream_head ==
9300 session->idle_stream_tail->closed_prev);
9301 CU_ASSERT(session->idle_stream_tail ==
9302 session->idle_stream_head->closed_next);
9304 /* Detach head stream */
9305 stream = session->idle_stream_head;
9307 nghttp2_session_detach_idle_stream(session, stream);
9309 CU_ASSERT(1 == session->num_idle_streams);
9311 CU_ASSERT(session->idle_stream_head == session->idle_stream_tail);
9312 CU_ASSERT(NULL == session->idle_stream_head->closed_prev);
9313 CU_ASSERT(NULL == session->idle_stream_head->closed_next);
9315 /* Detach last stream */
9317 stream = session->idle_stream_head;
9319 nghttp2_session_detach_idle_stream(session, stream);
9321 CU_ASSERT(0 == session->num_idle_streams);
9323 CU_ASSERT(NULL == session->idle_stream_head);
9324 CU_ASSERT(NULL == session->idle_stream_tail);
9326 for (i = 4; i <= 5; ++i) {
9327 nghttp2_session_open_stream(session, i, NGHTTP2_STREAM_FLAG_NONE,
9328 &pri_spec_default, NGHTTP2_STREAM_IDLE, NULL);
9331 CU_ASSERT(2 == session->num_idle_streams);
9333 /* Detach tail stream */
9335 stream = session->idle_stream_tail;
9337 nghttp2_session_detach_idle_stream(session, stream);
9339 CU_ASSERT(1 == session->num_idle_streams);
9341 CU_ASSERT(session->idle_stream_head == session->idle_stream_tail);
9342 CU_ASSERT(NULL == session->idle_stream_head->closed_prev);
9343 CU_ASSERT(NULL == session->idle_stream_head->closed_next);
9345 nghttp2_session_del(session);
9348 void test_nghttp2_session_large_dep_tree(void) {
9349 nghttp2_session *session;
9350 nghttp2_session_callbacks callbacks;
9352 nghttp2_stream *dep_stream = NULL;
9353 nghttp2_stream *stream;
9356 memset(&callbacks, 0, sizeof(callbacks));
9357 callbacks.send_callback = null_send_callback;
9359 nghttp2_session_server_new(&session, &callbacks, NULL);
9362 for (i = 0; i < 250; ++i, stream_id += 2) {
9363 dep_stream = open_stream_with_dep(session, stream_id, dep_stream);
9367 for (i = 0; i < 250; ++i, stream_id += 2) {
9368 stream = nghttp2_session_get_stream(session, stream_id);
9369 CU_ASSERT(nghttp2_stream_dep_find_ancestor(stream, &session->root));
9370 CU_ASSERT(nghttp2_stream_in_dep_tree(stream));
9373 nghttp2_session_del(session);
9376 void test_nghttp2_session_graceful_shutdown(void) {
9377 nghttp2_session *session;
9378 nghttp2_session_callbacks callbacks;
9381 memset(&callbacks, 0, sizeof(callbacks));
9382 callbacks.send_callback = null_send_callback;
9383 callbacks.on_frame_send_callback = on_frame_send_callback;
9384 callbacks.on_stream_close_callback = on_stream_close_callback;
9386 nghttp2_session_server_new(&session, &callbacks, &ud);
9388 open_recv_stream(session, 301);
9389 open_sent_stream(session, 302);
9390 open_recv_stream(session, 309);
9391 open_recv_stream(session, 311);
9392 open_recv_stream(session, 319);
9394 CU_ASSERT(0 == nghttp2_submit_shutdown_notice(session));
9396 ud.frame_send_cb_called = 0;
9398 CU_ASSERT(0 == nghttp2_session_send(session));
9400 CU_ASSERT(1 == ud.frame_send_cb_called);
9401 CU_ASSERT((1u << 31) - 1 == session->local_last_stream_id);
9403 CU_ASSERT(0 == nghttp2_submit_goaway(session, NGHTTP2_FLAG_NONE, 311,
9404 NGHTTP2_NO_ERROR, NULL, 0));
9406 ud.frame_send_cb_called = 0;
9407 ud.stream_close_cb_called = 0;
9409 CU_ASSERT(0 == nghttp2_session_send(session));
9411 CU_ASSERT(1 == ud.frame_send_cb_called);
9412 CU_ASSERT(311 == session->local_last_stream_id);
9413 CU_ASSERT(1 == ud.stream_close_cb_called);
9416 nghttp2_session_terminate_session2(session, 301, NGHTTP2_NO_ERROR));
9418 ud.frame_send_cb_called = 0;
9419 ud.stream_close_cb_called = 0;
9421 CU_ASSERT(0 == nghttp2_session_send(session));
9423 CU_ASSERT(1 == ud.frame_send_cb_called);
9424 CU_ASSERT(301 == session->local_last_stream_id);
9425 CU_ASSERT(2 == ud.stream_close_cb_called);
9427 CU_ASSERT(NULL != nghttp2_session_get_stream(session, 301));
9428 CU_ASSERT(NULL != nghttp2_session_get_stream(session, 302));
9429 CU_ASSERT(NULL == nghttp2_session_get_stream(session, 309));
9430 CU_ASSERT(NULL == nghttp2_session_get_stream(session, 311));
9431 CU_ASSERT(NULL == nghttp2_session_get_stream(session, 319));
9433 nghttp2_session_del(session);
9436 void test_nghttp2_session_on_header_temporal_failure(void) {
9437 nghttp2_session *session;
9438 nghttp2_session_callbacks callbacks;
9442 nghttp2_hd_deflater deflater;
9443 nghttp2_nv nv[] = {MAKE_NV("alpha", "bravo"), MAKE_NV("charlie", "delta")};
9447 nghttp2_frame frame;
9448 nghttp2_frame_hd hd;
9449 nghttp2_outbound_item *item;
9452 mem = nghttp2_mem_default();
9453 memset(&callbacks, 0, sizeof(callbacks));
9454 callbacks.on_header_callback = temporal_failure_on_header_callback;
9456 nghttp2_session_server_new(&session, &callbacks, &ud);
9458 frame_pack_bufs_init(&bufs);
9460 nghttp2_hd_deflate_init(&deflater, mem);
9462 nghttp2_nv_array_copy(&nva, reqnv, ARRLEN(reqnv), mem);
9464 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_STREAM, 1,
9465 NGHTTP2_HCAT_REQUEST, NULL, nva, ARRLEN(reqnv));
9466 nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
9467 nghttp2_frame_headers_free(&frame.headers, mem);
9469 /* We are going to create CONTINUATION. First serialize header
9470 block, and then frame header. */
9471 hdpos = nghttp2_bufs_len(&bufs);
9473 buf = &bufs.head->buf;
9474 buf->last += NGHTTP2_FRAME_HDLEN;
9476 nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, &nv[1], 1);
9478 nghttp2_frame_hd_init(&hd,
9479 nghttp2_bufs_len(&bufs) - hdpos - NGHTTP2_FRAME_HDLEN,
9480 NGHTTP2_CONTINUATION, NGHTTP2_FLAG_END_HEADERS, 1);
9482 nghttp2_frame_pack_frame_hd(&buf->pos[hdpos], &hd);
9484 ud.header_cb_called = 0;
9485 rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_bufs_len(&bufs));
9487 CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == rv);
9488 CU_ASSERT(1 == ud.header_cb_called);
9490 item = nghttp2_session_get_next_ob_item(session);
9492 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
9493 CU_ASSERT(1 == item->frame.hd.stream_id);
9495 /* Make sure no header decompression error occurred */
9496 CU_ASSERT(NGHTTP2_GOAWAY_NONE == session->goaway_flags);
9498 nghttp2_hd_deflate_free(&deflater);
9499 nghttp2_session_del(session);
9501 nghttp2_bufs_reset(&bufs);
9503 /* Check for PUSH_PROMISE */
9504 nghttp2_hd_deflate_init(&deflater, mem);
9505 nghttp2_session_client_new(&session, &callbacks, &ud);
9507 open_sent_stream(session, 1);
9509 rv = pack_push_promise(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, 2,
9510 reqnv, ARRLEN(reqnv), mem);
9513 ud.header_cb_called = 0;
9514 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
9515 nghttp2_bufs_len(&bufs));
9516 CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == rv);
9517 CU_ASSERT(1 == ud.header_cb_called);
9519 item = nghttp2_session_get_next_ob_item(session);
9520 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
9521 CU_ASSERT(2 == item->frame.hd.stream_id);
9522 CU_ASSERT(NGHTTP2_INTERNAL_ERROR == item->frame.rst_stream.error_code);
9524 nghttp2_session_del(session);
9525 nghttp2_hd_deflate_free(&deflater);
9526 nghttp2_bufs_free(&bufs);
9529 void test_nghttp2_session_recv_client_magic(void) {
9530 nghttp2_session *session;
9531 nghttp2_session_callbacks callbacks;
9533 nghttp2_frame ping_frame;
9536 /* enable global nghttp2_enable_strict_preface here */
9537 nghttp2_enable_strict_preface = 1;
9539 memset(&callbacks, 0, sizeof(callbacks));
9541 /* Check success case */
9542 nghttp2_session_server_new(&session, &callbacks, NULL);
9544 rv = nghttp2_session_mem_recv(session, (const uint8_t *)NGHTTP2_CLIENT_MAGIC,
9545 NGHTTP2_CLIENT_MAGIC_LEN);
9547 CU_ASSERT(rv == NGHTTP2_CLIENT_MAGIC_LEN);
9548 CU_ASSERT(NGHTTP2_IB_READ_FIRST_SETTINGS == session->iframe.state);
9550 /* Receiving PING is error because we want SETTINGS. */
9551 nghttp2_frame_ping_init(&ping_frame.ping, NGHTTP2_FLAG_NONE, NULL);
9553 nghttp2_frame_pack_frame_hd(buf, &ping_frame.ping.hd);
9555 rv = nghttp2_session_mem_recv(session, buf, NGHTTP2_FRAME_HDLEN);
9556 CU_ASSERT(NGHTTP2_FRAME_HDLEN == rv);
9557 CU_ASSERT(NGHTTP2_IB_IGN_ALL == session->iframe.state);
9558 CU_ASSERT(0 == session->iframe.payloadleft);
9560 nghttp2_frame_ping_free(&ping_frame.ping);
9562 nghttp2_session_del(session);
9564 /* Check bad case */
9565 nghttp2_session_server_new(&session, &callbacks, NULL);
9567 /* Feed magic with one byte less */
9568 rv = nghttp2_session_mem_recv(session, (const uint8_t *)NGHTTP2_CLIENT_MAGIC,
9569 NGHTTP2_CLIENT_MAGIC_LEN - 1);
9571 CU_ASSERT(rv == NGHTTP2_CLIENT_MAGIC_LEN - 1);
9572 CU_ASSERT(NGHTTP2_IB_READ_CLIENT_MAGIC == session->iframe.state);
9573 CU_ASSERT(1 == session->iframe.payloadleft);
9575 rv = nghttp2_session_mem_recv(session, (const uint8_t *)"\0", 1);
9577 CU_ASSERT(NGHTTP2_ERR_BAD_CLIENT_MAGIC == rv);
9579 nghttp2_session_del(session);
9581 /* disable global nghttp2_enable_strict_preface here */
9582 nghttp2_enable_strict_preface = 0;
9585 void test_nghttp2_session_delete_data_item(void) {
9586 nghttp2_session *session;
9587 nghttp2_session_callbacks callbacks;
9589 nghttp2_data_provider prd;
9591 memset(&callbacks, 0, sizeof(callbacks));
9593 nghttp2_session_server_new(&session, &callbacks, NULL);
9595 a = open_recv_stream(session, 1);
9596 open_recv_stream_with_dep(session, 3, a);
9598 /* We don't care about these members, since we won't send data */
9599 prd.source.ptr = NULL;
9600 prd.read_callback = fail_data_source_read_callback;
9602 CU_ASSERT(0 == nghttp2_submit_data(session, NGHTTP2_FLAG_NONE, 1, &prd));
9603 CU_ASSERT(0 == nghttp2_submit_data(session, NGHTTP2_FLAG_NONE, 3, &prd));
9605 nghttp2_session_del(session);
9608 void test_nghttp2_session_open_idle_stream(void) {
9609 nghttp2_session *session;
9610 nghttp2_session_callbacks callbacks;
9611 nghttp2_stream *stream;
9612 nghttp2_stream *opened_stream;
9613 nghttp2_priority_spec pri_spec;
9614 nghttp2_frame frame;
9616 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
9618 nghttp2_session_server_new(&session, &callbacks, NULL);
9620 nghttp2_priority_spec_init(&pri_spec, 0, 3, 0);
9622 nghttp2_frame_priority_init(&frame.priority, 1, &pri_spec);
9624 CU_ASSERT(0 == nghttp2_session_on_priority_received(session, &frame));
9626 stream = nghttp2_session_get_stream_raw(session, 1);
9628 CU_ASSERT(NGHTTP2_STREAM_IDLE == stream->state);
9629 CU_ASSERT(NULL == stream->closed_prev);
9630 CU_ASSERT(NULL == stream->closed_next);
9631 CU_ASSERT(1 == session->num_idle_streams);
9632 CU_ASSERT(session->idle_stream_head == stream);
9633 CU_ASSERT(session->idle_stream_tail == stream);
9635 opened_stream = open_recv_stream2(session, 1, NGHTTP2_STREAM_OPENING);
9637 CU_ASSERT(stream == opened_stream);
9638 CU_ASSERT(NGHTTP2_STREAM_OPENING == stream->state);
9639 CU_ASSERT(0 == session->num_idle_streams);
9640 CU_ASSERT(NULL == session->idle_stream_head);
9641 CU_ASSERT(NULL == session->idle_stream_tail);
9643 nghttp2_frame_priority_free(&frame.priority);
9645 nghttp2_session_del(session);
9648 void test_nghttp2_session_cancel_reserved_remote(void) {
9649 nghttp2_session *session;
9650 nghttp2_session_callbacks callbacks;
9651 nghttp2_stream *stream;
9652 nghttp2_frame frame;
9655 nghttp2_hd_deflater deflater;
9660 mem = nghttp2_mem_default();
9661 frame_pack_bufs_init(&bufs);
9663 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
9664 callbacks.send_callback = null_send_callback;
9666 nghttp2_session_client_new(&session, &callbacks, NULL);
9668 nghttp2_hd_deflate_init(&deflater, mem);
9670 stream = open_recv_stream2(session, 2, NGHTTP2_STREAM_RESERVED);
9672 nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, 2, NGHTTP2_CANCEL);
9674 CU_ASSERT(NGHTTP2_STREAM_CLOSING == stream->state);
9676 CU_ASSERT(0 == nghttp2_session_send(session));
9678 nvlen = ARRLEN(resnv);
9679 nghttp2_nv_array_copy(&nva, resnv, nvlen, mem);
9681 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 2,
9682 NGHTTP2_HCAT_PUSH_RESPONSE, NULL, nva, nvlen);
9683 rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
9687 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
9688 nghttp2_buf_len(&bufs.head->buf));
9690 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
9692 /* stream is not dangling, so assign NULL */
9695 /* No RST_STREAM or GOAWAY is generated since stream should be in
9696 NGHTTP2_STREAM_CLOSING and push response should be ignored. */
9697 CU_ASSERT(0 == nghttp2_outbound_queue_size(&session->ob_reg));
9699 /* Check that we can receive push response HEADERS while RST_STREAM
9701 open_recv_stream2(session, 4, NGHTTP2_STREAM_RESERVED);
9703 nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, 2, NGHTTP2_CANCEL);
9705 nghttp2_bufs_reset(&bufs);
9707 frame.hd.stream_id = 4;
9708 rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
9712 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
9713 nghttp2_buf_len(&bufs.head->buf));
9715 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
9717 CU_ASSERT(1 == nghttp2_outbound_queue_size(&session->ob_reg));
9719 nghttp2_frame_headers_free(&frame.headers, mem);
9721 nghttp2_hd_deflate_free(&deflater);
9723 nghttp2_session_del(session);
9725 nghttp2_bufs_free(&bufs);
9728 void test_nghttp2_session_reset_pending_headers(void) {
9729 nghttp2_session *session;
9730 nghttp2_session_callbacks callbacks;
9731 nghttp2_stream *stream;
9735 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
9736 callbacks.send_callback = null_send_callback;
9737 callbacks.on_frame_send_callback = on_frame_send_callback;
9738 callbacks.on_frame_not_send_callback = on_frame_not_send_callback;
9739 callbacks.on_stream_close_callback = on_stream_close_callback;
9741 nghttp2_session_client_new(&session, &callbacks, &ud);
9743 stream_id = nghttp2_submit_request(session, NULL, NULL, 0, NULL, NULL);
9744 CU_ASSERT(stream_id >= 1);
9746 nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, stream_id,
9749 session->remote_settings.max_concurrent_streams = 0;
9751 /* RST_STREAM cancels pending HEADERS and is not actually sent. */
9752 ud.frame_send_cb_called = 0;
9753 CU_ASSERT(0 == nghttp2_session_send(session));
9755 CU_ASSERT(0 == ud.frame_send_cb_called);
9757 stream = nghttp2_session_get_stream(session, stream_id);
9759 CU_ASSERT(NULL == stream);
9761 /* See HEADERS is not sent. on_stream_close is called just like
9762 transmission failure. */
9763 session->remote_settings.max_concurrent_streams = 1;
9765 ud.frame_not_send_cb_called = 0;
9766 ud.stream_close_error_code = 0;
9767 CU_ASSERT(0 == nghttp2_session_send(session));
9769 CU_ASSERT(1 == ud.frame_not_send_cb_called);
9770 CU_ASSERT(NGHTTP2_HEADERS == ud.not_sent_frame_type);
9771 CU_ASSERT(NGHTTP2_CANCEL == ud.stream_close_error_code);
9773 stream = nghttp2_session_get_stream(session, stream_id);
9775 CU_ASSERT(NULL == stream);
9777 nghttp2_session_del(session);
9780 void test_nghttp2_session_send_data_callback(void) {
9781 nghttp2_session *session;
9782 nghttp2_session_callbacks callbacks;
9783 nghttp2_data_provider data_prd;
9786 nghttp2_frame_hd hd;
9788 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
9789 callbacks.send_callback = accumulator_send_callback;
9790 callbacks.send_data_callback = send_data_callback;
9792 data_prd.read_callback = no_copy_data_source_read_callback;
9797 ud.data_source_length = NGHTTP2_DATA_PAYLOADLEN * 2;
9799 nghttp2_session_client_new(&session, &callbacks, &ud);
9801 open_sent_stream(session, 1);
9803 nghttp2_submit_data(session, NGHTTP2_FLAG_END_STREAM, 1, &data_prd);
9805 CU_ASSERT(0 == nghttp2_session_send(session));
9807 CU_ASSERT((NGHTTP2_FRAME_HDLEN + NGHTTP2_DATA_PAYLOADLEN) * 2 == acc.length);
9809 nghttp2_frame_unpack_frame_hd(&hd, acc.buf);
9811 CU_ASSERT(16384 == hd.length);
9812 CU_ASSERT(NGHTTP2_DATA == hd.type);
9813 CU_ASSERT(NGHTTP2_FLAG_NONE == hd.flags);
9815 nghttp2_frame_unpack_frame_hd(&hd, acc.buf + NGHTTP2_FRAME_HDLEN + hd.length);
9817 CU_ASSERT(16384 == hd.length);
9818 CU_ASSERT(NGHTTP2_DATA == hd.type);
9819 CU_ASSERT(NGHTTP2_FLAG_END_STREAM == hd.flags);
9821 nghttp2_session_del(session);
9824 void test_nghttp2_session_on_begin_headers_temporal_failure(void) {
9825 nghttp2_session *session;
9826 nghttp2_session_callbacks callbacks;
9831 nghttp2_hd_deflater deflater;
9832 nghttp2_outbound_item *item;
9834 mem = nghttp2_mem_default();
9835 frame_pack_bufs_init(&bufs);
9836 nghttp2_hd_deflate_init(&deflater, mem);
9838 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
9839 callbacks.on_begin_headers_callback =
9840 temporal_failure_on_begin_headers_callback;
9841 callbacks.on_header_callback = on_header_callback;
9842 callbacks.on_frame_recv_callback = on_frame_recv_callback;
9843 callbacks.send_callback = null_send_callback;
9844 nghttp2_session_server_new(&session, &callbacks, &ud);
9846 rv = pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, reqnv,
9847 ARRLEN(reqnv), mem);
9850 ud.header_cb_called = 0;
9851 ud.frame_recv_cb_called = 0;
9852 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
9853 nghttp2_bufs_len(&bufs));
9854 CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == rv);
9855 CU_ASSERT(0 == ud.header_cb_called);
9856 CU_ASSERT(0 == ud.frame_recv_cb_called);
9858 item = nghttp2_session_get_next_ob_item(session);
9859 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
9860 CU_ASSERT(1 == item->frame.hd.stream_id);
9861 CU_ASSERT(NGHTTP2_INTERNAL_ERROR == item->frame.rst_stream.error_code);
9863 nghttp2_session_del(session);
9864 nghttp2_hd_deflate_free(&deflater);
9866 nghttp2_bufs_reset(&bufs);
9867 /* check for PUSH_PROMISE */
9868 nghttp2_hd_deflate_init(&deflater, mem);
9869 nghttp2_session_client_new(&session, &callbacks, &ud);
9871 open_sent_stream(session, 1);
9873 rv = pack_push_promise(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, 2,
9874 reqnv, ARRLEN(reqnv), mem);
9877 ud.header_cb_called = 0;
9878 ud.frame_recv_cb_called = 0;
9879 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
9880 nghttp2_bufs_len(&bufs));
9881 CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == rv);
9882 CU_ASSERT(0 == ud.header_cb_called);
9883 CU_ASSERT(0 == ud.frame_recv_cb_called);
9885 item = nghttp2_session_get_next_ob_item(session);
9886 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
9887 CU_ASSERT(2 == item->frame.hd.stream_id);
9888 CU_ASSERT(NGHTTP2_INTERNAL_ERROR == item->frame.rst_stream.error_code);
9890 nghttp2_session_del(session);
9891 nghttp2_hd_deflate_free(&deflater);
9892 nghttp2_bufs_free(&bufs);
9895 void test_nghttp2_session_defer_then_close(void) {
9896 nghttp2_session *session;
9897 nghttp2_session_callbacks callbacks;
9898 nghttp2_data_provider prd;
9900 const uint8_t *datap;
9902 nghttp2_frame frame;
9904 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
9905 callbacks.send_callback = null_send_callback;
9907 nghttp2_session_client_new(&session, &callbacks, NULL);
9909 prd.read_callback = defer_data_source_read_callback;
9911 rv = nghttp2_submit_request(session, NULL, reqnv, ARRLEN(reqnv), &prd, NULL);
9914 /* This sends HEADERS */
9915 datalen = nghttp2_session_mem_send(session, &datap);
9917 CU_ASSERT(datalen > 0);
9919 /* This makes DATA item deferred */
9920 datalen = nghttp2_session_mem_send(session, &datap);
9922 CU_ASSERT(datalen == 0);
9924 nghttp2_frame_rst_stream_init(&frame.rst_stream, 1, NGHTTP2_CANCEL);
9926 /* Assertion failure; GH-264 */
9927 rv = nghttp2_session_on_rst_stream_received(session, &frame);
9931 nghttp2_session_del(session);
9934 static int submit_response_on_stream_close(nghttp2_session *session,
9936 uint32_t error_code,
9938 nghttp2_data_provider data_prd;
9942 data_prd.read_callback = temporal_failure_data_source_read_callback;
9944 // Attempt to submit response or data to the stream being closed
9945 switch (stream_id) {
9947 CU_ASSERT(0 == nghttp2_submit_response(session, stream_id, resnv,
9948 ARRLEN(resnv), &data_prd));
9951 CU_ASSERT(0 == nghttp2_submit_data(session, NGHTTP2_FLAG_NONE, stream_id,
9959 void test_nghttp2_session_detach_item_from_closed_stream(void) {
9960 nghttp2_session *session;
9961 nghttp2_session_callbacks callbacks;
9963 memset(&callbacks, 0, sizeof(callbacks));
9965 callbacks.send_callback = null_send_callback;
9966 callbacks.on_stream_close_callback = submit_response_on_stream_close;
9968 nghttp2_session_server_new(&session, &callbacks, NULL);
9970 open_recv_stream(session, 1);
9971 open_recv_stream(session, 3);
9973 nghttp2_session_close_stream(session, 1, NGHTTP2_NO_ERROR);
9974 nghttp2_session_close_stream(session, 3, NGHTTP2_NO_ERROR);
9976 CU_ASSERT(0 == nghttp2_session_send(session));
9978 nghttp2_session_del(session);
9981 void test_nghttp2_session_flooding(void) {
9982 nghttp2_session *session;
9983 nghttp2_session_callbacks callbacks;
9986 nghttp2_frame frame;
9990 mem = nghttp2_mem_default();
9992 frame_pack_bufs_init(&bufs);
9994 memset(&callbacks, 0, sizeof(callbacks));
9997 nghttp2_session_server_new(&session, &callbacks, NULL);
9999 nghttp2_frame_ping_init(&frame.ping, NGHTTP2_FLAG_NONE, NULL);
10000 nghttp2_frame_pack_ping(&bufs, &frame.ping);
10001 nghttp2_frame_ping_free(&frame.ping);
10003 buf = &bufs.head->buf;
10005 for (i = 0; i < NGHTTP2_DEFAULT_MAX_OBQ_FLOOD_ITEM; ++i) {
10007 (ssize_t)nghttp2_buf_len(buf) ==
10008 nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf)));
10011 CU_ASSERT(NGHTTP2_ERR_FLOODED ==
10012 nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf)));
10014 nghttp2_session_del(session);
10017 nghttp2_bufs_reset(&bufs);
10019 nghttp2_session_server_new(&session, &callbacks, NULL);
10021 nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE, NULL, 0);
10022 nghttp2_frame_pack_settings(&bufs, &frame.settings);
10023 nghttp2_frame_settings_free(&frame.settings, mem);
10025 buf = &bufs.head->buf;
10027 for (i = 0; i < NGHTTP2_DEFAULT_MAX_OBQ_FLOOD_ITEM; ++i) {
10029 (ssize_t)nghttp2_buf_len(buf) ==
10030 nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf)));
10033 CU_ASSERT(NGHTTP2_ERR_FLOODED ==
10034 nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf)));
10036 nghttp2_session_del(session);
10037 nghttp2_bufs_free(&bufs);
10040 void test_nghttp2_session_change_stream_priority(void) {
10041 nghttp2_session *session;
10042 nghttp2_session_callbacks callbacks;
10043 nghttp2_stream *stream1, *stream2, *stream3, *stream5;
10044 nghttp2_priority_spec pri_spec;
10047 memset(&callbacks, 0, sizeof(callbacks));
10049 nghttp2_session_server_new(&session, &callbacks, NULL);
10051 stream1 = open_recv_stream(session, 1);
10052 stream3 = open_recv_stream_with_dep_weight(session, 3, 199, stream1);
10053 stream2 = open_sent_stream_with_dep_weight(session, 2, 101, stream3);
10055 nghttp2_priority_spec_init(&pri_spec, 1, 256, 0);
10057 rv = nghttp2_session_change_stream_priority(session, 2, &pri_spec);
10059 CU_ASSERT(0 == rv);
10061 CU_ASSERT(stream1 == stream2->dep_prev);
10062 CU_ASSERT(256 == stream2->weight);
10064 /* Cannot change stream which does not exist */
10065 rv = nghttp2_session_change_stream_priority(session, 5, &pri_spec);
10066 CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT == rv);
10068 /* It is an error to depend on itself */
10069 rv = nghttp2_session_change_stream_priority(session, 1, &pri_spec);
10070 CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT == rv);
10072 /* It is an error to change priority of root stream (0) */
10073 rv = nghttp2_session_change_stream_priority(session, 0, &pri_spec);
10074 CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT == rv);
10076 /* Depends on the non-existing idle stream. This creates that idle
10078 nghttp2_priority_spec_init(&pri_spec, 5, 9, 1);
10080 rv = nghttp2_session_change_stream_priority(session, 2, &pri_spec);
10082 CU_ASSERT(0 == rv);
10084 stream5 = nghttp2_session_get_stream_raw(session, 5);
10086 CU_ASSERT(NULL != stream5);
10087 CU_ASSERT(&session->root == stream5->dep_prev);
10088 CU_ASSERT(stream5 == stream2->dep_prev);
10089 CU_ASSERT(9 == stream2->weight);
10091 nghttp2_session_del(session);
10093 /* Check that this works in client session too */
10094 nghttp2_session_client_new(&session, &callbacks, NULL);
10096 stream1 = open_sent_stream(session, 1);
10098 nghttp2_priority_spec_init(&pri_spec, 5, 9, 1);
10100 rv = nghttp2_session_change_stream_priority(session, 1, &pri_spec);
10102 CU_ASSERT(0 == rv);
10104 stream5 = nghttp2_session_get_stream_raw(session, 5);
10106 CU_ASSERT(NULL != stream5);
10107 CU_ASSERT(&session->root == stream5->dep_prev);
10108 CU_ASSERT(stream5 == stream1->dep_prev);
10109 CU_ASSERT(9 == stream1->weight);
10111 nghttp2_session_del(session);
10114 void test_nghttp2_session_create_idle_stream(void) {
10115 nghttp2_session *session;
10116 nghttp2_session_callbacks callbacks;
10117 nghttp2_stream *stream2, *stream4, *stream8, *stream10;
10118 nghttp2_priority_spec pri_spec;
10122 memset(&callbacks, 0, sizeof(callbacks));
10123 callbacks.send_callback = null_send_callback;
10125 nghttp2_session_server_new(&session, &callbacks, NULL);
10127 stream2 = open_sent_stream(session, 2);
10129 nghttp2_priority_spec_init(&pri_spec, 2, 111, 1);
10131 rv = nghttp2_session_create_idle_stream(session, 4, &pri_spec);
10133 CU_ASSERT(0 == rv);
10135 stream4 = nghttp2_session_get_stream_raw(session, 4);
10137 CU_ASSERT(4 == stream4->stream_id);
10138 CU_ASSERT(111 == stream4->weight);
10139 CU_ASSERT(stream2 == stream4->dep_prev);
10140 CU_ASSERT(stream4 == stream2->dep_next);
10142 /* If pri_spec->stream_id does not exist, and it is idle stream, it
10144 nghttp2_priority_spec_init(&pri_spec, 10, 109, 0);
10146 rv = nghttp2_session_create_idle_stream(session, 8, &pri_spec);
10148 CU_ASSERT(0 == rv);
10150 stream8 = nghttp2_session_get_stream_raw(session, 8);
10151 stream10 = nghttp2_session_get_stream_raw(session, 10);
10153 CU_ASSERT(8 == stream8->stream_id);
10154 CU_ASSERT(109 == stream8->weight);
10155 CU_ASSERT(10 == stream10->stream_id);
10156 CU_ASSERT(16 == stream10->weight);
10157 CU_ASSERT(stream10 == stream8->dep_prev);
10158 CU_ASSERT(&session->root == stream10->dep_prev);
10160 /* It is an error to attempt to create already existing idle
10162 rv = nghttp2_session_create_idle_stream(session, 4, &pri_spec);
10164 CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT == rv);
10166 /* It is an error to depend on itself */
10167 pri_spec.stream_id = 6;
10169 rv = nghttp2_session_create_idle_stream(session, 6, &pri_spec);
10170 CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT == rv);
10172 /* It is an error to create root stream (0) as idle stream */
10173 rv = nghttp2_session_create_idle_stream(session, 0, &pri_spec);
10174 CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT == rv);
10176 /* It is an error to create non-idle stream */
10177 session->last_sent_stream_id = 20;
10178 pri_spec.stream_id = 2;
10180 rv = nghttp2_session_create_idle_stream(session, 18, &pri_spec);
10182 CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT == rv);
10184 nghttp2_session_del(session);
10186 /* Check that this works in client session too */
10187 nghttp2_session_client_new(&session, &callbacks, NULL);
10189 nghttp2_priority_spec_init(&pri_spec, 4, 99, 1);
10191 rv = nghttp2_session_create_idle_stream(session, 2, &pri_spec);
10193 CU_ASSERT(0 == rv);
10195 stream4 = nghttp2_session_get_stream_raw(session, 4);
10196 stream2 = nghttp2_session_get_stream_raw(session, 2);
10198 CU_ASSERT(NULL != stream4);
10199 CU_ASSERT(NULL != stream2);
10200 CU_ASSERT(&session->root == stream4->dep_prev);
10201 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == stream4->weight);
10202 CU_ASSERT(stream4 == stream2->dep_prev);
10203 CU_ASSERT(99 == stream2->weight);
10205 nghttp2_session_del(session);
10207 /* Check that idle stream is reduced when nghttp2_session_send() is
10209 nghttp2_session_server_new(&session, &callbacks, NULL);
10211 session->local_settings.max_concurrent_streams = 30;
10213 nghttp2_priority_spec_init(&pri_spec, 0, 16, 0);
10214 for (i = 0; i < 100; ++i) {
10215 rv = nghttp2_session_create_idle_stream(session, i * 2 + 1, &pri_spec);
10217 CU_ASSERT(0 == rv);
10219 nghttp2_priority_spec_init(&pri_spec, i * 2 + 1, 16, 0);
10222 CU_ASSERT(100 == session->num_idle_streams);
10223 CU_ASSERT(0 == nghttp2_session_send(session));
10224 CU_ASSERT(30 == session->num_idle_streams);
10225 CU_ASSERT(141 == session->idle_stream_head->stream_id);
10227 nghttp2_session_del(session);
10229 /* Check that idle stream is reduced when nghttp2_session_mem_recv() is
10231 nghttp2_session_client_new(&session, &callbacks, NULL);
10233 session->local_settings.max_concurrent_streams = 30;
10235 nghttp2_priority_spec_init(&pri_spec, 0, 16, 0);
10236 for (i = 0; i < 100; ++i) {
10237 rv = nghttp2_session_create_idle_stream(session, i * 2 + 1, &pri_spec);
10239 CU_ASSERT(0 == rv);
10241 nghttp2_priority_spec_init(&pri_spec, i * 2 + 1, 16, 0);
10244 CU_ASSERT(100 == session->num_idle_streams);
10245 CU_ASSERT(0 == nghttp2_session_mem_recv(session, NULL, 0));
10246 CU_ASSERT(30 == session->num_idle_streams);
10247 CU_ASSERT(141 == session->idle_stream_head->stream_id);
10249 nghttp2_session_del(session);
10252 void test_nghttp2_session_repeated_priority_change(void) {
10253 nghttp2_session *session;
10254 nghttp2_session_callbacks callbacks;
10255 nghttp2_frame frame;
10256 nghttp2_priority_spec pri_spec;
10257 int32_t stream_id, last_stream_id;
10258 int32_t max_streams = 20;
10260 memset(&callbacks, 0, sizeof(callbacks));
10262 nghttp2_session_server_new(&session, &callbacks, NULL);
10264 session->local_settings.max_concurrent_streams = (uint32_t)max_streams;
10267 nghttp2_priority_spec_init(&pri_spec, 0, 16, 0);
10268 nghttp2_frame_priority_init(&frame.priority, 1, &pri_spec);
10270 CU_ASSERT(0 == nghttp2_session_on_priority_received(session, &frame));
10272 nghttp2_frame_priority_free(&frame.priority);
10274 last_stream_id = max_streams * 2 + 1;
10276 for (stream_id = 3; stream_id < last_stream_id; stream_id += 2) {
10277 /* 1 -> stream_id */
10278 nghttp2_priority_spec_init(&pri_spec, stream_id, 16, 0);
10279 nghttp2_frame_priority_init(&frame.priority, 1, &pri_spec);
10281 CU_ASSERT(0 == nghttp2_session_on_priority_received(session, &frame));
10283 nghttp2_frame_priority_free(&frame.priority);
10286 CU_ASSERT(20 == session->num_idle_streams);
10287 CU_ASSERT(1 == session->idle_stream_head->stream_id);
10289 /* 1 -> last_stream_id */
10290 nghttp2_priority_spec_init(&pri_spec, last_stream_id, 16, 0);
10291 nghttp2_frame_priority_init(&frame.priority, 1, &pri_spec);
10293 CU_ASSERT(0 == nghttp2_session_on_priority_received(session, &frame));
10295 nghttp2_frame_priority_free(&frame.priority);
10297 CU_ASSERT(20 == session->num_idle_streams);
10298 CU_ASSERT(3 == session->idle_stream_head->stream_id);
10300 nghttp2_session_del(session);
10303 void test_nghttp2_session_repeated_priority_submission(void) {
10304 nghttp2_session *session;
10305 nghttp2_session_callbacks callbacks;
10306 nghttp2_priority_spec pri_spec;
10307 int32_t stream_id, last_stream_id;
10308 uint32_t max_streams = NGHTTP2_MIN_IDLE_STREAMS;
10310 memset(&callbacks, 0, sizeof(callbacks));
10312 callbacks.send_callback = null_send_callback;
10314 nghttp2_session_client_new(&session, &callbacks, NULL);
10316 session->local_settings.max_concurrent_streams = max_streams;
10319 nghttp2_priority_spec_init(&pri_spec, 0, 16, 0);
10322 nghttp2_submit_priority(session, NGHTTP2_FLAG_NONE, 1, &pri_spec));
10324 last_stream_id = (int32_t)(max_streams * 2 + 1);
10326 for (stream_id = 3; stream_id < last_stream_id; stream_id += 2) {
10327 /* 1 -> stream_id */
10328 nghttp2_priority_spec_init(&pri_spec, stream_id, 16, 0);
10331 0 == nghttp2_submit_priority(session, NGHTTP2_FLAG_NONE, 1, &pri_spec));
10334 CU_ASSERT(0 == nghttp2_session_send(session));
10335 CU_ASSERT(max_streams == session->num_idle_streams);
10336 CU_ASSERT(1 == session->idle_stream_head->stream_id);
10338 /* 1 -> last_stream_id */
10339 nghttp2_priority_spec_init(&pri_spec, last_stream_id, 16, 0);
10342 nghttp2_submit_priority(session, NGHTTP2_FLAG_NONE, 1, &pri_spec));
10344 CU_ASSERT(0 == nghttp2_session_send(session));
10345 CU_ASSERT(max_streams == session->num_idle_streams);
10346 CU_ASSERT(3 == session->idle_stream_head->stream_id);
10348 nghttp2_session_del(session);
10351 void test_nghttp2_session_set_local_window_size(void) {
10352 nghttp2_session *session;
10353 nghttp2_session_callbacks callbacks;
10354 nghttp2_outbound_item *item;
10355 nghttp2_stream *stream;
10357 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
10358 callbacks.send_callback = null_send_callback;
10360 nghttp2_session_client_new(&session, &callbacks, NULL);
10361 stream = open_sent_stream(session, 1);
10362 stream->recv_window_size = 4096;
10364 CU_ASSERT(0 == nghttp2_session_set_local_window_size(
10365 session, NGHTTP2_FLAG_NONE, 1, 65536));
10366 CU_ASSERT(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE + 1 ==
10367 stream->local_window_size);
10368 CU_ASSERT(4096 == stream->recv_window_size);
10369 CU_ASSERT(65536 - 4096 ==
10370 nghttp2_session_get_stream_local_window_size(session, 1));
10372 item = nghttp2_session_get_next_ob_item(session);
10374 CU_ASSERT(NGHTTP2_WINDOW_UPDATE == item->frame.hd.type);
10375 CU_ASSERT(1 == item->frame.window_update.hd.stream_id);
10376 CU_ASSERT(1 == item->frame.window_update.window_size_increment);
10378 CU_ASSERT(0 == nghttp2_session_send(session));
10380 /* Go decrement part */
10381 CU_ASSERT(0 == nghttp2_session_set_local_window_size(
10382 session, NGHTTP2_FLAG_NONE, 1, 32768));
10383 CU_ASSERT(32768 == stream->local_window_size);
10384 CU_ASSERT(-28672 == stream->recv_window_size);
10385 CU_ASSERT(32768 == stream->recv_reduction);
10386 CU_ASSERT(65536 - 4096 ==
10387 nghttp2_session_get_stream_local_window_size(session, 1));
10389 item = nghttp2_session_get_next_ob_item(session);
10391 CU_ASSERT(item == NULL);
10393 /* Increase local window size */
10394 CU_ASSERT(0 == nghttp2_session_set_local_window_size(
10395 session, NGHTTP2_FLAG_NONE, 1, 49152));
10396 CU_ASSERT(49152 == stream->local_window_size);
10397 CU_ASSERT(-12288 == stream->recv_window_size);
10398 CU_ASSERT(16384 == stream->recv_reduction);
10399 CU_ASSERT(65536 - 4096 ==
10400 nghttp2_session_get_stream_local_window_size(session, 1));
10401 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
10403 /* Increase local window again */
10404 CU_ASSERT(0 == nghttp2_session_set_local_window_size(
10405 session, NGHTTP2_FLAG_NONE, 1, 65537));
10406 CU_ASSERT(65537 == stream->local_window_size);
10407 CU_ASSERT(4096 == stream->recv_window_size);
10408 CU_ASSERT(0 == stream->recv_reduction);
10409 CU_ASSERT(65537 - 4096 ==
10410 nghttp2_session_get_stream_local_window_size(session, 1));
10412 item = nghttp2_session_get_next_ob_item(session);
10414 CU_ASSERT(1 == item->frame.window_update.window_size_increment);
10416 CU_ASSERT(0 == nghttp2_session_send(session));
10418 /* Check connection-level flow control */
10419 session->recv_window_size = 4096;
10420 CU_ASSERT(0 == nghttp2_session_set_local_window_size(
10421 session, NGHTTP2_FLAG_NONE, 0, 65536));
10422 CU_ASSERT(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE + 1 ==
10423 session->local_window_size);
10424 CU_ASSERT(4096 == session->recv_window_size);
10425 CU_ASSERT(65536 - 4096 == nghttp2_session_get_local_window_size(session));
10427 item = nghttp2_session_get_next_ob_item(session);
10429 CU_ASSERT(NGHTTP2_WINDOW_UPDATE == item->frame.hd.type);
10430 CU_ASSERT(0 == item->frame.window_update.hd.stream_id);
10431 CU_ASSERT(1 == item->frame.window_update.window_size_increment);
10433 CU_ASSERT(0 == nghttp2_session_send(session));
10435 /* Go decrement part */
10436 CU_ASSERT(0 == nghttp2_session_set_local_window_size(
10437 session, NGHTTP2_FLAG_NONE, 0, 32768));
10438 CU_ASSERT(32768 == session->local_window_size);
10439 CU_ASSERT(-28672 == session->recv_window_size);
10440 CU_ASSERT(32768 == session->recv_reduction);
10441 CU_ASSERT(65536 - 4096 == nghttp2_session_get_local_window_size(session));
10443 item = nghttp2_session_get_next_ob_item(session);
10445 CU_ASSERT(item == NULL);
10447 /* Increase local window size */
10448 CU_ASSERT(0 == nghttp2_session_set_local_window_size(
10449 session, NGHTTP2_FLAG_NONE, 0, 49152));
10450 CU_ASSERT(49152 == session->local_window_size);
10451 CU_ASSERT(-12288 == session->recv_window_size);
10452 CU_ASSERT(16384 == session->recv_reduction);
10453 CU_ASSERT(65536 - 4096 == nghttp2_session_get_local_window_size(session));
10454 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
10456 /* Increase local window again */
10457 CU_ASSERT(0 == nghttp2_session_set_local_window_size(
10458 session, NGHTTP2_FLAG_NONE, 0, 65537));
10459 CU_ASSERT(65537 == session->local_window_size);
10460 CU_ASSERT(4096 == session->recv_window_size);
10461 CU_ASSERT(0 == session->recv_reduction);
10462 CU_ASSERT(65537 - 4096 == nghttp2_session_get_local_window_size(session));
10464 item = nghttp2_session_get_next_ob_item(session);
10466 CU_ASSERT(1 == item->frame.window_update.window_size_increment);
10468 CU_ASSERT(0 == nghttp2_session_send(session));
10470 nghttp2_session_del(session);
10472 /* Make sure that nghttp2_session_set_local_window_size submits
10473 WINDOW_UPDATE if necessary to increase stream-level window. */
10474 nghttp2_session_client_new(&session, &callbacks, NULL);
10475 stream = open_sent_stream(session, 1);
10476 stream->recv_window_size = NGHTTP2_INITIAL_WINDOW_SIZE;
10478 CU_ASSERT(0 == nghttp2_session_set_local_window_size(
10479 session, NGHTTP2_FLAG_NONE, 1, 0));
10480 CU_ASSERT(0 == stream->recv_window_size);
10481 CU_ASSERT(0 == nghttp2_session_get_stream_local_window_size(session, 1));
10482 /* This should submit WINDOW_UPDATE frame because stream-level
10483 receiving window is now full. */
10485 nghttp2_session_set_local_window_size(session, NGHTTP2_FLAG_NONE, 1,
10486 NGHTTP2_INITIAL_WINDOW_SIZE));
10487 CU_ASSERT(0 == stream->recv_window_size);
10488 CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE ==
10489 nghttp2_session_get_stream_local_window_size(session, 1));
10491 item = nghttp2_session_get_next_ob_item(session);
10493 CU_ASSERT(NGHTTP2_WINDOW_UPDATE == item->frame.hd.type);
10494 CU_ASSERT(1 == item->frame.hd.stream_id);
10495 CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE ==
10496 item->frame.window_update.window_size_increment);
10498 nghttp2_session_del(session);
10500 /* Make sure that nghttp2_session_set_local_window_size submits
10501 WINDOW_UPDATE if necessary to increase connection-level
10503 nghttp2_session_client_new(&session, &callbacks, NULL);
10504 session->recv_window_size = NGHTTP2_INITIAL_WINDOW_SIZE;
10506 CU_ASSERT(0 == nghttp2_session_set_local_window_size(
10507 session, NGHTTP2_FLAG_NONE, 0, 0));
10508 CU_ASSERT(0 == session->recv_window_size);
10509 CU_ASSERT(0 == nghttp2_session_get_local_window_size(session));
10510 /* This should submit WINDOW_UPDATE frame because connection-level
10511 receiving window is now full. */
10513 nghttp2_session_set_local_window_size(session, NGHTTP2_FLAG_NONE, 0,
10514 NGHTTP2_INITIAL_WINDOW_SIZE));
10515 CU_ASSERT(0 == session->recv_window_size);
10516 CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE ==
10517 nghttp2_session_get_local_window_size(session));
10519 item = nghttp2_session_get_next_ob_item(session);
10521 CU_ASSERT(NGHTTP2_WINDOW_UPDATE == item->frame.hd.type);
10522 CU_ASSERT(0 == item->frame.hd.stream_id);
10523 CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE ==
10524 item->frame.window_update.window_size_increment);
10526 nghttp2_session_del(session);
10529 void test_nghttp2_session_cancel_from_before_frame_send(void) {
10531 nghttp2_session *session;
10532 nghttp2_session_callbacks callbacks;
10534 nghttp2_settings_entry iv;
10535 nghttp2_data_provider data_prd;
10537 nghttp2_stream *stream;
10539 memset(&callbacks, 0, sizeof(callbacks));
10541 callbacks.before_frame_send_callback = cancel_before_frame_send_callback;
10542 callbacks.on_frame_not_send_callback = on_frame_not_send_callback;
10543 callbacks.send_callback = null_send_callback;
10545 nghttp2_session_client_new(&session, &callbacks, &ud);
10547 iv.settings_id = 0;
10548 iv.value = 1000000009;
10550 rv = nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, &iv, 1);
10552 CU_ASSERT(0 == rv);
10554 ud.frame_send_cb_called = 0;
10555 ud.before_frame_send_cb_called = 0;
10556 ud.frame_not_send_cb_called = 0;
10558 rv = nghttp2_session_send(session);
10560 CU_ASSERT(0 == rv);
10561 CU_ASSERT(0 == ud.frame_send_cb_called);
10562 CU_ASSERT(1 == ud.before_frame_send_cb_called);
10563 CU_ASSERT(1 == ud.frame_not_send_cb_called);
10565 data_prd.source.ptr = NULL;
10566 data_prd.read_callback = temporal_failure_data_source_read_callback;
10568 stream_id = nghttp2_submit_request(session, NULL, reqnv, ARRLEN(reqnv),
10571 CU_ASSERT(stream_id > 0);
10573 ud.frame_send_cb_called = 0;
10574 ud.before_frame_send_cb_called = 0;
10575 ud.frame_not_send_cb_called = 0;
10577 rv = nghttp2_session_send(session);
10579 CU_ASSERT(0 == rv);
10580 CU_ASSERT(0 == ud.frame_send_cb_called);
10581 CU_ASSERT(1 == ud.before_frame_send_cb_called);
10582 CU_ASSERT(1 == ud.frame_not_send_cb_called);
10584 stream = nghttp2_session_get_stream_raw(session, stream_id);
10586 CU_ASSERT(NULL == stream);
10588 nghttp2_session_del(session);
10590 nghttp2_session_server_new(&session, &callbacks, &ud);
10592 open_recv_stream(session, 1);
10594 stream_id = nghttp2_submit_push_promise(session, NGHTTP2_FLAG_NONE, 1, reqnv,
10595 ARRLEN(reqnv), NULL);
10597 CU_ASSERT(stream_id > 0);
10599 ud.frame_send_cb_called = 0;
10600 ud.before_frame_send_cb_called = 0;
10601 ud.frame_not_send_cb_called = 0;
10603 rv = nghttp2_session_send(session);
10605 CU_ASSERT(0 == rv);
10606 CU_ASSERT(0 == ud.frame_send_cb_called);
10607 CU_ASSERT(1 == ud.before_frame_send_cb_called);
10608 CU_ASSERT(1 == ud.frame_not_send_cb_called);
10610 stream = nghttp2_session_get_stream_raw(session, stream_id);
10612 CU_ASSERT(NULL == stream);
10614 nghttp2_session_del(session);
10617 void test_nghttp2_session_too_many_settings(void) {
10618 nghttp2_session *session;
10619 nghttp2_option *option;
10620 nghttp2_session_callbacks callbacks;
10621 nghttp2_frame frame;
10626 nghttp2_settings_entry iv[3];
10628 nghttp2_outbound_item *item;
10630 mem = nghttp2_mem_default();
10631 frame_pack_bufs_init(&bufs);
10633 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
10634 callbacks.on_frame_recv_callback = on_frame_recv_callback;
10635 callbacks.send_callback = null_send_callback;
10637 nghttp2_option_new(&option);
10638 nghttp2_option_set_max_settings(option, 1);
10640 nghttp2_session_client_new2(&session, &callbacks, &ud, option);
10642 CU_ASSERT(1 == session->max_settings);
10644 nghttp2_option_del(option);
10646 iv[0].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
10647 iv[0].value = 3000;
10649 iv[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
10650 iv[1].value = 16384;
10652 nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE, dup_iv(iv, 2),
10655 rv = nghttp2_frame_pack_settings(&bufs, &frame.settings);
10657 CU_ASSERT(0 == rv);
10658 CU_ASSERT(nghttp2_bufs_len(&bufs) > 0);
10660 nghttp2_frame_settings_free(&frame.settings, mem);
10662 buf = &bufs.head->buf;
10663 assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
10665 ud.frame_recv_cb_called = 0;
10667 rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
10668 CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv);
10670 item = nghttp2_session_get_next_ob_item(session);
10671 CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
10673 nghttp2_bufs_reset(&bufs);
10674 nghttp2_bufs_free(&bufs);
10675 nghttp2_session_del(session);
10679 prepare_session_removed_closed_stream(nghttp2_session *session,
10680 nghttp2_hd_deflater *deflater) {
10682 nghttp2_settings_entry iv;
10687 nghttp2_stream *stream;
10688 nghttp2_frame_hd hd;
10690 mem = nghttp2_mem_default();
10692 frame_pack_bufs_init(&bufs);
10694 iv.settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS;
10697 rv = nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, &iv, 1);
10699 CU_ASSERT(0 == rv);
10701 rv = nghttp2_session_send(session);
10703 CU_ASSERT(0 == rv);
10705 for (i = 1; i <= 3; i += 2) {
10706 rv = pack_headers(&bufs, deflater, i,
10707 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM, reqnv,
10708 ARRLEN(reqnv), mem);
10710 CU_ASSERT(0 == rv);
10712 nread = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
10713 nghttp2_bufs_len(&bufs));
10715 CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == nread);
10717 nghttp2_bufs_reset(&bufs);
10720 nghttp2_session_close_stream(session, 3, NGHTTP2_NO_ERROR);
10722 rv = pack_headers(&bufs, deflater, 5,
10723 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM, reqnv,
10724 ARRLEN(reqnv), mem);
10726 CU_ASSERT(0 == rv);
10728 /* Receiving stream 5 will erase stream 3 from closed stream list */
10729 nread = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
10730 nghttp2_bufs_len(&bufs));
10732 CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == nread);
10734 stream = nghttp2_session_get_stream_raw(session, 3);
10736 CU_ASSERT(NULL == stream);
10738 /* Since the current max concurrent streams is
10739 NGHTTP2_DEFAULT_MAX_CONCURRENT_STREAMS, receiving frame on stream
10741 nghttp2_bufs_reset(&bufs);
10742 rv = pack_headers(&bufs, deflater, 3,
10743 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM,
10744 trailernv, ARRLEN(trailernv), mem);
10746 CU_ASSERT(0 == rv);
10748 nread = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
10749 nghttp2_bufs_len(&bufs));
10751 CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == nread);
10752 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
10754 nghttp2_frame_hd_init(&hd, 0, NGHTTP2_DATA, NGHTTP2_FLAG_NONE, 3);
10755 nghttp2_bufs_reset(&bufs);
10756 nghttp2_frame_pack_frame_hd(bufs.head->buf.last, &hd);
10757 bufs.head->buf.last += NGHTTP2_FRAME_HDLEN;
10759 nread = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
10760 nghttp2_bufs_len(&bufs));
10762 CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == nread);
10763 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
10765 /* Now server receives SETTINGS ACK */
10766 nghttp2_frame_hd_init(&hd, 0, NGHTTP2_SETTINGS, NGHTTP2_FLAG_ACK, 0);
10767 nghttp2_bufs_reset(&bufs);
10768 nghttp2_frame_pack_frame_hd(bufs.head->buf.last, &hd);
10769 bufs.head->buf.last += NGHTTP2_FRAME_HDLEN;
10771 nread = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
10772 nghttp2_bufs_len(&bufs));
10774 CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == nread);
10776 nghttp2_bufs_free(&bufs);
10779 void test_nghttp2_session_removed_closed_stream(void) {
10780 nghttp2_session *session;
10781 nghttp2_session_callbacks callbacks;
10783 nghttp2_hd_deflater deflater;
10787 nghttp2_frame_hd hd;
10788 nghttp2_outbound_item *item;
10790 mem = nghttp2_mem_default();
10792 frame_pack_bufs_init(&bufs);
10794 memset(&callbacks, 0, sizeof(callbacks));
10796 callbacks.send_callback = null_send_callback;
10798 nghttp2_session_server_new(&session, &callbacks, NULL);
10800 /* Now local max concurrent streams is still unlimited, pending max
10801 concurrent streams is now 2. */
10803 nghttp2_hd_deflate_init(&deflater, mem);
10805 prepare_session_removed_closed_stream(session, &deflater);
10807 /* Now current max concurrent streams is 2. Receiving frame on
10808 stream 3 is ignored because we have no stream object for stream
10810 nghttp2_bufs_reset(&bufs);
10811 rv = pack_headers(&bufs, &deflater, 3,
10812 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM,
10813 trailernv, ARRLEN(trailernv), mem);
10815 CU_ASSERT(0 == rv);
10817 nread = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
10818 nghttp2_bufs_len(&bufs));
10820 CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == nread);
10822 item = nghttp2_session_get_next_ob_item(session);
10824 CU_ASSERT(NULL == item);
10826 nghttp2_hd_deflate_free(&deflater);
10827 nghttp2_session_del(session);
10829 nghttp2_session_server_new(&session, &callbacks, NULL);
10830 nghttp2_hd_deflate_init(&deflater, mem);
10831 /* Same setup, and then receive DATA instead of HEADERS */
10833 prepare_session_removed_closed_stream(session, &deflater);
10835 nghttp2_frame_hd_init(&hd, 0, NGHTTP2_DATA, NGHTTP2_FLAG_NONE, 3);
10836 nghttp2_bufs_reset(&bufs);
10837 nghttp2_frame_pack_frame_hd(bufs.head->buf.last, &hd);
10838 bufs.head->buf.last += NGHTTP2_FRAME_HDLEN;
10840 nread = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
10841 nghttp2_bufs_len(&bufs));
10843 CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == nread);
10845 item = nghttp2_session_get_next_ob_item(session);
10847 CU_ASSERT(NULL == item);
10849 nghttp2_hd_deflate_free(&deflater);
10850 nghttp2_session_del(session);
10852 nghttp2_bufs_free(&bufs);
10855 static ssize_t pause_once_data_source_read_callback(
10856 nghttp2_session *session, int32_t stream_id, uint8_t *buf, size_t len,
10857 uint32_t *data_flags, nghttp2_data_source *source, void *user_data) {
10858 my_user_data *ud = user_data;
10859 if (ud->data_source_read_cb_paused == 0) {
10860 ++ud->data_source_read_cb_paused;
10861 return NGHTTP2_ERR_PAUSE;
10864 return fixed_length_data_source_read_callback(session, stream_id, buf, len,
10865 data_flags, source, user_data);
10868 void test_nghttp2_session_pause_data(void) {
10869 nghttp2_session *session;
10870 nghttp2_session_callbacks callbacks;
10871 nghttp2_data_provider data_prd;
10874 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
10875 callbacks.send_callback = null_send_callback;
10876 callbacks.on_frame_send_callback = on_frame_send_callback;
10878 data_prd.read_callback = pause_once_data_source_read_callback;
10879 ud.data_source_length = NGHTTP2_DATA_PAYLOADLEN;
10881 nghttp2_session_server_new(&session, &callbacks, &ud);
10883 open_recv_stream(session, 1);
10886 0 == nghttp2_submit_data(session, NGHTTP2_FLAG_END_STREAM, 1, &data_prd));
10888 ud.frame_send_cb_called = 0;
10889 ud.data_source_read_cb_paused = 0;
10891 CU_ASSERT(0 == nghttp2_session_send(session));
10892 CU_ASSERT(0 == ud.frame_send_cb_called);
10893 CU_ASSERT(NULL == session->aob.item);
10894 CU_ASSERT(0 == nghttp2_session_send(session));
10895 CU_ASSERT(1 == ud.frame_send_cb_called);
10896 CU_ASSERT(NGHTTP2_DATA == ud.sent_frame_type);
10897 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
10899 nghttp2_session_del(session);
10902 void test_nghttp2_session_no_closed_streams(void) {
10903 nghttp2_session *session;
10904 nghttp2_session_callbacks callbacks;
10905 nghttp2_option *option;
10907 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
10909 nghttp2_option_new(&option);
10910 nghttp2_option_set_no_closed_streams(option, 1);
10912 nghttp2_session_server_new2(&session, &callbacks, NULL, option);
10914 open_recv_stream(session, 1);
10916 nghttp2_session_close_stream(session, 1, NGHTTP2_NO_ERROR);
10918 CU_ASSERT(0 == session->num_closed_streams);
10920 nghttp2_session_del(session);
10921 nghttp2_option_del(option);
10924 void test_nghttp2_session_set_stream_user_data(void) {
10925 nghttp2_session *session;
10926 nghttp2_session_callbacks callbacks;
10928 int user_data1, user_data2;
10930 const uint8_t *datap;
10933 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
10935 nghttp2_session_client_new(&session, &callbacks, NULL);
10937 stream_id = nghttp2_submit_request(session, NULL, reqnv, ARRLEN(reqnv), NULL,
10940 rv = nghttp2_session_set_stream_user_data(session, stream_id, &user_data2);
10942 CU_ASSERT(0 == rv);
10944 datalen = nghttp2_session_mem_send(session, &datap);
10946 CU_ASSERT(datalen > 0);
10948 CU_ASSERT(&user_data2 ==
10949 nghttp2_session_get_stream_user_data(session, stream_id));
10951 CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT ==
10952 nghttp2_session_set_stream_user_data(session, 2, NULL));
10954 nghttp2_session_del(session);
10957 static void check_nghttp2_http_recv_headers_fail(
10958 nghttp2_session *session, nghttp2_hd_deflater *deflater, int32_t stream_id,
10959 int stream_state, const nghttp2_nv *nva, size_t nvlen) {
10962 nghttp2_outbound_item *item;
10966 mem = nghttp2_mem_default();
10967 frame_pack_bufs_init(&bufs);
10969 ud = session->user_data;
10971 if (stream_state != -1) {
10972 if (nghttp2_session_is_my_stream_id(session, stream_id)) {
10973 open_sent_stream2(session, stream_id, (nghttp2_stream_state)stream_state);
10975 open_recv_stream2(session, stream_id, (nghttp2_stream_state)stream_state);
10979 rv = pack_headers(&bufs, deflater, stream_id, NGHTTP2_FLAG_END_HEADERS, nva,
10981 CU_ASSERT(0 == rv);
10983 ud->invalid_frame_recv_cb_called = 0;
10985 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
10986 nghttp2_buf_len(&bufs.head->buf));
10988 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
10990 item = nghttp2_session_get_next_ob_item(session);
10992 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
10993 CU_ASSERT(1 == ud->invalid_frame_recv_cb_called);
10995 CU_ASSERT(0 == nghttp2_session_send(session));
10997 nghttp2_bufs_free(&bufs);
11000 static void check_nghttp2_http_recv_headers_ok(
11001 nghttp2_session *session, nghttp2_hd_deflater *deflater, int32_t stream_id,
11002 int stream_state, const nghttp2_nv *nva, size_t nvlen) {
11008 mem = nghttp2_mem_default();
11009 frame_pack_bufs_init(&bufs);
11011 ud = session->user_data;
11013 if (stream_state != -1) {
11014 if (nghttp2_session_is_my_stream_id(session, stream_id)) {
11015 open_sent_stream2(session, stream_id, (nghttp2_stream_state)stream_state);
11017 open_recv_stream2(session, stream_id, (nghttp2_stream_state)stream_state);
11021 rv = pack_headers(&bufs, deflater, stream_id, NGHTTP2_FLAG_END_HEADERS, nva,
11023 CU_ASSERT(0 == rv);
11025 ud->frame_recv_cb_called = 0;
11027 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11028 nghttp2_buf_len(&bufs.head->buf));
11030 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
11031 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
11032 CU_ASSERT(1 == ud->frame_recv_cb_called);
11034 nghttp2_bufs_free(&bufs);
11037 void test_nghttp2_http_mandatory_headers(void) {
11038 nghttp2_session *session;
11039 nghttp2_session_callbacks callbacks;
11040 nghttp2_hd_deflater deflater;
11043 /* test case for response */
11044 const nghttp2_nv nostatus_resnv[] = {MAKE_NV("server", "foo")};
11045 const nghttp2_nv dupstatus_resnv[] = {MAKE_NV(":status", "200"),
11046 MAKE_NV(":status", "200")};
11047 const nghttp2_nv badpseudo_resnv[] = {MAKE_NV(":status", "200"),
11048 MAKE_NV(":scheme", "https")};
11049 const nghttp2_nv latepseudo_resnv[] = {MAKE_NV("server", "foo"),
11050 MAKE_NV(":status", "200")};
11051 const nghttp2_nv badstatus_resnv[] = {MAKE_NV(":status", "2000")};
11052 const nghttp2_nv badcl_resnv[] = {MAKE_NV(":status", "200"),
11053 MAKE_NV("content-length", "-1")};
11054 const nghttp2_nv dupcl_resnv[] = {MAKE_NV(":status", "200"),
11055 MAKE_NV("content-length", "0"),
11056 MAKE_NV("content-length", "0")};
11057 const nghttp2_nv badhd_resnv[] = {MAKE_NV(":status", "200"),
11058 MAKE_NV("connection", "close")};
11059 const nghttp2_nv cl1xx_resnv[] = {MAKE_NV(":status", "100"),
11060 MAKE_NV("content-length", "0")};
11061 const nghttp2_nv cl204_resnv[] = {MAKE_NV(":status", "204"),
11062 MAKE_NV("content-length", "0")};
11063 const nghttp2_nv clnonzero204_resnv[] = {MAKE_NV(":status", "204"),
11064 MAKE_NV("content-length", "100")};
11065 const nghttp2_nv status101_resnv[] = {MAKE_NV(":status", "101")};
11067 /* test case for request */
11068 const nghttp2_nv nopath_reqnv[] = {MAKE_NV(":scheme", "https"),
11069 MAKE_NV(":method", "GET"),
11070 MAKE_NV(":authority", "localhost")};
11071 const nghttp2_nv earlyconnect_reqnv[] = {
11072 MAKE_NV(":method", "CONNECT"), MAKE_NV(":scheme", "https"),
11073 MAKE_NV(":path", "/"), MAKE_NV(":authority", "localhost")};
11074 const nghttp2_nv lateconnect_reqnv[] = {
11075 MAKE_NV(":scheme", "https"), MAKE_NV(":path", "/"),
11076 MAKE_NV(":method", "CONNECT"), MAKE_NV(":authority", "localhost")};
11077 const nghttp2_nv duppath_reqnv[] = {
11078 MAKE_NV(":scheme", "https"), MAKE_NV(":method", "GET"),
11079 MAKE_NV(":authority", "localhost"), MAKE_NV(":path", "/"),
11080 MAKE_NV(":path", "/")};
11081 const nghttp2_nv badcl_reqnv[] = {
11082 MAKE_NV(":scheme", "https"), MAKE_NV(":method", "POST"),
11083 MAKE_NV(":authority", "localhost"), MAKE_NV(":path", "/"),
11084 MAKE_NV("content-length", "-1")};
11085 const nghttp2_nv dupcl_reqnv[] = {
11086 MAKE_NV(":scheme", "https"), MAKE_NV(":method", "POST"),
11087 MAKE_NV(":authority", "localhost"), MAKE_NV(":path", "/"),
11088 MAKE_NV("content-length", "0"), MAKE_NV("content-length", "0")};
11089 const nghttp2_nv badhd_reqnv[] = {
11090 MAKE_NV(":scheme", "https"), MAKE_NV(":method", "GET"),
11091 MAKE_NV(":authority", "localhost"), MAKE_NV(":path", "/"),
11092 MAKE_NV("connection", "close")};
11093 const nghttp2_nv badauthority_reqnv[] = {
11094 MAKE_NV(":scheme", "https"), MAKE_NV(":method", "GET"),
11095 MAKE_NV(":authority", "\x0d\x0alocalhost"), MAKE_NV(":path", "/")};
11096 const nghttp2_nv badhdbtw_reqnv[] = {
11097 MAKE_NV(":scheme", "https"), MAKE_NV(":method", "GET"),
11098 MAKE_NV("foo", "\x0d\x0a"), MAKE_NV(":authority", "localhost"),
11099 MAKE_NV(":path", "/")};
11100 const nghttp2_nv asteriskget1_reqnv[] = {
11101 MAKE_NV(":path", "*"), MAKE_NV(":scheme", "https"),
11102 MAKE_NV(":authority", "localhost"), MAKE_NV(":method", "GET")};
11103 const nghttp2_nv asteriskget2_reqnv[] = {
11104 MAKE_NV(":scheme", "https"), MAKE_NV(":authority", "localhost"),
11105 MAKE_NV(":method", "GET"), MAKE_NV(":path", "*")};
11106 const nghttp2_nv asteriskoptions1_reqnv[] = {
11107 MAKE_NV(":path", "*"), MAKE_NV(":scheme", "https"),
11108 MAKE_NV(":authority", "localhost"), MAKE_NV(":method", "OPTIONS")};
11109 const nghttp2_nv asteriskoptions2_reqnv[] = {
11110 MAKE_NV(":scheme", "https"), MAKE_NV(":authority", "localhost"),
11111 MAKE_NV(":method", "OPTIONS"), MAKE_NV(":path", "*")};
11112 const nghttp2_nv connectproto_reqnv[] = {
11113 MAKE_NV(":scheme", "https"), MAKE_NV(":path", "/"),
11114 MAKE_NV(":method", "CONNECT"), MAKE_NV(":authority", "localhost"),
11115 MAKE_NV(":protocol", "websocket")};
11116 const nghttp2_nv connectprotoget_reqnv[] = {
11117 MAKE_NV(":scheme", "https"), MAKE_NV(":path", "/"),
11118 MAKE_NV(":method", "GET"), MAKE_NV(":authority", "localhost"),
11119 MAKE_NV(":protocol", "websocket")};
11120 const nghttp2_nv connectprotonopath_reqnv[] = {
11121 MAKE_NV(":scheme", "https"), MAKE_NV(":method", "CONNECT"),
11122 MAKE_NV(":authority", "localhost"), MAKE_NV(":protocol", "websocket")};
11123 const nghttp2_nv connectprotonoauth_reqnv[] = {
11124 MAKE_NV(":scheme", "http"), MAKE_NV(":path", "/"),
11125 MAKE_NV(":method", "CONNECT"), MAKE_NV("host", "localhost"),
11126 MAKE_NV(":protocol", "websocket")};
11127 const nghttp2_nv regularconnect_reqnv[] = {
11128 MAKE_NV(":method", "CONNECT"), MAKE_NV(":authority", "localhost")};
11130 mem = nghttp2_mem_default();
11132 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
11133 callbacks.send_callback = null_send_callback;
11134 callbacks.on_frame_recv_callback = on_frame_recv_callback;
11135 callbacks.on_invalid_frame_recv_callback = on_invalid_frame_recv_callback;
11137 nghttp2_session_client_new(&session, &callbacks, &ud);
11139 nghttp2_hd_deflate_init(&deflater, mem);
11141 /* response header lacks :status */
11142 check_nghttp2_http_recv_headers_fail(session, &deflater, 1,
11143 NGHTTP2_STREAM_OPENING, nostatus_resnv,
11144 ARRLEN(nostatus_resnv));
11146 /* response header has 2 :status */
11147 check_nghttp2_http_recv_headers_fail(session, &deflater, 3,
11148 NGHTTP2_STREAM_OPENING, dupstatus_resnv,
11149 ARRLEN(dupstatus_resnv));
11151 /* response header has bad pseudo header :scheme */
11152 check_nghttp2_http_recv_headers_fail(session, &deflater, 5,
11153 NGHTTP2_STREAM_OPENING, badpseudo_resnv,
11154 ARRLEN(badpseudo_resnv));
11156 /* response header has :status after regular header field */
11157 check_nghttp2_http_recv_headers_fail(session, &deflater, 7,
11158 NGHTTP2_STREAM_OPENING, latepseudo_resnv,
11159 ARRLEN(latepseudo_resnv));
11161 /* response header has bad status code */
11162 check_nghttp2_http_recv_headers_fail(session, &deflater, 9,
11163 NGHTTP2_STREAM_OPENING, badstatus_resnv,
11164 ARRLEN(badstatus_resnv));
11166 /* response header has bad content-length */
11167 check_nghttp2_http_recv_headers_fail(session, &deflater, 11,
11168 NGHTTP2_STREAM_OPENING, badcl_resnv,
11169 ARRLEN(badcl_resnv));
11171 /* response header has multiple content-length */
11172 check_nghttp2_http_recv_headers_fail(session, &deflater, 13,
11173 NGHTTP2_STREAM_OPENING, dupcl_resnv,
11174 ARRLEN(dupcl_resnv));
11176 /* response header has disallowed header field */
11177 check_nghttp2_http_recv_headers_fail(session, &deflater, 15,
11178 NGHTTP2_STREAM_OPENING, badhd_resnv,
11179 ARRLEN(badhd_resnv));
11181 /* response header has content-length with 100 status code */
11182 check_nghttp2_http_recv_headers_fail(session, &deflater, 17,
11183 NGHTTP2_STREAM_OPENING, cl1xx_resnv,
11184 ARRLEN(cl1xx_resnv));
11186 /* response header has 0 content-length with 204 status code */
11187 check_nghttp2_http_recv_headers_ok(session, &deflater, 19,
11188 NGHTTP2_STREAM_OPENING, cl204_resnv,
11189 ARRLEN(cl204_resnv));
11191 /* response header has nonzero content-length with 204 status
11193 check_nghttp2_http_recv_headers_fail(
11194 session, &deflater, 21, NGHTTP2_STREAM_OPENING, clnonzero204_resnv,
11195 ARRLEN(clnonzero204_resnv));
11197 /* status code 101 should not be used in HTTP/2 because it is used
11198 for HTTP Upgrade which HTTP/2 removes. */
11199 check_nghttp2_http_recv_headers_fail(session, &deflater, 23,
11200 NGHTTP2_STREAM_OPENING, status101_resnv,
11201 ARRLEN(status101_resnv));
11203 nghttp2_hd_deflate_free(&deflater);
11205 nghttp2_session_del(session);
11207 /* check server side */
11208 nghttp2_session_server_new(&session, &callbacks, &ud);
11210 nghttp2_hd_deflate_init(&deflater, mem);
11212 /* request header has no :path */
11213 check_nghttp2_http_recv_headers_fail(session, &deflater, 1, -1, nopath_reqnv,
11214 ARRLEN(nopath_reqnv));
11216 /* request header has CONNECT method, but followed by :path */
11217 check_nghttp2_http_recv_headers_fail(session, &deflater, 3, -1,
11218 earlyconnect_reqnv,
11219 ARRLEN(earlyconnect_reqnv));
11221 /* request header has CONNECT method following :path */
11222 check_nghttp2_http_recv_headers_fail(
11223 session, &deflater, 5, -1, lateconnect_reqnv, ARRLEN(lateconnect_reqnv));
11225 /* request header has multiple :path */
11226 check_nghttp2_http_recv_headers_fail(session, &deflater, 7, -1, duppath_reqnv,
11227 ARRLEN(duppath_reqnv));
11229 /* request header has bad content-length */
11230 check_nghttp2_http_recv_headers_fail(session, &deflater, 9, -1, badcl_reqnv,
11231 ARRLEN(badcl_reqnv));
11233 /* request header has multiple content-length */
11234 check_nghttp2_http_recv_headers_fail(session, &deflater, 11, -1, dupcl_reqnv,
11235 ARRLEN(dupcl_reqnv));
11237 /* request header has disallowed header field */
11238 check_nghttp2_http_recv_headers_fail(session, &deflater, 13, -1, badhd_reqnv,
11239 ARRLEN(badhd_reqnv));
11241 /* request header has :authority header field containing illegal
11243 check_nghttp2_http_recv_headers_fail(session, &deflater, 15, -1,
11244 badauthority_reqnv,
11245 ARRLEN(badauthority_reqnv));
11247 /* request header has regular header field containing illegal
11248 character before all mandatory header fields are seen. */
11249 check_nghttp2_http_recv_headers_fail(session, &deflater, 17, -1,
11250 badhdbtw_reqnv, ARRLEN(badhdbtw_reqnv));
11252 /* request header has "*" in :path header field while method is GET.
11253 :path is received before :method */
11254 check_nghttp2_http_recv_headers_fail(session, &deflater, 19, -1,
11255 asteriskget1_reqnv,
11256 ARRLEN(asteriskget1_reqnv));
11258 /* request header has "*" in :path header field while method is GET.
11259 :method is received before :path */
11260 check_nghttp2_http_recv_headers_fail(session, &deflater, 21, -1,
11261 asteriskget2_reqnv,
11262 ARRLEN(asteriskget2_reqnv));
11264 /* OPTIONS method can include "*" in :path header field. :path is
11265 received before :method. */
11266 check_nghttp2_http_recv_headers_ok(session, &deflater, 23, -1,
11267 asteriskoptions1_reqnv,
11268 ARRLEN(asteriskoptions1_reqnv));
11270 /* OPTIONS method can include "*" in :path header field. :method is
11271 received before :path. */
11272 check_nghttp2_http_recv_headers_ok(session, &deflater, 25, -1,
11273 asteriskoptions2_reqnv,
11274 ARRLEN(asteriskoptions2_reqnv));
11276 /* :protocol is not allowed unless it is enabled by the local
11278 check_nghttp2_http_recv_headers_fail(session, &deflater, 27, -1,
11279 connectproto_reqnv,
11280 ARRLEN(connectproto_reqnv));
11282 nghttp2_hd_deflate_free(&deflater);
11284 nghttp2_session_del(session);
11286 /* enable SETTINGS_CONNECT_PROTOCOL */
11287 nghttp2_session_server_new(&session, &callbacks, &ud);
11289 session->pending_enable_connect_protocol = 1;
11291 nghttp2_hd_deflate_init(&deflater, mem);
11293 /* :protocol is allowed if SETTINGS_CONNECT_PROTOCOL is enabled by
11294 the local endpoint. */
11295 check_nghttp2_http_recv_headers_ok(session, &deflater, 1, -1,
11296 connectproto_reqnv,
11297 ARRLEN(connectproto_reqnv));
11299 /* :protocol is only allowed with CONNECT method. */
11300 check_nghttp2_http_recv_headers_fail(session, &deflater, 3, -1,
11301 connectprotoget_reqnv,
11302 ARRLEN(connectprotoget_reqnv));
11304 /* CONNECT method with :protocol requires :path. */
11305 check_nghttp2_http_recv_headers_fail(session, &deflater, 5, -1,
11306 connectprotonopath_reqnv,
11307 ARRLEN(connectprotonopath_reqnv));
11309 /* CONNECT method with :protocol requires :authority. */
11310 check_nghttp2_http_recv_headers_fail(session, &deflater, 7, -1,
11311 connectprotonoauth_reqnv,
11312 ARRLEN(connectprotonoauth_reqnv));
11314 /* regular CONNECT method should succeed with
11315 SETTINGS_CONNECT_PROTOCOL */
11316 check_nghttp2_http_recv_headers_ok(session, &deflater, 9, -1,
11317 regularconnect_reqnv,
11318 ARRLEN(regularconnect_reqnv));
11320 nghttp2_hd_deflate_free(&deflater);
11322 nghttp2_session_del(session);
11325 void test_nghttp2_http_content_length(void) {
11326 nghttp2_session *session;
11327 nghttp2_session_callbacks callbacks;
11328 nghttp2_hd_deflater deflater;
11332 nghttp2_stream *stream;
11333 const nghttp2_nv cl_resnv[] = {MAKE_NV(":status", "200"),
11334 MAKE_NV("te", "trailers"),
11335 MAKE_NV("content-length", "9000000000")};
11336 const nghttp2_nv cl_reqnv[] = {
11337 MAKE_NV(":path", "/"), MAKE_NV(":method", "PUT"),
11338 MAKE_NV(":scheme", "https"), MAKE_NV("te", "trailers"),
11339 MAKE_NV("host", "localhost"), MAKE_NV("content-length", "9000000000")};
11341 mem = nghttp2_mem_default();
11342 frame_pack_bufs_init(&bufs);
11344 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
11345 callbacks.send_callback = null_send_callback;
11347 nghttp2_session_client_new(&session, &callbacks, NULL);
11349 nghttp2_hd_deflate_init(&deflater, mem);
11351 stream = open_sent_stream2(session, 1, NGHTTP2_STREAM_OPENING);
11353 rv = pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, cl_resnv,
11354 ARRLEN(cl_resnv), mem);
11355 CU_ASSERT(0 == rv);
11357 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11358 nghttp2_buf_len(&bufs.head->buf));
11360 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
11361 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
11362 CU_ASSERT(9000000000LL == stream->content_length);
11363 CU_ASSERT(200 == stream->status_code);
11365 nghttp2_hd_deflate_free(&deflater);
11367 nghttp2_session_del(session);
11369 nghttp2_bufs_reset(&bufs);
11371 /* check server side */
11372 nghttp2_session_server_new(&session, &callbacks, NULL);
11374 nghttp2_hd_deflate_init(&deflater, mem);
11376 rv = pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, cl_reqnv,
11377 ARRLEN(cl_reqnv), mem);
11378 CU_ASSERT(0 == rv);
11380 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11381 nghttp2_buf_len(&bufs.head->buf));
11383 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
11385 stream = nghttp2_session_get_stream(session, 1);
11387 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
11388 CU_ASSERT(9000000000LL == stream->content_length);
11390 nghttp2_hd_deflate_free(&deflater);
11392 nghttp2_session_del(session);
11394 nghttp2_bufs_free(&bufs);
11397 void test_nghttp2_http_content_length_mismatch(void) {
11398 nghttp2_session *session;
11399 nghttp2_session_callbacks callbacks;
11400 nghttp2_hd_deflater deflater;
11404 const nghttp2_nv cl_reqnv[] = {
11405 MAKE_NV(":path", "/"), MAKE_NV(":method", "PUT"),
11406 MAKE_NV(":authority", "localhost"), MAKE_NV(":scheme", "https"),
11407 MAKE_NV("content-length", "20")};
11408 const nghttp2_nv cl_resnv[] = {MAKE_NV(":status", "200"),
11409 MAKE_NV("content-length", "20")};
11410 nghttp2_outbound_item *item;
11411 nghttp2_frame_hd hd;
11413 mem = nghttp2_mem_default();
11414 frame_pack_bufs_init(&bufs);
11416 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
11417 callbacks.send_callback = null_send_callback;
11419 nghttp2_session_server_new(&session, &callbacks, NULL);
11421 nghttp2_hd_deflate_init(&deflater, mem);
11423 /* header says content-length: 20, but HEADERS has END_STREAM flag set */
11424 rv = pack_headers(&bufs, &deflater, 1,
11425 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM,
11426 cl_reqnv, ARRLEN(cl_reqnv), mem);
11427 CU_ASSERT(0 == rv);
11429 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11430 nghttp2_buf_len(&bufs.head->buf));
11432 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
11434 item = nghttp2_session_get_next_ob_item(session);
11435 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
11437 CU_ASSERT(0 == nghttp2_session_send(session));
11439 nghttp2_bufs_reset(&bufs);
11441 /* header says content-length: 20, but DATA has 0 byte */
11442 rv = pack_headers(&bufs, &deflater, 3, NGHTTP2_FLAG_END_HEADERS, cl_reqnv,
11443 ARRLEN(cl_reqnv), mem);
11444 CU_ASSERT(0 == rv);
11446 nghttp2_frame_hd_init(&hd, 0, NGHTTP2_DATA, NGHTTP2_FLAG_END_STREAM, 3);
11447 nghttp2_frame_pack_frame_hd(bufs.head->buf.last, &hd);
11448 bufs.head->buf.last += NGHTTP2_FRAME_HDLEN;
11450 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11451 nghttp2_buf_len(&bufs.head->buf));
11453 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
11455 item = nghttp2_session_get_next_ob_item(session);
11456 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
11458 CU_ASSERT(0 == nghttp2_session_send(session));
11460 nghttp2_bufs_reset(&bufs);
11462 /* header says content-length: 20, but DATA has 21 bytes */
11463 rv = pack_headers(&bufs, &deflater, 5, NGHTTP2_FLAG_END_HEADERS, cl_reqnv,
11464 ARRLEN(cl_reqnv), mem);
11465 CU_ASSERT(0 == rv);
11467 nghttp2_frame_hd_init(&hd, 21, NGHTTP2_DATA, NGHTTP2_FLAG_END_STREAM, 5);
11468 nghttp2_frame_pack_frame_hd(bufs.head->buf.last, &hd);
11469 bufs.head->buf.last += NGHTTP2_FRAME_HDLEN + 21;
11471 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11472 nghttp2_buf_len(&bufs.head->buf));
11474 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
11476 item = nghttp2_session_get_next_ob_item(session);
11477 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
11479 CU_ASSERT(0 == nghttp2_session_send(session));
11481 nghttp2_bufs_reset(&bufs);
11483 nghttp2_hd_deflate_free(&deflater);
11485 nghttp2_session_del(session);
11487 /* Check for client */
11488 nghttp2_session_client_new(&session, &callbacks, NULL);
11490 nghttp2_hd_deflate_init(&deflater, mem);
11492 /* header says content-length: 20, but HEADERS has END_STREAM flag set */
11493 nghttp2_submit_request(session, NULL, reqnv, ARRLEN(reqnv), NULL, NULL);
11495 CU_ASSERT(0 == nghttp2_session_send(session));
11497 rv = pack_headers(&bufs, &deflater, 1,
11498 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM,
11499 cl_resnv, ARRLEN(cl_resnv), mem);
11500 CU_ASSERT(0 == rv);
11502 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11503 nghttp2_buf_len(&bufs.head->buf));
11505 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
11507 item = nghttp2_session_get_next_ob_item(session);
11508 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
11510 CU_ASSERT(NULL != nghttp2_session_get_stream(session, 1));
11511 CU_ASSERT(0 == nghttp2_session_send(session));
11512 /* After sending RST_STREAM, stream must be closed */
11513 CU_ASSERT(NULL == nghttp2_session_get_stream(session, 1));
11515 nghttp2_bufs_reset(&bufs);
11517 /* header says content-length: 20, but DATA has 0 byte */
11518 nghttp2_submit_request(session, NULL, reqnv, ARRLEN(reqnv), NULL, NULL);
11520 CU_ASSERT(0 == nghttp2_session_send(session));
11522 rv = pack_headers(&bufs, &deflater, 3, NGHTTP2_FLAG_END_HEADERS, cl_resnv,
11523 ARRLEN(cl_resnv), mem);
11524 CU_ASSERT(0 == rv);
11526 nghttp2_frame_hd_init(&hd, 0, NGHTTP2_DATA, NGHTTP2_FLAG_END_STREAM, 3);
11527 nghttp2_frame_pack_frame_hd(bufs.head->buf.last, &hd);
11528 bufs.head->buf.last += NGHTTP2_FRAME_HDLEN;
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(NULL != nghttp2_session_get_stream(session, 3));
11539 CU_ASSERT(0 == nghttp2_session_send(session));
11540 /* After sending RST_STREAM, stream must be closed */
11541 CU_ASSERT(NULL == nghttp2_session_get_stream(session, 3));
11543 nghttp2_bufs_reset(&bufs);
11545 /* header says content-length: 20, but DATA has 21 bytes */
11546 nghttp2_submit_request(session, NULL, reqnv, ARRLEN(reqnv), NULL, NULL);
11548 CU_ASSERT(0 == nghttp2_session_send(session));
11550 rv = pack_headers(&bufs, &deflater, 5, NGHTTP2_FLAG_END_HEADERS, cl_resnv,
11551 ARRLEN(cl_resnv), mem);
11552 CU_ASSERT(0 == rv);
11554 nghttp2_frame_hd_init(&hd, 21, NGHTTP2_DATA, NGHTTP2_FLAG_END_STREAM, 5);
11555 nghttp2_frame_pack_frame_hd(bufs.head->buf.last, &hd);
11556 bufs.head->buf.last += NGHTTP2_FRAME_HDLEN + 21;
11558 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11559 nghttp2_buf_len(&bufs.head->buf));
11561 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
11563 item = nghttp2_session_get_next_ob_item(session);
11564 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
11566 CU_ASSERT(NULL != nghttp2_session_get_stream(session, 5));
11567 CU_ASSERT(0 == nghttp2_session_send(session));
11568 /* After sending RST_STREAM, stream must be closed */
11569 CU_ASSERT(NULL == nghttp2_session_get_stream(session, 5));
11571 nghttp2_bufs_reset(&bufs);
11573 nghttp2_bufs_free(&bufs);
11575 nghttp2_hd_deflate_free(&deflater);
11577 nghttp2_session_del(session);
11580 void test_nghttp2_http_non_final_response(void) {
11581 nghttp2_session *session;
11582 nghttp2_session_callbacks callbacks;
11583 nghttp2_hd_deflater deflater;
11587 const nghttp2_nv nonfinal_resnv[] = {
11588 MAKE_NV(":status", "100"),
11590 nghttp2_outbound_item *item;
11591 nghttp2_frame_hd hd;
11593 mem = nghttp2_mem_default();
11594 frame_pack_bufs_init(&bufs);
11596 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
11597 callbacks.send_callback = null_send_callback;
11599 nghttp2_session_client_new(&session, &callbacks, NULL);
11601 nghttp2_hd_deflate_init(&deflater, mem);
11603 /* non-final HEADERS with END_STREAM is illegal */
11604 open_sent_stream2(session, 1, NGHTTP2_STREAM_OPENING);
11606 rv = pack_headers(&bufs, &deflater, 1,
11607 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM,
11608 nonfinal_resnv, ARRLEN(nonfinal_resnv), mem);
11609 CU_ASSERT(0 == rv);
11611 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11612 nghttp2_buf_len(&bufs.head->buf));
11614 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
11616 item = nghttp2_session_get_next_ob_item(session);
11617 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
11619 CU_ASSERT(0 == nghttp2_session_send(session));
11621 nghttp2_bufs_reset(&bufs);
11623 /* non-final HEADERS followed by non-empty DATA is illegal */
11624 open_sent_stream2(session, 3, NGHTTP2_STREAM_OPENING);
11626 rv = pack_headers(&bufs, &deflater, 3, NGHTTP2_FLAG_END_HEADERS,
11627 nonfinal_resnv, ARRLEN(nonfinal_resnv), mem);
11628 CU_ASSERT(0 == rv);
11630 nghttp2_frame_hd_init(&hd, 10, NGHTTP2_DATA, NGHTTP2_FLAG_END_STREAM, 3);
11631 nghttp2_frame_pack_frame_hd(bufs.head->buf.last, &hd);
11632 bufs.head->buf.last += NGHTTP2_FRAME_HDLEN + 10;
11634 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11635 nghttp2_buf_len(&bufs.head->buf));
11637 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
11639 item = nghttp2_session_get_next_ob_item(session);
11640 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
11642 CU_ASSERT(0 == nghttp2_session_send(session));
11644 nghttp2_bufs_reset(&bufs);
11646 /* non-final HEADERS followed by empty DATA (without END_STREAM) is
11648 open_sent_stream2(session, 5, NGHTTP2_STREAM_OPENING);
11650 rv = pack_headers(&bufs, &deflater, 5, NGHTTP2_FLAG_END_HEADERS,
11651 nonfinal_resnv, ARRLEN(nonfinal_resnv), mem);
11652 CU_ASSERT(0 == rv);
11654 nghttp2_frame_hd_init(&hd, 0, NGHTTP2_DATA, NGHTTP2_FLAG_NONE, 5);
11655 nghttp2_frame_pack_frame_hd(bufs.head->buf.last, &hd);
11656 bufs.head->buf.last += NGHTTP2_FRAME_HDLEN;
11658 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11659 nghttp2_buf_len(&bufs.head->buf));
11661 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
11663 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
11665 nghttp2_bufs_reset(&bufs);
11667 /* non-final HEADERS followed by empty DATA (with END_STREAM) is
11669 open_sent_stream2(session, 7, NGHTTP2_STREAM_OPENING);
11671 rv = pack_headers(&bufs, &deflater, 7, NGHTTP2_FLAG_END_HEADERS,
11672 nonfinal_resnv, ARRLEN(nonfinal_resnv), mem);
11673 CU_ASSERT(0 == rv);
11675 nghttp2_frame_hd_init(&hd, 0, NGHTTP2_DATA, NGHTTP2_FLAG_END_STREAM, 7);
11676 nghttp2_frame_pack_frame_hd(bufs.head->buf.last, &hd);
11677 bufs.head->buf.last += NGHTTP2_FRAME_HDLEN;
11679 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11680 nghttp2_buf_len(&bufs.head->buf));
11682 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
11684 item = nghttp2_session_get_next_ob_item(session);
11686 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
11688 CU_ASSERT(0 == nghttp2_session_send(session));
11690 nghttp2_bufs_reset(&bufs);
11692 /* non-final HEADERS followed by final HEADERS is OK */
11693 open_sent_stream2(session, 9, NGHTTP2_STREAM_OPENING);
11695 rv = pack_headers(&bufs, &deflater, 9, NGHTTP2_FLAG_END_HEADERS,
11696 nonfinal_resnv, ARRLEN(nonfinal_resnv), mem);
11697 CU_ASSERT(0 == rv);
11699 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11700 nghttp2_buf_len(&bufs.head->buf));
11702 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
11704 nghttp2_bufs_reset(&bufs);
11706 rv = pack_headers(&bufs, &deflater, 9, NGHTTP2_FLAG_END_HEADERS, resnv,
11707 ARRLEN(resnv), mem);
11708 CU_ASSERT(0 == rv);
11710 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11711 nghttp2_buf_len(&bufs.head->buf));
11713 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
11715 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
11717 nghttp2_bufs_reset(&bufs);
11719 nghttp2_hd_deflate_free(&deflater);
11721 nghttp2_session_del(session);
11723 nghttp2_bufs_free(&bufs);
11726 void test_nghttp2_http_trailer_headers(void) {
11727 nghttp2_session *session;
11728 nghttp2_session_callbacks callbacks;
11729 nghttp2_hd_deflater deflater;
11733 const nghttp2_nv trailer_reqnv[] = {
11734 MAKE_NV("foo", "bar"),
11736 nghttp2_outbound_item *item;
11738 mem = nghttp2_mem_default();
11739 frame_pack_bufs_init(&bufs);
11741 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
11742 callbacks.send_callback = null_send_callback;
11744 nghttp2_session_server_new(&session, &callbacks, NULL);
11746 nghttp2_hd_deflate_init(&deflater, mem);
11748 /* good trailer header */
11749 rv = pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, reqnv,
11750 ARRLEN(reqnv), mem);
11751 CU_ASSERT(0 == rv);
11753 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11754 nghttp2_buf_len(&bufs.head->buf));
11756 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
11758 nghttp2_bufs_reset(&bufs);
11760 rv = pack_headers(&bufs, &deflater, 1,
11761 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM,
11762 trailer_reqnv, ARRLEN(trailer_reqnv), mem);
11763 CU_ASSERT(0 == rv);
11765 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11766 nghttp2_buf_len(&bufs.head->buf));
11768 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
11770 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
11772 nghttp2_bufs_reset(&bufs);
11774 /* trailer header without END_STREAM is illegal */
11775 rv = pack_headers(&bufs, &deflater, 3, NGHTTP2_FLAG_END_HEADERS, reqnv,
11776 ARRLEN(reqnv), mem);
11777 CU_ASSERT(0 == rv);
11779 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11780 nghttp2_buf_len(&bufs.head->buf));
11782 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
11784 nghttp2_bufs_reset(&bufs);
11786 rv = pack_headers(&bufs, &deflater, 3, NGHTTP2_FLAG_END_HEADERS,
11787 trailer_reqnv, ARRLEN(trailer_reqnv), mem);
11788 CU_ASSERT(0 == rv);
11790 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11791 nghttp2_buf_len(&bufs.head->buf));
11793 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
11795 item = nghttp2_session_get_next_ob_item(session);
11797 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
11799 CU_ASSERT(0 == nghttp2_session_send(session));
11801 nghttp2_bufs_reset(&bufs);
11803 /* trailer header including pseudo header field is illegal */
11804 rv = pack_headers(&bufs, &deflater, 5, NGHTTP2_FLAG_END_HEADERS, reqnv,
11805 ARRLEN(reqnv), mem);
11806 CU_ASSERT(0 == rv);
11808 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11809 nghttp2_buf_len(&bufs.head->buf));
11811 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
11813 nghttp2_bufs_reset(&bufs);
11815 rv = pack_headers(&bufs, &deflater, 5, NGHTTP2_FLAG_END_HEADERS, reqnv,
11816 ARRLEN(reqnv), mem);
11817 CU_ASSERT(0 == rv);
11819 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11820 nghttp2_buf_len(&bufs.head->buf));
11822 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
11824 item = nghttp2_session_get_next_ob_item(session);
11826 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
11828 CU_ASSERT(0 == nghttp2_session_send(session));
11830 nghttp2_bufs_reset(&bufs);
11832 nghttp2_hd_deflate_free(&deflater);
11834 nghttp2_session_del(session);
11836 nghttp2_bufs_free(&bufs);
11839 void test_nghttp2_http_ignore_regular_header(void) {
11840 nghttp2_session *session;
11841 nghttp2_session_callbacks callbacks;
11842 nghttp2_hd_deflater deflater;
11847 const nghttp2_nv bad_reqnv[] = {
11848 MAKE_NV(":authority", "localhost"),
11849 MAKE_NV(":scheme", "https"),
11850 MAKE_NV(":path", "/"),
11851 MAKE_NV(":method", "GET"),
11852 MAKE_NV("foo", "\x0zzz"),
11853 MAKE_NV("bar", "buzz"),
11855 const nghttp2_nv bad_ansnv[] = {
11856 MAKE_NV(":authority", "localhost"), MAKE_NV(":scheme", "https"),
11857 MAKE_NV(":path", "/"), MAKE_NV(":method", "GET"), MAKE_NV("bar", "buzz")};
11860 nghttp2_outbound_item *item;
11862 mem = nghttp2_mem_default();
11863 frame_pack_bufs_init(&bufs);
11865 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
11866 callbacks.send_callback = null_send_callback;
11867 callbacks.on_header_callback = pause_on_header_callback;
11869 nghttp2_session_server_new(&session, &callbacks, &ud);
11870 nghttp2_hd_deflate_init(&deflater, mem);
11872 rv = pack_headers(&bufs, &deflater, 1,
11873 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM,
11874 bad_reqnv, ARRLEN(bad_reqnv), mem);
11876 CU_ASSERT_FATAL(0 == rv);
11878 nghttp2_hd_deflate_free(&deflater);
11882 for (i = 0; i < 4; ++i) {
11883 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos + proclen,
11884 nghttp2_buf_len(&bufs.head->buf) - proclen);
11885 CU_ASSERT_FATAL(rv > 0);
11886 proclen += (size_t)rv;
11887 CU_ASSERT(nghttp2_nv_equal(&bad_ansnv[i], &ud.nv));
11890 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos + proclen,
11891 nghttp2_buf_len(&bufs.head->buf) - proclen);
11892 CU_ASSERT_FATAL(rv > 0);
11893 /* Without on_invalid_frame_recv_callback, bad header causes stream
11895 item = nghttp2_session_get_next_ob_item(session);
11897 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
11899 proclen += (size_t)rv;
11901 CU_ASSERT(nghttp2_buf_len(&bufs.head->buf) == proclen);
11903 nghttp2_session_del(session);
11905 /* use on_invalid_header_callback */
11906 callbacks.on_invalid_header_callback = pause_on_invalid_header_callback;
11908 nghttp2_session_server_new(&session, &callbacks, &ud);
11912 ud.invalid_header_cb_called = 0;
11914 for (i = 0; i < 4; ++i) {
11915 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos + proclen,
11916 nghttp2_buf_len(&bufs.head->buf) - proclen);
11917 CU_ASSERT_FATAL(rv > 0);
11918 proclen += (size_t)rv;
11919 CU_ASSERT(nghttp2_nv_equal(&bad_ansnv[i], &ud.nv));
11922 CU_ASSERT(0 == ud.invalid_header_cb_called);
11924 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos + proclen,
11925 nghttp2_buf_len(&bufs.head->buf) - proclen);
11927 CU_ASSERT_FATAL(rv > 0);
11928 CU_ASSERT(1 == ud.invalid_header_cb_called);
11929 CU_ASSERT(nghttp2_nv_equal(&bad_reqnv[4], &ud.nv));
11931 proclen += (size_t)rv;
11933 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos + proclen,
11934 nghttp2_buf_len(&bufs.head->buf) - proclen);
11937 CU_ASSERT(nghttp2_nv_equal(&bad_ansnv[4], &ud.nv));
11939 nghttp2_session_del(session);
11941 /* make sure that we can reset stream from
11942 on_invalid_header_callback */
11943 callbacks.on_header_callback = on_header_callback;
11944 callbacks.on_invalid_header_callback = reset_on_invalid_header_callback;
11946 nghttp2_session_server_new(&session, &callbacks, &ud);
11948 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11949 nghttp2_buf_len(&bufs.head->buf));
11951 CU_ASSERT(rv == (ssize_t)nghttp2_buf_len(&bufs.head->buf));
11953 item = nghttp2_session_get_next_ob_item(session);
11955 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
11956 CU_ASSERT(1 == item->frame.hd.stream_id);
11958 nghttp2_session_del(session);
11959 nghttp2_bufs_free(&bufs);
11962 void test_nghttp2_http_ignore_content_length(void) {
11963 nghttp2_session *session;
11964 nghttp2_session_callbacks callbacks;
11965 nghttp2_hd_deflater deflater;
11969 const nghttp2_nv cl_resnv[] = {MAKE_NV(":status", "304"),
11970 MAKE_NV("content-length", "20")};
11971 const nghttp2_nv conn_reqnv[] = {MAKE_NV(":authority", "localhost"),
11972 MAKE_NV(":method", "CONNECT"),
11973 MAKE_NV("content-length", "999999")};
11974 const nghttp2_nv conn_cl_resnv[] = {MAKE_NV(":status", "200"),
11975 MAKE_NV("content-length", "0")};
11976 nghttp2_stream *stream;
11978 mem = nghttp2_mem_default();
11979 frame_pack_bufs_init(&bufs);
11981 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
11982 callbacks.send_callback = null_send_callback;
11984 nghttp2_session_client_new(&session, &callbacks, NULL);
11986 nghttp2_hd_deflate_init(&deflater, mem);
11988 /* If status 304, content-length must be ignored */
11989 open_sent_stream2(session, 1, NGHTTP2_STREAM_OPENING);
11991 rv = pack_headers(&bufs, &deflater, 1,
11992 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM,
11993 cl_resnv, ARRLEN(cl_resnv), mem);
11994 CU_ASSERT(0 == rv);
11996 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11997 nghttp2_buf_len(&bufs.head->buf));
11999 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
12001 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
12003 nghttp2_bufs_reset(&bufs);
12005 /* Content-Length in 200 response to CONNECT is ignored */
12006 stream = open_sent_stream2(session, 3, NGHTTP2_STREAM_OPENING);
12007 stream->http_flags |= NGHTTP2_HTTP_FLAG_METH_CONNECT;
12009 rv = pack_headers(&bufs, &deflater, 3, NGHTTP2_FLAG_END_HEADERS,
12010 conn_cl_resnv, ARRLEN(conn_cl_resnv), mem);
12011 CU_ASSERT(0 == rv);
12013 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
12014 nghttp2_buf_len(&bufs.head->buf));
12016 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
12018 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
12019 CU_ASSERT(-1 == stream->content_length);
12021 nghttp2_bufs_reset(&bufs);
12023 nghttp2_hd_deflate_free(&deflater);
12024 nghttp2_session_del(session);
12026 /* If request method is CONNECT, content-length must be ignored */
12027 nghttp2_session_server_new(&session, &callbacks, NULL);
12029 nghttp2_hd_deflate_init(&deflater, mem);
12031 rv = pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, conn_reqnv,
12032 ARRLEN(conn_reqnv), mem);
12034 CU_ASSERT(0 == rv);
12036 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
12037 nghttp2_buf_len(&bufs.head->buf));
12039 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
12041 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
12043 stream = nghttp2_session_get_stream(session, 1);
12045 CU_ASSERT(-1 == stream->content_length);
12046 CU_ASSERT((stream->http_flags & NGHTTP2_HTTP_FLAG_METH_CONNECT) > 0);
12048 nghttp2_hd_deflate_free(&deflater);
12049 nghttp2_session_del(session);
12050 nghttp2_bufs_free(&bufs);
12053 void test_nghttp2_http_record_request_method(void) {
12054 nghttp2_session *session;
12055 nghttp2_session_callbacks callbacks;
12056 const nghttp2_nv conn_reqnv[] = {MAKE_NV(":method", "CONNECT"),
12057 MAKE_NV(":authority", "localhost")};
12058 const nghttp2_nv conn_resnv[] = {MAKE_NV(":status", "200"),
12059 MAKE_NV("content-length", "9999")};
12060 nghttp2_stream *stream;
12063 nghttp2_hd_deflater deflater;
12065 nghttp2_outbound_item *item;
12067 mem = nghttp2_mem_default();
12068 frame_pack_bufs_init(&bufs);
12070 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
12071 callbacks.send_callback = null_send_callback;
12073 nghttp2_session_client_new(&session, &callbacks, NULL);
12075 nghttp2_hd_deflate_init(&deflater, mem);
12077 CU_ASSERT(1 == nghttp2_submit_request(session, NULL, conn_reqnv,
12078 ARRLEN(conn_reqnv), NULL, NULL));
12080 CU_ASSERT(0 == nghttp2_session_send(session));
12082 stream = nghttp2_session_get_stream(session, 1);
12084 CU_ASSERT(NGHTTP2_HTTP_FLAG_METH_CONNECT == stream->http_flags);
12086 rv = pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, conn_resnv,
12087 ARRLEN(conn_resnv), mem);
12088 CU_ASSERT(0 == rv);
12090 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
12091 nghttp2_buf_len(&bufs.head->buf));
12093 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
12095 CU_ASSERT((NGHTTP2_HTTP_FLAG_METH_CONNECT & stream->http_flags) > 0);
12096 CU_ASSERT(-1 == stream->content_length);
12098 /* content-length is ignored in 200 response to a CONNECT request */
12099 item = nghttp2_session_get_next_ob_item(session);
12101 CU_ASSERT(NULL == item);
12103 nghttp2_hd_deflate_free(&deflater);
12104 nghttp2_session_del(session);
12105 nghttp2_bufs_free(&bufs);
12108 void test_nghttp2_http_push_promise(void) {
12109 nghttp2_session *session;
12110 nghttp2_session_callbacks callbacks;
12111 nghttp2_hd_deflater deflater;
12115 nghttp2_stream *stream;
12116 const nghttp2_nv bad_reqnv[] = {MAKE_NV(":method", "GET")};
12117 nghttp2_outbound_item *item;
12119 mem = nghttp2_mem_default();
12120 frame_pack_bufs_init(&bufs);
12122 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
12123 callbacks.send_callback = null_send_callback;
12125 /* good PUSH_PROMISE case */
12126 nghttp2_session_client_new(&session, &callbacks, NULL);
12128 nghttp2_hd_deflate_init(&deflater, mem);
12130 open_sent_stream2(session, 1, NGHTTP2_STREAM_OPENING);
12132 rv = pack_push_promise(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, 2,
12133 reqnv, ARRLEN(reqnv), mem);
12134 CU_ASSERT(0 == rv);
12136 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
12137 nghttp2_buf_len(&bufs.head->buf));
12139 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
12141 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
12143 stream = nghttp2_session_get_stream(session, 2);
12144 CU_ASSERT(NULL != stream);
12146 nghttp2_bufs_reset(&bufs);
12148 rv = pack_headers(&bufs, &deflater, 2, NGHTTP2_FLAG_END_HEADERS, resnv,
12149 ARRLEN(resnv), mem);
12151 CU_ASSERT(0 == rv);
12153 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
12154 nghttp2_buf_len(&bufs.head->buf));
12156 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
12158 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
12160 CU_ASSERT(200 == stream->status_code);
12162 nghttp2_bufs_reset(&bufs);
12164 /* PUSH_PROMISE lacks mandatory header */
12165 rv = pack_push_promise(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, 4,
12166 bad_reqnv, ARRLEN(bad_reqnv), mem);
12168 CU_ASSERT(0 == rv);
12170 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
12171 nghttp2_buf_len(&bufs.head->buf));
12173 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
12175 item = nghttp2_session_get_next_ob_item(session);
12177 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
12178 CU_ASSERT(4 == item->frame.hd.stream_id);
12180 nghttp2_bufs_reset(&bufs);
12182 nghttp2_hd_deflate_free(&deflater);
12183 nghttp2_session_del(session);
12184 nghttp2_bufs_free(&bufs);
12187 void test_nghttp2_http_head_method_upgrade_workaround(void) {
12188 nghttp2_session *session;
12189 nghttp2_session_callbacks callbacks;
12190 const nghttp2_nv cl_resnv[] = {MAKE_NV(":status", "200"),
12191 MAKE_NV("content-length", "1000000007")};
12193 nghttp2_hd_deflater deflater;
12196 nghttp2_stream *stream;
12198 mem = nghttp2_mem_default();
12199 frame_pack_bufs_init(&bufs);
12201 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
12202 callbacks.send_callback = null_send_callback;
12204 nghttp2_session_client_new(&session, &callbacks, NULL);
12206 nghttp2_hd_deflate_init(&deflater, mem);
12208 nghttp2_session_upgrade(session, NULL, 0, NULL);
12210 rv = pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, cl_resnv,
12211 ARRLEN(cl_resnv), mem);
12213 CU_ASSERT(0 == rv);
12215 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
12216 nghttp2_buf_len(&bufs.head->buf));
12218 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
12220 stream = nghttp2_session_get_stream(session, 1);
12222 CU_ASSERT(-1 == stream->content_length);
12224 nghttp2_hd_deflate_free(&deflater);
12225 nghttp2_session_del(session);
12226 nghttp2_bufs_free(&bufs);