Upgrade to 1.46.0
[platform/upstream/nghttp2.git] / tests / nghttp2_session_test.c
1 /*
2  * nghttp2 - HTTP/2 C Library
3  *
4  * Copyright (c) 2013 Tatsuhiro Tsujikawa
5  *
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:
13  *
14  * The above copyright notice and this permission notice shall be
15  * included in all copies or substantial portions of the Software.
16  *
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.
24  */
25 #include "nghttp2_session_test.h"
26
27 #include <stdio.h>
28 #include <assert.h>
29
30 #include <CUnit/CUnit.h>
31
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"
38
39 typedef struct {
40   uint8_t buf[65535];
41   size_t length;
42 } accumulator;
43
44 typedef struct {
45   uint8_t data[8192];
46   uint8_t *datamark;
47   uint8_t *datalimit;
48   size_t feedseq[8192];
49   size_t seqidx;
50 } scripted_data_feed;
51
52 typedef struct {
53   accumulator *acc;
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;
63   int not_sent_error;
64   int stream_close_cb_called;
65   uint32_t stream_close_error_code;
66   size_t data_source_length;
67   int32_t stream_id;
68   size_t block_count;
69   int data_chunk_recv_cb_called;
70   const nghttp2_frame *frame;
71   size_t fixed_sendlen;
72   int header_cb_called;
73   int invalid_header_cb_called;
74   int begin_headers_cb_called;
75   nghttp2_nv nv;
76   size_t data_chunk_len;
77   size_t padlen;
78   int begin_frame_cb_called;
79   nghttp2_buf scratchbuf;
80   size_t data_source_read_cb_paused;
81 } my_user_data;
82
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"),
88 };
89
90 static const nghttp2_nv resnv[] = {
91     MAKE_NV(":status", "200"),
92 };
93
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=="),
99 };
100
101 static void scripted_data_feed_init2(scripted_data_feed *df,
102                                      nghttp2_bufs *bufs) {
103   nghttp2_buf_chain *ci;
104   nghttp2_buf *buf;
105   uint8_t *ptr;
106   size_t len;
107
108   memset(df, 0, sizeof(scripted_data_feed));
109   ptr = df->data;
110   len = 0;
111
112   for (ci = bufs->head; ci; ci = ci->next) {
113     buf = &ci->buf;
114     ptr = nghttp2_cpymem(ptr, buf->pos, nghttp2_buf_len(buf));
115     len += nghttp2_buf_len(buf);
116   }
117
118   df->datamark = df->data;
119   df->datalimit = df->data + len;
120   df->feedseq[0] = len;
121 }
122
123 static ssize_t null_send_callback(nghttp2_session *session, const uint8_t *data,
124                                   size_t len, int flags, void *user_data) {
125   (void)session;
126   (void)data;
127   (void)flags;
128   (void)user_data;
129
130   return (ssize_t)len;
131 }
132
133 static ssize_t fail_send_callback(nghttp2_session *session, const uint8_t *data,
134                                   size_t len, int flags, void *user_data) {
135   (void)session;
136   (void)data;
137   (void)len;
138   (void)flags;
139   (void)user_data;
140
141   return NGHTTP2_ERR_CALLBACK_FAILURE;
142 }
143
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;
148   (void)session;
149   (void)data;
150   (void)flags;
151
152   return (ssize_t)(fixed_sendlen < len ? fixed_sendlen : len);
153 }
154
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];
159   (void)session;
160   (void)flags;
161
162   memcpy(data, df->datamark, wlen);
163   df->datamark += wlen;
164   df->feedseq[df->seqidx] -= wlen;
165   if (df->feedseq[df->seqidx] == 0) {
166     ++df->seqidx;
167   }
168   return (ssize_t)wlen;
169 }
170
171 static ssize_t eof_recv_callback(nghttp2_session *session, uint8_t *data,
172                                  size_t len, int flags, void *user_data) {
173   (void)session;
174   (void)data;
175   (void)len;
176   (void)flags;
177   (void)user_data;
178
179   return NGHTTP2_ERR_EOF;
180 }
181
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;
186   (void)session;
187   (void)flags;
188
189   assert(acc->length + len < sizeof(acc->buf));
190   memcpy(acc->buf + acc->length, buf, len);
191   acc->length += len;
192   return (ssize_t)len;
193 }
194
195 static int on_begin_frame_callback(nghttp2_session *session,
196                                    const nghttp2_frame_hd *hd,
197                                    void *user_data) {
198   my_user_data *ud = (my_user_data *)user_data;
199   (void)session;
200   (void)hd;
201
202   ++ud->begin_frame_cb_called;
203   return 0;
204 }
205
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;
209   (void)session;
210
211   ++ud->frame_recv_cb_called;
212   ud->recv_frame_type = frame->hd.type;
213   ud->recv_frame_hd = frame->hd;
214
215   return 0;
216 }
217
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;
222   (void)session;
223   (void)frame;
224   (void)lib_error_code;
225
226   ++ud->invalid_frame_recv_cb_called;
227   return 0;
228 }
229
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;
233   (void)session;
234
235   ++ud->frame_send_cb_called;
236   ud->sent_frame_type = frame->hd.type;
237   return 0;
238 }
239
240 static int on_frame_not_send_callback(nghttp2_session *session,
241                                       const nghttp2_frame *frame, int lib_error,
242                                       void *user_data) {
243   my_user_data *ud = (my_user_data *)user_data;
244   (void)session;
245
246   ++ud->frame_not_send_cb_called;
247   ud->not_sent_frame_type = frame->hd.type;
248   ud->not_sent_error = lib_error;
249   return 0;
250 }
251
252 static int cancel_before_frame_send_callback(nghttp2_session *session,
253                                              const nghttp2_frame *frame,
254                                              void *user_data) {
255   my_user_data *ud = (my_user_data *)user_data;
256   (void)session;
257   (void)frame;
258
259   ++ud->before_frame_send_cb_called;
260   return NGHTTP2_ERR_CANCEL;
261 }
262
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;
267   (void)session;
268   (void)flags;
269   (void)stream_id;
270   (void)data;
271
272   ++ud->data_chunk_recv_cb_called;
273   ud->data_chunk_len = len;
274   return 0;
275 }
276
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,
280                                              void *user_data) {
281   my_user_data *ud = (my_user_data *)user_data;
282   (void)session;
283   (void)flags;
284   (void)stream_id;
285   (void)data;
286   (void)len;
287
288   ++ud->data_chunk_recv_cb_called;
289   return NGHTTP2_ERR_PAUSE;
290 }
291
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;
296   (void)session;
297
298   return (ssize_t)nghttp2_min(max_payloadlen, frame->hd.length + ud->padlen);
299 }
300
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) {
305   (void)session;
306   (void)frame_type;
307   (void)stream_id;
308   (void)session_remote_window_size;
309   (void)stream_remote_window_size;
310   (void)remote_max_frame_size;
311   (void)user_data;
312
313   return NGHTTP2_MAX_FRAME_SIZE_MAX + 1;
314 }
315
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) {
320   (void)session;
321   (void)frame_type;
322   (void)stream_id;
323   (void)session_remote_window_size;
324   (void)stream_remote_window_size;
325   (void)remote_max_frame_size;
326   (void)user_data;
327
328   return 1;
329 }
330
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;
335   size_t wlen;
336   (void)session;
337   (void)stream_id;
338   (void)buf;
339   (void)source;
340
341   if (len < ud->data_source_length) {
342     wlen = len;
343   } else {
344     wlen = ud->data_source_length;
345   }
346   ud->data_source_length -= wlen;
347   if (ud->data_source_length == 0) {
348     *data_flags |= NGHTTP2_DATA_FLAG_EOF;
349   }
350   return (ssize_t)wlen;
351 }
352
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) {
356   (void)session;
357   (void)stream_id;
358   (void)buf;
359   (void)len;
360   (void)data_flags;
361   (void)source;
362   (void)user_data;
363
364   return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
365 }
366
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,
371                                               void *user_data) {
372   (void)session;
373   (void)stream_id;
374   (void)buf;
375   (void)len;
376   (void)data_flags;
377   (void)source;
378   (void)user_data;
379
380   return NGHTTP2_ERR_CALLBACK_FAILURE;
381 }
382
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) {
386   (void)session;
387   (void)stream_id;
388   (void)buf;
389   (void)len;
390   (void)source;
391   (void)user_data;
392
393   *data_flags |= NGHTTP2_DATA_FLAG_EOF | NGHTTP2_DATA_FLAG_NO_END_STREAM;
394   return 0;
395 }
396
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;
401   size_t wlen;
402   (void)session;
403   (void)stream_id;
404   (void)buf;
405   (void)source;
406
407   if (len < ud->data_source_length) {
408     wlen = len;
409   } else {
410     wlen = ud->data_source_length;
411   }
412
413   ud->data_source_length -= wlen;
414
415   *data_flags |= NGHTTP2_DATA_FLAG_NO_COPY;
416
417   if (ud->data_source_length == 0) {
418     *data_flags |= NGHTTP2_DATA_FLAG_EOF;
419   }
420   return (ssize_t)wlen;
421 }
422
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;
427   (void)session;
428   (void)source;
429
430   memcpy(acc->buf + acc->length, framehd, NGHTTP2_FRAME_HDLEN);
431   acc->length += NGHTTP2_FRAME_HDLEN;
432
433   if (frame->data.padlen) {
434     *(acc->buf + acc->length++) = (uint8_t)(frame->data.padlen - 1);
435   }
436
437   acc->length += length;
438
439   if (frame->data.padlen) {
440     acc->length += frame->data.padlen - 1;
441   }
442
443   return 0;
444 }
445
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;
450   (void)session;
451   (void)data;
452   (void)flags;
453
454   if (ud->block_count == 0) {
455     return NGHTTP2_ERR_WOULDBLOCK;
456   }
457
458   --ud->block_count;
459   return (ssize_t)len;
460 }
461
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;
467   (void)session;
468   (void)flags;
469
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;
475
476   ud->frame = frame;
477   return 0;
478 }
479
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,
486                      user_data);
487   return NGHTTP2_ERR_PAUSE;
488 }
489
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,
493     void *user_data) {
494   on_header_callback(session, frame, name, namelen, value, valuelen, flags,
495                      user_data);
496   return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
497 }
498
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;
505   (void)session;
506   (void)flags;
507
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;
513
514   ud->frame = frame;
515   return 0;
516 }
517
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,
523                                             void *user_data) {
524   on_invalid_header_callback(session, frame, name, namelen, value, valuelen,
525                              flags, user_data);
526   return NGHTTP2_ERR_PAUSE;
527 }
528
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,
534                                             void *user_data) {
535   on_invalid_header_callback(session, frame, name, namelen, value, valuelen,
536                              flags, user_data);
537   return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
538 }
539
540 static int on_begin_headers_callback(nghttp2_session *session,
541                                      const nghttp2_frame *frame,
542                                      void *user_data) {
543   my_user_data *ud = (my_user_data *)user_data;
544   (void)session;
545   (void)frame;
546
547   ++ud->begin_headers_cb_called;
548   return 0;
549 }
550
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;
555 }
556
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,
561                                                void *user_data) {
562   (void)session;
563   (void)stream_id;
564   (void)buf;
565   (void)len;
566   (void)data_flags;
567   (void)source;
568   (void)user_data;
569
570   return NGHTTP2_ERR_DEFERRED;
571 }
572
573 static int on_stream_close_callback(nghttp2_session *session, int32_t stream_id,
574                                     nghttp2_error_code error_code,
575                                     void *user_data) {
576   my_user_data *my_data = (my_user_data *)user_data;
577   (void)session;
578   (void)stream_id;
579   (void)error_code;
580
581   ++my_data->stream_close_cb_called;
582   my_data->stream_close_error_code = error_code;
583
584   return 0;
585 }
586
587 static ssize_t pack_extension_callback(nghttp2_session *session, uint8_t *buf,
588                                        size_t len, const nghttp2_frame *frame,
589                                        void *user_data) {
590   nghttp2_buf *p = frame->ext.payload;
591   (void)session;
592   (void)len;
593   (void)user_data;
594
595   memcpy(buf, p->pos, nghttp2_buf_len(p));
596
597   return (ssize_t)nghttp2_buf_len(p);
598 }
599
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,
603                                             void *user_data) {
604   my_user_data *my_data = (my_user_data *)user_data;
605   nghttp2_buf *buf = &my_data->scratchbuf;
606   (void)session;
607   (void)hd;
608
609   buf->last = nghttp2_cpymem(buf->last, data, len);
610
611   return 0;
612 }
613
614 static int cancel_on_extension_chunk_recv_callback(nghttp2_session *session,
615                                                    const nghttp2_frame_hd *hd,
616                                                    const uint8_t *data,
617                                                    size_t len,
618                                                    void *user_data) {
619   (void)session;
620   (void)hd;
621   (void)data;
622   (void)len;
623   (void)user_data;
624
625   return NGHTTP2_ERR_CANCEL;
626 }
627
628 static int unpack_extension_callback(nghttp2_session *session, void **payload,
629                                      const nghttp2_frame_hd *hd,
630                                      void *user_data) {
631   my_user_data *my_data = (my_user_data *)user_data;
632   nghttp2_buf *buf = &my_data->scratchbuf;
633   (void)session;
634   (void)hd;
635
636   *payload = buf;
637
638   return 0;
639 }
640
641 static int cancel_unpack_extension_callback(nghttp2_session *session,
642                                             void **payload,
643                                             const nghttp2_frame_hd *hd,
644                                             void *user_data) {
645   (void)session;
646   (void)payload;
647   (void)hd;
648   (void)user_data;
649
650   return NGHTTP2_ERR_CANCEL;
651 }
652
653 static nghttp2_settings_entry *dup_iv(const nghttp2_settings_entry *iv,
654                                       size_t niv) {
655   return nghttp2_frame_iv_copy(iv, niv, nghttp2_mem_default());
656 }
657
658 static nghttp2_priority_spec pri_spec_default = {0, NGHTTP2_DEFAULT_WEIGHT, 0};
659
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;
665   nghttp2_bufs bufs;
666   size_t framelen;
667   nghttp2_frame frame;
668   size_t i;
669   nghttp2_outbound_item *item;
670   nghttp2_nv *nva;
671   size_t nvlen;
672   nghttp2_hd_deflater deflater;
673   int rv;
674   nghttp2_mem *mem;
675
676   mem = nghttp2_mem_default();
677   frame_pack_bufs_init(&bufs);
678
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;
684
685   user_data.df = &df;
686
687   nghttp2_session_server_new(&session, &callbacks, &user_data);
688   nghttp2_hd_deflate_init(&deflater, mem);
689
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);
695
696   CU_ASSERT(0 == rv);
697
698   scripted_data_feed_init2(&df, &bufs);
699
700   framelen = nghttp2_bufs_len(&bufs);
701
702   /* Send 1 byte per each read */
703   for (i = 0; i < framelen; ++i) {
704     df.feedseq[i] = 1;
705   }
706
707   nghttp2_frame_headers_free(&frame.headers, mem);
708
709   user_data.frame_recv_cb_called = 0;
710   user_data.begin_frame_cb_called = 0;
711
712   while (df.seqidx < framelen) {
713     CU_ASSERT(0 == nghttp2_session_recv(session));
714   }
715   CU_ASSERT(1 == user_data.frame_recv_cb_called);
716   CU_ASSERT(1 == user_data.begin_frame_cb_called);
717
718   nghttp2_bufs_reset(&bufs);
719
720   /* Receive PRIORITY */
721   nghttp2_frame_priority_init(&frame.priority, 5, &pri_spec_default);
722
723   rv = nghttp2_frame_pack_priority(&bufs, &frame.priority);
724
725   CU_ASSERT(0 == rv);
726
727   nghttp2_frame_priority_free(&frame.priority);
728
729   scripted_data_feed_init2(&df, &bufs);
730
731   user_data.frame_recv_cb_called = 0;
732   user_data.begin_frame_cb_called = 0;
733
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);
737
738   nghttp2_bufs_reset(&bufs);
739
740   nghttp2_hd_deflate_free(&deflater);
741   nghttp2_session_del(session);
742
743   /* Some tests for frame too large */
744   nghttp2_session_server_new(&session, &callbacks, &user_data);
745
746   /* Receive PING with too large payload */
747   nghttp2_frame_ping_init(&frame.ping, NGHTTP2_FLAG_NONE, NULL);
748
749   rv = nghttp2_frame_pack_ping(&bufs, &frame.ping);
750
751   CU_ASSERT(0 == rv);
752
753   /* Add extra 16 bytes */
754   nghttp2_bufs_seek_last_present(&bufs);
755   assert(nghttp2_buf_len(&bufs.cur->buf) >= 16);
756
757   bufs.cur->buf.last += 16;
758   nghttp2_put_uint32be(
759       bufs.cur->buf.pos,
760       (uint32_t)(((frame.hd.length + 16) << 8) + bufs.cur->buf.pos[3]));
761
762   nghttp2_frame_ping_free(&frame.ping);
763
764   scripted_data_feed_init2(&df, &bufs);
765   user_data.frame_recv_cb_called = 0;
766   user_data.begin_frame_cb_called = 0;
767
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);
771
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));
776
777   nghttp2_bufs_free(&bufs);
778   nghttp2_session_del(session);
779 }
780
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;
786   nghttp2_bufs bufs;
787   nghttp2_frame frame;
788   nghttp2_hd_deflater deflater;
789   int rv;
790   nghttp2_mem *mem;
791   nghttp2_nv *nva;
792   size_t nvlen;
793
794   mem = nghttp2_mem_default();
795   frame_pack_bufs_init(&bufs);
796
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;
800
801   user_data.df = &df;
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);
805
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);
811
812   CU_ASSERT(0 == rv);
813   CU_ASSERT(nghttp2_bufs_len(&bufs) > 0);
814
815   scripted_data_feed_init2(&df, &bufs);
816   nghttp2_frame_headers_free(&frame.headers, mem);
817
818   CU_ASSERT(0 == nghttp2_session_recv(session));
819   CU_ASSERT(1 == user_data.invalid_frame_recv_cb_called);
820
821   nghttp2_bufs_free(&bufs);
822   nghttp2_hd_deflate_free(&deflater);
823   nghttp2_session_del(session);
824 }
825
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;
831   nghttp2_bufs bufs;
832   nghttp2_frame frame;
833   nghttp2_nv *nva;
834   size_t nvlen;
835   nghttp2_hd_deflater deflater;
836   int rv;
837   nghttp2_mem *mem;
838
839   mem = nghttp2_mem_default();
840   frame_pack_bufs_init(&bufs);
841
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;
846
847   user_data.df = &df;
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);
856
857   CU_ASSERT(0 == rv);
858   CU_ASSERT(nghttp2_bufs_len(&bufs) > 0);
859
860   scripted_data_feed_init2(&df, &bufs);
861
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);
865
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);
869
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);
874
875   nghttp2_bufs_free(&bufs);
876   nghttp2_frame_headers_free(&frame.headers, mem);
877
878   nghttp2_hd_deflate_free(&deflater);
879   nghttp2_session_del(session);
880 }
881
882 void test_nghttp2_session_recv_eof(void) {
883   nghttp2_session *session;
884   nghttp2_session_callbacks callbacks;
885
886   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
887   callbacks.send_callback = null_send_callback;
888   callbacks.recv_callback = eof_recv_callback;
889
890   nghttp2_session_client_new(&session, &callbacks, NULL);
891   CU_ASSERT(NGHTTP2_ERR_EOF == nghttp2_session_recv(session));
892
893   nghttp2_session_del(session);
894 }
895
896 void test_nghttp2_session_recv_data(void) {
897   nghttp2_session *session;
898   nghttp2_session_callbacks callbacks;
899   my_user_data ud;
900   uint8_t data[8092];
901   ssize_t rv;
902   nghttp2_outbound_item *item;
903   nghttp2_stream *stream;
904   nghttp2_frame_hd hd;
905   int i;
906
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;
912
913   nghttp2_session_client_new(&session, &callbacks, &ud);
914
915   /* Create DATA frame with length 4KiB */
916   memset(data, 0, sizeof(data));
917   hd.length = 4096;
918   hd.type = NGHTTP2_DATA;
919   hd.flags = NGHTTP2_FLAG_NONE;
920   hd.stream_id = 1;
921   nghttp2_frame_pack_frame_hd(data, &hd);
922
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);
929
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);
934
935   nghttp2_session_del(session);
936
937   nghttp2_session_client_new(&session, &callbacks, &ud);
938
939   /* Create stream 1 with CLOSING state. DATA is ignored. */
940   stream = open_sent_stream2(session, 1, NGHTTP2_STREAM_CLOSING);
941
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;
945
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);
950
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);
955
956   /* This is normal case. DATA is acceptable. */
957   stream->state = NGHTTP2_STREAM_OPENED;
958
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);
963
964   CU_ASSERT(1 == ud.data_chunk_recv_cb_called);
965   CU_ASSERT(1 == ud.frame_recv_cb_called);
966
967   CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
968
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);
973
974   /* Now we got data more than initial-window-size / 2, WINDOW_UPDATE
975      must be queued */
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));
982
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
989      in. */
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);
993   }
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));
998
999   /* Reception of DATA with stream ID = 0 causes connection error */
1000   hd.length = 4096;
1001   hd.type = NGHTTP2_DATA;
1002   hd.flags = NGHTTP2_FLAG_NONE;
1003   hd.stream_id = 0;
1004   nghttp2_frame_pack_frame_hd(data, &hd);
1005
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);
1010
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);
1016
1017   nghttp2_session_del(session);
1018
1019   /* Check window_update_queued flag in both session and stream */
1020   nghttp2_session_server_new(&session, &callbacks, &ud);
1021
1022   hd.length = 4096;
1023   hd.type = NGHTTP2_DATA;
1024   hd.flags = NGHTTP2_FLAG_NONE;
1025   hd.stream_id = 1;
1026   nghttp2_frame_pack_frame_hd(data, &hd);
1027
1028   stream = open_recv_stream(session, 1);
1029
1030   /* Send 32767 bytes of DATA.  In our current flow control algorithm,
1031      it triggers first WINDOW_UPDATE of window_size_increment
1032      32767. */
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);
1036   }
1037
1038   hd.length = 4095;
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);
1042
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);
1048
1049   /* Then send 32768 bytes of DATA.  Since we have not sent queued
1050      WINDOW_UDPATE frame, recv_window_size should not be decreased */
1051   hd.length = 4096;
1052   nghttp2_frame_pack_frame_hd(data, &hd);
1053
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);
1057   }
1058
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);
1065
1066   ud.frame_send_cb_called = 0;
1067
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));
1072
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);
1078
1079   nghttp2_session_del(session);
1080 }
1081
1082 void test_nghttp2_session_recv_data_no_auto_flow_control(void) {
1083   nghttp2_session *session;
1084   nghttp2_session_callbacks callbacks;
1085   my_user_data ud;
1086   nghttp2_option *option;
1087   nghttp2_frame_hd hd;
1088   size_t padlen;
1089   uint8_t data[8192];
1090   ssize_t rv;
1091   size_t sendlen;
1092   nghttp2_stream *stream;
1093   size_t i;
1094
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;
1098
1099   nghttp2_option_new(&option);
1100   nghttp2_option_set_no_auto_window_update(option, 1);
1101
1102   nghttp2_session_server_new2(&session, &callbacks, &ud, option);
1103
1104   /* Create DATA frame with length 4KiB + 11 bytes padding*/
1105   padlen = 11;
1106   memset(data, 0, sizeof(data));
1107   hd.length = 4096 + 1 + padlen;
1108   hd.type = NGHTTP2_DATA;
1109   hd.flags = NGHTTP2_FLAG_PADDED;
1110   hd.stream_id = 1;
1111   nghttp2_frame_pack_frame_hd(data, &hd);
1112   data[NGHTTP2_FRAME_HDLEN] = (uint8_t)padlen;
1113
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);
1117
1118   /* Receive first 100 bytes */
1119   sendlen = 100;
1120   rv = nghttp2_session_mem_recv(session, data, sendlen);
1121   CU_ASSERT((ssize_t)sendlen == rv);
1122
1123   /* We consumed pad length field (1 byte) */
1124   CU_ASSERT(1 == session->consumed_size);
1125
1126   /* close stream here */
1127   nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, 1, NGHTTP2_NO_ERROR);
1128   nghttp2_session_send(session);
1129
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);
1135
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);
1139
1140   nghttp2_session_del(session);
1141
1142   /* Reuse DATA created previously. */
1143
1144   nghttp2_session_server_new2(&session, &callbacks, &ud, option);
1145
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;
1150
1151   rv = nghttp2_session_mem_recv(session, data, NGHTTP2_FRAME_HDLEN + hd.length);
1152   CU_ASSERT((ssize_t)(NGHTTP2_FRAME_HDLEN + hd.length) == rv);
1153
1154   /* Whole payload must be consumed now because HTTP messaging rule
1155      was not honored. */
1156   CU_ASSERT((int32_t)hd.length == session->consumed_size);
1157
1158   nghttp2_session_del(session);
1159
1160   /* Check window_update_queued flag in both session and stream */
1161   nghttp2_session_server_new2(&session, &callbacks, &ud, option);
1162
1163   stream = open_recv_stream(session, 1);
1164
1165   hd.length = 4096;
1166   hd.type = NGHTTP2_DATA;
1167   hd.flags = NGHTTP2_FLAG_NONE;
1168   hd.stream_id = 1;
1169   nghttp2_frame_pack_frame_hd(data, &hd);
1170
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);
1175   }
1176
1177   hd.length = 4095;
1178   nghttp2_frame_pack_frame_hd(data, &hd);
1179
1180   rv = nghttp2_session_mem_recv(session, data, NGHTTP2_FRAME_HDLEN + 4095);
1181   CU_ASSERT(NGHTTP2_FRAME_HDLEN + 4095 == rv);
1182
1183   CU_ASSERT(65535 == session->recv_window_size);
1184   CU_ASSERT(65535 == stream->recv_window_size);
1185
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);
1190
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);
1195
1196   ud.frame_send_cb_called = 0;
1197
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);
1206
1207   /* Do the same for stream */
1208   nghttp2_session_consume_stream(session, 1, 32767);
1209   nghttp2_session_consume_stream(session, 1, 32768);
1210
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);
1215
1216   ud.frame_send_cb_called = 0;
1217
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);
1224
1225   nghttp2_session_del(session);
1226   nghttp2_option_del(option);
1227 }
1228
1229 void test_nghttp2_session_recv_continuation(void) {
1230   nghttp2_session *session;
1231   nghttp2_session_callbacks callbacks;
1232   nghttp2_nv *nva;
1233   size_t nvlen;
1234   nghttp2_frame frame;
1235   nghttp2_bufs bufs;
1236   nghttp2_buf *buf;
1237   ssize_t rv;
1238   my_user_data ud;
1239   nghttp2_hd_deflater deflater;
1240   uint8_t data[1024];
1241   size_t datalen;
1242   nghttp2_frame_hd cont_hd;
1243   nghttp2_priority_spec pri_spec;
1244   nghttp2_mem *mem;
1245
1246   mem = nghttp2_mem_default();
1247   frame_pack_bufs_init(&bufs);
1248
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;
1253
1254   nghttp2_session_server_new(&session, &callbacks, &ud);
1255
1256   nghttp2_hd_deflate_init(&deflater, mem);
1257
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);
1264
1265   CU_ASSERT(0 == rv);
1266   CU_ASSERT(nghttp2_bufs_len(&bufs) > 0);
1267
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));
1271
1272   nghttp2_frame_headers_free(&frame.headers, mem);
1273
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;
1278
1279   nghttp2_put_uint32be(data, (uint32_t)((1 << 8) + data[3]));
1280
1281   /* First CONTINUATION, 2 bytes */
1282   nghttp2_frame_hd_init(&cont_hd, 2, NGHTTP2_CONTINUATION, NGHTTP2_FLAG_NONE,
1283                         1);
1284
1285   nghttp2_frame_pack_frame_hd(data + datalen, &cont_hd);
1286   datalen += NGHTTP2_FRAME_HDLEN;
1287
1288   memcpy(data + datalen, buf->pos, cont_hd.length);
1289   datalen += cont_hd.length;
1290   buf->pos += cont_hd.length;
1291
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);
1295
1296   nghttp2_frame_pack_frame_hd(data + datalen, &cont_hd);
1297   datalen += NGHTTP2_FRAME_HDLEN;
1298
1299   memcpy(data + datalen, buf->pos, cont_hd.length);
1300   datalen += cont_hd.length;
1301   buf->pos += cont_hd.length;
1302
1303   CU_ASSERT(0 == nghttp2_buf_len(buf));
1304
1305   ud.header_cb_called = 0;
1306   ud.begin_frame_cb_called = 0;
1307
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);
1312
1313   nghttp2_hd_deflate_free(&deflater);
1314   nghttp2_session_del(session);
1315
1316   /* HEADERS with padding followed by CONTINUATION */
1317   nghttp2_session_server_new(&session, &callbacks, &ud);
1318
1319   nghttp2_hd_deflate_init(&deflater, mem);
1320
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);
1325
1326   nghttp2_bufs_reset(&bufs);
1327   rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
1328
1329   CU_ASSERT(0 == rv);
1330
1331   nghttp2_frame_headers_free(&frame.headers, mem);
1332
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));
1336
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;
1341   /* padding field */
1342   data[NGHTTP2_FRAME_HDLEN] = 1;
1343   data[NGHTTP2_FRAME_HDLEN + 1] = buf->pos[NGHTTP2_FRAME_HDLEN];
1344   /* padding */
1345   data[NGHTTP2_FRAME_HDLEN + 2] = 0;
1346   datalen = NGHTTP2_FRAME_HDLEN + 3;
1347   buf->pos += NGHTTP2_FRAME_HDLEN + 1;
1348
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;
1354
1355   memcpy(data + datalen, buf->pos, cont_hd.length);
1356   datalen += cont_hd.length;
1357   buf->pos += cont_hd.length;
1358
1359   CU_ASSERT(0 == nghttp2_buf_len(buf));
1360
1361   ud.header_cb_called = 0;
1362   ud.begin_frame_cb_called = 0;
1363
1364   rv = nghttp2_session_mem_recv(session, data, datalen);
1365
1366   CU_ASSERT((ssize_t)datalen == rv);
1367   CU_ASSERT(4 == ud.header_cb_called);
1368   CU_ASSERT(2 == ud.begin_frame_cb_called);
1369
1370   nghttp2_hd_deflate_free(&deflater);
1371   nghttp2_session_del(session);
1372
1373   /* Expecting CONTINUATION, but get the other frame */
1374   nghttp2_session_server_new(&session, &callbacks, &ud);
1375
1376   nghttp2_hd_deflate_init(&deflater, mem);
1377
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);
1385
1386   CU_ASSERT(0 == rv);
1387   CU_ASSERT(nghttp2_bufs_len(&bufs) > 0);
1388
1389   nghttp2_frame_headers_free(&frame.headers, mem);
1390
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));
1394
1395   memcpy(data, buf->pos, nghttp2_buf_len(buf));
1396   datalen = nghttp2_buf_len(buf);
1397
1398   /* Followed by PRIORITY */
1399   nghttp2_priority_spec_default_init(&pri_spec);
1400
1401   nghttp2_frame_priority_init(&frame.priority, 1, &pri_spec);
1402   nghttp2_bufs_reset(&bufs);
1403
1404   rv = nghttp2_frame_pack_priority(&bufs, &frame.priority);
1405
1406   CU_ASSERT(0 == rv);
1407   CU_ASSERT(nghttp2_bufs_len(&bufs) > 0);
1408
1409   memcpy(data + datalen, buf->pos, nghttp2_buf_len(buf));
1410   datalen += nghttp2_buf_len(buf);
1411
1412   ud.begin_headers_cb_called = 0;
1413   rv = nghttp2_session_mem_recv(session, data, datalen);
1414   CU_ASSERT((ssize_t)datalen == rv);
1415
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);
1419
1420   nghttp2_bufs_free(&bufs);
1421   nghttp2_hd_deflate_free(&deflater);
1422   nghttp2_session_del(session);
1423 }
1424
1425 void test_nghttp2_session_recv_headers_with_priority(void) {
1426   nghttp2_session *session;
1427   nghttp2_session_callbacks callbacks;
1428   nghttp2_nv *nva;
1429   size_t nvlen;
1430   nghttp2_frame frame;
1431   nghttp2_bufs bufs;
1432   nghttp2_buf *buf;
1433   ssize_t rv;
1434   my_user_data ud;
1435   nghttp2_hd_deflater deflater;
1436   nghttp2_outbound_item *item;
1437   nghttp2_priority_spec pri_spec;
1438   nghttp2_stream *stream;
1439   nghttp2_mem *mem;
1440
1441   mem = nghttp2_mem_default();
1442   frame_pack_bufs_init(&bufs);
1443
1444   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
1445   callbacks.on_frame_recv_callback = on_frame_recv_callback;
1446
1447   nghttp2_session_server_new(&session, &callbacks, &ud);
1448
1449   nghttp2_hd_deflate_init(&deflater, mem);
1450
1451   open_recv_stream(session, 1);
1452
1453   /* With NGHTTP2_FLAG_PRIORITY without exclusive flag set */
1454   nvlen = ARRLEN(reqnv);
1455   nghttp2_nv_array_copy(&nva, reqnv, nvlen, mem);
1456
1457   nghttp2_priority_spec_init(&pri_spec, 1, 99, 0);
1458
1459   nghttp2_frame_headers_init(&frame.headers,
1460                              NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PRIORITY,
1461                              3, NGHTTP2_HCAT_HEADERS, &pri_spec, nva, nvlen);
1462
1463   rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
1464
1465   CU_ASSERT(0 == rv);
1466   CU_ASSERT(nghttp2_bufs_len(&bufs) > 0);
1467
1468   nghttp2_frame_headers_free(&frame.headers, mem);
1469
1470   buf = &bufs.head->buf;
1471   assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
1472
1473   ud.frame_recv_cb_called = 0;
1474
1475   rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
1476
1477   CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv);
1478   CU_ASSERT(1 == ud.frame_recv_cb_called);
1479
1480   stream = nghttp2_session_get_stream(session, 3);
1481
1482   CU_ASSERT(99 == stream->weight);
1483   CU_ASSERT(1 == stream->dep_prev->stream_id);
1484
1485   nghttp2_bufs_reset(&bufs);
1486
1487   /* With NGHTTP2_FLAG_PRIORITY, but cut last 1 byte to make it
1488      invalid. */
1489   nvlen = ARRLEN(reqnv);
1490   nghttp2_nv_array_copy(&nva, reqnv, nvlen, mem);
1491
1492   nghttp2_priority_spec_init(&pri_spec, 0, 99, 0);
1493
1494   nghttp2_frame_headers_init(&frame.headers,
1495                              NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PRIORITY,
1496                              5, NGHTTP2_HCAT_HEADERS, &pri_spec, nva, nvlen);
1497
1498   rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
1499
1500   CU_ASSERT(0 == rv);
1501   CU_ASSERT(nghttp2_bufs_len(&bufs) > NGHTTP2_FRAME_HDLEN + 5);
1502
1503   nghttp2_frame_headers_free(&frame.headers, mem);
1504
1505   buf = &bufs.head->buf;
1506   /* Make payload shorter than required length to store priority
1507      group */
1508   nghttp2_put_uint32be(buf->pos, (uint32_t)((4 << 8) + buf->pos[3]));
1509
1510   ud.frame_recv_cb_called = 0;
1511
1512   rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
1513
1514   CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv);
1515   CU_ASSERT(0 == ud.frame_recv_cb_called);
1516
1517   stream = nghttp2_session_get_stream(session, 5);
1518
1519   CU_ASSERT(NULL == stream);
1520
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);
1525
1526   nghttp2_bufs_reset(&bufs);
1527
1528   nghttp2_hd_deflate_free(&deflater);
1529   nghttp2_session_del(session);
1530
1531   /* Check dep_stream_id == stream_id */
1532   nghttp2_session_server_new(&session, &callbacks, &ud);
1533
1534   nghttp2_hd_deflate_init(&deflater, mem);
1535
1536   nvlen = ARRLEN(reqnv);
1537   nghttp2_nv_array_copy(&nva, reqnv, nvlen, mem);
1538
1539   nghttp2_priority_spec_init(&pri_spec, 1, 0, 0);
1540
1541   nghttp2_frame_headers_init(&frame.headers,
1542                              NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PRIORITY,
1543                              1, NGHTTP2_HCAT_HEADERS, &pri_spec, nva, nvlen);
1544
1545   rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
1546
1547   CU_ASSERT(0 == rv);
1548   CU_ASSERT(nghttp2_bufs_len(&bufs) > 0);
1549
1550   nghttp2_frame_headers_free(&frame.headers, mem);
1551
1552   buf = &bufs.head->buf;
1553   assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
1554
1555   ud.frame_recv_cb_called = 0;
1556
1557   rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
1558
1559   CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv);
1560   CU_ASSERT(0 == ud.frame_recv_cb_called);
1561
1562   stream = nghttp2_session_get_stream(session, 1);
1563
1564   CU_ASSERT(NULL == stream);
1565
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);
1570
1571   nghttp2_bufs_reset(&bufs);
1572
1573   nghttp2_bufs_free(&bufs);
1574   nghttp2_hd_deflate_free(&deflater);
1575   nghttp2_session_del(session);
1576 }
1577
1578 void test_nghttp2_session_recv_headers_with_padding(void) {
1579   nghttp2_session *session;
1580   nghttp2_session_callbacks callbacks;
1581   nghttp2_bufs bufs;
1582   nghttp2_buf *buf;
1583   nghttp2_frame_hd hd;
1584   nghttp2_outbound_item *item;
1585   my_user_data ud;
1586   ssize_t rv;
1587
1588   frame_pack_bufs_init(&bufs);
1589
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;
1593
1594   /* HEADERS: Wrong padding length */
1595   nghttp2_session_server_new(&session, &callbacks, &ud);
1596   nghttp2_session_send(session);
1597
1598   nghttp2_frame_hd_init(&hd, 10, NGHTTP2_HEADERS,
1599                         NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PRIORITY |
1600                             NGHTTP2_FLAG_PADDED,
1601                         1);
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 */
1606   *buf->last++ = 5;
1607   /* priority field */
1608   nghttp2_put_uint32be(buf->last, 3);
1609   buf->last += sizeof(uint32_t);
1610   *buf->last++ = 1;
1611   /* rest is garbage */
1612   memset(buf->last, 0, 4);
1613   buf->last += 4;
1614
1615   ud.frame_recv_cb_called = 0;
1616
1617   rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
1618
1619   CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv);
1620   CU_ASSERT(0 == ud.frame_recv_cb_called);
1621
1622   item = nghttp2_session_get_next_ob_item(session);
1623
1624   CU_ASSERT(NULL != item);
1625   CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
1626
1627   nghttp2_bufs_reset(&bufs);
1628   nghttp2_session_del(session);
1629
1630   /* PUSH_PROMISE: Wrong padding length */
1631   nghttp2_session_client_new(&session, &callbacks, &ud);
1632   nghttp2_session_send(session);
1633
1634   open_sent_stream(session, 1);
1635
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 */
1642   *buf->last++ = 5;
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);
1648   buf->last += 4;
1649
1650   ud.frame_recv_cb_called = 0;
1651
1652   rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
1653
1654   CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv);
1655   CU_ASSERT(0 == ud.frame_recv_cb_called);
1656
1657   item = nghttp2_session_get_next_ob_item(session);
1658
1659   CU_ASSERT(NULL != item);
1660   CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
1661
1662   nghttp2_bufs_free(&bufs);
1663   nghttp2_session_del(session);
1664 }
1665
1666 static int response_on_begin_frame_callback(nghttp2_session *session,
1667                                             const nghttp2_frame_hd *hd,
1668                                             void *user_data) {
1669   int rv;
1670   (void)user_data;
1671
1672   if (hd->type != NGHTTP2_HEADERS) {
1673     return 0;
1674   }
1675
1676   rv = nghttp2_submit_response(session, hd->stream_id, resnv, ARRLEN(resnv),
1677                                NULL);
1678
1679   CU_ASSERT(0 == rv);
1680
1681   return 0;
1682 }
1683
1684 void test_nghttp2_session_recv_headers_early_response(void) {
1685   nghttp2_session *session;
1686   nghttp2_session_callbacks callbacks;
1687   nghttp2_bufs bufs;
1688   nghttp2_buf *buf;
1689   nghttp2_hd_deflater deflater;
1690   nghttp2_mem *mem;
1691   nghttp2_nv *nva;
1692   size_t nvlen;
1693   nghttp2_frame frame;
1694   ssize_t rv;
1695   nghttp2_stream *stream;
1696
1697   mem = nghttp2_mem_default();
1698   frame_pack_bufs_init(&bufs);
1699
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;
1703
1704   nghttp2_session_server_new(&session, &callbacks, NULL);
1705
1706   nghttp2_hd_deflate_init(&deflater, mem);
1707
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);
1713
1714   rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
1715
1716   CU_ASSERT(0 == rv);
1717
1718   nghttp2_frame_headers_free(&frame.headers, mem);
1719
1720   buf = &bufs.head->buf;
1721
1722   /* Only receive 9 bytes headers, and invoke
1723      on_begin_frame_callback */
1724   rv = nghttp2_session_mem_recv(session, buf->pos, 9);
1725
1726   CU_ASSERT(9 == rv);
1727
1728   rv = nghttp2_session_send(session);
1729
1730   CU_ASSERT(0 == rv);
1731
1732   rv =
1733       nghttp2_session_mem_recv(session, buf->pos + 9, nghttp2_buf_len(buf) - 9);
1734
1735   CU_ASSERT((ssize_t)nghttp2_buf_len(buf) - 9 == rv);
1736
1737   stream = nghttp2_session_get_stream_raw(session, 1);
1738
1739   CU_ASSERT(stream->flags & NGHTTP2_STREAM_FLAG_CLOSED);
1740
1741   nghttp2_hd_deflate_free(&deflater);
1742   nghttp2_session_del(session);
1743   nghttp2_bufs_free(&bufs);
1744 }
1745
1746 void test_nghttp2_session_recv_headers_for_closed_stream(void) {
1747   nghttp2_session *session;
1748   nghttp2_session_callbacks callbacks;
1749   nghttp2_nv *nva;
1750   size_t nvlen;
1751   nghttp2_frame frame;
1752   nghttp2_bufs bufs;
1753   nghttp2_buf *buf;
1754   ssize_t rv;
1755   my_user_data ud;
1756   nghttp2_hd_deflater deflater;
1757   nghttp2_stream *stream;
1758   nghttp2_mem *mem;
1759   const uint8_t *data;
1760
1761   mem = nghttp2_mem_default();
1762   frame_pack_bufs_init(&bufs);
1763
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;
1767
1768   nghttp2_session_server_new(&session, &callbacks, &ud);
1769
1770   nghttp2_hd_deflate_init(&deflater, mem);
1771
1772   /* Make sure that on_header callback never be invoked for closed
1773      stream */
1774   nvlen = ARRLEN(reqnv);
1775   nghttp2_nv_array_copy(&nva, reqnv, nvlen, mem);
1776
1777   nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 1,
1778                              NGHTTP2_HCAT_HEADERS, NULL, nva, nvlen);
1779
1780   rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
1781
1782   CU_ASSERT(0 == rv);
1783   CU_ASSERT(nghttp2_bufs_len(&bufs) > 0);
1784
1785   nghttp2_frame_headers_free(&frame.headers, mem);
1786
1787   buf = &bufs.head->buf;
1788   assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
1789
1790   ud.header_cb_called = 0;
1791   ud.frame_recv_cb_called = 0;
1792
1793   rv = nghttp2_session_mem_recv(session, buf->pos, NGHTTP2_FRAME_HDLEN);
1794
1795   CU_ASSERT(NGHTTP2_FRAME_HDLEN == rv);
1796   CU_ASSERT(0 == ud.header_cb_called);
1797   CU_ASSERT(0 == ud.frame_recv_cb_called);
1798
1799   stream = nghttp2_session_get_stream(session, 1);
1800
1801   CU_ASSERT(NULL != stream);
1802
1803   rv = nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, 1,
1804                                  NGHTTP2_NO_ERROR);
1805
1806   CU_ASSERT(0 == rv);
1807
1808   rv = nghttp2_session_mem_send(session, &data);
1809
1810   CU_ASSERT(rv > 0);
1811
1812   stream = nghttp2_session_get_stream(session, 1);
1813
1814   CU_ASSERT(NULL == stream);
1815
1816   ud.header_cb_called = 0;
1817   ud.frame_recv_cb_called = 0;
1818
1819   rv = nghttp2_session_mem_recv(session, buf->pos + NGHTTP2_FRAME_HDLEN,
1820                                 nghttp2_buf_len(buf) - NGHTTP2_FRAME_HDLEN);
1821
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);
1825
1826   nghttp2_bufs_free(&bufs);
1827   nghttp2_hd_deflate_free(&deflater);
1828   nghttp2_session_del(session);
1829 }
1830
1831 void test_nghttp2_session_server_recv_push_response(void) {
1832   nghttp2_session *session;
1833   nghttp2_session_callbacks callbacks;
1834   nghttp2_bufs bufs;
1835   nghttp2_buf *buf;
1836   ssize_t rv;
1837   my_user_data ud;
1838   nghttp2_mem *mem;
1839   nghttp2_frame frame;
1840   nghttp2_hd_deflater deflater;
1841   nghttp2_nv *nva;
1842   size_t nvlen;
1843
1844   mem = nghttp2_mem_default();
1845   frame_pack_bufs_init(&bufs);
1846
1847   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
1848   callbacks.on_invalid_frame_recv_callback = on_invalid_frame_recv_callback;
1849
1850   nghttp2_session_server_new(&session, &callbacks, &ud);
1851
1852   nghttp2_hd_deflate_init(&deflater, mem);
1853
1854   open_sent_stream2(session, 2, NGHTTP2_STREAM_RESERVED);
1855
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,
1860                              nvlen);
1861   rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
1862
1863   CU_ASSERT(0 == rv);
1864   CU_ASSERT(nghttp2_bufs_len(&bufs) > 0);
1865
1866   nghttp2_frame_headers_free(&frame.headers, mem);
1867
1868   buf = &bufs.head->buf;
1869
1870   ud.invalid_frame_recv_cb_called = 0;
1871
1872   rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
1873
1874   CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv);
1875   CU_ASSERT(1 == ud.invalid_frame_recv_cb_called);
1876
1877   nghttp2_bufs_free(&bufs);
1878   nghttp2_hd_deflate_free(&deflater);
1879   nghttp2_session_del(session);
1880 }
1881
1882 void test_nghttp2_session_recv_premature_headers(void) {
1883   nghttp2_session *session;
1884   nghttp2_session_callbacks callbacks;
1885   nghttp2_bufs bufs;
1886   nghttp2_buf *buf;
1887   ssize_t rv;
1888   my_user_data ud;
1889   nghttp2_hd_deflater deflater;
1890   nghttp2_outbound_item *item;
1891   nghttp2_mem *mem;
1892   uint32_t payloadlen;
1893
1894   mem = nghttp2_mem_default();
1895   frame_pack_bufs_init(&bufs);
1896
1897   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
1898   callbacks.send_callback = null_send_callback;
1899
1900   nghttp2_session_server_new(&session, &callbacks, &ud);
1901
1902   nghttp2_hd_deflate_init(&deflater, mem);
1903
1904   pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, reqnv,
1905                ARRLEN(reqnv), mem);
1906
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);
1912
1913   CU_ASSERT((ssize_t)(nghttp2_buf_len(buf) - 1) == rv);
1914
1915   item = nghttp2_session_get_next_ob_item(session);
1916
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));
1922
1923   nghttp2_bufs_reset(&bufs);
1924   nghttp2_hd_deflate_free(&deflater);
1925   nghttp2_session_del(session);
1926
1927   /* Test for PUSH_PROMISE */
1928   nghttp2_session_client_new(&session, &callbacks, &ud);
1929   nghttp2_hd_deflate_init(&deflater, mem);
1930
1931   open_sent_stream3(session, 1, NGHTTP2_STREAM_FLAG_NONE, &pri_spec_default,
1932                     NGHTTP2_STREAM_OPENING, NULL);
1933
1934   rv = pack_push_promise(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, 2,
1935                          reqnv, ARRLEN(reqnv), mem);
1936
1937   CU_ASSERT(0 == rv);
1938
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);
1944
1945   CU_ASSERT((ssize_t)(nghttp2_buf_len(buf) - 1) == rv);
1946
1947   item = nghttp2_session_get_next_ob_item(session);
1948
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));
1954
1955   nghttp2_hd_deflate_free(&deflater);
1956   nghttp2_session_del(session);
1957   nghttp2_bufs_free(&bufs);
1958 }
1959
1960 void test_nghttp2_session_recv_unknown_frame(void) {
1961   nghttp2_session *session;
1962   nghttp2_session_callbacks callbacks;
1963   my_user_data ud;
1964   uint8_t data[16384];
1965   size_t datalen;
1966   nghttp2_frame_hd hd;
1967   ssize_t rv;
1968
1969   nghttp2_frame_hd_init(&hd, 16000, 99, NGHTTP2_FLAG_NONE, 0);
1970
1971   nghttp2_frame_pack_frame_hd(data, &hd);
1972   datalen = NGHTTP2_FRAME_HDLEN + hd.length;
1973
1974   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
1975   callbacks.on_frame_recv_callback = on_frame_recv_callback;
1976
1977   nghttp2_session_server_new(&session, &callbacks, &ud);
1978
1979   ud.frame_recv_cb_called = 0;
1980
1981   /* Unknown frame must be ignored */
1982   rv = nghttp2_session_mem_recv(session, data, datalen);
1983
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));
1987
1988   nghttp2_session_del(session);
1989 }
1990
1991 void test_nghttp2_session_recv_unexpected_continuation(void) {
1992   nghttp2_session *session;
1993   nghttp2_session_callbacks callbacks;
1994   my_user_data ud;
1995   uint8_t data[16384];
1996   size_t datalen;
1997   nghttp2_frame_hd hd;
1998   ssize_t rv;
1999   nghttp2_outbound_item *item;
2000
2001   nghttp2_frame_hd_init(&hd, 16000, NGHTTP2_CONTINUATION,
2002                         NGHTTP2_FLAG_END_HEADERS, 1);
2003
2004   nghttp2_frame_pack_frame_hd(data, &hd);
2005   datalen = NGHTTP2_FRAME_HDLEN + hd.length;
2006
2007   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
2008   callbacks.on_frame_recv_callback = on_frame_recv_callback;
2009
2010   nghttp2_session_server_new(&session, &callbacks, &ud);
2011
2012   open_recv_stream(session, 1);
2013
2014   ud.frame_recv_cb_called = 0;
2015
2016   /* unexpected CONTINUATION must be treated as connection error */
2017   rv = nghttp2_session_mem_recv(session, data, datalen);
2018
2019   CU_ASSERT(rv == (ssize_t)datalen);
2020   CU_ASSERT(0 == ud.frame_recv_cb_called);
2021
2022   item = nghttp2_session_get_next_ob_item(session);
2023
2024   CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
2025
2026   nghttp2_session_del(session);
2027 }
2028
2029 void test_nghttp2_session_recv_settings_header_table_size(void) {
2030   nghttp2_session *session;
2031   nghttp2_session_callbacks callbacks;
2032   nghttp2_frame frame;
2033   nghttp2_bufs bufs;
2034   nghttp2_buf *buf;
2035   ssize_t rv;
2036   my_user_data ud;
2037   nghttp2_settings_entry iv[3];
2038   nghttp2_nv nv = MAKE_NV(":authority", "example.org");
2039   nghttp2_mem *mem;
2040
2041   mem = nghttp2_mem_default();
2042   frame_pack_bufs_init(&bufs);
2043
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;
2047
2048   nghttp2_session_client_new(&session, &callbacks, &ud);
2049
2050   iv[0].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
2051   iv[0].value = 3000;
2052
2053   iv[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
2054   iv[1].value = 16384;
2055
2056   nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE, dup_iv(iv, 2),
2057                               2);
2058
2059   rv = nghttp2_frame_pack_settings(&bufs, &frame.settings);
2060
2061   CU_ASSERT(0 == rv);
2062   CU_ASSERT(nghttp2_bufs_len(&bufs) > 0);
2063
2064   nghttp2_frame_settings_free(&frame.settings, mem);
2065
2066   buf = &bufs.head->buf;
2067   assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
2068
2069   ud.frame_recv_cb_called = 0;
2070
2071   rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
2072
2073   CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv);
2074   CU_ASSERT(1 == ud.frame_recv_cb_called);
2075
2076   CU_ASSERT(3000 == session->remote_settings.header_table_size);
2077   CU_ASSERT(16384 == session->remote_settings.initial_window_size);
2078
2079   nghttp2_bufs_reset(&bufs);
2080
2081   /* 2 SETTINGS_HEADER_TABLE_SIZE */
2082   iv[0].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
2083   iv[0].value = 3001;
2084
2085   iv[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
2086   iv[1].value = 16383;
2087
2088   iv[2].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
2089   iv[2].value = 3001;
2090
2091   nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE, dup_iv(iv, 3),
2092                               3);
2093
2094   rv = nghttp2_frame_pack_settings(&bufs, &frame.settings);
2095
2096   CU_ASSERT(0 == rv);
2097   CU_ASSERT(nghttp2_bufs_len(&bufs) > 0);
2098
2099   nghttp2_frame_settings_free(&frame.settings, mem);
2100
2101   buf = &bufs.head->buf;
2102   assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
2103
2104   ud.frame_recv_cb_called = 0;
2105
2106   rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
2107
2108   CU_ASSERT((ssize_t)(nghttp2_buf_len(buf)) == rv);
2109   CU_ASSERT(1 == ud.frame_recv_cb_called);
2110
2111   CU_ASSERT(3001 == session->remote_settings.header_table_size);
2112   CU_ASSERT(16383 == session->remote_settings.initial_window_size);
2113
2114   nghttp2_bufs_reset(&bufs);
2115
2116   /* 2 SETTINGS_HEADER_TABLE_SIZE; first entry clears dynamic header
2117      table. */
2118
2119   nghttp2_submit_request(session, NULL, &nv, 1, NULL, NULL);
2120   nghttp2_session_send(session);
2121
2122   CU_ASSERT(0 < session->hd_deflater.ctx.hd_table.len);
2123
2124   iv[0].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
2125   iv[0].value = 0;
2126
2127   iv[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
2128   iv[1].value = 16382;
2129
2130   iv[2].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
2131   iv[2].value = 4096;
2132
2133   nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE, dup_iv(iv, 3),
2134                               3);
2135
2136   rv = nghttp2_frame_pack_settings(&bufs, &frame.settings);
2137
2138   CU_ASSERT(0 == rv);
2139   CU_ASSERT(nghttp2_bufs_len(&bufs) > 0);
2140
2141   nghttp2_frame_settings_free(&frame.settings, mem);
2142
2143   buf = &bufs.head->buf;
2144   assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
2145
2146   ud.frame_recv_cb_called = 0;
2147
2148   rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
2149
2150   CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv);
2151   CU_ASSERT(1 == ud.frame_recv_cb_called);
2152
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);
2156
2157   nghttp2_bufs_reset(&bufs);
2158
2159   /* 2 SETTINGS_HEADER_TABLE_SIZE; second entry clears dynamic header
2160      table. */
2161
2162   nghttp2_submit_request(session, NULL, &nv, 1, NULL, NULL);
2163   nghttp2_session_send(session);
2164
2165   CU_ASSERT(0 < session->hd_deflater.ctx.hd_table.len);
2166
2167   iv[0].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
2168   iv[0].value = 3000;
2169
2170   iv[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
2171   iv[1].value = 16381;
2172
2173   iv[2].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
2174   iv[2].value = 0;
2175
2176   nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE, dup_iv(iv, 3),
2177                               3);
2178
2179   rv = nghttp2_frame_pack_settings(&bufs, &frame.settings);
2180
2181   CU_ASSERT(0 == rv);
2182   CU_ASSERT(nghttp2_bufs_len(&bufs) > 0);
2183
2184   nghttp2_frame_settings_free(&frame.settings, mem);
2185
2186   buf = &bufs.head->buf;
2187   assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
2188
2189   ud.frame_recv_cb_called = 0;
2190
2191   rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
2192
2193   CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv);
2194   CU_ASSERT(1 == ud.frame_recv_cb_called);
2195
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);
2199
2200   nghttp2_bufs_reset(&bufs);
2201
2202   nghttp2_bufs_free(&bufs);
2203   nghttp2_session_del(session);
2204 }
2205
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;
2212
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);
2216
2217   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
2218
2219   nghttp2_session_server_new(&session, &callbacks, NULL);
2220
2221   nghttp2_frame_pack_frame_hd(buf, &hd);
2222
2223   CU_ASSERT(sizeof(buf) == nghttp2_session_mem_recv(session, buf, sizeof(buf)));
2224
2225   item = nghttp2_session_get_next_ob_item(session);
2226
2227   CU_ASSERT(item != NULL);
2228   CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
2229
2230   nghttp2_session_del(session);
2231 }
2232
2233 void test_nghttp2_session_recv_extension(void) {
2234   nghttp2_session *session;
2235   nghttp2_session_callbacks callbacks;
2236   my_user_data ud;
2237   nghttp2_buf buf;
2238   nghttp2_frame_hd hd;
2239   nghttp2_mem *mem;
2240   const char data[] = "Hello World!";
2241   ssize_t rv;
2242   nghttp2_option *option;
2243
2244   mem = nghttp2_mem_default();
2245
2246   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
2247
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;
2251
2252   nghttp2_option_new(&option);
2253   nghttp2_option_set_user_recv_extension_type(option, 111);
2254
2255   nghttp2_buf_init2(&ud.scratchbuf, 4096, mem);
2256   nghttp2_buf_init2(&buf, 4096, mem);
2257
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));
2262
2263   nghttp2_session_client_new2(&session, &callbacks, &ud, option);
2264
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));
2267
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)));
2273
2274   nghttp2_session_del(session);
2275
2276   /* cancel in on_extension_chunk_recv_callback */
2277   nghttp2_buf_reset(&ud.scratchbuf);
2278
2279   callbacks.on_extension_chunk_recv_callback =
2280       cancel_on_extension_chunk_recv_callback;
2281
2282   nghttp2_session_server_new2(&session, &callbacks, &ud, option);
2283
2284   ud.frame_recv_cb_called = 0;
2285   rv = nghttp2_session_mem_recv(session, buf.pos, nghttp2_buf_len(&buf));
2286
2287   CU_ASSERT(NGHTTP2_FRAME_HDLEN + hd.length == (size_t)rv);
2288   CU_ASSERT(0 == ud.frame_recv_cb_called);
2289
2290   nghttp2_session_del(session);
2291
2292   /* cancel in unpack_extension_callback */
2293   nghttp2_buf_reset(&ud.scratchbuf);
2294
2295   callbacks.on_extension_chunk_recv_callback = on_extension_chunk_recv_callback;
2296   callbacks.unpack_extension_callback = cancel_unpack_extension_callback;
2297
2298   nghttp2_session_server_new2(&session, &callbacks, &ud, option);
2299
2300   ud.frame_recv_cb_called = 0;
2301   rv = nghttp2_session_mem_recv(session, buf.pos, nghttp2_buf_len(&buf));
2302
2303   CU_ASSERT(NGHTTP2_FRAME_HDLEN + hd.length == (size_t)rv);
2304   CU_ASSERT(0 == ud.frame_recv_cb_called);
2305
2306   nghttp2_session_del(session);
2307
2308   nghttp2_buf_free(&buf, mem);
2309   nghttp2_buf_free(&ud.scratchbuf, mem);
2310
2311   nghttp2_option_del(option);
2312 }
2313
2314 void test_nghttp2_session_recv_altsvc(void) {
2315   nghttp2_session *session;
2316   nghttp2_session_callbacks callbacks;
2317   my_user_data ud;
2318   nghttp2_buf buf;
2319   nghttp2_frame_hd hd;
2320   nghttp2_mem *mem;
2321   ssize_t rv;
2322   nghttp2_option *option;
2323   static const uint8_t origin[] = "nghttp2.org";
2324   static const uint8_t field_value[] = "h2=\":443\"";
2325
2326   mem = nghttp2_mem_default();
2327
2328   nghttp2_buf_init2(&buf, NGHTTP2_FRAME_HDLEN + NGHTTP2_MAX_FRAME_SIZE_MIN,
2329                     mem);
2330
2331   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
2332
2333   callbacks.on_frame_recv_callback = on_frame_recv_callback;
2334   callbacks.on_invalid_frame_recv_callback = on_invalid_frame_recv_callback;
2335
2336   nghttp2_option_new(&option);
2337   nghttp2_option_set_builtin_recv_extension_type(option, NGHTTP2_ALTSVC);
2338
2339   nghttp2_session_client_new2(&session, &callbacks, &ud, option);
2340
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);
2346   buf.last += 2;
2347   buf.last = nghttp2_cpymem(buf.last, origin, sizeof(origin) - 1);
2348   buf.last = nghttp2_cpymem(buf.last, field_value, sizeof(field_value) - 1);
2349
2350   ud.frame_recv_cb_called = 0;
2351   rv = nghttp2_session_mem_recv(session, buf.pos, nghttp2_buf_len(&buf));
2352
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);
2358
2359   nghttp2_session_del(session);
2360
2361   /* size of origin is larger than frame length */
2362   nghttp2_buf_reset(&buf);
2363
2364   nghttp2_session_client_new2(&session, &callbacks, &ud, option);
2365
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);
2371   buf.last += 2;
2372   buf.last = nghttp2_cpymem(buf.last, origin, sizeof(origin) - 1 - 1);
2373
2374   ud.frame_recv_cb_called = 0;
2375   rv = nghttp2_session_mem_recv(session, buf.pos, nghttp2_buf_len(&buf));
2376
2377   CU_ASSERT((ssize_t)nghttp2_buf_len(&buf) == rv);
2378   CU_ASSERT(0 == ud.frame_recv_cb_called);
2379
2380   nghttp2_session_del(session);
2381
2382   /* zero-length value */
2383   nghttp2_buf_reset(&buf);
2384
2385   nghttp2_session_client_new2(&session, &callbacks, &ud, option);
2386
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);
2392   buf.last += 2;
2393   buf.last = nghttp2_cpymem(buf.last, origin, sizeof(origin) - 1);
2394
2395   ud.invalid_frame_recv_cb_called = 0;
2396   rv = nghttp2_session_mem_recv(session, buf.pos, nghttp2_buf_len(&buf));
2397
2398   CU_ASSERT((ssize_t)nghttp2_buf_len(&buf) == rv);
2399   CU_ASSERT(1 == ud.invalid_frame_recv_cb_called);
2400
2401   nghttp2_session_del(session);
2402
2403   /* non-empty origin to a stream other than 0 */
2404   nghttp2_buf_reset(&buf);
2405
2406   nghttp2_session_client_new2(&session, &callbacks, &ud, option);
2407
2408   open_sent_stream(session, 1);
2409
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);
2415   buf.last += 2;
2416   buf.last = nghttp2_cpymem(buf.last, origin, sizeof(origin) - 1);
2417   buf.last = nghttp2_cpymem(buf.last, field_value, sizeof(field_value) - 1);
2418
2419   ud.invalid_frame_recv_cb_called = 0;
2420   rv = nghttp2_session_mem_recv(session, buf.pos, nghttp2_buf_len(&buf));
2421
2422   CU_ASSERT((ssize_t)nghttp2_buf_len(&buf) == rv);
2423   CU_ASSERT(1 == ud.invalid_frame_recv_cb_called);
2424
2425   nghttp2_session_del(session);
2426
2427   /* empty origin to stream 0 */
2428   nghttp2_buf_reset(&buf);
2429
2430   nghttp2_session_client_new2(&session, &callbacks, &ud, option);
2431
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);
2437   buf.last += 2;
2438   buf.last = nghttp2_cpymem(buf.last, field_value, sizeof(field_value) - 1);
2439
2440   ud.invalid_frame_recv_cb_called = 0;
2441   rv = nghttp2_session_mem_recv(session, buf.pos, nghttp2_buf_len(&buf));
2442
2443   CU_ASSERT((ssize_t)nghttp2_buf_len(&buf) == rv);
2444   CU_ASSERT(1 == ud.invalid_frame_recv_cb_called);
2445
2446   nghttp2_session_del(session);
2447
2448   /* send large frame (16KiB) */
2449   nghttp2_buf_reset(&buf);
2450
2451   nghttp2_session_client_new2(&session, &callbacks, &ud, option);
2452
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);
2458   buf.last += 2;
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);
2462
2463   ud.frame_recv_cb_called = 0;
2464   rv = nghttp2_session_mem_recv(session, buf.pos, nghttp2_buf_len(&buf));
2465
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);
2470
2471   nghttp2_session_del(session);
2472
2473   /* send too large frame */
2474   nghttp2_buf_reset(&buf);
2475
2476   nghttp2_session_client_new2(&session, &callbacks, &ud, option);
2477
2478   session->local_settings.max_frame_size = NGHTTP2_MAX_FRAME_SIZE_MIN - 1;
2479
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);
2485   buf.last += 2;
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);
2489
2490   ud.frame_recv_cb_called = 0;
2491   rv = nghttp2_session_mem_recv(session, buf.pos, nghttp2_buf_len(&buf));
2492
2493   CU_ASSERT((ssize_t)nghttp2_buf_len(&buf) == rv);
2494   CU_ASSERT(0 == ud.frame_recv_cb_called);
2495
2496   nghttp2_session_del(session);
2497
2498   /* received by server */
2499   nghttp2_buf_reset(&buf);
2500
2501   nghttp2_session_server_new2(&session, &callbacks, &ud, option);
2502
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);
2508   buf.last += 2;
2509   buf.last = nghttp2_cpymem(buf.last, origin, sizeof(origin) - 1);
2510   buf.last = nghttp2_cpymem(buf.last, field_value, sizeof(field_value) - 1);
2511
2512   ud.frame_recv_cb_called = 0;
2513   rv = nghttp2_session_mem_recv(session, buf.pos, nghttp2_buf_len(&buf));
2514
2515   CU_ASSERT((ssize_t)nghttp2_buf_len(&buf) == rv);
2516   CU_ASSERT(0 == ud.frame_recv_cb_called);
2517
2518   nghttp2_session_del(session);
2519
2520   nghttp2_buf_free(&buf, mem);
2521   nghttp2_option_del(option);
2522 }
2523
2524 void test_nghttp2_session_recv_origin(void) {
2525   nghttp2_session *session;
2526   nghttp2_session_callbacks callbacks;
2527   my_user_data ud;
2528   nghttp2_bufs bufs;
2529   ssize_t rv;
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";
2535
2536   frame_pack_bufs_init(&bufs);
2537
2538   frame.payload = &origin;
2539
2540   ov.origin = (uint8_t *)nghttp2;
2541   ov.origin_len = sizeof(nghttp2) - 1;
2542
2543   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
2544
2545   callbacks.on_frame_recv_callback = on_frame_recv_callback;
2546
2547   nghttp2_option_new(&option);
2548   nghttp2_option_set_builtin_recv_extension_type(option, NGHTTP2_ORIGIN);
2549
2550   nghttp2_session_client_new2(&session, &callbacks, &ud, option);
2551
2552   nghttp2_frame_origin_init(&frame, &ov, 1);
2553
2554   rv = nghttp2_frame_pack_origin(&bufs, &frame);
2555
2556   CU_ASSERT(0 == rv);
2557
2558   ud.frame_recv_cb_called = 0;
2559   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
2560                                 nghttp2_bufs_len(&bufs));
2561
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);
2567
2568   nghttp2_session_del(session);
2569   nghttp2_bufs_reset(&bufs);
2570
2571   /* The length of origin is larger than payload length. */
2572   nghttp2_session_client_new2(&session, &callbacks, &ud, option);
2573
2574   nghttp2_frame_origin_init(&frame, &ov, 1);
2575   rv = nghttp2_frame_pack_origin(&bufs, &frame);
2576
2577   CU_ASSERT(0 == rv);
2578
2579   nghttp2_put_uint16be(bufs.head->buf.pos + NGHTTP2_FRAME_HDLEN,
2580                        (uint16_t)sizeof(nghttp2));
2581
2582   ud.frame_recv_cb_called = 0;
2583   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
2584                                 nghttp2_bufs_len(&bufs));
2585
2586   CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == rv);
2587   CU_ASSERT(0 == ud.frame_recv_cb_called);
2588
2589   nghttp2_session_del(session);
2590   nghttp2_bufs_reset(&bufs);
2591
2592   /* A frame should be ignored if it is sent to a stream other than
2593      stream 0. */
2594   nghttp2_session_client_new2(&session, &callbacks, &ud, option);
2595
2596   nghttp2_frame_origin_init(&frame, &ov, 1);
2597   frame.hd.stream_id = 1;
2598   rv = nghttp2_frame_pack_origin(&bufs, &frame);
2599
2600   CU_ASSERT(0 == rv);
2601
2602   ud.frame_recv_cb_called = 0;
2603   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
2604                                 nghttp2_bufs_len(&bufs));
2605
2606   CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == rv);
2607   CU_ASSERT(0 == ud.frame_recv_cb_called);
2608
2609   nghttp2_session_del(session);
2610   nghttp2_bufs_reset(&bufs);
2611
2612   /* A frame should be ignored if the reserved flag is set */
2613   nghttp2_session_client_new2(&session, &callbacks, &ud, option);
2614
2615   nghttp2_frame_origin_init(&frame, &ov, 1);
2616   frame.hd.flags = 0xf0;
2617   rv = nghttp2_frame_pack_origin(&bufs, &frame);
2618
2619   CU_ASSERT(0 == rv);
2620
2621   ud.frame_recv_cb_called = 0;
2622   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
2623                                 nghttp2_bufs_len(&bufs));
2624
2625   CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == rv);
2626   CU_ASSERT(0 == ud.frame_recv_cb_called);
2627
2628   nghttp2_session_del(session);
2629   nghttp2_bufs_reset(&bufs);
2630
2631   /* A frame should be ignored if it is received by a server. */
2632   nghttp2_session_server_new2(&session, &callbacks, &ud, option);
2633
2634   nghttp2_frame_origin_init(&frame, &ov, 1);
2635   rv = nghttp2_frame_pack_origin(&bufs, &frame);
2636
2637   CU_ASSERT(0 == rv);
2638
2639   ud.frame_recv_cb_called = 0;
2640   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
2641                                 nghttp2_bufs_len(&bufs));
2642
2643   CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == rv);
2644   CU_ASSERT(0 == ud.frame_recv_cb_called);
2645
2646   nghttp2_session_del(session);
2647   nghttp2_bufs_reset(&bufs);
2648
2649   /* Receiving empty ORIGIN frame */
2650   nghttp2_session_client_new2(&session, &callbacks, &ud, option);
2651
2652   nghttp2_frame_origin_init(&frame, NULL, 0);
2653   rv = nghttp2_frame_pack_origin(&bufs, &frame);
2654
2655   CU_ASSERT(0 == rv);
2656
2657   ud.frame_recv_cb_called = 0;
2658   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
2659                                 nghttp2_bufs_len(&bufs));
2660
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);
2664
2665   nghttp2_session_del(session);
2666
2667   nghttp2_option_del(option);
2668   nghttp2_bufs_free(&bufs);
2669 }
2670
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")};
2678   nghttp2_bufs bufs;
2679   nghttp2_buf *buf;
2680   size_t framelen1, framelen2;
2681   ssize_t rv;
2682   uint8_t buffer[4096];
2683   nghttp2_buf databuf;
2684   nghttp2_frame frame;
2685   nghttp2_nv *nva;
2686   size_t nvlen;
2687   const nghttp2_frame *recv_frame;
2688   nghttp2_frame_hd data_hd;
2689   nghttp2_hd_deflater deflater;
2690   nghttp2_mem *mem;
2691
2692   mem = nghttp2_mem_default();
2693   frame_pack_bufs_init(&bufs);
2694   nghttp2_buf_wrap_init(&databuf, buffer, sizeof(buffer));
2695
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;
2702
2703   nghttp2_session_server_new(&session, &callbacks, &user_data);
2704   /* disable strict HTTP layering checks */
2705   session->opt_flags |= NGHTTP2_OPTMASK_NO_HTTP_MESSAGING;
2706
2707   nghttp2_hd_deflate_init(&deflater, mem);
2708
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);
2715
2716   CU_ASSERT(0 == rv);
2717   CU_ASSERT(nghttp2_bufs_len(&bufs) > 0);
2718
2719   nghttp2_frame_headers_free(&frame.headers, mem);
2720
2721   buf = &bufs.head->buf;
2722   assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
2723
2724   framelen1 = nghttp2_buf_len(buf);
2725   databuf.last = nghttp2_cpymem(databuf.last, buf->pos, nghttp2_buf_len(buf));
2726
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);
2733
2734   CU_ASSERT(0 == rv);
2735   CU_ASSERT(nghttp2_bufs_len(&bufs) > 0);
2736
2737   nghttp2_frame_headers_free(&frame.headers, mem);
2738
2739   assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
2740
2741   framelen2 = nghttp2_buf_len(buf);
2742   databuf.last = nghttp2_cpymem(databuf.last, buf->pos, nghttp2_buf_len(buf));
2743
2744   /* Receive 1st HEADERS and pause */
2745   user_data.begin_headers_cb_called = 0;
2746   user_data.header_cb_called = 0;
2747   rv =
2748       nghttp2_session_mem_recv(session, databuf.pos, nghttp2_buf_len(&databuf));
2749
2750   CU_ASSERT(rv >= 0);
2751   databuf.pos += rv;
2752
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);
2756
2757   CU_ASSERT(1 == user_data.begin_headers_cb_called);
2758   CU_ASSERT(1 == user_data.header_cb_called);
2759
2760   CU_ASSERT(nghttp2_nv_equal(&nv1[0], &user_data.nv));
2761
2762   /* get 2nd header field */
2763   user_data.begin_headers_cb_called = 0;
2764   user_data.header_cb_called = 0;
2765   rv =
2766       nghttp2_session_mem_recv(session, databuf.pos, nghttp2_buf_len(&databuf));
2767
2768   CU_ASSERT(rv >= 0);
2769   databuf.pos += rv;
2770
2771   CU_ASSERT(0 == user_data.begin_headers_cb_called);
2772   CU_ASSERT(1 == user_data.header_cb_called);
2773
2774   CU_ASSERT(nghttp2_nv_equal(&nv1[1], &user_data.nv));
2775
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;
2779   rv =
2780       nghttp2_session_mem_recv(session, databuf.pos, nghttp2_buf_len(&databuf));
2781
2782   CU_ASSERT(rv >= 0);
2783   databuf.pos += rv;
2784
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);
2788
2789   CU_ASSERT(1 == user_data.begin_headers_cb_called);
2790   CU_ASSERT(1 == user_data.header_cb_called);
2791
2792   CU_ASSERT(nghttp2_nv_equal(&nv2[0], &user_data.nv));
2793
2794   /* get 2nd header field */
2795   user_data.begin_headers_cb_called = 0;
2796   user_data.header_cb_called = 0;
2797   rv =
2798       nghttp2_session_mem_recv(session, databuf.pos, nghttp2_buf_len(&databuf));
2799
2800   CU_ASSERT(rv >= 0);
2801   databuf.pos += rv;
2802
2803   CU_ASSERT(0 == user_data.begin_headers_cb_called);
2804   CU_ASSERT(1 == user_data.header_cb_called);
2805
2806   CU_ASSERT(nghttp2_nv_equal(&nv2[1], &user_data.nv));
2807
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;
2812   rv =
2813       nghttp2_session_mem_recv(session, databuf.pos, nghttp2_buf_len(&databuf));
2814
2815   CU_ASSERT(rv >= 0);
2816   databuf.pos += rv;
2817
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);
2821
2822   /* Receive DATA */
2823   nghttp2_frame_hd_init(&data_hd, 16, NGHTTP2_DATA, NGHTTP2_FLAG_NONE, 1);
2824
2825   nghttp2_buf_reset(&databuf);
2826   nghttp2_frame_pack_frame_hd(databuf.pos, &data_hd);
2827
2828   /* Intentionally specify larger buffer size to see pause is kicked
2829      in. */
2830   databuf.last = databuf.end;
2831
2832   user_data.frame_recv_cb_called = 0;
2833   rv =
2834       nghttp2_session_mem_recv(session, databuf.pos, nghttp2_buf_len(&databuf));
2835
2836   CU_ASSERT(16 + NGHTTP2_FRAME_HDLEN == rv);
2837   CU_ASSERT(0 == user_data.frame_recv_cb_called);
2838
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
2841      DATA frame. */
2842   user_data.frame_recv_cb_called = 0;
2843   rv =
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);
2847
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);
2851   CU_ASSERT(0 == rv);
2852   CU_ASSERT(1 == user_data.frame_recv_cb_called);
2853
2854   nghttp2_bufs_free(&bufs);
2855   nghttp2_hd_deflate_free(&deflater);
2856   nghttp2_session_del(session);
2857 }
2858
2859 void test_nghttp2_session_add_frame(void) {
2860   nghttp2_session *session;
2861   nghttp2_session_callbacks callbacks;
2862   accumulator acc;
2863   my_user_data user_data;
2864   nghttp2_outbound_item *item;
2865   nghttp2_frame *frame;
2866   nghttp2_nv *nva;
2867   size_t nvlen;
2868   nghttp2_mem *mem;
2869
2870   mem = nghttp2_mem_default();
2871   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
2872   callbacks.send_callback = accumulator_send_callback;
2873
2874   acc.length = 0;
2875   user_data.acc = &acc;
2876
2877   CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, &user_data));
2878
2879   item = mem->malloc(sizeof(nghttp2_outbound_item), NULL);
2880
2881   nghttp2_outbound_item_init(item);
2882
2883   frame = &item->frame;
2884
2885   nvlen = ARRLEN(reqnv);
2886   nghttp2_nv_array_copy(&nva, reqnv, nvlen, mem);
2887
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);
2891
2892   session->next_stream_id += 2;
2893
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]));
2901
2902   nghttp2_session_del(session);
2903 }
2904
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")};
2913   nghttp2_nv *nva;
2914   size_t nvlen;
2915   nghttp2_priority_spec pri_spec;
2916   nghttp2_mem *mem;
2917
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;
2922
2923   nghttp2_session_server_new(&session, &callbacks, &user_data);
2924
2925   nghttp2_priority_spec_init(&pri_spec, 0, 255, 0);
2926
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);
2930
2931   user_data.begin_headers_cb_called = 0;
2932   user_data.invalid_frame_recv_cb_called = 0;
2933
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);
2939
2940   nghttp2_frame_headers_free(&frame.headers, mem);
2941
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));
2952
2953   nghttp2_frame_headers_free(&frame.headers, mem);
2954   session->local_settings.max_concurrent_streams =
2955       NGHTTP2_DEFAULT_MAX_CONCURRENT_STREAMS;
2956
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));
2967
2968   nghttp2_frame_headers_free(&frame.headers, mem);
2969
2970   /* Stream ID is our side and it is idle stream ID, then treat it as
2971      connection error */
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);
2980
2981   nghttp2_frame_headers_free(&frame.headers, mem);
2982
2983   nghttp2_session_del(session);
2984
2985   /* Check malformed headers. The library accept it. */
2986   nghttp2_session_server_new(&session, &callbacks, &user_data);
2987
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);
2998
2999   nghttp2_frame_headers_free(&frame.headers, mem);
3000
3001   nghttp2_session_del(session);
3002
3003   /* Check client side */
3004   nghttp2_session_client_new(&session, &callbacks, &user_data);
3005
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);
3009
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);
3015
3016   nghttp2_frame_headers_free(&frame.headers, mem);
3017
3018   nghttp2_session_del(session);
3019
3020   nghttp2_session_client_new(&session, &callbacks, &user_data);
3021
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);
3025
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);
3031
3032   nghttp2_frame_headers_free(&frame.headers, mem);
3033
3034   nghttp2_session_del(session);
3035
3036   nghttp2_session_client_new(&session, &callbacks, &user_data);
3037
3038   session->next_stream_id = 5;
3039   session->last_sent_stream_id = 3;
3040
3041   /* Stream ID which is not idle and not in stream map is just
3042      ignored */
3043   nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 3,
3044                              NGHTTP2_HCAT_REQUEST, NULL, NULL, 0);
3045
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));
3051
3052   nghttp2_frame_headers_free(&frame.headers, mem);
3053
3054   nghttp2_session_del(session);
3055
3056   nghttp2_session_server_new(&session, &callbacks, &user_data);
3057
3058   /* Stream ID which is equal to local_last_stream_id is ok. */
3059   session->local_last_stream_id = 3;
3060
3061   nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 3,
3062                              NGHTTP2_HCAT_REQUEST, NULL, NULL, 0);
3063
3064   CU_ASSERT(0 == nghttp2_session_on_request_headers_received(session, &frame));
3065
3066   nghttp2_frame_headers_free(&frame.headers, mem);
3067
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);
3071
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));
3078
3079   nghttp2_frame_headers_free(&frame.headers, mem);
3080
3081   nghttp2_session_del(session);
3082
3083   nghttp2_session_server_new(&session, &callbacks, &user_data);
3084
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);
3089
3090   nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 1,
3091                              NGHTTP2_HCAT_REQUEST, NULL, NULL, 0);
3092
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);
3096
3097   nghttp2_frame_headers_free(&frame.headers, mem);
3098
3099   nghttp2_session_del(session);
3100 }
3101
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;
3108   nghttp2_mem *mem;
3109
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;
3114
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);
3119
3120   user_data.begin_headers_cb_called = 0;
3121   user_data.invalid_frame_recv_cb_called = 0;
3122
3123   CU_ASSERT(0 == nghttp2_session_on_response_headers_received(session, &frame,
3124                                                               stream));
3125   CU_ASSERT(1 == user_data.begin_headers_cb_called);
3126   CU_ASSERT(NGHTTP2_STREAM_OPENED == stream->state);
3127
3128   nghttp2_frame_headers_free(&frame.headers, mem);
3129   nghttp2_session_del(session);
3130 }
3131
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;
3138   nghttp2_mem *mem;
3139
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;
3144
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);
3150
3151   user_data.begin_headers_cb_called = 0;
3152   user_data.invalid_frame_recv_cb_called = 0;
3153
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);
3157
3158   /* stream closed */
3159   frame.hd.flags |= NGHTTP2_FLAG_END_STREAM;
3160
3161   CU_ASSERT(0 == nghttp2_session_on_headers_received(session, &frame, stream));
3162   CU_ASSERT(2 == user_data.begin_headers_cb_called);
3163
3164   /* Check to see when NGHTTP2_STREAM_CLOSING, incoming HEADERS is
3165      discarded. */
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);
3174
3175   /* Server initiated stream */
3176   stream = open_recv_stream(session, 2);
3177
3178   frame.hd.flags = NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM;
3179   frame.hd.stream_id = 2;
3180
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);
3184
3185   nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_RD);
3186
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);
3191
3192   nghttp2_frame_headers_free(&frame.headers, mem);
3193
3194   nghttp2_session_del(session);
3195 }
3196
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;
3204   nghttp2_mem *mem;
3205
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;
3211
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
3218      0. */
3219
3220   user_data.begin_headers_cb_called = 0;
3221   user_data.invalid_frame_recv_cb_called = 0;
3222
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));
3231
3232   /* If un-ACKed max concurrent streams limit is exceeded,
3233      RST_STREAMed */
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,
3239                                                               stream));
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);
3245
3246   CU_ASSERT(0 == nghttp2_session_send(session));
3247   CU_ASSERT(1 == session->num_incoming_streams);
3248
3249   /* If ACKed max concurrent streams limit is exceeded, GOAWAY is
3250      issued */
3251   session->local_settings.max_concurrent_streams = 1;
3252
3253   stream = open_recv_stream2(session, 6, NGHTTP2_STREAM_RESERVED);
3254   frame.hd.stream_id = 6;
3255
3256   CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
3257             nghttp2_session_on_push_response_headers_received(session, &frame,
3258                                                               stream));
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);
3264
3265   nghttp2_frame_headers_free(&frame.headers, mem);
3266   nghttp2_session_del(session);
3267 }
3268
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;
3277
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;
3281
3282   nghttp2_session_server_new(&session, &callbacks, &user_data);
3283   stream = open_recv_stream(session, 1);
3284
3285   nghttp2_priority_spec_init(&pri_spec, 0, 2, 0);
3286
3287   nghttp2_frame_priority_init(&frame.priority, 1, &pri_spec);
3288
3289   /* depend on stream 0 */
3290   CU_ASSERT(0 == nghttp2_session_on_priority_received(session, &frame));
3291
3292   CU_ASSERT(2 == stream->weight);
3293
3294   stream = open_sent_stream(session, 2);
3295   dep_stream = open_recv_stream(session, 3);
3296
3297   frame.hd.stream_id = 2;
3298
3299   /* using dependency stream */
3300   nghttp2_priority_spec_init(&frame.priority.pri_spec, 3, 1, 0);
3301
3302   CU_ASSERT(0 == nghttp2_session_on_priority_received(session, &frame));
3303   CU_ASSERT(dep_stream == stream->dep_prev);
3304
3305   /* PRIORITY against idle stream */
3306
3307   frame.hd.stream_id = 100;
3308
3309   CU_ASSERT(0 == nghttp2_session_on_priority_received(session, &frame));
3310
3311   stream = nghttp2_session_get_stream_raw(session, frame.hd.stream_id);
3312
3313   CU_ASSERT(NGHTTP2_STREAM_IDLE == stream->state);
3314   CU_ASSERT(dep_stream == stream->dep_prev);
3315
3316   nghttp2_frame_priority_free(&frame.priority);
3317   nghttp2_session_del(session);
3318
3319   /* Check dep_stream_id == stream_id case */
3320   nghttp2_session_server_new(&session, &callbacks, &user_data);
3321   open_recv_stream(session, 1);
3322
3323   nghttp2_priority_spec_init(&pri_spec, 1, 0, 0);
3324
3325   nghttp2_frame_priority_init(&frame.priority, 1, &pri_spec);
3326
3327   CU_ASSERT(0 == nghttp2_session_on_priority_received(session, &frame));
3328
3329   item = nghttp2_session_get_next_ob_item(session);
3330
3331   CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
3332
3333   nghttp2_frame_priority_free(&frame.priority);
3334   nghttp2_session_del(session);
3335
3336   /* Check again dep_stream_id == stream_id, and stream_id is idle */
3337   nghttp2_session_server_new(&session, &callbacks, &user_data);
3338
3339   nghttp2_priority_spec_init(&pri_spec, 1, 16, 0);
3340
3341   nghttp2_frame_priority_init(&frame.priority, 1, &pri_spec);
3342
3343   CU_ASSERT(0 == nghttp2_session_on_priority_received(session, &frame));
3344
3345   item = nghttp2_session_get_next_ob_item(session);
3346
3347   CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
3348
3349   nghttp2_frame_priority_free(&frame.priority);
3350   nghttp2_session_del(session);
3351 }
3352
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);
3361
3362   nghttp2_frame_rst_stream_init(&frame.rst_stream, 1, NGHTTP2_PROTOCOL_ERROR);
3363
3364   CU_ASSERT(0 == nghttp2_session_on_rst_stream_received(session, &frame));
3365   CU_ASSERT(NULL == nghttp2_session_get_stream(session, 1));
3366
3367   nghttp2_frame_rst_stream_free(&frame.rst_stream);
3368   nghttp2_session_del(session);
3369 }
3370
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");
3381   nghttp2_mem *mem;
3382   nghttp2_option *option;
3383
3384   mem = nghttp2_mem_default();
3385
3386   iv[0].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS;
3387   iv[0].value = 50;
3388
3389   iv[1].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS;
3390   iv[1].value = 1000000009;
3391
3392   iv[2].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
3393   iv[2].value = 64 * 1024;
3394
3395   iv[3].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
3396   iv[3].value = 1024;
3397
3398   iv[4].settings_id = NGHTTP2_SETTINGS_ENABLE_PUSH;
3399   iv[4].value = 0;
3400
3401   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
3402   callbacks.send_callback = null_send_callback;
3403
3404   nghttp2_session_client_new(&session, &callbacks, &user_data);
3405   session->remote_settings.initial_window_size = 16 * 1024;
3406
3407   stream1 = open_sent_stream(session, 1);
3408   stream2 = open_recv_stream(session, 2);
3409
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;
3414
3415   nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE,
3416                               dup_iv(iv, niv), niv);
3417
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);
3423
3424   CU_ASSERT(64 * 1024 == stream1->remote_window_size);
3425   CU_ASSERT(0 == stream2->remote_window_size);
3426
3427   frame.settings.iv[2].value = 16 * 1024;
3428
3429   CU_ASSERT(0 == nghttp2_session_on_settings_received(session, &frame, 0));
3430
3431   CU_ASSERT(16 * 1024 == stream1->remote_window_size);
3432   CU_ASSERT(-48 * 1024 == stream2->remote_window_size);
3433
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));
3438
3439   nghttp2_frame_settings_free(&frame.settings, mem);
3440
3441   nghttp2_session_del(session);
3442
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),
3446                               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);
3451
3452   nghttp2_frame_settings_free(&frame.settings, mem);
3453   nghttp2_session_del(session);
3454
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);
3458
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);
3463
3464   nghttp2_frame_settings_free(&frame.settings, mem);
3465   nghttp2_session_del(session);
3466
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);
3470
3471   nghttp2_submit_request(session, NULL, &nv, 1, NULL, NULL);
3472
3473   nghttp2_session_send(session);
3474
3475   CU_ASSERT(session->hd_deflater.ctx.hd_table.len > 0);
3476
3477   iv[0].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
3478   iv[0].value = 0;
3479
3480   iv[1].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
3481   iv[1].value = 2048;
3482
3483   nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE, dup_iv(iv, 2),
3484                               2);
3485
3486   CU_ASSERT(0 == nghttp2_session_on_settings_received(session, &frame, 0));
3487
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);
3491
3492   nghttp2_frame_settings_free(&frame.settings, mem);
3493   nghttp2_session_del(session);
3494
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);
3502
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);
3507
3508   nghttp2_frame_settings_free(&frame.settings, mem);
3509   nghttp2_session_del(session);
3510   nghttp2_option_del(option);
3511
3512   /* Check too large SETTINGS_MAX_FRAME_SIZE */
3513   nghttp2_session_server_new(&session, &callbacks, NULL);
3514
3515   iv[0].settings_id = NGHTTP2_SETTINGS_MAX_FRAME_SIZE;
3516   iv[0].value = NGHTTP2_MAX_FRAME_SIZE_MAX + 1;
3517
3518   nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE, dup_iv(iv, 1),
3519                               1);
3520
3521   CU_ASSERT(0 == nghttp2_session_on_settings_received(session, &frame, 0));
3522
3523   item = nghttp2_session_get_next_ob_item(session);
3524
3525   CU_ASSERT(item != NULL);
3526   CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
3527
3528   nghttp2_frame_settings_free(&frame.settings, mem);
3529   nghttp2_session_del(session);
3530
3531   /* Check the case where stream window size overflows */
3532   nghttp2_session_server_new(&session, &callbacks, NULL);
3533
3534   stream1 = open_recv_stream(session, 1);
3535
3536   /* This will increment window size by 1 */
3537   nghttp2_frame_window_update_init(&frame.window_update, NGHTTP2_FLAG_NONE, 1,
3538                                    1);
3539
3540   CU_ASSERT(0 == nghttp2_session_on_window_update_received(session, &frame));
3541
3542   nghttp2_frame_window_update_free(&frame.window_update);
3543
3544   iv[0].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
3545   iv[0].value = NGHTTP2_MAX_WINDOW_SIZE;
3546
3547   nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE, dup_iv(iv, 1),
3548                               1);
3549
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));
3553
3554   nghttp2_frame_settings_free(&frame.settings, mem);
3555
3556   item = nghttp2_session_get_next_ob_item(session);
3557
3558   CU_ASSERT(NULL != item);
3559   CU_ASSERT(NGHTTP2_SETTINGS == item->frame.hd.type);
3560
3561   item = nghttp2_outbound_queue_top(&session->ob_reg);
3562
3563   CU_ASSERT(NULL != item);
3564   CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
3565   CU_ASSERT(NGHTTP2_STREAM_CLOSING == stream1->state);
3566
3567   nghttp2_session_del(session);
3568
3569   /* It is invalid that peer disables ENABLE_CONNECT_PROTOCOL once it
3570      has been enabled. */
3571   nghttp2_session_client_new(&session, &callbacks, NULL);
3572
3573   session->remote_settings.enable_connect_protocol = 1;
3574
3575   iv[0].settings_id = NGHTTP2_SETTINGS_ENABLE_CONNECT_PROTOCOL;
3576   iv[0].value = 0;
3577
3578   nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE, dup_iv(iv, 1),
3579                               1);
3580
3581   CU_ASSERT(0 == nghttp2_session_on_settings_received(session, &frame, 0));
3582
3583   nghttp2_frame_settings_free(&frame.settings, mem);
3584
3585   item = nghttp2_session_get_next_ob_item(session);
3586
3587   CU_ASSERT(NULL != item);
3588   CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
3589
3590   nghttp2_session_del(session);
3591 }
3592
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")};
3601   nghttp2_nv *nva;
3602   size_t nvlen;
3603   nghttp2_mem *mem;
3604   nghttp2_settings_entry iv = {NGHTTP2_SETTINGS_ENABLE_PUSH, 0};
3605
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;
3611
3612   nghttp2_session_client_new(&session, &callbacks, &user_data);
3613
3614   stream = open_sent_stream(session, 1);
3615
3616   nghttp2_frame_push_promise_init(&frame.push_promise, NGHTTP2_FLAG_END_HEADERS,
3617                                   1, 2, NULL, 0);
3618
3619   user_data.begin_headers_cb_called = 0;
3620   user_data.invalid_frame_recv_cb_called = 0;
3621
3622   CU_ASSERT(0 == nghttp2_session_on_push_promise_received(session, &frame));
3623
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);
3629
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;
3633
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));
3638
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);
3648
3649   nghttp2_session_del(session);
3650
3651   nghttp2_session_client_new(&session, &callbacks, &user_data);
3652
3653   stream = open_sent_stream(session, 1);
3654
3655   /* Attempt to PUSH_PROMISE against stream in closing state */
3656   stream->state = NGHTTP2_STREAM_CLOSING;
3657   frame.push_promise.promised_stream_id = 6;
3658
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));
3663
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));
3672
3673   /* Attempt to PUSH_PROMISE against idle stream */
3674   frame.hd.stream_id = 3;
3675   frame.push_promise.promised_stream_id = 8;
3676
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));
3681
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));
3690
3691   nghttp2_session_del(session);
3692
3693   nghttp2_session_client_new(&session, &callbacks, &user_data);
3694
3695   stream = open_sent_stream(session, 1);
3696
3697   /* Same ID twice */
3698   frame.hd.stream_id = 1;
3699   frame.push_promise.promised_stream_id = 2;
3700
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));
3704
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));
3708
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));
3713
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));
3721
3722   /* After GOAWAY, PUSH_PROMISE will be discarded */
3723   frame.push_promise.promised_stream_id = 10;
3724
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));
3729
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));
3734
3735   nghttp2_frame_push_promise_free(&frame.push_promise, mem);
3736   nghttp2_session_del(session);
3737
3738   nghttp2_session_client_new(&session, &callbacks, &user_data);
3739
3740   open_recv_stream2(session, 2, NGHTTP2_STREAM_RESERVED);
3741
3742   /* Attempt to PUSH_PROMISE against reserved (remote) stream */
3743   nghttp2_frame_push_promise_init(&frame.push_promise, NGHTTP2_FLAG_END_HEADERS,
3744                                   2, 4, NULL, 0);
3745
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));
3750
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);
3754
3755   nghttp2_frame_push_promise_free(&frame.push_promise, mem);
3756   nghttp2_session_del(session);
3757
3758   /* Disable PUSH */
3759   nghttp2_session_client_new(&session, &callbacks, &user_data);
3760
3761   open_sent_stream(session, 1);
3762
3763   session->local_settings.enable_push = 0;
3764
3765   nghttp2_frame_push_promise_init(&frame.push_promise, NGHTTP2_FLAG_END_HEADERS,
3766                                   1, 2, NULL, 0);
3767
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));
3772
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);
3776
3777   nghttp2_frame_push_promise_free(&frame.push_promise, mem);
3778   nghttp2_session_del(session);
3779
3780   /* Check malformed headers. We accept malformed headers */
3781   nghttp2_session_client_new(&session, &callbacks, &user_data);
3782
3783   open_sent_stream(session, 1);
3784
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,
3788                                   1, 2, nva, nvlen);
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));
3792
3793   CU_ASSERT(1 == user_data.begin_headers_cb_called);
3794   CU_ASSERT(0 == user_data.invalid_frame_recv_cb_called);
3795
3796   nghttp2_frame_push_promise_free(&frame.push_promise, mem);
3797   nghttp2_session_del(session);
3798
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);
3802
3803   open_sent_stream(session, 1);
3804
3805   /* Submit settings with ENABLE_PUSH = 0 (thus disabling push) */
3806   nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, &iv, 1);
3807
3808   nghttp2_frame_push_promise_init(&frame.push_promise, NGHTTP2_FLAG_END_HEADERS,
3809                                   1, 2, NULL, 0);
3810
3811   CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
3812             nghttp2_session_on_push_promise_received(session, &frame));
3813
3814   CU_ASSERT(0 == session->num_incoming_reserved_streams);
3815
3816   nghttp2_frame_push_promise_free(&frame.push_promise, mem);
3817   nghttp2_session_del(session);
3818
3819   /* Check max_incoming_reserved_streams */
3820   nghttp2_session_client_new(&session, &callbacks, &user_data);
3821   session->max_incoming_reserved_streams = 1;
3822
3823   open_sent_stream(session, 1);
3824   open_recv_stream2(session, 2, NGHTTP2_STREAM_RESERVED);
3825
3826   CU_ASSERT(1 == session->num_incoming_reserved_streams);
3827
3828   nghttp2_frame_push_promise_init(&frame.push_promise, NGHTTP2_FLAG_END_HEADERS,
3829                                   1, 4, NULL, 0);
3830
3831   CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
3832             nghttp2_session_on_push_promise_received(session, &frame));
3833
3834   CU_ASSERT(1 == session->num_incoming_reserved_streams);
3835
3836   item = nghttp2_session_get_next_ob_item(session);
3837
3838   CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
3839   CU_ASSERT(NGHTTP2_CANCEL == item->frame.rst_stream.error_code);
3840
3841   nghttp2_frame_push_promise_free(&frame.push_promise, mem);
3842   nghttp2_session_del(session);
3843 }
3844
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;
3853
3854   user_data.frame_recv_cb_called = 0;
3855   user_data.invalid_frame_recv_cb_called = 0;
3856
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;
3860
3861   nghttp2_session_client_new(&session, &callbacks, &user_data);
3862   nghttp2_frame_ping_init(&frame.ping, NGHTTP2_FLAG_ACK, opaque_data);
3863
3864   CU_ASSERT(0 == nghttp2_session_on_ping_received(session, &frame));
3865   CU_ASSERT(1 == user_data.frame_recv_cb_called);
3866
3867   /* Since this ping frame has ACK flag set, no further action is
3868      performed. */
3869   CU_ASSERT(NULL == nghttp2_outbound_queue_top(&session->ob_urgent));
3870
3871   /* Clear the flag, and receive it again */
3872   frame.hd.flags = NGHTTP2_FLAG_NONE;
3873
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);
3880
3881   nghttp2_frame_ping_free(&frame.ping);
3882   nghttp2_session_del(session);
3883
3884   /* Use nghttp2_option_set_no_auto_ping_ack() */
3885   nghttp2_option_new(&option);
3886   nghttp2_option_set_no_auto_ping_ack(option, 1);
3887
3888   nghttp2_session_server_new2(&session, &callbacks, &user_data, option);
3889   nghttp2_frame_ping_init(&frame.ping, NGHTTP2_FLAG_NONE, NULL);
3890
3891   user_data.frame_recv_cb_called = 0;
3892
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));
3896
3897   nghttp2_frame_ping_free(&frame.ping);
3898   nghttp2_session_del(session);
3899   nghttp2_option_del(option);
3900 }
3901
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;
3907   int i;
3908   nghttp2_mem *mem;
3909
3910   mem = nghttp2_mem_default();
3911   user_data.frame_recv_cb_called = 0;
3912   user_data.invalid_frame_recv_cb_called = 0;
3913
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;
3918
3919   nghttp2_session_client_new(&session, &callbacks, &user_data);
3920
3921   for (i = 1; i <= 7; ++i) {
3922     if (nghttp2_session_is_my_stream_id(session, i)) {
3923       open_sent_stream(session, i);
3924     } else {
3925       open_recv_stream(session, i);
3926     }
3927   }
3928
3929   nghttp2_frame_goaway_init(&frame.goaway, 3, NGHTTP2_PROTOCOL_ERROR, NULL, 0);
3930
3931   user_data.stream_close_cb_called = 0;
3932
3933   CU_ASSERT(0 == nghttp2_session_on_goaway_received(session, &frame));
3934
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);
3939
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));
3947
3948   nghttp2_frame_goaway_free(&frame.goaway, mem);
3949   nghttp2_session_del(session);
3950 }
3951
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;
3959   nghttp2_mem *mem;
3960
3961   mem = nghttp2_mem_default();
3962
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;
3968
3969   nghttp2_session_client_new(&session, &callbacks, &user_data);
3970
3971   stream = open_sent_stream(session, 1);
3972
3973   data_item = create_data_ob_item(mem);
3974
3975   CU_ASSERT(0 == nghttp2_stream_attach_item(stream, data_item));
3976
3977   nghttp2_frame_window_update_init(&frame.window_update, NGHTTP2_FLAG_NONE, 1,
3978                                    16 * 1024);
3979
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);
3984
3985   CU_ASSERT(0 == nghttp2_stream_defer_item(
3986                      stream, NGHTTP2_STREAM_FLAG_DEFERRED_FLOW_CONTROL));
3987
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));
3993
3994   nghttp2_frame_window_update_free(&frame.window_update);
3995
3996   /* Receiving WINDOW_UPDATE on reserved (remote) stream is a
3997      connection error */
3998   open_recv_stream2(session, 2, NGHTTP2_STREAM_RESERVED);
3999
4000   nghttp2_frame_window_update_init(&frame.window_update, NGHTTP2_FLAG_NONE, 2,
4001                                    4096);
4002
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);
4006
4007   nghttp2_frame_window_update_free(&frame.window_update);
4008
4009   nghttp2_session_del(session);
4010
4011   /* Receiving WINDOW_UPDATE on reserved (local) stream is allowed */
4012   nghttp2_session_server_new(&session, &callbacks, &user_data);
4013
4014   stream = open_sent_stream2(session, 2, NGHTTP2_STREAM_RESERVED);
4015
4016   nghttp2_frame_window_update_init(&frame.window_update, NGHTTP2_FLAG_NONE, 2,
4017                                    4096);
4018
4019   CU_ASSERT(0 == nghttp2_session_on_window_update_received(session, &frame));
4020   CU_ASSERT(!(session->goaway_flags & NGHTTP2_GOAWAY_TERM_ON_SEND));
4021
4022   CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE + 4096 == stream->remote_window_size);
4023
4024   nghttp2_frame_window_update_free(&frame.window_update);
4025
4026   nghttp2_session_del(session);
4027 }
4028
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;
4036
4037   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4038
4039   nghttp2_session_client_new(&session, &callbacks, &user_data);
4040   stream = open_recv_stream(session, 2);
4041
4042   nghttp2_frame_hd_init(&frame.hd, 4096, NGHTTP2_DATA, NGHTTP2_FLAG_NONE, 2);
4043
4044   CU_ASSERT(0 == nghttp2_session_on_data_received(session, &frame));
4045   CU_ASSERT(0 == stream->shut_flags);
4046
4047   frame.hd.flags = NGHTTP2_FLAG_END_STREAM;
4048
4049   CU_ASSERT(0 == nghttp2_session_on_data_received(session, &frame));
4050   CU_ASSERT(NGHTTP2_SHUT_RD == stream->shut_flags);
4051
4052   /* If NGHTTP2_STREAM_CLOSING state, DATA frame is discarded. */
4053   open_sent_stream2(session, 1, NGHTTP2_STREAM_CLOSING);
4054
4055   frame.hd.flags = NGHTTP2_FLAG_NONE;
4056   frame.hd.stream_id = 1;
4057
4058   CU_ASSERT(0 == nghttp2_session_on_data_received(session, &frame));
4059   CU_ASSERT(NULL == nghttp2_outbound_queue_top(&session->ob_reg));
4060
4061   /* Check INVALID_STREAM case: DATA frame with stream ID which does
4062      not exist. */
4063
4064   frame.hd.stream_id = 3;
4065
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);
4070
4071   nghttp2_session_del(session);
4072 }
4073
4074 void test_nghttp2_session_on_data_received_fail_fast(void) {
4075   nghttp2_session *session;
4076   nghttp2_session_callbacks callbacks;
4077   uint8_t buf[9];
4078   nghttp2_stream *stream;
4079   nghttp2_frame_hd hd;
4080   nghttp2_outbound_item *item;
4081
4082   memset(&callbacks, 0, sizeof(callbacks));
4083
4084   nghttp2_frame_hd_init(&hd, 0, NGHTTP2_DATA, NGHTTP2_FLAG_NONE, 1);
4085   nghttp2_frame_pack_frame_hd(buf, &hd);
4086
4087   nghttp2_session_server_new(&session, &callbacks, NULL);
4088
4089   /* DATA to closed (remote) */
4090   stream = open_recv_stream(session, 1);
4091   nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_RD);
4092
4093   CU_ASSERT((ssize_t)sizeof(buf) ==
4094             nghttp2_session_mem_recv(session, buf, sizeof(buf)));
4095
4096   item = nghttp2_session_get_next_ob_item(session);
4097
4098   CU_ASSERT(NULL != item);
4099   CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
4100
4101   nghttp2_session_del(session);
4102
4103   nghttp2_session_server_new(&session, &callbacks, NULL);
4104
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);
4109
4110   CU_ASSERT((ssize_t)sizeof(buf) ==
4111             nghttp2_session_mem_recv(session, buf, sizeof(buf)));
4112
4113   item = nghttp2_session_get_next_ob_item(session);
4114
4115   CU_ASSERT(NULL != item);
4116   CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
4117
4118   nghttp2_session_del(session);
4119 }
4120
4121 void test_nghttp2_session_on_altsvc_received(void) {
4122   nghttp2_session *session;
4123   nghttp2_session_callbacks callbacks;
4124   my_user_data ud;
4125   nghttp2_frame frame;
4126   nghttp2_option *option;
4127   uint8_t origin[] = "nghttp2.org";
4128   uint8_t field_value[] = "h2=\":443\"";
4129   int rv;
4130
4131   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4132   callbacks.on_frame_recv_callback = on_frame_recv_callback;
4133
4134   nghttp2_option_new(&option);
4135   nghttp2_option_set_builtin_recv_extension_type(option, NGHTTP2_ALTSVC);
4136
4137   nghttp2_session_client_new2(&session, &callbacks, &ud, option);
4138
4139   frame.ext.payload = &session->iframe.ext_frame_payload;
4140
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);
4145
4146   ud.frame_recv_cb_called = 0;
4147   rv = nghttp2_session_on_altsvc_received(session, &frame);
4148
4149   CU_ASSERT(0 == rv);
4150   CU_ASSERT(1 == ud.frame_recv_cb_called);
4151
4152   nghttp2_session_del(session);
4153
4154   /* Receiving empty origin with stream ID == 0 */
4155   nghttp2_session_client_new2(&session, &callbacks, &ud, option);
4156
4157   frame.ext.payload = &session->iframe.ext_frame_payload;
4158
4159   nghttp2_frame_altsvc_init(&frame.ext, 0, origin, 0, field_value,
4160                             sizeof(field_value) - 1);
4161
4162   ud.frame_recv_cb_called = 0;
4163   rv = nghttp2_session_on_altsvc_received(session, &frame);
4164
4165   CU_ASSERT(0 == rv);
4166   CU_ASSERT(0 == ud.frame_recv_cb_called);
4167
4168   nghttp2_session_del(session);
4169
4170   /* Receiving non-empty origin with stream ID != 0 */
4171   nghttp2_session_client_new2(&session, &callbacks, &ud, option);
4172
4173   frame.ext.payload = &session->iframe.ext_frame_payload;
4174
4175   open_sent_stream(session, 1);
4176
4177   nghttp2_frame_altsvc_init(&frame.ext, 1, origin, sizeof(origin) - 1,
4178                             field_value, sizeof(field_value) - 1);
4179
4180   ud.frame_recv_cb_called = 0;
4181   rv = nghttp2_session_on_altsvc_received(session, &frame);
4182
4183   CU_ASSERT(0 == rv);
4184   CU_ASSERT(0 == ud.frame_recv_cb_called);
4185
4186   nghttp2_session_del(session);
4187
4188   /* Receiving empty origin with stream ID != 0; this is OK */
4189   nghttp2_session_client_new2(&session, &callbacks, &ud, option);
4190
4191   frame.ext.payload = &session->iframe.ext_frame_payload;
4192
4193   open_sent_stream(session, 1);
4194
4195   nghttp2_frame_altsvc_init(&frame.ext, 1, origin, 0, field_value,
4196                             sizeof(field_value) - 1);
4197
4198   ud.frame_recv_cb_called = 0;
4199   rv = nghttp2_session_on_altsvc_received(session, &frame);
4200
4201   CU_ASSERT(0 == rv);
4202   CU_ASSERT(1 == ud.frame_recv_cb_called);
4203
4204   nghttp2_session_del(session);
4205
4206   /* Stream does not exist; ALTSVC will be ignored. */
4207   nghttp2_session_client_new2(&session, &callbacks, &ud, option);
4208
4209   frame.ext.payload = &session->iframe.ext_frame_payload;
4210
4211   nghttp2_frame_altsvc_init(&frame.ext, 1, origin, 0, field_value,
4212                             sizeof(field_value) - 1);
4213
4214   ud.frame_recv_cb_called = 0;
4215   rv = nghttp2_session_on_altsvc_received(session, &frame);
4216
4217   CU_ASSERT(0 == rv);
4218   CU_ASSERT(0 == ud.frame_recv_cb_called);
4219
4220   nghttp2_session_del(session);
4221
4222   nghttp2_option_del(option);
4223 }
4224
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;
4231   nghttp2_mem *mem;
4232
4233   mem = nghttp2_mem_default();
4234
4235   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4236   callbacks.send_callback = null_send_callback;
4237
4238   nghttp2_session_client_new(&session, &callbacks, NULL);
4239
4240   item = mem->malloc(sizeof(nghttp2_outbound_item), NULL);
4241
4242   nghttp2_outbound_item_init(item);
4243
4244   frame = &item->frame;
4245
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;
4250
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);
4255
4256   nghttp2_session_del(session);
4257 }
4258
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;
4265   nghttp2_mem *mem;
4266
4267   mem = nghttp2_mem_default();
4268
4269   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4270   callbacks.send_callback = null_send_callback;
4271
4272   CU_ASSERT(0 == nghttp2_session_server_new(&session, &callbacks, NULL));
4273   open_recv_stream2(session, 1, NGHTTP2_STREAM_OPENING);
4274
4275   item = mem->malloc(sizeof(nghttp2_outbound_item), NULL);
4276
4277   nghttp2_outbound_item_init(item);
4278
4279   frame = &item->frame;
4280
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);
4287
4288   nghttp2_session_del(session);
4289 }
4290
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;
4296   nghttp2_nv *nva;
4297   size_t nvlen;
4298   size_t vallen = NGHTTP2_HD_MAX_NV;
4299   nghttp2_nv nv[28];
4300   size_t nnv = ARRLEN(nv);
4301   size_t i;
4302   my_user_data ud;
4303   nghttp2_mem *mem;
4304
4305   mem = nghttp2_mem_default();
4306
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;
4315   }
4316
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;
4320
4321   nghttp2_session_client_new(&session, &callbacks, &ud);
4322   nvlen = nnv;
4323   nghttp2_nv_array_copy(&nva, nv, nvlen, mem);
4324
4325   item = mem->malloc(sizeof(nghttp2_outbound_item), NULL);
4326
4327   nghttp2_outbound_item_init(item);
4328
4329   frame = &item->frame;
4330
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);
4334
4335   session->next_stream_id += 2;
4336
4337   nghttp2_session_add_item(session, item);
4338
4339   ud.frame_not_send_cb_called = 0;
4340
4341   CU_ASSERT(0 == nghttp2_session_send(session));
4342
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);
4346
4347   for (i = 0; i < nnv; ++i) {
4348     mem->free(nv[i].value, NULL);
4349   }
4350   nghttp2_session_del(session);
4351 }
4352
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;
4359   nghttp2_mem *mem;
4360
4361   mem = nghttp2_mem_default();
4362
4363   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4364   callbacks.send_callback = null_send_callback;
4365
4366   CU_ASSERT(0 == nghttp2_session_server_new(&session, &callbacks, NULL));
4367   open_sent_stream2(session, 2, NGHTTP2_STREAM_RESERVED);
4368
4369   item = mem->malloc(sizeof(nghttp2_outbound_item), NULL);
4370
4371   nghttp2_outbound_item_init(item);
4372
4373   frame = &item->frame;
4374
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);
4385 }
4386
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;
4393   nghttp2_mem *mem;
4394
4395   mem = nghttp2_mem_default();
4396
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);
4401
4402   item = mem->malloc(sizeof(nghttp2_outbound_item), NULL);
4403
4404   nghttp2_outbound_item_init(item);
4405
4406   frame = &item->frame;
4407
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));
4411
4412   CU_ASSERT(NULL == nghttp2_session_get_stream(session, 1));
4413
4414   nghttp2_session_del(session);
4415 }
4416
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;
4424   my_user_data ud;
4425   nghttp2_mem *mem;
4426
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;
4431
4432   nghttp2_session_server_new(&session, &callbacks, &ud);
4433   open_recv_stream(session, 1);
4434
4435   item = mem->malloc(sizeof(nghttp2_outbound_item), NULL);
4436
4437   nghttp2_outbound_item_init(item);
4438
4439   frame = &item->frame;
4440
4441   nghttp2_frame_push_promise_init(&frame->push_promise,
4442                                   NGHTTP2_FLAG_END_HEADERS, 1,
4443                                   (int32_t)session->next_stream_id, NULL, 0);
4444
4445   session->next_stream_id += 2;
4446
4447   nghttp2_session_add_item(session, item);
4448
4449   CU_ASSERT(0 == nghttp2_session_send(session));
4450   stream = nghttp2_session_get_stream(session, 2);
4451   CU_ASSERT(NGHTTP2_STREAM_RESERVED == stream->state);
4452
4453   /* Received ENABLE_PUSH = 0 */
4454   iv.settings_id = NGHTTP2_SETTINGS_ENABLE_PUSH;
4455   iv.value = 0;
4456   frame = mem->malloc(sizeof(nghttp2_frame), NULL);
4457   nghttp2_frame_settings_init(&frame->settings, NGHTTP2_FLAG_NONE,
4458                               dup_iv(&iv, 1), 1);
4459   nghttp2_session_on_settings_received(session, frame, 1);
4460   nghttp2_frame_settings_free(&frame->settings, mem);
4461   mem->free(frame, NULL);
4462
4463   item = mem->malloc(sizeof(nghttp2_outbound_item), NULL);
4464
4465   nghttp2_outbound_item_init(item);
4466
4467   frame = &item->frame;
4468
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);
4472
4473   ud.frame_not_send_cb_called = 0;
4474   CU_ASSERT(0 == nghttp2_session_send(session));
4475
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);
4479
4480   nghttp2_session_del(session);
4481
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);
4486
4487   nghttp2_outbound_item_init(item);
4488
4489   frame = &item->frame;
4490
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);
4494
4495   CU_ASSERT(0 == nghttp2_session_send(session));
4496   CU_ASSERT(NULL == nghttp2_session_get_stream(session, 3));
4497
4498   nghttp2_session_del(session);
4499 }
4500
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);
4506
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));
4510
4511   nghttp2_session_del(session);
4512
4513   nghttp2_session_client_new(&session, &callbacks, NULL);
4514
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));
4518
4519   nghttp2_session_del(session);
4520 }
4521
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;
4530   ssize_t rv;
4531   nghttp2_bufs bufs;
4532   nghttp2_buf *buf;
4533   nghttp2_hd_deflater deflater;
4534   nghttp2_mem *mem;
4535
4536   mem = nghttp2_mem_default();
4537   frame_pack_bufs_init(&bufs);
4538
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;
4542   iv[0].value = 1;
4543   iv[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
4544   iv[1].value = 4095;
4545   settings_payloadlen = (size_t)nghttp2_pack_settings_payload(
4546       settings_payload, sizeof(settings_payload), iv, 2);
4547
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);
4566
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);
4572
4573   /* Make sure that response from server can be received */
4574   nghttp2_session_client_new(&session, &callbacks, NULL);
4575
4576   CU_ASSERT(0 == nghttp2_session_upgrade2(session, settings_payload,
4577                                           settings_payloadlen, 0, &callbacks));
4578
4579   stream = nghttp2_session_get_stream(session, 1);
4580
4581   CU_ASSERT(NGHTTP2_STREAM_OPENING == stream->state);
4582
4583   nghttp2_hd_deflate_init(&deflater, mem);
4584   rv = pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, resnv,
4585                     ARRLEN(resnv), mem);
4586
4587   CU_ASSERT(0 == rv);
4588
4589   buf = &bufs.head->buf;
4590
4591   rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
4592
4593   CU_ASSERT(rv == (ssize_t)nghttp2_buf_len(buf));
4594   CU_ASSERT(NGHTTP2_STREAM_OPENED == stream->state);
4595
4596   nghttp2_hd_deflate_free(&deflater);
4597   nghttp2_session_del(session);
4598
4599   nghttp2_bufs_reset(&bufs);
4600
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);
4618
4619   /* Empty SETTINGS is OK */
4620   settings_payloadlen = (size_t)nghttp2_pack_settings_payload(
4621       settings_payload, sizeof(settings_payload), NULL, 0);
4622
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);
4628 }
4629
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;
4636   int rv;
4637
4638   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4639   callbacks.send_callback = block_count_send_callback;
4640
4641   nghttp2_session_server_new(&session, &callbacks, NULL);
4642
4643   stream = open_recv_stream(session, 1);
4644
4645   nghttp2_priority_spec_init(&pri_spec, 0, 10, 0);
4646
4647   rv = nghttp2_session_reprioritize_stream(session, stream, &pri_spec);
4648
4649   CU_ASSERT(0 == rv);
4650   CU_ASSERT(10 == stream->weight);
4651   CU_ASSERT(&session->root == stream->dep_prev);
4652
4653   /* If depenency to idle stream which is not in depdenency tree yet */
4654
4655   nghttp2_priority_spec_init(&pri_spec, 3, 99, 0);
4656
4657   rv = nghttp2_session_reprioritize_stream(session, stream, &pri_spec);
4658
4659   CU_ASSERT(0 == rv);
4660   CU_ASSERT(99 == stream->weight);
4661   CU_ASSERT(3 == stream->dep_prev->stream_id);
4662
4663   dep_stream = nghttp2_session_get_stream_raw(session, 3);
4664
4665   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == dep_stream->weight);
4666
4667   dep_stream = open_recv_stream(session, 3);
4668
4669   /* Change weight */
4670   pri_spec.weight = 128;
4671
4672   rv = nghttp2_session_reprioritize_stream(session, stream, &pri_spec);
4673
4674   CU_ASSERT(0 == rv);
4675   CU_ASSERT(128 == stream->weight);
4676   CU_ASSERT(dep_stream == stream->dep_prev);
4677
4678   /* Change weight again to test short-path case */
4679   pri_spec.weight = 100;
4680
4681   rv = nghttp2_session_reprioritize_stream(session, stream, &pri_spec);
4682
4683   CU_ASSERT(0 == rv);
4684   CU_ASSERT(100 == stream->weight);
4685   CU_ASSERT(dep_stream == stream->dep_prev);
4686   CU_ASSERT(100 == dep_stream->sum_dep_weight);
4687
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);
4691
4692   rv = nghttp2_session_reprioritize_stream(session, dep_stream, &pri_spec);
4693
4694   CU_ASSERT(0 == rv);
4695   CU_ASSERT(1 == dep_stream->weight);
4696   CU_ASSERT(stream == dep_stream->dep_prev);
4697
4698   /* Making priority to closed stream will result in default
4699      priority */
4700   session->last_recv_stream_id = 9;
4701
4702   nghttp2_priority_spec_init(&pri_spec, 5, 5, 0);
4703
4704   rv = nghttp2_session_reprioritize_stream(session, stream, &pri_spec);
4705
4706   CU_ASSERT(0 == rv);
4707   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == stream->weight);
4708
4709   nghttp2_session_del(session);
4710
4711   nghttp2_session_server_new(&session, &callbacks, NULL);
4712
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);
4720
4721   nghttp2_priority_spec_init(&pri_spec, 7, 1, 1);
4722
4723   stream = nghttp2_session_get_stream(session, 3);
4724   rv = nghttp2_session_reprioritize_stream(session, stream, &pri_spec);
4725
4726   CU_ASSERT(0 == rv);
4727   CU_ASSERT(7 == stream->dep_prev->stream_id);
4728
4729   stream = nghttp2_session_get_stream(session, 7);
4730
4731   CU_ASSERT(1 == stream->dep_prev->stream_id);
4732
4733   stream = nghttp2_session_get_stream(session, 9);
4734
4735   CU_ASSERT(3 == stream->dep_prev->stream_id);
4736
4737   stream = nghttp2_session_get_stream(session, 5);
4738
4739   CU_ASSERT(3 == stream->dep_prev->stream_id);
4740
4741   nghttp2_session_del(session);
4742
4743   nghttp2_session_server_new(&session, &callbacks, NULL);
4744
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);
4752
4753   nghttp2_priority_spec_init(&pri_spec, 7, 1, 0);
4754
4755   stream = nghttp2_session_get_stream(session, 3);
4756   rv = nghttp2_session_reprioritize_stream(session, stream, &pri_spec);
4757
4758   CU_ASSERT(0 == rv);
4759   CU_ASSERT(7 == stream->dep_prev->stream_id);
4760
4761   stream = nghttp2_session_get_stream(session, 7);
4762
4763   CU_ASSERT(1 == stream->dep_prev->stream_id);
4764
4765   stream = nghttp2_session_get_stream(session, 9);
4766
4767   CU_ASSERT(7 == stream->dep_prev->stream_id);
4768
4769   stream = nghttp2_session_get_stream(session, 5);
4770
4771   CU_ASSERT(3 == stream->dep_prev->stream_id);
4772
4773   nghttp2_session_del(session);
4774 }
4775
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;
4781
4782   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4783   callbacks.send_callback = block_count_send_callback;
4784
4785   nghttp2_session_server_new(&session, &callbacks, NULL);
4786
4787   stream = open_recv_stream(session, 1);
4788
4789   session->pending_local_max_concurrent_stream = 1;
4790
4791   nghttp2_priority_spec_init(&pri_spec, 101, 10, 0);
4792
4793   nghttp2_session_reprioritize_stream(session, stream, &pri_spec);
4794
4795   /* idle stream is not counteed to max concurrent streams */
4796
4797   CU_ASSERT(10 == stream->weight);
4798   CU_ASSERT(101 == stream->dep_prev->stream_id);
4799
4800   stream = nghttp2_session_get_stream_raw(session, 101);
4801
4802   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == stream->weight);
4803
4804   nghttp2_session_del(session);
4805 }
4806
4807 void test_nghttp2_submit_data(void) {
4808   nghttp2_session *session;
4809   nghttp2_session_callbacks callbacks;
4810   nghttp2_data_provider data_prd;
4811   my_user_data ud;
4812   nghttp2_frame *frame;
4813   nghttp2_frame_hd hd;
4814   nghttp2_active_outbound_item *aob;
4815   nghttp2_bufs *framebufs;
4816   nghttp2_buf *buf;
4817
4818   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4819   callbacks.send_callback = block_count_send_callback;
4820
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;
4826
4827   open_sent_stream(session, 1);
4828
4829   CU_ASSERT(
4830       0 == nghttp2_submit_data(session, NGHTTP2_FLAG_END_STREAM, 1, &data_prd));
4831
4832   ud.block_count = 0;
4833   CU_ASSERT(0 == nghttp2_session_send(session));
4834   frame = &aob->item->frame;
4835
4836   buf = &framebufs->head->buf;
4837   nghttp2_frame_unpack_frame_hd(&hd, buf->pos);
4838
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);
4843
4844   nghttp2_session_del(session);
4845 }
4846
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;
4851   my_user_data ud;
4852   nghttp2_frame *frame;
4853   nghttp2_frame_hd hd;
4854   nghttp2_active_outbound_item *aob;
4855   nghttp2_bufs *framebufs;
4856   nghttp2_buf *buf;
4857   size_t payloadlen;
4858
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;
4862
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;
4868
4869   open_sent_stream(session, 1);
4870
4871   CU_ASSERT(
4872       0 == nghttp2_submit_data(session, NGHTTP2_FLAG_END_STREAM, 1, &data_prd));
4873
4874   ud.block_count = 0;
4875   CU_ASSERT(0 == nghttp2_session_send(session));
4876   frame = &aob->item->frame;
4877
4878   buf = &framebufs->head->buf;
4879   nghttp2_frame_unpack_frame_hd(&hd, buf->pos);
4880
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);
4886
4887   nghttp2_session_del(session);
4888
4889   /* Check that buffers are expanded */
4890   CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, &ud));
4891
4892   ud.data_source_length = NGHTTP2_MAX_FRAME_SIZE_MAX;
4893
4894   session->remote_settings.max_frame_size = NGHTTP2_MAX_FRAME_SIZE_MAX;
4895
4896   open_sent_stream(session, 1);
4897
4898   CU_ASSERT(
4899       0 == nghttp2_submit_data(session, NGHTTP2_FLAG_END_STREAM, 1, &data_prd));
4900
4901   ud.block_count = 0;
4902   CU_ASSERT(0 == nghttp2_session_send(session));
4903
4904   aob = &session->aob;
4905
4906   frame = &aob->item->frame;
4907
4908   framebufs = &aob->framebufs;
4909
4910   buf = &framebufs->head->buf;
4911   nghttp2_frame_unpack_frame_hd(&hd, buf->pos);
4912
4913   payloadlen = nghttp2_min(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE,
4914                            NGHTTP2_INITIAL_WINDOW_SIZE);
4915
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);
4923
4924   nghttp2_session_del(session);
4925 }
4926
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;
4931   my_user_data ud;
4932   nghttp2_frame *frame;
4933   nghttp2_frame_hd hd;
4934   nghttp2_active_outbound_item *aob;
4935   nghttp2_bufs *framebufs;
4936   nghttp2_buf *buf;
4937
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;
4941
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;
4947
4948   open_sent_stream(session, 1);
4949
4950   CU_ASSERT(
4951       0 == nghttp2_submit_data(session, NGHTTP2_FLAG_END_STREAM, 1, &data_prd));
4952
4953   ud.block_count = 0;
4954   CU_ASSERT(0 == nghttp2_session_send(session));
4955   frame = &aob->item->frame;
4956
4957   buf = &framebufs->head->buf;
4958   nghttp2_frame_unpack_frame_hd(&hd, buf->pos);
4959
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);
4965
4966   nghttp2_session_del(session);
4967 }
4968
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) {
4972   (void)session;
4973   (void)stream_id;
4974   (void)buf;
4975   (void)source;
4976   (void)user_data;
4977
4978   *data_flags |= NGHTTP2_DATA_FLAG_EOF;
4979   return (ssize_t)nghttp2_min(len, 16);
4980 }
4981
4982 static int submit_data_twice_on_frame_send_callback(nghttp2_session *session,
4983                                                     const nghttp2_frame *frame,
4984                                                     void *user_data) {
4985   static int called = 0;
4986   int rv;
4987   nghttp2_data_provider data_prd;
4988   (void)user_data;
4989
4990   if (called == 0) {
4991     called = 1;
4992
4993     data_prd.read_callback = submit_data_twice_data_source_read_callback;
4994
4995     rv = nghttp2_submit_data(session, NGHTTP2_FLAG_END_STREAM,
4996                              frame->hd.stream_id, &data_prd);
4997     CU_ASSERT(0 == rv);
4998   }
4999
5000   return 0;
5001 }
5002
5003 void test_nghttp2_submit_data_twice(void) {
5004   nghttp2_session *session;
5005   nghttp2_session_callbacks callbacks;
5006   nghttp2_data_provider data_prd;
5007   my_user_data ud;
5008   accumulator acc;
5009
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;
5013
5014   data_prd.read_callback = submit_data_twice_data_source_read_callback;
5015
5016   acc.length = 0;
5017   ud.acc = &acc;
5018
5019   CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, &ud));
5020
5021   open_sent_stream(session, 1);
5022
5023   CU_ASSERT(0 == nghttp2_submit_data(session, NGHTTP2_FLAG_NONE, 1, &data_prd));
5024   CU_ASSERT(0 == nghttp2_session_send(session));
5025
5026   /* We should have sent 2 DATA frame with 16 bytes payload each */
5027   CU_ASSERT(NGHTTP2_FRAME_HDLEN * 2 + 16 * 2 == acc.length);
5028
5029   nghttp2_session_del(session);
5030 }
5031
5032 void test_nghttp2_submit_request_with_data(void) {
5033   nghttp2_session *session;
5034   nghttp2_session_callbacks callbacks;
5035   nghttp2_data_provider data_prd;
5036   my_user_data ud;
5037   nghttp2_outbound_item *item;
5038   nghttp2_mem *mem;
5039
5040   mem = nghttp2_mem_default();
5041
5042   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
5043   callbacks.send_callback = null_send_callback;
5044
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),
5049                                         &data_prd, NULL));
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,
5053                   mem);
5054   CU_ASSERT(0 == nghttp2_session_send(session));
5055   CU_ASSERT(0 == ud.data_source_length);
5056
5057   nghttp2_session_del(session);
5058
5059   /* nghttp2_submit_request() with server session is error */
5060   nghttp2_session_server_new(&session, &callbacks, NULL);
5061
5062   CU_ASSERT(NGHTTP2_ERR_PROTO == nghttp2_submit_request(session, NULL, reqnv,
5063                                                         ARRLEN(reqnv), NULL,
5064                                                         NULL));
5065
5066   nghttp2_session_del(session);
5067 }
5068
5069 void test_nghttp2_submit_request_without_data(void) {
5070   nghttp2_session *session;
5071   nghttp2_session_callbacks callbacks;
5072   accumulator acc;
5073   nghttp2_data_provider data_prd = {{-1}, NULL};
5074   nghttp2_outbound_item *item;
5075   my_user_data ud;
5076   nghttp2_frame frame;
5077   nghttp2_hd_inflater inflater;
5078   nva_out out;
5079   nghttp2_bufs bufs;
5080   nghttp2_mem *mem;
5081   nghttp2_priority_spec pri_spec;
5082
5083   mem = nghttp2_mem_default();
5084   frame_pack_bufs_init(&bufs);
5085
5086   nva_out_init(&out);
5087   acc.length = 0;
5088   ud.acc = &acc;
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));
5092
5093   nghttp2_hd_inflate_init(&inflater, mem);
5094   CU_ASSERT(1 == nghttp2_submit_request(session, NULL, reqnv, ARRLEN(reqnv),
5095                                         &data_prd, NULL));
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,
5099                   mem);
5100   CU_ASSERT(item->frame.hd.flags & NGHTTP2_FLAG_END_STREAM);
5101
5102   CU_ASSERT(0 == nghttp2_session_send(session));
5103   CU_ASSERT(0 == unpack_frame(&frame, acc.buf, acc.length));
5104
5105   nghttp2_bufs_add(&bufs, acc.buf, acc.length);
5106   inflate_hd(&inflater, &out, &bufs, NGHTTP2_FRAME_HDLEN, mem);
5107
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);
5112
5113   nghttp2_bufs_free(&bufs);
5114   nghttp2_hd_inflate_free(&inflater);
5115
5116   /* Try to depend on itself is error */
5117   nghttp2_priority_spec_init(&pri_spec, (int32_t)session->next_stream_id, 16,
5118                              0);
5119
5120   CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT ==
5121             nghttp2_submit_request(session, &pri_spec, reqnv, ARRLEN(reqnv),
5122                                    NULL, NULL));
5123
5124   nghttp2_session_del(session);
5125 }
5126
5127 void test_nghttp2_submit_response_with_data(void) {
5128   nghttp2_session *session;
5129   nghttp2_session_callbacks callbacks;
5130   nghttp2_data_provider data_prd;
5131   my_user_data ud;
5132   nghttp2_outbound_item *item;
5133   nghttp2_mem *mem;
5134
5135   mem = nghttp2_mem_default();
5136
5137   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
5138   callbacks.send_callback = null_send_callback;
5139
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),
5145                                          &data_prd));
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,
5149                   mem);
5150   CU_ASSERT(0 == nghttp2_session_send(session));
5151   CU_ASSERT(0 == ud.data_source_length);
5152
5153   nghttp2_session_del(session);
5154
5155   /* Various error cases */
5156   nghttp2_session_client_new(&session, &callbacks, NULL);
5157
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));
5161
5162   /* Stream ID <= 0 is error */
5163   CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT ==
5164             nghttp2_submit_response(session, 0, resnv, ARRLEN(resnv), NULL));
5165
5166   nghttp2_session_del(session);
5167 }
5168
5169 void test_nghttp2_submit_response_without_data(void) {
5170   nghttp2_session *session;
5171   nghttp2_session_callbacks callbacks;
5172   accumulator acc;
5173   nghttp2_data_provider data_prd = {{-1}, NULL};
5174   nghttp2_outbound_item *item;
5175   my_user_data ud;
5176   nghttp2_frame frame;
5177   nghttp2_hd_inflater inflater;
5178   nva_out out;
5179   nghttp2_bufs bufs;
5180   nghttp2_mem *mem;
5181
5182   mem = nghttp2_mem_default();
5183   frame_pack_bufs_init(&bufs);
5184
5185   nva_out_init(&out);
5186   acc.length = 0;
5187   ud.acc = &acc;
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));
5191
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),
5195                                          &data_prd));
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,
5199                   mem);
5200   CU_ASSERT(item->frame.hd.flags & NGHTTP2_FLAG_END_STREAM);
5201
5202   CU_ASSERT(0 == nghttp2_session_send(session));
5203   CU_ASSERT(0 == unpack_frame(&frame, acc.buf, acc.length));
5204
5205   nghttp2_bufs_add(&bufs, acc.buf, acc.length);
5206   inflate_hd(&inflater, &out, &bufs, NGHTTP2_FRAME_HDLEN, mem);
5207
5208   CU_ASSERT(ARRLEN(resnv) == out.nvlen);
5209   assert_nv_equal(resnv, out.nva, out.nvlen, mem);
5210
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);
5216 }
5217
5218 void test_nghttp2_submit_response_push_response(void) {
5219   nghttp2_session *session;
5220   nghttp2_session_callbacks callbacks;
5221   my_user_data ud;
5222
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;
5226
5227   nghttp2_session_server_new(&session, &callbacks, &ud);
5228
5229   open_sent_stream2(session, 2, NGHTTP2_STREAM_RESERVED);
5230
5231   session->goaway_flags |= NGHTTP2_GOAWAY_RECV;
5232
5233   CU_ASSERT(0 ==
5234             nghttp2_submit_response(session, 2, resnv, ARRLEN(resnv), NULL));
5235
5236   ud.frame_not_send_cb_called = 0;
5237
5238   CU_ASSERT(0 == nghttp2_session_send(session));
5239   CU_ASSERT(1 == ud.frame_not_send_cb_called);
5240
5241   nghttp2_session_del(session);
5242 }
5243
5244 void test_nghttp2_submit_trailer(void) {
5245   nghttp2_session *session;
5246   nghttp2_session_callbacks callbacks;
5247   accumulator acc;
5248   nghttp2_data_provider data_prd;
5249   nghttp2_outbound_item *item;
5250   my_user_data ud;
5251   nghttp2_frame frame;
5252   nghttp2_hd_inflater inflater;
5253   nva_out out;
5254   nghttp2_bufs bufs;
5255   nghttp2_mem *mem;
5256
5257   mem = nghttp2_mem_default();
5258   frame_pack_bufs_init(&bufs);
5259
5260   data_prd.read_callback = no_end_stream_data_source_read_callback;
5261   nva_out_init(&out);
5262   acc.length = 0;
5263   ud.acc = &acc;
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));
5267
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),
5271                                          &data_prd));
5272   CU_ASSERT(0 == nghttp2_session_send(session));
5273
5274   CU_ASSERT(0 ==
5275             nghttp2_submit_trailer(session, 1, trailernv, ARRLEN(trailernv)));
5276
5277   session->callbacks.send_callback = accumulator_send_callback;
5278
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);
5283
5284   CU_ASSERT(0 == nghttp2_session_send(session));
5285   CU_ASSERT(0 == unpack_frame(&frame, acc.buf, acc.length));
5286
5287   nghttp2_bufs_add(&bufs, acc.buf, acc.length);
5288   inflate_hd(&inflater, &out, &bufs, NGHTTP2_FRAME_HDLEN, mem);
5289
5290   CU_ASSERT(ARRLEN(trailernv) == out.nvlen);
5291   assert_nv_equal(trailernv, out.nva, out.nvlen, mem);
5292
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);
5298
5299   /* Specifying stream ID <= 0 is error */
5300   nghttp2_session_server_new(&session, &callbacks, NULL);
5301   open_recv_stream(session, 1);
5302
5303   CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT ==
5304             nghttp2_submit_trailer(session, 0, trailernv, ARRLEN(trailernv)));
5305
5306   CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT ==
5307             nghttp2_submit_trailer(session, -1, trailernv, ARRLEN(trailernv)));
5308
5309   nghttp2_session_del(session);
5310 }
5311
5312 void test_nghttp2_submit_headers_start_stream(void) {
5313   nghttp2_session *session;
5314   nghttp2_session_callbacks callbacks;
5315   nghttp2_outbound_item *item;
5316   nghttp2_mem *mem;
5317
5318   mem = nghttp2_mem_default();
5319
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,
5327                   mem);
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));
5331
5332   nghttp2_session_del(session);
5333 }
5334
5335 void test_nghttp2_submit_headers_reply(void) {
5336   nghttp2_session *session;
5337   nghttp2_session_callbacks callbacks;
5338   my_user_data ud;
5339   nghttp2_outbound_item *item;
5340   nghttp2_stream *stream;
5341   nghttp2_mem *mem;
5342
5343   mem = nghttp2_mem_default();
5344
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;
5348
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,
5355                   mem);
5356   CU_ASSERT((NGHTTP2_FLAG_END_STREAM | NGHTTP2_FLAG_END_HEADERS) ==
5357             item->frame.hd.flags);
5358
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
5362      open. */
5363   CU_ASSERT(0 == nghttp2_session_send(session));
5364   CU_ASSERT(0 == ud.frame_send_cb_called);
5365
5366   stream = open_recv_stream2(session, 1, NGHTTP2_STREAM_OPENING);
5367
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);
5374
5375   nghttp2_session_del(session);
5376 }
5377
5378 void test_nghttp2_submit_headers_push_reply(void) {
5379   nghttp2_session *session;
5380   nghttp2_session_callbacks callbacks;
5381   my_user_data ud;
5382   nghttp2_stream *stream;
5383   int foo;
5384
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;
5388
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));
5393
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);
5401
5402   nghttp2_session_del(session);
5403
5404   /* Sending HEADERS from client against stream in reserved state is
5405      error */
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));
5410
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);
5415
5416   nghttp2_session_del(session);
5417 }
5418
5419 void test_nghttp2_submit_headers(void) {
5420   nghttp2_session *session;
5421   nghttp2_session_callbacks callbacks;
5422   my_user_data ud;
5423   nghttp2_outbound_item *item;
5424   nghttp2_stream *stream;
5425   accumulator acc;
5426   nghttp2_frame frame;
5427   nghttp2_hd_inflater inflater;
5428   nva_out out;
5429   nghttp2_bufs bufs;
5430   nghttp2_mem *mem;
5431   nghttp2_priority_spec pri_spec;
5432
5433   mem = nghttp2_mem_default();
5434   frame_pack_bufs_init(&bufs);
5435
5436   nva_out_init(&out);
5437   acc.length = 0;
5438   ud.acc = &acc;
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;
5442
5443   CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, &ud));
5444
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,
5451                   mem);
5452   CU_ASSERT((NGHTTP2_FLAG_END_STREAM | NGHTTP2_FLAG_END_HEADERS) ==
5453             item->frame.hd.flags);
5454
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
5458      open. */
5459   CU_ASSERT(0 == nghttp2_session_send(session));
5460   CU_ASSERT(0 == ud.frame_send_cb_called);
5461
5462   stream = open_sent_stream(session, 1);
5463
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);
5470
5471   CU_ASSERT(0 == unpack_frame(&frame, acc.buf, acc.length));
5472
5473   nghttp2_bufs_add(&bufs, acc.buf, acc.length);
5474   inflate_hd(&inflater, &out, &bufs, NGHTTP2_FRAME_HDLEN, mem);
5475
5476   CU_ASSERT(ARRLEN(reqnv) == out.nvlen);
5477   assert_nv_equal(reqnv, out.nva, out.nvlen, mem);
5478
5479   nva_out_reset(&out, mem);
5480   nghttp2_bufs_free(&bufs);
5481   nghttp2_frame_headers_free(&frame.headers, mem);
5482
5483   nghttp2_hd_inflate_free(&inflater);
5484
5485   /* Try to depend on itself */
5486   nghttp2_priority_spec_init(&pri_spec, 3, 16, 0);
5487
5488   CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT ==
5489             nghttp2_submit_headers(session, NGHTTP2_FLAG_NONE, 3, &pri_spec,
5490                                    reqnv, ARRLEN(reqnv), NULL));
5491
5492   session->next_stream_id = 5;
5493   nghttp2_priority_spec_init(&pri_spec, 5, 16, 0);
5494
5495   CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT ==
5496             nghttp2_submit_headers(session, NGHTTP2_FLAG_NONE, -1, &pri_spec,
5497                                    reqnv, ARRLEN(reqnv), NULL));
5498
5499   nghttp2_session_del(session);
5500
5501   /* Error cases with invalid stream ID */
5502   nghttp2_session_server_new(&session, &callbacks, NULL);
5503
5504   /* Sending nghttp2_submit_headers() with stream_id == 1 and server
5505      session is error */
5506   CU_ASSERT(NGHTTP2_ERR_PROTO ==
5507             nghttp2_submit_headers(session, NGHTTP2_FLAG_NONE, -1, NULL, reqnv,
5508                                    ARRLEN(reqnv), NULL));
5509
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));
5514
5515   nghttp2_session_del(session);
5516 }
5517
5518 void test_nghttp2_submit_headers_continuation(void) {
5519   nghttp2_session *session;
5520   nghttp2_session_callbacks callbacks;
5521   nghttp2_nv nv[] = {
5522       MAKE_NV("h1", ""), MAKE_NV("h1", ""), MAKE_NV("h1", ""),
5523       MAKE_NV("h1", ""), MAKE_NV("h1", ""), MAKE_NV("h1", ""),
5524       MAKE_NV("h1", ""),
5525   };
5526   nghttp2_outbound_item *item;
5527   uint8_t data[4096];
5528   size_t i;
5529   my_user_data ud;
5530
5531   memset(data, '0', sizeof(data));
5532   for (i = 0; i < ARRLEN(nv); ++i) {
5533     nv[i].valuelen = sizeof(data);
5534     nv[i].value = data;
5535   }
5536
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;
5540
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));
5549
5550   ud.frame_send_cb_called = 0;
5551   CU_ASSERT(0 == nghttp2_session_send(session));
5552   CU_ASSERT(1 == ud.frame_send_cb_called);
5553
5554   nghttp2_session_del(session);
5555 }
5556
5557 void test_nghttp2_submit_headers_continuation_extra_large(void) {
5558   nghttp2_session *session;
5559   nghttp2_session_callbacks callbacks;
5560   nghttp2_nv nv[] = {
5561       MAKE_NV("h1", ""), MAKE_NV("h1", ""), MAKE_NV("h1", ""),
5562       MAKE_NV("h1", ""), MAKE_NV("h1", ""), MAKE_NV("h1", ""),
5563   };
5564   nghttp2_outbound_item *item;
5565   uint8_t data[16384];
5566   size_t i;
5567   my_user_data ud;
5568   nghttp2_option *opt;
5569
5570   memset(data, '0', sizeof(data));
5571   for (i = 0; i < ARRLEN(nv); ++i) {
5572     nv[i].valuelen = sizeof(data);
5573     nv[i].value = data;
5574   }
5575
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;
5579
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);
5584
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));
5593
5594   ud.frame_send_cb_called = 0;
5595   CU_ASSERT(0 == nghttp2_session_send(session));
5596   CU_ASSERT(1 == ud.frame_send_cb_called);
5597
5598   nghttp2_session_del(session);
5599   nghttp2_option_del(opt);
5600 }
5601
5602 void test_nghttp2_submit_priority(void) {
5603   nghttp2_session *session;
5604   nghttp2_session_callbacks callbacks;
5605   nghttp2_stream *stream;
5606   my_user_data ud;
5607   nghttp2_priority_spec pri_spec;
5608
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;
5612
5613   nghttp2_session_client_new(&session, &callbacks, &ud);
5614   stream = open_sent_stream(session, 1);
5615
5616   nghttp2_priority_spec_init(&pri_spec, 0, 3, 0);
5617
5618   /* depends on stream 0 */
5619   CU_ASSERT(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);
5623
5624   /* submit against idle stream */
5625   CU_ASSERT(0 ==
5626             nghttp2_submit_priority(session, NGHTTP2_FLAG_NONE, 3, &pri_spec));
5627
5628   ud.frame_send_cb_called = 0;
5629   CU_ASSERT(0 == nghttp2_session_send(session));
5630   CU_ASSERT(1 == ud.frame_send_cb_called);
5631
5632   nghttp2_session_del(session);
5633 }
5634
5635 void test_nghttp2_submit_settings(void) {
5636   nghttp2_session *session;
5637   nghttp2_session_callbacks callbacks;
5638   my_user_data ud;
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;
5644   nghttp2_mem *mem;
5645
5646   mem = nghttp2_mem_default();
5647
5648   iv[0].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS;
5649   iv[0].value = 5;
5650
5651   iv[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
5652   iv[1].value = 16 * 1024;
5653
5654   iv[2].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS;
5655   iv[2].value = 50;
5656
5657   iv[3].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
5658   iv[3].value = 111;
5659
5660   iv[4].settings_id = UNKNOWN_ID;
5661   iv[4].value = 999;
5662
5663   iv[5].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
5664   iv[5].value = 1023;
5665
5666   iv[6].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
5667   iv[6].value = (uint32_t)NGHTTP2_MAX_WINDOW_SIZE + 1;
5668
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);
5673
5674   CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT ==
5675             nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, iv, 7));
5676
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);
5682
5683   /* Now sends without 6th one */
5684   CU_ASSERT(0 == nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, iv, 6));
5685
5686   item = nghttp2_session_get_next_ob_item(session);
5687
5688   CU_ASSERT(NGHTTP2_SETTINGS == item->frame.hd.type);
5689
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);
5695
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);
5699
5700   CU_ASSERT(UNKNOWN_ID == frame->settings.iv[4].settings_id);
5701   CU_ASSERT(999 == frame->settings.iv[4].value);
5702
5703   ud.frame_send_cb_called = 0;
5704   CU_ASSERT(0 == nghttp2_session_send(session));
5705   CU_ASSERT(1 == ud.frame_send_cb_called);
5706
5707   CU_ASSERT(50 == session->pending_local_max_concurrent_stream);
5708
5709   /* before receiving SETTINGS ACK, local settings have still default
5710      values */
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));
5717
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);
5721
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);
5726
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));
5731
5732   /* We just keep the last seen value */
5733   CU_ASSERT(50 == session->pending_local_max_concurrent_stream);
5734
5735   nghttp2_session_del(session);
5736 }
5737
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;
5745   nghttp2_mem *mem;
5746   nghttp2_option *option;
5747
5748   mem = nghttp2_mem_default();
5749   nghttp2_frame_settings_init(&ack_frame.settings, NGHTTP2_FLAG_ACK, NULL, 0);
5750
5751   iv[0].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
5752   iv[0].value = 16 * 1024;
5753
5754   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
5755   callbacks.send_callback = null_send_callback;
5756
5757   nghttp2_session_server_new(&session, &callbacks, NULL);
5758
5759   stream = open_recv_stream(session, 1);
5760   stream->local_window_size = NGHTTP2_INITIAL_WINDOW_SIZE + 100;
5761   stream->recv_window_size = 32768;
5762
5763   open_recv_stream(session, 3);
5764
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));
5768
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);
5772
5773   stream = nghttp2_session_get_stream(session, 3);
5774   CU_ASSERT(16 * 1024 == stream->local_window_size);
5775
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);
5779
5780   nghttp2_session_del(session);
5781
5782   /* Without auto-window update */
5783   nghttp2_option_new(&option);
5784   nghttp2_option_set_no_auto_window_update(option, 1);
5785
5786   nghttp2_session_server_new2(&session, &callbacks, NULL, option);
5787
5788   nghttp2_option_del(option);
5789
5790   stream = open_recv_stream(session, 1);
5791   stream->local_window_size = NGHTTP2_INITIAL_WINDOW_SIZE + 100;
5792   stream->recv_window_size = 32768;
5793
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));
5797
5798   stream = nghttp2_session_get_stream(session, 1);
5799
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 <
5803      recv_window_size */
5804   CU_ASSERT(0 == nghttp2_session_get_stream_local_window_size(session, 1));
5805
5806   nghttp2_session_del(session);
5807
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;
5813
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));
5817
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);
5821
5822   nghttp2_session_del(session);
5823   nghttp2_frame_settings_free(&ack_frame.settings, mem);
5824 }
5825
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;
5832
5833   memset(&callbacks, 0, sizeof(callbacks));
5834   callbacks.send_callback = null_send_callback;
5835
5836   nghttp2_session_client_new(&session, &callbacks, NULL);
5837
5838   /* first SETTINGS */
5839   iv[0].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS;
5840   iv[0].value = 100;
5841
5842   iv[1].settings_id = NGHTTP2_SETTINGS_ENABLE_PUSH;
5843   iv[1].value = 0;
5844
5845   CU_ASSERT(0 == nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, iv, 2));
5846
5847   inflight_settings = session->inflight_settings_head;
5848
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);
5855
5856   CU_ASSERT(100 == session->pending_local_max_concurrent_stream);
5857   CU_ASSERT(0 == session->pending_enable_push);
5858
5859   /* second SETTINGS */
5860   iv[0].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS;
5861   iv[0].value = 99;
5862
5863   CU_ASSERT(0 == nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, iv, 1));
5864
5865   inflight_settings = session->inflight_settings_head->next;
5866
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);
5873
5874   CU_ASSERT(99 == session->pending_local_max_concurrent_stream);
5875   CU_ASSERT(0 == session->pending_enable_push);
5876
5877   nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_ACK, NULL, 0);
5878
5879   /* receive SETTINGS ACK */
5880   CU_ASSERT(0 == nghttp2_session_on_settings_received(session, &frame, 0));
5881
5882   inflight_settings = session->inflight_settings_head;
5883
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);
5891
5892   CU_ASSERT(100 == session->local_settings.max_concurrent_streams);
5893
5894   /* receive SETTINGS ACK again */
5895   CU_ASSERT(0 == nghttp2_session_on_settings_received(session, &frame, 0));
5896
5897   CU_ASSERT(NULL == session->inflight_settings_head);
5898   CU_ASSERT(99 == session->local_settings.max_concurrent_streams);
5899
5900   nghttp2_session_del(session);
5901 }
5902
5903 void test_nghttp2_submit_push_promise(void) {
5904   nghttp2_session *session;
5905   nghttp2_session_callbacks callbacks;
5906   my_user_data ud;
5907   nghttp2_stream *stream;
5908
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;
5913
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));
5918
5919   stream = nghttp2_session_get_stream(session, 2);
5920
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));
5924
5925   ud.frame_send_cb_called = 0;
5926   ud.sent_frame_type = 0;
5927
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);
5931
5932   stream = nghttp2_session_get_stream(session, 2);
5933
5934   CU_ASSERT(NGHTTP2_STREAM_RESERVED == stream->state);
5935   CU_ASSERT(&ud == nghttp2_session_get_stream_user_data(session, 2));
5936
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));
5941
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));
5946
5947   nghttp2_session_del(session);
5948 }
5949
5950 void test_nghttp2_submit_window_update(void) {
5951   nghttp2_session *session;
5952   nghttp2_session_callbacks callbacks;
5953   my_user_data ud;
5954   nghttp2_outbound_item *item;
5955   nghttp2_stream *stream;
5956
5957   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
5958   callbacks.send_callback = null_send_callback;
5959
5960   nghttp2_session_client_new(&session, &callbacks, &ud);
5961   stream = open_recv_stream(session, 2);
5962   stream->recv_window_size = 4096;
5963
5964   CU_ASSERT(0 ==
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);
5971
5972   CU_ASSERT(0 ==
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);
5979
5980   CU_ASSERT(0 ==
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);
5987
5988   CU_ASSERT(0 ==
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
5991      time */
5992   CU_ASSERT(0 ==
5993             nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 4, 4096));
5994
5995   nghttp2_session_del(session);
5996 }
5997
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;
6003
6004   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6005   callbacks.send_callback = null_send_callback;
6006
6007   nghttp2_session_client_new(&session, &callbacks, NULL);
6008   stream = open_recv_stream(session, 2);
6009   stream->recv_window_size = 4096;
6010
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);
6018
6019   CU_ASSERT(0 == nghttp2_session_send(session));
6020
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);
6028
6029   item = nghttp2_session_get_next_ob_item(session);
6030   CU_ASSERT(item == NULL);
6031
6032   /* Increase local window size */
6033   CU_ASSERT(0 ==
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));
6039
6040   CU_ASSERT(NGHTTP2_ERR_FLOW_CONTROL ==
6041             nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 2,
6042                                          NGHTTP2_MAX_WINDOW_SIZE));
6043
6044   CU_ASSERT(0 == nghttp2_session_send(session));
6045
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);
6056
6057   CU_ASSERT(0 == nghttp2_session_send(session));
6058
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);
6068
6069   /* Increase local window size */
6070   CU_ASSERT(0 ==
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));
6076
6077   CU_ASSERT(NGHTTP2_ERR_FLOW_CONTROL ==
6078             nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 0,
6079                                          NGHTTP2_MAX_WINDOW_SIZE));
6080
6081   nghttp2_session_del(session);
6082 }
6083
6084 void test_nghttp2_submit_shutdown_notice(void) {
6085   nghttp2_session *session;
6086   nghttp2_session_callbacks callbacks;
6087   my_user_data ud;
6088
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;
6093
6094   nghttp2_session_server_new(&session, &callbacks, &ud);
6095
6096   CU_ASSERT(0 == nghttp2_submit_shutdown_notice(session));
6097
6098   ud.frame_send_cb_called = 0;
6099
6100   nghttp2_session_send(session);
6101
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);
6105
6106   /* After another GOAWAY, nghttp2_submit_shutdown_notice() is
6107      noop. */
6108   CU_ASSERT(0 == nghttp2_session_terminate_session(session, NGHTTP2_NO_ERROR));
6109
6110   ud.frame_send_cb_called = 0;
6111
6112   nghttp2_session_send(session);
6113
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);
6117
6118   CU_ASSERT(0 == nghttp2_submit_shutdown_notice(session));
6119
6120   ud.frame_send_cb_called = 0;
6121   ud.frame_not_send_cb_called = 0;
6122
6123   nghttp2_session_send(session);
6124
6125   CU_ASSERT(0 == ud.frame_send_cb_called);
6126   CU_ASSERT(0 == ud.frame_not_send_cb_called);
6127
6128   nghttp2_session_del(session);
6129
6130   /* Using nghttp2_submit_shutdown_notice() with client side session
6131      is error */
6132   nghttp2_session_client_new(&session, &callbacks, NULL);
6133
6134   CU_ASSERT(NGHTTP2_ERR_INVALID_STATE ==
6135             nghttp2_submit_shutdown_notice(session));
6136
6137   nghttp2_session_del(session);
6138 }
6139
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")};
6145
6146   /* Now invalid header name/value pair in HTTP/1.1 is accepted in
6147      nghttp2 */
6148
6149   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6150
6151   CU_ASSERT(0 == nghttp2_session_server_new(&session, &callbacks, NULL));
6152
6153   /* nghttp2_submit_response */
6154   CU_ASSERT(0 == nghttp2_submit_response(session, 2, empty_name_nv,
6155                                          ARRLEN(empty_name_nv), NULL));
6156
6157   /* nghttp2_submit_push_promise */
6158   open_recv_stream(session, 1);
6159
6160   CU_ASSERT(0 < nghttp2_submit_push_promise(session, NGHTTP2_FLAG_NONE, 1,
6161                                             empty_name_nv,
6162                                             ARRLEN(empty_name_nv), NULL));
6163
6164   nghttp2_session_del(session);
6165
6166   CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, NULL));
6167
6168   /* nghttp2_submit_request */
6169   CU_ASSERT(0 < nghttp2_submit_request(session, NULL, empty_name_nv,
6170                                        ARRLEN(empty_name_nv), NULL, NULL));
6171
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),
6175                                        NULL));
6176
6177   nghttp2_session_del(session);
6178 }
6179
6180 void test_nghttp2_submit_extension(void) {
6181   nghttp2_session *session;
6182   nghttp2_session_callbacks callbacks;
6183   my_user_data ud;
6184   accumulator acc;
6185   nghttp2_mem *mem;
6186   const char data[] = "Hello World!";
6187   size_t len;
6188   int32_t stream_id;
6189   int rv;
6190
6191   mem = nghttp2_mem_default();
6192
6193   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6194
6195   callbacks.pack_extension_callback = pack_extension_callback;
6196   callbacks.send_callback = accumulator_send_callback;
6197
6198   nghttp2_buf_init2(&ud.scratchbuf, 4096, mem);
6199
6200   nghttp2_session_client_new(&session, &callbacks, &ud);
6201
6202   ud.scratchbuf.last = nghttp2_cpymem(ud.scratchbuf.last, data, sizeof(data));
6203   ud.acc = &acc;
6204
6205   rv = nghttp2_submit_extension(session, 211, 0x01, 3, &ud.scratchbuf);
6206
6207   CU_ASSERT(0 == rv);
6208
6209   acc.length = 0;
6210
6211   rv = nghttp2_session_send(session);
6212
6213   CU_ASSERT(0 == rv);
6214   CU_ASSERT(NGHTTP2_FRAME_HDLEN + sizeof(data) == acc.length);
6215
6216   len = nghttp2_get_uint32(acc.buf) >> 8;
6217
6218   CU_ASSERT(sizeof(data) == len);
6219   CU_ASSERT(211 == acc.buf[3]);
6220   CU_ASSERT(0x01 == acc.buf[4]);
6221
6222   stream_id = (int32_t)nghttp2_get_uint32(acc.buf + 5);
6223
6224   CU_ASSERT(3 == stream_id);
6225   CU_ASSERT(0 == memcmp(data, &acc.buf[NGHTTP2_FRAME_HDLEN], sizeof(data)));
6226
6227   nghttp2_session_del(session);
6228
6229   /* submitting standard HTTP/2 frame is error */
6230   nghttp2_session_server_new(&session, &callbacks, &ud);
6231
6232   rv = nghttp2_submit_extension(session, NGHTTP2_GOAWAY, NGHTTP2_FLAG_NONE, 0,
6233                                 NULL);
6234
6235   CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT == rv);
6236
6237   nghttp2_session_del(session);
6238   nghttp2_buf_free(&ud.scratchbuf, mem);
6239 }
6240
6241 void test_nghttp2_submit_altsvc(void) {
6242   nghttp2_session *session;
6243   nghttp2_session_callbacks callbacks;
6244   my_user_data ud;
6245   int rv;
6246   ssize_t len;
6247   const uint8_t *data;
6248   nghttp2_frame_hd hd;
6249   size_t origin_len;
6250   const uint8_t origin[] = "nghttp2.org";
6251   const uint8_t field_value[] = "h2=\":443\"";
6252
6253   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6254
6255   nghttp2_session_server_new(&session, &callbacks, &ud);
6256
6257   rv = nghttp2_submit_altsvc(session, NGHTTP2_FLAG_NONE, 0, origin,
6258                              sizeof(origin) - 1, field_value,
6259                              sizeof(field_value) - 1);
6260
6261   CU_ASSERT(0 == rv);
6262
6263   ud.frame_send_cb_called = 0;
6264
6265   len = nghttp2_session_mem_send(session, &data);
6266
6267   CU_ASSERT(len == NGHTTP2_FRAME_HDLEN + 2 + sizeof(origin) - 1 +
6268                        sizeof(field_value) - 1);
6269
6270   nghttp2_frame_unpack_frame_hd(&hd, data);
6271
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);
6275
6276   origin_len = nghttp2_get_uint16(data + NGHTTP2_FRAME_HDLEN);
6277
6278   CU_ASSERT(sizeof(origin) - 1 == origin_len);
6279   CU_ASSERT(0 ==
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));
6284
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);
6288
6289   CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT == rv);
6290
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);
6295
6296   CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT == rv);
6297
6298   nghttp2_session_del(session);
6299
6300   /* submitting from client side session is error */
6301   nghttp2_session_client_new(&session, &callbacks, NULL);
6302
6303   rv = nghttp2_submit_altsvc(session, NGHTTP2_FLAG_NONE, 0, origin,
6304                              sizeof(origin) - 1, field_value,
6305                              sizeof(field_value) - 1);
6306
6307   CU_ASSERT(NGHTTP2_ERR_INVALID_STATE == rv);
6308
6309   nghttp2_session_del(session);
6310 }
6311
6312 void test_nghttp2_submit_origin(void) {
6313   nghttp2_session *session;
6314   nghttp2_session_callbacks callbacks;
6315   my_user_data ud;
6316   int rv;
6317   ssize_t len;
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[] = {
6322       {
6323           (uint8_t *)nghttp2,
6324           sizeof(nghttp2) - 1,
6325       },
6326       {
6327           (uint8_t *)examples,
6328           sizeof(examples) - 1,
6329       },
6330   };
6331   nghttp2_frame frame;
6332   nghttp2_ext_origin origin;
6333   nghttp2_mem *mem;
6334
6335   mem = nghttp2_mem_default();
6336
6337   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6338   callbacks.on_frame_send_callback = on_frame_send_callback;
6339
6340   frame.ext.payload = &origin;
6341
6342   nghttp2_session_server_new(&session, &callbacks, &ud);
6343
6344   rv = nghttp2_submit_origin(session, NGHTTP2_FLAG_NONE, ov, 2);
6345
6346   CU_ASSERT(0 == rv);
6347
6348   ud.frame_send_cb_called = 0;
6349   len = nghttp2_session_mem_send(session, &data);
6350
6351   CU_ASSERT(len > 0);
6352   CU_ASSERT(1 == ud.frame_send_cb_called);
6353
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,
6357       mem);
6358
6359   CU_ASSERT(0 == rv);
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);
6367
6368   nghttp2_frame_origin_free(&frame.ext, mem);
6369
6370   nghttp2_session_del(session);
6371
6372   /* Submitting ORIGIN frame from client session is error */
6373   nghttp2_session_client_new(&session, &callbacks, NULL);
6374
6375   rv = nghttp2_submit_origin(session, NGHTTP2_FLAG_NONE, ov, 1);
6376
6377   CU_ASSERT(NGHTTP2_ERR_INVALID_STATE == rv);
6378
6379   nghttp2_session_del(session);
6380
6381   /* Submitting empty ORIGIN frame */
6382   nghttp2_session_server_new(&session, &callbacks, &ud);
6383
6384   rv = nghttp2_submit_origin(session, NGHTTP2_FLAG_NONE, NULL, 0);
6385
6386   CU_ASSERT(0 == rv);
6387
6388   ud.frame_send_cb_called = 0;
6389   len = nghttp2_session_mem_send(session, &data);
6390
6391   CU_ASSERT(len == NGHTTP2_FRAME_HDLEN);
6392   CU_ASSERT(1 == ud.frame_send_cb_called);
6393
6394   nghttp2_frame_unpack_frame_hd(&frame.hd, data);
6395
6396   CU_ASSERT(NGHTTP2_ORIGIN == frame.hd.type);
6397
6398   nghttp2_session_del(session);
6399 }
6400
6401 void test_nghttp2_submit_rst_stream(void) {
6402   nghttp2_session *session;
6403   nghttp2_session_callbacks callbacks;
6404   nghttp2_outbound_item *item;
6405   int rv;
6406   int32_t stream_id;
6407
6408   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6409
6410   /* Sending RST_STREAM to idle stream (local) is ignored */
6411   nghttp2_session_client_new(&session, &callbacks, NULL);
6412
6413   rv = nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, 1,
6414                                  NGHTTP2_NO_ERROR);
6415
6416   CU_ASSERT(0 == rv);
6417
6418   item = nghttp2_outbound_queue_top(&session->ob_reg);
6419
6420   CU_ASSERT(NULL == item);
6421
6422   nghttp2_session_del(session);
6423
6424   /* Sending RST_STREAM to idle stream (remote) is ignored */
6425   nghttp2_session_client_new(&session, &callbacks, NULL);
6426
6427   rv = nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, 2,
6428                                  NGHTTP2_NO_ERROR);
6429
6430   CU_ASSERT(0 == rv);
6431
6432   item = nghttp2_outbound_queue_top(&session->ob_reg);
6433
6434   CU_ASSERT(NULL == item);
6435
6436   nghttp2_session_del(session);
6437
6438   /* Sending RST_STREAM to non-idle stream (local) */
6439   nghttp2_session_client_new(&session, &callbacks, NULL);
6440
6441   open_sent_stream(session, 1);
6442
6443   rv = nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, 1,
6444                                  NGHTTP2_NO_ERROR);
6445
6446   CU_ASSERT(0 == rv);
6447
6448   item = nghttp2_outbound_queue_top(&session->ob_reg);
6449
6450   CU_ASSERT(NULL != item);
6451   CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
6452   CU_ASSERT(1 == item->frame.hd.stream_id);
6453
6454   nghttp2_session_del(session);
6455
6456   /* Sending RST_STREAM to non-idle stream (remote) */
6457   nghttp2_session_client_new(&session, &callbacks, NULL);
6458
6459   open_recv_stream(session, 2);
6460
6461   rv = nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, 2,
6462                                  NGHTTP2_NO_ERROR);
6463
6464   CU_ASSERT(0 == rv);
6465
6466   item = nghttp2_outbound_queue_top(&session->ob_reg);
6467
6468   CU_ASSERT(NULL != item);
6469   CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
6470   CU_ASSERT(2 == item->frame.hd.stream_id);
6471
6472   nghttp2_session_del(session);
6473
6474   /* Sending RST_STREAM to pending stream */
6475   nghttp2_session_client_new(&session, &callbacks, NULL);
6476
6477   stream_id =
6478       nghttp2_submit_request(session, NULL, reqnv, ARRLEN(reqnv), NULL, NULL);
6479
6480   CU_ASSERT(stream_id > 0);
6481
6482   item = nghttp2_outbound_queue_top(&session->ob_syn);
6483
6484   CU_ASSERT(NULL != item);
6485   CU_ASSERT(NGHTTP2_HEADERS == item->frame.hd.type);
6486   CU_ASSERT(0 == item->aux_data.headers.canceled);
6487
6488   rv = nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, stream_id,
6489                                  NGHTTP2_NO_ERROR);
6490
6491   CU_ASSERT(0 == rv);
6492
6493   item = nghttp2_outbound_queue_top(&session->ob_syn);
6494
6495   CU_ASSERT(NULL != item);
6496   CU_ASSERT(NGHTTP2_HEADERS == item->frame.hd.type);
6497   CU_ASSERT(1 == item->aux_data.headers.canceled);
6498
6499   nghttp2_session_del(session);
6500 }
6501
6502 void test_nghttp2_session_open_stream(void) {
6503   nghttp2_session *session;
6504   nghttp2_session_callbacks callbacks;
6505   nghttp2_stream *stream;
6506   nghttp2_priority_spec pri_spec;
6507
6508   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6509   nghttp2_session_server_new(&session, &callbacks, NULL);
6510
6511   nghttp2_priority_spec_init(&pri_spec, 0, 245, 0);
6512
6513   stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
6514                                        &pri_spec, NGHTTP2_STREAM_OPENED, NULL);
6515   CU_ASSERT(1 == session->num_incoming_streams);
6516   CU_ASSERT(0 == session->num_outgoing_streams);
6517   CU_ASSERT(NGHTTP2_STREAM_OPENED == stream->state);
6518   CU_ASSERT(245 == stream->weight);
6519   CU_ASSERT(&session->root == stream->dep_prev);
6520   CU_ASSERT(NGHTTP2_SHUT_NONE == stream->shut_flags);
6521
6522   stream = nghttp2_session_open_stream(session, 2, NGHTTP2_STREAM_FLAG_NONE,
6523                                        &pri_spec_default,
6524                                        NGHTTP2_STREAM_OPENING, NULL);
6525   CU_ASSERT(1 == session->num_incoming_streams);
6526   CU_ASSERT(1 == session->num_outgoing_streams);
6527   CU_ASSERT(&session->root == stream->dep_prev);
6528   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == stream->weight);
6529   CU_ASSERT(NGHTTP2_SHUT_NONE == stream->shut_flags);
6530
6531   stream = nghttp2_session_open_stream(session, 4, NGHTTP2_STREAM_FLAG_NONE,
6532                                        &pri_spec_default,
6533                                        NGHTTP2_STREAM_RESERVED, NULL);
6534   CU_ASSERT(1 == session->num_incoming_streams);
6535   CU_ASSERT(1 == session->num_outgoing_streams);
6536   CU_ASSERT(&session->root == stream->dep_prev);
6537   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == stream->weight);
6538   CU_ASSERT(NGHTTP2_SHUT_RD == stream->shut_flags);
6539
6540   nghttp2_priority_spec_init(&pri_spec, 1, 17, 1);
6541
6542   stream = nghttp2_session_open_stream(session, 3, NGHTTP2_STREAM_FLAG_NONE,
6543                                        &pri_spec, NGHTTP2_STREAM_OPENED, NULL);
6544   CU_ASSERT(17 == stream->weight);
6545   CU_ASSERT(1 == stream->dep_prev->stream_id);
6546
6547   /* Dependency to idle stream */
6548   nghttp2_priority_spec_init(&pri_spec, 1000000007, 240, 1);
6549
6550   stream = nghttp2_session_open_stream(session, 5, NGHTTP2_STREAM_FLAG_NONE,
6551                                        &pri_spec, NGHTTP2_STREAM_OPENED, NULL);
6552   CU_ASSERT(240 == stream->weight);
6553   CU_ASSERT(1000000007 == stream->dep_prev->stream_id);
6554
6555   stream = nghttp2_session_get_stream_raw(session, 1000000007);
6556
6557   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == stream->weight);
6558   CU_ASSERT(&session->root == stream->dep_prev);
6559
6560   /* Dependency to closed stream which is not in dependency tree */
6561   session->last_recv_stream_id = 7;
6562
6563   nghttp2_priority_spec_init(&pri_spec, 7, 10, 0);
6564
6565   stream = nghttp2_session_open_stream(session, 9, NGHTTP2_FLAG_NONE, &pri_spec,
6566                                        NGHTTP2_STREAM_OPENED, NULL);
6567
6568   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == stream->weight);
6569   CU_ASSERT(&session->root == stream->dep_prev);
6570
6571   nghttp2_session_del(session);
6572
6573   nghttp2_session_client_new(&session, &callbacks, NULL);
6574   stream = nghttp2_session_open_stream(session, 4, NGHTTP2_STREAM_FLAG_NONE,
6575                                        &pri_spec_default,
6576                                        NGHTTP2_STREAM_RESERVED, NULL);
6577   CU_ASSERT(0 == session->num_incoming_streams);
6578   CU_ASSERT(0 == session->num_outgoing_streams);
6579   CU_ASSERT(&session->root == stream->dep_prev);
6580   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == stream->weight);
6581   CU_ASSERT(NGHTTP2_SHUT_WR == stream->shut_flags);
6582
6583   nghttp2_session_del(session);
6584 }
6585
6586 void test_nghttp2_session_open_stream_with_idle_stream_dep(void) {
6587   nghttp2_session *session;
6588   nghttp2_session_callbacks callbacks;
6589   nghttp2_stream *stream;
6590   nghttp2_priority_spec pri_spec;
6591
6592   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6593   nghttp2_session_server_new(&session, &callbacks, NULL);
6594
6595   /* Dependency to idle stream */
6596   nghttp2_priority_spec_init(&pri_spec, 101, 245, 0);
6597
6598   stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
6599                                        &pri_spec, NGHTTP2_STREAM_OPENED, NULL);
6600
6601   CU_ASSERT(245 == stream->weight);
6602   CU_ASSERT(101 == stream->dep_prev->stream_id);
6603
6604   stream = nghttp2_session_get_stream_raw(session, 101);
6605
6606   CU_ASSERT(NGHTTP2_STREAM_IDLE == stream->state);
6607   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == stream->weight);
6608
6609   nghttp2_priority_spec_init(&pri_spec, 211, 1, 0);
6610
6611   /* stream 101 was already created as idle. */
6612   stream = nghttp2_session_open_stream(session, 101, NGHTTP2_STREAM_FLAG_NONE,
6613                                        &pri_spec, NGHTTP2_STREAM_OPENED, NULL);
6614
6615   CU_ASSERT(1 == stream->weight);
6616   CU_ASSERT(211 == stream->dep_prev->stream_id);
6617
6618   stream = nghttp2_session_get_stream_raw(session, 211);
6619
6620   CU_ASSERT(NGHTTP2_STREAM_IDLE == stream->state);
6621   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == stream->weight);
6622
6623   nghttp2_session_del(session);
6624 }
6625
6626 void test_nghttp2_session_get_next_ob_item(void) {
6627   nghttp2_session *session;
6628   nghttp2_session_callbacks callbacks;
6629   nghttp2_priority_spec pri_spec;
6630
6631   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6632   callbacks.send_callback = null_send_callback;
6633
6634   nghttp2_session_client_new(&session, &callbacks, NULL);
6635   session->remote_settings.max_concurrent_streams = 2;
6636
6637   CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
6638   nghttp2_submit_ping(session, NGHTTP2_FLAG_NONE, NULL);
6639   CU_ASSERT(NGHTTP2_PING ==
6640             nghttp2_session_get_next_ob_item(session)->frame.hd.type);
6641
6642   CU_ASSERT(1 == nghttp2_submit_request(session, NULL, NULL, 0, NULL, NULL));
6643   CU_ASSERT(NGHTTP2_PING ==
6644             nghttp2_session_get_next_ob_item(session)->frame.hd.type);
6645
6646   CU_ASSERT(0 == nghttp2_session_send(session));
6647   CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
6648
6649   /* Incoming stream does not affect the number of outgoing max
6650      concurrent streams. */
6651   open_recv_stream(session, 2);
6652
6653   nghttp2_priority_spec_init(&pri_spec, 0, NGHTTP2_MAX_WEIGHT, 0);
6654
6655   CU_ASSERT(3 ==
6656             nghttp2_submit_request(session, &pri_spec, NULL, 0, NULL, NULL));
6657   CU_ASSERT(NGHTTP2_HEADERS ==
6658             nghttp2_session_get_next_ob_item(session)->frame.hd.type);
6659   CU_ASSERT(0 == nghttp2_session_send(session));
6660
6661   CU_ASSERT(5 ==
6662             nghttp2_submit_request(session, &pri_spec, NULL, 0, NULL, NULL));
6663   CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
6664
6665   session->remote_settings.max_concurrent_streams = 3;
6666
6667   CU_ASSERT(NGHTTP2_HEADERS ==
6668             nghttp2_session_get_next_ob_item(session)->frame.hd.type);
6669
6670   nghttp2_session_del(session);
6671
6672   /* Check that push reply HEADERS are queued into ob_ss_pq */
6673   nghttp2_session_server_new(&session, &callbacks, NULL);
6674   session->remote_settings.max_concurrent_streams = 0;
6675   open_sent_stream2(session, 2, NGHTTP2_STREAM_RESERVED);
6676   CU_ASSERT(0 == nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, 2,
6677                                         NULL, NULL, 0, NULL));
6678   CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
6679   CU_ASSERT(1 == nghttp2_outbound_queue_size(&session->ob_syn));
6680   nghttp2_session_del(session);
6681 }
6682
6683 void test_nghttp2_session_pop_next_ob_item(void) {
6684   nghttp2_session *session;
6685   nghttp2_session_callbacks callbacks;
6686   nghttp2_outbound_item *item;
6687   nghttp2_priority_spec pri_spec;
6688   nghttp2_mem *mem;
6689
6690   mem = nghttp2_mem_default();
6691   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6692   callbacks.send_callback = null_send_callback;
6693
6694   nghttp2_session_client_new(&session, &callbacks, NULL);
6695   session->remote_settings.max_concurrent_streams = 1;
6696
6697   CU_ASSERT(NULL == nghttp2_session_pop_next_ob_item(session));
6698
6699   nghttp2_submit_ping(session, NGHTTP2_FLAG_NONE, NULL);
6700
6701   nghttp2_priority_spec_init(&pri_spec, 0, 254, 0);
6702
6703   nghttp2_submit_request(session, &pri_spec, NULL, 0, NULL, NULL);
6704
6705   item = nghttp2_session_pop_next_ob_item(session);
6706   CU_ASSERT(NGHTTP2_PING == item->frame.hd.type);
6707   nghttp2_outbound_item_free(item, mem);
6708   mem->free(item, NULL);
6709
6710   item = nghttp2_session_pop_next_ob_item(session);
6711   CU_ASSERT(NGHTTP2_HEADERS == item->frame.hd.type);
6712   nghttp2_outbound_item_free(item, mem);
6713   mem->free(item, NULL);
6714
6715   CU_ASSERT(NULL == nghttp2_session_pop_next_ob_item(session));
6716
6717   /* Incoming stream does not affect the number of outgoing max
6718      concurrent streams. */
6719   open_recv_stream(session, 4);
6720   /* In-flight outgoing stream */
6721   open_sent_stream(session, 1);
6722
6723   nghttp2_priority_spec_init(&pri_spec, 0, NGHTTP2_MAX_WEIGHT, 0);
6724
6725   nghttp2_submit_request(session, &pri_spec, NULL, 0, NULL, NULL);
6726
6727   CU_ASSERT(NULL == nghttp2_session_pop_next_ob_item(session));
6728
6729   session->remote_settings.max_concurrent_streams = 2;
6730
6731   item = nghttp2_session_pop_next_ob_item(session);
6732   CU_ASSERT(NGHTTP2_HEADERS == item->frame.hd.type);
6733   nghttp2_outbound_item_free(item, mem);
6734   mem->free(item, NULL);
6735
6736   nghttp2_session_del(session);
6737
6738   /* Check that push reply HEADERS are queued into ob_ss_pq */
6739   nghttp2_session_server_new(&session, &callbacks, NULL);
6740   session->remote_settings.max_concurrent_streams = 0;
6741   open_sent_stream2(session, 2, NGHTTP2_STREAM_RESERVED);
6742   CU_ASSERT(0 == nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, 2,
6743                                         NULL, NULL, 0, NULL));
6744   CU_ASSERT(NULL == nghttp2_session_pop_next_ob_item(session));
6745   CU_ASSERT(1 == nghttp2_outbound_queue_size(&session->ob_syn));
6746   nghttp2_session_del(session);
6747 }
6748
6749 void test_nghttp2_session_reply_fail(void) {
6750   nghttp2_session *session;
6751   nghttp2_session_callbacks callbacks;
6752   nghttp2_data_provider data_prd;
6753   my_user_data ud;
6754
6755   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6756   callbacks.send_callback = fail_send_callback;
6757
6758   data_prd.read_callback = fixed_length_data_source_read_callback;
6759   ud.data_source_length = 4 * 1024;
6760   CU_ASSERT(0 == nghttp2_session_server_new(&session, &callbacks, &ud));
6761   open_recv_stream2(session, 1, NGHTTP2_STREAM_OPENING);
6762   CU_ASSERT(0 == nghttp2_submit_response(session, 1, NULL, 0, &data_prd));
6763   CU_ASSERT(NGHTTP2_ERR_CALLBACK_FAILURE == nghttp2_session_send(session));
6764   nghttp2_session_del(session);
6765 }
6766
6767 void test_nghttp2_session_max_concurrent_streams(void) {
6768   nghttp2_session *session;
6769   nghttp2_session_callbacks callbacks;
6770   nghttp2_frame frame;
6771   nghttp2_outbound_item *item;
6772   nghttp2_mem *mem;
6773
6774   mem = nghttp2_mem_default();
6775   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6776   callbacks.send_callback = null_send_callback;
6777
6778   nghttp2_session_server_new(&session, &callbacks, NULL);
6779   open_recv_stream(session, 1);
6780
6781   /* Check un-ACKed SETTINGS_MAX_CONCURRENT_STREAMS */
6782   nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 3,
6783                              NGHTTP2_HCAT_HEADERS, NULL, NULL, 0);
6784   session->pending_local_max_concurrent_stream = 1;
6785
6786   CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
6787             nghttp2_session_on_request_headers_received(session, &frame));
6788
6789   item = nghttp2_outbound_queue_top(&session->ob_reg);
6790   CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
6791   CU_ASSERT(NGHTTP2_REFUSED_STREAM == item->frame.rst_stream.error_code);
6792
6793   CU_ASSERT(0 == nghttp2_session_send(session));
6794
6795   /* Check ACKed SETTINGS_MAX_CONCURRENT_STREAMS */
6796   session->local_settings.max_concurrent_streams = 1;
6797   frame.hd.stream_id = 5;
6798
6799   CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
6800             nghttp2_session_on_request_headers_received(session, &frame));
6801
6802   item = nghttp2_outbound_queue_top(&session->ob_reg);
6803   CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
6804   CU_ASSERT(NGHTTP2_PROTOCOL_ERROR == item->frame.goaway.error_code);
6805
6806   nghttp2_frame_headers_free(&frame.headers, mem);
6807   nghttp2_session_del(session);
6808 }
6809
6810 void test_nghttp2_session_stop_data_with_rst_stream(void) {
6811   nghttp2_session *session;
6812   nghttp2_session_callbacks callbacks;
6813   my_user_data ud;
6814   nghttp2_data_provider data_prd;
6815   nghttp2_frame frame;
6816
6817   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6818   callbacks.on_frame_send_callback = on_frame_send_callback;
6819   callbacks.send_callback = block_count_send_callback;
6820   data_prd.read_callback = fixed_length_data_source_read_callback;
6821
6822   ud.frame_send_cb_called = 0;
6823   ud.data_source_length = NGHTTP2_DATA_PAYLOADLEN * 4;
6824
6825   nghttp2_session_server_new(&session, &callbacks, &ud);
6826   open_recv_stream2(session, 1, NGHTTP2_STREAM_OPENING);
6827   nghttp2_submit_response(session, 1, NULL, 0, &data_prd);
6828
6829   ud.block_count = 2;
6830   /* Sends response HEADERS + DATA[0] */
6831   CU_ASSERT(0 == nghttp2_session_send(session));
6832   CU_ASSERT(NGHTTP2_DATA == ud.sent_frame_type);
6833   /* data for DATA[1] is read from data_prd but it is not sent */
6834   CU_ASSERT(ud.data_source_length == NGHTTP2_DATA_PAYLOADLEN * 2);
6835
6836   nghttp2_frame_rst_stream_init(&frame.rst_stream, 1, NGHTTP2_CANCEL);
6837   CU_ASSERT(0 == nghttp2_session_on_rst_stream_received(session, &frame));
6838   nghttp2_frame_rst_stream_free(&frame.rst_stream);
6839
6840   /* Big enough number to send all DATA frames potentially. */
6841   ud.block_count = 100;
6842   /* Nothing will be sent in the following call. */
6843   CU_ASSERT(0 == nghttp2_session_send(session));
6844   /* With RST_STREAM, stream is canceled and further DATA on that
6845      stream are not sent. */
6846   CU_ASSERT(ud.data_source_length == NGHTTP2_DATA_PAYLOADLEN * 2);
6847
6848   CU_ASSERT(NULL == nghttp2_session_get_stream(session, 1));
6849
6850   nghttp2_session_del(session);
6851 }
6852
6853 void test_nghttp2_session_defer_data(void) {
6854   nghttp2_session *session;
6855   nghttp2_session_callbacks callbacks;
6856   my_user_data ud;
6857   nghttp2_data_provider data_prd;
6858   nghttp2_outbound_item *item;
6859   nghttp2_stream *stream;
6860
6861   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6862   callbacks.on_frame_send_callback = on_frame_send_callback;
6863   callbacks.send_callback = block_count_send_callback;
6864   data_prd.read_callback = defer_data_source_read_callback;
6865
6866   ud.frame_send_cb_called = 0;
6867   ud.data_source_length = NGHTTP2_DATA_PAYLOADLEN * 4;
6868
6869   nghttp2_session_server_new(&session, &callbacks, &ud);
6870   stream = open_recv_stream2(session, 1, NGHTTP2_STREAM_OPENING);
6871
6872   session->remote_window_size = 1 << 20;
6873   stream->remote_window_size = 1 << 20;
6874
6875   nghttp2_submit_response(session, 1, NULL, 0, &data_prd);
6876
6877   ud.block_count = 1;
6878   /* Sends HEADERS reply */
6879   CU_ASSERT(0 == nghttp2_session_send(session));
6880   CU_ASSERT(NGHTTP2_HEADERS == ud.sent_frame_type);
6881   /* No data is read */
6882   CU_ASSERT(ud.data_source_length == NGHTTP2_DATA_PAYLOADLEN * 4);
6883
6884   ud.block_count = 1;
6885   nghttp2_submit_ping(session, NGHTTP2_FLAG_NONE, NULL);
6886   /* Sends PING */
6887   CU_ASSERT(0 == nghttp2_session_send(session));
6888   CU_ASSERT(NGHTTP2_PING == ud.sent_frame_type);
6889
6890   /* Resume deferred DATA */
6891   CU_ASSERT(0 == nghttp2_session_resume_data(session, 1));
6892   item = stream->item;
6893   item->aux_data.data.data_prd.read_callback =
6894       fixed_length_data_source_read_callback;
6895   ud.block_count = 1;
6896   /* Reads 2 DATA chunks */
6897   CU_ASSERT(0 == nghttp2_session_send(session));
6898   CU_ASSERT(ud.data_source_length == NGHTTP2_DATA_PAYLOADLEN * 2);
6899
6900   /* Deferred again */
6901   item->aux_data.data.data_prd.read_callback = defer_data_source_read_callback;
6902   /* This is needed since 16KiB block is already read and waiting to be
6903      sent. No read_callback invocation. */
6904   ud.block_count = 1;
6905   CU_ASSERT(0 == nghttp2_session_send(session));
6906   CU_ASSERT(ud.data_source_length == NGHTTP2_DATA_PAYLOADLEN * 2);
6907
6908   /* Resume deferred DATA */
6909   CU_ASSERT(0 == nghttp2_session_resume_data(session, 1));
6910   item->aux_data.data.data_prd.read_callback =
6911       fixed_length_data_source_read_callback;
6912   ud.block_count = 1;
6913   /* Reads 2 16KiB blocks */
6914   CU_ASSERT(0 == nghttp2_session_send(session));
6915   CU_ASSERT(ud.data_source_length == 0);
6916
6917   nghttp2_session_del(session);
6918 }
6919
6920 void test_nghttp2_session_flow_control(void) {
6921   nghttp2_session *session;
6922   nghttp2_session_callbacks callbacks;
6923   my_user_data ud;
6924   nghttp2_data_provider data_prd;
6925   nghttp2_frame frame;
6926   nghttp2_stream *stream;
6927   int32_t new_initial_window_size;
6928   nghttp2_settings_entry iv[1];
6929   nghttp2_frame settings_frame;
6930   nghttp2_mem *mem;
6931
6932   mem = nghttp2_mem_default();
6933   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6934   callbacks.send_callback = fixed_bytes_send_callback;
6935   callbacks.on_frame_send_callback = on_frame_send_callback;
6936   data_prd.read_callback = fixed_length_data_source_read_callback;
6937
6938   ud.frame_send_cb_called = 0;
6939   ud.data_source_length = 128 * 1024;
6940   /* Use smaller emission count so that we can check outbound flow
6941      control window calculation is correct. */
6942   ud.fixed_sendlen = 2 * 1024;
6943
6944   /* Initial window size to 64KiB - 1*/
6945   nghttp2_session_client_new(&session, &callbacks, &ud);
6946   /* Change it to 64KiB for easy calculation */
6947   session->remote_window_size = 64 * 1024;
6948   session->remote_settings.initial_window_size = 64 * 1024;
6949
6950   nghttp2_submit_request(session, NULL, NULL, 0, &data_prd, NULL);
6951
6952   /* Sends 64KiB - 1 data */
6953   CU_ASSERT(0 == nghttp2_session_send(session));
6954   CU_ASSERT(64 * 1024 == ud.data_source_length);
6955
6956   /* Back 32KiB in stream window */
6957   nghttp2_frame_window_update_init(&frame.window_update, NGHTTP2_FLAG_NONE, 1,
6958                                    32 * 1024);
6959   nghttp2_session_on_window_update_received(session, &frame);
6960
6961   /* Send nothing because of connection-level window */
6962   CU_ASSERT(0 == nghttp2_session_send(session));
6963   CU_ASSERT(64 * 1024 == ud.data_source_length);
6964
6965   /* Back 32KiB in connection-level window */
6966   frame.hd.stream_id = 0;
6967   nghttp2_session_on_window_update_received(session, &frame);
6968
6969   /* Sends another 32KiB data */
6970   CU_ASSERT(0 == nghttp2_session_send(session));
6971   CU_ASSERT(32 * 1024 == ud.data_source_length);
6972
6973   stream = nghttp2_session_get_stream(session, 1);
6974   /* Change initial window size to 16KiB. The window_size becomes
6975      negative. */
6976   new_initial_window_size = 16 * 1024;
6977   stream->remote_window_size =
6978       new_initial_window_size -
6979       ((int32_t)session->remote_settings.initial_window_size -
6980        stream->remote_window_size);
6981   session->remote_settings.initial_window_size =
6982       (uint32_t)new_initial_window_size;
6983   CU_ASSERT(-48 * 1024 == stream->remote_window_size);
6984
6985   /* Back 48KiB to stream window */
6986   frame.hd.stream_id = 1;
6987   frame.window_update.window_size_increment = 48 * 1024;
6988   nghttp2_session_on_window_update_received(session, &frame);
6989
6990   /* Nothing is sent because window_size is 0 */
6991   CU_ASSERT(0 == nghttp2_session_send(session));
6992   CU_ASSERT(32 * 1024 == ud.data_source_length);
6993
6994   /* Back 16KiB in stream window */
6995   frame.hd.stream_id = 1;
6996   frame.window_update.window_size_increment = 16 * 1024;
6997   nghttp2_session_on_window_update_received(session, &frame);
6998
6999   /* Back 24KiB in connection-level window */
7000   frame.hd.stream_id = 0;
7001   frame.window_update.window_size_increment = 24 * 1024;
7002   nghttp2_session_on_window_update_received(session, &frame);
7003
7004   /* Sends another 16KiB data */
7005   CU_ASSERT(0 == nghttp2_session_send(session));
7006   CU_ASSERT(16 * 1024 == ud.data_source_length);
7007
7008   /* Increase initial window size to 32KiB */
7009   iv[0].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
7010   iv[0].value = 32 * 1024;
7011
7012   nghttp2_frame_settings_init(&settings_frame.settings, NGHTTP2_FLAG_NONE,
7013                               dup_iv(iv, 1), 1);
7014   nghttp2_session_on_settings_received(session, &settings_frame, 1);
7015   nghttp2_frame_settings_free(&settings_frame.settings, mem);
7016
7017   /* Sends another 8KiB data */
7018   CU_ASSERT(0 == nghttp2_session_send(session));
7019   CU_ASSERT(8 * 1024 == ud.data_source_length);
7020
7021   /* Back 8KiB in connection-level window */
7022   frame.hd.stream_id = 0;
7023   frame.window_update.window_size_increment = 8 * 1024;
7024   nghttp2_session_on_window_update_received(session, &frame);
7025
7026   /* Sends last 8KiB data */
7027   CU_ASSERT(0 == nghttp2_session_send(session));
7028   CU_ASSERT(0 == ud.data_source_length);
7029   CU_ASSERT(nghttp2_session_get_stream(session, 1)->shut_flags &
7030             NGHTTP2_SHUT_WR);
7031
7032   nghttp2_frame_window_update_free(&frame.window_update);
7033   nghttp2_session_del(session);
7034 }
7035
7036 void test_nghttp2_session_flow_control_data_recv(void) {
7037   nghttp2_session *session;
7038   nghttp2_session_callbacks callbacks;
7039   uint8_t data[64 * 1024 + 16];
7040   nghttp2_frame_hd hd;
7041   nghttp2_outbound_item *item;
7042   nghttp2_stream *stream;
7043
7044   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7045   callbacks.send_callback = null_send_callback;
7046
7047   /* Initial window size to 64KiB - 1*/
7048   nghttp2_session_client_new(&session, &callbacks, NULL);
7049
7050   stream = open_sent_stream(session, 1);
7051
7052   nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_WR);
7053
7054   session->local_window_size = NGHTTP2_MAX_PAYLOADLEN;
7055   stream->local_window_size = NGHTTP2_MAX_PAYLOADLEN;
7056
7057   /* Create DATA frame */
7058   memset(data, 0, sizeof(data));
7059   nghttp2_frame_hd_init(&hd, NGHTTP2_MAX_PAYLOADLEN, NGHTTP2_DATA,
7060                         NGHTTP2_FLAG_END_STREAM, 1);
7061
7062   nghttp2_frame_pack_frame_hd(data, &hd);
7063   CU_ASSERT(NGHTTP2_MAX_PAYLOADLEN + NGHTTP2_FRAME_HDLEN ==
7064             nghttp2_session_mem_recv(
7065                 session, data, NGHTTP2_MAX_PAYLOADLEN + NGHTTP2_FRAME_HDLEN));
7066
7067   item = nghttp2_session_get_next_ob_item(session);
7068   /* Since this is the last frame, stream-level WINDOW_UPDATE is not
7069      issued, but connection-level is. */
7070   CU_ASSERT(NGHTTP2_WINDOW_UPDATE == item->frame.hd.type);
7071   CU_ASSERT(0 == item->frame.hd.stream_id);
7072   CU_ASSERT(NGHTTP2_MAX_PAYLOADLEN ==
7073             item->frame.window_update.window_size_increment);
7074
7075   CU_ASSERT(0 == nghttp2_session_send(session));
7076
7077   /* Receive DATA for closed stream. They are still subject to under
7078      connection-level flow control, since this situation arises when
7079      RST_STREAM is issued by the remote, but the local side keeps
7080      sending DATA frames. Without calculating connection-level window,
7081      the subsequent flow control gets confused. */
7082   CU_ASSERT(NGHTTP2_MAX_PAYLOADLEN + NGHTTP2_FRAME_HDLEN ==
7083             nghttp2_session_mem_recv(
7084                 session, data, NGHTTP2_MAX_PAYLOADLEN + NGHTTP2_FRAME_HDLEN));
7085
7086   item = nghttp2_session_get_next_ob_item(session);
7087   CU_ASSERT(NGHTTP2_WINDOW_UPDATE == item->frame.hd.type);
7088   CU_ASSERT(0 == item->frame.hd.stream_id);
7089   CU_ASSERT(NGHTTP2_MAX_PAYLOADLEN ==
7090             item->frame.window_update.window_size_increment);
7091
7092   nghttp2_session_del(session);
7093 }
7094
7095 void test_nghttp2_session_flow_control_data_with_padding_recv(void) {
7096   nghttp2_session *session;
7097   nghttp2_session_callbacks callbacks;
7098   uint8_t data[1024];
7099   nghttp2_frame_hd hd;
7100   nghttp2_stream *stream;
7101   nghttp2_option *option;
7102
7103   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7104   callbacks.send_callback = null_send_callback;
7105
7106   nghttp2_option_new(&option);
7107   /* Disable auto window update so that we can check padding is
7108      consumed automatically */
7109   nghttp2_option_set_no_auto_window_update(option, 1);
7110
7111   /* Initial window size to 64KiB - 1*/
7112   nghttp2_session_client_new2(&session, &callbacks, NULL, option);
7113
7114   nghttp2_option_del(option);
7115
7116   stream = open_sent_stream(session, 1);
7117
7118   /* Create DATA frame */
7119   memset(data, 0, sizeof(data));
7120   nghttp2_frame_hd_init(&hd, 357, NGHTTP2_DATA, NGHTTP2_FLAG_PADDED, 1);
7121
7122   nghttp2_frame_pack_frame_hd(data, &hd);
7123   /* Set Pad Length field, which itself is padding */
7124   data[NGHTTP2_FRAME_HDLEN] = 255;
7125
7126   CU_ASSERT(
7127       (ssize_t)(NGHTTP2_FRAME_HDLEN + hd.length) ==
7128       nghttp2_session_mem_recv(session, data, NGHTTP2_FRAME_HDLEN + hd.length));
7129
7130   CU_ASSERT((int32_t)hd.length == session->recv_window_size);
7131   CU_ASSERT((int32_t)hd.length == stream->recv_window_size);
7132   CU_ASSERT(256 == session->consumed_size);
7133   CU_ASSERT(256 == stream->consumed_size);
7134   CU_ASSERT(357 == session->recv_window_size);
7135   CU_ASSERT(357 == stream->recv_window_size);
7136
7137   /* Receive the same DATA frame, but in 2 parts: first 9 + 1 + 102
7138      bytes which includes 1st padding byte, and remainder */
7139   CU_ASSERT((ssize_t)(NGHTTP2_FRAME_HDLEN + 103) ==
7140             nghttp2_session_mem_recv(session, data, NGHTTP2_FRAME_HDLEN + 103));
7141   CU_ASSERT(258 == session->consumed_size);
7142   CU_ASSERT(258 == stream->consumed_size);
7143   CU_ASSERT(460 == session->recv_window_size);
7144   CU_ASSERT(460 == stream->recv_window_size);
7145
7146   /* 357 - 103 = 254 bytes left */
7147   CU_ASSERT(254 == nghttp2_session_mem_recv(session, data, 254));
7148   CU_ASSERT(512 == session->consumed_size);
7149   CU_ASSERT(512 == stream->consumed_size);
7150   CU_ASSERT(714 == session->recv_window_size);
7151   CU_ASSERT(714 == stream->recv_window_size);
7152
7153   /* Receive the same DATA frame, but in 2 parts: first 9 = 1 + 101
7154      bytes which only includes data without padding, 2nd part is
7155      padding only */
7156   CU_ASSERT((ssize_t)(NGHTTP2_FRAME_HDLEN + 102) ==
7157             nghttp2_session_mem_recv(session, data, NGHTTP2_FRAME_HDLEN + 102));
7158   CU_ASSERT(513 == session->consumed_size);
7159   CU_ASSERT(513 == stream->consumed_size);
7160   CU_ASSERT(816 == session->recv_window_size);
7161   CU_ASSERT(816 == stream->recv_window_size);
7162
7163   /* 357 - 102 = 255 bytes left */
7164   CU_ASSERT(255 == nghttp2_session_mem_recv(session, data, 255));
7165   CU_ASSERT(768 == session->consumed_size);
7166   CU_ASSERT(768 == stream->consumed_size);
7167   CU_ASSERT(1071 == session->recv_window_size);
7168   CU_ASSERT(1071 == stream->recv_window_size);
7169
7170   /* Receive the same DATA frame, but in 2 parts: first 9 = 1 + 50
7171      bytes which includes byte up to middle of data, 2nd part is the
7172      remainder */
7173   CU_ASSERT((ssize_t)(NGHTTP2_FRAME_HDLEN + 51) ==
7174             nghttp2_session_mem_recv(session, data, NGHTTP2_FRAME_HDLEN + 51));
7175   CU_ASSERT(769 == session->consumed_size);
7176   CU_ASSERT(769 == stream->consumed_size);
7177   CU_ASSERT(1122 == session->recv_window_size);
7178   CU_ASSERT(1122 == stream->recv_window_size);
7179
7180   /* 357 - 51 = 306 bytes left */
7181   CU_ASSERT(306 == nghttp2_session_mem_recv(session, data, 306));
7182   CU_ASSERT(1024 == session->consumed_size);
7183   CU_ASSERT(1024 == stream->consumed_size);
7184   CU_ASSERT(1428 == session->recv_window_size);
7185   CU_ASSERT(1428 == stream->recv_window_size);
7186
7187   nghttp2_session_del(session);
7188 }
7189
7190 void test_nghttp2_session_data_read_temporal_failure(void) {
7191   nghttp2_session *session;
7192   nghttp2_session_callbacks callbacks;
7193   my_user_data ud;
7194   nghttp2_data_provider data_prd;
7195   nghttp2_frame frame;
7196   nghttp2_stream *stream;
7197   size_t data_size = 128 * 1024;
7198
7199   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7200   callbacks.send_callback = null_send_callback;
7201   callbacks.on_frame_send_callback = on_frame_send_callback;
7202   data_prd.read_callback = fixed_length_data_source_read_callback;
7203
7204   ud.data_source_length = data_size;
7205
7206   /* Initial window size is 64KiB - 1 */
7207   nghttp2_session_client_new(&session, &callbacks, &ud);
7208   nghttp2_submit_request(session, NULL, NULL, 0, &data_prd, NULL);
7209
7210   /* Sends NGHTTP2_INITIAL_WINDOW_SIZE data, assuming, it is equal to
7211      or smaller than NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE */
7212   CU_ASSERT(0 == nghttp2_session_send(session));
7213   CU_ASSERT(data_size - NGHTTP2_INITIAL_WINDOW_SIZE == ud.data_source_length);
7214
7215   stream = nghttp2_session_get_stream(session, 1);
7216   CU_ASSERT(NGHTTP2_DATA == stream->item->frame.hd.type);
7217
7218   stream->item->aux_data.data.data_prd.read_callback =
7219       temporal_failure_data_source_read_callback;
7220
7221   /* Back NGHTTP2_INITIAL_WINDOW_SIZE to both connection-level and
7222      stream-wise window */
7223   nghttp2_frame_window_update_init(&frame.window_update, NGHTTP2_FLAG_NONE, 1,
7224                                    NGHTTP2_INITIAL_WINDOW_SIZE);
7225   nghttp2_session_on_window_update_received(session, &frame);
7226   frame.hd.stream_id = 0;
7227   nghttp2_session_on_window_update_received(session, &frame);
7228   nghttp2_frame_window_update_free(&frame.window_update);
7229
7230   /* Sending data will fail (soft fail) and treated as stream error */
7231   ud.frame_send_cb_called = 0;
7232   CU_ASSERT(0 == nghttp2_session_send(session));
7233   CU_ASSERT(data_size - NGHTTP2_INITIAL_WINDOW_SIZE == ud.data_source_length);
7234
7235   CU_ASSERT(1 == ud.frame_send_cb_called);
7236   CU_ASSERT(NGHTTP2_RST_STREAM == ud.sent_frame_type);
7237
7238   data_prd.read_callback = fail_data_source_read_callback;
7239   nghttp2_submit_request(session, NULL, NULL, 0, &data_prd, NULL);
7240   /* Sending data will fail (hard fail) and session tear down */
7241   CU_ASSERT(NGHTTP2_ERR_CALLBACK_FAILURE == nghttp2_session_send(session));
7242
7243   nghttp2_session_del(session);
7244 }
7245
7246 void test_nghttp2_session_on_stream_close(void) {
7247   nghttp2_session *session;
7248   nghttp2_session_callbacks callbacks;
7249   my_user_data user_data;
7250   nghttp2_stream *stream;
7251
7252   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7253   callbacks.on_stream_close_callback = on_stream_close_callback;
7254   user_data.stream_close_cb_called = 0;
7255
7256   nghttp2_session_client_new(&session, &callbacks, &user_data);
7257   stream =
7258       open_sent_stream3(session, 1, NGHTTP2_STREAM_FLAG_NONE, &pri_spec_default,
7259                         NGHTTP2_STREAM_OPENED, &user_data);
7260   CU_ASSERT(stream != NULL);
7261   CU_ASSERT(nghttp2_session_close_stream(session, 1, NGHTTP2_NO_ERROR) == 0);
7262   CU_ASSERT(user_data.stream_close_cb_called == 1);
7263   nghttp2_session_del(session);
7264 }
7265
7266 void test_nghttp2_session_on_ctrl_not_send(void) {
7267   nghttp2_session *session;
7268   nghttp2_session_callbacks callbacks;
7269   my_user_data user_data;
7270   nghttp2_stream *stream;
7271
7272   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7273   callbacks.on_frame_not_send_callback = on_frame_not_send_callback;
7274   callbacks.send_callback = null_send_callback;
7275   user_data.frame_not_send_cb_called = 0;
7276   user_data.not_sent_frame_type = 0;
7277   user_data.not_sent_error = 0;
7278
7279   nghttp2_session_server_new(&session, &callbacks, &user_data);
7280   stream =
7281       open_recv_stream3(session, 1, NGHTTP2_STREAM_FLAG_NONE, &pri_spec_default,
7282                         NGHTTP2_STREAM_OPENING, &user_data);
7283
7284   /* Check response HEADERS */
7285   /* Send bogus stream ID */
7286   CU_ASSERT(0 == nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, 3,
7287                                         NULL, NULL, 0, NULL));
7288   CU_ASSERT(0 == nghttp2_session_send(session));
7289   CU_ASSERT(1 == user_data.frame_not_send_cb_called);
7290   CU_ASSERT(NGHTTP2_HEADERS == user_data.not_sent_frame_type);
7291   CU_ASSERT(NGHTTP2_ERR_STREAM_CLOSED == user_data.not_sent_error);
7292
7293   user_data.frame_not_send_cb_called = 0;
7294   /* Shutdown transmission */
7295   stream->shut_flags |= NGHTTP2_SHUT_WR;
7296   CU_ASSERT(0 == nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, 1,
7297                                         NULL, NULL, 0, NULL));
7298   CU_ASSERT(0 == nghttp2_session_send(session));
7299   CU_ASSERT(1 == user_data.frame_not_send_cb_called);
7300   CU_ASSERT(NGHTTP2_HEADERS == user_data.not_sent_frame_type);
7301   CU_ASSERT(NGHTTP2_ERR_STREAM_SHUT_WR == user_data.not_sent_error);
7302
7303   stream->shut_flags = NGHTTP2_SHUT_NONE;
7304   user_data.frame_not_send_cb_called = 0;
7305   /* Queue RST_STREAM */
7306   CU_ASSERT(0 == nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, 1,
7307                                         NULL, NULL, 0, NULL));
7308   CU_ASSERT(0 == nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, 1,
7309                                            NGHTTP2_INTERNAL_ERROR));
7310   CU_ASSERT(0 == nghttp2_session_send(session));
7311   CU_ASSERT(1 == user_data.frame_not_send_cb_called);
7312   CU_ASSERT(NGHTTP2_HEADERS == user_data.not_sent_frame_type);
7313   CU_ASSERT(NGHTTP2_ERR_STREAM_CLOSING == user_data.not_sent_error);
7314
7315   nghttp2_session_del(session);
7316
7317   /* Check request HEADERS */
7318   user_data.frame_not_send_cb_called = 0;
7319   CU_ASSERT(nghttp2_session_client_new(&session, &callbacks, &user_data) == 0);
7320   /* Maximum Stream ID is reached */
7321   session->next_stream_id = (1u << 31) + 1;
7322   CU_ASSERT(NGHTTP2_ERR_STREAM_ID_NOT_AVAILABLE ==
7323             nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, -1, NULL,
7324                                    NULL, 0, NULL));
7325
7326   user_data.frame_not_send_cb_called = 0;
7327   /* GOAWAY received */
7328   session->goaway_flags |= NGHTTP2_GOAWAY_RECV;
7329   session->next_stream_id = 9;
7330
7331   CU_ASSERT(0 < nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, -1,
7332                                        NULL, NULL, 0, NULL));
7333   CU_ASSERT(0 == nghttp2_session_send(session));
7334   CU_ASSERT(1 == user_data.frame_not_send_cb_called);
7335   CU_ASSERT(NGHTTP2_HEADERS == user_data.not_sent_frame_type);
7336   CU_ASSERT(NGHTTP2_ERR_START_STREAM_NOT_ALLOWED == user_data.not_sent_error);
7337
7338   nghttp2_session_del(session);
7339 }
7340
7341 void test_nghttp2_session_get_outbound_queue_size(void) {
7342   nghttp2_session *session;
7343   nghttp2_session_callbacks callbacks;
7344
7345   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7346   CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, NULL));
7347   CU_ASSERT(0 == nghttp2_session_get_outbound_queue_size(session));
7348
7349   CU_ASSERT(0 == nghttp2_submit_ping(session, NGHTTP2_FLAG_NONE, NULL));
7350   CU_ASSERT(1 == nghttp2_session_get_outbound_queue_size(session));
7351
7352   CU_ASSERT(0 == nghttp2_submit_goaway(session, NGHTTP2_FLAG_NONE, 2,
7353                                        NGHTTP2_NO_ERROR, NULL, 0));
7354   CU_ASSERT(2 == nghttp2_session_get_outbound_queue_size(session));
7355
7356   nghttp2_session_del(session);
7357 }
7358
7359 void test_nghttp2_session_get_effective_local_window_size(void) {
7360   nghttp2_session *session;
7361   nghttp2_session_callbacks callbacks;
7362   nghttp2_stream *stream;
7363
7364   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7365   CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, NULL));
7366
7367   stream = open_sent_stream(session, 1);
7368
7369   CU_ASSERT(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE ==
7370             nghttp2_session_get_effective_local_window_size(session));
7371   CU_ASSERT(0 == nghttp2_session_get_effective_recv_data_length(session));
7372
7373   CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE ==
7374             nghttp2_session_get_stream_effective_local_window_size(session, 1));
7375   CU_ASSERT(0 ==
7376             nghttp2_session_get_stream_effective_recv_data_length(session, 1));
7377
7378   /* Check connection flow control */
7379   session->recv_window_size = 100;
7380   nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 0, 1100);
7381
7382   CU_ASSERT(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE + 1000 ==
7383             nghttp2_session_get_effective_local_window_size(session));
7384   CU_ASSERT(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE + 1000 ==
7385             nghttp2_session_get_local_window_size(session));
7386   CU_ASSERT(0 == nghttp2_session_get_effective_recv_data_length(session));
7387
7388   nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 0, -50);
7389   /* Now session->recv_window_size = -50 */
7390   CU_ASSERT(-50 == session->recv_window_size);
7391   CU_ASSERT(50 == session->recv_reduction);
7392   CU_ASSERT(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE + 950 ==
7393             nghttp2_session_get_effective_local_window_size(session));
7394   CU_ASSERT(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE + 1000 ==
7395             nghttp2_session_get_local_window_size(session));
7396   CU_ASSERT(0 == nghttp2_session_get_effective_recv_data_length(session));
7397
7398   session->recv_window_size += 50;
7399
7400   /* Now session->recv_window_size = 0 */
7401
7402   CU_ASSERT(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE + 950 ==
7403             nghttp2_session_get_local_window_size(session));
7404
7405   nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 0, 100);
7406   CU_ASSERT(50 == session->recv_window_size);
7407   CU_ASSERT(0 == session->recv_reduction);
7408   CU_ASSERT(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE + 1050 ==
7409             nghttp2_session_get_effective_local_window_size(session));
7410   CU_ASSERT(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE + 1000 ==
7411             nghttp2_session_get_local_window_size(session));
7412   CU_ASSERT(50 == nghttp2_session_get_effective_recv_data_length(session));
7413
7414   /* Check stream flow control */
7415   stream->recv_window_size = 100;
7416   nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 1, 1100);
7417
7418   CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE + 1000 ==
7419             nghttp2_session_get_stream_effective_local_window_size(session, 1));
7420   CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE + 1000 ==
7421             nghttp2_session_get_stream_local_window_size(session, 1));
7422   CU_ASSERT(0 ==
7423             nghttp2_session_get_stream_effective_recv_data_length(session, 1));
7424
7425   nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 1, -50);
7426   /* Now stream->recv_window_size = -50 */
7427   CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE + 950 ==
7428             nghttp2_session_get_stream_effective_local_window_size(session, 1));
7429   CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE + 1000 ==
7430             nghttp2_session_get_stream_local_window_size(session, 1));
7431   CU_ASSERT(0 ==
7432             nghttp2_session_get_stream_effective_recv_data_length(session, 1));
7433
7434   stream->recv_window_size += 50;
7435   /* Now stream->recv_window_size = 0 */
7436   nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 1, 100);
7437   CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE + 1050 ==
7438             nghttp2_session_get_stream_effective_local_window_size(session, 1));
7439   CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE + 1000 ==
7440             nghttp2_session_get_stream_local_window_size(session, 1));
7441   CU_ASSERT(50 ==
7442             nghttp2_session_get_stream_effective_recv_data_length(session, 1));
7443
7444   nghttp2_session_del(session);
7445 }
7446
7447 void test_nghttp2_session_set_option(void) {
7448   nghttp2_session *session;
7449   nghttp2_session_callbacks callbacks;
7450   nghttp2_option *option;
7451   nghttp2_hd_deflater *deflater;
7452   int rv;
7453
7454   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7455   callbacks.send_callback = null_send_callback;
7456
7457   /* Test for nghttp2_option_set_no_auto_window_update */
7458   nghttp2_option_new(&option);
7459   nghttp2_option_set_no_auto_window_update(option, 1);
7460
7461   nghttp2_session_client_new2(&session, &callbacks, NULL, option);
7462
7463   CU_ASSERT(session->opt_flags & NGHTTP2_OPTMASK_NO_AUTO_WINDOW_UPDATE);
7464
7465   nghttp2_session_del(session);
7466   nghttp2_option_del(option);
7467
7468   /* Test for nghttp2_option_set_peer_max_concurrent_streams */
7469   nghttp2_option_new(&option);
7470   nghttp2_option_set_peer_max_concurrent_streams(option, 100);
7471
7472   nghttp2_session_client_new2(&session, &callbacks, NULL, option);
7473
7474   CU_ASSERT(100 == session->remote_settings.max_concurrent_streams);
7475   nghttp2_session_del(session);
7476   nghttp2_option_del(option);
7477
7478   /* Test for nghttp2_option_set_max_reserved_remote_streams */
7479   nghttp2_option_new(&option);
7480   nghttp2_option_set_max_reserved_remote_streams(option, 99);
7481
7482   nghttp2_session_client_new2(&session, &callbacks, NULL, option);
7483
7484   CU_ASSERT(99 == session->max_incoming_reserved_streams);
7485   nghttp2_session_del(session);
7486   nghttp2_option_del(option);
7487
7488   /* Test for nghttp2_option_set_no_auto_ping_ack */
7489   nghttp2_option_new(&option);
7490   nghttp2_option_set_no_auto_ping_ack(option, 1);
7491
7492   nghttp2_session_client_new2(&session, &callbacks, NULL, option);
7493
7494   CU_ASSERT(session->opt_flags & NGHTTP2_OPTMASK_NO_AUTO_PING_ACK);
7495
7496   nghttp2_session_del(session);
7497   nghttp2_option_del(option);
7498
7499   /* Test for nghttp2_option_set_max_deflate_dynamic_table_size */
7500   nghttp2_option_new(&option);
7501   nghttp2_option_set_max_deflate_dynamic_table_size(option, 0);
7502
7503   nghttp2_session_client_new2(&session, &callbacks, NULL, option);
7504
7505   deflater = &session->hd_deflater;
7506
7507   rv = nghttp2_submit_request(session, NULL, reqnv, ARRLEN(reqnv), NULL, NULL);
7508
7509   CU_ASSERT(1 == rv);
7510
7511   rv = nghttp2_session_send(session);
7512
7513   CU_ASSERT(0 == rv);
7514   CU_ASSERT(0 == deflater->deflate_hd_table_bufsize_max);
7515   CU_ASSERT(0 == deflater->ctx.hd_table_bufsize);
7516
7517   nghttp2_session_del(session);
7518   nghttp2_option_del(option);
7519 }
7520
7521 void test_nghttp2_session_data_backoff_by_high_pri_frame(void) {
7522   nghttp2_session *session;
7523   nghttp2_session_callbacks callbacks;
7524   my_user_data ud;
7525   nghttp2_data_provider data_prd;
7526   nghttp2_stream *stream;
7527
7528   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7529   callbacks.send_callback = block_count_send_callback;
7530   callbacks.on_frame_send_callback = on_frame_send_callback;
7531   data_prd.read_callback = fixed_length_data_source_read_callback;
7532
7533   ud.frame_send_cb_called = 0;
7534   ud.data_source_length = NGHTTP2_DATA_PAYLOADLEN * 4;
7535
7536   nghttp2_session_client_new(&session, &callbacks, &ud);
7537   nghttp2_submit_request(session, NULL, NULL, 0, &data_prd, NULL);
7538
7539   session->remote_window_size = 1 << 20;
7540
7541   ud.block_count = 2;
7542   /* Sends request HEADERS + DATA[0] */
7543   CU_ASSERT(0 == nghttp2_session_send(session));
7544
7545   stream = nghttp2_session_get_stream(session, 1);
7546   stream->remote_window_size = 1 << 20;
7547
7548   CU_ASSERT(NGHTTP2_DATA == ud.sent_frame_type);
7549   /* data for DATA[1] is read from data_prd but it is not sent */
7550   CU_ASSERT(ud.data_source_length == NGHTTP2_DATA_PAYLOADLEN * 2);
7551
7552   nghttp2_submit_ping(session, NGHTTP2_FLAG_NONE, NULL);
7553   ud.block_count = 2;
7554   /* Sends DATA[1] + PING, PING is interleaved in DATA sequence */
7555   CU_ASSERT(0 == nghttp2_session_send(session));
7556   CU_ASSERT(NGHTTP2_PING == ud.sent_frame_type);
7557   /* data for DATA[2] is read from data_prd but it is not sent */
7558   CU_ASSERT(ud.data_source_length == NGHTTP2_DATA_PAYLOADLEN);
7559
7560   ud.block_count = 2;
7561   /* Sends DATA[2..3] */
7562   CU_ASSERT(0 == nghttp2_session_send(session));
7563
7564   CU_ASSERT(stream->shut_flags & NGHTTP2_SHUT_WR);
7565
7566   nghttp2_session_del(session);
7567 }
7568
7569 static void check_session_recv_data_with_padding(nghttp2_bufs *bufs,
7570                                                  size_t datalen,
7571                                                  nghttp2_mem *mem) {
7572   nghttp2_session *session;
7573   my_user_data ud;
7574   nghttp2_session_callbacks callbacks;
7575   uint8_t *in;
7576   size_t inlen;
7577
7578   memset(&callbacks, 0, sizeof(callbacks));
7579   callbacks.on_frame_recv_callback = on_frame_recv_callback;
7580   callbacks.on_data_chunk_recv_callback = on_data_chunk_recv_callback;
7581   nghttp2_session_server_new(&session, &callbacks, &ud);
7582
7583   open_recv_stream(session, 1);
7584
7585   inlen = (size_t)nghttp2_bufs_remove(bufs, &in);
7586
7587   ud.frame_recv_cb_called = 0;
7588   ud.data_chunk_len = 0;
7589
7590   CU_ASSERT((ssize_t)inlen == nghttp2_session_mem_recv(session, in, inlen));
7591
7592   CU_ASSERT(1 == ud.frame_recv_cb_called);
7593   CU_ASSERT(datalen == ud.data_chunk_len);
7594
7595   mem->free(in, NULL);
7596   nghttp2_session_del(session);
7597 }
7598
7599 void test_nghttp2_session_pack_data_with_padding(void) {
7600   nghttp2_session *session;
7601   my_user_data ud;
7602   nghttp2_session_callbacks callbacks;
7603   nghttp2_data_provider data_prd;
7604   nghttp2_frame *frame;
7605   size_t datalen = 55;
7606   nghttp2_mem *mem;
7607
7608   mem = nghttp2_mem_default();
7609
7610   memset(&callbacks, 0, sizeof(callbacks));
7611   callbacks.send_callback = block_count_send_callback;
7612   callbacks.on_frame_send_callback = on_frame_send_callback;
7613   callbacks.select_padding_callback = select_padding_callback;
7614
7615   data_prd.read_callback = fixed_length_data_source_read_callback;
7616
7617   nghttp2_session_client_new(&session, &callbacks, &ud);
7618
7619   ud.padlen = 63;
7620
7621   nghttp2_submit_request(session, NULL, NULL, 0, &data_prd, NULL);
7622   ud.block_count = 1;
7623   ud.data_source_length = datalen;
7624   /* Sends HEADERS */
7625   CU_ASSERT(0 == nghttp2_session_send(session));
7626   CU_ASSERT(NGHTTP2_HEADERS == ud.sent_frame_type);
7627
7628   frame = &session->aob.item->frame;
7629
7630   CU_ASSERT(ud.padlen == frame->data.padlen);
7631   CU_ASSERT(frame->hd.flags & NGHTTP2_FLAG_PADDED);
7632
7633   /* Check reception of this DATA frame */
7634   check_session_recv_data_with_padding(&session->aob.framebufs, datalen, mem);
7635
7636   nghttp2_session_del(session);
7637 }
7638
7639 void test_nghttp2_session_pack_headers_with_padding(void) {
7640   nghttp2_session *session, *sv_session;
7641   accumulator acc;
7642   my_user_data ud;
7643   nghttp2_session_callbacks callbacks;
7644
7645   memset(&callbacks, 0, sizeof(callbacks));
7646   callbacks.send_callback = accumulator_send_callback;
7647   callbacks.on_frame_send_callback = on_frame_send_callback;
7648   callbacks.select_padding_callback = select_padding_callback;
7649   callbacks.on_frame_recv_callback = on_frame_recv_callback;
7650
7651   acc.length = 0;
7652   ud.acc = &acc;
7653
7654   nghttp2_session_client_new(&session, &callbacks, &ud);
7655   nghttp2_session_server_new(&sv_session, &callbacks, &ud);
7656
7657   ud.padlen = 163;
7658
7659   CU_ASSERT(1 == nghttp2_submit_request(session, NULL, reqnv, ARRLEN(reqnv),
7660                                         NULL, NULL));
7661   CU_ASSERT(0 == nghttp2_session_send(session));
7662
7663   CU_ASSERT(acc.length < NGHTTP2_MAX_PAYLOADLEN);
7664   ud.frame_recv_cb_called = 0;
7665   CU_ASSERT((ssize_t)acc.length ==
7666             nghttp2_session_mem_recv(sv_session, acc.buf, acc.length));
7667   CU_ASSERT(1 == ud.frame_recv_cb_called);
7668   CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(sv_session));
7669
7670   nghttp2_session_del(sv_session);
7671   nghttp2_session_del(session);
7672 }
7673
7674 void test_nghttp2_pack_settings_payload(void) {
7675   nghttp2_settings_entry iv[2];
7676   uint8_t buf[64];
7677   ssize_t len;
7678   nghttp2_settings_entry *resiv;
7679   size_t resniv;
7680   nghttp2_mem *mem;
7681
7682   mem = nghttp2_mem_default();
7683
7684   iv[0].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
7685   iv[0].value = 1023;
7686   iv[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
7687   iv[1].value = 4095;
7688
7689   len = nghttp2_pack_settings_payload(buf, sizeof(buf), iv, 2);
7690   CU_ASSERT(2 * NGHTTP2_FRAME_SETTINGS_ENTRY_LENGTH == len);
7691   CU_ASSERT(0 == nghttp2_frame_unpack_settings_payload2(&resiv, &resniv, buf,
7692                                                         (size_t)len, mem));
7693   CU_ASSERT(2 == resniv);
7694   CU_ASSERT(NGHTTP2_SETTINGS_HEADER_TABLE_SIZE == resiv[0].settings_id);
7695   CU_ASSERT(1023 == resiv[0].value);
7696   CU_ASSERT(NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE == resiv[1].settings_id);
7697   CU_ASSERT(4095 == resiv[1].value);
7698
7699   mem->free(resiv, NULL);
7700
7701   len = nghttp2_pack_settings_payload(buf, 9 /* too small */, iv, 2);
7702   CU_ASSERT(NGHTTP2_ERR_INSUFF_BUFSIZE == len);
7703 }
7704
7705 #define check_stream_dep_sib(STREAM, DEP_PREV, DEP_NEXT, SIB_PREV, SIB_NEXT)   \
7706   do {                                                                         \
7707     CU_ASSERT(DEP_PREV == STREAM->dep_prev);                                   \
7708     CU_ASSERT(DEP_NEXT == STREAM->dep_next);                                   \
7709     CU_ASSERT(SIB_PREV == STREAM->sib_prev);                                   \
7710     CU_ASSERT(SIB_NEXT == STREAM->sib_next);                                   \
7711   } while (0)
7712
7713 /* nghttp2_stream_dep_add() and its families functions should be
7714    tested in nghttp2_stream_test.c, but it is easier to use
7715    nghttp2_session_open_stream().  Therefore, we test them here. */
7716 void test_nghttp2_session_stream_dep_add(void) {
7717   nghttp2_session *session;
7718   nghttp2_session_callbacks callbacks;
7719   nghttp2_stream *a, *b, *c, *d, *e, *root;
7720
7721   memset(&callbacks, 0, sizeof(callbacks));
7722
7723   nghttp2_session_server_new(&session, &callbacks, NULL);
7724
7725   root = &session->root;
7726
7727   a = open_stream(session, 1);
7728
7729   c = open_stream_with_dep(session, 5, a);
7730   b = open_stream_with_dep(session, 3, a);
7731   d = open_stream_with_dep(session, 7, c);
7732
7733   /* a
7734    * |
7735    * b--c
7736    *    |
7737    *    d
7738    */
7739
7740   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 2 == a->sum_dep_weight);
7741   CU_ASSERT(0 == b->sum_dep_weight);
7742   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == c->sum_dep_weight);
7743   CU_ASSERT(0 == d->sum_dep_weight);
7744
7745   check_stream_dep_sib(a, root, b, NULL, NULL);
7746   check_stream_dep_sib(b, a, NULL, NULL, c);
7747   check_stream_dep_sib(c, a, d, b, NULL);
7748   check_stream_dep_sib(d, c, NULL, NULL, NULL);
7749
7750   CU_ASSERT(a == session->root.dep_next);
7751
7752   e = open_stream_with_dep_excl(session, 9, a);
7753
7754   /* a
7755    * |
7756    * e
7757    * |
7758    * b--c
7759    *    |
7760    *    d
7761    */
7762
7763   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == a->sum_dep_weight);
7764   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 2 == e->sum_dep_weight);
7765   CU_ASSERT(0 == b->sum_dep_weight);
7766   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == c->sum_dep_weight);
7767   CU_ASSERT(0 == d->sum_dep_weight);
7768
7769   check_stream_dep_sib(a, root, e, NULL, NULL);
7770   check_stream_dep_sib(e, a, b, NULL, NULL);
7771   check_stream_dep_sib(b, e, NULL, NULL, c);
7772   check_stream_dep_sib(c, e, d, b, NULL);
7773   check_stream_dep_sib(d, c, NULL, NULL, NULL);
7774
7775   CU_ASSERT(a == session->root.dep_next);
7776
7777   nghttp2_session_del(session);
7778 }
7779
7780 void test_nghttp2_session_stream_dep_remove(void) {
7781   nghttp2_session *session;
7782   nghttp2_session_callbacks callbacks;
7783   nghttp2_stream *a, *b, *c, *d, *e, *f, *root;
7784
7785   memset(&callbacks, 0, sizeof(callbacks));
7786
7787   /* Remove root */
7788   nghttp2_session_server_new(&session, &callbacks, NULL);
7789
7790   root = &session->root;
7791
7792   a = open_stream(session, 1);
7793   b = open_stream_with_dep(session, 3, a);
7794   c = open_stream_with_dep(session, 5, a);
7795   d = open_stream_with_dep(session, 7, c);
7796
7797   /* a
7798    * |
7799    * c--b
7800    * |
7801    * d
7802    */
7803
7804   nghttp2_stream_dep_remove(a);
7805
7806   /* becomes:
7807    * c    b
7808    * |
7809    * d
7810    */
7811
7812   CU_ASSERT(0 == a->sum_dep_weight);
7813   CU_ASSERT(0 == b->sum_dep_weight);
7814   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == c->sum_dep_weight);
7815   CU_ASSERT(0 == d->sum_dep_weight);
7816
7817   check_stream_dep_sib(a, NULL, NULL, NULL, NULL);
7818   check_stream_dep_sib(b, root, NULL, c, NULL);
7819   check_stream_dep_sib(c, root, d, NULL, b);
7820   check_stream_dep_sib(d, c, NULL, NULL, NULL);
7821
7822   CU_ASSERT(c == session->root.dep_next);
7823
7824   nghttp2_session_del(session);
7825
7826   /* Remove right most stream */
7827   nghttp2_session_server_new(&session, &callbacks, NULL);
7828
7829   root = &session->root;
7830
7831   a = open_stream(session, 1);
7832   b = open_stream_with_dep(session, 3, a);
7833   c = open_stream_with_dep(session, 5, a);
7834   d = open_stream_with_dep(session, 7, c);
7835
7836   /* a
7837    * |
7838    * c--b
7839    * |
7840    * d
7841    */
7842
7843   nghttp2_stream_dep_remove(b);
7844
7845   /* becomes:
7846    * a
7847    * |
7848    * c
7849    * |
7850    * d
7851    */
7852
7853   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == a->sum_dep_weight);
7854   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == c->sum_dep_weight);
7855   CU_ASSERT(0 == d->sum_dep_weight);
7856   CU_ASSERT(0 == b->sum_dep_weight);
7857
7858   check_stream_dep_sib(a, root, c, NULL, NULL);
7859   check_stream_dep_sib(b, NULL, NULL, NULL, NULL);
7860   check_stream_dep_sib(c, a, d, NULL, NULL);
7861   check_stream_dep_sib(d, c, NULL, NULL, NULL);
7862
7863   CU_ASSERT(a == session->root.dep_next);
7864
7865   nghttp2_session_del(session);
7866
7867   /* Remove left most stream */
7868   nghttp2_session_server_new(&session, &callbacks, NULL);
7869
7870   root = &session->root;
7871
7872   a = open_stream(session, 1);
7873   b = open_stream_with_dep(session, 3, a);
7874   c = open_stream_with_dep(session, 5, a);
7875   d = open_stream_with_dep(session, 7, c);
7876   e = open_stream_with_dep(session, 9, c);
7877
7878   /* a
7879    * |
7880    * c--b
7881    * |
7882    * e--d
7883    */
7884
7885   nghttp2_stream_dep_remove(c);
7886
7887   /* becomes:
7888    * a
7889    * |
7890    * e--d--b
7891    */
7892
7893   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 2 == a->sum_dep_weight);
7894   CU_ASSERT(0 == b->sum_dep_weight);
7895   CU_ASSERT(0 == d->sum_dep_weight);
7896   CU_ASSERT(0 == c->sum_dep_weight);
7897   CU_ASSERT(0 == e->sum_dep_weight);
7898
7899   check_stream_dep_sib(a, root, e, NULL, NULL);
7900   check_stream_dep_sib(b, a, NULL, d, NULL);
7901   check_stream_dep_sib(c, NULL, NULL, NULL, NULL);
7902   check_stream_dep_sib(d, a, NULL, e, b);
7903   check_stream_dep_sib(e, a, NULL, NULL, d);
7904
7905   nghttp2_session_del(session);
7906
7907   /* Remove middle stream */
7908   nghttp2_session_server_new(&session, &callbacks, NULL);
7909
7910   root = &session->root;
7911
7912   a = open_stream(session, 1);
7913   b = open_stream_with_dep(session, 3, a);
7914   c = open_stream_with_dep(session, 5, a);
7915   d = open_stream_with_dep(session, 7, a);
7916   e = open_stream_with_dep(session, 9, c);
7917   f = open_stream_with_dep(session, 11, c);
7918
7919   /* a
7920    * |
7921    * d--c--b
7922    *    |
7923    *    f--e
7924    */
7925
7926   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 3 == a->sum_dep_weight);
7927   CU_ASSERT(0 == b->sum_dep_weight);
7928   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 2 == c->sum_dep_weight);
7929   CU_ASSERT(0 == d->sum_dep_weight);
7930   CU_ASSERT(0 == e->sum_dep_weight);
7931   CU_ASSERT(0 == f->sum_dep_weight);
7932
7933   nghttp2_stream_dep_remove(c);
7934
7935   /* becomes:
7936    * a
7937    * |
7938    * d--f--e--b
7939    */
7940
7941   /* c's weight 16 is distributed evenly to e and f.  Each weight of e
7942      and f becomes 8. */
7943   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 2 + 8 * 2 == a->sum_dep_weight);
7944   CU_ASSERT(0 == b->sum_dep_weight);
7945   CU_ASSERT(0 == c->sum_dep_weight);
7946   CU_ASSERT(0 == d->sum_dep_weight);
7947   CU_ASSERT(0 == e->sum_dep_weight);
7948   CU_ASSERT(0 == f->sum_dep_weight);
7949
7950   check_stream_dep_sib(a, root, d, NULL, NULL);
7951   check_stream_dep_sib(b, a, NULL, e, NULL);
7952   check_stream_dep_sib(c, NULL, NULL, NULL, NULL);
7953   check_stream_dep_sib(e, a, NULL, f, b);
7954   check_stream_dep_sib(f, a, NULL, d, e);
7955   check_stream_dep_sib(d, a, NULL, NULL, f);
7956
7957   nghttp2_session_del(session);
7958 }
7959
7960 void test_nghttp2_session_stream_dep_add_subtree(void) {
7961   nghttp2_session *session;
7962   nghttp2_session_callbacks callbacks;
7963   nghttp2_stream *a, *b, *c, *d, *e, *f, *root;
7964
7965   memset(&callbacks, 0, sizeof(callbacks));
7966
7967   /* dep_stream has dep_next */
7968   nghttp2_session_server_new(&session, &callbacks, NULL);
7969
7970   root = &session->root;
7971
7972   a = open_stream(session, 1);
7973   b = open_stream_with_dep(session, 3, a);
7974   c = open_stream_with_dep(session, 5, a);
7975   d = open_stream_with_dep(session, 7, c);
7976
7977   e = open_stream(session, 9);
7978   f = open_stream_with_dep(session, 11, e);
7979
7980   /* a         e
7981    * |         |
7982    * c--b      f
7983    * |
7984    * d
7985    */
7986
7987   nghttp2_stream_dep_remove_subtree(e);
7988   nghttp2_stream_dep_add_subtree(a, e);
7989
7990   /* becomes
7991    * a
7992    * |
7993    * e--c--b
7994    * |  |
7995    * f  d
7996    */
7997
7998   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 3 == a->sum_dep_weight);
7999   CU_ASSERT(0 == b->sum_dep_weight);
8000   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == c->sum_dep_weight);
8001   CU_ASSERT(0 == d->sum_dep_weight);
8002   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == e->sum_dep_weight);
8003   CU_ASSERT(0 == f->sum_dep_weight);
8004
8005   check_stream_dep_sib(a, root, e, NULL, NULL);
8006   check_stream_dep_sib(b, a, NULL, c, NULL);
8007   check_stream_dep_sib(c, a, d, e, b);
8008   check_stream_dep_sib(d, c, NULL, NULL, NULL);
8009   check_stream_dep_sib(e, a, f, NULL, c);
8010   check_stream_dep_sib(f, e, NULL, NULL, NULL);
8011
8012   nghttp2_session_del(session);
8013
8014   /* dep_stream has dep_next and now we insert subtree */
8015   nghttp2_session_server_new(&session, &callbacks, NULL);
8016
8017   root = &session->root;
8018
8019   a = open_stream(session, 1);
8020   b = open_stream_with_dep(session, 3, a);
8021   c = open_stream_with_dep(session, 5, a);
8022   d = open_stream_with_dep(session, 7, c);
8023
8024   e = open_stream(session, 9);
8025   f = open_stream_with_dep(session, 11, e);
8026
8027   /* a         e
8028    * |         |
8029    * c--b      f
8030    * |
8031    * d
8032    */
8033
8034   nghttp2_stream_dep_remove_subtree(e);
8035   nghttp2_stream_dep_insert_subtree(a, e);
8036
8037   /* becomes
8038    * a
8039    * |
8040    * e
8041    * |
8042    * f--c--b
8043    *    |
8044    *    d
8045    */
8046
8047   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == a->sum_dep_weight);
8048   CU_ASSERT(0 == b->sum_dep_weight);
8049   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == c->sum_dep_weight);
8050   CU_ASSERT(0 == d->sum_dep_weight);
8051   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 3 == e->sum_dep_weight);
8052   CU_ASSERT(0 == f->sum_dep_weight);
8053
8054   check_stream_dep_sib(a, root, e, NULL, NULL);
8055   check_stream_dep_sib(e, a, f, NULL, NULL);
8056   check_stream_dep_sib(f, e, NULL, NULL, c);
8057   check_stream_dep_sib(b, e, NULL, c, NULL);
8058   check_stream_dep_sib(c, e, d, f, b);
8059   check_stream_dep_sib(d, c, NULL, NULL, NULL);
8060
8061   nghttp2_session_del(session);
8062 }
8063
8064 void test_nghttp2_session_stream_dep_remove_subtree(void) {
8065   nghttp2_session *session;
8066   nghttp2_session_callbacks callbacks;
8067   nghttp2_stream *a, *b, *c, *d, *e, *root;
8068
8069   memset(&callbacks, 0, sizeof(callbacks));
8070
8071   /* Remove left most stream */
8072   nghttp2_session_server_new(&session, &callbacks, NULL);
8073
8074   root = &session->root;
8075
8076   a = open_stream(session, 1);
8077   b = open_stream_with_dep(session, 3, a);
8078   c = open_stream_with_dep(session, 5, a);
8079   d = open_stream_with_dep(session, 7, c);
8080
8081   /* a
8082    * |
8083    * c--b
8084    * |
8085    * d
8086    */
8087
8088   nghttp2_stream_dep_remove_subtree(c);
8089
8090   /* becomes
8091    * a  c
8092    * |  |
8093    * b  d
8094    */
8095
8096   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == a->sum_dep_weight);
8097   CU_ASSERT(0 == b->sum_dep_weight);
8098   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == c->sum_dep_weight);
8099   CU_ASSERT(0 == d->sum_dep_weight);
8100
8101   check_stream_dep_sib(a, root, b, NULL, NULL);
8102   check_stream_dep_sib(b, a, NULL, NULL, NULL);
8103   check_stream_dep_sib(c, NULL, d, NULL, NULL);
8104   check_stream_dep_sib(d, c, NULL, NULL, NULL);
8105
8106   nghttp2_session_del(session);
8107
8108   /* Remove right most stream */
8109   nghttp2_session_server_new(&session, &callbacks, NULL);
8110
8111   root = &session->root;
8112
8113   a = open_stream(session, 1);
8114   b = open_stream_with_dep(session, 3, a);
8115   c = open_stream_with_dep(session, 5, a);
8116   d = open_stream_with_dep(session, 7, c);
8117
8118   /* a
8119    * |
8120    * c--b
8121    * |
8122    * d
8123    */
8124
8125   nghttp2_stream_dep_remove_subtree(b);
8126
8127   /* becomes
8128    * a  b
8129    * |
8130    * c
8131    * |
8132    * d
8133    */
8134
8135   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == a->sum_dep_weight);
8136   CU_ASSERT(0 == b->sum_dep_weight);
8137   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == c->sum_dep_weight);
8138   CU_ASSERT(0 == d->sum_dep_weight);
8139
8140   check_stream_dep_sib(a, root, c, NULL, NULL);
8141   check_stream_dep_sib(c, a, d, NULL, NULL);
8142   check_stream_dep_sib(d, c, NULL, NULL, NULL);
8143   check_stream_dep_sib(b, NULL, NULL, NULL, NULL);
8144
8145   nghttp2_session_del(session);
8146
8147   /* Remove middle stream */
8148   nghttp2_session_server_new(&session, &callbacks, NULL);
8149
8150   root = &session->root;
8151
8152   a = open_stream(session, 1);
8153   e = open_stream_with_dep(session, 9, a);
8154   c = open_stream_with_dep(session, 5, a);
8155   b = open_stream_with_dep(session, 3, a);
8156   d = open_stream_with_dep(session, 7, c);
8157
8158   /* a
8159    * |
8160    * b--c--e
8161    *    |
8162    *    d
8163    */
8164
8165   nghttp2_stream_dep_remove_subtree(c);
8166
8167   /* becomes
8168    * a     c
8169    * |     |
8170    * b--e  d
8171    */
8172
8173   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 2 == a->sum_dep_weight);
8174   CU_ASSERT(0 == b->sum_dep_weight);
8175   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == c->sum_dep_weight);
8176   CU_ASSERT(0 == d->sum_dep_weight);
8177   CU_ASSERT(0 == e->sum_dep_weight);
8178
8179   check_stream_dep_sib(a, root, b, NULL, NULL);
8180   check_stream_dep_sib(b, a, NULL, NULL, e);
8181   check_stream_dep_sib(e, a, NULL, b, NULL);
8182   check_stream_dep_sib(c, NULL, d, NULL, NULL);
8183   check_stream_dep_sib(d, c, NULL, NULL, NULL);
8184
8185   nghttp2_session_del(session);
8186 }
8187
8188 void test_nghttp2_session_stream_dep_all_your_stream_are_belong_to_us(void) {
8189   nghttp2_session *session;
8190   nghttp2_session_callbacks callbacks;
8191   nghttp2_stream *a, *b, *c, *d, *root;
8192   nghttp2_outbound_item *db, *dc;
8193   nghttp2_mem *mem;
8194
8195   mem = nghttp2_mem_default();
8196
8197   memset(&callbacks, 0, sizeof(callbacks));
8198
8199   nghttp2_session_server_new(&session, &callbacks, NULL);
8200
8201   root = &session->root;
8202
8203   a = open_stream(session, 1);
8204   b = open_stream_with_dep(session, 3, a);
8205
8206   c = open_stream(session, 5);
8207
8208   /* a     c
8209    * |
8210    * b
8211    */
8212
8213   nghttp2_stream_dep_remove_subtree(c);
8214   CU_ASSERT(0 == nghttp2_stream_dep_insert_subtree(&session->root, c));
8215
8216   /*
8217    * c
8218    * |
8219    * a
8220    * |
8221    * b
8222    */
8223
8224   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == c->sum_dep_weight);
8225   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == a->sum_dep_weight);
8226   CU_ASSERT(0 == b->sum_dep_weight);
8227
8228   CU_ASSERT(nghttp2_pq_empty(&a->obq));
8229   CU_ASSERT(nghttp2_pq_empty(&b->obq));
8230   CU_ASSERT(nghttp2_pq_empty(&c->obq));
8231
8232   check_stream_dep_sib(c, root, a, NULL, NULL);
8233   check_stream_dep_sib(a, c, b, NULL, NULL);
8234   check_stream_dep_sib(b, a, NULL, NULL, NULL);
8235
8236   nghttp2_session_del(session);
8237
8238   nghttp2_session_server_new(&session, &callbacks, NULL);
8239
8240   root = &session->root;
8241
8242   a = open_stream(session, 1);
8243   b = open_stream(session, 3);
8244   c = open_stream(session, 5);
8245
8246   /*
8247    * a  b   c
8248    */
8249
8250   nghttp2_stream_dep_remove_subtree(c);
8251   CU_ASSERT(0 == nghttp2_stream_dep_insert_subtree(&session->root, c));
8252
8253   /*
8254    * c
8255    * |
8256    * b--a
8257    */
8258
8259   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 2 == c->sum_dep_weight);
8260   CU_ASSERT(0 == b->sum_dep_weight);
8261   CU_ASSERT(0 == a->sum_dep_weight);
8262
8263   CU_ASSERT(nghttp2_pq_empty(&a->obq));
8264   CU_ASSERT(nghttp2_pq_empty(&b->obq));
8265   CU_ASSERT(nghttp2_pq_empty(&c->obq));
8266
8267   check_stream_dep_sib(c, root, b, NULL, NULL);
8268   check_stream_dep_sib(b, c, NULL, NULL, a);
8269   check_stream_dep_sib(a, c, NULL, b, NULL);
8270
8271   nghttp2_session_del(session);
8272
8273   nghttp2_session_server_new(&session, &callbacks, NULL);
8274
8275   root = &session->root;
8276
8277   a = open_stream(session, 1);
8278   b = open_stream_with_dep(session, 3, a);
8279
8280   c = open_stream(session, 5);
8281   d = open_stream_with_dep(session, 7, c);
8282
8283   /* a     c
8284    * |     |
8285    * b     d
8286    */
8287
8288   nghttp2_stream_dep_remove_subtree(c);
8289   CU_ASSERT(0 == nghttp2_stream_dep_insert_subtree(&session->root, c));
8290
8291   /*
8292    * c
8293    * |
8294    * d--a
8295    *    |
8296    *    b
8297    */
8298
8299   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 2 == c->sum_dep_weight);
8300   CU_ASSERT(0 == d->sum_dep_weight);
8301   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == a->sum_dep_weight);
8302   CU_ASSERT(0 == b->sum_dep_weight);
8303
8304   CU_ASSERT(nghttp2_pq_empty(&a->obq));
8305   CU_ASSERT(nghttp2_pq_empty(&b->obq));
8306   CU_ASSERT(nghttp2_pq_empty(&c->obq));
8307   CU_ASSERT(nghttp2_pq_empty(&d->obq));
8308
8309   check_stream_dep_sib(c, root, d, NULL, NULL);
8310   check_stream_dep_sib(d, c, NULL, NULL, a);
8311   check_stream_dep_sib(a, c, b, d, NULL);
8312   check_stream_dep_sib(b, a, NULL, NULL, NULL);
8313
8314   nghttp2_session_del(session);
8315
8316   nghttp2_session_server_new(&session, &callbacks, NULL);
8317
8318   root = &session->root;
8319
8320   a = open_stream(session, 1);
8321   b = open_stream_with_dep(session, 3, a);
8322
8323   c = open_stream(session, 5);
8324   d = open_stream_with_dep(session, 7, c);
8325
8326   /* a     c
8327    * |     |
8328    * b     d
8329    */
8330
8331   db = create_data_ob_item(mem);
8332
8333   nghttp2_stream_attach_item(b, db);
8334
8335   nghttp2_stream_dep_remove_subtree(c);
8336   CU_ASSERT(0 == nghttp2_stream_dep_insert_subtree(&session->root, c));
8337
8338   /*
8339    * c
8340    * |
8341    * d--a
8342    *    |
8343    *    b
8344    */
8345
8346   CU_ASSERT(c->queued);
8347   CU_ASSERT(a->queued);
8348   CU_ASSERT(b->queued);
8349   CU_ASSERT(!d->queued);
8350
8351   CU_ASSERT(1 == nghttp2_pq_size(&a->obq));
8352   CU_ASSERT(1 == nghttp2_pq_size(&c->obq));
8353   CU_ASSERT(nghttp2_pq_empty(&d->obq));
8354
8355   check_stream_dep_sib(c, root, d, NULL, NULL);
8356   check_stream_dep_sib(d, c, NULL, NULL, a);
8357   check_stream_dep_sib(a, c, b, d, NULL);
8358   check_stream_dep_sib(b, a, NULL, NULL, NULL);
8359
8360   nghttp2_session_del(session);
8361
8362   nghttp2_session_server_new(&session, &callbacks, NULL);
8363
8364   root = &session->root;
8365
8366   a = open_stream(session, 1);
8367   b = open_stream_with_dep(session, 3, a);
8368
8369   c = open_stream(session, 5);
8370   d = open_stream_with_dep(session, 7, c);
8371
8372   /* a     c
8373    * |     |
8374    * b     d
8375    */
8376
8377   db = create_data_ob_item(mem);
8378   dc = create_data_ob_item(mem);
8379
8380   nghttp2_stream_attach_item(b, db);
8381   nghttp2_stream_attach_item(c, dc);
8382
8383   nghttp2_stream_dep_remove_subtree(c);
8384   CU_ASSERT(0 == nghttp2_stream_dep_insert_subtree(&session->root, c));
8385
8386   /*
8387    * c
8388    * |
8389    * d--a
8390    *    |
8391    *    b
8392    */
8393
8394   CU_ASSERT(c->queued);
8395   CU_ASSERT(a->queued);
8396   CU_ASSERT(b->queued);
8397   CU_ASSERT(!d->queued);
8398
8399   check_stream_dep_sib(c, root, d, NULL, NULL);
8400   check_stream_dep_sib(d, c, NULL, NULL, a);
8401   check_stream_dep_sib(a, c, b, d, NULL);
8402   check_stream_dep_sib(b, a, NULL, NULL, NULL);
8403
8404   nghttp2_session_del(session);
8405 }
8406
8407 void test_nghttp2_session_stream_attach_item(void) {
8408   nghttp2_session *session;
8409   nghttp2_session_callbacks callbacks;
8410   nghttp2_stream *a, *b, *c, *d, *e;
8411   nghttp2_outbound_item *da, *db, *dc, *dd;
8412   nghttp2_mem *mem;
8413
8414   mem = nghttp2_mem_default();
8415
8416   memset(&callbacks, 0, sizeof(callbacks));
8417
8418   nghttp2_session_server_new(&session, &callbacks, NULL);
8419
8420   a = open_stream(session, 1);
8421   b = open_stream_with_dep(session, 3, a);
8422   c = open_stream_with_dep(session, 5, a);
8423   d = open_stream_with_dep(session, 7, c);
8424
8425   /* a
8426    * |
8427    * c--b
8428    * |
8429    * d
8430    */
8431
8432   db = create_data_ob_item(mem);
8433
8434   nghttp2_stream_attach_item(b, db);
8435
8436   CU_ASSERT(a->queued);
8437   CU_ASSERT(b->queued);
8438   CU_ASSERT(!c->queued);
8439   CU_ASSERT(!d->queued);
8440
8441   CU_ASSERT(1 == nghttp2_pq_size(&a->obq));
8442
8443   /* Attach item to c */
8444   dc = create_data_ob_item(mem);
8445
8446   nghttp2_stream_attach_item(c, dc);
8447
8448   CU_ASSERT(a->queued);
8449   CU_ASSERT(b->queued);
8450   CU_ASSERT(c->queued);
8451   CU_ASSERT(!d->queued);
8452
8453   CU_ASSERT(2 == nghttp2_pq_size(&a->obq));
8454
8455   /* Attach item to a */
8456   da = create_data_ob_item(mem);
8457
8458   nghttp2_stream_attach_item(a, da);
8459
8460   CU_ASSERT(a->queued);
8461   CU_ASSERT(b->queued);
8462   CU_ASSERT(c->queued);
8463   CU_ASSERT(!d->queued);
8464
8465   CU_ASSERT(2 == nghttp2_pq_size(&a->obq));
8466
8467   /* Detach item from a */
8468   nghttp2_stream_detach_item(a);
8469
8470   CU_ASSERT(a->queued);
8471   CU_ASSERT(b->queued);
8472   CU_ASSERT(c->queued);
8473   CU_ASSERT(!d->queued);
8474
8475   CU_ASSERT(2 == nghttp2_pq_size(&a->obq));
8476
8477   /* Attach item to d */
8478   dd = create_data_ob_item(mem);
8479
8480   nghttp2_stream_attach_item(d, dd);
8481
8482   CU_ASSERT(a->queued);
8483   CU_ASSERT(b->queued);
8484   CU_ASSERT(c->queued);
8485   CU_ASSERT(d->queued);
8486
8487   CU_ASSERT(2 == nghttp2_pq_size(&a->obq));
8488   CU_ASSERT(1 == nghttp2_pq_size(&c->obq));
8489
8490   /* Detach item from c */
8491   nghttp2_stream_detach_item(c);
8492
8493   CU_ASSERT(a->queued);
8494   CU_ASSERT(b->queued);
8495   CU_ASSERT(c->queued);
8496   CU_ASSERT(d->queued);
8497
8498   CU_ASSERT(2 == nghttp2_pq_size(&a->obq));
8499   CU_ASSERT(1 == nghttp2_pq_size(&c->obq));
8500
8501   /* Detach item from b */
8502   nghttp2_stream_detach_item(b);
8503
8504   CU_ASSERT(a->queued);
8505   CU_ASSERT(!b->queued);
8506   CU_ASSERT(c->queued);
8507   CU_ASSERT(d->queued);
8508
8509   CU_ASSERT(1 == nghttp2_pq_size(&a->obq));
8510
8511   /* exercises insertion */
8512   e = open_stream_with_dep_excl(session, 9, a);
8513
8514   /* a
8515    * |
8516    * e
8517    * |
8518    * c--b
8519    * |
8520    * d
8521    */
8522
8523   CU_ASSERT(a->queued);
8524   CU_ASSERT(e->queued);
8525   CU_ASSERT(!b->queued);
8526   CU_ASSERT(c->queued);
8527   CU_ASSERT(d->queued);
8528
8529   CU_ASSERT(1 == nghttp2_pq_size(&a->obq));
8530   CU_ASSERT(1 == nghttp2_pq_size(&e->obq));
8531   CU_ASSERT(nghttp2_pq_empty(&b->obq));
8532   CU_ASSERT(1 == nghttp2_pq_size(&c->obq));
8533   CU_ASSERT(nghttp2_pq_empty(&d->obq));
8534
8535   /* exercises deletion */
8536   nghttp2_stream_dep_remove(e);
8537
8538   /* a
8539    * |
8540    * c--b
8541    * |
8542    * d
8543    */
8544
8545   CU_ASSERT(a->queued);
8546   CU_ASSERT(!b->queued);
8547   CU_ASSERT(c->queued);
8548   CU_ASSERT(d->queued);
8549
8550   CU_ASSERT(1 == nghttp2_pq_size(&a->obq));
8551   CU_ASSERT(nghttp2_pq_empty(&b->obq));
8552   CU_ASSERT(1 == nghttp2_pq_size(&c->obq));
8553   CU_ASSERT(nghttp2_pq_empty(&d->obq));
8554
8555   /* e's weight 16 is distributed equally among c and b, both now have
8556      weight 8 each. */
8557   CU_ASSERT(8 == b->weight);
8558   CU_ASSERT(8 == c->weight);
8559
8560   /* da, db, dc have been detached */
8561   nghttp2_outbound_item_free(da, mem);
8562   nghttp2_outbound_item_free(db, mem);
8563   nghttp2_outbound_item_free(dc, mem);
8564   free(da);
8565   free(db);
8566   free(dc);
8567
8568   nghttp2_session_del(session);
8569
8570   nghttp2_session_server_new(&session, &callbacks, NULL);
8571
8572   a = open_stream(session, 1);
8573   b = open_stream_with_dep(session, 3, a);
8574   c = open_stream_with_dep(session, 5, a);
8575   d = open_stream_with_dep(session, 7, c);
8576
8577   /* a
8578    * |
8579    * c--b
8580    * |
8581    * d
8582    */
8583
8584   da = create_data_ob_item(mem);
8585   db = create_data_ob_item(mem);
8586   dc = create_data_ob_item(mem);
8587
8588   nghttp2_stream_attach_item(a, da);
8589   nghttp2_stream_attach_item(b, db);
8590   nghttp2_stream_attach_item(c, dc);
8591
8592   CU_ASSERT(a->queued);
8593   CU_ASSERT(b->queued);
8594   CU_ASSERT(c->queued);
8595   CU_ASSERT(!d->queued);
8596
8597   CU_ASSERT(2 == nghttp2_pq_size(&a->obq));
8598   CU_ASSERT(nghttp2_pq_empty(&b->obq));
8599   CU_ASSERT(nghttp2_pq_empty(&c->obq));
8600   CU_ASSERT(nghttp2_pq_empty(&d->obq));
8601
8602   /* Detach item from a */
8603   nghttp2_stream_detach_item(a);
8604
8605   CU_ASSERT(a->queued);
8606   CU_ASSERT(b->queued);
8607   CU_ASSERT(c->queued);
8608   CU_ASSERT(!d->queued);
8609
8610   CU_ASSERT(2 == nghttp2_pq_size(&a->obq));
8611   CU_ASSERT(nghttp2_pq_empty(&b->obq));
8612   CU_ASSERT(nghttp2_pq_empty(&c->obq));
8613   CU_ASSERT(nghttp2_pq_empty(&d->obq));
8614
8615   /* da has been detached */
8616   nghttp2_outbound_item_free(da, mem);
8617   free(da);
8618
8619   nghttp2_session_del(session);
8620 }
8621
8622 void test_nghttp2_session_stream_attach_item_subtree(void) {
8623   nghttp2_session *session;
8624   nghttp2_session_callbacks callbacks;
8625   nghttp2_stream *a, *b, *c, *d, *e, *f;
8626   nghttp2_outbound_item *da, *db, *dd, *de;
8627   nghttp2_mem *mem;
8628
8629   mem = nghttp2_mem_default();
8630
8631   memset(&callbacks, 0, sizeof(callbacks));
8632
8633   nghttp2_session_server_new(&session, &callbacks, NULL);
8634
8635   a = open_stream(session, 1);
8636   b = open_stream_with_dep(session, 3, a);
8637   c = open_stream_with_dep(session, 5, a);
8638   d = open_stream_with_dep(session, 7, c);
8639
8640   e = open_stream_with_dep_weight(session, 9, 32, &session->root);
8641   f = open_stream_with_dep(session, 11, e);
8642
8643   /*
8644    * a        e
8645    * |        |
8646    * c--b     f
8647    * |
8648    * d
8649    */
8650
8651   de = create_data_ob_item(mem);
8652
8653   nghttp2_stream_attach_item(e, de);
8654
8655   db = create_data_ob_item(mem);
8656
8657   nghttp2_stream_attach_item(b, db);
8658
8659   CU_ASSERT(a->queued);
8660   CU_ASSERT(b->queued);
8661   CU_ASSERT(!c->queued);
8662   CU_ASSERT(!d->queued);
8663   CU_ASSERT(e->queued);
8664   CU_ASSERT(!f->queued);
8665
8666   CU_ASSERT(1 == nghttp2_pq_size(&a->obq));
8667   CU_ASSERT(nghttp2_pq_empty(&b->obq));
8668   CU_ASSERT(nghttp2_pq_empty(&c->obq));
8669   CU_ASSERT(nghttp2_pq_empty(&d->obq));
8670   CU_ASSERT(nghttp2_pq_empty(&e->obq));
8671   CU_ASSERT(nghttp2_pq_empty(&f->obq));
8672
8673   /* Insert subtree e under a */
8674
8675   nghttp2_stream_dep_remove_subtree(e);
8676   nghttp2_stream_dep_insert_subtree(a, e);
8677
8678   /*
8679    * a
8680    * |
8681    * e
8682    * |
8683    * f--c--b
8684    *    |
8685    *    d
8686    */
8687
8688   CU_ASSERT(a->queued);
8689   CU_ASSERT(b->queued);
8690   CU_ASSERT(!c->queued);
8691   CU_ASSERT(!d->queued);
8692   CU_ASSERT(e->queued);
8693   CU_ASSERT(!f->queued);
8694
8695   CU_ASSERT(1 == nghttp2_pq_size(&a->obq));
8696   CU_ASSERT(nghttp2_pq_empty(&b->obq));
8697   CU_ASSERT(nghttp2_pq_empty(&c->obq));
8698   CU_ASSERT(nghttp2_pq_empty(&d->obq));
8699   CU_ASSERT(1 == nghttp2_pq_size(&e->obq));
8700   CU_ASSERT(nghttp2_pq_empty(&f->obq));
8701
8702   /* Remove subtree b */
8703
8704   nghttp2_stream_dep_remove_subtree(b);
8705
8706   CU_ASSERT(0 == nghttp2_stream_dep_add_subtree(&session->root, b));
8707
8708   /*
8709    * a       b
8710    * |
8711    * e
8712    * |
8713    * f--c
8714    *    |
8715    *    d
8716    */
8717
8718   CU_ASSERT(a->queued);
8719   CU_ASSERT(b->queued);
8720   CU_ASSERT(!c->queued);
8721   CU_ASSERT(!d->queued);
8722   CU_ASSERT(e->queued);
8723   CU_ASSERT(!f->queued);
8724
8725   CU_ASSERT(1 == nghttp2_pq_size(&a->obq));
8726   CU_ASSERT(nghttp2_pq_empty(&b->obq));
8727   CU_ASSERT(nghttp2_pq_empty(&c->obq));
8728   CU_ASSERT(nghttp2_pq_empty(&d->obq));
8729   CU_ASSERT(nghttp2_pq_empty(&e->obq));
8730   CU_ASSERT(nghttp2_pq_empty(&f->obq));
8731
8732   /* Remove subtree a, and add it to root again */
8733
8734   nghttp2_stream_dep_remove_subtree(a);
8735
8736   CU_ASSERT(0 == nghttp2_stream_dep_add_subtree(&session->root, a));
8737
8738   CU_ASSERT(a->queued);
8739   CU_ASSERT(b->queued);
8740   CU_ASSERT(!c->queued);
8741   CU_ASSERT(!d->queued);
8742   CU_ASSERT(e->queued);
8743   CU_ASSERT(!f->queued);
8744
8745   CU_ASSERT(1 == nghttp2_pq_size(&a->obq));
8746   CU_ASSERT(nghttp2_pq_empty(&b->obq));
8747   CU_ASSERT(nghttp2_pq_empty(&c->obq));
8748   CU_ASSERT(nghttp2_pq_empty(&d->obq));
8749   CU_ASSERT(nghttp2_pq_empty(&e->obq));
8750   CU_ASSERT(nghttp2_pq_empty(&f->obq));
8751
8752   /* Remove subtree c */
8753
8754   nghttp2_stream_dep_remove_subtree(c);
8755
8756   CU_ASSERT(0 == nghttp2_stream_dep_add_subtree(&session->root, c));
8757
8758   /*
8759    * a       b     c
8760    * |             |
8761    * e             d
8762    * |
8763    * f
8764    */
8765
8766   CU_ASSERT(a->queued);
8767   CU_ASSERT(b->queued);
8768   CU_ASSERT(!c->queued);
8769   CU_ASSERT(!d->queued);
8770   CU_ASSERT(e->queued);
8771   CU_ASSERT(!f->queued);
8772
8773   CU_ASSERT(1 == nghttp2_pq_size(&a->obq));
8774   CU_ASSERT(nghttp2_pq_empty(&b->obq));
8775   CU_ASSERT(nghttp2_pq_empty(&c->obq));
8776   CU_ASSERT(nghttp2_pq_empty(&d->obq));
8777   CU_ASSERT(nghttp2_pq_empty(&e->obq));
8778   CU_ASSERT(nghttp2_pq_empty(&f->obq));
8779
8780   dd = create_data_ob_item(mem);
8781
8782   nghttp2_stream_attach_item(d, dd);
8783
8784   /* Add subtree c to a */
8785
8786   nghttp2_stream_dep_remove_subtree(c);
8787   nghttp2_stream_dep_add_subtree(a, c);
8788
8789   /*
8790    * a       b
8791    * |
8792    * c--e
8793    * |  |
8794    * d  f
8795    */
8796
8797   CU_ASSERT(a->queued);
8798   CU_ASSERT(b->queued);
8799   CU_ASSERT(c->queued);
8800   CU_ASSERT(d->queued);
8801   CU_ASSERT(e->queued);
8802   CU_ASSERT(!f->queued);
8803
8804   CU_ASSERT(2 == nghttp2_pq_size(&a->obq));
8805   CU_ASSERT(nghttp2_pq_empty(&b->obq));
8806   CU_ASSERT(1 == nghttp2_pq_size(&c->obq));
8807   CU_ASSERT(nghttp2_pq_empty(&d->obq));
8808   CU_ASSERT(nghttp2_pq_empty(&e->obq));
8809   CU_ASSERT(nghttp2_pq_empty(&f->obq));
8810
8811   /* Insert b under a */
8812
8813   nghttp2_stream_dep_remove_subtree(b);
8814   nghttp2_stream_dep_insert_subtree(a, b);
8815
8816   /*
8817    * a
8818    * |
8819    * b
8820    * |
8821    * c--e
8822    * |  |
8823    * d  f
8824    */
8825
8826   CU_ASSERT(a->queued);
8827   CU_ASSERT(b->queued);
8828   CU_ASSERT(c->queued);
8829   CU_ASSERT(d->queued);
8830   CU_ASSERT(e->queued);
8831   CU_ASSERT(!f->queued);
8832
8833   CU_ASSERT(1 == nghttp2_pq_size(&a->obq));
8834   CU_ASSERT(2 == nghttp2_pq_size(&b->obq));
8835   CU_ASSERT(1 == nghttp2_pq_size(&c->obq));
8836   CU_ASSERT(nghttp2_pq_empty(&d->obq));
8837   CU_ASSERT(nghttp2_pq_empty(&e->obq));
8838   CU_ASSERT(nghttp2_pq_empty(&f->obq));
8839
8840   /* Remove subtree b */
8841
8842   nghttp2_stream_dep_remove_subtree(b);
8843   CU_ASSERT(0 == nghttp2_stream_dep_add_subtree(&session->root, b));
8844
8845   /*
8846    * b       a
8847    * |
8848    * e--c
8849    * |  |
8850    * f  d
8851    */
8852
8853   CU_ASSERT(!a->queued);
8854   CU_ASSERT(b->queued);
8855   CU_ASSERT(c->queued);
8856   CU_ASSERT(d->queued);
8857   CU_ASSERT(e->queued);
8858   CU_ASSERT(!f->queued);
8859
8860   CU_ASSERT(nghttp2_pq_empty(&a->obq));
8861   CU_ASSERT(2 == nghttp2_pq_size(&b->obq));
8862   CU_ASSERT(1 == nghttp2_pq_size(&c->obq));
8863   CU_ASSERT(nghttp2_pq_empty(&d->obq));
8864   CU_ASSERT(nghttp2_pq_empty(&e->obq));
8865   CU_ASSERT(nghttp2_pq_empty(&f->obq));
8866
8867   /* Remove subtree c, and detach item from b, and then re-add
8868      subtree c under b */
8869
8870   nghttp2_stream_dep_remove_subtree(c);
8871   nghttp2_stream_detach_item(b);
8872   nghttp2_stream_dep_add_subtree(b, c);
8873
8874   /*
8875    * b       a
8876    * |
8877    * e--c
8878    * |  |
8879    * f  d
8880    */
8881
8882   CU_ASSERT(!a->queued);
8883   CU_ASSERT(b->queued);
8884   CU_ASSERT(c->queued);
8885   CU_ASSERT(d->queued);
8886   CU_ASSERT(e->queued);
8887   CU_ASSERT(!f->queued);
8888
8889   CU_ASSERT(nghttp2_pq_empty(&a->obq));
8890   CU_ASSERT(2 == nghttp2_pq_size(&b->obq));
8891   CU_ASSERT(1 == nghttp2_pq_size(&c->obq));
8892   CU_ASSERT(nghttp2_pq_empty(&d->obq));
8893   CU_ASSERT(nghttp2_pq_empty(&e->obq));
8894   CU_ASSERT(nghttp2_pq_empty(&f->obq));
8895
8896   /* Attach data to a, and add subtree a under b */
8897
8898   da = create_data_ob_item(mem);
8899   nghttp2_stream_attach_item(a, da);
8900   nghttp2_stream_dep_remove_subtree(a);
8901   nghttp2_stream_dep_add_subtree(b, a);
8902
8903   /*
8904    * b
8905    * |
8906    * a--e--c
8907    *    |  |
8908    *    f  d
8909    */
8910
8911   CU_ASSERT(a->queued);
8912   CU_ASSERT(b->queued);
8913   CU_ASSERT(c->queued);
8914   CU_ASSERT(d->queued);
8915   CU_ASSERT(e->queued);
8916   CU_ASSERT(!f->queued);
8917
8918   CU_ASSERT(nghttp2_pq_empty(&a->obq));
8919   CU_ASSERT(3 == nghttp2_pq_size(&b->obq));
8920   CU_ASSERT(1 == nghttp2_pq_size(&c->obq));
8921   CU_ASSERT(nghttp2_pq_empty(&d->obq));
8922   CU_ASSERT(nghttp2_pq_empty(&e->obq));
8923   CU_ASSERT(nghttp2_pq_empty(&f->obq));
8924
8925   /* Remove subtree c, and add under f */
8926   nghttp2_stream_dep_remove_subtree(c);
8927   nghttp2_stream_dep_insert_subtree(f, c);
8928
8929   /*
8930    * b
8931    * |
8932    * a--e
8933    *    |
8934    *    f
8935    *    |
8936    *    c
8937    *    |
8938    *    d
8939    */
8940
8941   CU_ASSERT(a->queued);
8942   CU_ASSERT(b->queued);
8943   CU_ASSERT(c->queued);
8944   CU_ASSERT(d->queued);
8945   CU_ASSERT(e->queued);
8946   CU_ASSERT(f->queued);
8947
8948   CU_ASSERT(nghttp2_pq_empty(&a->obq));
8949   CU_ASSERT(2 == nghttp2_pq_size(&b->obq));
8950   CU_ASSERT(1 == nghttp2_pq_size(&c->obq));
8951   CU_ASSERT(nghttp2_pq_empty(&d->obq));
8952   CU_ASSERT(1 == nghttp2_pq_size(&e->obq));
8953   CU_ASSERT(1 == nghttp2_pq_size(&f->obq));
8954
8955   /* db has been detached */
8956   nghttp2_outbound_item_free(db, mem);
8957   free(db);
8958
8959   nghttp2_session_del(session);
8960 }
8961
8962 void test_nghttp2_session_stream_get_state(void) {
8963   nghttp2_session *session;
8964   nghttp2_session_callbacks callbacks;
8965   nghttp2_mem *mem;
8966   nghttp2_hd_deflater deflater;
8967   nghttp2_bufs bufs;
8968   nghttp2_buf *buf;
8969   nghttp2_stream *stream;
8970   ssize_t rv;
8971   nghttp2_data_provider data_prd;
8972   nghttp2_frame frame;
8973
8974   mem = nghttp2_mem_default();
8975   frame_pack_bufs_init(&bufs);
8976   memset(&data_prd, 0, sizeof(data_prd));
8977
8978   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
8979   callbacks.send_callback = null_send_callback;
8980
8981   nghttp2_session_server_new(&session, &callbacks, NULL);
8982   nghttp2_hd_deflate_init(&deflater, mem);
8983
8984   CU_ASSERT(NGHTTP2_STREAM_STATE_IDLE ==
8985             nghttp2_stream_get_state(nghttp2_session_get_root_stream(session)));
8986
8987   /* stream 1 HEADERS; without END_STREAM flag set */
8988   pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, reqnv,
8989                ARRLEN(reqnv), mem);
8990
8991   buf = &bufs.head->buf;
8992   rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
8993
8994   CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv);
8995
8996   stream = nghttp2_session_find_stream(session, 1);
8997
8998   CU_ASSERT(NULL != stream);
8999   CU_ASSERT(1 == stream->stream_id);
9000   CU_ASSERT(NGHTTP2_STREAM_STATE_OPEN == nghttp2_stream_get_state(stream));
9001
9002   nghttp2_bufs_reset(&bufs);
9003
9004   /* stream 3 HEADERS; with END_STREAM flag set */
9005   pack_headers(&bufs, &deflater, 3,
9006                NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM, reqnv,
9007                ARRLEN(reqnv), mem);
9008
9009   buf = &bufs.head->buf;
9010   rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
9011
9012   CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv);
9013
9014   stream = nghttp2_session_find_stream(session, 3);
9015
9016   CU_ASSERT(NULL != stream);
9017   CU_ASSERT(3 == stream->stream_id);
9018   CU_ASSERT(NGHTTP2_STREAM_STATE_HALF_CLOSED_REMOTE ==
9019             nghttp2_stream_get_state(stream));
9020
9021   nghttp2_bufs_reset(&bufs);
9022
9023   /* Respond to stream 1 */
9024   nghttp2_submit_response(session, 1, resnv, ARRLEN(resnv), NULL);
9025
9026   rv = nghttp2_session_send(session);
9027
9028   CU_ASSERT(0 == rv);
9029
9030   stream = nghttp2_session_find_stream(session, 1);
9031
9032   CU_ASSERT(NGHTTP2_STREAM_STATE_HALF_CLOSED_LOCAL ==
9033             nghttp2_stream_get_state(stream));
9034
9035   /* Respond to stream 3 */
9036   nghttp2_submit_response(session, 3, resnv, ARRLEN(resnv), NULL);
9037
9038   rv = nghttp2_session_send(session);
9039
9040   CU_ASSERT(0 == rv);
9041
9042   stream = nghttp2_session_find_stream(session, 3);
9043
9044   CU_ASSERT(NGHTTP2_STREAM_STATE_CLOSED == nghttp2_stream_get_state(stream));
9045
9046   /* stream 5 HEADERS; with END_STREAM flag set */
9047   pack_headers(&bufs, &deflater, 5,
9048                NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM, reqnv,
9049                ARRLEN(reqnv), mem);
9050
9051   buf = &bufs.head->buf;
9052   rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
9053
9054   CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv);
9055
9056   nghttp2_bufs_reset(&bufs);
9057
9058   /* Push stream 2 associated to stream 5 */
9059   rv = nghttp2_submit_push_promise(session, NGHTTP2_FLAG_NONE, 5, reqnv,
9060                                    ARRLEN(reqnv), NULL);
9061
9062   CU_ASSERT(2 == rv);
9063
9064   rv = nghttp2_session_send(session);
9065
9066   CU_ASSERT(0 == rv);
9067
9068   stream = nghttp2_session_find_stream(session, 2);
9069
9070   CU_ASSERT(NGHTTP2_STREAM_STATE_RESERVED_LOCAL ==
9071             nghttp2_stream_get_state(stream));
9072
9073   /* Send resposne to push stream 2 with END_STREAM set */
9074   nghttp2_submit_response(session, 2, resnv, ARRLEN(resnv), NULL);
9075
9076   rv = nghttp2_session_send(session);
9077
9078   CU_ASSERT(0 == rv);
9079
9080   stream = nghttp2_session_find_stream(session, 2);
9081
9082   /* At server, pushed stream object is not retained after closed */
9083   CU_ASSERT(NULL == stream);
9084
9085   /* Push stream 4 associated to stream 5 */
9086   rv = nghttp2_submit_push_promise(session, NGHTTP2_FLAG_NONE, 5, reqnv,
9087                                    ARRLEN(reqnv), NULL);
9088
9089   CU_ASSERT(4 == rv);
9090
9091   rv = nghttp2_session_send(session);
9092
9093   CU_ASSERT(0 == rv);
9094
9095   stream = nghttp2_session_find_stream(session, 4);
9096
9097   CU_ASSERT(NGHTTP2_STREAM_STATE_RESERVED_LOCAL ==
9098             nghttp2_stream_get_state(stream));
9099
9100   /* Send response to push stream 4 without closing */
9101   data_prd.read_callback = defer_data_source_read_callback;
9102
9103   nghttp2_submit_response(session, 4, resnv, ARRLEN(resnv), &data_prd);
9104
9105   rv = nghttp2_session_send(session);
9106
9107   CU_ASSERT(0 == rv);
9108
9109   stream = nghttp2_session_find_stream(session, 4);
9110
9111   CU_ASSERT(NGHTTP2_STREAM_STATE_HALF_CLOSED_REMOTE ==
9112             nghttp2_stream_get_state(stream));
9113
9114   /* Create idle stream by PRIORITY frame */
9115   nghttp2_frame_priority_init(&frame.priority, 7, &pri_spec_default);
9116
9117   rv = nghttp2_frame_pack_priority(&bufs, &frame.priority);
9118
9119   CU_ASSERT(0 == rv);
9120
9121   nghttp2_frame_priority_free(&frame.priority);
9122
9123   buf = &bufs.head->buf;
9124   rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
9125
9126   CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv);
9127
9128   stream = nghttp2_session_find_stream(session, 7);
9129
9130   CU_ASSERT(NGHTTP2_STREAM_STATE_IDLE == nghttp2_stream_get_state(stream));
9131
9132   nghttp2_bufs_reset(&bufs);
9133
9134   nghttp2_hd_deflate_free(&deflater);
9135   nghttp2_session_del(session);
9136
9137   /* Test for client side */
9138
9139   nghttp2_session_client_new(&session, &callbacks, NULL);
9140   nghttp2_hd_deflate_init(&deflater, mem);
9141
9142   nghttp2_submit_request(session, NULL, reqnv, ARRLEN(reqnv), NULL, NULL);
9143
9144   rv = nghttp2_session_send(session);
9145
9146   CU_ASSERT(0 == rv);
9147
9148   /* Receive PUSH_PROMISE 2 associated to stream 1 */
9149   pack_push_promise(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, 2, reqnv,
9150                     ARRLEN(reqnv), mem);
9151
9152   buf = &bufs.head->buf;
9153   rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
9154
9155   CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv);
9156
9157   stream = nghttp2_session_find_stream(session, 2);
9158
9159   CU_ASSERT(NGHTTP2_STREAM_STATE_RESERVED_REMOTE ==
9160             nghttp2_stream_get_state(stream));
9161
9162   nghttp2_bufs_reset(&bufs);
9163
9164   /* Receive push response for stream 2 without END_STREAM set */
9165   pack_headers(&bufs, &deflater, 2, NGHTTP2_FLAG_END_HEADERS, resnv,
9166                ARRLEN(resnv), mem);
9167
9168   buf = &bufs.head->buf;
9169   rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
9170
9171   CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv);
9172
9173   stream = nghttp2_session_find_stream(session, 2);
9174
9175   CU_ASSERT(NGHTTP2_STREAM_STATE_HALF_CLOSED_LOCAL ==
9176             nghttp2_stream_get_state(stream));
9177
9178   nghttp2_bufs_reset(&bufs);
9179
9180   nghttp2_hd_deflate_free(&deflater);
9181   nghttp2_session_del(session);
9182
9183   nghttp2_bufs_free(&bufs);
9184 }
9185
9186 void test_nghttp2_session_stream_get_something(void) {
9187   nghttp2_session *session;
9188   nghttp2_session_callbacks callbacks;
9189   nghttp2_stream *a, *b, *c;
9190
9191   memset(&callbacks, 0, sizeof(callbacks));
9192
9193   nghttp2_session_server_new(&session, &callbacks, NULL);
9194
9195   a = open_stream(session, 1);
9196
9197   CU_ASSERT(nghttp2_session_get_root_stream(session) ==
9198             nghttp2_stream_get_parent(a));
9199   CU_ASSERT(NULL == nghttp2_stream_get_previous_sibling(a));
9200   CU_ASSERT(NULL == nghttp2_stream_get_next_sibling(a));
9201   CU_ASSERT(NULL == nghttp2_stream_get_first_child(a));
9202
9203   b = open_stream_with_dep(session, 3, a);
9204   c = open_stream_with_dep_weight(session, 5, 11, a);
9205
9206   CU_ASSERT(a == nghttp2_stream_get_parent(c));
9207   CU_ASSERT(a == nghttp2_stream_get_parent(b));
9208
9209   CU_ASSERT(c == nghttp2_stream_get_first_child(a));
9210
9211   CU_ASSERT(b == nghttp2_stream_get_next_sibling(c));
9212   CU_ASSERT(c == nghttp2_stream_get_previous_sibling(b));
9213
9214   CU_ASSERT(27 == nghttp2_stream_get_sum_dependency_weight(a));
9215
9216   CU_ASSERT(11 == nghttp2_stream_get_weight(c));
9217   CU_ASSERT(5 == nghttp2_stream_get_stream_id(c));
9218   CU_ASSERT(0 == nghttp2_stream_get_stream_id(&session->root));
9219
9220   nghttp2_session_del(session);
9221 }
9222
9223 void test_nghttp2_session_find_stream(void) {
9224   nghttp2_session *session;
9225   nghttp2_session_callbacks callbacks;
9226   nghttp2_stream *stream;
9227
9228   memset(&callbacks, 0, sizeof(callbacks));
9229
9230   nghttp2_session_server_new(&session, &callbacks, NULL);
9231
9232   open_recv_stream(session, 1);
9233
9234   stream = nghttp2_session_find_stream(session, 1);
9235
9236   CU_ASSERT(NULL != stream);
9237   CU_ASSERT(1 == stream->stream_id);
9238
9239   stream = nghttp2_session_find_stream(session, 0);
9240
9241   CU_ASSERT(&session->root == stream);
9242   CU_ASSERT(0 == stream->stream_id);
9243
9244   stream = nghttp2_session_find_stream(session, 2);
9245
9246   CU_ASSERT(NULL == stream);
9247
9248   nghttp2_session_del(session);
9249 }
9250
9251 void test_nghttp2_session_keep_closed_stream(void) {
9252   nghttp2_session *session;
9253   nghttp2_session_callbacks callbacks;
9254   const size_t max_concurrent_streams = 5;
9255   nghttp2_settings_entry iv = {NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS,
9256                                (uint32_t)max_concurrent_streams};
9257   size_t i;
9258
9259   memset(&callbacks, 0, sizeof(callbacks));
9260   callbacks.send_callback = null_send_callback;
9261
9262   nghttp2_session_server_new(&session, &callbacks, NULL);
9263
9264   nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, &iv, 1);
9265
9266   for (i = 0; i < max_concurrent_streams; ++i) {
9267     open_recv_stream(session, (int32_t)i * 2 + 1);
9268   }
9269
9270   CU_ASSERT(0 == session->num_closed_streams);
9271
9272   nghttp2_session_close_stream(session, 1, NGHTTP2_NO_ERROR);
9273
9274   CU_ASSERT(1 == session->num_closed_streams);
9275   CU_ASSERT(1 == session->closed_stream_tail->stream_id);
9276   CU_ASSERT(session->closed_stream_tail == session->closed_stream_head);
9277
9278   nghttp2_session_close_stream(session, 5, NGHTTP2_NO_ERROR);
9279
9280   CU_ASSERT(2 == session->num_closed_streams);
9281   CU_ASSERT(5 == session->closed_stream_tail->stream_id);
9282   CU_ASSERT(1 == session->closed_stream_head->stream_id);
9283   CU_ASSERT(session->closed_stream_head ==
9284             session->closed_stream_tail->closed_prev);
9285   CU_ASSERT(NULL == session->closed_stream_tail->closed_next);
9286   CU_ASSERT(session->closed_stream_tail ==
9287             session->closed_stream_head->closed_next);
9288   CU_ASSERT(NULL == session->closed_stream_head->closed_prev);
9289
9290   open_recv_stream(session, 11);
9291   nghttp2_session_adjust_closed_stream(session);
9292
9293   CU_ASSERT(1 == session->num_closed_streams);
9294   CU_ASSERT(5 == session->closed_stream_tail->stream_id);
9295   CU_ASSERT(session->closed_stream_tail == session->closed_stream_head);
9296   CU_ASSERT(NULL == session->closed_stream_head->closed_prev);
9297   CU_ASSERT(NULL == session->closed_stream_head->closed_next);
9298
9299   open_recv_stream(session, 13);
9300   nghttp2_session_adjust_closed_stream(session);
9301
9302   CU_ASSERT(0 == session->num_closed_streams);
9303   CU_ASSERT(NULL == session->closed_stream_tail);
9304   CU_ASSERT(NULL == session->closed_stream_head);
9305
9306   nghttp2_session_close_stream(session, 3, NGHTTP2_NO_ERROR);
9307
9308   CU_ASSERT(1 == session->num_closed_streams);
9309   CU_ASSERT(3 == session->closed_stream_head->stream_id);
9310
9311   /* server initiated stream is not counted to max concurrent limit */
9312   open_sent_stream(session, 2);
9313   nghttp2_session_adjust_closed_stream(session);
9314
9315   CU_ASSERT(1 == session->num_closed_streams);
9316   CU_ASSERT(3 == session->closed_stream_head->stream_id);
9317
9318   nghttp2_session_close_stream(session, 2, NGHTTP2_NO_ERROR);
9319
9320   CU_ASSERT(1 == session->num_closed_streams);
9321   CU_ASSERT(3 == session->closed_stream_head->stream_id);
9322
9323   nghttp2_session_del(session);
9324 }
9325
9326 void test_nghttp2_session_keep_idle_stream(void) {
9327   nghttp2_session *session;
9328   nghttp2_session_callbacks callbacks;
9329   const size_t max_concurrent_streams = 1;
9330   nghttp2_settings_entry iv = {NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS,
9331                                (uint32_t)max_concurrent_streams};
9332   int i;
9333   int32_t stream_id;
9334
9335   memset(&callbacks, 0, sizeof(callbacks));
9336   callbacks.send_callback = null_send_callback;
9337
9338   nghttp2_session_server_new(&session, &callbacks, NULL);
9339
9340   nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, &iv, 1);
9341
9342   /* We at least allow NGHTTP2_MIN_IDLE_STREAM idle streams even if
9343      max concurrent streams is very low. */
9344   for (i = 0; i < NGHTTP2_MIN_IDLE_STREAMS; ++i) {
9345     open_recv_stream2(session, i * 2 + 1, NGHTTP2_STREAM_IDLE);
9346     nghttp2_session_adjust_idle_stream(session);
9347   }
9348
9349   CU_ASSERT(NGHTTP2_MIN_IDLE_STREAMS == session->num_idle_streams);
9350
9351   stream_id = (NGHTTP2_MIN_IDLE_STREAMS - 1) * 2 + 1;
9352   CU_ASSERT(1 == session->idle_stream_head->stream_id);
9353   CU_ASSERT(stream_id == session->idle_stream_tail->stream_id);
9354
9355   stream_id += 2;
9356
9357   open_recv_stream2(session, stream_id, NGHTTP2_STREAM_IDLE);
9358   nghttp2_session_adjust_idle_stream(session);
9359
9360   CU_ASSERT(NGHTTP2_MIN_IDLE_STREAMS == session->num_idle_streams);
9361   CU_ASSERT(3 == session->idle_stream_head->stream_id);
9362   CU_ASSERT(stream_id == session->idle_stream_tail->stream_id);
9363
9364   nghttp2_session_del(session);
9365 }
9366
9367 void test_nghttp2_session_detach_idle_stream(void) {
9368   nghttp2_session *session;
9369   nghttp2_session_callbacks callbacks;
9370   int i;
9371   nghttp2_stream *stream;
9372
9373   memset(&callbacks, 0, sizeof(callbacks));
9374   callbacks.send_callback = null_send_callback;
9375
9376   nghttp2_session_server_new(&session, &callbacks, NULL);
9377
9378   for (i = 1; i <= 3; ++i) {
9379     nghttp2_session_open_stream(session, i, NGHTTP2_STREAM_FLAG_NONE,
9380                                 &pri_spec_default, NGHTTP2_STREAM_IDLE, NULL);
9381   }
9382
9383   CU_ASSERT(3 == session->num_idle_streams);
9384
9385   /* Detach middle stream */
9386   stream = nghttp2_session_get_stream_raw(session, 2);
9387
9388   CU_ASSERT(session->idle_stream_head == stream->closed_prev);
9389   CU_ASSERT(session->idle_stream_tail == stream->closed_next);
9390   CU_ASSERT(stream == session->idle_stream_head->closed_next);
9391   CU_ASSERT(stream == session->idle_stream_tail->closed_prev);
9392
9393   nghttp2_session_detach_idle_stream(session, stream);
9394
9395   CU_ASSERT(2 == session->num_idle_streams);
9396
9397   CU_ASSERT(NULL == stream->closed_prev);
9398   CU_ASSERT(NULL == stream->closed_next);
9399
9400   CU_ASSERT(session->idle_stream_head ==
9401             session->idle_stream_tail->closed_prev);
9402   CU_ASSERT(session->idle_stream_tail ==
9403             session->idle_stream_head->closed_next);
9404
9405   /* Detach head stream */
9406   stream = session->idle_stream_head;
9407
9408   nghttp2_session_detach_idle_stream(session, stream);
9409
9410   CU_ASSERT(1 == session->num_idle_streams);
9411
9412   CU_ASSERT(session->idle_stream_head == session->idle_stream_tail);
9413   CU_ASSERT(NULL == session->idle_stream_head->closed_prev);
9414   CU_ASSERT(NULL == session->idle_stream_head->closed_next);
9415
9416   /* Detach last stream */
9417
9418   stream = session->idle_stream_head;
9419
9420   nghttp2_session_detach_idle_stream(session, stream);
9421
9422   CU_ASSERT(0 == session->num_idle_streams);
9423
9424   CU_ASSERT(NULL == session->idle_stream_head);
9425   CU_ASSERT(NULL == session->idle_stream_tail);
9426
9427   for (i = 4; i <= 5; ++i) {
9428     nghttp2_session_open_stream(session, i, NGHTTP2_STREAM_FLAG_NONE,
9429                                 &pri_spec_default, NGHTTP2_STREAM_IDLE, NULL);
9430   }
9431
9432   CU_ASSERT(2 == session->num_idle_streams);
9433
9434   /* Detach tail stream */
9435
9436   stream = session->idle_stream_tail;
9437
9438   nghttp2_session_detach_idle_stream(session, stream);
9439
9440   CU_ASSERT(1 == session->num_idle_streams);
9441
9442   CU_ASSERT(session->idle_stream_head == session->idle_stream_tail);
9443   CU_ASSERT(NULL == session->idle_stream_head->closed_prev);
9444   CU_ASSERT(NULL == session->idle_stream_head->closed_next);
9445
9446   nghttp2_session_del(session);
9447 }
9448
9449 void test_nghttp2_session_large_dep_tree(void) {
9450   nghttp2_session *session;
9451   nghttp2_session_callbacks callbacks;
9452   size_t i;
9453   nghttp2_stream *dep_stream = NULL;
9454   nghttp2_stream *stream;
9455   int32_t stream_id;
9456
9457   memset(&callbacks, 0, sizeof(callbacks));
9458   callbacks.send_callback = null_send_callback;
9459
9460   nghttp2_session_server_new(&session, &callbacks, NULL);
9461
9462   stream_id = 1;
9463   for (i = 0; i < 250; ++i, stream_id += 2) {
9464     dep_stream = open_stream_with_dep(session, stream_id, dep_stream);
9465   }
9466
9467   stream_id = 1;
9468   for (i = 0; i < 250; ++i, stream_id += 2) {
9469     stream = nghttp2_session_get_stream(session, stream_id);
9470     CU_ASSERT(nghttp2_stream_dep_find_ancestor(stream, &session->root));
9471     CU_ASSERT(nghttp2_stream_in_dep_tree(stream));
9472   }
9473
9474   nghttp2_session_del(session);
9475 }
9476
9477 void test_nghttp2_session_graceful_shutdown(void) {
9478   nghttp2_session *session;
9479   nghttp2_session_callbacks callbacks;
9480   my_user_data ud;
9481
9482   memset(&callbacks, 0, sizeof(callbacks));
9483   callbacks.send_callback = null_send_callback;
9484   callbacks.on_frame_send_callback = on_frame_send_callback;
9485   callbacks.on_stream_close_callback = on_stream_close_callback;
9486
9487   nghttp2_session_server_new(&session, &callbacks, &ud);
9488
9489   open_recv_stream(session, 301);
9490   open_sent_stream(session, 302);
9491   open_recv_stream(session, 309);
9492   open_recv_stream(session, 311);
9493   open_recv_stream(session, 319);
9494
9495   CU_ASSERT(0 == nghttp2_submit_shutdown_notice(session));
9496
9497   ud.frame_send_cb_called = 0;
9498
9499   CU_ASSERT(0 == nghttp2_session_send(session));
9500
9501   CU_ASSERT(1 == ud.frame_send_cb_called);
9502   CU_ASSERT((1u << 31) - 1 == session->local_last_stream_id);
9503
9504   CU_ASSERT(0 == nghttp2_submit_goaway(session, NGHTTP2_FLAG_NONE, 311,
9505                                        NGHTTP2_NO_ERROR, NULL, 0));
9506
9507   ud.frame_send_cb_called = 0;
9508   ud.stream_close_cb_called = 0;
9509
9510   CU_ASSERT(0 == nghttp2_session_send(session));
9511
9512   CU_ASSERT(1 == ud.frame_send_cb_called);
9513   CU_ASSERT(311 == session->local_last_stream_id);
9514   CU_ASSERT(1 == ud.stream_close_cb_called);
9515
9516   CU_ASSERT(0 ==
9517             nghttp2_session_terminate_session2(session, 301, NGHTTP2_NO_ERROR));
9518
9519   ud.frame_send_cb_called = 0;
9520   ud.stream_close_cb_called = 0;
9521
9522   CU_ASSERT(0 == nghttp2_session_send(session));
9523
9524   CU_ASSERT(1 == ud.frame_send_cb_called);
9525   CU_ASSERT(301 == session->local_last_stream_id);
9526   CU_ASSERT(2 == ud.stream_close_cb_called);
9527
9528   CU_ASSERT(NULL != nghttp2_session_get_stream(session, 301));
9529   CU_ASSERT(NULL != nghttp2_session_get_stream(session, 302));
9530   CU_ASSERT(NULL == nghttp2_session_get_stream(session, 309));
9531   CU_ASSERT(NULL == nghttp2_session_get_stream(session, 311));
9532   CU_ASSERT(NULL == nghttp2_session_get_stream(session, 319));
9533
9534   nghttp2_session_del(session);
9535 }
9536
9537 void test_nghttp2_session_on_header_temporal_failure(void) {
9538   nghttp2_session *session;
9539   nghttp2_session_callbacks callbacks;
9540   my_user_data ud;
9541   nghttp2_bufs bufs;
9542   nghttp2_buf *buf;
9543   nghttp2_hd_deflater deflater;
9544   nghttp2_nv nv[] = {MAKE_NV("alpha", "bravo"), MAKE_NV("charlie", "delta")};
9545   nghttp2_nv *nva;
9546   size_t hdpos;
9547   ssize_t rv;
9548   nghttp2_frame frame;
9549   nghttp2_frame_hd hd;
9550   nghttp2_outbound_item *item;
9551   nghttp2_mem *mem;
9552
9553   mem = nghttp2_mem_default();
9554   memset(&callbacks, 0, sizeof(callbacks));
9555   callbacks.on_header_callback = temporal_failure_on_header_callback;
9556
9557   nghttp2_session_server_new(&session, &callbacks, &ud);
9558
9559   frame_pack_bufs_init(&bufs);
9560
9561   nghttp2_hd_deflate_init(&deflater, mem);
9562
9563   nghttp2_nv_array_copy(&nva, reqnv, ARRLEN(reqnv), mem);
9564
9565   nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_STREAM, 1,
9566                              NGHTTP2_HCAT_REQUEST, NULL, nva, ARRLEN(reqnv));
9567   nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
9568   nghttp2_frame_headers_free(&frame.headers, mem);
9569
9570   /* We are going to create CONTINUATION.  First serialize header
9571      block, and then frame header. */
9572   hdpos = nghttp2_bufs_len(&bufs);
9573
9574   buf = &bufs.head->buf;
9575   buf->last += NGHTTP2_FRAME_HDLEN;
9576
9577   nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, &nv[1], 1);
9578
9579   nghttp2_frame_hd_init(&hd,
9580                         nghttp2_bufs_len(&bufs) - hdpos - NGHTTP2_FRAME_HDLEN,
9581                         NGHTTP2_CONTINUATION, NGHTTP2_FLAG_END_HEADERS, 1);
9582
9583   nghttp2_frame_pack_frame_hd(&buf->pos[hdpos], &hd);
9584
9585   ud.header_cb_called = 0;
9586   rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_bufs_len(&bufs));
9587
9588   CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == rv);
9589   CU_ASSERT(1 == ud.header_cb_called);
9590
9591   item = nghttp2_session_get_next_ob_item(session);
9592
9593   CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
9594   CU_ASSERT(1 == item->frame.hd.stream_id);
9595
9596   /* Make sure no header decompression error occurred */
9597   CU_ASSERT(NGHTTP2_GOAWAY_NONE == session->goaway_flags);
9598
9599   nghttp2_hd_deflate_free(&deflater);
9600   nghttp2_session_del(session);
9601
9602   nghttp2_bufs_reset(&bufs);
9603
9604   /* Check for PUSH_PROMISE */
9605   nghttp2_hd_deflate_init(&deflater, mem);
9606   nghttp2_session_client_new(&session, &callbacks, &ud);
9607
9608   open_sent_stream(session, 1);
9609
9610   rv = pack_push_promise(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, 2,
9611                          reqnv, ARRLEN(reqnv), mem);
9612   CU_ASSERT(0 == rv);
9613
9614   ud.header_cb_called = 0;
9615   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
9616                                 nghttp2_bufs_len(&bufs));
9617   CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == rv);
9618   CU_ASSERT(1 == ud.header_cb_called);
9619
9620   item = nghttp2_session_get_next_ob_item(session);
9621   CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
9622   CU_ASSERT(2 == item->frame.hd.stream_id);
9623   CU_ASSERT(NGHTTP2_INTERNAL_ERROR == item->frame.rst_stream.error_code);
9624
9625   nghttp2_session_del(session);
9626   nghttp2_hd_deflate_free(&deflater);
9627   nghttp2_bufs_free(&bufs);
9628 }
9629
9630 void test_nghttp2_session_recv_client_magic(void) {
9631   nghttp2_session *session;
9632   nghttp2_session_callbacks callbacks;
9633   ssize_t rv;
9634   nghttp2_frame ping_frame;
9635   uint8_t buf[16];
9636
9637   /* enable global nghttp2_enable_strict_preface here */
9638   nghttp2_enable_strict_preface = 1;
9639
9640   memset(&callbacks, 0, sizeof(callbacks));
9641
9642   /* Check success case */
9643   nghttp2_session_server_new(&session, &callbacks, NULL);
9644
9645   rv = nghttp2_session_mem_recv(session, (const uint8_t *)NGHTTP2_CLIENT_MAGIC,
9646                                 NGHTTP2_CLIENT_MAGIC_LEN);
9647
9648   CU_ASSERT(rv == NGHTTP2_CLIENT_MAGIC_LEN);
9649   CU_ASSERT(NGHTTP2_IB_READ_FIRST_SETTINGS == session->iframe.state);
9650
9651   /* Receiving PING is error because we want SETTINGS. */
9652   nghttp2_frame_ping_init(&ping_frame.ping, NGHTTP2_FLAG_NONE, NULL);
9653
9654   nghttp2_frame_pack_frame_hd(buf, &ping_frame.ping.hd);
9655
9656   rv = nghttp2_session_mem_recv(session, buf, NGHTTP2_FRAME_HDLEN);
9657   CU_ASSERT(NGHTTP2_FRAME_HDLEN == rv);
9658   CU_ASSERT(NGHTTP2_IB_IGN_ALL == session->iframe.state);
9659   CU_ASSERT(0 == session->iframe.payloadleft);
9660
9661   nghttp2_frame_ping_free(&ping_frame.ping);
9662
9663   nghttp2_session_del(session);
9664
9665   /* Check bad case */
9666   nghttp2_session_server_new(&session, &callbacks, NULL);
9667
9668   /* Feed magic with one byte less */
9669   rv = nghttp2_session_mem_recv(session, (const uint8_t *)NGHTTP2_CLIENT_MAGIC,
9670                                 NGHTTP2_CLIENT_MAGIC_LEN - 1);
9671
9672   CU_ASSERT(rv == NGHTTP2_CLIENT_MAGIC_LEN - 1);
9673   CU_ASSERT(NGHTTP2_IB_READ_CLIENT_MAGIC == session->iframe.state);
9674   CU_ASSERT(1 == session->iframe.payloadleft);
9675
9676   rv = nghttp2_session_mem_recv(session, (const uint8_t *)"\0", 1);
9677
9678   CU_ASSERT(NGHTTP2_ERR_BAD_CLIENT_MAGIC == rv);
9679
9680   nghttp2_session_del(session);
9681
9682   /* disable global nghttp2_enable_strict_preface here */
9683   nghttp2_enable_strict_preface = 0;
9684 }
9685
9686 void test_nghttp2_session_delete_data_item(void) {
9687   nghttp2_session *session;
9688   nghttp2_session_callbacks callbacks;
9689   nghttp2_stream *a;
9690   nghttp2_data_provider prd;
9691
9692   memset(&callbacks, 0, sizeof(callbacks));
9693
9694   nghttp2_session_server_new(&session, &callbacks, NULL);
9695
9696   a = open_recv_stream(session, 1);
9697   open_recv_stream_with_dep(session, 3, a);
9698
9699   /* We don't care about these members, since we won't send data */
9700   prd.source.ptr = NULL;
9701   prd.read_callback = fail_data_source_read_callback;
9702
9703   CU_ASSERT(0 == nghttp2_submit_data(session, NGHTTP2_FLAG_NONE, 1, &prd));
9704   CU_ASSERT(0 == nghttp2_submit_data(session, NGHTTP2_FLAG_NONE, 3, &prd));
9705
9706   nghttp2_session_del(session);
9707 }
9708
9709 void test_nghttp2_session_open_idle_stream(void) {
9710   nghttp2_session *session;
9711   nghttp2_session_callbacks callbacks;
9712   nghttp2_stream *stream;
9713   nghttp2_stream *opened_stream;
9714   nghttp2_priority_spec pri_spec;
9715   nghttp2_frame frame;
9716
9717   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
9718
9719   nghttp2_session_server_new(&session, &callbacks, NULL);
9720
9721   nghttp2_priority_spec_init(&pri_spec, 0, 3, 0);
9722
9723   nghttp2_frame_priority_init(&frame.priority, 1, &pri_spec);
9724
9725   CU_ASSERT(0 == nghttp2_session_on_priority_received(session, &frame));
9726
9727   stream = nghttp2_session_get_stream_raw(session, 1);
9728
9729   CU_ASSERT(NGHTTP2_STREAM_IDLE == stream->state);
9730   CU_ASSERT(NULL == stream->closed_prev);
9731   CU_ASSERT(NULL == stream->closed_next);
9732   CU_ASSERT(1 == session->num_idle_streams);
9733   CU_ASSERT(session->idle_stream_head == stream);
9734   CU_ASSERT(session->idle_stream_tail == stream);
9735
9736   opened_stream = open_recv_stream2(session, 1, NGHTTP2_STREAM_OPENING);
9737
9738   CU_ASSERT(stream == opened_stream);
9739   CU_ASSERT(NGHTTP2_STREAM_OPENING == stream->state);
9740   CU_ASSERT(0 == session->num_idle_streams);
9741   CU_ASSERT(NULL == session->idle_stream_head);
9742   CU_ASSERT(NULL == session->idle_stream_tail);
9743
9744   nghttp2_frame_priority_free(&frame.priority);
9745
9746   nghttp2_session_del(session);
9747 }
9748
9749 void test_nghttp2_session_cancel_reserved_remote(void) {
9750   nghttp2_session *session;
9751   nghttp2_session_callbacks callbacks;
9752   nghttp2_stream *stream;
9753   nghttp2_frame frame;
9754   nghttp2_nv *nva;
9755   size_t nvlen;
9756   nghttp2_hd_deflater deflater;
9757   nghttp2_mem *mem;
9758   nghttp2_bufs bufs;
9759   ssize_t rv;
9760
9761   mem = nghttp2_mem_default();
9762   frame_pack_bufs_init(&bufs);
9763
9764   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
9765   callbacks.send_callback = null_send_callback;
9766
9767   nghttp2_session_client_new(&session, &callbacks, NULL);
9768
9769   nghttp2_hd_deflate_init(&deflater, mem);
9770
9771   stream = open_recv_stream2(session, 2, NGHTTP2_STREAM_RESERVED);
9772
9773   nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, 2, NGHTTP2_CANCEL);
9774
9775   CU_ASSERT(NGHTTP2_STREAM_CLOSING == stream->state);
9776
9777   CU_ASSERT(0 == nghttp2_session_send(session));
9778
9779   nvlen = ARRLEN(resnv);
9780   nghttp2_nv_array_copy(&nva, resnv, nvlen, mem);
9781
9782   nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 2,
9783                              NGHTTP2_HCAT_PUSH_RESPONSE, NULL, nva, nvlen);
9784   rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
9785
9786   CU_ASSERT(0 == rv);
9787
9788   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
9789                                 nghttp2_buf_len(&bufs.head->buf));
9790
9791   CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
9792
9793   /* stream is not dangling, so assign NULL */
9794   stream = NULL;
9795
9796   /* No RST_STREAM or GOAWAY is generated since stream should be in
9797      NGHTTP2_STREAM_CLOSING and push response should be ignored. */
9798   CU_ASSERT(0 == nghttp2_outbound_queue_size(&session->ob_reg));
9799
9800   /* Check that we can receive push response HEADERS while RST_STREAM
9801      is just queued. */
9802   open_recv_stream2(session, 4, NGHTTP2_STREAM_RESERVED);
9803
9804   nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, 2, NGHTTP2_CANCEL);
9805
9806   nghttp2_bufs_reset(&bufs);
9807
9808   frame.hd.stream_id = 4;
9809   rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
9810
9811   CU_ASSERT(0 == rv);
9812
9813   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
9814                                 nghttp2_buf_len(&bufs.head->buf));
9815
9816   CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
9817
9818   CU_ASSERT(1 == nghttp2_outbound_queue_size(&session->ob_reg));
9819
9820   nghttp2_frame_headers_free(&frame.headers, mem);
9821
9822   nghttp2_hd_deflate_free(&deflater);
9823
9824   nghttp2_session_del(session);
9825
9826   nghttp2_bufs_free(&bufs);
9827 }
9828
9829 void test_nghttp2_session_reset_pending_headers(void) {
9830   nghttp2_session *session;
9831   nghttp2_session_callbacks callbacks;
9832   nghttp2_stream *stream;
9833   int32_t stream_id;
9834   my_user_data ud;
9835
9836   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
9837   callbacks.send_callback = null_send_callback;
9838   callbacks.on_frame_send_callback = on_frame_send_callback;
9839   callbacks.on_frame_not_send_callback = on_frame_not_send_callback;
9840   callbacks.on_stream_close_callback = on_stream_close_callback;
9841
9842   nghttp2_session_client_new(&session, &callbacks, &ud);
9843
9844   stream_id = nghttp2_submit_request(session, NULL, NULL, 0, NULL, NULL);
9845   CU_ASSERT(stream_id >= 1);
9846
9847   nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, stream_id,
9848                             NGHTTP2_CANCEL);
9849
9850   session->remote_settings.max_concurrent_streams = 0;
9851
9852   /* RST_STREAM cancels pending HEADERS and is not actually sent. */
9853   ud.frame_send_cb_called = 0;
9854   CU_ASSERT(0 == nghttp2_session_send(session));
9855
9856   CU_ASSERT(0 == ud.frame_send_cb_called);
9857
9858   stream = nghttp2_session_get_stream(session, stream_id);
9859
9860   CU_ASSERT(NULL == stream);
9861
9862   /* See HEADERS is not sent.  on_stream_close is called just like
9863      transmission failure. */
9864   session->remote_settings.max_concurrent_streams = 1;
9865
9866   ud.frame_not_send_cb_called = 0;
9867   ud.stream_close_error_code = 0;
9868   CU_ASSERT(0 == nghttp2_session_send(session));
9869
9870   CU_ASSERT(1 == ud.frame_not_send_cb_called);
9871   CU_ASSERT(NGHTTP2_HEADERS == ud.not_sent_frame_type);
9872   CU_ASSERT(NGHTTP2_CANCEL == ud.stream_close_error_code);
9873
9874   stream = nghttp2_session_get_stream(session, stream_id);
9875
9876   CU_ASSERT(NULL == stream);
9877
9878   nghttp2_session_del(session);
9879 }
9880
9881 void test_nghttp2_session_send_data_callback(void) {
9882   nghttp2_session *session;
9883   nghttp2_session_callbacks callbacks;
9884   nghttp2_data_provider data_prd;
9885   my_user_data ud;
9886   accumulator acc;
9887   nghttp2_frame_hd hd;
9888
9889   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
9890   callbacks.send_callback = accumulator_send_callback;
9891   callbacks.send_data_callback = send_data_callback;
9892
9893   data_prd.read_callback = no_copy_data_source_read_callback;
9894
9895   acc.length = 0;
9896   ud.acc = &acc;
9897
9898   ud.data_source_length = NGHTTP2_DATA_PAYLOADLEN * 2;
9899
9900   nghttp2_session_client_new(&session, &callbacks, &ud);
9901
9902   open_sent_stream(session, 1);
9903
9904   nghttp2_submit_data(session, NGHTTP2_FLAG_END_STREAM, 1, &data_prd);
9905
9906   CU_ASSERT(0 == nghttp2_session_send(session));
9907
9908   CU_ASSERT((NGHTTP2_FRAME_HDLEN + NGHTTP2_DATA_PAYLOADLEN) * 2 == acc.length);
9909
9910   nghttp2_frame_unpack_frame_hd(&hd, acc.buf);
9911
9912   CU_ASSERT(16384 == hd.length);
9913   CU_ASSERT(NGHTTP2_DATA == hd.type);
9914   CU_ASSERT(NGHTTP2_FLAG_NONE == hd.flags);
9915
9916   nghttp2_frame_unpack_frame_hd(&hd, acc.buf + NGHTTP2_FRAME_HDLEN + hd.length);
9917
9918   CU_ASSERT(16384 == hd.length);
9919   CU_ASSERT(NGHTTP2_DATA == hd.type);
9920   CU_ASSERT(NGHTTP2_FLAG_END_STREAM == hd.flags);
9921
9922   nghttp2_session_del(session);
9923 }
9924
9925 void test_nghttp2_session_on_begin_headers_temporal_failure(void) {
9926   nghttp2_session *session;
9927   nghttp2_session_callbacks callbacks;
9928   my_user_data ud;
9929   nghttp2_bufs bufs;
9930   nghttp2_mem *mem;
9931   ssize_t rv;
9932   nghttp2_hd_deflater deflater;
9933   nghttp2_outbound_item *item;
9934
9935   mem = nghttp2_mem_default();
9936   frame_pack_bufs_init(&bufs);
9937   nghttp2_hd_deflate_init(&deflater, mem);
9938
9939   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
9940   callbacks.on_begin_headers_callback =
9941       temporal_failure_on_begin_headers_callback;
9942   callbacks.on_header_callback = on_header_callback;
9943   callbacks.on_frame_recv_callback = on_frame_recv_callback;
9944   callbacks.send_callback = null_send_callback;
9945   nghttp2_session_server_new(&session, &callbacks, &ud);
9946
9947   rv = pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, reqnv,
9948                     ARRLEN(reqnv), mem);
9949   CU_ASSERT(0 == rv);
9950
9951   ud.header_cb_called = 0;
9952   ud.frame_recv_cb_called = 0;
9953   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
9954                                 nghttp2_bufs_len(&bufs));
9955   CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == rv);
9956   CU_ASSERT(0 == ud.header_cb_called);
9957   CU_ASSERT(0 == ud.frame_recv_cb_called);
9958
9959   item = nghttp2_session_get_next_ob_item(session);
9960   CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
9961   CU_ASSERT(1 == item->frame.hd.stream_id);
9962   CU_ASSERT(NGHTTP2_INTERNAL_ERROR == item->frame.rst_stream.error_code);
9963
9964   nghttp2_session_del(session);
9965   nghttp2_hd_deflate_free(&deflater);
9966
9967   nghttp2_bufs_reset(&bufs);
9968   /* check for PUSH_PROMISE */
9969   nghttp2_hd_deflate_init(&deflater, mem);
9970   nghttp2_session_client_new(&session, &callbacks, &ud);
9971
9972   open_sent_stream(session, 1);
9973
9974   rv = pack_push_promise(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, 2,
9975                          reqnv, ARRLEN(reqnv), mem);
9976   CU_ASSERT(0 == rv);
9977
9978   ud.header_cb_called = 0;
9979   ud.frame_recv_cb_called = 0;
9980   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
9981                                 nghttp2_bufs_len(&bufs));
9982   CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == rv);
9983   CU_ASSERT(0 == ud.header_cb_called);
9984   CU_ASSERT(0 == ud.frame_recv_cb_called);
9985
9986   item = nghttp2_session_get_next_ob_item(session);
9987   CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
9988   CU_ASSERT(2 == item->frame.hd.stream_id);
9989   CU_ASSERT(NGHTTP2_INTERNAL_ERROR == item->frame.rst_stream.error_code);
9990
9991   nghttp2_session_del(session);
9992   nghttp2_hd_deflate_free(&deflater);
9993   nghttp2_bufs_free(&bufs);
9994 }
9995
9996 void test_nghttp2_session_defer_then_close(void) {
9997   nghttp2_session *session;
9998   nghttp2_session_callbacks callbacks;
9999   nghttp2_data_provider prd;
10000   int rv;
10001   const uint8_t *datap;
10002   ssize_t datalen;
10003   nghttp2_frame frame;
10004
10005   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
10006   callbacks.send_callback = null_send_callback;
10007
10008   nghttp2_session_client_new(&session, &callbacks, NULL);
10009
10010   prd.read_callback = defer_data_source_read_callback;
10011
10012   rv = nghttp2_submit_request(session, NULL, reqnv, ARRLEN(reqnv), &prd, NULL);
10013   CU_ASSERT(rv > 0);
10014
10015   /* This sends HEADERS */
10016   datalen = nghttp2_session_mem_send(session, &datap);
10017
10018   CU_ASSERT(datalen > 0);
10019
10020   /* This makes DATA item deferred */
10021   datalen = nghttp2_session_mem_send(session, &datap);
10022
10023   CU_ASSERT(datalen == 0);
10024
10025   nghttp2_frame_rst_stream_init(&frame.rst_stream, 1, NGHTTP2_CANCEL);
10026
10027   /* Assertion failure; GH-264 */
10028   rv = nghttp2_session_on_rst_stream_received(session, &frame);
10029
10030   CU_ASSERT(rv == 0);
10031
10032   nghttp2_session_del(session);
10033 }
10034
10035 static int submit_response_on_stream_close(nghttp2_session *session,
10036                                            int32_t stream_id,
10037                                            uint32_t error_code,
10038                                            void *user_data) {
10039   nghttp2_data_provider data_prd;
10040   (void)error_code;
10041   (void)user_data;
10042
10043   data_prd.read_callback = temporal_failure_data_source_read_callback;
10044
10045   // Attempt to submit response or data to the stream being closed
10046   switch (stream_id) {
10047   case 1:
10048     CU_ASSERT(0 == nghttp2_submit_response(session, stream_id, resnv,
10049                                            ARRLEN(resnv), &data_prd));
10050     break;
10051   case 3:
10052     CU_ASSERT(0 == nghttp2_submit_data(session, NGHTTP2_FLAG_NONE, stream_id,
10053                                        &data_prd));
10054     break;
10055   }
10056
10057   return 0;
10058 }
10059
10060 void test_nghttp2_session_detach_item_from_closed_stream(void) {
10061   nghttp2_session *session;
10062   nghttp2_session_callbacks callbacks;
10063
10064   memset(&callbacks, 0, sizeof(callbacks));
10065
10066   callbacks.send_callback = null_send_callback;
10067   callbacks.on_stream_close_callback = submit_response_on_stream_close;
10068
10069   nghttp2_session_server_new(&session, &callbacks, NULL);
10070
10071   open_recv_stream(session, 1);
10072   open_recv_stream(session, 3);
10073
10074   nghttp2_session_close_stream(session, 1, NGHTTP2_NO_ERROR);
10075   nghttp2_session_close_stream(session, 3, NGHTTP2_NO_ERROR);
10076
10077   CU_ASSERT(0 == nghttp2_session_send(session));
10078
10079   nghttp2_session_del(session);
10080 }
10081
10082 void test_nghttp2_session_flooding(void) {
10083   nghttp2_session *session;
10084   nghttp2_session_callbacks callbacks;
10085   nghttp2_bufs bufs;
10086   nghttp2_buf *buf;
10087   nghttp2_frame frame;
10088   nghttp2_mem *mem;
10089   size_t i;
10090
10091   mem = nghttp2_mem_default();
10092
10093   frame_pack_bufs_init(&bufs);
10094
10095   memset(&callbacks, 0, sizeof(callbacks));
10096
10097   /* PING ACK */
10098   nghttp2_session_server_new(&session, &callbacks, NULL);
10099
10100   nghttp2_frame_ping_init(&frame.ping, NGHTTP2_FLAG_NONE, NULL);
10101   nghttp2_frame_pack_ping(&bufs, &frame.ping);
10102   nghttp2_frame_ping_free(&frame.ping);
10103
10104   buf = &bufs.head->buf;
10105
10106   for (i = 0; i < NGHTTP2_DEFAULT_MAX_OBQ_FLOOD_ITEM; ++i) {
10107     CU_ASSERT(
10108         (ssize_t)nghttp2_buf_len(buf) ==
10109         nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf)));
10110   }
10111
10112   CU_ASSERT(NGHTTP2_ERR_FLOODED ==
10113             nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf)));
10114
10115   nghttp2_session_del(session);
10116
10117   /* SETTINGS ACK */
10118   nghttp2_bufs_reset(&bufs);
10119
10120   nghttp2_session_server_new(&session, &callbacks, NULL);
10121
10122   nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE, NULL, 0);
10123   nghttp2_frame_pack_settings(&bufs, &frame.settings);
10124   nghttp2_frame_settings_free(&frame.settings, mem);
10125
10126   buf = &bufs.head->buf;
10127
10128   for (i = 0; i < NGHTTP2_DEFAULT_MAX_OBQ_FLOOD_ITEM; ++i) {
10129     CU_ASSERT(
10130         (ssize_t)nghttp2_buf_len(buf) ==
10131         nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf)));
10132   }
10133
10134   CU_ASSERT(NGHTTP2_ERR_FLOODED ==
10135             nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf)));
10136
10137   nghttp2_session_del(session);
10138   nghttp2_bufs_free(&bufs);
10139 }
10140
10141 void test_nghttp2_session_change_stream_priority(void) {
10142   nghttp2_session *session;
10143   nghttp2_session_callbacks callbacks;
10144   nghttp2_stream *stream1, *stream2, *stream3, *stream5;
10145   nghttp2_priority_spec pri_spec;
10146   int rv;
10147
10148   memset(&callbacks, 0, sizeof(callbacks));
10149
10150   nghttp2_session_server_new(&session, &callbacks, NULL);
10151
10152   stream1 = open_recv_stream(session, 1);
10153   stream3 = open_recv_stream_with_dep_weight(session, 3, 199, stream1);
10154   stream2 = open_sent_stream_with_dep_weight(session, 2, 101, stream3);
10155
10156   nghttp2_priority_spec_init(&pri_spec, 1, 256, 0);
10157
10158   rv = nghttp2_session_change_stream_priority(session, 2, &pri_spec);
10159
10160   CU_ASSERT(0 == rv);
10161
10162   CU_ASSERT(stream1 == stream2->dep_prev);
10163   CU_ASSERT(256 == stream2->weight);
10164
10165   /* Cannot change stream which does not exist */
10166   rv = nghttp2_session_change_stream_priority(session, 5, &pri_spec);
10167   CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT == rv);
10168
10169   /* It is an error to depend on itself */
10170   rv = nghttp2_session_change_stream_priority(session, 1, &pri_spec);
10171   CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT == rv);
10172
10173   /* It is an error to change priority of root stream (0) */
10174   rv = nghttp2_session_change_stream_priority(session, 0, &pri_spec);
10175   CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT == rv);
10176
10177   /* Depends on the non-existing idle stream.  This creates that idle
10178      stream. */
10179   nghttp2_priority_spec_init(&pri_spec, 5, 9, 1);
10180
10181   rv = nghttp2_session_change_stream_priority(session, 2, &pri_spec);
10182
10183   CU_ASSERT(0 == rv);
10184
10185   stream5 = nghttp2_session_get_stream_raw(session, 5);
10186
10187   CU_ASSERT(NULL != stream5);
10188   CU_ASSERT(&session->root == stream5->dep_prev);
10189   CU_ASSERT(stream5 == stream2->dep_prev);
10190   CU_ASSERT(9 == stream2->weight);
10191
10192   nghttp2_session_del(session);
10193
10194   /* Check that this works in client session too */
10195   nghttp2_session_client_new(&session, &callbacks, NULL);
10196
10197   stream1 = open_sent_stream(session, 1);
10198
10199   nghttp2_priority_spec_init(&pri_spec, 5, 9, 1);
10200
10201   rv = nghttp2_session_change_stream_priority(session, 1, &pri_spec);
10202
10203   CU_ASSERT(0 == rv);
10204
10205   stream5 = nghttp2_session_get_stream_raw(session, 5);
10206
10207   CU_ASSERT(NULL != stream5);
10208   CU_ASSERT(&session->root == stream5->dep_prev);
10209   CU_ASSERT(stream5 == stream1->dep_prev);
10210   CU_ASSERT(9 == stream1->weight);
10211
10212   nghttp2_session_del(session);
10213 }
10214
10215 void test_nghttp2_session_create_idle_stream(void) {
10216   nghttp2_session *session;
10217   nghttp2_session_callbacks callbacks;
10218   nghttp2_stream *stream2, *stream4, *stream8, *stream10;
10219   nghttp2_priority_spec pri_spec;
10220   int rv;
10221   int i;
10222
10223   memset(&callbacks, 0, sizeof(callbacks));
10224   callbacks.send_callback = null_send_callback;
10225
10226   nghttp2_session_server_new(&session, &callbacks, NULL);
10227
10228   stream2 = open_sent_stream(session, 2);
10229
10230   nghttp2_priority_spec_init(&pri_spec, 2, 111, 1);
10231
10232   rv = nghttp2_session_create_idle_stream(session, 4, &pri_spec);
10233
10234   CU_ASSERT(0 == rv);
10235
10236   stream4 = nghttp2_session_get_stream_raw(session, 4);
10237
10238   CU_ASSERT(4 == stream4->stream_id);
10239   CU_ASSERT(111 == stream4->weight);
10240   CU_ASSERT(stream2 == stream4->dep_prev);
10241   CU_ASSERT(stream4 == stream2->dep_next);
10242
10243   /* If pri_spec->stream_id does not exist, and it is idle stream, it
10244      is created too */
10245   nghttp2_priority_spec_init(&pri_spec, 10, 109, 0);
10246
10247   rv = nghttp2_session_create_idle_stream(session, 8, &pri_spec);
10248
10249   CU_ASSERT(0 == rv);
10250
10251   stream8 = nghttp2_session_get_stream_raw(session, 8);
10252   stream10 = nghttp2_session_get_stream_raw(session, 10);
10253
10254   CU_ASSERT(8 == stream8->stream_id);
10255   CU_ASSERT(109 == stream8->weight);
10256   CU_ASSERT(10 == stream10->stream_id);
10257   CU_ASSERT(16 == stream10->weight);
10258   CU_ASSERT(stream10 == stream8->dep_prev);
10259   CU_ASSERT(&session->root == stream10->dep_prev);
10260
10261   /* It is an error to attempt to create already existing idle
10262      stream */
10263   rv = nghttp2_session_create_idle_stream(session, 4, &pri_spec);
10264
10265   CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT == rv);
10266
10267   /* It is an error to depend on itself */
10268   pri_spec.stream_id = 6;
10269
10270   rv = nghttp2_session_create_idle_stream(session, 6, &pri_spec);
10271   CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT == rv);
10272
10273   /* It is an error to create root stream (0) as idle stream */
10274   rv = nghttp2_session_create_idle_stream(session, 0, &pri_spec);
10275   CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT == rv);
10276
10277   /* It is an error to create non-idle stream */
10278   session->last_sent_stream_id = 20;
10279   pri_spec.stream_id = 2;
10280
10281   rv = nghttp2_session_create_idle_stream(session, 18, &pri_spec);
10282
10283   CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT == rv);
10284
10285   nghttp2_session_del(session);
10286
10287   /* Check that this works in client session too */
10288   nghttp2_session_client_new(&session, &callbacks, NULL);
10289
10290   nghttp2_priority_spec_init(&pri_spec, 4, 99, 1);
10291
10292   rv = nghttp2_session_create_idle_stream(session, 2, &pri_spec);
10293
10294   CU_ASSERT(0 == rv);
10295
10296   stream4 = nghttp2_session_get_stream_raw(session, 4);
10297   stream2 = nghttp2_session_get_stream_raw(session, 2);
10298
10299   CU_ASSERT(NULL != stream4);
10300   CU_ASSERT(NULL != stream2);
10301   CU_ASSERT(&session->root == stream4->dep_prev);
10302   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == stream4->weight);
10303   CU_ASSERT(stream4 == stream2->dep_prev);
10304   CU_ASSERT(99 == stream2->weight);
10305
10306   nghttp2_session_del(session);
10307
10308   /* Check that idle stream is reduced when nghttp2_session_send() is
10309      called. */
10310   nghttp2_session_server_new(&session, &callbacks, NULL);
10311
10312   session->local_settings.max_concurrent_streams = 30;
10313
10314   nghttp2_priority_spec_init(&pri_spec, 0, 16, 0);
10315   for (i = 0; i < 100; ++i) {
10316     rv = nghttp2_session_create_idle_stream(session, i * 2 + 1, &pri_spec);
10317
10318     CU_ASSERT(0 == rv);
10319
10320     nghttp2_priority_spec_init(&pri_spec, i * 2 + 1, 16, 0);
10321   }
10322
10323   CU_ASSERT(100 == session->num_idle_streams);
10324   CU_ASSERT(0 == nghttp2_session_send(session));
10325   CU_ASSERT(30 == session->num_idle_streams);
10326   CU_ASSERT(141 == session->idle_stream_head->stream_id);
10327
10328   nghttp2_session_del(session);
10329
10330   /* Check that idle stream is reduced when nghttp2_session_mem_recv() is
10331      called. */
10332   nghttp2_session_client_new(&session, &callbacks, NULL);
10333
10334   session->local_settings.max_concurrent_streams = 30;
10335
10336   nghttp2_priority_spec_init(&pri_spec, 0, 16, 0);
10337   for (i = 0; i < 100; ++i) {
10338     rv = nghttp2_session_create_idle_stream(session, i * 2 + 1, &pri_spec);
10339
10340     CU_ASSERT(0 == rv);
10341
10342     nghttp2_priority_spec_init(&pri_spec, i * 2 + 1, 16, 0);
10343   }
10344
10345   CU_ASSERT(100 == session->num_idle_streams);
10346   CU_ASSERT(0 == nghttp2_session_mem_recv(session, NULL, 0));
10347   CU_ASSERT(30 == session->num_idle_streams);
10348   CU_ASSERT(141 == session->idle_stream_head->stream_id);
10349
10350   nghttp2_session_del(session);
10351 }
10352
10353 void test_nghttp2_session_repeated_priority_change(void) {
10354   nghttp2_session *session;
10355   nghttp2_session_callbacks callbacks;
10356   nghttp2_frame frame;
10357   nghttp2_priority_spec pri_spec;
10358   int32_t stream_id, last_stream_id;
10359   int32_t max_streams = 20;
10360
10361   memset(&callbacks, 0, sizeof(callbacks));
10362
10363   nghttp2_session_server_new(&session, &callbacks, NULL);
10364
10365   session->local_settings.max_concurrent_streams = (uint32_t)max_streams;
10366
10367   /* 1 -> 0 */
10368   nghttp2_priority_spec_init(&pri_spec, 0, 16, 0);
10369   nghttp2_frame_priority_init(&frame.priority, 1, &pri_spec);
10370
10371   CU_ASSERT(0 == nghttp2_session_on_priority_received(session, &frame));
10372
10373   nghttp2_frame_priority_free(&frame.priority);
10374
10375   last_stream_id = max_streams * 2 + 1;
10376
10377   for (stream_id = 3; stream_id < last_stream_id; stream_id += 2) {
10378     /* 1 -> stream_id */
10379     nghttp2_priority_spec_init(&pri_spec, stream_id, 16, 0);
10380     nghttp2_frame_priority_init(&frame.priority, 1, &pri_spec);
10381
10382     CU_ASSERT(0 == nghttp2_session_on_priority_received(session, &frame));
10383
10384     nghttp2_frame_priority_free(&frame.priority);
10385   }
10386
10387   CU_ASSERT(20 == session->num_idle_streams);
10388   CU_ASSERT(1 == session->idle_stream_head->stream_id);
10389
10390   /* 1 -> last_stream_id */
10391   nghttp2_priority_spec_init(&pri_spec, last_stream_id, 16, 0);
10392   nghttp2_frame_priority_init(&frame.priority, 1, &pri_spec);
10393
10394   CU_ASSERT(0 == nghttp2_session_on_priority_received(session, &frame));
10395
10396   nghttp2_frame_priority_free(&frame.priority);
10397
10398   CU_ASSERT(20 == session->num_idle_streams);
10399   CU_ASSERT(3 == session->idle_stream_head->stream_id);
10400
10401   nghttp2_session_del(session);
10402 }
10403
10404 void test_nghttp2_session_repeated_priority_submission(void) {
10405   nghttp2_session *session;
10406   nghttp2_session_callbacks callbacks;
10407   nghttp2_priority_spec pri_spec;
10408   int32_t stream_id, last_stream_id;
10409   uint32_t max_streams = NGHTTP2_MIN_IDLE_STREAMS;
10410
10411   memset(&callbacks, 0, sizeof(callbacks));
10412
10413   callbacks.send_callback = null_send_callback;
10414
10415   nghttp2_session_client_new(&session, &callbacks, NULL);
10416
10417   session->local_settings.max_concurrent_streams = max_streams;
10418
10419   /* 1 -> 0 */
10420   nghttp2_priority_spec_init(&pri_spec, 0, 16, 0);
10421
10422   CU_ASSERT(0 ==
10423             nghttp2_submit_priority(session, NGHTTP2_FLAG_NONE, 1, &pri_spec));
10424
10425   last_stream_id = (int32_t)(max_streams * 2 + 1);
10426
10427   for (stream_id = 3; stream_id < last_stream_id; stream_id += 2) {
10428     /* 1 -> stream_id */
10429     nghttp2_priority_spec_init(&pri_spec, stream_id, 16, 0);
10430
10431     CU_ASSERT(
10432         0 == nghttp2_submit_priority(session, NGHTTP2_FLAG_NONE, 1, &pri_spec));
10433   }
10434
10435   CU_ASSERT(0 == nghttp2_session_send(session));
10436   CU_ASSERT(max_streams == session->num_idle_streams);
10437   CU_ASSERT(1 == session->idle_stream_head->stream_id);
10438
10439   /* 1 -> last_stream_id */
10440   nghttp2_priority_spec_init(&pri_spec, last_stream_id, 16, 0);
10441
10442   CU_ASSERT(0 ==
10443             nghttp2_submit_priority(session, NGHTTP2_FLAG_NONE, 1, &pri_spec));
10444
10445   CU_ASSERT(0 == nghttp2_session_send(session));
10446   CU_ASSERT(max_streams == session->num_idle_streams);
10447   CU_ASSERT(3 == session->idle_stream_head->stream_id);
10448
10449   nghttp2_session_del(session);
10450 }
10451
10452 void test_nghttp2_session_set_local_window_size(void) {
10453   nghttp2_session *session;
10454   nghttp2_session_callbacks callbacks;
10455   nghttp2_outbound_item *item;
10456   nghttp2_stream *stream;
10457
10458   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
10459   callbacks.send_callback = null_send_callback;
10460
10461   nghttp2_session_client_new(&session, &callbacks, NULL);
10462   stream = open_sent_stream(session, 1);
10463   stream->recv_window_size = 4096;
10464
10465   CU_ASSERT(0 == nghttp2_session_set_local_window_size(
10466                      session, NGHTTP2_FLAG_NONE, 1, 65536));
10467   CU_ASSERT(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE + 1 ==
10468             stream->local_window_size);
10469   CU_ASSERT(4096 == stream->recv_window_size);
10470   CU_ASSERT(65536 - 4096 ==
10471             nghttp2_session_get_stream_local_window_size(session, 1));
10472
10473   item = nghttp2_session_get_next_ob_item(session);
10474
10475   CU_ASSERT(NGHTTP2_WINDOW_UPDATE == item->frame.hd.type);
10476   CU_ASSERT(1 == item->frame.window_update.hd.stream_id);
10477   CU_ASSERT(1 == item->frame.window_update.window_size_increment);
10478
10479   CU_ASSERT(0 == nghttp2_session_send(session));
10480
10481   /* Go decrement part */
10482   CU_ASSERT(0 == nghttp2_session_set_local_window_size(
10483                      session, NGHTTP2_FLAG_NONE, 1, 32768));
10484   CU_ASSERT(32768 == stream->local_window_size);
10485   CU_ASSERT(-28672 == stream->recv_window_size);
10486   CU_ASSERT(32768 == stream->recv_reduction);
10487   CU_ASSERT(65536 - 4096 ==
10488             nghttp2_session_get_stream_local_window_size(session, 1));
10489
10490   item = nghttp2_session_get_next_ob_item(session);
10491
10492   CU_ASSERT(item == NULL);
10493
10494   /* Increase local window size */
10495   CU_ASSERT(0 == nghttp2_session_set_local_window_size(
10496                      session, NGHTTP2_FLAG_NONE, 1, 49152));
10497   CU_ASSERT(49152 == stream->local_window_size);
10498   CU_ASSERT(-12288 == stream->recv_window_size);
10499   CU_ASSERT(16384 == stream->recv_reduction);
10500   CU_ASSERT(65536 - 4096 ==
10501             nghttp2_session_get_stream_local_window_size(session, 1));
10502   CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
10503
10504   /* Increase local window again */
10505   CU_ASSERT(0 == nghttp2_session_set_local_window_size(
10506                      session, NGHTTP2_FLAG_NONE, 1, 65537));
10507   CU_ASSERT(65537 == stream->local_window_size);
10508   CU_ASSERT(4096 == stream->recv_window_size);
10509   CU_ASSERT(0 == stream->recv_reduction);
10510   CU_ASSERT(65537 - 4096 ==
10511             nghttp2_session_get_stream_local_window_size(session, 1));
10512
10513   item = nghttp2_session_get_next_ob_item(session);
10514
10515   CU_ASSERT(1 == item->frame.window_update.window_size_increment);
10516
10517   CU_ASSERT(0 == nghttp2_session_send(session));
10518
10519   /* Check connection-level flow control */
10520   session->recv_window_size = 4096;
10521   CU_ASSERT(0 == nghttp2_session_set_local_window_size(
10522                      session, NGHTTP2_FLAG_NONE, 0, 65536));
10523   CU_ASSERT(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE + 1 ==
10524             session->local_window_size);
10525   CU_ASSERT(4096 == session->recv_window_size);
10526   CU_ASSERT(65536 - 4096 == nghttp2_session_get_local_window_size(session));
10527
10528   item = nghttp2_session_get_next_ob_item(session);
10529
10530   CU_ASSERT(NGHTTP2_WINDOW_UPDATE == item->frame.hd.type);
10531   CU_ASSERT(0 == item->frame.window_update.hd.stream_id);
10532   CU_ASSERT(1 == item->frame.window_update.window_size_increment);
10533
10534   CU_ASSERT(0 == nghttp2_session_send(session));
10535
10536   /* Go decrement part */
10537   CU_ASSERT(0 == nghttp2_session_set_local_window_size(
10538                      session, NGHTTP2_FLAG_NONE, 0, 32768));
10539   CU_ASSERT(32768 == session->local_window_size);
10540   CU_ASSERT(-28672 == session->recv_window_size);
10541   CU_ASSERT(32768 == session->recv_reduction);
10542   CU_ASSERT(65536 - 4096 == nghttp2_session_get_local_window_size(session));
10543
10544   item = nghttp2_session_get_next_ob_item(session);
10545
10546   CU_ASSERT(item == NULL);
10547
10548   /* Increase local window size */
10549   CU_ASSERT(0 == nghttp2_session_set_local_window_size(
10550                      session, NGHTTP2_FLAG_NONE, 0, 49152));
10551   CU_ASSERT(49152 == session->local_window_size);
10552   CU_ASSERT(-12288 == session->recv_window_size);
10553   CU_ASSERT(16384 == session->recv_reduction);
10554   CU_ASSERT(65536 - 4096 == nghttp2_session_get_local_window_size(session));
10555   CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
10556
10557   /* Increase local window again */
10558   CU_ASSERT(0 == nghttp2_session_set_local_window_size(
10559                      session, NGHTTP2_FLAG_NONE, 0, 65537));
10560   CU_ASSERT(65537 == session->local_window_size);
10561   CU_ASSERT(4096 == session->recv_window_size);
10562   CU_ASSERT(0 == session->recv_reduction);
10563   CU_ASSERT(65537 - 4096 == nghttp2_session_get_local_window_size(session));
10564
10565   item = nghttp2_session_get_next_ob_item(session);
10566
10567   CU_ASSERT(1 == item->frame.window_update.window_size_increment);
10568
10569   CU_ASSERT(0 == nghttp2_session_send(session));
10570
10571   nghttp2_session_del(session);
10572
10573   /* Make sure that nghttp2_session_set_local_window_size submits
10574      WINDOW_UPDATE if necessary to increase stream-level window. */
10575   nghttp2_session_client_new(&session, &callbacks, NULL);
10576   stream = open_sent_stream(session, 1);
10577   stream->recv_window_size = NGHTTP2_INITIAL_WINDOW_SIZE;
10578
10579   CU_ASSERT(0 == nghttp2_session_set_local_window_size(
10580                      session, NGHTTP2_FLAG_NONE, 1, 0));
10581   CU_ASSERT(0 == stream->recv_window_size);
10582   CU_ASSERT(0 == nghttp2_session_get_stream_local_window_size(session, 1));
10583   /* This should submit WINDOW_UPDATE frame because stream-level
10584      receiving window is now full. */
10585   CU_ASSERT(0 ==
10586             nghttp2_session_set_local_window_size(session, NGHTTP2_FLAG_NONE, 1,
10587                                                   NGHTTP2_INITIAL_WINDOW_SIZE));
10588   CU_ASSERT(0 == stream->recv_window_size);
10589   CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE ==
10590             nghttp2_session_get_stream_local_window_size(session, 1));
10591
10592   item = nghttp2_session_get_next_ob_item(session);
10593
10594   CU_ASSERT(NGHTTP2_WINDOW_UPDATE == item->frame.hd.type);
10595   CU_ASSERT(1 == item->frame.hd.stream_id);
10596   CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE ==
10597             item->frame.window_update.window_size_increment);
10598
10599   nghttp2_session_del(session);
10600
10601   /* Make sure that nghttp2_session_set_local_window_size submits
10602      WINDOW_UPDATE if necessary to increase connection-level
10603      window. */
10604   nghttp2_session_client_new(&session, &callbacks, NULL);
10605   session->recv_window_size = NGHTTP2_INITIAL_WINDOW_SIZE;
10606
10607   CU_ASSERT(0 == nghttp2_session_set_local_window_size(
10608                      session, NGHTTP2_FLAG_NONE, 0, 0));
10609   CU_ASSERT(0 == session->recv_window_size);
10610   CU_ASSERT(0 == nghttp2_session_get_local_window_size(session));
10611   /* This should submit WINDOW_UPDATE frame because connection-level
10612      receiving window is now full. */
10613   CU_ASSERT(0 ==
10614             nghttp2_session_set_local_window_size(session, NGHTTP2_FLAG_NONE, 0,
10615                                                   NGHTTP2_INITIAL_WINDOW_SIZE));
10616   CU_ASSERT(0 == session->recv_window_size);
10617   CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE ==
10618             nghttp2_session_get_local_window_size(session));
10619
10620   item = nghttp2_session_get_next_ob_item(session);
10621
10622   CU_ASSERT(NGHTTP2_WINDOW_UPDATE == item->frame.hd.type);
10623   CU_ASSERT(0 == item->frame.hd.stream_id);
10624   CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE ==
10625             item->frame.window_update.window_size_increment);
10626
10627   nghttp2_session_del(session);
10628 }
10629
10630 void test_nghttp2_session_cancel_from_before_frame_send(void) {
10631   int rv;
10632   nghttp2_session *session;
10633   nghttp2_session_callbacks callbacks;
10634   my_user_data ud;
10635   nghttp2_settings_entry iv;
10636   nghttp2_data_provider data_prd;
10637   int32_t stream_id;
10638   nghttp2_stream *stream;
10639
10640   memset(&callbacks, 0, sizeof(callbacks));
10641
10642   callbacks.before_frame_send_callback = cancel_before_frame_send_callback;
10643   callbacks.on_frame_not_send_callback = on_frame_not_send_callback;
10644   callbacks.send_callback = null_send_callback;
10645
10646   nghttp2_session_client_new(&session, &callbacks, &ud);
10647
10648   iv.settings_id = 0;
10649   iv.value = 1000000009;
10650
10651   rv = nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, &iv, 1);
10652
10653   CU_ASSERT(0 == rv);
10654
10655   ud.frame_send_cb_called = 0;
10656   ud.before_frame_send_cb_called = 0;
10657   ud.frame_not_send_cb_called = 0;
10658
10659   rv = nghttp2_session_send(session);
10660
10661   CU_ASSERT(0 == rv);
10662   CU_ASSERT(0 == ud.frame_send_cb_called);
10663   CU_ASSERT(1 == ud.before_frame_send_cb_called);
10664   CU_ASSERT(1 == ud.frame_not_send_cb_called);
10665
10666   data_prd.source.ptr = NULL;
10667   data_prd.read_callback = temporal_failure_data_source_read_callback;
10668
10669   stream_id = nghttp2_submit_request(session, NULL, reqnv, ARRLEN(reqnv),
10670                                      &data_prd, NULL);
10671
10672   CU_ASSERT(stream_id > 0);
10673
10674   ud.frame_send_cb_called = 0;
10675   ud.before_frame_send_cb_called = 0;
10676   ud.frame_not_send_cb_called = 0;
10677
10678   rv = nghttp2_session_send(session);
10679
10680   CU_ASSERT(0 == rv);
10681   CU_ASSERT(0 == ud.frame_send_cb_called);
10682   CU_ASSERT(1 == ud.before_frame_send_cb_called);
10683   CU_ASSERT(1 == ud.frame_not_send_cb_called);
10684
10685   stream = nghttp2_session_get_stream_raw(session, stream_id);
10686
10687   CU_ASSERT(NULL == stream);
10688
10689   nghttp2_session_del(session);
10690
10691   nghttp2_session_server_new(&session, &callbacks, &ud);
10692
10693   open_recv_stream(session, 1);
10694
10695   stream_id = nghttp2_submit_push_promise(session, NGHTTP2_FLAG_NONE, 1, reqnv,
10696                                           ARRLEN(reqnv), NULL);
10697
10698   CU_ASSERT(stream_id > 0);
10699
10700   ud.frame_send_cb_called = 0;
10701   ud.before_frame_send_cb_called = 0;
10702   ud.frame_not_send_cb_called = 0;
10703
10704   rv = nghttp2_session_send(session);
10705
10706   CU_ASSERT(0 == rv);
10707   CU_ASSERT(0 == ud.frame_send_cb_called);
10708   CU_ASSERT(1 == ud.before_frame_send_cb_called);
10709   CU_ASSERT(1 == ud.frame_not_send_cb_called);
10710
10711   stream = nghttp2_session_get_stream_raw(session, stream_id);
10712
10713   CU_ASSERT(NULL == stream);
10714
10715   nghttp2_session_del(session);
10716 }
10717
10718 void test_nghttp2_session_too_many_settings(void) {
10719   nghttp2_session *session;
10720   nghttp2_option *option;
10721   nghttp2_session_callbacks callbacks;
10722   nghttp2_frame frame;
10723   nghttp2_bufs bufs;
10724   nghttp2_buf *buf;
10725   ssize_t rv;
10726   my_user_data ud;
10727   nghttp2_settings_entry iv[3];
10728   nghttp2_mem *mem;
10729   nghttp2_outbound_item *item;
10730
10731   mem = nghttp2_mem_default();
10732   frame_pack_bufs_init(&bufs);
10733
10734   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
10735   callbacks.on_frame_recv_callback = on_frame_recv_callback;
10736   callbacks.send_callback = null_send_callback;
10737
10738   nghttp2_option_new(&option);
10739   nghttp2_option_set_max_settings(option, 1);
10740
10741   nghttp2_session_client_new2(&session, &callbacks, &ud, option);
10742
10743   CU_ASSERT(1 == session->max_settings);
10744
10745   nghttp2_option_del(option);
10746
10747   iv[0].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
10748   iv[0].value = 3000;
10749
10750   iv[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
10751   iv[1].value = 16384;
10752
10753   nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE, dup_iv(iv, 2),
10754                               2);
10755
10756   rv = nghttp2_frame_pack_settings(&bufs, &frame.settings);
10757
10758   CU_ASSERT(0 == rv);
10759   CU_ASSERT(nghttp2_bufs_len(&bufs) > 0);
10760
10761   nghttp2_frame_settings_free(&frame.settings, mem);
10762
10763   buf = &bufs.head->buf;
10764   assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
10765
10766   ud.frame_recv_cb_called = 0;
10767
10768   rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
10769   CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv);
10770
10771   item = nghttp2_session_get_next_ob_item(session);
10772   CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
10773
10774   nghttp2_bufs_reset(&bufs);
10775   nghttp2_bufs_free(&bufs);
10776   nghttp2_session_del(session);
10777 }
10778
10779 static void
10780 prepare_session_removed_closed_stream(nghttp2_session *session,
10781                                       nghttp2_hd_deflater *deflater) {
10782   int rv;
10783   nghttp2_settings_entry iv;
10784   nghttp2_bufs bufs;
10785   nghttp2_mem *mem;
10786   ssize_t nread;
10787   int i;
10788   nghttp2_stream *stream;
10789   nghttp2_frame_hd hd;
10790
10791   mem = nghttp2_mem_default();
10792
10793   frame_pack_bufs_init(&bufs);
10794
10795   iv.settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS;
10796   iv.value = 2;
10797
10798   rv = nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, &iv, 1);
10799
10800   CU_ASSERT(0 == rv);
10801
10802   rv = nghttp2_session_send(session);
10803
10804   CU_ASSERT(0 == rv);
10805
10806   for (i = 1; i <= 3; i += 2) {
10807     rv = pack_headers(&bufs, deflater, i,
10808                       NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM, reqnv,
10809                       ARRLEN(reqnv), mem);
10810
10811     CU_ASSERT(0 == rv);
10812
10813     nread = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
10814                                      nghttp2_bufs_len(&bufs));
10815
10816     CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == nread);
10817
10818     nghttp2_bufs_reset(&bufs);
10819   }
10820
10821   nghttp2_session_close_stream(session, 3, NGHTTP2_NO_ERROR);
10822
10823   rv = pack_headers(&bufs, deflater, 5,
10824                     NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM, reqnv,
10825                     ARRLEN(reqnv), mem);
10826
10827   CU_ASSERT(0 == rv);
10828
10829   /* Receiving stream 5 will erase stream 3 from closed stream list */
10830   nread = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
10831                                    nghttp2_bufs_len(&bufs));
10832
10833   CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == nread);
10834
10835   stream = nghttp2_session_get_stream_raw(session, 3);
10836
10837   CU_ASSERT(NULL == stream);
10838
10839   /* Since the current max concurrent streams is
10840      NGHTTP2_DEFAULT_MAX_CONCURRENT_STREAMS, receiving frame on stream
10841      3 is ignored. */
10842   nghttp2_bufs_reset(&bufs);
10843   rv = pack_headers(&bufs, deflater, 3,
10844                     NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM,
10845                     trailernv, ARRLEN(trailernv), mem);
10846
10847   CU_ASSERT(0 == rv);
10848
10849   nread = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
10850                                    nghttp2_bufs_len(&bufs));
10851
10852   CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == nread);
10853   CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
10854
10855   nghttp2_frame_hd_init(&hd, 0, NGHTTP2_DATA, NGHTTP2_FLAG_NONE, 3);
10856   nghttp2_bufs_reset(&bufs);
10857   nghttp2_frame_pack_frame_hd(bufs.head->buf.last, &hd);
10858   bufs.head->buf.last += NGHTTP2_FRAME_HDLEN;
10859
10860   nread = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
10861                                    nghttp2_bufs_len(&bufs));
10862
10863   CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == nread);
10864   CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
10865
10866   /* Now server receives SETTINGS ACK */
10867   nghttp2_frame_hd_init(&hd, 0, NGHTTP2_SETTINGS, NGHTTP2_FLAG_ACK, 0);
10868   nghttp2_bufs_reset(&bufs);
10869   nghttp2_frame_pack_frame_hd(bufs.head->buf.last, &hd);
10870   bufs.head->buf.last += NGHTTP2_FRAME_HDLEN;
10871
10872   nread = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
10873                                    nghttp2_bufs_len(&bufs));
10874
10875   CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == nread);
10876
10877   nghttp2_bufs_free(&bufs);
10878 }
10879
10880 void test_nghttp2_session_removed_closed_stream(void) {
10881   nghttp2_session *session;
10882   nghttp2_session_callbacks callbacks;
10883   int rv;
10884   nghttp2_hd_deflater deflater;
10885   nghttp2_bufs bufs;
10886   nghttp2_mem *mem;
10887   ssize_t nread;
10888   nghttp2_frame_hd hd;
10889   nghttp2_outbound_item *item;
10890
10891   mem = nghttp2_mem_default();
10892
10893   frame_pack_bufs_init(&bufs);
10894
10895   memset(&callbacks, 0, sizeof(callbacks));
10896
10897   callbacks.send_callback = null_send_callback;
10898
10899   nghttp2_session_server_new(&session, &callbacks, NULL);
10900
10901   /* Now local max concurrent streams is still unlimited, pending max
10902      concurrent streams is now 2. */
10903
10904   nghttp2_hd_deflate_init(&deflater, mem);
10905
10906   prepare_session_removed_closed_stream(session, &deflater);
10907
10908   /* Now current max concurrent streams is 2.  Receiving frame on
10909      stream 3 is ignored because we have no stream object for stream
10910      3. */
10911   nghttp2_bufs_reset(&bufs);
10912   rv = pack_headers(&bufs, &deflater, 3,
10913                     NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM,
10914                     trailernv, ARRLEN(trailernv), mem);
10915
10916   CU_ASSERT(0 == rv);
10917
10918   nread = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
10919                                    nghttp2_bufs_len(&bufs));
10920
10921   CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == nread);
10922
10923   item = nghttp2_session_get_next_ob_item(session);
10924
10925   CU_ASSERT(NULL == item);
10926
10927   nghttp2_hd_deflate_free(&deflater);
10928   nghttp2_session_del(session);
10929
10930   nghttp2_session_server_new(&session, &callbacks, NULL);
10931   nghttp2_hd_deflate_init(&deflater, mem);
10932   /* Same setup, and then receive DATA instead of HEADERS */
10933
10934   prepare_session_removed_closed_stream(session, &deflater);
10935
10936   nghttp2_frame_hd_init(&hd, 0, NGHTTP2_DATA, NGHTTP2_FLAG_NONE, 3);
10937   nghttp2_bufs_reset(&bufs);
10938   nghttp2_frame_pack_frame_hd(bufs.head->buf.last, &hd);
10939   bufs.head->buf.last += NGHTTP2_FRAME_HDLEN;
10940
10941   nread = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
10942                                    nghttp2_bufs_len(&bufs));
10943
10944   CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == nread);
10945
10946   item = nghttp2_session_get_next_ob_item(session);
10947
10948   CU_ASSERT(NULL == item);
10949
10950   nghttp2_hd_deflate_free(&deflater);
10951   nghttp2_session_del(session);
10952
10953   nghttp2_bufs_free(&bufs);
10954 }
10955
10956 static ssize_t pause_once_data_source_read_callback(
10957     nghttp2_session *session, int32_t stream_id, uint8_t *buf, size_t len,
10958     uint32_t *data_flags, nghttp2_data_source *source, void *user_data) {
10959   my_user_data *ud = user_data;
10960   if (ud->data_source_read_cb_paused == 0) {
10961     ++ud->data_source_read_cb_paused;
10962     return NGHTTP2_ERR_PAUSE;
10963   }
10964
10965   return fixed_length_data_source_read_callback(session, stream_id, buf, len,
10966                                                 data_flags, source, user_data);
10967 }
10968
10969 void test_nghttp2_session_pause_data(void) {
10970   nghttp2_session *session;
10971   nghttp2_session_callbacks callbacks;
10972   nghttp2_data_provider data_prd;
10973   my_user_data ud;
10974
10975   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
10976   callbacks.send_callback = null_send_callback;
10977   callbacks.on_frame_send_callback = on_frame_send_callback;
10978
10979   data_prd.read_callback = pause_once_data_source_read_callback;
10980   ud.data_source_length = NGHTTP2_DATA_PAYLOADLEN;
10981
10982   nghttp2_session_server_new(&session, &callbacks, &ud);
10983
10984   open_recv_stream(session, 1);
10985
10986   CU_ASSERT(
10987       0 == nghttp2_submit_data(session, NGHTTP2_FLAG_END_STREAM, 1, &data_prd));
10988
10989   ud.frame_send_cb_called = 0;
10990   ud.data_source_read_cb_paused = 0;
10991
10992   CU_ASSERT(0 == nghttp2_session_send(session));
10993   CU_ASSERT(0 == ud.frame_send_cb_called);
10994   CU_ASSERT(NULL == session->aob.item);
10995   CU_ASSERT(0 == nghttp2_session_send(session));
10996   CU_ASSERT(1 == ud.frame_send_cb_called);
10997   CU_ASSERT(NGHTTP2_DATA == ud.sent_frame_type);
10998   CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
10999
11000   nghttp2_session_del(session);
11001 }
11002
11003 void test_nghttp2_session_no_closed_streams(void) {
11004   nghttp2_session *session;
11005   nghttp2_session_callbacks callbacks;
11006   nghttp2_option *option;
11007
11008   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
11009
11010   nghttp2_option_new(&option);
11011   nghttp2_option_set_no_closed_streams(option, 1);
11012
11013   nghttp2_session_server_new2(&session, &callbacks, NULL, option);
11014
11015   open_recv_stream(session, 1);
11016
11017   nghttp2_session_close_stream(session, 1, NGHTTP2_NO_ERROR);
11018
11019   CU_ASSERT(0 == session->num_closed_streams);
11020
11021   nghttp2_session_del(session);
11022   nghttp2_option_del(option);
11023 }
11024
11025 void test_nghttp2_session_set_stream_user_data(void) {
11026   nghttp2_session *session;
11027   nghttp2_session_callbacks callbacks;
11028   int32_t stream_id;
11029   int user_data1, user_data2;
11030   int rv;
11031   const uint8_t *datap;
11032   ssize_t datalen;
11033
11034   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
11035
11036   nghttp2_session_client_new(&session, &callbacks, NULL);
11037
11038   stream_id = nghttp2_submit_request(session, NULL, reqnv, ARRLEN(reqnv), NULL,
11039                                      &user_data1);
11040
11041   rv = nghttp2_session_set_stream_user_data(session, stream_id, &user_data2);
11042
11043   CU_ASSERT(0 == rv);
11044
11045   datalen = nghttp2_session_mem_send(session, &datap);
11046
11047   CU_ASSERT(datalen > 0);
11048
11049   CU_ASSERT(&user_data2 ==
11050             nghttp2_session_get_stream_user_data(session, stream_id));
11051
11052   CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT ==
11053             nghttp2_session_set_stream_user_data(session, 2, NULL));
11054
11055   nghttp2_session_del(session);
11056 }
11057
11058 static void check_nghttp2_http_recv_headers_fail(
11059     nghttp2_session *session, nghttp2_hd_deflater *deflater, int32_t stream_id,
11060     int stream_state, const nghttp2_nv *nva, size_t nvlen) {
11061   nghttp2_mem *mem;
11062   ssize_t rv;
11063   nghttp2_outbound_item *item;
11064   nghttp2_bufs bufs;
11065   my_user_data *ud;
11066
11067   mem = nghttp2_mem_default();
11068   frame_pack_bufs_init(&bufs);
11069
11070   ud = session->user_data;
11071
11072   if (stream_state != -1) {
11073     if (nghttp2_session_is_my_stream_id(session, stream_id)) {
11074       open_sent_stream2(session, stream_id, (nghttp2_stream_state)stream_state);
11075     } else {
11076       open_recv_stream2(session, stream_id, (nghttp2_stream_state)stream_state);
11077     }
11078   }
11079
11080   rv = pack_headers(&bufs, deflater, stream_id, NGHTTP2_FLAG_END_HEADERS, nva,
11081                     nvlen, mem);
11082   CU_ASSERT(0 == rv);
11083
11084   ud->invalid_frame_recv_cb_called = 0;
11085
11086   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11087                                 nghttp2_buf_len(&bufs.head->buf));
11088
11089   CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
11090
11091   item = nghttp2_session_get_next_ob_item(session);
11092
11093   CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
11094   CU_ASSERT(1 == ud->invalid_frame_recv_cb_called);
11095
11096   CU_ASSERT(0 == nghttp2_session_send(session));
11097
11098   nghttp2_bufs_free(&bufs);
11099 }
11100
11101 static void check_nghttp2_http_recv_headers_ok(
11102     nghttp2_session *session, nghttp2_hd_deflater *deflater, int32_t stream_id,
11103     int stream_state, const nghttp2_nv *nva, size_t nvlen) {
11104   nghttp2_mem *mem;
11105   ssize_t rv;
11106   nghttp2_bufs bufs;
11107   my_user_data *ud;
11108
11109   mem = nghttp2_mem_default();
11110   frame_pack_bufs_init(&bufs);
11111
11112   ud = session->user_data;
11113
11114   if (stream_state != -1) {
11115     if (nghttp2_session_is_my_stream_id(session, stream_id)) {
11116       open_sent_stream2(session, stream_id, (nghttp2_stream_state)stream_state);
11117     } else {
11118       open_recv_stream2(session, stream_id, (nghttp2_stream_state)stream_state);
11119     }
11120   }
11121
11122   rv = pack_headers(&bufs, deflater, stream_id, NGHTTP2_FLAG_END_HEADERS, nva,
11123                     nvlen, mem);
11124   CU_ASSERT(0 == rv);
11125
11126   ud->frame_recv_cb_called = 0;
11127
11128   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11129                                 nghttp2_buf_len(&bufs.head->buf));
11130
11131   CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
11132   CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
11133   CU_ASSERT(1 == ud->frame_recv_cb_called);
11134
11135   nghttp2_bufs_free(&bufs);
11136 }
11137
11138 void test_nghttp2_http_mandatory_headers(void) {
11139   nghttp2_session *session;
11140   nghttp2_session_callbacks callbacks;
11141   nghttp2_hd_deflater deflater;
11142   nghttp2_mem *mem;
11143   my_user_data ud;
11144   /* test case for response */
11145   const nghttp2_nv nostatus_resnv[] = {MAKE_NV("server", "foo")};
11146   const nghttp2_nv dupstatus_resnv[] = {MAKE_NV(":status", "200"),
11147                                         MAKE_NV(":status", "200")};
11148   const nghttp2_nv badpseudo_resnv[] = {MAKE_NV(":status", "200"),
11149                                         MAKE_NV(":scheme", "https")};
11150   const nghttp2_nv latepseudo_resnv[] = {MAKE_NV("server", "foo"),
11151                                          MAKE_NV(":status", "200")};
11152   const nghttp2_nv badstatus_resnv[] = {MAKE_NV(":status", "2000")};
11153   const nghttp2_nv badcl_resnv[] = {MAKE_NV(":status", "200"),
11154                                     MAKE_NV("content-length", "-1")};
11155   const nghttp2_nv dupcl_resnv[] = {MAKE_NV(":status", "200"),
11156                                     MAKE_NV("content-length", "0"),
11157                                     MAKE_NV("content-length", "0")};
11158   const nghttp2_nv badhd_resnv[] = {MAKE_NV(":status", "200"),
11159                                     MAKE_NV("connection", "close")};
11160   const nghttp2_nv cl1xx_resnv[] = {MAKE_NV(":status", "100"),
11161                                     MAKE_NV("content-length", "0")};
11162   const nghttp2_nv cl204_resnv[] = {MAKE_NV(":status", "204"),
11163                                     MAKE_NV("content-length", "0")};
11164   const nghttp2_nv clnonzero204_resnv[] = {MAKE_NV(":status", "204"),
11165                                            MAKE_NV("content-length", "100")};
11166   const nghttp2_nv status101_resnv[] = {MAKE_NV(":status", "101")};
11167
11168   /* test case for request */
11169   const nghttp2_nv nopath_reqnv[] = {MAKE_NV(":scheme", "https"),
11170                                      MAKE_NV(":method", "GET"),
11171                                      MAKE_NV(":authority", "localhost")};
11172   const nghttp2_nv earlyconnect_reqnv[] = {
11173       MAKE_NV(":method", "CONNECT"), MAKE_NV(":scheme", "https"),
11174       MAKE_NV(":path", "/"), MAKE_NV(":authority", "localhost")};
11175   const nghttp2_nv lateconnect_reqnv[] = {
11176       MAKE_NV(":scheme", "https"), MAKE_NV(":path", "/"),
11177       MAKE_NV(":method", "CONNECT"), MAKE_NV(":authority", "localhost")};
11178   const nghttp2_nv duppath_reqnv[] = {
11179       MAKE_NV(":scheme", "https"), MAKE_NV(":method", "GET"),
11180       MAKE_NV(":authority", "localhost"), MAKE_NV(":path", "/"),
11181       MAKE_NV(":path", "/")};
11182   const nghttp2_nv badcl_reqnv[] = {
11183       MAKE_NV(":scheme", "https"), MAKE_NV(":method", "POST"),
11184       MAKE_NV(":authority", "localhost"), MAKE_NV(":path", "/"),
11185       MAKE_NV("content-length", "-1")};
11186   const nghttp2_nv dupcl_reqnv[] = {
11187       MAKE_NV(":scheme", "https"),        MAKE_NV(":method", "POST"),
11188       MAKE_NV(":authority", "localhost"), MAKE_NV(":path", "/"),
11189       MAKE_NV("content-length", "0"),     MAKE_NV("content-length", "0")};
11190   const nghttp2_nv badhd_reqnv[] = {
11191       MAKE_NV(":scheme", "https"), MAKE_NV(":method", "GET"),
11192       MAKE_NV(":authority", "localhost"), MAKE_NV(":path", "/"),
11193       MAKE_NV("connection", "close")};
11194   const nghttp2_nv badauthority_reqnv[] = {
11195       MAKE_NV(":scheme", "https"), MAKE_NV(":method", "GET"),
11196       MAKE_NV(":authority", "\x0d\x0alocalhost"), MAKE_NV(":path", "/")};
11197   const nghttp2_nv badhdbtw_reqnv[] = {
11198       MAKE_NV(":scheme", "https"), MAKE_NV(":method", "GET"),
11199       MAKE_NV("foo", "\x0d\x0a"), MAKE_NV(":authority", "localhost"),
11200       MAKE_NV(":path", "/")};
11201   const nghttp2_nv asteriskget1_reqnv[] = {
11202       MAKE_NV(":path", "*"), MAKE_NV(":scheme", "https"),
11203       MAKE_NV(":authority", "localhost"), MAKE_NV(":method", "GET")};
11204   const nghttp2_nv asteriskget2_reqnv[] = {
11205       MAKE_NV(":scheme", "https"), MAKE_NV(":authority", "localhost"),
11206       MAKE_NV(":method", "GET"), MAKE_NV(":path", "*")};
11207   const nghttp2_nv asteriskoptions1_reqnv[] = {
11208       MAKE_NV(":path", "*"), MAKE_NV(":scheme", "https"),
11209       MAKE_NV(":authority", "localhost"), MAKE_NV(":method", "OPTIONS")};
11210   const nghttp2_nv asteriskoptions2_reqnv[] = {
11211       MAKE_NV(":scheme", "https"), MAKE_NV(":authority", "localhost"),
11212       MAKE_NV(":method", "OPTIONS"), MAKE_NV(":path", "*")};
11213   const nghttp2_nv connectproto_reqnv[] = {
11214       MAKE_NV(":scheme", "https"), MAKE_NV(":path", "/"),
11215       MAKE_NV(":method", "CONNECT"), MAKE_NV(":authority", "localhost"),
11216       MAKE_NV(":protocol", "websocket")};
11217   const nghttp2_nv connectprotoget_reqnv[] = {
11218       MAKE_NV(":scheme", "https"), MAKE_NV(":path", "/"),
11219       MAKE_NV(":method", "GET"), MAKE_NV(":authority", "localhost"),
11220       MAKE_NV(":protocol", "websocket")};
11221   const nghttp2_nv connectprotonopath_reqnv[] = {
11222       MAKE_NV(":scheme", "https"), MAKE_NV(":method", "CONNECT"),
11223       MAKE_NV(":authority", "localhost"), MAKE_NV(":protocol", "websocket")};
11224   const nghttp2_nv connectprotonoauth_reqnv[] = {
11225       MAKE_NV(":scheme", "http"), MAKE_NV(":path", "/"),
11226       MAKE_NV(":method", "CONNECT"), MAKE_NV("host", "localhost"),
11227       MAKE_NV(":protocol", "websocket")};
11228   const nghttp2_nv regularconnect_reqnv[] = {
11229       MAKE_NV(":method", "CONNECT"), MAKE_NV(":authority", "localhost")};
11230
11231   mem = nghttp2_mem_default();
11232
11233   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
11234   callbacks.send_callback = null_send_callback;
11235   callbacks.on_frame_recv_callback = on_frame_recv_callback;
11236   callbacks.on_invalid_frame_recv_callback = on_invalid_frame_recv_callback;
11237
11238   nghttp2_session_client_new(&session, &callbacks, &ud);
11239
11240   nghttp2_hd_deflate_init(&deflater, mem);
11241
11242   /* response header lacks :status */
11243   check_nghttp2_http_recv_headers_fail(session, &deflater, 1,
11244                                        NGHTTP2_STREAM_OPENING, nostatus_resnv,
11245                                        ARRLEN(nostatus_resnv));
11246
11247   /* response header has 2 :status */
11248   check_nghttp2_http_recv_headers_fail(session, &deflater, 3,
11249                                        NGHTTP2_STREAM_OPENING, dupstatus_resnv,
11250                                        ARRLEN(dupstatus_resnv));
11251
11252   /* response header has bad pseudo header :scheme */
11253   check_nghttp2_http_recv_headers_fail(session, &deflater, 5,
11254                                        NGHTTP2_STREAM_OPENING, badpseudo_resnv,
11255                                        ARRLEN(badpseudo_resnv));
11256
11257   /* response header has :status after regular header field */
11258   check_nghttp2_http_recv_headers_fail(session, &deflater, 7,
11259                                        NGHTTP2_STREAM_OPENING, latepseudo_resnv,
11260                                        ARRLEN(latepseudo_resnv));
11261
11262   /* response header has bad status code */
11263   check_nghttp2_http_recv_headers_fail(session, &deflater, 9,
11264                                        NGHTTP2_STREAM_OPENING, badstatus_resnv,
11265                                        ARRLEN(badstatus_resnv));
11266
11267   /* response header has bad content-length */
11268   check_nghttp2_http_recv_headers_fail(session, &deflater, 11,
11269                                        NGHTTP2_STREAM_OPENING, badcl_resnv,
11270                                        ARRLEN(badcl_resnv));
11271
11272   /* response header has multiple content-length */
11273   check_nghttp2_http_recv_headers_fail(session, &deflater, 13,
11274                                        NGHTTP2_STREAM_OPENING, dupcl_resnv,
11275                                        ARRLEN(dupcl_resnv));
11276
11277   /* response header has disallowed header field */
11278   check_nghttp2_http_recv_headers_fail(session, &deflater, 15,
11279                                        NGHTTP2_STREAM_OPENING, badhd_resnv,
11280                                        ARRLEN(badhd_resnv));
11281
11282   /* response header has content-length with 100 status code */
11283   check_nghttp2_http_recv_headers_fail(session, &deflater, 17,
11284                                        NGHTTP2_STREAM_OPENING, cl1xx_resnv,
11285                                        ARRLEN(cl1xx_resnv));
11286
11287   /* response header has 0 content-length with 204 status code */
11288   check_nghttp2_http_recv_headers_ok(session, &deflater, 19,
11289                                      NGHTTP2_STREAM_OPENING, cl204_resnv,
11290                                      ARRLEN(cl204_resnv));
11291
11292   /* response header has nonzero content-length with 204 status
11293      code */
11294   check_nghttp2_http_recv_headers_fail(
11295       session, &deflater, 21, NGHTTP2_STREAM_OPENING, clnonzero204_resnv,
11296       ARRLEN(clnonzero204_resnv));
11297
11298   /* status code 101 should not be used in HTTP/2 because it is used
11299      for HTTP Upgrade which HTTP/2 removes. */
11300   check_nghttp2_http_recv_headers_fail(session, &deflater, 23,
11301                                        NGHTTP2_STREAM_OPENING, status101_resnv,
11302                                        ARRLEN(status101_resnv));
11303
11304   nghttp2_hd_deflate_free(&deflater);
11305
11306   nghttp2_session_del(session);
11307
11308   /* check server side */
11309   nghttp2_session_server_new(&session, &callbacks, &ud);
11310
11311   nghttp2_hd_deflate_init(&deflater, mem);
11312
11313   /* request header has no :path */
11314   check_nghttp2_http_recv_headers_fail(session, &deflater, 1, -1, nopath_reqnv,
11315                                        ARRLEN(nopath_reqnv));
11316
11317   /* request header has CONNECT method, but followed by :path */
11318   check_nghttp2_http_recv_headers_fail(session, &deflater, 3, -1,
11319                                        earlyconnect_reqnv,
11320                                        ARRLEN(earlyconnect_reqnv));
11321
11322   /* request header has CONNECT method following :path */
11323   check_nghttp2_http_recv_headers_fail(
11324       session, &deflater, 5, -1, lateconnect_reqnv, ARRLEN(lateconnect_reqnv));
11325
11326   /* request header has multiple :path */
11327   check_nghttp2_http_recv_headers_fail(session, &deflater, 7, -1, duppath_reqnv,
11328                                        ARRLEN(duppath_reqnv));
11329
11330   /* request header has bad content-length */
11331   check_nghttp2_http_recv_headers_fail(session, &deflater, 9, -1, badcl_reqnv,
11332                                        ARRLEN(badcl_reqnv));
11333
11334   /* request header has multiple content-length */
11335   check_nghttp2_http_recv_headers_fail(session, &deflater, 11, -1, dupcl_reqnv,
11336                                        ARRLEN(dupcl_reqnv));
11337
11338   /* request header has disallowed header field */
11339   check_nghttp2_http_recv_headers_fail(session, &deflater, 13, -1, badhd_reqnv,
11340                                        ARRLEN(badhd_reqnv));
11341
11342   /* request header has :authority header field containing illegal
11343      characters */
11344   check_nghttp2_http_recv_headers_fail(session, &deflater, 15, -1,
11345                                        badauthority_reqnv,
11346                                        ARRLEN(badauthority_reqnv));
11347
11348   /* request header has regular header field containing illegal
11349      character before all mandatory header fields are seen. */
11350   check_nghttp2_http_recv_headers_fail(session, &deflater, 17, -1,
11351                                        badhdbtw_reqnv, ARRLEN(badhdbtw_reqnv));
11352
11353   /* request header has "*" in :path header field while method is GET.
11354      :path is received before :method */
11355   check_nghttp2_http_recv_headers_fail(session, &deflater, 19, -1,
11356                                        asteriskget1_reqnv,
11357                                        ARRLEN(asteriskget1_reqnv));
11358
11359   /* request header has "*" in :path header field while method is GET.
11360      :method is received before :path */
11361   check_nghttp2_http_recv_headers_fail(session, &deflater, 21, -1,
11362                                        asteriskget2_reqnv,
11363                                        ARRLEN(asteriskget2_reqnv));
11364
11365   /* OPTIONS method can include "*" in :path header field.  :path is
11366      received before :method. */
11367   check_nghttp2_http_recv_headers_ok(session, &deflater, 23, -1,
11368                                      asteriskoptions1_reqnv,
11369                                      ARRLEN(asteriskoptions1_reqnv));
11370
11371   /* OPTIONS method can include "*" in :path header field.  :method is
11372      received before :path. */
11373   check_nghttp2_http_recv_headers_ok(session, &deflater, 25, -1,
11374                                      asteriskoptions2_reqnv,
11375                                      ARRLEN(asteriskoptions2_reqnv));
11376
11377   /* :protocol is not allowed unless it is enabled by the local
11378      endpoint. */
11379   check_nghttp2_http_recv_headers_fail(session, &deflater, 27, -1,
11380                                        connectproto_reqnv,
11381                                        ARRLEN(connectproto_reqnv));
11382
11383   nghttp2_hd_deflate_free(&deflater);
11384
11385   nghttp2_session_del(session);
11386
11387   /* enable SETTINGS_CONNECT_PROTOCOL */
11388   nghttp2_session_server_new(&session, &callbacks, &ud);
11389
11390   session->pending_enable_connect_protocol = 1;
11391
11392   nghttp2_hd_deflate_init(&deflater, mem);
11393
11394   /* :protocol is allowed if SETTINGS_CONNECT_PROTOCOL is enabled by
11395      the local endpoint. */
11396   check_nghttp2_http_recv_headers_ok(session, &deflater, 1, -1,
11397                                      connectproto_reqnv,
11398                                      ARRLEN(connectproto_reqnv));
11399
11400   /* :protocol is only allowed with CONNECT method. */
11401   check_nghttp2_http_recv_headers_fail(session, &deflater, 3, -1,
11402                                        connectprotoget_reqnv,
11403                                        ARRLEN(connectprotoget_reqnv));
11404
11405   /* CONNECT method with :protocol requires :path. */
11406   check_nghttp2_http_recv_headers_fail(session, &deflater, 5, -1,
11407                                        connectprotonopath_reqnv,
11408                                        ARRLEN(connectprotonopath_reqnv));
11409
11410   /* CONNECT method with :protocol requires :authority. */
11411   check_nghttp2_http_recv_headers_fail(session, &deflater, 7, -1,
11412                                        connectprotonoauth_reqnv,
11413                                        ARRLEN(connectprotonoauth_reqnv));
11414
11415   /* regular CONNECT method should succeed with
11416      SETTINGS_CONNECT_PROTOCOL */
11417   check_nghttp2_http_recv_headers_ok(session, &deflater, 9, -1,
11418                                      regularconnect_reqnv,
11419                                      ARRLEN(regularconnect_reqnv));
11420
11421   nghttp2_hd_deflate_free(&deflater);
11422
11423   nghttp2_session_del(session);
11424 }
11425
11426 void test_nghttp2_http_content_length(void) {
11427   nghttp2_session *session;
11428   nghttp2_session_callbacks callbacks;
11429   nghttp2_hd_deflater deflater;
11430   nghttp2_mem *mem;
11431   nghttp2_bufs bufs;
11432   ssize_t rv;
11433   nghttp2_stream *stream;
11434   const nghttp2_nv cl_resnv[] = {MAKE_NV(":status", "200"),
11435                                  MAKE_NV("te", "trailers"),
11436                                  MAKE_NV("content-length", "9000000000")};
11437   const nghttp2_nv cl_reqnv[] = {
11438       MAKE_NV(":path", "/"),        MAKE_NV(":method", "PUT"),
11439       MAKE_NV(":scheme", "https"),  MAKE_NV("te", "trailers"),
11440       MAKE_NV("host", "localhost"), MAKE_NV("content-length", "9000000000")};
11441
11442   mem = nghttp2_mem_default();
11443   frame_pack_bufs_init(&bufs);
11444
11445   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
11446   callbacks.send_callback = null_send_callback;
11447
11448   nghttp2_session_client_new(&session, &callbacks, NULL);
11449
11450   nghttp2_hd_deflate_init(&deflater, mem);
11451
11452   stream = open_sent_stream2(session, 1, NGHTTP2_STREAM_OPENING);
11453
11454   rv = pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, cl_resnv,
11455                     ARRLEN(cl_resnv), mem);
11456   CU_ASSERT(0 == rv);
11457
11458   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11459                                 nghttp2_buf_len(&bufs.head->buf));
11460
11461   CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
11462   CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
11463   CU_ASSERT(9000000000LL == stream->content_length);
11464   CU_ASSERT(200 == stream->status_code);
11465
11466   nghttp2_hd_deflate_free(&deflater);
11467
11468   nghttp2_session_del(session);
11469
11470   nghttp2_bufs_reset(&bufs);
11471
11472   /* check server side */
11473   nghttp2_session_server_new(&session, &callbacks, NULL);
11474
11475   nghttp2_hd_deflate_init(&deflater, mem);
11476
11477   rv = pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, cl_reqnv,
11478                     ARRLEN(cl_reqnv), mem);
11479   CU_ASSERT(0 == rv);
11480
11481   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11482                                 nghttp2_buf_len(&bufs.head->buf));
11483
11484   CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
11485
11486   stream = nghttp2_session_get_stream(session, 1);
11487
11488   CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
11489   CU_ASSERT(9000000000LL == stream->content_length);
11490
11491   nghttp2_hd_deflate_free(&deflater);
11492
11493   nghttp2_session_del(session);
11494
11495   nghttp2_bufs_free(&bufs);
11496 }
11497
11498 void test_nghttp2_http_content_length_mismatch(void) {
11499   nghttp2_session *session;
11500   nghttp2_session_callbacks callbacks;
11501   nghttp2_hd_deflater deflater;
11502   nghttp2_mem *mem;
11503   nghttp2_bufs bufs;
11504   ssize_t rv;
11505   const nghttp2_nv cl_reqnv[] = {
11506       MAKE_NV(":path", "/"), MAKE_NV(":method", "PUT"),
11507       MAKE_NV(":authority", "localhost"), MAKE_NV(":scheme", "https"),
11508       MAKE_NV("content-length", "20")};
11509   const nghttp2_nv cl_resnv[] = {MAKE_NV(":status", "200"),
11510                                  MAKE_NV("content-length", "20")};
11511   nghttp2_outbound_item *item;
11512   nghttp2_frame_hd hd;
11513
11514   mem = nghttp2_mem_default();
11515   frame_pack_bufs_init(&bufs);
11516
11517   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
11518   callbacks.send_callback = null_send_callback;
11519
11520   nghttp2_session_server_new(&session, &callbacks, NULL);
11521
11522   nghttp2_hd_deflate_init(&deflater, mem);
11523
11524   /* header says content-length: 20, but HEADERS has END_STREAM flag set */
11525   rv = pack_headers(&bufs, &deflater, 1,
11526                     NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM,
11527                     cl_reqnv, ARRLEN(cl_reqnv), mem);
11528   CU_ASSERT(0 == rv);
11529
11530   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11531                                 nghttp2_buf_len(&bufs.head->buf));
11532
11533   CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
11534
11535   item = nghttp2_session_get_next_ob_item(session);
11536   CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
11537
11538   CU_ASSERT(0 == nghttp2_session_send(session));
11539
11540   nghttp2_bufs_reset(&bufs);
11541
11542   /* header says content-length: 20, but DATA has 0 byte */
11543   rv = pack_headers(&bufs, &deflater, 3, NGHTTP2_FLAG_END_HEADERS, cl_reqnv,
11544                     ARRLEN(cl_reqnv), mem);
11545   CU_ASSERT(0 == rv);
11546
11547   nghttp2_frame_hd_init(&hd, 0, NGHTTP2_DATA, NGHTTP2_FLAG_END_STREAM, 3);
11548   nghttp2_frame_pack_frame_hd(bufs.head->buf.last, &hd);
11549   bufs.head->buf.last += NGHTTP2_FRAME_HDLEN;
11550
11551   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11552                                 nghttp2_buf_len(&bufs.head->buf));
11553
11554   CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
11555
11556   item = nghttp2_session_get_next_ob_item(session);
11557   CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
11558
11559   CU_ASSERT(0 == nghttp2_session_send(session));
11560
11561   nghttp2_bufs_reset(&bufs);
11562
11563   /* header says content-length: 20, but DATA has 21 bytes */
11564   rv = pack_headers(&bufs, &deflater, 5, NGHTTP2_FLAG_END_HEADERS, cl_reqnv,
11565                     ARRLEN(cl_reqnv), mem);
11566   CU_ASSERT(0 == rv);
11567
11568   nghttp2_frame_hd_init(&hd, 21, NGHTTP2_DATA, NGHTTP2_FLAG_END_STREAM, 5);
11569   nghttp2_frame_pack_frame_hd(bufs.head->buf.last, &hd);
11570   bufs.head->buf.last += NGHTTP2_FRAME_HDLEN + 21;
11571
11572   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11573                                 nghttp2_buf_len(&bufs.head->buf));
11574
11575   CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
11576
11577   item = nghttp2_session_get_next_ob_item(session);
11578   CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
11579
11580   CU_ASSERT(0 == nghttp2_session_send(session));
11581
11582   nghttp2_bufs_reset(&bufs);
11583
11584   nghttp2_hd_deflate_free(&deflater);
11585
11586   nghttp2_session_del(session);
11587
11588   /* Check for client */
11589   nghttp2_session_client_new(&session, &callbacks, NULL);
11590
11591   nghttp2_hd_deflate_init(&deflater, mem);
11592
11593   /* header says content-length: 20, but HEADERS has END_STREAM flag set */
11594   nghttp2_submit_request(session, NULL, reqnv, ARRLEN(reqnv), NULL, NULL);
11595
11596   CU_ASSERT(0 == nghttp2_session_send(session));
11597
11598   rv = pack_headers(&bufs, &deflater, 1,
11599                     NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM,
11600                     cl_resnv, ARRLEN(cl_resnv), mem);
11601   CU_ASSERT(0 == rv);
11602
11603   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11604                                 nghttp2_buf_len(&bufs.head->buf));
11605
11606   CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
11607
11608   item = nghttp2_session_get_next_ob_item(session);
11609   CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
11610
11611   CU_ASSERT(NULL != nghttp2_session_get_stream(session, 1));
11612   CU_ASSERT(0 == nghttp2_session_send(session));
11613   /* After sending RST_STREAM, stream must be closed */
11614   CU_ASSERT(NULL == nghttp2_session_get_stream(session, 1));
11615
11616   nghttp2_bufs_reset(&bufs);
11617
11618   /* header says content-length: 20, but DATA has 0 byte */
11619   nghttp2_submit_request(session, NULL, reqnv, ARRLEN(reqnv), NULL, NULL);
11620
11621   CU_ASSERT(0 == nghttp2_session_send(session));
11622
11623   rv = pack_headers(&bufs, &deflater, 3, NGHTTP2_FLAG_END_HEADERS, cl_resnv,
11624                     ARRLEN(cl_resnv), mem);
11625   CU_ASSERT(0 == rv);
11626
11627   nghttp2_frame_hd_init(&hd, 0, NGHTTP2_DATA, NGHTTP2_FLAG_END_STREAM, 3);
11628   nghttp2_frame_pack_frame_hd(bufs.head->buf.last, &hd);
11629   bufs.head->buf.last += NGHTTP2_FRAME_HDLEN;
11630
11631   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11632                                 nghttp2_buf_len(&bufs.head->buf));
11633
11634   CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
11635
11636   item = nghttp2_session_get_next_ob_item(session);
11637   CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
11638
11639   CU_ASSERT(NULL != nghttp2_session_get_stream(session, 3));
11640   CU_ASSERT(0 == nghttp2_session_send(session));
11641   /* After sending RST_STREAM, stream must be closed */
11642   CU_ASSERT(NULL == nghttp2_session_get_stream(session, 3));
11643
11644   nghttp2_bufs_reset(&bufs);
11645
11646   /* header says content-length: 20, but DATA has 21 bytes */
11647   nghttp2_submit_request(session, NULL, reqnv, ARRLEN(reqnv), NULL, NULL);
11648
11649   CU_ASSERT(0 == nghttp2_session_send(session));
11650
11651   rv = pack_headers(&bufs, &deflater, 5, NGHTTP2_FLAG_END_HEADERS, cl_resnv,
11652                     ARRLEN(cl_resnv), mem);
11653   CU_ASSERT(0 == rv);
11654
11655   nghttp2_frame_hd_init(&hd, 21, NGHTTP2_DATA, NGHTTP2_FLAG_END_STREAM, 5);
11656   nghttp2_frame_pack_frame_hd(bufs.head->buf.last, &hd);
11657   bufs.head->buf.last += NGHTTP2_FRAME_HDLEN + 21;
11658
11659   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11660                                 nghttp2_buf_len(&bufs.head->buf));
11661
11662   CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
11663
11664   item = nghttp2_session_get_next_ob_item(session);
11665   CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
11666
11667   CU_ASSERT(NULL != nghttp2_session_get_stream(session, 5));
11668   CU_ASSERT(0 == nghttp2_session_send(session));
11669   /* After sending RST_STREAM, stream must be closed */
11670   CU_ASSERT(NULL == nghttp2_session_get_stream(session, 5));
11671
11672   nghttp2_bufs_reset(&bufs);
11673
11674   nghttp2_bufs_free(&bufs);
11675
11676   nghttp2_hd_deflate_free(&deflater);
11677
11678   nghttp2_session_del(session);
11679 }
11680
11681 void test_nghttp2_http_non_final_response(void) {
11682   nghttp2_session *session;
11683   nghttp2_session_callbacks callbacks;
11684   nghttp2_hd_deflater deflater;
11685   nghttp2_mem *mem;
11686   nghttp2_bufs bufs;
11687   ssize_t rv;
11688   const nghttp2_nv nonfinal_resnv[] = {
11689       MAKE_NV(":status", "100"),
11690   };
11691   nghttp2_outbound_item *item;
11692   nghttp2_frame_hd hd;
11693
11694   mem = nghttp2_mem_default();
11695   frame_pack_bufs_init(&bufs);
11696
11697   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
11698   callbacks.send_callback = null_send_callback;
11699
11700   nghttp2_session_client_new(&session, &callbacks, NULL);
11701
11702   nghttp2_hd_deflate_init(&deflater, mem);
11703
11704   /* non-final HEADERS with END_STREAM is illegal */
11705   open_sent_stream2(session, 1, NGHTTP2_STREAM_OPENING);
11706
11707   rv = pack_headers(&bufs, &deflater, 1,
11708                     NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM,
11709                     nonfinal_resnv, ARRLEN(nonfinal_resnv), mem);
11710   CU_ASSERT(0 == rv);
11711
11712   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11713                                 nghttp2_buf_len(&bufs.head->buf));
11714
11715   CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
11716
11717   item = nghttp2_session_get_next_ob_item(session);
11718   CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
11719
11720   CU_ASSERT(0 == nghttp2_session_send(session));
11721
11722   nghttp2_bufs_reset(&bufs);
11723
11724   /* non-final HEADERS followed by non-empty DATA is illegal */
11725   open_sent_stream2(session, 3, NGHTTP2_STREAM_OPENING);
11726
11727   rv = pack_headers(&bufs, &deflater, 3, NGHTTP2_FLAG_END_HEADERS,
11728                     nonfinal_resnv, ARRLEN(nonfinal_resnv), mem);
11729   CU_ASSERT(0 == rv);
11730
11731   nghttp2_frame_hd_init(&hd, 10, NGHTTP2_DATA, NGHTTP2_FLAG_END_STREAM, 3);
11732   nghttp2_frame_pack_frame_hd(bufs.head->buf.last, &hd);
11733   bufs.head->buf.last += NGHTTP2_FRAME_HDLEN + 10;
11734
11735   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11736                                 nghttp2_buf_len(&bufs.head->buf));
11737
11738   CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
11739
11740   item = nghttp2_session_get_next_ob_item(session);
11741   CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
11742
11743   CU_ASSERT(0 == nghttp2_session_send(session));
11744
11745   nghttp2_bufs_reset(&bufs);
11746
11747   /* non-final HEADERS followed by empty DATA (without END_STREAM) is
11748      ok */
11749   open_sent_stream2(session, 5, NGHTTP2_STREAM_OPENING);
11750
11751   rv = pack_headers(&bufs, &deflater, 5, NGHTTP2_FLAG_END_HEADERS,
11752                     nonfinal_resnv, ARRLEN(nonfinal_resnv), mem);
11753   CU_ASSERT(0 == rv);
11754
11755   nghttp2_frame_hd_init(&hd, 0, NGHTTP2_DATA, NGHTTP2_FLAG_NONE, 5);
11756   nghttp2_frame_pack_frame_hd(bufs.head->buf.last, &hd);
11757   bufs.head->buf.last += NGHTTP2_FRAME_HDLEN;
11758
11759   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11760                                 nghttp2_buf_len(&bufs.head->buf));
11761
11762   CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
11763
11764   CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
11765
11766   nghttp2_bufs_reset(&bufs);
11767
11768   /* non-final HEADERS followed by empty DATA (with END_STREAM) is
11769      illegal */
11770   open_sent_stream2(session, 7, NGHTTP2_STREAM_OPENING);
11771
11772   rv = pack_headers(&bufs, &deflater, 7, NGHTTP2_FLAG_END_HEADERS,
11773                     nonfinal_resnv, ARRLEN(nonfinal_resnv), mem);
11774   CU_ASSERT(0 == rv);
11775
11776   nghttp2_frame_hd_init(&hd, 0, NGHTTP2_DATA, NGHTTP2_FLAG_END_STREAM, 7);
11777   nghttp2_frame_pack_frame_hd(bufs.head->buf.last, &hd);
11778   bufs.head->buf.last += NGHTTP2_FRAME_HDLEN;
11779
11780   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11781                                 nghttp2_buf_len(&bufs.head->buf));
11782
11783   CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
11784
11785   item = nghttp2_session_get_next_ob_item(session);
11786
11787   CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
11788
11789   CU_ASSERT(0 == nghttp2_session_send(session));
11790
11791   nghttp2_bufs_reset(&bufs);
11792
11793   /* non-final HEADERS followed by final HEADERS is OK */
11794   open_sent_stream2(session, 9, NGHTTP2_STREAM_OPENING);
11795
11796   rv = pack_headers(&bufs, &deflater, 9, NGHTTP2_FLAG_END_HEADERS,
11797                     nonfinal_resnv, ARRLEN(nonfinal_resnv), mem);
11798   CU_ASSERT(0 == rv);
11799
11800   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11801                                 nghttp2_buf_len(&bufs.head->buf));
11802
11803   CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
11804
11805   nghttp2_bufs_reset(&bufs);
11806
11807   rv = pack_headers(&bufs, &deflater, 9, NGHTTP2_FLAG_END_HEADERS, resnv,
11808                     ARRLEN(resnv), mem);
11809   CU_ASSERT(0 == rv);
11810
11811   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11812                                 nghttp2_buf_len(&bufs.head->buf));
11813
11814   CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
11815
11816   CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
11817
11818   nghttp2_bufs_reset(&bufs);
11819
11820   nghttp2_hd_deflate_free(&deflater);
11821
11822   nghttp2_session_del(session);
11823
11824   nghttp2_bufs_free(&bufs);
11825 }
11826
11827 void test_nghttp2_http_trailer_headers(void) {
11828   nghttp2_session *session;
11829   nghttp2_session_callbacks callbacks;
11830   nghttp2_hd_deflater deflater;
11831   nghttp2_mem *mem;
11832   nghttp2_bufs bufs;
11833   ssize_t rv;
11834   const nghttp2_nv trailer_reqnv[] = {
11835       MAKE_NV("foo", "bar"),
11836   };
11837   nghttp2_outbound_item *item;
11838
11839   mem = nghttp2_mem_default();
11840   frame_pack_bufs_init(&bufs);
11841
11842   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
11843   callbacks.send_callback = null_send_callback;
11844
11845   nghttp2_session_server_new(&session, &callbacks, NULL);
11846
11847   nghttp2_hd_deflate_init(&deflater, mem);
11848
11849   /* good trailer header */
11850   rv = pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, reqnv,
11851                     ARRLEN(reqnv), mem);
11852   CU_ASSERT(0 == rv);
11853
11854   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11855                                 nghttp2_buf_len(&bufs.head->buf));
11856
11857   CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
11858
11859   nghttp2_bufs_reset(&bufs);
11860
11861   rv = pack_headers(&bufs, &deflater, 1,
11862                     NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM,
11863                     trailer_reqnv, ARRLEN(trailer_reqnv), mem);
11864   CU_ASSERT(0 == rv);
11865
11866   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11867                                 nghttp2_buf_len(&bufs.head->buf));
11868
11869   CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
11870
11871   CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
11872
11873   nghttp2_bufs_reset(&bufs);
11874
11875   /* trailer header without END_STREAM is illegal */
11876   rv = pack_headers(&bufs, &deflater, 3, NGHTTP2_FLAG_END_HEADERS, reqnv,
11877                     ARRLEN(reqnv), mem);
11878   CU_ASSERT(0 == rv);
11879
11880   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11881                                 nghttp2_buf_len(&bufs.head->buf));
11882
11883   CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
11884
11885   nghttp2_bufs_reset(&bufs);
11886
11887   rv = pack_headers(&bufs, &deflater, 3, NGHTTP2_FLAG_END_HEADERS,
11888                     trailer_reqnv, ARRLEN(trailer_reqnv), mem);
11889   CU_ASSERT(0 == rv);
11890
11891   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11892                                 nghttp2_buf_len(&bufs.head->buf));
11893
11894   CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
11895
11896   item = nghttp2_session_get_next_ob_item(session);
11897
11898   CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
11899
11900   CU_ASSERT(0 == nghttp2_session_send(session));
11901
11902   nghttp2_bufs_reset(&bufs);
11903
11904   /* trailer header including pseudo header field is illegal */
11905   rv = pack_headers(&bufs, &deflater, 5, NGHTTP2_FLAG_END_HEADERS, reqnv,
11906                     ARRLEN(reqnv), mem);
11907   CU_ASSERT(0 == rv);
11908
11909   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11910                                 nghttp2_buf_len(&bufs.head->buf));
11911
11912   CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
11913
11914   nghttp2_bufs_reset(&bufs);
11915
11916   rv = pack_headers(&bufs, &deflater, 5, NGHTTP2_FLAG_END_HEADERS, reqnv,
11917                     ARRLEN(reqnv), mem);
11918   CU_ASSERT(0 == rv);
11919
11920   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11921                                 nghttp2_buf_len(&bufs.head->buf));
11922
11923   CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
11924
11925   item = nghttp2_session_get_next_ob_item(session);
11926
11927   CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
11928
11929   CU_ASSERT(0 == nghttp2_session_send(session));
11930
11931   nghttp2_bufs_reset(&bufs);
11932
11933   nghttp2_hd_deflate_free(&deflater);
11934
11935   nghttp2_session_del(session);
11936
11937   nghttp2_bufs_free(&bufs);
11938 }
11939
11940 void test_nghttp2_http_ignore_regular_header(void) {
11941   nghttp2_session *session;
11942   nghttp2_session_callbacks callbacks;
11943   nghttp2_hd_deflater deflater;
11944   nghttp2_mem *mem;
11945   nghttp2_bufs bufs;
11946   ssize_t rv;
11947   my_user_data ud;
11948   const nghttp2_nv bad_reqnv[] = {
11949       MAKE_NV(":authority", "localhost"),
11950       MAKE_NV(":scheme", "https"),
11951       MAKE_NV(":path", "/"),
11952       MAKE_NV(":method", "GET"),
11953       MAKE_NV("foo", "\x0zzz"),
11954       MAKE_NV("bar", "buzz"),
11955   };
11956   const nghttp2_nv bad_ansnv[] = {
11957       MAKE_NV(":authority", "localhost"), MAKE_NV(":scheme", "https"),
11958       MAKE_NV(":path", "/"), MAKE_NV(":method", "GET"), MAKE_NV("bar", "buzz")};
11959   size_t proclen;
11960   size_t i;
11961   nghttp2_outbound_item *item;
11962
11963   mem = nghttp2_mem_default();
11964   frame_pack_bufs_init(&bufs);
11965
11966   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
11967   callbacks.send_callback = null_send_callback;
11968   callbacks.on_header_callback = pause_on_header_callback;
11969
11970   nghttp2_session_server_new(&session, &callbacks, &ud);
11971   nghttp2_hd_deflate_init(&deflater, mem);
11972
11973   rv = pack_headers(&bufs, &deflater, 1,
11974                     NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM,
11975                     bad_reqnv, ARRLEN(bad_reqnv), mem);
11976
11977   CU_ASSERT_FATAL(0 == rv);
11978
11979   nghttp2_hd_deflate_free(&deflater);
11980
11981   proclen = 0;
11982
11983   for (i = 0; i < 4; ++i) {
11984     rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos + proclen,
11985                                   nghttp2_buf_len(&bufs.head->buf) - proclen);
11986     CU_ASSERT_FATAL(rv > 0);
11987     proclen += (size_t)rv;
11988     CU_ASSERT(nghttp2_nv_equal(&bad_ansnv[i], &ud.nv));
11989   }
11990
11991   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos + proclen,
11992                                 nghttp2_buf_len(&bufs.head->buf) - proclen);
11993   CU_ASSERT_FATAL(rv > 0);
11994   /* Without on_invalid_frame_recv_callback, bad header causes stream
11995      reset */
11996   item = nghttp2_session_get_next_ob_item(session);
11997
11998   CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
11999
12000   proclen += (size_t)rv;
12001
12002   CU_ASSERT(nghttp2_buf_len(&bufs.head->buf) == proclen);
12003
12004   nghttp2_session_del(session);
12005
12006   /* use on_invalid_header_callback */
12007   callbacks.on_invalid_header_callback = pause_on_invalid_header_callback;
12008
12009   nghttp2_session_server_new(&session, &callbacks, &ud);
12010
12011   proclen = 0;
12012
12013   ud.invalid_header_cb_called = 0;
12014
12015   for (i = 0; i < 4; ++i) {
12016     rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos + proclen,
12017                                   nghttp2_buf_len(&bufs.head->buf) - proclen);
12018     CU_ASSERT_FATAL(rv > 0);
12019     proclen += (size_t)rv;
12020     CU_ASSERT(nghttp2_nv_equal(&bad_ansnv[i], &ud.nv));
12021   }
12022
12023   CU_ASSERT(0 == ud.invalid_header_cb_called);
12024
12025   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos + proclen,
12026                                 nghttp2_buf_len(&bufs.head->buf) - proclen);
12027
12028   CU_ASSERT_FATAL(rv > 0);
12029   CU_ASSERT(1 == ud.invalid_header_cb_called);
12030   CU_ASSERT(nghttp2_nv_equal(&bad_reqnv[4], &ud.nv));
12031
12032   proclen += (size_t)rv;
12033
12034   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos + proclen,
12035                                 nghttp2_buf_len(&bufs.head->buf) - proclen);
12036
12037   CU_ASSERT(rv > 0);
12038   CU_ASSERT(nghttp2_nv_equal(&bad_ansnv[4], &ud.nv));
12039
12040   nghttp2_session_del(session);
12041
12042   /* make sure that we can reset stream from
12043      on_invalid_header_callback */
12044   callbacks.on_header_callback = on_header_callback;
12045   callbacks.on_invalid_header_callback = reset_on_invalid_header_callback;
12046
12047   nghttp2_session_server_new(&session, &callbacks, &ud);
12048
12049   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
12050                                 nghttp2_buf_len(&bufs.head->buf));
12051
12052   CU_ASSERT(rv == (ssize_t)nghttp2_buf_len(&bufs.head->buf));
12053
12054   item = nghttp2_session_get_next_ob_item(session);
12055
12056   CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
12057   CU_ASSERT(1 == item->frame.hd.stream_id);
12058
12059   nghttp2_session_del(session);
12060   nghttp2_bufs_free(&bufs);
12061 }
12062
12063 void test_nghttp2_http_ignore_content_length(void) {
12064   nghttp2_session *session;
12065   nghttp2_session_callbacks callbacks;
12066   nghttp2_hd_deflater deflater;
12067   nghttp2_mem *mem;
12068   nghttp2_bufs bufs;
12069   ssize_t rv;
12070   const nghttp2_nv cl_resnv[] = {MAKE_NV(":status", "304"),
12071                                  MAKE_NV("content-length", "20")};
12072   const nghttp2_nv conn_reqnv[] = {MAKE_NV(":authority", "localhost"),
12073                                    MAKE_NV(":method", "CONNECT"),
12074                                    MAKE_NV("content-length", "999999")};
12075   const nghttp2_nv conn_cl_resnv[] = {MAKE_NV(":status", "200"),
12076                                       MAKE_NV("content-length", "0")};
12077   nghttp2_stream *stream;
12078
12079   mem = nghttp2_mem_default();
12080   frame_pack_bufs_init(&bufs);
12081
12082   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
12083   callbacks.send_callback = null_send_callback;
12084
12085   nghttp2_session_client_new(&session, &callbacks, NULL);
12086
12087   nghttp2_hd_deflate_init(&deflater, mem);
12088
12089   /* If status 304, content-length must be ignored */
12090   open_sent_stream2(session, 1, NGHTTP2_STREAM_OPENING);
12091
12092   rv = pack_headers(&bufs, &deflater, 1,
12093                     NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM,
12094                     cl_resnv, ARRLEN(cl_resnv), mem);
12095   CU_ASSERT(0 == rv);
12096
12097   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
12098                                 nghttp2_buf_len(&bufs.head->buf));
12099
12100   CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
12101
12102   CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
12103
12104   nghttp2_bufs_reset(&bufs);
12105
12106   /* Content-Length in 200 response to CONNECT is ignored */
12107   stream = open_sent_stream2(session, 3, NGHTTP2_STREAM_OPENING);
12108   stream->http_flags |= NGHTTP2_HTTP_FLAG_METH_CONNECT;
12109
12110   rv = pack_headers(&bufs, &deflater, 3, NGHTTP2_FLAG_END_HEADERS,
12111                     conn_cl_resnv, ARRLEN(conn_cl_resnv), mem);
12112   CU_ASSERT(0 == rv);
12113
12114   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
12115                                 nghttp2_buf_len(&bufs.head->buf));
12116
12117   CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
12118
12119   CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
12120   CU_ASSERT(-1 == stream->content_length);
12121
12122   nghttp2_bufs_reset(&bufs);
12123
12124   nghttp2_hd_deflate_free(&deflater);
12125   nghttp2_session_del(session);
12126
12127   /* If request method is CONNECT, content-length must be ignored */
12128   nghttp2_session_server_new(&session, &callbacks, NULL);
12129
12130   nghttp2_hd_deflate_init(&deflater, mem);
12131
12132   rv = pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, conn_reqnv,
12133                     ARRLEN(conn_reqnv), mem);
12134
12135   CU_ASSERT(0 == rv);
12136
12137   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
12138                                 nghttp2_buf_len(&bufs.head->buf));
12139
12140   CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
12141
12142   CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
12143
12144   stream = nghttp2_session_get_stream(session, 1);
12145
12146   CU_ASSERT(-1 == stream->content_length);
12147   CU_ASSERT((stream->http_flags & NGHTTP2_HTTP_FLAG_METH_CONNECT) > 0);
12148
12149   nghttp2_hd_deflate_free(&deflater);
12150   nghttp2_session_del(session);
12151   nghttp2_bufs_free(&bufs);
12152 }
12153
12154 void test_nghttp2_http_record_request_method(void) {
12155   nghttp2_session *session;
12156   nghttp2_session_callbacks callbacks;
12157   const nghttp2_nv conn_reqnv[] = {MAKE_NV(":method", "CONNECT"),
12158                                    MAKE_NV(":authority", "localhost")};
12159   const nghttp2_nv conn_resnv[] = {MAKE_NV(":status", "200"),
12160                                    MAKE_NV("content-length", "9999")};
12161   nghttp2_stream *stream;
12162   ssize_t rv;
12163   nghttp2_bufs bufs;
12164   nghttp2_hd_deflater deflater;
12165   nghttp2_mem *mem;
12166   nghttp2_outbound_item *item;
12167
12168   mem = nghttp2_mem_default();
12169   frame_pack_bufs_init(&bufs);
12170
12171   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
12172   callbacks.send_callback = null_send_callback;
12173
12174   nghttp2_session_client_new(&session, &callbacks, NULL);
12175
12176   nghttp2_hd_deflate_init(&deflater, mem);
12177
12178   CU_ASSERT(1 == nghttp2_submit_request(session, NULL, conn_reqnv,
12179                                         ARRLEN(conn_reqnv), NULL, NULL));
12180
12181   CU_ASSERT(0 == nghttp2_session_send(session));
12182
12183   stream = nghttp2_session_get_stream(session, 1);
12184
12185   CU_ASSERT(NGHTTP2_HTTP_FLAG_METH_CONNECT == stream->http_flags);
12186
12187   rv = pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, conn_resnv,
12188                     ARRLEN(conn_resnv), mem);
12189   CU_ASSERT(0 == rv);
12190
12191   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
12192                                 nghttp2_buf_len(&bufs.head->buf));
12193
12194   CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
12195
12196   CU_ASSERT((NGHTTP2_HTTP_FLAG_METH_CONNECT & stream->http_flags) > 0);
12197   CU_ASSERT(-1 == stream->content_length);
12198
12199   /* content-length is ignored in 200 response to a CONNECT request */
12200   item = nghttp2_session_get_next_ob_item(session);
12201
12202   CU_ASSERT(NULL == item);
12203
12204   nghttp2_hd_deflate_free(&deflater);
12205   nghttp2_session_del(session);
12206   nghttp2_bufs_free(&bufs);
12207 }
12208
12209 void test_nghttp2_http_push_promise(void) {
12210   nghttp2_session *session;
12211   nghttp2_session_callbacks callbacks;
12212   nghttp2_hd_deflater deflater;
12213   nghttp2_mem *mem;
12214   nghttp2_bufs bufs;
12215   ssize_t rv;
12216   nghttp2_stream *stream;
12217   const nghttp2_nv bad_reqnv[] = {MAKE_NV(":method", "GET")};
12218   nghttp2_outbound_item *item;
12219
12220   mem = nghttp2_mem_default();
12221   frame_pack_bufs_init(&bufs);
12222
12223   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
12224   callbacks.send_callback = null_send_callback;
12225
12226   /* good PUSH_PROMISE case */
12227   nghttp2_session_client_new(&session, &callbacks, NULL);
12228
12229   nghttp2_hd_deflate_init(&deflater, mem);
12230
12231   open_sent_stream2(session, 1, NGHTTP2_STREAM_OPENING);
12232
12233   rv = pack_push_promise(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, 2,
12234                          reqnv, ARRLEN(reqnv), mem);
12235   CU_ASSERT(0 == rv);
12236
12237   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
12238                                 nghttp2_buf_len(&bufs.head->buf));
12239
12240   CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
12241
12242   CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
12243
12244   stream = nghttp2_session_get_stream(session, 2);
12245   CU_ASSERT(NULL != stream);
12246
12247   nghttp2_bufs_reset(&bufs);
12248
12249   rv = pack_headers(&bufs, &deflater, 2, NGHTTP2_FLAG_END_HEADERS, resnv,
12250                     ARRLEN(resnv), mem);
12251
12252   CU_ASSERT(0 == rv);
12253
12254   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
12255                                 nghttp2_buf_len(&bufs.head->buf));
12256
12257   CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
12258
12259   CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
12260
12261   CU_ASSERT(200 == stream->status_code);
12262
12263   nghttp2_bufs_reset(&bufs);
12264
12265   /* PUSH_PROMISE lacks mandatory header */
12266   rv = pack_push_promise(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, 4,
12267                          bad_reqnv, ARRLEN(bad_reqnv), mem);
12268
12269   CU_ASSERT(0 == rv);
12270
12271   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
12272                                 nghttp2_buf_len(&bufs.head->buf));
12273
12274   CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
12275
12276   item = nghttp2_session_get_next_ob_item(session);
12277
12278   CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
12279   CU_ASSERT(4 == item->frame.hd.stream_id);
12280
12281   nghttp2_bufs_reset(&bufs);
12282
12283   nghttp2_hd_deflate_free(&deflater);
12284   nghttp2_session_del(session);
12285   nghttp2_bufs_free(&bufs);
12286 }
12287
12288 void test_nghttp2_http_head_method_upgrade_workaround(void) {
12289   nghttp2_session *session;
12290   nghttp2_session_callbacks callbacks;
12291   const nghttp2_nv cl_resnv[] = {MAKE_NV(":status", "200"),
12292                                  MAKE_NV("content-length", "1000000007")};
12293   nghttp2_bufs bufs;
12294   nghttp2_hd_deflater deflater;
12295   nghttp2_mem *mem;
12296   ssize_t rv;
12297   nghttp2_stream *stream;
12298
12299   mem = nghttp2_mem_default();
12300   frame_pack_bufs_init(&bufs);
12301
12302   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
12303   callbacks.send_callback = null_send_callback;
12304
12305   nghttp2_session_client_new(&session, &callbacks, NULL);
12306
12307   nghttp2_hd_deflate_init(&deflater, mem);
12308
12309   nghttp2_session_upgrade(session, NULL, 0, NULL);
12310
12311   rv = pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, cl_resnv,
12312                     ARRLEN(cl_resnv), mem);
12313
12314   CU_ASSERT(0 == rv);
12315
12316   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
12317                                 nghttp2_buf_len(&bufs.head->buf));
12318
12319   CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
12320
12321   stream = nghttp2_session_get_stream(session, 1);
12322
12323   CU_ASSERT(-1 == stream->content_length);
12324
12325   nghttp2_hd_deflate_free(&deflater);
12326   nghttp2_session_del(session);
12327   nghttp2_bufs_free(&bufs);
12328 }