Apply PIE to nghttpx
[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_session_open_stream(void) {
6402   nghttp2_session *session;
6403   nghttp2_session_callbacks callbacks;
6404   nghttp2_stream *stream;
6405   nghttp2_priority_spec pri_spec;
6406
6407   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6408   nghttp2_session_server_new(&session, &callbacks, NULL);
6409
6410   nghttp2_priority_spec_init(&pri_spec, 0, 245, 0);
6411
6412   stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
6413                                        &pri_spec, NGHTTP2_STREAM_OPENED, NULL);
6414   CU_ASSERT(1 == session->num_incoming_streams);
6415   CU_ASSERT(0 == session->num_outgoing_streams);
6416   CU_ASSERT(NGHTTP2_STREAM_OPENED == stream->state);
6417   CU_ASSERT(245 == stream->weight);
6418   CU_ASSERT(&session->root == stream->dep_prev);
6419   CU_ASSERT(NGHTTP2_SHUT_NONE == stream->shut_flags);
6420
6421   stream = nghttp2_session_open_stream(session, 2, NGHTTP2_STREAM_FLAG_NONE,
6422                                        &pri_spec_default,
6423                                        NGHTTP2_STREAM_OPENING, NULL);
6424   CU_ASSERT(1 == session->num_incoming_streams);
6425   CU_ASSERT(1 == session->num_outgoing_streams);
6426   CU_ASSERT(&session->root == stream->dep_prev);
6427   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == stream->weight);
6428   CU_ASSERT(NGHTTP2_SHUT_NONE == stream->shut_flags);
6429
6430   stream = nghttp2_session_open_stream(session, 4, NGHTTP2_STREAM_FLAG_NONE,
6431                                        &pri_spec_default,
6432                                        NGHTTP2_STREAM_RESERVED, NULL);
6433   CU_ASSERT(1 == session->num_incoming_streams);
6434   CU_ASSERT(1 == session->num_outgoing_streams);
6435   CU_ASSERT(&session->root == stream->dep_prev);
6436   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == stream->weight);
6437   CU_ASSERT(NGHTTP2_SHUT_RD == stream->shut_flags);
6438
6439   nghttp2_priority_spec_init(&pri_spec, 1, 17, 1);
6440
6441   stream = nghttp2_session_open_stream(session, 3, NGHTTP2_STREAM_FLAG_NONE,
6442                                        &pri_spec, NGHTTP2_STREAM_OPENED, NULL);
6443   CU_ASSERT(17 == stream->weight);
6444   CU_ASSERT(1 == stream->dep_prev->stream_id);
6445
6446   /* Dependency to idle stream */
6447   nghttp2_priority_spec_init(&pri_spec, 1000000007, 240, 1);
6448
6449   stream = nghttp2_session_open_stream(session, 5, NGHTTP2_STREAM_FLAG_NONE,
6450                                        &pri_spec, NGHTTP2_STREAM_OPENED, NULL);
6451   CU_ASSERT(240 == stream->weight);
6452   CU_ASSERT(1000000007 == stream->dep_prev->stream_id);
6453
6454   stream = nghttp2_session_get_stream_raw(session, 1000000007);
6455
6456   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == stream->weight);
6457   CU_ASSERT(&session->root == stream->dep_prev);
6458
6459   /* Dependency to closed stream which is not in dependency tree */
6460   session->last_recv_stream_id = 7;
6461
6462   nghttp2_priority_spec_init(&pri_spec, 7, 10, 0);
6463
6464   stream = nghttp2_session_open_stream(session, 9, NGHTTP2_FLAG_NONE, &pri_spec,
6465                                        NGHTTP2_STREAM_OPENED, NULL);
6466
6467   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == stream->weight);
6468   CU_ASSERT(&session->root == stream->dep_prev);
6469
6470   nghttp2_session_del(session);
6471
6472   nghttp2_session_client_new(&session, &callbacks, NULL);
6473   stream = nghttp2_session_open_stream(session, 4, NGHTTP2_STREAM_FLAG_NONE,
6474                                        &pri_spec_default,
6475                                        NGHTTP2_STREAM_RESERVED, NULL);
6476   CU_ASSERT(0 == session->num_incoming_streams);
6477   CU_ASSERT(0 == session->num_outgoing_streams);
6478   CU_ASSERT(&session->root == stream->dep_prev);
6479   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == stream->weight);
6480   CU_ASSERT(NGHTTP2_SHUT_WR == stream->shut_flags);
6481
6482   nghttp2_session_del(session);
6483 }
6484
6485 void test_nghttp2_session_open_stream_with_idle_stream_dep(void) {
6486   nghttp2_session *session;
6487   nghttp2_session_callbacks callbacks;
6488   nghttp2_stream *stream;
6489   nghttp2_priority_spec pri_spec;
6490
6491   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6492   nghttp2_session_server_new(&session, &callbacks, NULL);
6493
6494   /* Dependency to idle stream */
6495   nghttp2_priority_spec_init(&pri_spec, 101, 245, 0);
6496
6497   stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
6498                                        &pri_spec, NGHTTP2_STREAM_OPENED, NULL);
6499
6500   CU_ASSERT(245 == stream->weight);
6501   CU_ASSERT(101 == stream->dep_prev->stream_id);
6502
6503   stream = nghttp2_session_get_stream_raw(session, 101);
6504
6505   CU_ASSERT(NGHTTP2_STREAM_IDLE == stream->state);
6506   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == stream->weight);
6507
6508   nghttp2_priority_spec_init(&pri_spec, 211, 1, 0);
6509
6510   /* stream 101 was already created as idle. */
6511   stream = nghttp2_session_open_stream(session, 101, NGHTTP2_STREAM_FLAG_NONE,
6512                                        &pri_spec, NGHTTP2_STREAM_OPENED, NULL);
6513
6514   CU_ASSERT(1 == stream->weight);
6515   CU_ASSERT(211 == stream->dep_prev->stream_id);
6516
6517   stream = nghttp2_session_get_stream_raw(session, 211);
6518
6519   CU_ASSERT(NGHTTP2_STREAM_IDLE == stream->state);
6520   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == stream->weight);
6521
6522   nghttp2_session_del(session);
6523 }
6524
6525 void test_nghttp2_session_get_next_ob_item(void) {
6526   nghttp2_session *session;
6527   nghttp2_session_callbacks callbacks;
6528   nghttp2_priority_spec pri_spec;
6529
6530   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6531   callbacks.send_callback = null_send_callback;
6532
6533   nghttp2_session_client_new(&session, &callbacks, NULL);
6534   session->remote_settings.max_concurrent_streams = 2;
6535
6536   CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
6537   nghttp2_submit_ping(session, NGHTTP2_FLAG_NONE, NULL);
6538   CU_ASSERT(NGHTTP2_PING ==
6539             nghttp2_session_get_next_ob_item(session)->frame.hd.type);
6540
6541   CU_ASSERT(1 == nghttp2_submit_request(session, NULL, NULL, 0, NULL, NULL));
6542   CU_ASSERT(NGHTTP2_PING ==
6543             nghttp2_session_get_next_ob_item(session)->frame.hd.type);
6544
6545   CU_ASSERT(0 == nghttp2_session_send(session));
6546   CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
6547
6548   /* Incoming stream does not affect the number of outgoing max
6549      concurrent streams. */
6550   open_recv_stream(session, 2);
6551
6552   nghttp2_priority_spec_init(&pri_spec, 0, NGHTTP2_MAX_WEIGHT, 0);
6553
6554   CU_ASSERT(3 ==
6555             nghttp2_submit_request(session, &pri_spec, NULL, 0, NULL, NULL));
6556   CU_ASSERT(NGHTTP2_HEADERS ==
6557             nghttp2_session_get_next_ob_item(session)->frame.hd.type);
6558   CU_ASSERT(0 == nghttp2_session_send(session));
6559
6560   CU_ASSERT(5 ==
6561             nghttp2_submit_request(session, &pri_spec, NULL, 0, NULL, NULL));
6562   CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
6563
6564   session->remote_settings.max_concurrent_streams = 3;
6565
6566   CU_ASSERT(NGHTTP2_HEADERS ==
6567             nghttp2_session_get_next_ob_item(session)->frame.hd.type);
6568
6569   nghttp2_session_del(session);
6570
6571   /* Check that push reply HEADERS are queued into ob_ss_pq */
6572   nghttp2_session_server_new(&session, &callbacks, NULL);
6573   session->remote_settings.max_concurrent_streams = 0;
6574   open_sent_stream2(session, 2, NGHTTP2_STREAM_RESERVED);
6575   CU_ASSERT(0 == nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, 2,
6576                                         NULL, NULL, 0, NULL));
6577   CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
6578   CU_ASSERT(1 == nghttp2_outbound_queue_size(&session->ob_syn));
6579   nghttp2_session_del(session);
6580 }
6581
6582 void test_nghttp2_session_pop_next_ob_item(void) {
6583   nghttp2_session *session;
6584   nghttp2_session_callbacks callbacks;
6585   nghttp2_outbound_item *item;
6586   nghttp2_priority_spec pri_spec;
6587   nghttp2_mem *mem;
6588
6589   mem = nghttp2_mem_default();
6590   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6591   callbacks.send_callback = null_send_callback;
6592
6593   nghttp2_session_client_new(&session, &callbacks, NULL);
6594   session->remote_settings.max_concurrent_streams = 1;
6595
6596   CU_ASSERT(NULL == nghttp2_session_pop_next_ob_item(session));
6597
6598   nghttp2_submit_ping(session, NGHTTP2_FLAG_NONE, NULL);
6599
6600   nghttp2_priority_spec_init(&pri_spec, 0, 254, 0);
6601
6602   nghttp2_submit_request(session, &pri_spec, NULL, 0, NULL, NULL);
6603
6604   item = nghttp2_session_pop_next_ob_item(session);
6605   CU_ASSERT(NGHTTP2_PING == item->frame.hd.type);
6606   nghttp2_outbound_item_free(item, mem);
6607   mem->free(item, NULL);
6608
6609   item = nghttp2_session_pop_next_ob_item(session);
6610   CU_ASSERT(NGHTTP2_HEADERS == item->frame.hd.type);
6611   nghttp2_outbound_item_free(item, mem);
6612   mem->free(item, NULL);
6613
6614   CU_ASSERT(NULL == nghttp2_session_pop_next_ob_item(session));
6615
6616   /* Incoming stream does not affect the number of outgoing max
6617      concurrent streams. */
6618   open_recv_stream(session, 4);
6619   /* In-flight outgoing stream */
6620   open_sent_stream(session, 1);
6621
6622   nghttp2_priority_spec_init(&pri_spec, 0, NGHTTP2_MAX_WEIGHT, 0);
6623
6624   nghttp2_submit_request(session, &pri_spec, NULL, 0, NULL, NULL);
6625
6626   CU_ASSERT(NULL == nghttp2_session_pop_next_ob_item(session));
6627
6628   session->remote_settings.max_concurrent_streams = 2;
6629
6630   item = nghttp2_session_pop_next_ob_item(session);
6631   CU_ASSERT(NGHTTP2_HEADERS == item->frame.hd.type);
6632   nghttp2_outbound_item_free(item, mem);
6633   mem->free(item, NULL);
6634
6635   nghttp2_session_del(session);
6636
6637   /* Check that push reply HEADERS are queued into ob_ss_pq */
6638   nghttp2_session_server_new(&session, &callbacks, NULL);
6639   session->remote_settings.max_concurrent_streams = 0;
6640   open_sent_stream2(session, 2, NGHTTP2_STREAM_RESERVED);
6641   CU_ASSERT(0 == nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, 2,
6642                                         NULL, NULL, 0, NULL));
6643   CU_ASSERT(NULL == nghttp2_session_pop_next_ob_item(session));
6644   CU_ASSERT(1 == nghttp2_outbound_queue_size(&session->ob_syn));
6645   nghttp2_session_del(session);
6646 }
6647
6648 void test_nghttp2_session_reply_fail(void) {
6649   nghttp2_session *session;
6650   nghttp2_session_callbacks callbacks;
6651   nghttp2_data_provider data_prd;
6652   my_user_data ud;
6653
6654   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6655   callbacks.send_callback = fail_send_callback;
6656
6657   data_prd.read_callback = fixed_length_data_source_read_callback;
6658   ud.data_source_length = 4 * 1024;
6659   CU_ASSERT(0 == nghttp2_session_server_new(&session, &callbacks, &ud));
6660   open_recv_stream2(session, 1, NGHTTP2_STREAM_OPENING);
6661   CU_ASSERT(0 == nghttp2_submit_response(session, 1, NULL, 0, &data_prd));
6662   CU_ASSERT(NGHTTP2_ERR_CALLBACK_FAILURE == nghttp2_session_send(session));
6663   nghttp2_session_del(session);
6664 }
6665
6666 void test_nghttp2_session_max_concurrent_streams(void) {
6667   nghttp2_session *session;
6668   nghttp2_session_callbacks callbacks;
6669   nghttp2_frame frame;
6670   nghttp2_outbound_item *item;
6671   nghttp2_mem *mem;
6672
6673   mem = nghttp2_mem_default();
6674   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6675   callbacks.send_callback = null_send_callback;
6676
6677   nghttp2_session_server_new(&session, &callbacks, NULL);
6678   open_recv_stream(session, 1);
6679
6680   /* Check un-ACKed SETTINGS_MAX_CONCURRENT_STREAMS */
6681   nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 3,
6682                              NGHTTP2_HCAT_HEADERS, NULL, NULL, 0);
6683   session->pending_local_max_concurrent_stream = 1;
6684
6685   CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
6686             nghttp2_session_on_request_headers_received(session, &frame));
6687
6688   item = nghttp2_outbound_queue_top(&session->ob_reg);
6689   CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
6690   CU_ASSERT(NGHTTP2_REFUSED_STREAM == item->frame.rst_stream.error_code);
6691
6692   CU_ASSERT(0 == nghttp2_session_send(session));
6693
6694   /* Check ACKed SETTINGS_MAX_CONCURRENT_STREAMS */
6695   session->local_settings.max_concurrent_streams = 1;
6696   frame.hd.stream_id = 5;
6697
6698   CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
6699             nghttp2_session_on_request_headers_received(session, &frame));
6700
6701   item = nghttp2_outbound_queue_top(&session->ob_reg);
6702   CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
6703   CU_ASSERT(NGHTTP2_PROTOCOL_ERROR == item->frame.goaway.error_code);
6704
6705   nghttp2_frame_headers_free(&frame.headers, mem);
6706   nghttp2_session_del(session);
6707 }
6708
6709 void test_nghttp2_session_stop_data_with_rst_stream(void) {
6710   nghttp2_session *session;
6711   nghttp2_session_callbacks callbacks;
6712   my_user_data ud;
6713   nghttp2_data_provider data_prd;
6714   nghttp2_frame frame;
6715
6716   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6717   callbacks.on_frame_send_callback = on_frame_send_callback;
6718   callbacks.send_callback = block_count_send_callback;
6719   data_prd.read_callback = fixed_length_data_source_read_callback;
6720
6721   ud.frame_send_cb_called = 0;
6722   ud.data_source_length = NGHTTP2_DATA_PAYLOADLEN * 4;
6723
6724   nghttp2_session_server_new(&session, &callbacks, &ud);
6725   open_recv_stream2(session, 1, NGHTTP2_STREAM_OPENING);
6726   nghttp2_submit_response(session, 1, NULL, 0, &data_prd);
6727
6728   ud.block_count = 2;
6729   /* Sends response HEADERS + DATA[0] */
6730   CU_ASSERT(0 == nghttp2_session_send(session));
6731   CU_ASSERT(NGHTTP2_DATA == ud.sent_frame_type);
6732   /* data for DATA[1] is read from data_prd but it is not sent */
6733   CU_ASSERT(ud.data_source_length == NGHTTP2_DATA_PAYLOADLEN * 2);
6734
6735   nghttp2_frame_rst_stream_init(&frame.rst_stream, 1, NGHTTP2_CANCEL);
6736   CU_ASSERT(0 == nghttp2_session_on_rst_stream_received(session, &frame));
6737   nghttp2_frame_rst_stream_free(&frame.rst_stream);
6738
6739   /* Big enough number to send all DATA frames potentially. */
6740   ud.block_count = 100;
6741   /* Nothing will be sent in the following call. */
6742   CU_ASSERT(0 == nghttp2_session_send(session));
6743   /* With RST_STREAM, stream is canceled and further DATA on that
6744      stream are not sent. */
6745   CU_ASSERT(ud.data_source_length == NGHTTP2_DATA_PAYLOADLEN * 2);
6746
6747   CU_ASSERT(NULL == nghttp2_session_get_stream(session, 1));
6748
6749   nghttp2_session_del(session);
6750 }
6751
6752 void test_nghttp2_session_defer_data(void) {
6753   nghttp2_session *session;
6754   nghttp2_session_callbacks callbacks;
6755   my_user_data ud;
6756   nghttp2_data_provider data_prd;
6757   nghttp2_outbound_item *item;
6758   nghttp2_stream *stream;
6759
6760   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6761   callbacks.on_frame_send_callback = on_frame_send_callback;
6762   callbacks.send_callback = block_count_send_callback;
6763   data_prd.read_callback = defer_data_source_read_callback;
6764
6765   ud.frame_send_cb_called = 0;
6766   ud.data_source_length = NGHTTP2_DATA_PAYLOADLEN * 4;
6767
6768   nghttp2_session_server_new(&session, &callbacks, &ud);
6769   stream = open_recv_stream2(session, 1, NGHTTP2_STREAM_OPENING);
6770
6771   session->remote_window_size = 1 << 20;
6772   stream->remote_window_size = 1 << 20;
6773
6774   nghttp2_submit_response(session, 1, NULL, 0, &data_prd);
6775
6776   ud.block_count = 1;
6777   /* Sends HEADERS reply */
6778   CU_ASSERT(0 == nghttp2_session_send(session));
6779   CU_ASSERT(NGHTTP2_HEADERS == ud.sent_frame_type);
6780   /* No data is read */
6781   CU_ASSERT(ud.data_source_length == NGHTTP2_DATA_PAYLOADLEN * 4);
6782
6783   ud.block_count = 1;
6784   nghttp2_submit_ping(session, NGHTTP2_FLAG_NONE, NULL);
6785   /* Sends PING */
6786   CU_ASSERT(0 == nghttp2_session_send(session));
6787   CU_ASSERT(NGHTTP2_PING == ud.sent_frame_type);
6788
6789   /* Resume deferred DATA */
6790   CU_ASSERT(0 == nghttp2_session_resume_data(session, 1));
6791   item = stream->item;
6792   item->aux_data.data.data_prd.read_callback =
6793       fixed_length_data_source_read_callback;
6794   ud.block_count = 1;
6795   /* Reads 2 DATA chunks */
6796   CU_ASSERT(0 == nghttp2_session_send(session));
6797   CU_ASSERT(ud.data_source_length == NGHTTP2_DATA_PAYLOADLEN * 2);
6798
6799   /* Deferred again */
6800   item->aux_data.data.data_prd.read_callback = defer_data_source_read_callback;
6801   /* This is needed since 16KiB block is already read and waiting to be
6802      sent. No read_callback invocation. */
6803   ud.block_count = 1;
6804   CU_ASSERT(0 == nghttp2_session_send(session));
6805   CU_ASSERT(ud.data_source_length == NGHTTP2_DATA_PAYLOADLEN * 2);
6806
6807   /* Resume deferred DATA */
6808   CU_ASSERT(0 == nghttp2_session_resume_data(session, 1));
6809   item->aux_data.data.data_prd.read_callback =
6810       fixed_length_data_source_read_callback;
6811   ud.block_count = 1;
6812   /* Reads 2 16KiB blocks */
6813   CU_ASSERT(0 == nghttp2_session_send(session));
6814   CU_ASSERT(ud.data_source_length == 0);
6815
6816   nghttp2_session_del(session);
6817 }
6818
6819 void test_nghttp2_session_flow_control(void) {
6820   nghttp2_session *session;
6821   nghttp2_session_callbacks callbacks;
6822   my_user_data ud;
6823   nghttp2_data_provider data_prd;
6824   nghttp2_frame frame;
6825   nghttp2_stream *stream;
6826   int32_t new_initial_window_size;
6827   nghttp2_settings_entry iv[1];
6828   nghttp2_frame settings_frame;
6829   nghttp2_mem *mem;
6830
6831   mem = nghttp2_mem_default();
6832   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6833   callbacks.send_callback = fixed_bytes_send_callback;
6834   callbacks.on_frame_send_callback = on_frame_send_callback;
6835   data_prd.read_callback = fixed_length_data_source_read_callback;
6836
6837   ud.frame_send_cb_called = 0;
6838   ud.data_source_length = 128 * 1024;
6839   /* Use smaller emission count so that we can check outbound flow
6840      control window calculation is correct. */
6841   ud.fixed_sendlen = 2 * 1024;
6842
6843   /* Initial window size to 64KiB - 1*/
6844   nghttp2_session_client_new(&session, &callbacks, &ud);
6845   /* Change it to 64KiB for easy calculation */
6846   session->remote_window_size = 64 * 1024;
6847   session->remote_settings.initial_window_size = 64 * 1024;
6848
6849   nghttp2_submit_request(session, NULL, NULL, 0, &data_prd, NULL);
6850
6851   /* Sends 64KiB - 1 data */
6852   CU_ASSERT(0 == nghttp2_session_send(session));
6853   CU_ASSERT(64 * 1024 == ud.data_source_length);
6854
6855   /* Back 32KiB in stream window */
6856   nghttp2_frame_window_update_init(&frame.window_update, NGHTTP2_FLAG_NONE, 1,
6857                                    32 * 1024);
6858   nghttp2_session_on_window_update_received(session, &frame);
6859
6860   /* Send nothing because of connection-level window */
6861   CU_ASSERT(0 == nghttp2_session_send(session));
6862   CU_ASSERT(64 * 1024 == ud.data_source_length);
6863
6864   /* Back 32KiB in connection-level window */
6865   frame.hd.stream_id = 0;
6866   nghttp2_session_on_window_update_received(session, &frame);
6867
6868   /* Sends another 32KiB data */
6869   CU_ASSERT(0 == nghttp2_session_send(session));
6870   CU_ASSERT(32 * 1024 == ud.data_source_length);
6871
6872   stream = nghttp2_session_get_stream(session, 1);
6873   /* Change initial window size to 16KiB. The window_size becomes
6874      negative. */
6875   new_initial_window_size = 16 * 1024;
6876   stream->remote_window_size =
6877       new_initial_window_size -
6878       ((int32_t)session->remote_settings.initial_window_size -
6879        stream->remote_window_size);
6880   session->remote_settings.initial_window_size =
6881       (uint32_t)new_initial_window_size;
6882   CU_ASSERT(-48 * 1024 == stream->remote_window_size);
6883
6884   /* Back 48KiB to stream window */
6885   frame.hd.stream_id = 1;
6886   frame.window_update.window_size_increment = 48 * 1024;
6887   nghttp2_session_on_window_update_received(session, &frame);
6888
6889   /* Nothing is sent because window_size is 0 */
6890   CU_ASSERT(0 == nghttp2_session_send(session));
6891   CU_ASSERT(32 * 1024 == ud.data_source_length);
6892
6893   /* Back 16KiB in stream window */
6894   frame.hd.stream_id = 1;
6895   frame.window_update.window_size_increment = 16 * 1024;
6896   nghttp2_session_on_window_update_received(session, &frame);
6897
6898   /* Back 24KiB in connection-level window */
6899   frame.hd.stream_id = 0;
6900   frame.window_update.window_size_increment = 24 * 1024;
6901   nghttp2_session_on_window_update_received(session, &frame);
6902
6903   /* Sends another 16KiB data */
6904   CU_ASSERT(0 == nghttp2_session_send(session));
6905   CU_ASSERT(16 * 1024 == ud.data_source_length);
6906
6907   /* Increase initial window size to 32KiB */
6908   iv[0].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
6909   iv[0].value = 32 * 1024;
6910
6911   nghttp2_frame_settings_init(&settings_frame.settings, NGHTTP2_FLAG_NONE,
6912                               dup_iv(iv, 1), 1);
6913   nghttp2_session_on_settings_received(session, &settings_frame, 1);
6914   nghttp2_frame_settings_free(&settings_frame.settings, mem);
6915
6916   /* Sends another 8KiB data */
6917   CU_ASSERT(0 == nghttp2_session_send(session));
6918   CU_ASSERT(8 * 1024 == ud.data_source_length);
6919
6920   /* Back 8KiB in connection-level window */
6921   frame.hd.stream_id = 0;
6922   frame.window_update.window_size_increment = 8 * 1024;
6923   nghttp2_session_on_window_update_received(session, &frame);
6924
6925   /* Sends last 8KiB data */
6926   CU_ASSERT(0 == nghttp2_session_send(session));
6927   CU_ASSERT(0 == ud.data_source_length);
6928   CU_ASSERT(nghttp2_session_get_stream(session, 1)->shut_flags &
6929             NGHTTP2_SHUT_WR);
6930
6931   nghttp2_frame_window_update_free(&frame.window_update);
6932   nghttp2_session_del(session);
6933 }
6934
6935 void test_nghttp2_session_flow_control_data_recv(void) {
6936   nghttp2_session *session;
6937   nghttp2_session_callbacks callbacks;
6938   uint8_t data[64 * 1024 + 16];
6939   nghttp2_frame_hd hd;
6940   nghttp2_outbound_item *item;
6941   nghttp2_stream *stream;
6942
6943   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6944   callbacks.send_callback = null_send_callback;
6945
6946   /* Initial window size to 64KiB - 1*/
6947   nghttp2_session_client_new(&session, &callbacks, NULL);
6948
6949   stream = open_sent_stream(session, 1);
6950
6951   nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_WR);
6952
6953   session->local_window_size = NGHTTP2_MAX_PAYLOADLEN;
6954   stream->local_window_size = NGHTTP2_MAX_PAYLOADLEN;
6955
6956   /* Create DATA frame */
6957   memset(data, 0, sizeof(data));
6958   nghttp2_frame_hd_init(&hd, NGHTTP2_MAX_PAYLOADLEN, NGHTTP2_DATA,
6959                         NGHTTP2_FLAG_END_STREAM, 1);
6960
6961   nghttp2_frame_pack_frame_hd(data, &hd);
6962   CU_ASSERT(NGHTTP2_MAX_PAYLOADLEN + NGHTTP2_FRAME_HDLEN ==
6963             nghttp2_session_mem_recv(
6964                 session, data, NGHTTP2_MAX_PAYLOADLEN + NGHTTP2_FRAME_HDLEN));
6965
6966   item = nghttp2_session_get_next_ob_item(session);
6967   /* Since this is the last frame, stream-level WINDOW_UPDATE is not
6968      issued, but connection-level is. */
6969   CU_ASSERT(NGHTTP2_WINDOW_UPDATE == item->frame.hd.type);
6970   CU_ASSERT(0 == item->frame.hd.stream_id);
6971   CU_ASSERT(NGHTTP2_MAX_PAYLOADLEN ==
6972             item->frame.window_update.window_size_increment);
6973
6974   CU_ASSERT(0 == nghttp2_session_send(session));
6975
6976   /* Receive DATA for closed stream. They are still subject to under
6977      connection-level flow control, since this situation arises when
6978      RST_STREAM is issued by the remote, but the local side keeps
6979      sending DATA frames. Without calculating connection-level window,
6980      the subsequent flow control gets confused. */
6981   CU_ASSERT(NGHTTP2_MAX_PAYLOADLEN + NGHTTP2_FRAME_HDLEN ==
6982             nghttp2_session_mem_recv(
6983                 session, data, NGHTTP2_MAX_PAYLOADLEN + NGHTTP2_FRAME_HDLEN));
6984
6985   item = nghttp2_session_get_next_ob_item(session);
6986   CU_ASSERT(NGHTTP2_WINDOW_UPDATE == item->frame.hd.type);
6987   CU_ASSERT(0 == item->frame.hd.stream_id);
6988   CU_ASSERT(NGHTTP2_MAX_PAYLOADLEN ==
6989             item->frame.window_update.window_size_increment);
6990
6991   nghttp2_session_del(session);
6992 }
6993
6994 void test_nghttp2_session_flow_control_data_with_padding_recv(void) {
6995   nghttp2_session *session;
6996   nghttp2_session_callbacks callbacks;
6997   uint8_t data[1024];
6998   nghttp2_frame_hd hd;
6999   nghttp2_stream *stream;
7000   nghttp2_option *option;
7001
7002   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7003   callbacks.send_callback = null_send_callback;
7004
7005   nghttp2_option_new(&option);
7006   /* Disable auto window update so that we can check padding is
7007      consumed automatically */
7008   nghttp2_option_set_no_auto_window_update(option, 1);
7009
7010   /* Initial window size to 64KiB - 1*/
7011   nghttp2_session_client_new2(&session, &callbacks, NULL, option);
7012
7013   nghttp2_option_del(option);
7014
7015   stream = open_sent_stream(session, 1);
7016
7017   /* Create DATA frame */
7018   memset(data, 0, sizeof(data));
7019   nghttp2_frame_hd_init(&hd, 357, NGHTTP2_DATA, NGHTTP2_FLAG_PADDED, 1);
7020
7021   nghttp2_frame_pack_frame_hd(data, &hd);
7022   /* Set Pad Length field, which itself is padding */
7023   data[NGHTTP2_FRAME_HDLEN] = 255;
7024
7025   CU_ASSERT(
7026       (ssize_t)(NGHTTP2_FRAME_HDLEN + hd.length) ==
7027       nghttp2_session_mem_recv(session, data, NGHTTP2_FRAME_HDLEN + hd.length));
7028
7029   CU_ASSERT((int32_t)hd.length == session->recv_window_size);
7030   CU_ASSERT((int32_t)hd.length == stream->recv_window_size);
7031   CU_ASSERT(256 == session->consumed_size);
7032   CU_ASSERT(256 == stream->consumed_size);
7033   CU_ASSERT(357 == session->recv_window_size);
7034   CU_ASSERT(357 == stream->recv_window_size);
7035
7036   /* Receive the same DATA frame, but in 2 parts: first 9 + 1 + 102
7037      bytes which includes 1st padding byte, and remainder */
7038   CU_ASSERT((ssize_t)(NGHTTP2_FRAME_HDLEN + 103) ==
7039             nghttp2_session_mem_recv(session, data, NGHTTP2_FRAME_HDLEN + 103));
7040   CU_ASSERT(258 == session->consumed_size);
7041   CU_ASSERT(258 == stream->consumed_size);
7042   CU_ASSERT(460 == session->recv_window_size);
7043   CU_ASSERT(460 == stream->recv_window_size);
7044
7045   /* 357 - 103 = 254 bytes left */
7046   CU_ASSERT(254 == nghttp2_session_mem_recv(session, data, 254));
7047   CU_ASSERT(512 == session->consumed_size);
7048   CU_ASSERT(512 == stream->consumed_size);
7049   CU_ASSERT(714 == session->recv_window_size);
7050   CU_ASSERT(714 == stream->recv_window_size);
7051
7052   /* Receive the same DATA frame, but in 2 parts: first 9 = 1 + 101
7053      bytes which only includes data without padding, 2nd part is
7054      padding only */
7055   CU_ASSERT((ssize_t)(NGHTTP2_FRAME_HDLEN + 102) ==
7056             nghttp2_session_mem_recv(session, data, NGHTTP2_FRAME_HDLEN + 102));
7057   CU_ASSERT(513 == session->consumed_size);
7058   CU_ASSERT(513 == stream->consumed_size);
7059   CU_ASSERT(816 == session->recv_window_size);
7060   CU_ASSERT(816 == stream->recv_window_size);
7061
7062   /* 357 - 102 = 255 bytes left */
7063   CU_ASSERT(255 == nghttp2_session_mem_recv(session, data, 255));
7064   CU_ASSERT(768 == session->consumed_size);
7065   CU_ASSERT(768 == stream->consumed_size);
7066   CU_ASSERT(1071 == session->recv_window_size);
7067   CU_ASSERT(1071 == stream->recv_window_size);
7068
7069   /* Receive the same DATA frame, but in 2 parts: first 9 = 1 + 50
7070      bytes which includes byte up to middle of data, 2nd part is the
7071      remainder */
7072   CU_ASSERT((ssize_t)(NGHTTP2_FRAME_HDLEN + 51) ==
7073             nghttp2_session_mem_recv(session, data, NGHTTP2_FRAME_HDLEN + 51));
7074   CU_ASSERT(769 == session->consumed_size);
7075   CU_ASSERT(769 == stream->consumed_size);
7076   CU_ASSERT(1122 == session->recv_window_size);
7077   CU_ASSERT(1122 == stream->recv_window_size);
7078
7079   /* 357 - 51 = 306 bytes left */
7080   CU_ASSERT(306 == nghttp2_session_mem_recv(session, data, 306));
7081   CU_ASSERT(1024 == session->consumed_size);
7082   CU_ASSERT(1024 == stream->consumed_size);
7083   CU_ASSERT(1428 == session->recv_window_size);
7084   CU_ASSERT(1428 == stream->recv_window_size);
7085
7086   nghttp2_session_del(session);
7087 }
7088
7089 void test_nghttp2_session_data_read_temporal_failure(void) {
7090   nghttp2_session *session;
7091   nghttp2_session_callbacks callbacks;
7092   my_user_data ud;
7093   nghttp2_data_provider data_prd;
7094   nghttp2_frame frame;
7095   nghttp2_stream *stream;
7096   size_t data_size = 128 * 1024;
7097
7098   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7099   callbacks.send_callback = null_send_callback;
7100   callbacks.on_frame_send_callback = on_frame_send_callback;
7101   data_prd.read_callback = fixed_length_data_source_read_callback;
7102
7103   ud.data_source_length = data_size;
7104
7105   /* Initial window size is 64KiB - 1 */
7106   nghttp2_session_client_new(&session, &callbacks, &ud);
7107   nghttp2_submit_request(session, NULL, NULL, 0, &data_prd, NULL);
7108
7109   /* Sends NGHTTP2_INITIAL_WINDOW_SIZE data, assuming, it is equal to
7110      or smaller than NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE */
7111   CU_ASSERT(0 == nghttp2_session_send(session));
7112   CU_ASSERT(data_size - NGHTTP2_INITIAL_WINDOW_SIZE == ud.data_source_length);
7113
7114   stream = nghttp2_session_get_stream(session, 1);
7115   CU_ASSERT(NGHTTP2_DATA == stream->item->frame.hd.type);
7116
7117   stream->item->aux_data.data.data_prd.read_callback =
7118       temporal_failure_data_source_read_callback;
7119
7120   /* Back NGHTTP2_INITIAL_WINDOW_SIZE to both connection-level and
7121      stream-wise window */
7122   nghttp2_frame_window_update_init(&frame.window_update, NGHTTP2_FLAG_NONE, 1,
7123                                    NGHTTP2_INITIAL_WINDOW_SIZE);
7124   nghttp2_session_on_window_update_received(session, &frame);
7125   frame.hd.stream_id = 0;
7126   nghttp2_session_on_window_update_received(session, &frame);
7127   nghttp2_frame_window_update_free(&frame.window_update);
7128
7129   /* Sending data will fail (soft fail) and treated as stream error */
7130   ud.frame_send_cb_called = 0;
7131   CU_ASSERT(0 == nghttp2_session_send(session));
7132   CU_ASSERT(data_size - NGHTTP2_INITIAL_WINDOW_SIZE == ud.data_source_length);
7133
7134   CU_ASSERT(1 == ud.frame_send_cb_called);
7135   CU_ASSERT(NGHTTP2_RST_STREAM == ud.sent_frame_type);
7136
7137   data_prd.read_callback = fail_data_source_read_callback;
7138   nghttp2_submit_request(session, NULL, NULL, 0, &data_prd, NULL);
7139   /* Sending data will fail (hard fail) and session tear down */
7140   CU_ASSERT(NGHTTP2_ERR_CALLBACK_FAILURE == nghttp2_session_send(session));
7141
7142   nghttp2_session_del(session);
7143 }
7144
7145 void test_nghttp2_session_on_stream_close(void) {
7146   nghttp2_session *session;
7147   nghttp2_session_callbacks callbacks;
7148   my_user_data user_data;
7149   nghttp2_stream *stream;
7150
7151   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7152   callbacks.on_stream_close_callback = on_stream_close_callback;
7153   user_data.stream_close_cb_called = 0;
7154
7155   nghttp2_session_client_new(&session, &callbacks, &user_data);
7156   stream =
7157       open_sent_stream3(session, 1, NGHTTP2_STREAM_FLAG_NONE, &pri_spec_default,
7158                         NGHTTP2_STREAM_OPENED, &user_data);
7159   CU_ASSERT(stream != NULL);
7160   CU_ASSERT(nghttp2_session_close_stream(session, 1, NGHTTP2_NO_ERROR) == 0);
7161   CU_ASSERT(user_data.stream_close_cb_called == 1);
7162   nghttp2_session_del(session);
7163 }
7164
7165 void test_nghttp2_session_on_ctrl_not_send(void) {
7166   nghttp2_session *session;
7167   nghttp2_session_callbacks callbacks;
7168   my_user_data user_data;
7169   nghttp2_stream *stream;
7170
7171   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7172   callbacks.on_frame_not_send_callback = on_frame_not_send_callback;
7173   callbacks.send_callback = null_send_callback;
7174   user_data.frame_not_send_cb_called = 0;
7175   user_data.not_sent_frame_type = 0;
7176   user_data.not_sent_error = 0;
7177
7178   nghttp2_session_server_new(&session, &callbacks, &user_data);
7179   stream =
7180       open_recv_stream3(session, 1, NGHTTP2_STREAM_FLAG_NONE, &pri_spec_default,
7181                         NGHTTP2_STREAM_OPENING, &user_data);
7182
7183   /* Check response HEADERS */
7184   /* Send bogus stream ID */
7185   CU_ASSERT(0 == nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, 3,
7186                                         NULL, NULL, 0, NULL));
7187   CU_ASSERT(0 == nghttp2_session_send(session));
7188   CU_ASSERT(1 == user_data.frame_not_send_cb_called);
7189   CU_ASSERT(NGHTTP2_HEADERS == user_data.not_sent_frame_type);
7190   CU_ASSERT(NGHTTP2_ERR_STREAM_CLOSED == user_data.not_sent_error);
7191
7192   user_data.frame_not_send_cb_called = 0;
7193   /* Shutdown transmission */
7194   stream->shut_flags |= NGHTTP2_SHUT_WR;
7195   CU_ASSERT(0 == nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, 1,
7196                                         NULL, NULL, 0, NULL));
7197   CU_ASSERT(0 == nghttp2_session_send(session));
7198   CU_ASSERT(1 == user_data.frame_not_send_cb_called);
7199   CU_ASSERT(NGHTTP2_HEADERS == user_data.not_sent_frame_type);
7200   CU_ASSERT(NGHTTP2_ERR_STREAM_SHUT_WR == user_data.not_sent_error);
7201
7202   stream->shut_flags = NGHTTP2_SHUT_NONE;
7203   user_data.frame_not_send_cb_called = 0;
7204   /* Queue RST_STREAM */
7205   CU_ASSERT(0 == nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, 1,
7206                                         NULL, NULL, 0, NULL));
7207   CU_ASSERT(0 == nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, 1,
7208                                            NGHTTP2_INTERNAL_ERROR));
7209   CU_ASSERT(0 == nghttp2_session_send(session));
7210   CU_ASSERT(1 == user_data.frame_not_send_cb_called);
7211   CU_ASSERT(NGHTTP2_HEADERS == user_data.not_sent_frame_type);
7212   CU_ASSERT(NGHTTP2_ERR_STREAM_CLOSING == user_data.not_sent_error);
7213
7214   nghttp2_session_del(session);
7215
7216   /* Check request HEADERS */
7217   user_data.frame_not_send_cb_called = 0;
7218   CU_ASSERT(nghttp2_session_client_new(&session, &callbacks, &user_data) == 0);
7219   /* Maximum Stream ID is reached */
7220   session->next_stream_id = (1u << 31) + 1;
7221   CU_ASSERT(NGHTTP2_ERR_STREAM_ID_NOT_AVAILABLE ==
7222             nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, -1, NULL,
7223                                    NULL, 0, NULL));
7224
7225   user_data.frame_not_send_cb_called = 0;
7226   /* GOAWAY received */
7227   session->goaway_flags |= NGHTTP2_GOAWAY_RECV;
7228   session->next_stream_id = 9;
7229
7230   CU_ASSERT(0 < nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, -1,
7231                                        NULL, NULL, 0, NULL));
7232   CU_ASSERT(0 == nghttp2_session_send(session));
7233   CU_ASSERT(1 == user_data.frame_not_send_cb_called);
7234   CU_ASSERT(NGHTTP2_HEADERS == user_data.not_sent_frame_type);
7235   CU_ASSERT(NGHTTP2_ERR_START_STREAM_NOT_ALLOWED == user_data.not_sent_error);
7236
7237   nghttp2_session_del(session);
7238 }
7239
7240 void test_nghttp2_session_get_outbound_queue_size(void) {
7241   nghttp2_session *session;
7242   nghttp2_session_callbacks callbacks;
7243
7244   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7245   CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, NULL));
7246   CU_ASSERT(0 == nghttp2_session_get_outbound_queue_size(session));
7247
7248   CU_ASSERT(0 == nghttp2_submit_ping(session, NGHTTP2_FLAG_NONE, NULL));
7249   CU_ASSERT(1 == nghttp2_session_get_outbound_queue_size(session));
7250
7251   CU_ASSERT(0 == nghttp2_submit_goaway(session, NGHTTP2_FLAG_NONE, 2,
7252                                        NGHTTP2_NO_ERROR, NULL, 0));
7253   CU_ASSERT(2 == nghttp2_session_get_outbound_queue_size(session));
7254
7255   nghttp2_session_del(session);
7256 }
7257
7258 void test_nghttp2_session_get_effective_local_window_size(void) {
7259   nghttp2_session *session;
7260   nghttp2_session_callbacks callbacks;
7261   nghttp2_stream *stream;
7262
7263   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7264   CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, NULL));
7265
7266   stream = open_sent_stream(session, 1);
7267
7268   CU_ASSERT(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE ==
7269             nghttp2_session_get_effective_local_window_size(session));
7270   CU_ASSERT(0 == nghttp2_session_get_effective_recv_data_length(session));
7271
7272   CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE ==
7273             nghttp2_session_get_stream_effective_local_window_size(session, 1));
7274   CU_ASSERT(0 ==
7275             nghttp2_session_get_stream_effective_recv_data_length(session, 1));
7276
7277   /* Check connection flow control */
7278   session->recv_window_size = 100;
7279   nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 0, 1100);
7280
7281   CU_ASSERT(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE + 1000 ==
7282             nghttp2_session_get_effective_local_window_size(session));
7283   CU_ASSERT(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE + 1000 ==
7284             nghttp2_session_get_local_window_size(session));
7285   CU_ASSERT(0 == nghttp2_session_get_effective_recv_data_length(session));
7286
7287   nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 0, -50);
7288   /* Now session->recv_window_size = -50 */
7289   CU_ASSERT(-50 == session->recv_window_size);
7290   CU_ASSERT(50 == session->recv_reduction);
7291   CU_ASSERT(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE + 950 ==
7292             nghttp2_session_get_effective_local_window_size(session));
7293   CU_ASSERT(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE + 1000 ==
7294             nghttp2_session_get_local_window_size(session));
7295   CU_ASSERT(0 == nghttp2_session_get_effective_recv_data_length(session));
7296
7297   session->recv_window_size += 50;
7298
7299   /* Now session->recv_window_size = 0 */
7300
7301   CU_ASSERT(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE + 950 ==
7302             nghttp2_session_get_local_window_size(session));
7303
7304   nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 0, 100);
7305   CU_ASSERT(50 == session->recv_window_size);
7306   CU_ASSERT(0 == session->recv_reduction);
7307   CU_ASSERT(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE + 1050 ==
7308             nghttp2_session_get_effective_local_window_size(session));
7309   CU_ASSERT(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE + 1000 ==
7310             nghttp2_session_get_local_window_size(session));
7311   CU_ASSERT(50 == nghttp2_session_get_effective_recv_data_length(session));
7312
7313   /* Check stream flow control */
7314   stream->recv_window_size = 100;
7315   nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 1, 1100);
7316
7317   CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE + 1000 ==
7318             nghttp2_session_get_stream_effective_local_window_size(session, 1));
7319   CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE + 1000 ==
7320             nghttp2_session_get_stream_local_window_size(session, 1));
7321   CU_ASSERT(0 ==
7322             nghttp2_session_get_stream_effective_recv_data_length(session, 1));
7323
7324   nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 1, -50);
7325   /* Now stream->recv_window_size = -50 */
7326   CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE + 950 ==
7327             nghttp2_session_get_stream_effective_local_window_size(session, 1));
7328   CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE + 1000 ==
7329             nghttp2_session_get_stream_local_window_size(session, 1));
7330   CU_ASSERT(0 ==
7331             nghttp2_session_get_stream_effective_recv_data_length(session, 1));
7332
7333   stream->recv_window_size += 50;
7334   /* Now stream->recv_window_size = 0 */
7335   nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 1, 100);
7336   CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE + 1050 ==
7337             nghttp2_session_get_stream_effective_local_window_size(session, 1));
7338   CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE + 1000 ==
7339             nghttp2_session_get_stream_local_window_size(session, 1));
7340   CU_ASSERT(50 ==
7341             nghttp2_session_get_stream_effective_recv_data_length(session, 1));
7342
7343   nghttp2_session_del(session);
7344 }
7345
7346 void test_nghttp2_session_set_option(void) {
7347   nghttp2_session *session;
7348   nghttp2_session_callbacks callbacks;
7349   nghttp2_option *option;
7350   nghttp2_hd_deflater *deflater;
7351   int rv;
7352
7353   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7354   callbacks.send_callback = null_send_callback;
7355
7356   /* Test for nghttp2_option_set_no_auto_window_update */
7357   nghttp2_option_new(&option);
7358   nghttp2_option_set_no_auto_window_update(option, 1);
7359
7360   nghttp2_session_client_new2(&session, &callbacks, NULL, option);
7361
7362   CU_ASSERT(session->opt_flags & NGHTTP2_OPTMASK_NO_AUTO_WINDOW_UPDATE);
7363
7364   nghttp2_session_del(session);
7365   nghttp2_option_del(option);
7366
7367   /* Test for nghttp2_option_set_peer_max_concurrent_streams */
7368   nghttp2_option_new(&option);
7369   nghttp2_option_set_peer_max_concurrent_streams(option, 100);
7370
7371   nghttp2_session_client_new2(&session, &callbacks, NULL, option);
7372
7373   CU_ASSERT(100 == session->remote_settings.max_concurrent_streams);
7374   nghttp2_session_del(session);
7375   nghttp2_option_del(option);
7376
7377   /* Test for nghttp2_option_set_max_reserved_remote_streams */
7378   nghttp2_option_new(&option);
7379   nghttp2_option_set_max_reserved_remote_streams(option, 99);
7380
7381   nghttp2_session_client_new2(&session, &callbacks, NULL, option);
7382
7383   CU_ASSERT(99 == session->max_incoming_reserved_streams);
7384   nghttp2_session_del(session);
7385   nghttp2_option_del(option);
7386
7387   /* Test for nghttp2_option_set_no_auto_ping_ack */
7388   nghttp2_option_new(&option);
7389   nghttp2_option_set_no_auto_ping_ack(option, 1);
7390
7391   nghttp2_session_client_new2(&session, &callbacks, NULL, option);
7392
7393   CU_ASSERT(session->opt_flags & NGHTTP2_OPTMASK_NO_AUTO_PING_ACK);
7394
7395   nghttp2_session_del(session);
7396   nghttp2_option_del(option);
7397
7398   /* Test for nghttp2_option_set_max_deflate_dynamic_table_size */
7399   nghttp2_option_new(&option);
7400   nghttp2_option_set_max_deflate_dynamic_table_size(option, 0);
7401
7402   nghttp2_session_client_new2(&session, &callbacks, NULL, option);
7403
7404   deflater = &session->hd_deflater;
7405
7406   rv = nghttp2_submit_request(session, NULL, reqnv, ARRLEN(reqnv), NULL, NULL);
7407
7408   CU_ASSERT(1 == rv);
7409
7410   rv = nghttp2_session_send(session);
7411
7412   CU_ASSERT(0 == rv);
7413   CU_ASSERT(0 == deflater->deflate_hd_table_bufsize_max);
7414   CU_ASSERT(0 == deflater->ctx.hd_table_bufsize);
7415
7416   nghttp2_session_del(session);
7417   nghttp2_option_del(option);
7418 }
7419
7420 void test_nghttp2_session_data_backoff_by_high_pri_frame(void) {
7421   nghttp2_session *session;
7422   nghttp2_session_callbacks callbacks;
7423   my_user_data ud;
7424   nghttp2_data_provider data_prd;
7425   nghttp2_stream *stream;
7426
7427   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7428   callbacks.send_callback = block_count_send_callback;
7429   callbacks.on_frame_send_callback = on_frame_send_callback;
7430   data_prd.read_callback = fixed_length_data_source_read_callback;
7431
7432   ud.frame_send_cb_called = 0;
7433   ud.data_source_length = NGHTTP2_DATA_PAYLOADLEN * 4;
7434
7435   nghttp2_session_client_new(&session, &callbacks, &ud);
7436   nghttp2_submit_request(session, NULL, NULL, 0, &data_prd, NULL);
7437
7438   session->remote_window_size = 1 << 20;
7439
7440   ud.block_count = 2;
7441   /* Sends request HEADERS + DATA[0] */
7442   CU_ASSERT(0 == nghttp2_session_send(session));
7443
7444   stream = nghttp2_session_get_stream(session, 1);
7445   stream->remote_window_size = 1 << 20;
7446
7447   CU_ASSERT(NGHTTP2_DATA == ud.sent_frame_type);
7448   /* data for DATA[1] is read from data_prd but it is not sent */
7449   CU_ASSERT(ud.data_source_length == NGHTTP2_DATA_PAYLOADLEN * 2);
7450
7451   nghttp2_submit_ping(session, NGHTTP2_FLAG_NONE, NULL);
7452   ud.block_count = 2;
7453   /* Sends DATA[1] + PING, PING is interleaved in DATA sequence */
7454   CU_ASSERT(0 == nghttp2_session_send(session));
7455   CU_ASSERT(NGHTTP2_PING == ud.sent_frame_type);
7456   /* data for DATA[2] is read from data_prd but it is not sent */
7457   CU_ASSERT(ud.data_source_length == NGHTTP2_DATA_PAYLOADLEN);
7458
7459   ud.block_count = 2;
7460   /* Sends DATA[2..3] */
7461   CU_ASSERT(0 == nghttp2_session_send(session));
7462
7463   CU_ASSERT(stream->shut_flags & NGHTTP2_SHUT_WR);
7464
7465   nghttp2_session_del(session);
7466 }
7467
7468 static void check_session_recv_data_with_padding(nghttp2_bufs *bufs,
7469                                                  size_t datalen,
7470                                                  nghttp2_mem *mem) {
7471   nghttp2_session *session;
7472   my_user_data ud;
7473   nghttp2_session_callbacks callbacks;
7474   uint8_t *in;
7475   size_t inlen;
7476
7477   memset(&callbacks, 0, sizeof(callbacks));
7478   callbacks.on_frame_recv_callback = on_frame_recv_callback;
7479   callbacks.on_data_chunk_recv_callback = on_data_chunk_recv_callback;
7480   nghttp2_session_server_new(&session, &callbacks, &ud);
7481
7482   open_recv_stream(session, 1);
7483
7484   inlen = (size_t)nghttp2_bufs_remove(bufs, &in);
7485
7486   ud.frame_recv_cb_called = 0;
7487   ud.data_chunk_len = 0;
7488
7489   CU_ASSERT((ssize_t)inlen == nghttp2_session_mem_recv(session, in, inlen));
7490
7491   CU_ASSERT(1 == ud.frame_recv_cb_called);
7492   CU_ASSERT(datalen == ud.data_chunk_len);
7493
7494   mem->free(in, NULL);
7495   nghttp2_session_del(session);
7496 }
7497
7498 void test_nghttp2_session_pack_data_with_padding(void) {
7499   nghttp2_session *session;
7500   my_user_data ud;
7501   nghttp2_session_callbacks callbacks;
7502   nghttp2_data_provider data_prd;
7503   nghttp2_frame *frame;
7504   size_t datalen = 55;
7505   nghttp2_mem *mem;
7506
7507   mem = nghttp2_mem_default();
7508
7509   memset(&callbacks, 0, sizeof(callbacks));
7510   callbacks.send_callback = block_count_send_callback;
7511   callbacks.on_frame_send_callback = on_frame_send_callback;
7512   callbacks.select_padding_callback = select_padding_callback;
7513
7514   data_prd.read_callback = fixed_length_data_source_read_callback;
7515
7516   nghttp2_session_client_new(&session, &callbacks, &ud);
7517
7518   ud.padlen = 63;
7519
7520   nghttp2_submit_request(session, NULL, NULL, 0, &data_prd, NULL);
7521   ud.block_count = 1;
7522   ud.data_source_length = datalen;
7523   /* Sends HEADERS */
7524   CU_ASSERT(0 == nghttp2_session_send(session));
7525   CU_ASSERT(NGHTTP2_HEADERS == ud.sent_frame_type);
7526
7527   frame = &session->aob.item->frame;
7528
7529   CU_ASSERT(ud.padlen == frame->data.padlen);
7530   CU_ASSERT(frame->hd.flags & NGHTTP2_FLAG_PADDED);
7531
7532   /* Check reception of this DATA frame */
7533   check_session_recv_data_with_padding(&session->aob.framebufs, datalen, mem);
7534
7535   nghttp2_session_del(session);
7536 }
7537
7538 void test_nghttp2_session_pack_headers_with_padding(void) {
7539   nghttp2_session *session, *sv_session;
7540   accumulator acc;
7541   my_user_data ud;
7542   nghttp2_session_callbacks callbacks;
7543
7544   memset(&callbacks, 0, sizeof(callbacks));
7545   callbacks.send_callback = accumulator_send_callback;
7546   callbacks.on_frame_send_callback = on_frame_send_callback;
7547   callbacks.select_padding_callback = select_padding_callback;
7548   callbacks.on_frame_recv_callback = on_frame_recv_callback;
7549
7550   acc.length = 0;
7551   ud.acc = &acc;
7552
7553   nghttp2_session_client_new(&session, &callbacks, &ud);
7554   nghttp2_session_server_new(&sv_session, &callbacks, &ud);
7555
7556   ud.padlen = 163;
7557
7558   CU_ASSERT(1 == nghttp2_submit_request(session, NULL, reqnv, ARRLEN(reqnv),
7559                                         NULL, NULL));
7560   CU_ASSERT(0 == nghttp2_session_send(session));
7561
7562   CU_ASSERT(acc.length < NGHTTP2_MAX_PAYLOADLEN);
7563   ud.frame_recv_cb_called = 0;
7564   CU_ASSERT((ssize_t)acc.length ==
7565             nghttp2_session_mem_recv(sv_session, acc.buf, acc.length));
7566   CU_ASSERT(1 == ud.frame_recv_cb_called);
7567   CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(sv_session));
7568
7569   nghttp2_session_del(sv_session);
7570   nghttp2_session_del(session);
7571 }
7572
7573 void test_nghttp2_pack_settings_payload(void) {
7574   nghttp2_settings_entry iv[2];
7575   uint8_t buf[64];
7576   ssize_t len;
7577   nghttp2_settings_entry *resiv;
7578   size_t resniv;
7579   nghttp2_mem *mem;
7580
7581   mem = nghttp2_mem_default();
7582
7583   iv[0].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
7584   iv[0].value = 1023;
7585   iv[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
7586   iv[1].value = 4095;
7587
7588   len = nghttp2_pack_settings_payload(buf, sizeof(buf), iv, 2);
7589   CU_ASSERT(2 * NGHTTP2_FRAME_SETTINGS_ENTRY_LENGTH == len);
7590   CU_ASSERT(0 == nghttp2_frame_unpack_settings_payload2(&resiv, &resniv, buf,
7591                                                         (size_t)len, mem));
7592   CU_ASSERT(2 == resniv);
7593   CU_ASSERT(NGHTTP2_SETTINGS_HEADER_TABLE_SIZE == resiv[0].settings_id);
7594   CU_ASSERT(1023 == resiv[0].value);
7595   CU_ASSERT(NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE == resiv[1].settings_id);
7596   CU_ASSERT(4095 == resiv[1].value);
7597
7598   mem->free(resiv, NULL);
7599
7600   len = nghttp2_pack_settings_payload(buf, 9 /* too small */, iv, 2);
7601   CU_ASSERT(NGHTTP2_ERR_INSUFF_BUFSIZE == len);
7602 }
7603
7604 #define check_stream_dep_sib(STREAM, DEP_PREV, DEP_NEXT, SIB_PREV, SIB_NEXT)   \
7605   do {                                                                         \
7606     CU_ASSERT(DEP_PREV == STREAM->dep_prev);                                   \
7607     CU_ASSERT(DEP_NEXT == STREAM->dep_next);                                   \
7608     CU_ASSERT(SIB_PREV == STREAM->sib_prev);                                   \
7609     CU_ASSERT(SIB_NEXT == STREAM->sib_next);                                   \
7610   } while (0)
7611
7612 /* nghttp2_stream_dep_add() and its families functions should be
7613    tested in nghttp2_stream_test.c, but it is easier to use
7614    nghttp2_session_open_stream().  Therefore, we test them here. */
7615 void test_nghttp2_session_stream_dep_add(void) {
7616   nghttp2_session *session;
7617   nghttp2_session_callbacks callbacks;
7618   nghttp2_stream *a, *b, *c, *d, *e, *root;
7619
7620   memset(&callbacks, 0, sizeof(callbacks));
7621
7622   nghttp2_session_server_new(&session, &callbacks, NULL);
7623
7624   root = &session->root;
7625
7626   a = open_stream(session, 1);
7627
7628   c = open_stream_with_dep(session, 5, a);
7629   b = open_stream_with_dep(session, 3, a);
7630   d = open_stream_with_dep(session, 7, c);
7631
7632   /* a
7633    * |
7634    * b--c
7635    *    |
7636    *    d
7637    */
7638
7639   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 2 == a->sum_dep_weight);
7640   CU_ASSERT(0 == b->sum_dep_weight);
7641   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == c->sum_dep_weight);
7642   CU_ASSERT(0 == d->sum_dep_weight);
7643
7644   check_stream_dep_sib(a, root, b, NULL, NULL);
7645   check_stream_dep_sib(b, a, NULL, NULL, c);
7646   check_stream_dep_sib(c, a, d, b, NULL);
7647   check_stream_dep_sib(d, c, NULL, NULL, NULL);
7648
7649   CU_ASSERT(a == session->root.dep_next);
7650
7651   e = open_stream_with_dep_excl(session, 9, a);
7652
7653   /* a
7654    * |
7655    * e
7656    * |
7657    * b--c
7658    *    |
7659    *    d
7660    */
7661
7662   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == a->sum_dep_weight);
7663   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 2 == e->sum_dep_weight);
7664   CU_ASSERT(0 == b->sum_dep_weight);
7665   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == c->sum_dep_weight);
7666   CU_ASSERT(0 == d->sum_dep_weight);
7667
7668   check_stream_dep_sib(a, root, e, NULL, NULL);
7669   check_stream_dep_sib(e, a, b, NULL, NULL);
7670   check_stream_dep_sib(b, e, NULL, NULL, c);
7671   check_stream_dep_sib(c, e, d, b, NULL);
7672   check_stream_dep_sib(d, c, NULL, NULL, NULL);
7673
7674   CU_ASSERT(a == session->root.dep_next);
7675
7676   nghttp2_session_del(session);
7677 }
7678
7679 void test_nghttp2_session_stream_dep_remove(void) {
7680   nghttp2_session *session;
7681   nghttp2_session_callbacks callbacks;
7682   nghttp2_stream *a, *b, *c, *d, *e, *f, *root;
7683
7684   memset(&callbacks, 0, sizeof(callbacks));
7685
7686   /* Remove root */
7687   nghttp2_session_server_new(&session, &callbacks, NULL);
7688
7689   root = &session->root;
7690
7691   a = open_stream(session, 1);
7692   b = open_stream_with_dep(session, 3, a);
7693   c = open_stream_with_dep(session, 5, a);
7694   d = open_stream_with_dep(session, 7, c);
7695
7696   /* a
7697    * |
7698    * c--b
7699    * |
7700    * d
7701    */
7702
7703   nghttp2_stream_dep_remove(a);
7704
7705   /* becomes:
7706    * c    b
7707    * |
7708    * d
7709    */
7710
7711   CU_ASSERT(0 == a->sum_dep_weight);
7712   CU_ASSERT(0 == b->sum_dep_weight);
7713   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == c->sum_dep_weight);
7714   CU_ASSERT(0 == d->sum_dep_weight);
7715
7716   check_stream_dep_sib(a, NULL, NULL, NULL, NULL);
7717   check_stream_dep_sib(b, root, NULL, c, NULL);
7718   check_stream_dep_sib(c, root, d, NULL, b);
7719   check_stream_dep_sib(d, c, NULL, NULL, NULL);
7720
7721   CU_ASSERT(c == session->root.dep_next);
7722
7723   nghttp2_session_del(session);
7724
7725   /* Remove right most stream */
7726   nghttp2_session_server_new(&session, &callbacks, NULL);
7727
7728   root = &session->root;
7729
7730   a = open_stream(session, 1);
7731   b = open_stream_with_dep(session, 3, a);
7732   c = open_stream_with_dep(session, 5, a);
7733   d = open_stream_with_dep(session, 7, c);
7734
7735   /* a
7736    * |
7737    * c--b
7738    * |
7739    * d
7740    */
7741
7742   nghttp2_stream_dep_remove(b);
7743
7744   /* becomes:
7745    * a
7746    * |
7747    * c
7748    * |
7749    * d
7750    */
7751
7752   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == a->sum_dep_weight);
7753   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == c->sum_dep_weight);
7754   CU_ASSERT(0 == d->sum_dep_weight);
7755   CU_ASSERT(0 == b->sum_dep_weight);
7756
7757   check_stream_dep_sib(a, root, c, NULL, NULL);
7758   check_stream_dep_sib(b, NULL, NULL, NULL, NULL);
7759   check_stream_dep_sib(c, a, d, NULL, NULL);
7760   check_stream_dep_sib(d, c, NULL, NULL, NULL);
7761
7762   CU_ASSERT(a == session->root.dep_next);
7763
7764   nghttp2_session_del(session);
7765
7766   /* Remove left most stream */
7767   nghttp2_session_server_new(&session, &callbacks, NULL);
7768
7769   root = &session->root;
7770
7771   a = open_stream(session, 1);
7772   b = open_stream_with_dep(session, 3, a);
7773   c = open_stream_with_dep(session, 5, a);
7774   d = open_stream_with_dep(session, 7, c);
7775   e = open_stream_with_dep(session, 9, c);
7776
7777   /* a
7778    * |
7779    * c--b
7780    * |
7781    * e--d
7782    */
7783
7784   nghttp2_stream_dep_remove(c);
7785
7786   /* becomes:
7787    * a
7788    * |
7789    * e--d--b
7790    */
7791
7792   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 2 == a->sum_dep_weight);
7793   CU_ASSERT(0 == b->sum_dep_weight);
7794   CU_ASSERT(0 == d->sum_dep_weight);
7795   CU_ASSERT(0 == c->sum_dep_weight);
7796   CU_ASSERT(0 == e->sum_dep_weight);
7797
7798   check_stream_dep_sib(a, root, e, NULL, NULL);
7799   check_stream_dep_sib(b, a, NULL, d, NULL);
7800   check_stream_dep_sib(c, NULL, NULL, NULL, NULL);
7801   check_stream_dep_sib(d, a, NULL, e, b);
7802   check_stream_dep_sib(e, a, NULL, NULL, d);
7803
7804   nghttp2_session_del(session);
7805
7806   /* Remove middle stream */
7807   nghttp2_session_server_new(&session, &callbacks, NULL);
7808
7809   root = &session->root;
7810
7811   a = open_stream(session, 1);
7812   b = open_stream_with_dep(session, 3, a);
7813   c = open_stream_with_dep(session, 5, a);
7814   d = open_stream_with_dep(session, 7, a);
7815   e = open_stream_with_dep(session, 9, c);
7816   f = open_stream_with_dep(session, 11, c);
7817
7818   /* a
7819    * |
7820    * d--c--b
7821    *    |
7822    *    f--e
7823    */
7824
7825   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 3 == a->sum_dep_weight);
7826   CU_ASSERT(0 == b->sum_dep_weight);
7827   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 2 == c->sum_dep_weight);
7828   CU_ASSERT(0 == d->sum_dep_weight);
7829   CU_ASSERT(0 == e->sum_dep_weight);
7830   CU_ASSERT(0 == f->sum_dep_weight);
7831
7832   nghttp2_stream_dep_remove(c);
7833
7834   /* becomes:
7835    * a
7836    * |
7837    * d--f--e--b
7838    */
7839
7840   /* c's weight 16 is distributed evenly to e and f.  Each weight of e
7841      and f becomes 8. */
7842   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 2 + 8 * 2 == a->sum_dep_weight);
7843   CU_ASSERT(0 == b->sum_dep_weight);
7844   CU_ASSERT(0 == c->sum_dep_weight);
7845   CU_ASSERT(0 == d->sum_dep_weight);
7846   CU_ASSERT(0 == e->sum_dep_weight);
7847   CU_ASSERT(0 == f->sum_dep_weight);
7848
7849   check_stream_dep_sib(a, root, d, NULL, NULL);
7850   check_stream_dep_sib(b, a, NULL, e, NULL);
7851   check_stream_dep_sib(c, NULL, NULL, NULL, NULL);
7852   check_stream_dep_sib(e, a, NULL, f, b);
7853   check_stream_dep_sib(f, a, NULL, d, e);
7854   check_stream_dep_sib(d, a, NULL, NULL, f);
7855
7856   nghttp2_session_del(session);
7857 }
7858
7859 void test_nghttp2_session_stream_dep_add_subtree(void) {
7860   nghttp2_session *session;
7861   nghttp2_session_callbacks callbacks;
7862   nghttp2_stream *a, *b, *c, *d, *e, *f, *root;
7863
7864   memset(&callbacks, 0, sizeof(callbacks));
7865
7866   /* dep_stream has dep_next */
7867   nghttp2_session_server_new(&session, &callbacks, NULL);
7868
7869   root = &session->root;
7870
7871   a = open_stream(session, 1);
7872   b = open_stream_with_dep(session, 3, a);
7873   c = open_stream_with_dep(session, 5, a);
7874   d = open_stream_with_dep(session, 7, c);
7875
7876   e = open_stream(session, 9);
7877   f = open_stream_with_dep(session, 11, e);
7878
7879   /* a         e
7880    * |         |
7881    * c--b      f
7882    * |
7883    * d
7884    */
7885
7886   nghttp2_stream_dep_remove_subtree(e);
7887   nghttp2_stream_dep_add_subtree(a, e);
7888
7889   /* becomes
7890    * a
7891    * |
7892    * e--c--b
7893    * |  |
7894    * f  d
7895    */
7896
7897   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 3 == a->sum_dep_weight);
7898   CU_ASSERT(0 == b->sum_dep_weight);
7899   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == c->sum_dep_weight);
7900   CU_ASSERT(0 == d->sum_dep_weight);
7901   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == e->sum_dep_weight);
7902   CU_ASSERT(0 == f->sum_dep_weight);
7903
7904   check_stream_dep_sib(a, root, e, NULL, NULL);
7905   check_stream_dep_sib(b, a, NULL, c, NULL);
7906   check_stream_dep_sib(c, a, d, e, b);
7907   check_stream_dep_sib(d, c, NULL, NULL, NULL);
7908   check_stream_dep_sib(e, a, f, NULL, c);
7909   check_stream_dep_sib(f, e, NULL, NULL, NULL);
7910
7911   nghttp2_session_del(session);
7912
7913   /* dep_stream has dep_next and now we insert subtree */
7914   nghttp2_session_server_new(&session, &callbacks, NULL);
7915
7916   root = &session->root;
7917
7918   a = open_stream(session, 1);
7919   b = open_stream_with_dep(session, 3, a);
7920   c = open_stream_with_dep(session, 5, a);
7921   d = open_stream_with_dep(session, 7, c);
7922
7923   e = open_stream(session, 9);
7924   f = open_stream_with_dep(session, 11, e);
7925
7926   /* a         e
7927    * |         |
7928    * c--b      f
7929    * |
7930    * d
7931    */
7932
7933   nghttp2_stream_dep_remove_subtree(e);
7934   nghttp2_stream_dep_insert_subtree(a, e);
7935
7936   /* becomes
7937    * a
7938    * |
7939    * e
7940    * |
7941    * f--c--b
7942    *    |
7943    *    d
7944    */
7945
7946   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == a->sum_dep_weight);
7947   CU_ASSERT(0 == b->sum_dep_weight);
7948   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == c->sum_dep_weight);
7949   CU_ASSERT(0 == d->sum_dep_weight);
7950   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 3 == e->sum_dep_weight);
7951   CU_ASSERT(0 == f->sum_dep_weight);
7952
7953   check_stream_dep_sib(a, root, e, NULL, NULL);
7954   check_stream_dep_sib(e, a, f, NULL, NULL);
7955   check_stream_dep_sib(f, e, NULL, NULL, c);
7956   check_stream_dep_sib(b, e, NULL, c, NULL);
7957   check_stream_dep_sib(c, e, d, f, b);
7958   check_stream_dep_sib(d, c, NULL, NULL, NULL);
7959
7960   nghttp2_session_del(session);
7961 }
7962
7963 void test_nghttp2_session_stream_dep_remove_subtree(void) {
7964   nghttp2_session *session;
7965   nghttp2_session_callbacks callbacks;
7966   nghttp2_stream *a, *b, *c, *d, *e, *root;
7967
7968   memset(&callbacks, 0, sizeof(callbacks));
7969
7970   /* Remove left most stream */
7971   nghttp2_session_server_new(&session, &callbacks, NULL);
7972
7973   root = &session->root;
7974
7975   a = open_stream(session, 1);
7976   b = open_stream_with_dep(session, 3, a);
7977   c = open_stream_with_dep(session, 5, a);
7978   d = open_stream_with_dep(session, 7, c);
7979
7980   /* a
7981    * |
7982    * c--b
7983    * |
7984    * d
7985    */
7986
7987   nghttp2_stream_dep_remove_subtree(c);
7988
7989   /* becomes
7990    * a  c
7991    * |  |
7992    * b  d
7993    */
7994
7995   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == a->sum_dep_weight);
7996   CU_ASSERT(0 == b->sum_dep_weight);
7997   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == c->sum_dep_weight);
7998   CU_ASSERT(0 == d->sum_dep_weight);
7999
8000   check_stream_dep_sib(a, root, b, NULL, NULL);
8001   check_stream_dep_sib(b, a, NULL, NULL, NULL);
8002   check_stream_dep_sib(c, NULL, d, NULL, NULL);
8003   check_stream_dep_sib(d, c, NULL, NULL, NULL);
8004
8005   nghttp2_session_del(session);
8006
8007   /* Remove right most stream */
8008   nghttp2_session_server_new(&session, &callbacks, NULL);
8009
8010   root = &session->root;
8011
8012   a = open_stream(session, 1);
8013   b = open_stream_with_dep(session, 3, a);
8014   c = open_stream_with_dep(session, 5, a);
8015   d = open_stream_with_dep(session, 7, c);
8016
8017   /* a
8018    * |
8019    * c--b
8020    * |
8021    * d
8022    */
8023
8024   nghttp2_stream_dep_remove_subtree(b);
8025
8026   /* becomes
8027    * a  b
8028    * |
8029    * c
8030    * |
8031    * d
8032    */
8033
8034   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == a->sum_dep_weight);
8035   CU_ASSERT(0 == b->sum_dep_weight);
8036   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == c->sum_dep_weight);
8037   CU_ASSERT(0 == d->sum_dep_weight);
8038
8039   check_stream_dep_sib(a, root, c, NULL, NULL);
8040   check_stream_dep_sib(c, a, d, NULL, NULL);
8041   check_stream_dep_sib(d, c, NULL, NULL, NULL);
8042   check_stream_dep_sib(b, NULL, NULL, NULL, NULL);
8043
8044   nghttp2_session_del(session);
8045
8046   /* Remove middle stream */
8047   nghttp2_session_server_new(&session, &callbacks, NULL);
8048
8049   root = &session->root;
8050
8051   a = open_stream(session, 1);
8052   e = open_stream_with_dep(session, 9, a);
8053   c = open_stream_with_dep(session, 5, a);
8054   b = open_stream_with_dep(session, 3, a);
8055   d = open_stream_with_dep(session, 7, c);
8056
8057   /* a
8058    * |
8059    * b--c--e
8060    *    |
8061    *    d
8062    */
8063
8064   nghttp2_stream_dep_remove_subtree(c);
8065
8066   /* becomes
8067    * a     c
8068    * |     |
8069    * b--e  d
8070    */
8071
8072   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 2 == a->sum_dep_weight);
8073   CU_ASSERT(0 == b->sum_dep_weight);
8074   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == c->sum_dep_weight);
8075   CU_ASSERT(0 == d->sum_dep_weight);
8076   CU_ASSERT(0 == e->sum_dep_weight);
8077
8078   check_stream_dep_sib(a, root, b, NULL, NULL);
8079   check_stream_dep_sib(b, a, NULL, NULL, e);
8080   check_stream_dep_sib(e, a, NULL, b, NULL);
8081   check_stream_dep_sib(c, NULL, d, NULL, NULL);
8082   check_stream_dep_sib(d, c, NULL, NULL, NULL);
8083
8084   nghttp2_session_del(session);
8085 }
8086
8087 void test_nghttp2_session_stream_dep_all_your_stream_are_belong_to_us(void) {
8088   nghttp2_session *session;
8089   nghttp2_session_callbacks callbacks;
8090   nghttp2_stream *a, *b, *c, *d, *root;
8091   nghttp2_outbound_item *db, *dc;
8092   nghttp2_mem *mem;
8093
8094   mem = nghttp2_mem_default();
8095
8096   memset(&callbacks, 0, sizeof(callbacks));
8097
8098   nghttp2_session_server_new(&session, &callbacks, NULL);
8099
8100   root = &session->root;
8101
8102   a = open_stream(session, 1);
8103   b = open_stream_with_dep(session, 3, a);
8104
8105   c = open_stream(session, 5);
8106
8107   /* a     c
8108    * |
8109    * b
8110    */
8111
8112   nghttp2_stream_dep_remove_subtree(c);
8113   CU_ASSERT(0 == nghttp2_stream_dep_insert_subtree(&session->root, c));
8114
8115   /*
8116    * c
8117    * |
8118    * a
8119    * |
8120    * b
8121    */
8122
8123   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == c->sum_dep_weight);
8124   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == a->sum_dep_weight);
8125   CU_ASSERT(0 == b->sum_dep_weight);
8126
8127   CU_ASSERT(nghttp2_pq_empty(&a->obq));
8128   CU_ASSERT(nghttp2_pq_empty(&b->obq));
8129   CU_ASSERT(nghttp2_pq_empty(&c->obq));
8130
8131   check_stream_dep_sib(c, root, a, NULL, NULL);
8132   check_stream_dep_sib(a, c, b, NULL, NULL);
8133   check_stream_dep_sib(b, a, NULL, NULL, NULL);
8134
8135   nghttp2_session_del(session);
8136
8137   nghttp2_session_server_new(&session, &callbacks, NULL);
8138
8139   root = &session->root;
8140
8141   a = open_stream(session, 1);
8142   b = open_stream(session, 3);
8143   c = open_stream(session, 5);
8144
8145   /*
8146    * a  b   c
8147    */
8148
8149   nghttp2_stream_dep_remove_subtree(c);
8150   CU_ASSERT(0 == nghttp2_stream_dep_insert_subtree(&session->root, c));
8151
8152   /*
8153    * c
8154    * |
8155    * b--a
8156    */
8157
8158   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 2 == c->sum_dep_weight);
8159   CU_ASSERT(0 == b->sum_dep_weight);
8160   CU_ASSERT(0 == a->sum_dep_weight);
8161
8162   CU_ASSERT(nghttp2_pq_empty(&a->obq));
8163   CU_ASSERT(nghttp2_pq_empty(&b->obq));
8164   CU_ASSERT(nghttp2_pq_empty(&c->obq));
8165
8166   check_stream_dep_sib(c, root, b, NULL, NULL);
8167   check_stream_dep_sib(b, c, NULL, NULL, a);
8168   check_stream_dep_sib(a, c, NULL, b, NULL);
8169
8170   nghttp2_session_del(session);
8171
8172   nghttp2_session_server_new(&session, &callbacks, NULL);
8173
8174   root = &session->root;
8175
8176   a = open_stream(session, 1);
8177   b = open_stream_with_dep(session, 3, a);
8178
8179   c = open_stream(session, 5);
8180   d = open_stream_with_dep(session, 7, c);
8181
8182   /* a     c
8183    * |     |
8184    * b     d
8185    */
8186
8187   nghttp2_stream_dep_remove_subtree(c);
8188   CU_ASSERT(0 == nghttp2_stream_dep_insert_subtree(&session->root, c));
8189
8190   /*
8191    * c
8192    * |
8193    * d--a
8194    *    |
8195    *    b
8196    */
8197
8198   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 2 == c->sum_dep_weight);
8199   CU_ASSERT(0 == d->sum_dep_weight);
8200   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == a->sum_dep_weight);
8201   CU_ASSERT(0 == b->sum_dep_weight);
8202
8203   CU_ASSERT(nghttp2_pq_empty(&a->obq));
8204   CU_ASSERT(nghttp2_pq_empty(&b->obq));
8205   CU_ASSERT(nghttp2_pq_empty(&c->obq));
8206   CU_ASSERT(nghttp2_pq_empty(&d->obq));
8207
8208   check_stream_dep_sib(c, root, d, NULL, NULL);
8209   check_stream_dep_sib(d, c, NULL, NULL, a);
8210   check_stream_dep_sib(a, c, b, d, NULL);
8211   check_stream_dep_sib(b, a, NULL, NULL, NULL);
8212
8213   nghttp2_session_del(session);
8214
8215   nghttp2_session_server_new(&session, &callbacks, NULL);
8216
8217   root = &session->root;
8218
8219   a = open_stream(session, 1);
8220   b = open_stream_with_dep(session, 3, a);
8221
8222   c = open_stream(session, 5);
8223   d = open_stream_with_dep(session, 7, c);
8224
8225   /* a     c
8226    * |     |
8227    * b     d
8228    */
8229
8230   db = create_data_ob_item(mem);
8231
8232   nghttp2_stream_attach_item(b, db);
8233
8234   nghttp2_stream_dep_remove_subtree(c);
8235   CU_ASSERT(0 == nghttp2_stream_dep_insert_subtree(&session->root, c));
8236
8237   /*
8238    * c
8239    * |
8240    * d--a
8241    *    |
8242    *    b
8243    */
8244
8245   CU_ASSERT(c->queued);
8246   CU_ASSERT(a->queued);
8247   CU_ASSERT(b->queued);
8248   CU_ASSERT(!d->queued);
8249
8250   CU_ASSERT(1 == nghttp2_pq_size(&a->obq));
8251   CU_ASSERT(1 == nghttp2_pq_size(&c->obq));
8252   CU_ASSERT(nghttp2_pq_empty(&d->obq));
8253
8254   check_stream_dep_sib(c, root, d, NULL, NULL);
8255   check_stream_dep_sib(d, c, NULL, NULL, a);
8256   check_stream_dep_sib(a, c, b, d, NULL);
8257   check_stream_dep_sib(b, a, NULL, NULL, NULL);
8258
8259   nghttp2_session_del(session);
8260
8261   nghttp2_session_server_new(&session, &callbacks, NULL);
8262
8263   root = &session->root;
8264
8265   a = open_stream(session, 1);
8266   b = open_stream_with_dep(session, 3, a);
8267
8268   c = open_stream(session, 5);
8269   d = open_stream_with_dep(session, 7, c);
8270
8271   /* a     c
8272    * |     |
8273    * b     d
8274    */
8275
8276   db = create_data_ob_item(mem);
8277   dc = create_data_ob_item(mem);
8278
8279   nghttp2_stream_attach_item(b, db);
8280   nghttp2_stream_attach_item(c, dc);
8281
8282   nghttp2_stream_dep_remove_subtree(c);
8283   CU_ASSERT(0 == nghttp2_stream_dep_insert_subtree(&session->root, c));
8284
8285   /*
8286    * c
8287    * |
8288    * d--a
8289    *    |
8290    *    b
8291    */
8292
8293   CU_ASSERT(c->queued);
8294   CU_ASSERT(a->queued);
8295   CU_ASSERT(b->queued);
8296   CU_ASSERT(!d->queued);
8297
8298   check_stream_dep_sib(c, root, d, NULL, NULL);
8299   check_stream_dep_sib(d, c, NULL, NULL, a);
8300   check_stream_dep_sib(a, c, b, d, NULL);
8301   check_stream_dep_sib(b, a, NULL, NULL, NULL);
8302
8303   nghttp2_session_del(session);
8304 }
8305
8306 void test_nghttp2_session_stream_attach_item(void) {
8307   nghttp2_session *session;
8308   nghttp2_session_callbacks callbacks;
8309   nghttp2_stream *a, *b, *c, *d, *e;
8310   nghttp2_outbound_item *da, *db, *dc, *dd;
8311   nghttp2_mem *mem;
8312
8313   mem = nghttp2_mem_default();
8314
8315   memset(&callbacks, 0, sizeof(callbacks));
8316
8317   nghttp2_session_server_new(&session, &callbacks, NULL);
8318
8319   a = open_stream(session, 1);
8320   b = open_stream_with_dep(session, 3, a);
8321   c = open_stream_with_dep(session, 5, a);
8322   d = open_stream_with_dep(session, 7, c);
8323
8324   /* a
8325    * |
8326    * c--b
8327    * |
8328    * d
8329    */
8330
8331   db = create_data_ob_item(mem);
8332
8333   nghttp2_stream_attach_item(b, db);
8334
8335   CU_ASSERT(a->queued);
8336   CU_ASSERT(b->queued);
8337   CU_ASSERT(!c->queued);
8338   CU_ASSERT(!d->queued);
8339
8340   CU_ASSERT(1 == nghttp2_pq_size(&a->obq));
8341
8342   /* Attach item to c */
8343   dc = create_data_ob_item(mem);
8344
8345   nghttp2_stream_attach_item(c, dc);
8346
8347   CU_ASSERT(a->queued);
8348   CU_ASSERT(b->queued);
8349   CU_ASSERT(c->queued);
8350   CU_ASSERT(!d->queued);
8351
8352   CU_ASSERT(2 == nghttp2_pq_size(&a->obq));
8353
8354   /* Attach item to a */
8355   da = create_data_ob_item(mem);
8356
8357   nghttp2_stream_attach_item(a, da);
8358
8359   CU_ASSERT(a->queued);
8360   CU_ASSERT(b->queued);
8361   CU_ASSERT(c->queued);
8362   CU_ASSERT(!d->queued);
8363
8364   CU_ASSERT(2 == nghttp2_pq_size(&a->obq));
8365
8366   /* Detach item from a */
8367   nghttp2_stream_detach_item(a);
8368
8369   CU_ASSERT(a->queued);
8370   CU_ASSERT(b->queued);
8371   CU_ASSERT(c->queued);
8372   CU_ASSERT(!d->queued);
8373
8374   CU_ASSERT(2 == nghttp2_pq_size(&a->obq));
8375
8376   /* Attach item to d */
8377   dd = create_data_ob_item(mem);
8378
8379   nghttp2_stream_attach_item(d, dd);
8380
8381   CU_ASSERT(a->queued);
8382   CU_ASSERT(b->queued);
8383   CU_ASSERT(c->queued);
8384   CU_ASSERT(d->queued);
8385
8386   CU_ASSERT(2 == nghttp2_pq_size(&a->obq));
8387   CU_ASSERT(1 == nghttp2_pq_size(&c->obq));
8388
8389   /* Detach item from c */
8390   nghttp2_stream_detach_item(c);
8391
8392   CU_ASSERT(a->queued);
8393   CU_ASSERT(b->queued);
8394   CU_ASSERT(c->queued);
8395   CU_ASSERT(d->queued);
8396
8397   CU_ASSERT(2 == nghttp2_pq_size(&a->obq));
8398   CU_ASSERT(1 == nghttp2_pq_size(&c->obq));
8399
8400   /* Detach item from b */
8401   nghttp2_stream_detach_item(b);
8402
8403   CU_ASSERT(a->queued);
8404   CU_ASSERT(!b->queued);
8405   CU_ASSERT(c->queued);
8406   CU_ASSERT(d->queued);
8407
8408   CU_ASSERT(1 == nghttp2_pq_size(&a->obq));
8409
8410   /* exercises insertion */
8411   e = open_stream_with_dep_excl(session, 9, a);
8412
8413   /* a
8414    * |
8415    * e
8416    * |
8417    * c--b
8418    * |
8419    * d
8420    */
8421
8422   CU_ASSERT(a->queued);
8423   CU_ASSERT(e->queued);
8424   CU_ASSERT(!b->queued);
8425   CU_ASSERT(c->queued);
8426   CU_ASSERT(d->queued);
8427
8428   CU_ASSERT(1 == nghttp2_pq_size(&a->obq));
8429   CU_ASSERT(1 == nghttp2_pq_size(&e->obq));
8430   CU_ASSERT(nghttp2_pq_empty(&b->obq));
8431   CU_ASSERT(1 == nghttp2_pq_size(&c->obq));
8432   CU_ASSERT(nghttp2_pq_empty(&d->obq));
8433
8434   /* exercises deletion */
8435   nghttp2_stream_dep_remove(e);
8436
8437   /* a
8438    * |
8439    * c--b
8440    * |
8441    * d
8442    */
8443
8444   CU_ASSERT(a->queued);
8445   CU_ASSERT(!b->queued);
8446   CU_ASSERT(c->queued);
8447   CU_ASSERT(d->queued);
8448
8449   CU_ASSERT(1 == nghttp2_pq_size(&a->obq));
8450   CU_ASSERT(nghttp2_pq_empty(&b->obq));
8451   CU_ASSERT(1 == nghttp2_pq_size(&c->obq));
8452   CU_ASSERT(nghttp2_pq_empty(&d->obq));
8453
8454   /* e's weight 16 is distributed equally among c and b, both now have
8455      weight 8 each. */
8456   CU_ASSERT(8 == b->weight);
8457   CU_ASSERT(8 == c->weight);
8458
8459   /* da, db, dc have been detached */
8460   nghttp2_outbound_item_free(da, mem);
8461   nghttp2_outbound_item_free(db, mem);
8462   nghttp2_outbound_item_free(dc, mem);
8463   free(da);
8464   free(db);
8465   free(dc);
8466
8467   nghttp2_session_del(session);
8468
8469   nghttp2_session_server_new(&session, &callbacks, NULL);
8470
8471   a = open_stream(session, 1);
8472   b = open_stream_with_dep(session, 3, a);
8473   c = open_stream_with_dep(session, 5, a);
8474   d = open_stream_with_dep(session, 7, c);
8475
8476   /* a
8477    * |
8478    * c--b
8479    * |
8480    * d
8481    */
8482
8483   da = create_data_ob_item(mem);
8484   db = create_data_ob_item(mem);
8485   dc = create_data_ob_item(mem);
8486
8487   nghttp2_stream_attach_item(a, da);
8488   nghttp2_stream_attach_item(b, db);
8489   nghttp2_stream_attach_item(c, dc);
8490
8491   CU_ASSERT(a->queued);
8492   CU_ASSERT(b->queued);
8493   CU_ASSERT(c->queued);
8494   CU_ASSERT(!d->queued);
8495
8496   CU_ASSERT(2 == nghttp2_pq_size(&a->obq));
8497   CU_ASSERT(nghttp2_pq_empty(&b->obq));
8498   CU_ASSERT(nghttp2_pq_empty(&c->obq));
8499   CU_ASSERT(nghttp2_pq_empty(&d->obq));
8500
8501   /* Detach item from a */
8502   nghttp2_stream_detach_item(a);
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(2 == nghttp2_pq_size(&a->obq));
8510   CU_ASSERT(nghttp2_pq_empty(&b->obq));
8511   CU_ASSERT(nghttp2_pq_empty(&c->obq));
8512   CU_ASSERT(nghttp2_pq_empty(&d->obq));
8513
8514   /* da has been detached */
8515   nghttp2_outbound_item_free(da, mem);
8516   free(da);
8517
8518   nghttp2_session_del(session);
8519 }
8520
8521 void test_nghttp2_session_stream_attach_item_subtree(void) {
8522   nghttp2_session *session;
8523   nghttp2_session_callbacks callbacks;
8524   nghttp2_stream *a, *b, *c, *d, *e, *f;
8525   nghttp2_outbound_item *da, *db, *dd, *de;
8526   nghttp2_mem *mem;
8527
8528   mem = nghttp2_mem_default();
8529
8530   memset(&callbacks, 0, sizeof(callbacks));
8531
8532   nghttp2_session_server_new(&session, &callbacks, NULL);
8533
8534   a = open_stream(session, 1);
8535   b = open_stream_with_dep(session, 3, a);
8536   c = open_stream_with_dep(session, 5, a);
8537   d = open_stream_with_dep(session, 7, c);
8538
8539   e = open_stream_with_dep_weight(session, 9, 32, &session->root);
8540   f = open_stream_with_dep(session, 11, e);
8541
8542   /*
8543    * a        e
8544    * |        |
8545    * c--b     f
8546    * |
8547    * d
8548    */
8549
8550   de = create_data_ob_item(mem);
8551
8552   nghttp2_stream_attach_item(e, de);
8553
8554   db = create_data_ob_item(mem);
8555
8556   nghttp2_stream_attach_item(b, db);
8557
8558   CU_ASSERT(a->queued);
8559   CU_ASSERT(b->queued);
8560   CU_ASSERT(!c->queued);
8561   CU_ASSERT(!d->queued);
8562   CU_ASSERT(e->queued);
8563   CU_ASSERT(!f->queued);
8564
8565   CU_ASSERT(1 == nghttp2_pq_size(&a->obq));
8566   CU_ASSERT(nghttp2_pq_empty(&b->obq));
8567   CU_ASSERT(nghttp2_pq_empty(&c->obq));
8568   CU_ASSERT(nghttp2_pq_empty(&d->obq));
8569   CU_ASSERT(nghttp2_pq_empty(&e->obq));
8570   CU_ASSERT(nghttp2_pq_empty(&f->obq));
8571
8572   /* Insert subtree e under a */
8573
8574   nghttp2_stream_dep_remove_subtree(e);
8575   nghttp2_stream_dep_insert_subtree(a, e);
8576
8577   /*
8578    * a
8579    * |
8580    * e
8581    * |
8582    * f--c--b
8583    *    |
8584    *    d
8585    */
8586
8587   CU_ASSERT(a->queued);
8588   CU_ASSERT(b->queued);
8589   CU_ASSERT(!c->queued);
8590   CU_ASSERT(!d->queued);
8591   CU_ASSERT(e->queued);
8592   CU_ASSERT(!f->queued);
8593
8594   CU_ASSERT(1 == nghttp2_pq_size(&a->obq));
8595   CU_ASSERT(nghttp2_pq_empty(&b->obq));
8596   CU_ASSERT(nghttp2_pq_empty(&c->obq));
8597   CU_ASSERT(nghttp2_pq_empty(&d->obq));
8598   CU_ASSERT(1 == nghttp2_pq_size(&e->obq));
8599   CU_ASSERT(nghttp2_pq_empty(&f->obq));
8600
8601   /* Remove subtree b */
8602
8603   nghttp2_stream_dep_remove_subtree(b);
8604
8605   CU_ASSERT(0 == nghttp2_stream_dep_add_subtree(&session->root, b));
8606
8607   /*
8608    * a       b
8609    * |
8610    * e
8611    * |
8612    * f--c
8613    *    |
8614    *    d
8615    */
8616
8617   CU_ASSERT(a->queued);
8618   CU_ASSERT(b->queued);
8619   CU_ASSERT(!c->queued);
8620   CU_ASSERT(!d->queued);
8621   CU_ASSERT(e->queued);
8622   CU_ASSERT(!f->queued);
8623
8624   CU_ASSERT(1 == nghttp2_pq_size(&a->obq));
8625   CU_ASSERT(nghttp2_pq_empty(&b->obq));
8626   CU_ASSERT(nghttp2_pq_empty(&c->obq));
8627   CU_ASSERT(nghttp2_pq_empty(&d->obq));
8628   CU_ASSERT(nghttp2_pq_empty(&e->obq));
8629   CU_ASSERT(nghttp2_pq_empty(&f->obq));
8630
8631   /* Remove subtree a, and add it to root again */
8632
8633   nghttp2_stream_dep_remove_subtree(a);
8634
8635   CU_ASSERT(0 == nghttp2_stream_dep_add_subtree(&session->root, a));
8636
8637   CU_ASSERT(a->queued);
8638   CU_ASSERT(b->queued);
8639   CU_ASSERT(!c->queued);
8640   CU_ASSERT(!d->queued);
8641   CU_ASSERT(e->queued);
8642   CU_ASSERT(!f->queued);
8643
8644   CU_ASSERT(1 == nghttp2_pq_size(&a->obq));
8645   CU_ASSERT(nghttp2_pq_empty(&b->obq));
8646   CU_ASSERT(nghttp2_pq_empty(&c->obq));
8647   CU_ASSERT(nghttp2_pq_empty(&d->obq));
8648   CU_ASSERT(nghttp2_pq_empty(&e->obq));
8649   CU_ASSERT(nghttp2_pq_empty(&f->obq));
8650
8651   /* Remove subtree c */
8652
8653   nghttp2_stream_dep_remove_subtree(c);
8654
8655   CU_ASSERT(0 == nghttp2_stream_dep_add_subtree(&session->root, c));
8656
8657   /*
8658    * a       b     c
8659    * |             |
8660    * e             d
8661    * |
8662    * f
8663    */
8664
8665   CU_ASSERT(a->queued);
8666   CU_ASSERT(b->queued);
8667   CU_ASSERT(!c->queued);
8668   CU_ASSERT(!d->queued);
8669   CU_ASSERT(e->queued);
8670   CU_ASSERT(!f->queued);
8671
8672   CU_ASSERT(1 == nghttp2_pq_size(&a->obq));
8673   CU_ASSERT(nghttp2_pq_empty(&b->obq));
8674   CU_ASSERT(nghttp2_pq_empty(&c->obq));
8675   CU_ASSERT(nghttp2_pq_empty(&d->obq));
8676   CU_ASSERT(nghttp2_pq_empty(&e->obq));
8677   CU_ASSERT(nghttp2_pq_empty(&f->obq));
8678
8679   dd = create_data_ob_item(mem);
8680
8681   nghttp2_stream_attach_item(d, dd);
8682
8683   /* Add subtree c to a */
8684
8685   nghttp2_stream_dep_remove_subtree(c);
8686   nghttp2_stream_dep_add_subtree(a, c);
8687
8688   /*
8689    * a       b
8690    * |
8691    * c--e
8692    * |  |
8693    * d  f
8694    */
8695
8696   CU_ASSERT(a->queued);
8697   CU_ASSERT(b->queued);
8698   CU_ASSERT(c->queued);
8699   CU_ASSERT(d->queued);
8700   CU_ASSERT(e->queued);
8701   CU_ASSERT(!f->queued);
8702
8703   CU_ASSERT(2 == nghttp2_pq_size(&a->obq));
8704   CU_ASSERT(nghttp2_pq_empty(&b->obq));
8705   CU_ASSERT(1 == nghttp2_pq_size(&c->obq));
8706   CU_ASSERT(nghttp2_pq_empty(&d->obq));
8707   CU_ASSERT(nghttp2_pq_empty(&e->obq));
8708   CU_ASSERT(nghttp2_pq_empty(&f->obq));
8709
8710   /* Insert b under a */
8711
8712   nghttp2_stream_dep_remove_subtree(b);
8713   nghttp2_stream_dep_insert_subtree(a, b);
8714
8715   /*
8716    * a
8717    * |
8718    * b
8719    * |
8720    * c--e
8721    * |  |
8722    * d  f
8723    */
8724
8725   CU_ASSERT(a->queued);
8726   CU_ASSERT(b->queued);
8727   CU_ASSERT(c->queued);
8728   CU_ASSERT(d->queued);
8729   CU_ASSERT(e->queued);
8730   CU_ASSERT(!f->queued);
8731
8732   CU_ASSERT(1 == nghttp2_pq_size(&a->obq));
8733   CU_ASSERT(2 == nghttp2_pq_size(&b->obq));
8734   CU_ASSERT(1 == nghttp2_pq_size(&c->obq));
8735   CU_ASSERT(nghttp2_pq_empty(&d->obq));
8736   CU_ASSERT(nghttp2_pq_empty(&e->obq));
8737   CU_ASSERT(nghttp2_pq_empty(&f->obq));
8738
8739   /* Remove subtree b */
8740
8741   nghttp2_stream_dep_remove_subtree(b);
8742   CU_ASSERT(0 == nghttp2_stream_dep_add_subtree(&session->root, b));
8743
8744   /*
8745    * b       a
8746    * |
8747    * e--c
8748    * |  |
8749    * f  d
8750    */
8751
8752   CU_ASSERT(!a->queued);
8753   CU_ASSERT(b->queued);
8754   CU_ASSERT(c->queued);
8755   CU_ASSERT(d->queued);
8756   CU_ASSERT(e->queued);
8757   CU_ASSERT(!f->queued);
8758
8759   CU_ASSERT(nghttp2_pq_empty(&a->obq));
8760   CU_ASSERT(2 == nghttp2_pq_size(&b->obq));
8761   CU_ASSERT(1 == nghttp2_pq_size(&c->obq));
8762   CU_ASSERT(nghttp2_pq_empty(&d->obq));
8763   CU_ASSERT(nghttp2_pq_empty(&e->obq));
8764   CU_ASSERT(nghttp2_pq_empty(&f->obq));
8765
8766   /* Remove subtree c, and detach item from b, and then re-add
8767      subtree c under b */
8768
8769   nghttp2_stream_dep_remove_subtree(c);
8770   nghttp2_stream_detach_item(b);
8771   nghttp2_stream_dep_add_subtree(b, c);
8772
8773   /*
8774    * b       a
8775    * |
8776    * e--c
8777    * |  |
8778    * f  d
8779    */
8780
8781   CU_ASSERT(!a->queued);
8782   CU_ASSERT(b->queued);
8783   CU_ASSERT(c->queued);
8784   CU_ASSERT(d->queued);
8785   CU_ASSERT(e->queued);
8786   CU_ASSERT(!f->queued);
8787
8788   CU_ASSERT(nghttp2_pq_empty(&a->obq));
8789   CU_ASSERT(2 == nghttp2_pq_size(&b->obq));
8790   CU_ASSERT(1 == nghttp2_pq_size(&c->obq));
8791   CU_ASSERT(nghttp2_pq_empty(&d->obq));
8792   CU_ASSERT(nghttp2_pq_empty(&e->obq));
8793   CU_ASSERT(nghttp2_pq_empty(&f->obq));
8794
8795   /* Attach data to a, and add subtree a under b */
8796
8797   da = create_data_ob_item(mem);
8798   nghttp2_stream_attach_item(a, da);
8799   nghttp2_stream_dep_remove_subtree(a);
8800   nghttp2_stream_dep_add_subtree(b, a);
8801
8802   /*
8803    * b
8804    * |
8805    * a--e--c
8806    *    |  |
8807    *    f  d
8808    */
8809
8810   CU_ASSERT(a->queued);
8811   CU_ASSERT(b->queued);
8812   CU_ASSERT(c->queued);
8813   CU_ASSERT(d->queued);
8814   CU_ASSERT(e->queued);
8815   CU_ASSERT(!f->queued);
8816
8817   CU_ASSERT(nghttp2_pq_empty(&a->obq));
8818   CU_ASSERT(3 == nghttp2_pq_size(&b->obq));
8819   CU_ASSERT(1 == nghttp2_pq_size(&c->obq));
8820   CU_ASSERT(nghttp2_pq_empty(&d->obq));
8821   CU_ASSERT(nghttp2_pq_empty(&e->obq));
8822   CU_ASSERT(nghttp2_pq_empty(&f->obq));
8823
8824   /* Remove subtree c, and add under f */
8825   nghttp2_stream_dep_remove_subtree(c);
8826   nghttp2_stream_dep_insert_subtree(f, c);
8827
8828   /*
8829    * b
8830    * |
8831    * a--e
8832    *    |
8833    *    f
8834    *    |
8835    *    c
8836    *    |
8837    *    d
8838    */
8839
8840   CU_ASSERT(a->queued);
8841   CU_ASSERT(b->queued);
8842   CU_ASSERT(c->queued);
8843   CU_ASSERT(d->queued);
8844   CU_ASSERT(e->queued);
8845   CU_ASSERT(f->queued);
8846
8847   CU_ASSERT(nghttp2_pq_empty(&a->obq));
8848   CU_ASSERT(2 == nghttp2_pq_size(&b->obq));
8849   CU_ASSERT(1 == nghttp2_pq_size(&c->obq));
8850   CU_ASSERT(nghttp2_pq_empty(&d->obq));
8851   CU_ASSERT(1 == nghttp2_pq_size(&e->obq));
8852   CU_ASSERT(1 == nghttp2_pq_size(&f->obq));
8853
8854   /* db has been detached */
8855   nghttp2_outbound_item_free(db, mem);
8856   free(db);
8857
8858   nghttp2_session_del(session);
8859 }
8860
8861 void test_nghttp2_session_stream_get_state(void) {
8862   nghttp2_session *session;
8863   nghttp2_session_callbacks callbacks;
8864   nghttp2_mem *mem;
8865   nghttp2_hd_deflater deflater;
8866   nghttp2_bufs bufs;
8867   nghttp2_buf *buf;
8868   nghttp2_stream *stream;
8869   ssize_t rv;
8870   nghttp2_data_provider data_prd;
8871   nghttp2_frame frame;
8872
8873   mem = nghttp2_mem_default();
8874   frame_pack_bufs_init(&bufs);
8875   memset(&data_prd, 0, sizeof(data_prd));
8876
8877   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
8878   callbacks.send_callback = null_send_callback;
8879
8880   nghttp2_session_server_new(&session, &callbacks, NULL);
8881   nghttp2_hd_deflate_init(&deflater, mem);
8882
8883   CU_ASSERT(NGHTTP2_STREAM_STATE_IDLE ==
8884             nghttp2_stream_get_state(nghttp2_session_get_root_stream(session)));
8885
8886   /* stream 1 HEADERS; without END_STREAM flag set */
8887   pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, reqnv,
8888                ARRLEN(reqnv), mem);
8889
8890   buf = &bufs.head->buf;
8891   rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
8892
8893   CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv);
8894
8895   stream = nghttp2_session_find_stream(session, 1);
8896
8897   CU_ASSERT(NULL != stream);
8898   CU_ASSERT(1 == stream->stream_id);
8899   CU_ASSERT(NGHTTP2_STREAM_STATE_OPEN == nghttp2_stream_get_state(stream));
8900
8901   nghttp2_bufs_reset(&bufs);
8902
8903   /* stream 3 HEADERS; with END_STREAM flag set */
8904   pack_headers(&bufs, &deflater, 3,
8905                NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM, reqnv,
8906                ARRLEN(reqnv), mem);
8907
8908   buf = &bufs.head->buf;
8909   rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
8910
8911   CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv);
8912
8913   stream = nghttp2_session_find_stream(session, 3);
8914
8915   CU_ASSERT(NULL != stream);
8916   CU_ASSERT(3 == stream->stream_id);
8917   CU_ASSERT(NGHTTP2_STREAM_STATE_HALF_CLOSED_REMOTE ==
8918             nghttp2_stream_get_state(stream));
8919
8920   nghttp2_bufs_reset(&bufs);
8921
8922   /* Respond to stream 1 */
8923   nghttp2_submit_response(session, 1, resnv, ARRLEN(resnv), NULL);
8924
8925   rv = nghttp2_session_send(session);
8926
8927   CU_ASSERT(0 == rv);
8928
8929   stream = nghttp2_session_find_stream(session, 1);
8930
8931   CU_ASSERT(NGHTTP2_STREAM_STATE_HALF_CLOSED_LOCAL ==
8932             nghttp2_stream_get_state(stream));
8933
8934   /* Respond to stream 3 */
8935   nghttp2_submit_response(session, 3, resnv, ARRLEN(resnv), NULL);
8936
8937   rv = nghttp2_session_send(session);
8938
8939   CU_ASSERT(0 == rv);
8940
8941   stream = nghttp2_session_find_stream(session, 3);
8942
8943   CU_ASSERT(NGHTTP2_STREAM_STATE_CLOSED == nghttp2_stream_get_state(stream));
8944
8945   /* stream 5 HEADERS; with END_STREAM flag set */
8946   pack_headers(&bufs, &deflater, 5,
8947                NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM, reqnv,
8948                ARRLEN(reqnv), mem);
8949
8950   buf = &bufs.head->buf;
8951   rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
8952
8953   CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv);
8954
8955   nghttp2_bufs_reset(&bufs);
8956
8957   /* Push stream 2 associated to stream 5 */
8958   rv = nghttp2_submit_push_promise(session, NGHTTP2_FLAG_NONE, 5, reqnv,
8959                                    ARRLEN(reqnv), NULL);
8960
8961   CU_ASSERT(2 == rv);
8962
8963   rv = nghttp2_session_send(session);
8964
8965   CU_ASSERT(0 == rv);
8966
8967   stream = nghttp2_session_find_stream(session, 2);
8968
8969   CU_ASSERT(NGHTTP2_STREAM_STATE_RESERVED_LOCAL ==
8970             nghttp2_stream_get_state(stream));
8971
8972   /* Send resposne to push stream 2 with END_STREAM set */
8973   nghttp2_submit_response(session, 2, resnv, ARRLEN(resnv), NULL);
8974
8975   rv = nghttp2_session_send(session);
8976
8977   CU_ASSERT(0 == rv);
8978
8979   stream = nghttp2_session_find_stream(session, 2);
8980
8981   /* At server, pushed stream object is not retained after closed */
8982   CU_ASSERT(NULL == stream);
8983
8984   /* Push stream 4 associated to stream 5 */
8985   rv = nghttp2_submit_push_promise(session, NGHTTP2_FLAG_NONE, 5, reqnv,
8986                                    ARRLEN(reqnv), NULL);
8987
8988   CU_ASSERT(4 == rv);
8989
8990   rv = nghttp2_session_send(session);
8991
8992   CU_ASSERT(0 == rv);
8993
8994   stream = nghttp2_session_find_stream(session, 4);
8995
8996   CU_ASSERT(NGHTTP2_STREAM_STATE_RESERVED_LOCAL ==
8997             nghttp2_stream_get_state(stream));
8998
8999   /* Send response to push stream 4 without closing */
9000   data_prd.read_callback = defer_data_source_read_callback;
9001
9002   nghttp2_submit_response(session, 4, resnv, ARRLEN(resnv), &data_prd);
9003
9004   rv = nghttp2_session_send(session);
9005
9006   CU_ASSERT(0 == rv);
9007
9008   stream = nghttp2_session_find_stream(session, 4);
9009
9010   CU_ASSERT(NGHTTP2_STREAM_STATE_HALF_CLOSED_REMOTE ==
9011             nghttp2_stream_get_state(stream));
9012
9013   /* Create idle stream by PRIORITY frame */
9014   nghttp2_frame_priority_init(&frame.priority, 7, &pri_spec_default);
9015
9016   rv = nghttp2_frame_pack_priority(&bufs, &frame.priority);
9017
9018   CU_ASSERT(0 == rv);
9019
9020   nghttp2_frame_priority_free(&frame.priority);
9021
9022   buf = &bufs.head->buf;
9023   rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
9024
9025   CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv);
9026
9027   stream = nghttp2_session_find_stream(session, 7);
9028
9029   CU_ASSERT(NGHTTP2_STREAM_STATE_IDLE == nghttp2_stream_get_state(stream));
9030
9031   nghttp2_bufs_reset(&bufs);
9032
9033   nghttp2_hd_deflate_free(&deflater);
9034   nghttp2_session_del(session);
9035
9036   /* Test for client side */
9037
9038   nghttp2_session_client_new(&session, &callbacks, NULL);
9039   nghttp2_hd_deflate_init(&deflater, mem);
9040
9041   nghttp2_submit_request(session, NULL, reqnv, ARRLEN(reqnv), NULL, NULL);
9042
9043   rv = nghttp2_session_send(session);
9044
9045   CU_ASSERT(0 == rv);
9046
9047   /* Receive PUSH_PROMISE 2 associated to stream 1 */
9048   pack_push_promise(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, 2, reqnv,
9049                     ARRLEN(reqnv), mem);
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   stream = nghttp2_session_find_stream(session, 2);
9057
9058   CU_ASSERT(NGHTTP2_STREAM_STATE_RESERVED_REMOTE ==
9059             nghttp2_stream_get_state(stream));
9060
9061   nghttp2_bufs_reset(&bufs);
9062
9063   /* Receive push response for stream 2 without END_STREAM set */
9064   pack_headers(&bufs, &deflater, 2, NGHTTP2_FLAG_END_HEADERS, resnv,
9065                ARRLEN(resnv), mem);
9066
9067   buf = &bufs.head->buf;
9068   rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
9069
9070   CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv);
9071
9072   stream = nghttp2_session_find_stream(session, 2);
9073
9074   CU_ASSERT(NGHTTP2_STREAM_STATE_HALF_CLOSED_LOCAL ==
9075             nghttp2_stream_get_state(stream));
9076
9077   nghttp2_bufs_reset(&bufs);
9078
9079   nghttp2_hd_deflate_free(&deflater);
9080   nghttp2_session_del(session);
9081
9082   nghttp2_bufs_free(&bufs);
9083 }
9084
9085 void test_nghttp2_session_stream_get_something(void) {
9086   nghttp2_session *session;
9087   nghttp2_session_callbacks callbacks;
9088   nghttp2_stream *a, *b, *c;
9089
9090   memset(&callbacks, 0, sizeof(callbacks));
9091
9092   nghttp2_session_server_new(&session, &callbacks, NULL);
9093
9094   a = open_stream(session, 1);
9095
9096   CU_ASSERT(nghttp2_session_get_root_stream(session) ==
9097             nghttp2_stream_get_parent(a));
9098   CU_ASSERT(NULL == nghttp2_stream_get_previous_sibling(a));
9099   CU_ASSERT(NULL == nghttp2_stream_get_next_sibling(a));
9100   CU_ASSERT(NULL == nghttp2_stream_get_first_child(a));
9101
9102   b = open_stream_with_dep(session, 3, a);
9103   c = open_stream_with_dep_weight(session, 5, 11, a);
9104
9105   CU_ASSERT(a == nghttp2_stream_get_parent(c));
9106   CU_ASSERT(a == nghttp2_stream_get_parent(b));
9107
9108   CU_ASSERT(c == nghttp2_stream_get_first_child(a));
9109
9110   CU_ASSERT(b == nghttp2_stream_get_next_sibling(c));
9111   CU_ASSERT(c == nghttp2_stream_get_previous_sibling(b));
9112
9113   CU_ASSERT(27 == nghttp2_stream_get_sum_dependency_weight(a));
9114
9115   CU_ASSERT(11 == nghttp2_stream_get_weight(c));
9116   CU_ASSERT(5 == nghttp2_stream_get_stream_id(c));
9117   CU_ASSERT(0 == nghttp2_stream_get_stream_id(&session->root));
9118
9119   nghttp2_session_del(session);
9120 }
9121
9122 void test_nghttp2_session_find_stream(void) {
9123   nghttp2_session *session;
9124   nghttp2_session_callbacks callbacks;
9125   nghttp2_stream *stream;
9126
9127   memset(&callbacks, 0, sizeof(callbacks));
9128
9129   nghttp2_session_server_new(&session, &callbacks, NULL);
9130
9131   open_recv_stream(session, 1);
9132
9133   stream = nghttp2_session_find_stream(session, 1);
9134
9135   CU_ASSERT(NULL != stream);
9136   CU_ASSERT(1 == stream->stream_id);
9137
9138   stream = nghttp2_session_find_stream(session, 0);
9139
9140   CU_ASSERT(&session->root == stream);
9141   CU_ASSERT(0 == stream->stream_id);
9142
9143   stream = nghttp2_session_find_stream(session, 2);
9144
9145   CU_ASSERT(NULL == stream);
9146
9147   nghttp2_session_del(session);
9148 }
9149
9150 void test_nghttp2_session_keep_closed_stream(void) {
9151   nghttp2_session *session;
9152   nghttp2_session_callbacks callbacks;
9153   const size_t max_concurrent_streams = 5;
9154   nghttp2_settings_entry iv = {NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS,
9155                                (uint32_t)max_concurrent_streams};
9156   size_t i;
9157
9158   memset(&callbacks, 0, sizeof(callbacks));
9159   callbacks.send_callback = null_send_callback;
9160
9161   nghttp2_session_server_new(&session, &callbacks, NULL);
9162
9163   nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, &iv, 1);
9164
9165   for (i = 0; i < max_concurrent_streams; ++i) {
9166     open_recv_stream(session, (int32_t)i * 2 + 1);
9167   }
9168
9169   CU_ASSERT(0 == session->num_closed_streams);
9170
9171   nghttp2_session_close_stream(session, 1, NGHTTP2_NO_ERROR);
9172
9173   CU_ASSERT(1 == session->num_closed_streams);
9174   CU_ASSERT(1 == session->closed_stream_tail->stream_id);
9175   CU_ASSERT(session->closed_stream_tail == session->closed_stream_head);
9176
9177   nghttp2_session_close_stream(session, 5, NGHTTP2_NO_ERROR);
9178
9179   CU_ASSERT(2 == session->num_closed_streams);
9180   CU_ASSERT(5 == session->closed_stream_tail->stream_id);
9181   CU_ASSERT(1 == session->closed_stream_head->stream_id);
9182   CU_ASSERT(session->closed_stream_head ==
9183             session->closed_stream_tail->closed_prev);
9184   CU_ASSERT(NULL == session->closed_stream_tail->closed_next);
9185   CU_ASSERT(session->closed_stream_tail ==
9186             session->closed_stream_head->closed_next);
9187   CU_ASSERT(NULL == session->closed_stream_head->closed_prev);
9188
9189   open_recv_stream(session, 11);
9190   nghttp2_session_adjust_closed_stream(session);
9191
9192   CU_ASSERT(1 == session->num_closed_streams);
9193   CU_ASSERT(5 == session->closed_stream_tail->stream_id);
9194   CU_ASSERT(session->closed_stream_tail == session->closed_stream_head);
9195   CU_ASSERT(NULL == session->closed_stream_head->closed_prev);
9196   CU_ASSERT(NULL == session->closed_stream_head->closed_next);
9197
9198   open_recv_stream(session, 13);
9199   nghttp2_session_adjust_closed_stream(session);
9200
9201   CU_ASSERT(0 == session->num_closed_streams);
9202   CU_ASSERT(NULL == session->closed_stream_tail);
9203   CU_ASSERT(NULL == session->closed_stream_head);
9204
9205   nghttp2_session_close_stream(session, 3, NGHTTP2_NO_ERROR);
9206
9207   CU_ASSERT(1 == session->num_closed_streams);
9208   CU_ASSERT(3 == session->closed_stream_head->stream_id);
9209
9210   /* server initiated stream is not counted to max concurrent limit */
9211   open_sent_stream(session, 2);
9212   nghttp2_session_adjust_closed_stream(session);
9213
9214   CU_ASSERT(1 == session->num_closed_streams);
9215   CU_ASSERT(3 == session->closed_stream_head->stream_id);
9216
9217   nghttp2_session_close_stream(session, 2, NGHTTP2_NO_ERROR);
9218
9219   CU_ASSERT(1 == session->num_closed_streams);
9220   CU_ASSERT(3 == session->closed_stream_head->stream_id);
9221
9222   nghttp2_session_del(session);
9223 }
9224
9225 void test_nghttp2_session_keep_idle_stream(void) {
9226   nghttp2_session *session;
9227   nghttp2_session_callbacks callbacks;
9228   const size_t max_concurrent_streams = 1;
9229   nghttp2_settings_entry iv = {NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS,
9230                                (uint32_t)max_concurrent_streams};
9231   int i;
9232   int32_t stream_id;
9233
9234   memset(&callbacks, 0, sizeof(callbacks));
9235   callbacks.send_callback = null_send_callback;
9236
9237   nghttp2_session_server_new(&session, &callbacks, NULL);
9238
9239   nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, &iv, 1);
9240
9241   /* We at least allow NGHTTP2_MIN_IDLE_STREAM idle streams even if
9242      max concurrent streams is very low. */
9243   for (i = 0; i < NGHTTP2_MIN_IDLE_STREAMS; ++i) {
9244     open_recv_stream2(session, i * 2 + 1, NGHTTP2_STREAM_IDLE);
9245     nghttp2_session_adjust_idle_stream(session);
9246   }
9247
9248   CU_ASSERT(NGHTTP2_MIN_IDLE_STREAMS == session->num_idle_streams);
9249
9250   stream_id = (NGHTTP2_MIN_IDLE_STREAMS - 1) * 2 + 1;
9251   CU_ASSERT(1 == session->idle_stream_head->stream_id);
9252   CU_ASSERT(stream_id == session->idle_stream_tail->stream_id);
9253
9254   stream_id += 2;
9255
9256   open_recv_stream2(session, stream_id, NGHTTP2_STREAM_IDLE);
9257   nghttp2_session_adjust_idle_stream(session);
9258
9259   CU_ASSERT(NGHTTP2_MIN_IDLE_STREAMS == session->num_idle_streams);
9260   CU_ASSERT(3 == session->idle_stream_head->stream_id);
9261   CU_ASSERT(stream_id == session->idle_stream_tail->stream_id);
9262
9263   nghttp2_session_del(session);
9264 }
9265
9266 void test_nghttp2_session_detach_idle_stream(void) {
9267   nghttp2_session *session;
9268   nghttp2_session_callbacks callbacks;
9269   int i;
9270   nghttp2_stream *stream;
9271
9272   memset(&callbacks, 0, sizeof(callbacks));
9273   callbacks.send_callback = null_send_callback;
9274
9275   nghttp2_session_server_new(&session, &callbacks, NULL);
9276
9277   for (i = 1; i <= 3; ++i) {
9278     nghttp2_session_open_stream(session, i, NGHTTP2_STREAM_FLAG_NONE,
9279                                 &pri_spec_default, NGHTTP2_STREAM_IDLE, NULL);
9280   }
9281
9282   CU_ASSERT(3 == session->num_idle_streams);
9283
9284   /* Detach middle stream */
9285   stream = nghttp2_session_get_stream_raw(session, 2);
9286
9287   CU_ASSERT(session->idle_stream_head == stream->closed_prev);
9288   CU_ASSERT(session->idle_stream_tail == stream->closed_next);
9289   CU_ASSERT(stream == session->idle_stream_head->closed_next);
9290   CU_ASSERT(stream == session->idle_stream_tail->closed_prev);
9291
9292   nghttp2_session_detach_idle_stream(session, stream);
9293
9294   CU_ASSERT(2 == session->num_idle_streams);
9295
9296   CU_ASSERT(NULL == stream->closed_prev);
9297   CU_ASSERT(NULL == stream->closed_next);
9298
9299   CU_ASSERT(session->idle_stream_head ==
9300             session->idle_stream_tail->closed_prev);
9301   CU_ASSERT(session->idle_stream_tail ==
9302             session->idle_stream_head->closed_next);
9303
9304   /* Detach head stream */
9305   stream = session->idle_stream_head;
9306
9307   nghttp2_session_detach_idle_stream(session, stream);
9308
9309   CU_ASSERT(1 == session->num_idle_streams);
9310
9311   CU_ASSERT(session->idle_stream_head == session->idle_stream_tail);
9312   CU_ASSERT(NULL == session->idle_stream_head->closed_prev);
9313   CU_ASSERT(NULL == session->idle_stream_head->closed_next);
9314
9315   /* Detach last stream */
9316
9317   stream = session->idle_stream_head;
9318
9319   nghttp2_session_detach_idle_stream(session, stream);
9320
9321   CU_ASSERT(0 == session->num_idle_streams);
9322
9323   CU_ASSERT(NULL == session->idle_stream_head);
9324   CU_ASSERT(NULL == session->idle_stream_tail);
9325
9326   for (i = 4; i <= 5; ++i) {
9327     nghttp2_session_open_stream(session, i, NGHTTP2_STREAM_FLAG_NONE,
9328                                 &pri_spec_default, NGHTTP2_STREAM_IDLE, NULL);
9329   }
9330
9331   CU_ASSERT(2 == session->num_idle_streams);
9332
9333   /* Detach tail stream */
9334
9335   stream = session->idle_stream_tail;
9336
9337   nghttp2_session_detach_idle_stream(session, stream);
9338
9339   CU_ASSERT(1 == session->num_idle_streams);
9340
9341   CU_ASSERT(session->idle_stream_head == session->idle_stream_tail);
9342   CU_ASSERT(NULL == session->idle_stream_head->closed_prev);
9343   CU_ASSERT(NULL == session->idle_stream_head->closed_next);
9344
9345   nghttp2_session_del(session);
9346 }
9347
9348 void test_nghttp2_session_large_dep_tree(void) {
9349   nghttp2_session *session;
9350   nghttp2_session_callbacks callbacks;
9351   size_t i;
9352   nghttp2_stream *dep_stream = NULL;
9353   nghttp2_stream *stream;
9354   int32_t stream_id;
9355
9356   memset(&callbacks, 0, sizeof(callbacks));
9357   callbacks.send_callback = null_send_callback;
9358
9359   nghttp2_session_server_new(&session, &callbacks, NULL);
9360
9361   stream_id = 1;
9362   for (i = 0; i < 250; ++i, stream_id += 2) {
9363     dep_stream = open_stream_with_dep(session, stream_id, dep_stream);
9364   }
9365
9366   stream_id = 1;
9367   for (i = 0; i < 250; ++i, stream_id += 2) {
9368     stream = nghttp2_session_get_stream(session, stream_id);
9369     CU_ASSERT(nghttp2_stream_dep_find_ancestor(stream, &session->root));
9370     CU_ASSERT(nghttp2_stream_in_dep_tree(stream));
9371   }
9372
9373   nghttp2_session_del(session);
9374 }
9375
9376 void test_nghttp2_session_graceful_shutdown(void) {
9377   nghttp2_session *session;
9378   nghttp2_session_callbacks callbacks;
9379   my_user_data ud;
9380
9381   memset(&callbacks, 0, sizeof(callbacks));
9382   callbacks.send_callback = null_send_callback;
9383   callbacks.on_frame_send_callback = on_frame_send_callback;
9384   callbacks.on_stream_close_callback = on_stream_close_callback;
9385
9386   nghttp2_session_server_new(&session, &callbacks, &ud);
9387
9388   open_recv_stream(session, 301);
9389   open_sent_stream(session, 302);
9390   open_recv_stream(session, 309);
9391   open_recv_stream(session, 311);
9392   open_recv_stream(session, 319);
9393
9394   CU_ASSERT(0 == nghttp2_submit_shutdown_notice(session));
9395
9396   ud.frame_send_cb_called = 0;
9397
9398   CU_ASSERT(0 == nghttp2_session_send(session));
9399
9400   CU_ASSERT(1 == ud.frame_send_cb_called);
9401   CU_ASSERT((1u << 31) - 1 == session->local_last_stream_id);
9402
9403   CU_ASSERT(0 == nghttp2_submit_goaway(session, NGHTTP2_FLAG_NONE, 311,
9404                                        NGHTTP2_NO_ERROR, NULL, 0));
9405
9406   ud.frame_send_cb_called = 0;
9407   ud.stream_close_cb_called = 0;
9408
9409   CU_ASSERT(0 == nghttp2_session_send(session));
9410
9411   CU_ASSERT(1 == ud.frame_send_cb_called);
9412   CU_ASSERT(311 == session->local_last_stream_id);
9413   CU_ASSERT(1 == ud.stream_close_cb_called);
9414
9415   CU_ASSERT(0 ==
9416             nghttp2_session_terminate_session2(session, 301, NGHTTP2_NO_ERROR));
9417
9418   ud.frame_send_cb_called = 0;
9419   ud.stream_close_cb_called = 0;
9420
9421   CU_ASSERT(0 == nghttp2_session_send(session));
9422
9423   CU_ASSERT(1 == ud.frame_send_cb_called);
9424   CU_ASSERT(301 == session->local_last_stream_id);
9425   CU_ASSERT(2 == ud.stream_close_cb_called);
9426
9427   CU_ASSERT(NULL != nghttp2_session_get_stream(session, 301));
9428   CU_ASSERT(NULL != nghttp2_session_get_stream(session, 302));
9429   CU_ASSERT(NULL == nghttp2_session_get_stream(session, 309));
9430   CU_ASSERT(NULL == nghttp2_session_get_stream(session, 311));
9431   CU_ASSERT(NULL == nghttp2_session_get_stream(session, 319));
9432
9433   nghttp2_session_del(session);
9434 }
9435
9436 void test_nghttp2_session_on_header_temporal_failure(void) {
9437   nghttp2_session *session;
9438   nghttp2_session_callbacks callbacks;
9439   my_user_data ud;
9440   nghttp2_bufs bufs;
9441   nghttp2_buf *buf;
9442   nghttp2_hd_deflater deflater;
9443   nghttp2_nv nv[] = {MAKE_NV("alpha", "bravo"), MAKE_NV("charlie", "delta")};
9444   nghttp2_nv *nva;
9445   size_t hdpos;
9446   ssize_t rv;
9447   nghttp2_frame frame;
9448   nghttp2_frame_hd hd;
9449   nghttp2_outbound_item *item;
9450   nghttp2_mem *mem;
9451
9452   mem = nghttp2_mem_default();
9453   memset(&callbacks, 0, sizeof(callbacks));
9454   callbacks.on_header_callback = temporal_failure_on_header_callback;
9455
9456   nghttp2_session_server_new(&session, &callbacks, &ud);
9457
9458   frame_pack_bufs_init(&bufs);
9459
9460   nghttp2_hd_deflate_init(&deflater, mem);
9461
9462   nghttp2_nv_array_copy(&nva, reqnv, ARRLEN(reqnv), mem);
9463
9464   nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_STREAM, 1,
9465                              NGHTTP2_HCAT_REQUEST, NULL, nva, ARRLEN(reqnv));
9466   nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
9467   nghttp2_frame_headers_free(&frame.headers, mem);
9468
9469   /* We are going to create CONTINUATION.  First serialize header
9470      block, and then frame header. */
9471   hdpos = nghttp2_bufs_len(&bufs);
9472
9473   buf = &bufs.head->buf;
9474   buf->last += NGHTTP2_FRAME_HDLEN;
9475
9476   nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, &nv[1], 1);
9477
9478   nghttp2_frame_hd_init(&hd,
9479                         nghttp2_bufs_len(&bufs) - hdpos - NGHTTP2_FRAME_HDLEN,
9480                         NGHTTP2_CONTINUATION, NGHTTP2_FLAG_END_HEADERS, 1);
9481
9482   nghttp2_frame_pack_frame_hd(&buf->pos[hdpos], &hd);
9483
9484   ud.header_cb_called = 0;
9485   rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_bufs_len(&bufs));
9486
9487   CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == rv);
9488   CU_ASSERT(1 == ud.header_cb_called);
9489
9490   item = nghttp2_session_get_next_ob_item(session);
9491
9492   CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
9493   CU_ASSERT(1 == item->frame.hd.stream_id);
9494
9495   /* Make sure no header decompression error occurred */
9496   CU_ASSERT(NGHTTP2_GOAWAY_NONE == session->goaway_flags);
9497
9498   nghttp2_hd_deflate_free(&deflater);
9499   nghttp2_session_del(session);
9500
9501   nghttp2_bufs_reset(&bufs);
9502
9503   /* Check for PUSH_PROMISE */
9504   nghttp2_hd_deflate_init(&deflater, mem);
9505   nghttp2_session_client_new(&session, &callbacks, &ud);
9506
9507   open_sent_stream(session, 1);
9508
9509   rv = pack_push_promise(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, 2,
9510                          reqnv, ARRLEN(reqnv), mem);
9511   CU_ASSERT(0 == rv);
9512
9513   ud.header_cb_called = 0;
9514   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
9515                                 nghttp2_bufs_len(&bufs));
9516   CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == rv);
9517   CU_ASSERT(1 == ud.header_cb_called);
9518
9519   item = nghttp2_session_get_next_ob_item(session);
9520   CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
9521   CU_ASSERT(2 == item->frame.hd.stream_id);
9522   CU_ASSERT(NGHTTP2_INTERNAL_ERROR == item->frame.rst_stream.error_code);
9523
9524   nghttp2_session_del(session);
9525   nghttp2_hd_deflate_free(&deflater);
9526   nghttp2_bufs_free(&bufs);
9527 }
9528
9529 void test_nghttp2_session_recv_client_magic(void) {
9530   nghttp2_session *session;
9531   nghttp2_session_callbacks callbacks;
9532   ssize_t rv;
9533   nghttp2_frame ping_frame;
9534   uint8_t buf[16];
9535
9536   /* enable global nghttp2_enable_strict_preface here */
9537   nghttp2_enable_strict_preface = 1;
9538
9539   memset(&callbacks, 0, sizeof(callbacks));
9540
9541   /* Check success case */
9542   nghttp2_session_server_new(&session, &callbacks, NULL);
9543
9544   rv = nghttp2_session_mem_recv(session, (const uint8_t *)NGHTTP2_CLIENT_MAGIC,
9545                                 NGHTTP2_CLIENT_MAGIC_LEN);
9546
9547   CU_ASSERT(rv == NGHTTP2_CLIENT_MAGIC_LEN);
9548   CU_ASSERT(NGHTTP2_IB_READ_FIRST_SETTINGS == session->iframe.state);
9549
9550   /* Receiving PING is error because we want SETTINGS. */
9551   nghttp2_frame_ping_init(&ping_frame.ping, NGHTTP2_FLAG_NONE, NULL);
9552
9553   nghttp2_frame_pack_frame_hd(buf, &ping_frame.ping.hd);
9554
9555   rv = nghttp2_session_mem_recv(session, buf, NGHTTP2_FRAME_HDLEN);
9556   CU_ASSERT(NGHTTP2_FRAME_HDLEN == rv);
9557   CU_ASSERT(NGHTTP2_IB_IGN_ALL == session->iframe.state);
9558   CU_ASSERT(0 == session->iframe.payloadleft);
9559
9560   nghttp2_frame_ping_free(&ping_frame.ping);
9561
9562   nghttp2_session_del(session);
9563
9564   /* Check bad case */
9565   nghttp2_session_server_new(&session, &callbacks, NULL);
9566
9567   /* Feed magic with one byte less */
9568   rv = nghttp2_session_mem_recv(session, (const uint8_t *)NGHTTP2_CLIENT_MAGIC,
9569                                 NGHTTP2_CLIENT_MAGIC_LEN - 1);
9570
9571   CU_ASSERT(rv == NGHTTP2_CLIENT_MAGIC_LEN - 1);
9572   CU_ASSERT(NGHTTP2_IB_READ_CLIENT_MAGIC == session->iframe.state);
9573   CU_ASSERT(1 == session->iframe.payloadleft);
9574
9575   rv = nghttp2_session_mem_recv(session, (const uint8_t *)"\0", 1);
9576
9577   CU_ASSERT(NGHTTP2_ERR_BAD_CLIENT_MAGIC == rv);
9578
9579   nghttp2_session_del(session);
9580
9581   /* disable global nghttp2_enable_strict_preface here */
9582   nghttp2_enable_strict_preface = 0;
9583 }
9584
9585 void test_nghttp2_session_delete_data_item(void) {
9586   nghttp2_session *session;
9587   nghttp2_session_callbacks callbacks;
9588   nghttp2_stream *a;
9589   nghttp2_data_provider prd;
9590
9591   memset(&callbacks, 0, sizeof(callbacks));
9592
9593   nghttp2_session_server_new(&session, &callbacks, NULL);
9594
9595   a = open_recv_stream(session, 1);
9596   open_recv_stream_with_dep(session, 3, a);
9597
9598   /* We don't care about these members, since we won't send data */
9599   prd.source.ptr = NULL;
9600   prd.read_callback = fail_data_source_read_callback;
9601
9602   CU_ASSERT(0 == nghttp2_submit_data(session, NGHTTP2_FLAG_NONE, 1, &prd));
9603   CU_ASSERT(0 == nghttp2_submit_data(session, NGHTTP2_FLAG_NONE, 3, &prd));
9604
9605   nghttp2_session_del(session);
9606 }
9607
9608 void test_nghttp2_session_open_idle_stream(void) {
9609   nghttp2_session *session;
9610   nghttp2_session_callbacks callbacks;
9611   nghttp2_stream *stream;
9612   nghttp2_stream *opened_stream;
9613   nghttp2_priority_spec pri_spec;
9614   nghttp2_frame frame;
9615
9616   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
9617
9618   nghttp2_session_server_new(&session, &callbacks, NULL);
9619
9620   nghttp2_priority_spec_init(&pri_spec, 0, 3, 0);
9621
9622   nghttp2_frame_priority_init(&frame.priority, 1, &pri_spec);
9623
9624   CU_ASSERT(0 == nghttp2_session_on_priority_received(session, &frame));
9625
9626   stream = nghttp2_session_get_stream_raw(session, 1);
9627
9628   CU_ASSERT(NGHTTP2_STREAM_IDLE == stream->state);
9629   CU_ASSERT(NULL == stream->closed_prev);
9630   CU_ASSERT(NULL == stream->closed_next);
9631   CU_ASSERT(1 == session->num_idle_streams);
9632   CU_ASSERT(session->idle_stream_head == stream);
9633   CU_ASSERT(session->idle_stream_tail == stream);
9634
9635   opened_stream = open_recv_stream2(session, 1, NGHTTP2_STREAM_OPENING);
9636
9637   CU_ASSERT(stream == opened_stream);
9638   CU_ASSERT(NGHTTP2_STREAM_OPENING == stream->state);
9639   CU_ASSERT(0 == session->num_idle_streams);
9640   CU_ASSERT(NULL == session->idle_stream_head);
9641   CU_ASSERT(NULL == session->idle_stream_tail);
9642
9643   nghttp2_frame_priority_free(&frame.priority);
9644
9645   nghttp2_session_del(session);
9646 }
9647
9648 void test_nghttp2_session_cancel_reserved_remote(void) {
9649   nghttp2_session *session;
9650   nghttp2_session_callbacks callbacks;
9651   nghttp2_stream *stream;
9652   nghttp2_frame frame;
9653   nghttp2_nv *nva;
9654   size_t nvlen;
9655   nghttp2_hd_deflater deflater;
9656   nghttp2_mem *mem;
9657   nghttp2_bufs bufs;
9658   ssize_t rv;
9659
9660   mem = nghttp2_mem_default();
9661   frame_pack_bufs_init(&bufs);
9662
9663   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
9664   callbacks.send_callback = null_send_callback;
9665
9666   nghttp2_session_client_new(&session, &callbacks, NULL);
9667
9668   nghttp2_hd_deflate_init(&deflater, mem);
9669
9670   stream = open_recv_stream2(session, 2, NGHTTP2_STREAM_RESERVED);
9671
9672   nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, 2, NGHTTP2_CANCEL);
9673
9674   CU_ASSERT(NGHTTP2_STREAM_CLOSING == stream->state);
9675
9676   CU_ASSERT(0 == nghttp2_session_send(session));
9677
9678   nvlen = ARRLEN(resnv);
9679   nghttp2_nv_array_copy(&nva, resnv, nvlen, mem);
9680
9681   nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 2,
9682                              NGHTTP2_HCAT_PUSH_RESPONSE, NULL, nva, nvlen);
9683   rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
9684
9685   CU_ASSERT(0 == rv);
9686
9687   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
9688                                 nghttp2_buf_len(&bufs.head->buf));
9689
9690   CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
9691
9692   /* stream is not dangling, so assign NULL */
9693   stream = NULL;
9694
9695   /* No RST_STREAM or GOAWAY is generated since stream should be in
9696      NGHTTP2_STREAM_CLOSING and push response should be ignored. */
9697   CU_ASSERT(0 == nghttp2_outbound_queue_size(&session->ob_reg));
9698
9699   /* Check that we can receive push response HEADERS while RST_STREAM
9700      is just queued. */
9701   open_recv_stream2(session, 4, NGHTTP2_STREAM_RESERVED);
9702
9703   nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, 2, NGHTTP2_CANCEL);
9704
9705   nghttp2_bufs_reset(&bufs);
9706
9707   frame.hd.stream_id = 4;
9708   rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
9709
9710   CU_ASSERT(0 == rv);
9711
9712   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
9713                                 nghttp2_buf_len(&bufs.head->buf));
9714
9715   CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
9716
9717   CU_ASSERT(1 == nghttp2_outbound_queue_size(&session->ob_reg));
9718
9719   nghttp2_frame_headers_free(&frame.headers, mem);
9720
9721   nghttp2_hd_deflate_free(&deflater);
9722
9723   nghttp2_session_del(session);
9724
9725   nghttp2_bufs_free(&bufs);
9726 }
9727
9728 void test_nghttp2_session_reset_pending_headers(void) {
9729   nghttp2_session *session;
9730   nghttp2_session_callbacks callbacks;
9731   nghttp2_stream *stream;
9732   int32_t stream_id;
9733   my_user_data ud;
9734
9735   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
9736   callbacks.send_callback = null_send_callback;
9737   callbacks.on_frame_send_callback = on_frame_send_callback;
9738   callbacks.on_frame_not_send_callback = on_frame_not_send_callback;
9739   callbacks.on_stream_close_callback = on_stream_close_callback;
9740
9741   nghttp2_session_client_new(&session, &callbacks, &ud);
9742
9743   stream_id = nghttp2_submit_request(session, NULL, NULL, 0, NULL, NULL);
9744   CU_ASSERT(stream_id >= 1);
9745
9746   nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, stream_id,
9747                             NGHTTP2_CANCEL);
9748
9749   session->remote_settings.max_concurrent_streams = 0;
9750
9751   /* RST_STREAM cancels pending HEADERS and is not actually sent. */
9752   ud.frame_send_cb_called = 0;
9753   CU_ASSERT(0 == nghttp2_session_send(session));
9754
9755   CU_ASSERT(0 == ud.frame_send_cb_called);
9756
9757   stream = nghttp2_session_get_stream(session, stream_id);
9758
9759   CU_ASSERT(NULL == stream);
9760
9761   /* See HEADERS is not sent.  on_stream_close is called just like
9762      transmission failure. */
9763   session->remote_settings.max_concurrent_streams = 1;
9764
9765   ud.frame_not_send_cb_called = 0;
9766   ud.stream_close_error_code = 0;
9767   CU_ASSERT(0 == nghttp2_session_send(session));
9768
9769   CU_ASSERT(1 == ud.frame_not_send_cb_called);
9770   CU_ASSERT(NGHTTP2_HEADERS == ud.not_sent_frame_type);
9771   CU_ASSERT(NGHTTP2_CANCEL == ud.stream_close_error_code);
9772
9773   stream = nghttp2_session_get_stream(session, stream_id);
9774
9775   CU_ASSERT(NULL == stream);
9776
9777   nghttp2_session_del(session);
9778 }
9779
9780 void test_nghttp2_session_send_data_callback(void) {
9781   nghttp2_session *session;
9782   nghttp2_session_callbacks callbacks;
9783   nghttp2_data_provider data_prd;
9784   my_user_data ud;
9785   accumulator acc;
9786   nghttp2_frame_hd hd;
9787
9788   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
9789   callbacks.send_callback = accumulator_send_callback;
9790   callbacks.send_data_callback = send_data_callback;
9791
9792   data_prd.read_callback = no_copy_data_source_read_callback;
9793
9794   acc.length = 0;
9795   ud.acc = &acc;
9796
9797   ud.data_source_length = NGHTTP2_DATA_PAYLOADLEN * 2;
9798
9799   nghttp2_session_client_new(&session, &callbacks, &ud);
9800
9801   open_sent_stream(session, 1);
9802
9803   nghttp2_submit_data(session, NGHTTP2_FLAG_END_STREAM, 1, &data_prd);
9804
9805   CU_ASSERT(0 == nghttp2_session_send(session));
9806
9807   CU_ASSERT((NGHTTP2_FRAME_HDLEN + NGHTTP2_DATA_PAYLOADLEN) * 2 == acc.length);
9808
9809   nghttp2_frame_unpack_frame_hd(&hd, acc.buf);
9810
9811   CU_ASSERT(16384 == hd.length);
9812   CU_ASSERT(NGHTTP2_DATA == hd.type);
9813   CU_ASSERT(NGHTTP2_FLAG_NONE == hd.flags);
9814
9815   nghttp2_frame_unpack_frame_hd(&hd, acc.buf + NGHTTP2_FRAME_HDLEN + hd.length);
9816
9817   CU_ASSERT(16384 == hd.length);
9818   CU_ASSERT(NGHTTP2_DATA == hd.type);
9819   CU_ASSERT(NGHTTP2_FLAG_END_STREAM == hd.flags);
9820
9821   nghttp2_session_del(session);
9822 }
9823
9824 void test_nghttp2_session_on_begin_headers_temporal_failure(void) {
9825   nghttp2_session *session;
9826   nghttp2_session_callbacks callbacks;
9827   my_user_data ud;
9828   nghttp2_bufs bufs;
9829   nghttp2_mem *mem;
9830   ssize_t rv;
9831   nghttp2_hd_deflater deflater;
9832   nghttp2_outbound_item *item;
9833
9834   mem = nghttp2_mem_default();
9835   frame_pack_bufs_init(&bufs);
9836   nghttp2_hd_deflate_init(&deflater, mem);
9837
9838   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
9839   callbacks.on_begin_headers_callback =
9840       temporal_failure_on_begin_headers_callback;
9841   callbacks.on_header_callback = on_header_callback;
9842   callbacks.on_frame_recv_callback = on_frame_recv_callback;
9843   callbacks.send_callback = null_send_callback;
9844   nghttp2_session_server_new(&session, &callbacks, &ud);
9845
9846   rv = pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, reqnv,
9847                     ARRLEN(reqnv), mem);
9848   CU_ASSERT(0 == rv);
9849
9850   ud.header_cb_called = 0;
9851   ud.frame_recv_cb_called = 0;
9852   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
9853                                 nghttp2_bufs_len(&bufs));
9854   CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == rv);
9855   CU_ASSERT(0 == ud.header_cb_called);
9856   CU_ASSERT(0 == ud.frame_recv_cb_called);
9857
9858   item = nghttp2_session_get_next_ob_item(session);
9859   CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
9860   CU_ASSERT(1 == item->frame.hd.stream_id);
9861   CU_ASSERT(NGHTTP2_INTERNAL_ERROR == item->frame.rst_stream.error_code);
9862
9863   nghttp2_session_del(session);
9864   nghttp2_hd_deflate_free(&deflater);
9865
9866   nghttp2_bufs_reset(&bufs);
9867   /* check for PUSH_PROMISE */
9868   nghttp2_hd_deflate_init(&deflater, mem);
9869   nghttp2_session_client_new(&session, &callbacks, &ud);
9870
9871   open_sent_stream(session, 1);
9872
9873   rv = pack_push_promise(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, 2,
9874                          reqnv, ARRLEN(reqnv), mem);
9875   CU_ASSERT(0 == rv);
9876
9877   ud.header_cb_called = 0;
9878   ud.frame_recv_cb_called = 0;
9879   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
9880                                 nghttp2_bufs_len(&bufs));
9881   CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == rv);
9882   CU_ASSERT(0 == ud.header_cb_called);
9883   CU_ASSERT(0 == ud.frame_recv_cb_called);
9884
9885   item = nghttp2_session_get_next_ob_item(session);
9886   CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
9887   CU_ASSERT(2 == item->frame.hd.stream_id);
9888   CU_ASSERT(NGHTTP2_INTERNAL_ERROR == item->frame.rst_stream.error_code);
9889
9890   nghttp2_session_del(session);
9891   nghttp2_hd_deflate_free(&deflater);
9892   nghttp2_bufs_free(&bufs);
9893 }
9894
9895 void test_nghttp2_session_defer_then_close(void) {
9896   nghttp2_session *session;
9897   nghttp2_session_callbacks callbacks;
9898   nghttp2_data_provider prd;
9899   int rv;
9900   const uint8_t *datap;
9901   ssize_t datalen;
9902   nghttp2_frame frame;
9903
9904   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
9905   callbacks.send_callback = null_send_callback;
9906
9907   nghttp2_session_client_new(&session, &callbacks, NULL);
9908
9909   prd.read_callback = defer_data_source_read_callback;
9910
9911   rv = nghttp2_submit_request(session, NULL, reqnv, ARRLEN(reqnv), &prd, NULL);
9912   CU_ASSERT(rv > 0);
9913
9914   /* This sends HEADERS */
9915   datalen = nghttp2_session_mem_send(session, &datap);
9916
9917   CU_ASSERT(datalen > 0);
9918
9919   /* This makes DATA item deferred */
9920   datalen = nghttp2_session_mem_send(session, &datap);
9921
9922   CU_ASSERT(datalen == 0);
9923
9924   nghttp2_frame_rst_stream_init(&frame.rst_stream, 1, NGHTTP2_CANCEL);
9925
9926   /* Assertion failure; GH-264 */
9927   rv = nghttp2_session_on_rst_stream_received(session, &frame);
9928
9929   CU_ASSERT(rv == 0);
9930
9931   nghttp2_session_del(session);
9932 }
9933
9934 static int submit_response_on_stream_close(nghttp2_session *session,
9935                                            int32_t stream_id,
9936                                            uint32_t error_code,
9937                                            void *user_data) {
9938   nghttp2_data_provider data_prd;
9939   (void)error_code;
9940   (void)user_data;
9941
9942   data_prd.read_callback = temporal_failure_data_source_read_callback;
9943
9944   // Attempt to submit response or data to the stream being closed
9945   switch (stream_id) {
9946   case 1:
9947     CU_ASSERT(0 == nghttp2_submit_response(session, stream_id, resnv,
9948                                            ARRLEN(resnv), &data_prd));
9949     break;
9950   case 3:
9951     CU_ASSERT(0 == nghttp2_submit_data(session, NGHTTP2_FLAG_NONE, stream_id,
9952                                        &data_prd));
9953     break;
9954   }
9955
9956   return 0;
9957 }
9958
9959 void test_nghttp2_session_detach_item_from_closed_stream(void) {
9960   nghttp2_session *session;
9961   nghttp2_session_callbacks callbacks;
9962
9963   memset(&callbacks, 0, sizeof(callbacks));
9964
9965   callbacks.send_callback = null_send_callback;
9966   callbacks.on_stream_close_callback = submit_response_on_stream_close;
9967
9968   nghttp2_session_server_new(&session, &callbacks, NULL);
9969
9970   open_recv_stream(session, 1);
9971   open_recv_stream(session, 3);
9972
9973   nghttp2_session_close_stream(session, 1, NGHTTP2_NO_ERROR);
9974   nghttp2_session_close_stream(session, 3, NGHTTP2_NO_ERROR);
9975
9976   CU_ASSERT(0 == nghttp2_session_send(session));
9977
9978   nghttp2_session_del(session);
9979 }
9980
9981 void test_nghttp2_session_flooding(void) {
9982   nghttp2_session *session;
9983   nghttp2_session_callbacks callbacks;
9984   nghttp2_bufs bufs;
9985   nghttp2_buf *buf;
9986   nghttp2_frame frame;
9987   nghttp2_mem *mem;
9988   size_t i;
9989
9990   mem = nghttp2_mem_default();
9991
9992   frame_pack_bufs_init(&bufs);
9993
9994   memset(&callbacks, 0, sizeof(callbacks));
9995
9996   /* PING ACK */
9997   nghttp2_session_server_new(&session, &callbacks, NULL);
9998
9999   nghttp2_frame_ping_init(&frame.ping, NGHTTP2_FLAG_NONE, NULL);
10000   nghttp2_frame_pack_ping(&bufs, &frame.ping);
10001   nghttp2_frame_ping_free(&frame.ping);
10002
10003   buf = &bufs.head->buf;
10004
10005   for (i = 0; i < NGHTTP2_DEFAULT_MAX_OBQ_FLOOD_ITEM; ++i) {
10006     CU_ASSERT(
10007         (ssize_t)nghttp2_buf_len(buf) ==
10008         nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf)));
10009   }
10010
10011   CU_ASSERT(NGHTTP2_ERR_FLOODED ==
10012             nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf)));
10013
10014   nghttp2_session_del(session);
10015
10016   /* SETTINGS ACK */
10017   nghttp2_bufs_reset(&bufs);
10018
10019   nghttp2_session_server_new(&session, &callbacks, NULL);
10020
10021   nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE, NULL, 0);
10022   nghttp2_frame_pack_settings(&bufs, &frame.settings);
10023   nghttp2_frame_settings_free(&frame.settings, mem);
10024
10025   buf = &bufs.head->buf;
10026
10027   for (i = 0; i < NGHTTP2_DEFAULT_MAX_OBQ_FLOOD_ITEM; ++i) {
10028     CU_ASSERT(
10029         (ssize_t)nghttp2_buf_len(buf) ==
10030         nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf)));
10031   }
10032
10033   CU_ASSERT(NGHTTP2_ERR_FLOODED ==
10034             nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf)));
10035
10036   nghttp2_session_del(session);
10037   nghttp2_bufs_free(&bufs);
10038 }
10039
10040 void test_nghttp2_session_change_stream_priority(void) {
10041   nghttp2_session *session;
10042   nghttp2_session_callbacks callbacks;
10043   nghttp2_stream *stream1, *stream2, *stream3, *stream5;
10044   nghttp2_priority_spec pri_spec;
10045   int rv;
10046
10047   memset(&callbacks, 0, sizeof(callbacks));
10048
10049   nghttp2_session_server_new(&session, &callbacks, NULL);
10050
10051   stream1 = open_recv_stream(session, 1);
10052   stream3 = open_recv_stream_with_dep_weight(session, 3, 199, stream1);
10053   stream2 = open_sent_stream_with_dep_weight(session, 2, 101, stream3);
10054
10055   nghttp2_priority_spec_init(&pri_spec, 1, 256, 0);
10056
10057   rv = nghttp2_session_change_stream_priority(session, 2, &pri_spec);
10058
10059   CU_ASSERT(0 == rv);
10060
10061   CU_ASSERT(stream1 == stream2->dep_prev);
10062   CU_ASSERT(256 == stream2->weight);
10063
10064   /* Cannot change stream which does not exist */
10065   rv = nghttp2_session_change_stream_priority(session, 5, &pri_spec);
10066   CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT == rv);
10067
10068   /* It is an error to depend on itself */
10069   rv = nghttp2_session_change_stream_priority(session, 1, &pri_spec);
10070   CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT == rv);
10071
10072   /* It is an error to change priority of root stream (0) */
10073   rv = nghttp2_session_change_stream_priority(session, 0, &pri_spec);
10074   CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT == rv);
10075
10076   /* Depends on the non-existing idle stream.  This creates that idle
10077      stream. */
10078   nghttp2_priority_spec_init(&pri_spec, 5, 9, 1);
10079
10080   rv = nghttp2_session_change_stream_priority(session, 2, &pri_spec);
10081
10082   CU_ASSERT(0 == rv);
10083
10084   stream5 = nghttp2_session_get_stream_raw(session, 5);
10085
10086   CU_ASSERT(NULL != stream5);
10087   CU_ASSERT(&session->root == stream5->dep_prev);
10088   CU_ASSERT(stream5 == stream2->dep_prev);
10089   CU_ASSERT(9 == stream2->weight);
10090
10091   nghttp2_session_del(session);
10092
10093   /* Check that this works in client session too */
10094   nghttp2_session_client_new(&session, &callbacks, NULL);
10095
10096   stream1 = open_sent_stream(session, 1);
10097
10098   nghttp2_priority_spec_init(&pri_spec, 5, 9, 1);
10099
10100   rv = nghttp2_session_change_stream_priority(session, 1, &pri_spec);
10101
10102   CU_ASSERT(0 == rv);
10103
10104   stream5 = nghttp2_session_get_stream_raw(session, 5);
10105
10106   CU_ASSERT(NULL != stream5);
10107   CU_ASSERT(&session->root == stream5->dep_prev);
10108   CU_ASSERT(stream5 == stream1->dep_prev);
10109   CU_ASSERT(9 == stream1->weight);
10110
10111   nghttp2_session_del(session);
10112 }
10113
10114 void test_nghttp2_session_create_idle_stream(void) {
10115   nghttp2_session *session;
10116   nghttp2_session_callbacks callbacks;
10117   nghttp2_stream *stream2, *stream4, *stream8, *stream10;
10118   nghttp2_priority_spec pri_spec;
10119   int rv;
10120   int i;
10121
10122   memset(&callbacks, 0, sizeof(callbacks));
10123   callbacks.send_callback = null_send_callback;
10124
10125   nghttp2_session_server_new(&session, &callbacks, NULL);
10126
10127   stream2 = open_sent_stream(session, 2);
10128
10129   nghttp2_priority_spec_init(&pri_spec, 2, 111, 1);
10130
10131   rv = nghttp2_session_create_idle_stream(session, 4, &pri_spec);
10132
10133   CU_ASSERT(0 == rv);
10134
10135   stream4 = nghttp2_session_get_stream_raw(session, 4);
10136
10137   CU_ASSERT(4 == stream4->stream_id);
10138   CU_ASSERT(111 == stream4->weight);
10139   CU_ASSERT(stream2 == stream4->dep_prev);
10140   CU_ASSERT(stream4 == stream2->dep_next);
10141
10142   /* If pri_spec->stream_id does not exist, and it is idle stream, it
10143      is created too */
10144   nghttp2_priority_spec_init(&pri_spec, 10, 109, 0);
10145
10146   rv = nghttp2_session_create_idle_stream(session, 8, &pri_spec);
10147
10148   CU_ASSERT(0 == rv);
10149
10150   stream8 = nghttp2_session_get_stream_raw(session, 8);
10151   stream10 = nghttp2_session_get_stream_raw(session, 10);
10152
10153   CU_ASSERT(8 == stream8->stream_id);
10154   CU_ASSERT(109 == stream8->weight);
10155   CU_ASSERT(10 == stream10->stream_id);
10156   CU_ASSERT(16 == stream10->weight);
10157   CU_ASSERT(stream10 == stream8->dep_prev);
10158   CU_ASSERT(&session->root == stream10->dep_prev);
10159
10160   /* It is an error to attempt to create already existing idle
10161      stream */
10162   rv = nghttp2_session_create_idle_stream(session, 4, &pri_spec);
10163
10164   CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT == rv);
10165
10166   /* It is an error to depend on itself */
10167   pri_spec.stream_id = 6;
10168
10169   rv = nghttp2_session_create_idle_stream(session, 6, &pri_spec);
10170   CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT == rv);
10171
10172   /* It is an error to create root stream (0) as idle stream */
10173   rv = nghttp2_session_create_idle_stream(session, 0, &pri_spec);
10174   CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT == rv);
10175
10176   /* It is an error to create non-idle stream */
10177   session->last_sent_stream_id = 20;
10178   pri_spec.stream_id = 2;
10179
10180   rv = nghttp2_session_create_idle_stream(session, 18, &pri_spec);
10181
10182   CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT == rv);
10183
10184   nghttp2_session_del(session);
10185
10186   /* Check that this works in client session too */
10187   nghttp2_session_client_new(&session, &callbacks, NULL);
10188
10189   nghttp2_priority_spec_init(&pri_spec, 4, 99, 1);
10190
10191   rv = nghttp2_session_create_idle_stream(session, 2, &pri_spec);
10192
10193   CU_ASSERT(0 == rv);
10194
10195   stream4 = nghttp2_session_get_stream_raw(session, 4);
10196   stream2 = nghttp2_session_get_stream_raw(session, 2);
10197
10198   CU_ASSERT(NULL != stream4);
10199   CU_ASSERT(NULL != stream2);
10200   CU_ASSERT(&session->root == stream4->dep_prev);
10201   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == stream4->weight);
10202   CU_ASSERT(stream4 == stream2->dep_prev);
10203   CU_ASSERT(99 == stream2->weight);
10204
10205   nghttp2_session_del(session);
10206
10207   /* Check that idle stream is reduced when nghttp2_session_send() is
10208      called. */
10209   nghttp2_session_server_new(&session, &callbacks, NULL);
10210
10211   session->local_settings.max_concurrent_streams = 30;
10212
10213   nghttp2_priority_spec_init(&pri_spec, 0, 16, 0);
10214   for (i = 0; i < 100; ++i) {
10215     rv = nghttp2_session_create_idle_stream(session, i * 2 + 1, &pri_spec);
10216
10217     CU_ASSERT(0 == rv);
10218
10219     nghttp2_priority_spec_init(&pri_spec, i * 2 + 1, 16, 0);
10220   }
10221
10222   CU_ASSERT(100 == session->num_idle_streams);
10223   CU_ASSERT(0 == nghttp2_session_send(session));
10224   CU_ASSERT(30 == session->num_idle_streams);
10225   CU_ASSERT(141 == session->idle_stream_head->stream_id);
10226
10227   nghttp2_session_del(session);
10228
10229   /* Check that idle stream is reduced when nghttp2_session_mem_recv() is
10230      called. */
10231   nghttp2_session_client_new(&session, &callbacks, NULL);
10232
10233   session->local_settings.max_concurrent_streams = 30;
10234
10235   nghttp2_priority_spec_init(&pri_spec, 0, 16, 0);
10236   for (i = 0; i < 100; ++i) {
10237     rv = nghttp2_session_create_idle_stream(session, i * 2 + 1, &pri_spec);
10238
10239     CU_ASSERT(0 == rv);
10240
10241     nghttp2_priority_spec_init(&pri_spec, i * 2 + 1, 16, 0);
10242   }
10243
10244   CU_ASSERT(100 == session->num_idle_streams);
10245   CU_ASSERT(0 == nghttp2_session_mem_recv(session, NULL, 0));
10246   CU_ASSERT(30 == session->num_idle_streams);
10247   CU_ASSERT(141 == session->idle_stream_head->stream_id);
10248
10249   nghttp2_session_del(session);
10250 }
10251
10252 void test_nghttp2_session_repeated_priority_change(void) {
10253   nghttp2_session *session;
10254   nghttp2_session_callbacks callbacks;
10255   nghttp2_frame frame;
10256   nghttp2_priority_spec pri_spec;
10257   int32_t stream_id, last_stream_id;
10258   int32_t max_streams = 20;
10259
10260   memset(&callbacks, 0, sizeof(callbacks));
10261
10262   nghttp2_session_server_new(&session, &callbacks, NULL);
10263
10264   session->local_settings.max_concurrent_streams = (uint32_t)max_streams;
10265
10266   /* 1 -> 0 */
10267   nghttp2_priority_spec_init(&pri_spec, 0, 16, 0);
10268   nghttp2_frame_priority_init(&frame.priority, 1, &pri_spec);
10269
10270   CU_ASSERT(0 == nghttp2_session_on_priority_received(session, &frame));
10271
10272   nghttp2_frame_priority_free(&frame.priority);
10273
10274   last_stream_id = max_streams * 2 + 1;
10275
10276   for (stream_id = 3; stream_id < last_stream_id; stream_id += 2) {
10277     /* 1 -> stream_id */
10278     nghttp2_priority_spec_init(&pri_spec, stream_id, 16, 0);
10279     nghttp2_frame_priority_init(&frame.priority, 1, &pri_spec);
10280
10281     CU_ASSERT(0 == nghttp2_session_on_priority_received(session, &frame));
10282
10283     nghttp2_frame_priority_free(&frame.priority);
10284   }
10285
10286   CU_ASSERT(20 == session->num_idle_streams);
10287   CU_ASSERT(1 == session->idle_stream_head->stream_id);
10288
10289   /* 1 -> last_stream_id */
10290   nghttp2_priority_spec_init(&pri_spec, last_stream_id, 16, 0);
10291   nghttp2_frame_priority_init(&frame.priority, 1, &pri_spec);
10292
10293   CU_ASSERT(0 == nghttp2_session_on_priority_received(session, &frame));
10294
10295   nghttp2_frame_priority_free(&frame.priority);
10296
10297   CU_ASSERT(20 == session->num_idle_streams);
10298   CU_ASSERT(3 == session->idle_stream_head->stream_id);
10299
10300   nghttp2_session_del(session);
10301 }
10302
10303 void test_nghttp2_session_repeated_priority_submission(void) {
10304   nghttp2_session *session;
10305   nghttp2_session_callbacks callbacks;
10306   nghttp2_priority_spec pri_spec;
10307   int32_t stream_id, last_stream_id;
10308   uint32_t max_streams = NGHTTP2_MIN_IDLE_STREAMS;
10309
10310   memset(&callbacks, 0, sizeof(callbacks));
10311
10312   callbacks.send_callback = null_send_callback;
10313
10314   nghttp2_session_client_new(&session, &callbacks, NULL);
10315
10316   session->local_settings.max_concurrent_streams = max_streams;
10317
10318   /* 1 -> 0 */
10319   nghttp2_priority_spec_init(&pri_spec, 0, 16, 0);
10320
10321   CU_ASSERT(0 ==
10322             nghttp2_submit_priority(session, NGHTTP2_FLAG_NONE, 1, &pri_spec));
10323
10324   last_stream_id = (int32_t)(max_streams * 2 + 1);
10325
10326   for (stream_id = 3; stream_id < last_stream_id; stream_id += 2) {
10327     /* 1 -> stream_id */
10328     nghttp2_priority_spec_init(&pri_spec, stream_id, 16, 0);
10329
10330     CU_ASSERT(
10331         0 == nghttp2_submit_priority(session, NGHTTP2_FLAG_NONE, 1, &pri_spec));
10332   }
10333
10334   CU_ASSERT(0 == nghttp2_session_send(session));
10335   CU_ASSERT(max_streams == session->num_idle_streams);
10336   CU_ASSERT(1 == session->idle_stream_head->stream_id);
10337
10338   /* 1 -> last_stream_id */
10339   nghttp2_priority_spec_init(&pri_spec, last_stream_id, 16, 0);
10340
10341   CU_ASSERT(0 ==
10342             nghttp2_submit_priority(session, NGHTTP2_FLAG_NONE, 1, &pri_spec));
10343
10344   CU_ASSERT(0 == nghttp2_session_send(session));
10345   CU_ASSERT(max_streams == session->num_idle_streams);
10346   CU_ASSERT(3 == session->idle_stream_head->stream_id);
10347
10348   nghttp2_session_del(session);
10349 }
10350
10351 void test_nghttp2_session_set_local_window_size(void) {
10352   nghttp2_session *session;
10353   nghttp2_session_callbacks callbacks;
10354   nghttp2_outbound_item *item;
10355   nghttp2_stream *stream;
10356
10357   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
10358   callbacks.send_callback = null_send_callback;
10359
10360   nghttp2_session_client_new(&session, &callbacks, NULL);
10361   stream = open_sent_stream(session, 1);
10362   stream->recv_window_size = 4096;
10363
10364   CU_ASSERT(0 == nghttp2_session_set_local_window_size(
10365                      session, NGHTTP2_FLAG_NONE, 1, 65536));
10366   CU_ASSERT(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE + 1 ==
10367             stream->local_window_size);
10368   CU_ASSERT(4096 == stream->recv_window_size);
10369   CU_ASSERT(65536 - 4096 ==
10370             nghttp2_session_get_stream_local_window_size(session, 1));
10371
10372   item = nghttp2_session_get_next_ob_item(session);
10373
10374   CU_ASSERT(NGHTTP2_WINDOW_UPDATE == item->frame.hd.type);
10375   CU_ASSERT(1 == item->frame.window_update.hd.stream_id);
10376   CU_ASSERT(1 == item->frame.window_update.window_size_increment);
10377
10378   CU_ASSERT(0 == nghttp2_session_send(session));
10379
10380   /* Go decrement part */
10381   CU_ASSERT(0 == nghttp2_session_set_local_window_size(
10382                      session, NGHTTP2_FLAG_NONE, 1, 32768));
10383   CU_ASSERT(32768 == stream->local_window_size);
10384   CU_ASSERT(-28672 == stream->recv_window_size);
10385   CU_ASSERT(32768 == stream->recv_reduction);
10386   CU_ASSERT(65536 - 4096 ==
10387             nghttp2_session_get_stream_local_window_size(session, 1));
10388
10389   item = nghttp2_session_get_next_ob_item(session);
10390
10391   CU_ASSERT(item == NULL);
10392
10393   /* Increase local window size */
10394   CU_ASSERT(0 == nghttp2_session_set_local_window_size(
10395                      session, NGHTTP2_FLAG_NONE, 1, 49152));
10396   CU_ASSERT(49152 == stream->local_window_size);
10397   CU_ASSERT(-12288 == stream->recv_window_size);
10398   CU_ASSERT(16384 == stream->recv_reduction);
10399   CU_ASSERT(65536 - 4096 ==
10400             nghttp2_session_get_stream_local_window_size(session, 1));
10401   CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
10402
10403   /* Increase local window again */
10404   CU_ASSERT(0 == nghttp2_session_set_local_window_size(
10405                      session, NGHTTP2_FLAG_NONE, 1, 65537));
10406   CU_ASSERT(65537 == stream->local_window_size);
10407   CU_ASSERT(4096 == stream->recv_window_size);
10408   CU_ASSERT(0 == stream->recv_reduction);
10409   CU_ASSERT(65537 - 4096 ==
10410             nghttp2_session_get_stream_local_window_size(session, 1));
10411
10412   item = nghttp2_session_get_next_ob_item(session);
10413
10414   CU_ASSERT(1 == item->frame.window_update.window_size_increment);
10415
10416   CU_ASSERT(0 == nghttp2_session_send(session));
10417
10418   /* Check connection-level flow control */
10419   session->recv_window_size = 4096;
10420   CU_ASSERT(0 == nghttp2_session_set_local_window_size(
10421                      session, NGHTTP2_FLAG_NONE, 0, 65536));
10422   CU_ASSERT(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE + 1 ==
10423             session->local_window_size);
10424   CU_ASSERT(4096 == session->recv_window_size);
10425   CU_ASSERT(65536 - 4096 == nghttp2_session_get_local_window_size(session));
10426
10427   item = nghttp2_session_get_next_ob_item(session);
10428
10429   CU_ASSERT(NGHTTP2_WINDOW_UPDATE == item->frame.hd.type);
10430   CU_ASSERT(0 == item->frame.window_update.hd.stream_id);
10431   CU_ASSERT(1 == item->frame.window_update.window_size_increment);
10432
10433   CU_ASSERT(0 == nghttp2_session_send(session));
10434
10435   /* Go decrement part */
10436   CU_ASSERT(0 == nghttp2_session_set_local_window_size(
10437                      session, NGHTTP2_FLAG_NONE, 0, 32768));
10438   CU_ASSERT(32768 == session->local_window_size);
10439   CU_ASSERT(-28672 == session->recv_window_size);
10440   CU_ASSERT(32768 == session->recv_reduction);
10441   CU_ASSERT(65536 - 4096 == nghttp2_session_get_local_window_size(session));
10442
10443   item = nghttp2_session_get_next_ob_item(session);
10444
10445   CU_ASSERT(item == NULL);
10446
10447   /* Increase local window size */
10448   CU_ASSERT(0 == nghttp2_session_set_local_window_size(
10449                      session, NGHTTP2_FLAG_NONE, 0, 49152));
10450   CU_ASSERT(49152 == session->local_window_size);
10451   CU_ASSERT(-12288 == session->recv_window_size);
10452   CU_ASSERT(16384 == session->recv_reduction);
10453   CU_ASSERT(65536 - 4096 == nghttp2_session_get_local_window_size(session));
10454   CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
10455
10456   /* Increase local window again */
10457   CU_ASSERT(0 == nghttp2_session_set_local_window_size(
10458                      session, NGHTTP2_FLAG_NONE, 0, 65537));
10459   CU_ASSERT(65537 == session->local_window_size);
10460   CU_ASSERT(4096 == session->recv_window_size);
10461   CU_ASSERT(0 == session->recv_reduction);
10462   CU_ASSERT(65537 - 4096 == nghttp2_session_get_local_window_size(session));
10463
10464   item = nghttp2_session_get_next_ob_item(session);
10465
10466   CU_ASSERT(1 == item->frame.window_update.window_size_increment);
10467
10468   CU_ASSERT(0 == nghttp2_session_send(session));
10469
10470   nghttp2_session_del(session);
10471
10472   /* Make sure that nghttp2_session_set_local_window_size submits
10473      WINDOW_UPDATE if necessary to increase stream-level window. */
10474   nghttp2_session_client_new(&session, &callbacks, NULL);
10475   stream = open_sent_stream(session, 1);
10476   stream->recv_window_size = NGHTTP2_INITIAL_WINDOW_SIZE;
10477
10478   CU_ASSERT(0 == nghttp2_session_set_local_window_size(
10479                      session, NGHTTP2_FLAG_NONE, 1, 0));
10480   CU_ASSERT(0 == stream->recv_window_size);
10481   CU_ASSERT(0 == nghttp2_session_get_stream_local_window_size(session, 1));
10482   /* This should submit WINDOW_UPDATE frame because stream-level
10483      receiving window is now full. */
10484   CU_ASSERT(0 ==
10485             nghttp2_session_set_local_window_size(session, NGHTTP2_FLAG_NONE, 1,
10486                                                   NGHTTP2_INITIAL_WINDOW_SIZE));
10487   CU_ASSERT(0 == stream->recv_window_size);
10488   CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE ==
10489             nghttp2_session_get_stream_local_window_size(session, 1));
10490
10491   item = nghttp2_session_get_next_ob_item(session);
10492
10493   CU_ASSERT(NGHTTP2_WINDOW_UPDATE == item->frame.hd.type);
10494   CU_ASSERT(1 == item->frame.hd.stream_id);
10495   CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE ==
10496             item->frame.window_update.window_size_increment);
10497
10498   nghttp2_session_del(session);
10499
10500   /* Make sure that nghttp2_session_set_local_window_size submits
10501      WINDOW_UPDATE if necessary to increase connection-level
10502      window. */
10503   nghttp2_session_client_new(&session, &callbacks, NULL);
10504   session->recv_window_size = NGHTTP2_INITIAL_WINDOW_SIZE;
10505
10506   CU_ASSERT(0 == nghttp2_session_set_local_window_size(
10507                      session, NGHTTP2_FLAG_NONE, 0, 0));
10508   CU_ASSERT(0 == session->recv_window_size);
10509   CU_ASSERT(0 == nghttp2_session_get_local_window_size(session));
10510   /* This should submit WINDOW_UPDATE frame because connection-level
10511      receiving window is now full. */
10512   CU_ASSERT(0 ==
10513             nghttp2_session_set_local_window_size(session, NGHTTP2_FLAG_NONE, 0,
10514                                                   NGHTTP2_INITIAL_WINDOW_SIZE));
10515   CU_ASSERT(0 == session->recv_window_size);
10516   CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE ==
10517             nghttp2_session_get_local_window_size(session));
10518
10519   item = nghttp2_session_get_next_ob_item(session);
10520
10521   CU_ASSERT(NGHTTP2_WINDOW_UPDATE == item->frame.hd.type);
10522   CU_ASSERT(0 == item->frame.hd.stream_id);
10523   CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE ==
10524             item->frame.window_update.window_size_increment);
10525
10526   nghttp2_session_del(session);
10527 }
10528
10529 void test_nghttp2_session_cancel_from_before_frame_send(void) {
10530   int rv;
10531   nghttp2_session *session;
10532   nghttp2_session_callbacks callbacks;
10533   my_user_data ud;
10534   nghttp2_settings_entry iv;
10535   nghttp2_data_provider data_prd;
10536   int32_t stream_id;
10537   nghttp2_stream *stream;
10538
10539   memset(&callbacks, 0, sizeof(callbacks));
10540
10541   callbacks.before_frame_send_callback = cancel_before_frame_send_callback;
10542   callbacks.on_frame_not_send_callback = on_frame_not_send_callback;
10543   callbacks.send_callback = null_send_callback;
10544
10545   nghttp2_session_client_new(&session, &callbacks, &ud);
10546
10547   iv.settings_id = 0;
10548   iv.value = 1000000009;
10549
10550   rv = nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, &iv, 1);
10551
10552   CU_ASSERT(0 == rv);
10553
10554   ud.frame_send_cb_called = 0;
10555   ud.before_frame_send_cb_called = 0;
10556   ud.frame_not_send_cb_called = 0;
10557
10558   rv = nghttp2_session_send(session);
10559
10560   CU_ASSERT(0 == rv);
10561   CU_ASSERT(0 == ud.frame_send_cb_called);
10562   CU_ASSERT(1 == ud.before_frame_send_cb_called);
10563   CU_ASSERT(1 == ud.frame_not_send_cb_called);
10564
10565   data_prd.source.ptr = NULL;
10566   data_prd.read_callback = temporal_failure_data_source_read_callback;
10567
10568   stream_id = nghttp2_submit_request(session, NULL, reqnv, ARRLEN(reqnv),
10569                                      &data_prd, NULL);
10570
10571   CU_ASSERT(stream_id > 0);
10572
10573   ud.frame_send_cb_called = 0;
10574   ud.before_frame_send_cb_called = 0;
10575   ud.frame_not_send_cb_called = 0;
10576
10577   rv = nghttp2_session_send(session);
10578
10579   CU_ASSERT(0 == rv);
10580   CU_ASSERT(0 == ud.frame_send_cb_called);
10581   CU_ASSERT(1 == ud.before_frame_send_cb_called);
10582   CU_ASSERT(1 == ud.frame_not_send_cb_called);
10583
10584   stream = nghttp2_session_get_stream_raw(session, stream_id);
10585
10586   CU_ASSERT(NULL == stream);
10587
10588   nghttp2_session_del(session);
10589
10590   nghttp2_session_server_new(&session, &callbacks, &ud);
10591
10592   open_recv_stream(session, 1);
10593
10594   stream_id = nghttp2_submit_push_promise(session, NGHTTP2_FLAG_NONE, 1, reqnv,
10595                                           ARRLEN(reqnv), NULL);
10596
10597   CU_ASSERT(stream_id > 0);
10598
10599   ud.frame_send_cb_called = 0;
10600   ud.before_frame_send_cb_called = 0;
10601   ud.frame_not_send_cb_called = 0;
10602
10603   rv = nghttp2_session_send(session);
10604
10605   CU_ASSERT(0 == rv);
10606   CU_ASSERT(0 == ud.frame_send_cb_called);
10607   CU_ASSERT(1 == ud.before_frame_send_cb_called);
10608   CU_ASSERT(1 == ud.frame_not_send_cb_called);
10609
10610   stream = nghttp2_session_get_stream_raw(session, stream_id);
10611
10612   CU_ASSERT(NULL == stream);
10613
10614   nghttp2_session_del(session);
10615 }
10616
10617 void test_nghttp2_session_too_many_settings(void) {
10618   nghttp2_session *session;
10619   nghttp2_option *option;
10620   nghttp2_session_callbacks callbacks;
10621   nghttp2_frame frame;
10622   nghttp2_bufs bufs;
10623   nghttp2_buf *buf;
10624   ssize_t rv;
10625   my_user_data ud;
10626   nghttp2_settings_entry iv[3];
10627   nghttp2_mem *mem;
10628   nghttp2_outbound_item *item;
10629
10630   mem = nghttp2_mem_default();
10631   frame_pack_bufs_init(&bufs);
10632
10633   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
10634   callbacks.on_frame_recv_callback = on_frame_recv_callback;
10635   callbacks.send_callback = null_send_callback;
10636
10637   nghttp2_option_new(&option);
10638   nghttp2_option_set_max_settings(option, 1);
10639
10640   nghttp2_session_client_new2(&session, &callbacks, &ud, option);
10641
10642   CU_ASSERT(1 == session->max_settings);
10643
10644   nghttp2_option_del(option);
10645
10646   iv[0].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
10647   iv[0].value = 3000;
10648
10649   iv[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
10650   iv[1].value = 16384;
10651
10652   nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE, dup_iv(iv, 2),
10653                               2);
10654
10655   rv = nghttp2_frame_pack_settings(&bufs, &frame.settings);
10656
10657   CU_ASSERT(0 == rv);
10658   CU_ASSERT(nghttp2_bufs_len(&bufs) > 0);
10659
10660   nghttp2_frame_settings_free(&frame.settings, mem);
10661
10662   buf = &bufs.head->buf;
10663   assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
10664
10665   ud.frame_recv_cb_called = 0;
10666
10667   rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
10668   CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv);
10669
10670   item = nghttp2_session_get_next_ob_item(session);
10671   CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
10672
10673   nghttp2_bufs_reset(&bufs);
10674   nghttp2_bufs_free(&bufs);
10675   nghttp2_session_del(session);
10676 }
10677
10678 static void
10679 prepare_session_removed_closed_stream(nghttp2_session *session,
10680                                       nghttp2_hd_deflater *deflater) {
10681   int rv;
10682   nghttp2_settings_entry iv;
10683   nghttp2_bufs bufs;
10684   nghttp2_mem *mem;
10685   ssize_t nread;
10686   int i;
10687   nghttp2_stream *stream;
10688   nghttp2_frame_hd hd;
10689
10690   mem = nghttp2_mem_default();
10691
10692   frame_pack_bufs_init(&bufs);
10693
10694   iv.settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS;
10695   iv.value = 2;
10696
10697   rv = nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, &iv, 1);
10698
10699   CU_ASSERT(0 == rv);
10700
10701   rv = nghttp2_session_send(session);
10702
10703   CU_ASSERT(0 == rv);
10704
10705   for (i = 1; i <= 3; i += 2) {
10706     rv = pack_headers(&bufs, deflater, i,
10707                       NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM, reqnv,
10708                       ARRLEN(reqnv), mem);
10709
10710     CU_ASSERT(0 == rv);
10711
10712     nread = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
10713                                      nghttp2_bufs_len(&bufs));
10714
10715     CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == nread);
10716
10717     nghttp2_bufs_reset(&bufs);
10718   }
10719
10720   nghttp2_session_close_stream(session, 3, NGHTTP2_NO_ERROR);
10721
10722   rv = pack_headers(&bufs, deflater, 5,
10723                     NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM, reqnv,
10724                     ARRLEN(reqnv), mem);
10725
10726   CU_ASSERT(0 == rv);
10727
10728   /* Receiving stream 5 will erase stream 3 from closed stream list */
10729   nread = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
10730                                    nghttp2_bufs_len(&bufs));
10731
10732   CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == nread);
10733
10734   stream = nghttp2_session_get_stream_raw(session, 3);
10735
10736   CU_ASSERT(NULL == stream);
10737
10738   /* Since the current max concurrent streams is
10739      NGHTTP2_DEFAULT_MAX_CONCURRENT_STREAMS, receiving frame on stream
10740      3 is ignored. */
10741   nghttp2_bufs_reset(&bufs);
10742   rv = pack_headers(&bufs, deflater, 3,
10743                     NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM,
10744                     trailernv, ARRLEN(trailernv), mem);
10745
10746   CU_ASSERT(0 == rv);
10747
10748   nread = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
10749                                    nghttp2_bufs_len(&bufs));
10750
10751   CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == nread);
10752   CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
10753
10754   nghttp2_frame_hd_init(&hd, 0, NGHTTP2_DATA, NGHTTP2_FLAG_NONE, 3);
10755   nghttp2_bufs_reset(&bufs);
10756   nghttp2_frame_pack_frame_hd(bufs.head->buf.last, &hd);
10757   bufs.head->buf.last += NGHTTP2_FRAME_HDLEN;
10758
10759   nread = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
10760                                    nghttp2_bufs_len(&bufs));
10761
10762   CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == nread);
10763   CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
10764
10765   /* Now server receives SETTINGS ACK */
10766   nghttp2_frame_hd_init(&hd, 0, NGHTTP2_SETTINGS, NGHTTP2_FLAG_ACK, 0);
10767   nghttp2_bufs_reset(&bufs);
10768   nghttp2_frame_pack_frame_hd(bufs.head->buf.last, &hd);
10769   bufs.head->buf.last += NGHTTP2_FRAME_HDLEN;
10770
10771   nread = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
10772                                    nghttp2_bufs_len(&bufs));
10773
10774   CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == nread);
10775
10776   nghttp2_bufs_free(&bufs);
10777 }
10778
10779 void test_nghttp2_session_removed_closed_stream(void) {
10780   nghttp2_session *session;
10781   nghttp2_session_callbacks callbacks;
10782   int rv;
10783   nghttp2_hd_deflater deflater;
10784   nghttp2_bufs bufs;
10785   nghttp2_mem *mem;
10786   ssize_t nread;
10787   nghttp2_frame_hd hd;
10788   nghttp2_outbound_item *item;
10789
10790   mem = nghttp2_mem_default();
10791
10792   frame_pack_bufs_init(&bufs);
10793
10794   memset(&callbacks, 0, sizeof(callbacks));
10795
10796   callbacks.send_callback = null_send_callback;
10797
10798   nghttp2_session_server_new(&session, &callbacks, NULL);
10799
10800   /* Now local max concurrent streams is still unlimited, pending max
10801      concurrent streams is now 2. */
10802
10803   nghttp2_hd_deflate_init(&deflater, mem);
10804
10805   prepare_session_removed_closed_stream(session, &deflater);
10806
10807   /* Now current max concurrent streams is 2.  Receiving frame on
10808      stream 3 is ignored because we have no stream object for stream
10809      3. */
10810   nghttp2_bufs_reset(&bufs);
10811   rv = pack_headers(&bufs, &deflater, 3,
10812                     NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM,
10813                     trailernv, ARRLEN(trailernv), mem);
10814
10815   CU_ASSERT(0 == rv);
10816
10817   nread = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
10818                                    nghttp2_bufs_len(&bufs));
10819
10820   CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == nread);
10821
10822   item = nghttp2_session_get_next_ob_item(session);
10823
10824   CU_ASSERT(NULL == item);
10825
10826   nghttp2_hd_deflate_free(&deflater);
10827   nghttp2_session_del(session);
10828
10829   nghttp2_session_server_new(&session, &callbacks, NULL);
10830   nghttp2_hd_deflate_init(&deflater, mem);
10831   /* Same setup, and then receive DATA instead of HEADERS */
10832
10833   prepare_session_removed_closed_stream(session, &deflater);
10834
10835   nghttp2_frame_hd_init(&hd, 0, NGHTTP2_DATA, NGHTTP2_FLAG_NONE, 3);
10836   nghttp2_bufs_reset(&bufs);
10837   nghttp2_frame_pack_frame_hd(bufs.head->buf.last, &hd);
10838   bufs.head->buf.last += NGHTTP2_FRAME_HDLEN;
10839
10840   nread = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
10841                                    nghttp2_bufs_len(&bufs));
10842
10843   CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == nread);
10844
10845   item = nghttp2_session_get_next_ob_item(session);
10846
10847   CU_ASSERT(NULL == item);
10848
10849   nghttp2_hd_deflate_free(&deflater);
10850   nghttp2_session_del(session);
10851
10852   nghttp2_bufs_free(&bufs);
10853 }
10854
10855 static ssize_t pause_once_data_source_read_callback(
10856     nghttp2_session *session, int32_t stream_id, uint8_t *buf, size_t len,
10857     uint32_t *data_flags, nghttp2_data_source *source, void *user_data) {
10858   my_user_data *ud = user_data;
10859   if (ud->data_source_read_cb_paused == 0) {
10860     ++ud->data_source_read_cb_paused;
10861     return NGHTTP2_ERR_PAUSE;
10862   }
10863
10864   return fixed_length_data_source_read_callback(session, stream_id, buf, len,
10865                                                 data_flags, source, user_data);
10866 }
10867
10868 void test_nghttp2_session_pause_data(void) {
10869   nghttp2_session *session;
10870   nghttp2_session_callbacks callbacks;
10871   nghttp2_data_provider data_prd;
10872   my_user_data ud;
10873
10874   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
10875   callbacks.send_callback = null_send_callback;
10876   callbacks.on_frame_send_callback = on_frame_send_callback;
10877
10878   data_prd.read_callback = pause_once_data_source_read_callback;
10879   ud.data_source_length = NGHTTP2_DATA_PAYLOADLEN;
10880
10881   nghttp2_session_server_new(&session, &callbacks, &ud);
10882
10883   open_recv_stream(session, 1);
10884
10885   CU_ASSERT(
10886       0 == nghttp2_submit_data(session, NGHTTP2_FLAG_END_STREAM, 1, &data_prd));
10887
10888   ud.frame_send_cb_called = 0;
10889   ud.data_source_read_cb_paused = 0;
10890
10891   CU_ASSERT(0 == nghttp2_session_send(session));
10892   CU_ASSERT(0 == ud.frame_send_cb_called);
10893   CU_ASSERT(NULL == session->aob.item);
10894   CU_ASSERT(0 == nghttp2_session_send(session));
10895   CU_ASSERT(1 == ud.frame_send_cb_called);
10896   CU_ASSERT(NGHTTP2_DATA == ud.sent_frame_type);
10897   CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
10898
10899   nghttp2_session_del(session);
10900 }
10901
10902 void test_nghttp2_session_no_closed_streams(void) {
10903   nghttp2_session *session;
10904   nghttp2_session_callbacks callbacks;
10905   nghttp2_option *option;
10906
10907   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
10908
10909   nghttp2_option_new(&option);
10910   nghttp2_option_set_no_closed_streams(option, 1);
10911
10912   nghttp2_session_server_new2(&session, &callbacks, NULL, option);
10913
10914   open_recv_stream(session, 1);
10915
10916   nghttp2_session_close_stream(session, 1, NGHTTP2_NO_ERROR);
10917
10918   CU_ASSERT(0 == session->num_closed_streams);
10919
10920   nghttp2_session_del(session);
10921   nghttp2_option_del(option);
10922 }
10923
10924 void test_nghttp2_session_set_stream_user_data(void) {
10925   nghttp2_session *session;
10926   nghttp2_session_callbacks callbacks;
10927   int32_t stream_id;
10928   int user_data1, user_data2;
10929   int rv;
10930   const uint8_t *datap;
10931   ssize_t datalen;
10932
10933   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
10934
10935   nghttp2_session_client_new(&session, &callbacks, NULL);
10936
10937   stream_id = nghttp2_submit_request(session, NULL, reqnv, ARRLEN(reqnv), NULL,
10938                                      &user_data1);
10939
10940   rv = nghttp2_session_set_stream_user_data(session, stream_id, &user_data2);
10941
10942   CU_ASSERT(0 == rv);
10943
10944   datalen = nghttp2_session_mem_send(session, &datap);
10945
10946   CU_ASSERT(datalen > 0);
10947
10948   CU_ASSERT(&user_data2 ==
10949             nghttp2_session_get_stream_user_data(session, stream_id));
10950
10951   CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT ==
10952             nghttp2_session_set_stream_user_data(session, 2, NULL));
10953
10954   nghttp2_session_del(session);
10955 }
10956
10957 static void check_nghttp2_http_recv_headers_fail(
10958     nghttp2_session *session, nghttp2_hd_deflater *deflater, int32_t stream_id,
10959     int stream_state, const nghttp2_nv *nva, size_t nvlen) {
10960   nghttp2_mem *mem;
10961   ssize_t rv;
10962   nghttp2_outbound_item *item;
10963   nghttp2_bufs bufs;
10964   my_user_data *ud;
10965
10966   mem = nghttp2_mem_default();
10967   frame_pack_bufs_init(&bufs);
10968
10969   ud = session->user_data;
10970
10971   if (stream_state != -1) {
10972     if (nghttp2_session_is_my_stream_id(session, stream_id)) {
10973       open_sent_stream2(session, stream_id, (nghttp2_stream_state)stream_state);
10974     } else {
10975       open_recv_stream2(session, stream_id, (nghttp2_stream_state)stream_state);
10976     }
10977   }
10978
10979   rv = pack_headers(&bufs, deflater, stream_id, NGHTTP2_FLAG_END_HEADERS, nva,
10980                     nvlen, mem);
10981   CU_ASSERT(0 == rv);
10982
10983   ud->invalid_frame_recv_cb_called = 0;
10984
10985   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
10986                                 nghttp2_buf_len(&bufs.head->buf));
10987
10988   CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
10989
10990   item = nghttp2_session_get_next_ob_item(session);
10991
10992   CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
10993   CU_ASSERT(1 == ud->invalid_frame_recv_cb_called);
10994
10995   CU_ASSERT(0 == nghttp2_session_send(session));
10996
10997   nghttp2_bufs_free(&bufs);
10998 }
10999
11000 static void check_nghttp2_http_recv_headers_ok(
11001     nghttp2_session *session, nghttp2_hd_deflater *deflater, int32_t stream_id,
11002     int stream_state, const nghttp2_nv *nva, size_t nvlen) {
11003   nghttp2_mem *mem;
11004   ssize_t rv;
11005   nghttp2_bufs bufs;
11006   my_user_data *ud;
11007
11008   mem = nghttp2_mem_default();
11009   frame_pack_bufs_init(&bufs);
11010
11011   ud = session->user_data;
11012
11013   if (stream_state != -1) {
11014     if (nghttp2_session_is_my_stream_id(session, stream_id)) {
11015       open_sent_stream2(session, stream_id, (nghttp2_stream_state)stream_state);
11016     } else {
11017       open_recv_stream2(session, stream_id, (nghttp2_stream_state)stream_state);
11018     }
11019   }
11020
11021   rv = pack_headers(&bufs, deflater, stream_id, NGHTTP2_FLAG_END_HEADERS, nva,
11022                     nvlen, mem);
11023   CU_ASSERT(0 == rv);
11024
11025   ud->frame_recv_cb_called = 0;
11026
11027   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11028                                 nghttp2_buf_len(&bufs.head->buf));
11029
11030   CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
11031   CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
11032   CU_ASSERT(1 == ud->frame_recv_cb_called);
11033
11034   nghttp2_bufs_free(&bufs);
11035 }
11036
11037 void test_nghttp2_http_mandatory_headers(void) {
11038   nghttp2_session *session;
11039   nghttp2_session_callbacks callbacks;
11040   nghttp2_hd_deflater deflater;
11041   nghttp2_mem *mem;
11042   my_user_data ud;
11043   /* test case for response */
11044   const nghttp2_nv nostatus_resnv[] = {MAKE_NV("server", "foo")};
11045   const nghttp2_nv dupstatus_resnv[] = {MAKE_NV(":status", "200"),
11046                                         MAKE_NV(":status", "200")};
11047   const nghttp2_nv badpseudo_resnv[] = {MAKE_NV(":status", "200"),
11048                                         MAKE_NV(":scheme", "https")};
11049   const nghttp2_nv latepseudo_resnv[] = {MAKE_NV("server", "foo"),
11050                                          MAKE_NV(":status", "200")};
11051   const nghttp2_nv badstatus_resnv[] = {MAKE_NV(":status", "2000")};
11052   const nghttp2_nv badcl_resnv[] = {MAKE_NV(":status", "200"),
11053                                     MAKE_NV("content-length", "-1")};
11054   const nghttp2_nv dupcl_resnv[] = {MAKE_NV(":status", "200"),
11055                                     MAKE_NV("content-length", "0"),
11056                                     MAKE_NV("content-length", "0")};
11057   const nghttp2_nv badhd_resnv[] = {MAKE_NV(":status", "200"),
11058                                     MAKE_NV("connection", "close")};
11059   const nghttp2_nv cl1xx_resnv[] = {MAKE_NV(":status", "100"),
11060                                     MAKE_NV("content-length", "0")};
11061   const nghttp2_nv cl204_resnv[] = {MAKE_NV(":status", "204"),
11062                                     MAKE_NV("content-length", "0")};
11063   const nghttp2_nv clnonzero204_resnv[] = {MAKE_NV(":status", "204"),
11064                                            MAKE_NV("content-length", "100")};
11065   const nghttp2_nv status101_resnv[] = {MAKE_NV(":status", "101")};
11066
11067   /* test case for request */
11068   const nghttp2_nv nopath_reqnv[] = {MAKE_NV(":scheme", "https"),
11069                                      MAKE_NV(":method", "GET"),
11070                                      MAKE_NV(":authority", "localhost")};
11071   const nghttp2_nv earlyconnect_reqnv[] = {
11072       MAKE_NV(":method", "CONNECT"), MAKE_NV(":scheme", "https"),
11073       MAKE_NV(":path", "/"), MAKE_NV(":authority", "localhost")};
11074   const nghttp2_nv lateconnect_reqnv[] = {
11075       MAKE_NV(":scheme", "https"), MAKE_NV(":path", "/"),
11076       MAKE_NV(":method", "CONNECT"), MAKE_NV(":authority", "localhost")};
11077   const nghttp2_nv duppath_reqnv[] = {
11078       MAKE_NV(":scheme", "https"), MAKE_NV(":method", "GET"),
11079       MAKE_NV(":authority", "localhost"), MAKE_NV(":path", "/"),
11080       MAKE_NV(":path", "/")};
11081   const nghttp2_nv badcl_reqnv[] = {
11082       MAKE_NV(":scheme", "https"), MAKE_NV(":method", "POST"),
11083       MAKE_NV(":authority", "localhost"), MAKE_NV(":path", "/"),
11084       MAKE_NV("content-length", "-1")};
11085   const nghttp2_nv dupcl_reqnv[] = {
11086       MAKE_NV(":scheme", "https"),        MAKE_NV(":method", "POST"),
11087       MAKE_NV(":authority", "localhost"), MAKE_NV(":path", "/"),
11088       MAKE_NV("content-length", "0"),     MAKE_NV("content-length", "0")};
11089   const nghttp2_nv badhd_reqnv[] = {
11090       MAKE_NV(":scheme", "https"), MAKE_NV(":method", "GET"),
11091       MAKE_NV(":authority", "localhost"), MAKE_NV(":path", "/"),
11092       MAKE_NV("connection", "close")};
11093   const nghttp2_nv badauthority_reqnv[] = {
11094       MAKE_NV(":scheme", "https"), MAKE_NV(":method", "GET"),
11095       MAKE_NV(":authority", "\x0d\x0alocalhost"), MAKE_NV(":path", "/")};
11096   const nghttp2_nv badhdbtw_reqnv[] = {
11097       MAKE_NV(":scheme", "https"), MAKE_NV(":method", "GET"),
11098       MAKE_NV("foo", "\x0d\x0a"), MAKE_NV(":authority", "localhost"),
11099       MAKE_NV(":path", "/")};
11100   const nghttp2_nv asteriskget1_reqnv[] = {
11101       MAKE_NV(":path", "*"), MAKE_NV(":scheme", "https"),
11102       MAKE_NV(":authority", "localhost"), MAKE_NV(":method", "GET")};
11103   const nghttp2_nv asteriskget2_reqnv[] = {
11104       MAKE_NV(":scheme", "https"), MAKE_NV(":authority", "localhost"),
11105       MAKE_NV(":method", "GET"), MAKE_NV(":path", "*")};
11106   const nghttp2_nv asteriskoptions1_reqnv[] = {
11107       MAKE_NV(":path", "*"), MAKE_NV(":scheme", "https"),
11108       MAKE_NV(":authority", "localhost"), MAKE_NV(":method", "OPTIONS")};
11109   const nghttp2_nv asteriskoptions2_reqnv[] = {
11110       MAKE_NV(":scheme", "https"), MAKE_NV(":authority", "localhost"),
11111       MAKE_NV(":method", "OPTIONS"), MAKE_NV(":path", "*")};
11112   const nghttp2_nv connectproto_reqnv[] = {
11113       MAKE_NV(":scheme", "https"), MAKE_NV(":path", "/"),
11114       MAKE_NV(":method", "CONNECT"), MAKE_NV(":authority", "localhost"),
11115       MAKE_NV(":protocol", "websocket")};
11116   const nghttp2_nv connectprotoget_reqnv[] = {
11117       MAKE_NV(":scheme", "https"), MAKE_NV(":path", "/"),
11118       MAKE_NV(":method", "GET"), MAKE_NV(":authority", "localhost"),
11119       MAKE_NV(":protocol", "websocket")};
11120   const nghttp2_nv connectprotonopath_reqnv[] = {
11121       MAKE_NV(":scheme", "https"), MAKE_NV(":method", "CONNECT"),
11122       MAKE_NV(":authority", "localhost"), MAKE_NV(":protocol", "websocket")};
11123   const nghttp2_nv connectprotonoauth_reqnv[] = {
11124       MAKE_NV(":scheme", "http"), MAKE_NV(":path", "/"),
11125       MAKE_NV(":method", "CONNECT"), MAKE_NV("host", "localhost"),
11126       MAKE_NV(":protocol", "websocket")};
11127   const nghttp2_nv regularconnect_reqnv[] = {
11128       MAKE_NV(":method", "CONNECT"), MAKE_NV(":authority", "localhost")};
11129
11130   mem = nghttp2_mem_default();
11131
11132   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
11133   callbacks.send_callback = null_send_callback;
11134   callbacks.on_frame_recv_callback = on_frame_recv_callback;
11135   callbacks.on_invalid_frame_recv_callback = on_invalid_frame_recv_callback;
11136
11137   nghttp2_session_client_new(&session, &callbacks, &ud);
11138
11139   nghttp2_hd_deflate_init(&deflater, mem);
11140
11141   /* response header lacks :status */
11142   check_nghttp2_http_recv_headers_fail(session, &deflater, 1,
11143                                        NGHTTP2_STREAM_OPENING, nostatus_resnv,
11144                                        ARRLEN(nostatus_resnv));
11145
11146   /* response header has 2 :status */
11147   check_nghttp2_http_recv_headers_fail(session, &deflater, 3,
11148                                        NGHTTP2_STREAM_OPENING, dupstatus_resnv,
11149                                        ARRLEN(dupstatus_resnv));
11150
11151   /* response header has bad pseudo header :scheme */
11152   check_nghttp2_http_recv_headers_fail(session, &deflater, 5,
11153                                        NGHTTP2_STREAM_OPENING, badpseudo_resnv,
11154                                        ARRLEN(badpseudo_resnv));
11155
11156   /* response header has :status after regular header field */
11157   check_nghttp2_http_recv_headers_fail(session, &deflater, 7,
11158                                        NGHTTP2_STREAM_OPENING, latepseudo_resnv,
11159                                        ARRLEN(latepseudo_resnv));
11160
11161   /* response header has bad status code */
11162   check_nghttp2_http_recv_headers_fail(session, &deflater, 9,
11163                                        NGHTTP2_STREAM_OPENING, badstatus_resnv,
11164                                        ARRLEN(badstatus_resnv));
11165
11166   /* response header has bad content-length */
11167   check_nghttp2_http_recv_headers_fail(session, &deflater, 11,
11168                                        NGHTTP2_STREAM_OPENING, badcl_resnv,
11169                                        ARRLEN(badcl_resnv));
11170
11171   /* response header has multiple content-length */
11172   check_nghttp2_http_recv_headers_fail(session, &deflater, 13,
11173                                        NGHTTP2_STREAM_OPENING, dupcl_resnv,
11174                                        ARRLEN(dupcl_resnv));
11175
11176   /* response header has disallowed header field */
11177   check_nghttp2_http_recv_headers_fail(session, &deflater, 15,
11178                                        NGHTTP2_STREAM_OPENING, badhd_resnv,
11179                                        ARRLEN(badhd_resnv));
11180
11181   /* response header has content-length with 100 status code */
11182   check_nghttp2_http_recv_headers_fail(session, &deflater, 17,
11183                                        NGHTTP2_STREAM_OPENING, cl1xx_resnv,
11184                                        ARRLEN(cl1xx_resnv));
11185
11186   /* response header has 0 content-length with 204 status code */
11187   check_nghttp2_http_recv_headers_ok(session, &deflater, 19,
11188                                      NGHTTP2_STREAM_OPENING, cl204_resnv,
11189                                      ARRLEN(cl204_resnv));
11190
11191   /* response header has nonzero content-length with 204 status
11192      code */
11193   check_nghttp2_http_recv_headers_fail(
11194       session, &deflater, 21, NGHTTP2_STREAM_OPENING, clnonzero204_resnv,
11195       ARRLEN(clnonzero204_resnv));
11196
11197   /* status code 101 should not be used in HTTP/2 because it is used
11198      for HTTP Upgrade which HTTP/2 removes. */
11199   check_nghttp2_http_recv_headers_fail(session, &deflater, 23,
11200                                        NGHTTP2_STREAM_OPENING, status101_resnv,
11201                                        ARRLEN(status101_resnv));
11202
11203   nghttp2_hd_deflate_free(&deflater);
11204
11205   nghttp2_session_del(session);
11206
11207   /* check server side */
11208   nghttp2_session_server_new(&session, &callbacks, &ud);
11209
11210   nghttp2_hd_deflate_init(&deflater, mem);
11211
11212   /* request header has no :path */
11213   check_nghttp2_http_recv_headers_fail(session, &deflater, 1, -1, nopath_reqnv,
11214                                        ARRLEN(nopath_reqnv));
11215
11216   /* request header has CONNECT method, but followed by :path */
11217   check_nghttp2_http_recv_headers_fail(session, &deflater, 3, -1,
11218                                        earlyconnect_reqnv,
11219                                        ARRLEN(earlyconnect_reqnv));
11220
11221   /* request header has CONNECT method following :path */
11222   check_nghttp2_http_recv_headers_fail(
11223       session, &deflater, 5, -1, lateconnect_reqnv, ARRLEN(lateconnect_reqnv));
11224
11225   /* request header has multiple :path */
11226   check_nghttp2_http_recv_headers_fail(session, &deflater, 7, -1, duppath_reqnv,
11227                                        ARRLEN(duppath_reqnv));
11228
11229   /* request header has bad content-length */
11230   check_nghttp2_http_recv_headers_fail(session, &deflater, 9, -1, badcl_reqnv,
11231                                        ARRLEN(badcl_reqnv));
11232
11233   /* request header has multiple content-length */
11234   check_nghttp2_http_recv_headers_fail(session, &deflater, 11, -1, dupcl_reqnv,
11235                                        ARRLEN(dupcl_reqnv));
11236
11237   /* request header has disallowed header field */
11238   check_nghttp2_http_recv_headers_fail(session, &deflater, 13, -1, badhd_reqnv,
11239                                        ARRLEN(badhd_reqnv));
11240
11241   /* request header has :authority header field containing illegal
11242      characters */
11243   check_nghttp2_http_recv_headers_fail(session, &deflater, 15, -1,
11244                                        badauthority_reqnv,
11245                                        ARRLEN(badauthority_reqnv));
11246
11247   /* request header has regular header field containing illegal
11248      character before all mandatory header fields are seen. */
11249   check_nghttp2_http_recv_headers_fail(session, &deflater, 17, -1,
11250                                        badhdbtw_reqnv, ARRLEN(badhdbtw_reqnv));
11251
11252   /* request header has "*" in :path header field while method is GET.
11253      :path is received before :method */
11254   check_nghttp2_http_recv_headers_fail(session, &deflater, 19, -1,
11255                                        asteriskget1_reqnv,
11256                                        ARRLEN(asteriskget1_reqnv));
11257
11258   /* request header has "*" in :path header field while method is GET.
11259      :method is received before :path */
11260   check_nghttp2_http_recv_headers_fail(session, &deflater, 21, -1,
11261                                        asteriskget2_reqnv,
11262                                        ARRLEN(asteriskget2_reqnv));
11263
11264   /* OPTIONS method can include "*" in :path header field.  :path is
11265      received before :method. */
11266   check_nghttp2_http_recv_headers_ok(session, &deflater, 23, -1,
11267                                      asteriskoptions1_reqnv,
11268                                      ARRLEN(asteriskoptions1_reqnv));
11269
11270   /* OPTIONS method can include "*" in :path header field.  :method is
11271      received before :path. */
11272   check_nghttp2_http_recv_headers_ok(session, &deflater, 25, -1,
11273                                      asteriskoptions2_reqnv,
11274                                      ARRLEN(asteriskoptions2_reqnv));
11275
11276   /* :protocol is not allowed unless it is enabled by the local
11277      endpoint. */
11278   check_nghttp2_http_recv_headers_fail(session, &deflater, 27, -1,
11279                                        connectproto_reqnv,
11280                                        ARRLEN(connectproto_reqnv));
11281
11282   nghttp2_hd_deflate_free(&deflater);
11283
11284   nghttp2_session_del(session);
11285
11286   /* enable SETTINGS_CONNECT_PROTOCOL */
11287   nghttp2_session_server_new(&session, &callbacks, &ud);
11288
11289   session->pending_enable_connect_protocol = 1;
11290
11291   nghttp2_hd_deflate_init(&deflater, mem);
11292
11293   /* :protocol is allowed if SETTINGS_CONNECT_PROTOCOL is enabled by
11294      the local endpoint. */
11295   check_nghttp2_http_recv_headers_ok(session, &deflater, 1, -1,
11296                                      connectproto_reqnv,
11297                                      ARRLEN(connectproto_reqnv));
11298
11299   /* :protocol is only allowed with CONNECT method. */
11300   check_nghttp2_http_recv_headers_fail(session, &deflater, 3, -1,
11301                                        connectprotoget_reqnv,
11302                                        ARRLEN(connectprotoget_reqnv));
11303
11304   /* CONNECT method with :protocol requires :path. */
11305   check_nghttp2_http_recv_headers_fail(session, &deflater, 5, -1,
11306                                        connectprotonopath_reqnv,
11307                                        ARRLEN(connectprotonopath_reqnv));
11308
11309   /* CONNECT method with :protocol requires :authority. */
11310   check_nghttp2_http_recv_headers_fail(session, &deflater, 7, -1,
11311                                        connectprotonoauth_reqnv,
11312                                        ARRLEN(connectprotonoauth_reqnv));
11313
11314   /* regular CONNECT method should succeed with
11315      SETTINGS_CONNECT_PROTOCOL */
11316   check_nghttp2_http_recv_headers_ok(session, &deflater, 9, -1,
11317                                      regularconnect_reqnv,
11318                                      ARRLEN(regularconnect_reqnv));
11319
11320   nghttp2_hd_deflate_free(&deflater);
11321
11322   nghttp2_session_del(session);
11323 }
11324
11325 void test_nghttp2_http_content_length(void) {
11326   nghttp2_session *session;
11327   nghttp2_session_callbacks callbacks;
11328   nghttp2_hd_deflater deflater;
11329   nghttp2_mem *mem;
11330   nghttp2_bufs bufs;
11331   ssize_t rv;
11332   nghttp2_stream *stream;
11333   const nghttp2_nv cl_resnv[] = {MAKE_NV(":status", "200"),
11334                                  MAKE_NV("te", "trailers"),
11335                                  MAKE_NV("content-length", "9000000000")};
11336   const nghttp2_nv cl_reqnv[] = {
11337       MAKE_NV(":path", "/"),        MAKE_NV(":method", "PUT"),
11338       MAKE_NV(":scheme", "https"),  MAKE_NV("te", "trailers"),
11339       MAKE_NV("host", "localhost"), MAKE_NV("content-length", "9000000000")};
11340
11341   mem = nghttp2_mem_default();
11342   frame_pack_bufs_init(&bufs);
11343
11344   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
11345   callbacks.send_callback = null_send_callback;
11346
11347   nghttp2_session_client_new(&session, &callbacks, NULL);
11348
11349   nghttp2_hd_deflate_init(&deflater, mem);
11350
11351   stream = open_sent_stream2(session, 1, NGHTTP2_STREAM_OPENING);
11352
11353   rv = pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, cl_resnv,
11354                     ARRLEN(cl_resnv), mem);
11355   CU_ASSERT(0 == rv);
11356
11357   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11358                                 nghttp2_buf_len(&bufs.head->buf));
11359
11360   CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
11361   CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
11362   CU_ASSERT(9000000000LL == stream->content_length);
11363   CU_ASSERT(200 == stream->status_code);
11364
11365   nghttp2_hd_deflate_free(&deflater);
11366
11367   nghttp2_session_del(session);
11368
11369   nghttp2_bufs_reset(&bufs);
11370
11371   /* check server side */
11372   nghttp2_session_server_new(&session, &callbacks, NULL);
11373
11374   nghttp2_hd_deflate_init(&deflater, mem);
11375
11376   rv = pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, cl_reqnv,
11377                     ARRLEN(cl_reqnv), mem);
11378   CU_ASSERT(0 == rv);
11379
11380   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11381                                 nghttp2_buf_len(&bufs.head->buf));
11382
11383   CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
11384
11385   stream = nghttp2_session_get_stream(session, 1);
11386
11387   CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
11388   CU_ASSERT(9000000000LL == stream->content_length);
11389
11390   nghttp2_hd_deflate_free(&deflater);
11391
11392   nghttp2_session_del(session);
11393
11394   nghttp2_bufs_free(&bufs);
11395 }
11396
11397 void test_nghttp2_http_content_length_mismatch(void) {
11398   nghttp2_session *session;
11399   nghttp2_session_callbacks callbacks;
11400   nghttp2_hd_deflater deflater;
11401   nghttp2_mem *mem;
11402   nghttp2_bufs bufs;
11403   ssize_t rv;
11404   const nghttp2_nv cl_reqnv[] = {
11405       MAKE_NV(":path", "/"), MAKE_NV(":method", "PUT"),
11406       MAKE_NV(":authority", "localhost"), MAKE_NV(":scheme", "https"),
11407       MAKE_NV("content-length", "20")};
11408   const nghttp2_nv cl_resnv[] = {MAKE_NV(":status", "200"),
11409                                  MAKE_NV("content-length", "20")};
11410   nghttp2_outbound_item *item;
11411   nghttp2_frame_hd hd;
11412
11413   mem = nghttp2_mem_default();
11414   frame_pack_bufs_init(&bufs);
11415
11416   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
11417   callbacks.send_callback = null_send_callback;
11418
11419   nghttp2_session_server_new(&session, &callbacks, NULL);
11420
11421   nghttp2_hd_deflate_init(&deflater, mem);
11422
11423   /* header says content-length: 20, but HEADERS has END_STREAM flag set */
11424   rv = pack_headers(&bufs, &deflater, 1,
11425                     NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM,
11426                     cl_reqnv, ARRLEN(cl_reqnv), mem);
11427   CU_ASSERT(0 == rv);
11428
11429   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11430                                 nghttp2_buf_len(&bufs.head->buf));
11431
11432   CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
11433
11434   item = nghttp2_session_get_next_ob_item(session);
11435   CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
11436
11437   CU_ASSERT(0 == nghttp2_session_send(session));
11438
11439   nghttp2_bufs_reset(&bufs);
11440
11441   /* header says content-length: 20, but DATA has 0 byte */
11442   rv = pack_headers(&bufs, &deflater, 3, NGHTTP2_FLAG_END_HEADERS, cl_reqnv,
11443                     ARRLEN(cl_reqnv), mem);
11444   CU_ASSERT(0 == rv);
11445
11446   nghttp2_frame_hd_init(&hd, 0, NGHTTP2_DATA, NGHTTP2_FLAG_END_STREAM, 3);
11447   nghttp2_frame_pack_frame_hd(bufs.head->buf.last, &hd);
11448   bufs.head->buf.last += NGHTTP2_FRAME_HDLEN;
11449
11450   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11451                                 nghttp2_buf_len(&bufs.head->buf));
11452
11453   CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
11454
11455   item = nghttp2_session_get_next_ob_item(session);
11456   CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
11457
11458   CU_ASSERT(0 == nghttp2_session_send(session));
11459
11460   nghttp2_bufs_reset(&bufs);
11461
11462   /* header says content-length: 20, but DATA has 21 bytes */
11463   rv = pack_headers(&bufs, &deflater, 5, NGHTTP2_FLAG_END_HEADERS, cl_reqnv,
11464                     ARRLEN(cl_reqnv), mem);
11465   CU_ASSERT(0 == rv);
11466
11467   nghttp2_frame_hd_init(&hd, 21, NGHTTP2_DATA, NGHTTP2_FLAG_END_STREAM, 5);
11468   nghttp2_frame_pack_frame_hd(bufs.head->buf.last, &hd);
11469   bufs.head->buf.last += NGHTTP2_FRAME_HDLEN + 21;
11470
11471   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11472                                 nghttp2_buf_len(&bufs.head->buf));
11473
11474   CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
11475
11476   item = nghttp2_session_get_next_ob_item(session);
11477   CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
11478
11479   CU_ASSERT(0 == nghttp2_session_send(session));
11480
11481   nghttp2_bufs_reset(&bufs);
11482
11483   nghttp2_hd_deflate_free(&deflater);
11484
11485   nghttp2_session_del(session);
11486
11487   /* Check for client */
11488   nghttp2_session_client_new(&session, &callbacks, NULL);
11489
11490   nghttp2_hd_deflate_init(&deflater, mem);
11491
11492   /* header says content-length: 20, but HEADERS has END_STREAM flag set */
11493   nghttp2_submit_request(session, NULL, reqnv, ARRLEN(reqnv), NULL, NULL);
11494
11495   CU_ASSERT(0 == nghttp2_session_send(session));
11496
11497   rv = pack_headers(&bufs, &deflater, 1,
11498                     NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM,
11499                     cl_resnv, ARRLEN(cl_resnv), mem);
11500   CU_ASSERT(0 == rv);
11501
11502   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11503                                 nghttp2_buf_len(&bufs.head->buf));
11504
11505   CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
11506
11507   item = nghttp2_session_get_next_ob_item(session);
11508   CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
11509
11510   CU_ASSERT(NULL != nghttp2_session_get_stream(session, 1));
11511   CU_ASSERT(0 == nghttp2_session_send(session));
11512   /* After sending RST_STREAM, stream must be closed */
11513   CU_ASSERT(NULL == nghttp2_session_get_stream(session, 1));
11514
11515   nghttp2_bufs_reset(&bufs);
11516
11517   /* header says content-length: 20, but DATA has 0 byte */
11518   nghttp2_submit_request(session, NULL, reqnv, ARRLEN(reqnv), NULL, NULL);
11519
11520   CU_ASSERT(0 == nghttp2_session_send(session));
11521
11522   rv = pack_headers(&bufs, &deflater, 3, NGHTTP2_FLAG_END_HEADERS, cl_resnv,
11523                     ARRLEN(cl_resnv), mem);
11524   CU_ASSERT(0 == rv);
11525
11526   nghttp2_frame_hd_init(&hd, 0, NGHTTP2_DATA, NGHTTP2_FLAG_END_STREAM, 3);
11527   nghttp2_frame_pack_frame_hd(bufs.head->buf.last, &hd);
11528   bufs.head->buf.last += NGHTTP2_FRAME_HDLEN;
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(NULL != nghttp2_session_get_stream(session, 3));
11539   CU_ASSERT(0 == nghttp2_session_send(session));
11540   /* After sending RST_STREAM, stream must be closed */
11541   CU_ASSERT(NULL == nghttp2_session_get_stream(session, 3));
11542
11543   nghttp2_bufs_reset(&bufs);
11544
11545   /* header says content-length: 20, but DATA has 21 bytes */
11546   nghttp2_submit_request(session, NULL, reqnv, ARRLEN(reqnv), NULL, NULL);
11547
11548   CU_ASSERT(0 == nghttp2_session_send(session));
11549
11550   rv = pack_headers(&bufs, &deflater, 5, NGHTTP2_FLAG_END_HEADERS, cl_resnv,
11551                     ARRLEN(cl_resnv), mem);
11552   CU_ASSERT(0 == rv);
11553
11554   nghttp2_frame_hd_init(&hd, 21, NGHTTP2_DATA, NGHTTP2_FLAG_END_STREAM, 5);
11555   nghttp2_frame_pack_frame_hd(bufs.head->buf.last, &hd);
11556   bufs.head->buf.last += NGHTTP2_FRAME_HDLEN + 21;
11557
11558   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11559                                 nghttp2_buf_len(&bufs.head->buf));
11560
11561   CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
11562
11563   item = nghttp2_session_get_next_ob_item(session);
11564   CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
11565
11566   CU_ASSERT(NULL != nghttp2_session_get_stream(session, 5));
11567   CU_ASSERT(0 == nghttp2_session_send(session));
11568   /* After sending RST_STREAM, stream must be closed */
11569   CU_ASSERT(NULL == nghttp2_session_get_stream(session, 5));
11570
11571   nghttp2_bufs_reset(&bufs);
11572
11573   nghttp2_bufs_free(&bufs);
11574
11575   nghttp2_hd_deflate_free(&deflater);
11576
11577   nghttp2_session_del(session);
11578 }
11579
11580 void test_nghttp2_http_non_final_response(void) {
11581   nghttp2_session *session;
11582   nghttp2_session_callbacks callbacks;
11583   nghttp2_hd_deflater deflater;
11584   nghttp2_mem *mem;
11585   nghttp2_bufs bufs;
11586   ssize_t rv;
11587   const nghttp2_nv nonfinal_resnv[] = {
11588       MAKE_NV(":status", "100"),
11589   };
11590   nghttp2_outbound_item *item;
11591   nghttp2_frame_hd hd;
11592
11593   mem = nghttp2_mem_default();
11594   frame_pack_bufs_init(&bufs);
11595
11596   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
11597   callbacks.send_callback = null_send_callback;
11598
11599   nghttp2_session_client_new(&session, &callbacks, NULL);
11600
11601   nghttp2_hd_deflate_init(&deflater, mem);
11602
11603   /* non-final HEADERS with END_STREAM is illegal */
11604   open_sent_stream2(session, 1, NGHTTP2_STREAM_OPENING);
11605
11606   rv = pack_headers(&bufs, &deflater, 1,
11607                     NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM,
11608                     nonfinal_resnv, ARRLEN(nonfinal_resnv), mem);
11609   CU_ASSERT(0 == rv);
11610
11611   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11612                                 nghttp2_buf_len(&bufs.head->buf));
11613
11614   CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
11615
11616   item = nghttp2_session_get_next_ob_item(session);
11617   CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
11618
11619   CU_ASSERT(0 == nghttp2_session_send(session));
11620
11621   nghttp2_bufs_reset(&bufs);
11622
11623   /* non-final HEADERS followed by non-empty DATA is illegal */
11624   open_sent_stream2(session, 3, NGHTTP2_STREAM_OPENING);
11625
11626   rv = pack_headers(&bufs, &deflater, 3, NGHTTP2_FLAG_END_HEADERS,
11627                     nonfinal_resnv, ARRLEN(nonfinal_resnv), mem);
11628   CU_ASSERT(0 == rv);
11629
11630   nghttp2_frame_hd_init(&hd, 10, NGHTTP2_DATA, NGHTTP2_FLAG_END_STREAM, 3);
11631   nghttp2_frame_pack_frame_hd(bufs.head->buf.last, &hd);
11632   bufs.head->buf.last += NGHTTP2_FRAME_HDLEN + 10;
11633
11634   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11635                                 nghttp2_buf_len(&bufs.head->buf));
11636
11637   CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
11638
11639   item = nghttp2_session_get_next_ob_item(session);
11640   CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
11641
11642   CU_ASSERT(0 == nghttp2_session_send(session));
11643
11644   nghttp2_bufs_reset(&bufs);
11645
11646   /* non-final HEADERS followed by empty DATA (without END_STREAM) is
11647      ok */
11648   open_sent_stream2(session, 5, NGHTTP2_STREAM_OPENING);
11649
11650   rv = pack_headers(&bufs, &deflater, 5, NGHTTP2_FLAG_END_HEADERS,
11651                     nonfinal_resnv, ARRLEN(nonfinal_resnv), mem);
11652   CU_ASSERT(0 == rv);
11653
11654   nghttp2_frame_hd_init(&hd, 0, NGHTTP2_DATA, NGHTTP2_FLAG_NONE, 5);
11655   nghttp2_frame_pack_frame_hd(bufs.head->buf.last, &hd);
11656   bufs.head->buf.last += NGHTTP2_FRAME_HDLEN;
11657
11658   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11659                                 nghttp2_buf_len(&bufs.head->buf));
11660
11661   CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
11662
11663   CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
11664
11665   nghttp2_bufs_reset(&bufs);
11666
11667   /* non-final HEADERS followed by empty DATA (with END_STREAM) is
11668      illegal */
11669   open_sent_stream2(session, 7, NGHTTP2_STREAM_OPENING);
11670
11671   rv = pack_headers(&bufs, &deflater, 7, NGHTTP2_FLAG_END_HEADERS,
11672                     nonfinal_resnv, ARRLEN(nonfinal_resnv), mem);
11673   CU_ASSERT(0 == rv);
11674
11675   nghttp2_frame_hd_init(&hd, 0, NGHTTP2_DATA, NGHTTP2_FLAG_END_STREAM, 7);
11676   nghttp2_frame_pack_frame_hd(bufs.head->buf.last, &hd);
11677   bufs.head->buf.last += NGHTTP2_FRAME_HDLEN;
11678
11679   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11680                                 nghttp2_buf_len(&bufs.head->buf));
11681
11682   CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
11683
11684   item = nghttp2_session_get_next_ob_item(session);
11685
11686   CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
11687
11688   CU_ASSERT(0 == nghttp2_session_send(session));
11689
11690   nghttp2_bufs_reset(&bufs);
11691
11692   /* non-final HEADERS followed by final HEADERS is OK */
11693   open_sent_stream2(session, 9, NGHTTP2_STREAM_OPENING);
11694
11695   rv = pack_headers(&bufs, &deflater, 9, NGHTTP2_FLAG_END_HEADERS,
11696                     nonfinal_resnv, ARRLEN(nonfinal_resnv), mem);
11697   CU_ASSERT(0 == rv);
11698
11699   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11700                                 nghttp2_buf_len(&bufs.head->buf));
11701
11702   CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
11703
11704   nghttp2_bufs_reset(&bufs);
11705
11706   rv = pack_headers(&bufs, &deflater, 9, NGHTTP2_FLAG_END_HEADERS, resnv,
11707                     ARRLEN(resnv), mem);
11708   CU_ASSERT(0 == rv);
11709
11710   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11711                                 nghttp2_buf_len(&bufs.head->buf));
11712
11713   CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
11714
11715   CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
11716
11717   nghttp2_bufs_reset(&bufs);
11718
11719   nghttp2_hd_deflate_free(&deflater);
11720
11721   nghttp2_session_del(session);
11722
11723   nghttp2_bufs_free(&bufs);
11724 }
11725
11726 void test_nghttp2_http_trailer_headers(void) {
11727   nghttp2_session *session;
11728   nghttp2_session_callbacks callbacks;
11729   nghttp2_hd_deflater deflater;
11730   nghttp2_mem *mem;
11731   nghttp2_bufs bufs;
11732   ssize_t rv;
11733   const nghttp2_nv trailer_reqnv[] = {
11734       MAKE_NV("foo", "bar"),
11735   };
11736   nghttp2_outbound_item *item;
11737
11738   mem = nghttp2_mem_default();
11739   frame_pack_bufs_init(&bufs);
11740
11741   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
11742   callbacks.send_callback = null_send_callback;
11743
11744   nghttp2_session_server_new(&session, &callbacks, NULL);
11745
11746   nghttp2_hd_deflate_init(&deflater, mem);
11747
11748   /* good trailer header */
11749   rv = pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, reqnv,
11750                     ARRLEN(reqnv), mem);
11751   CU_ASSERT(0 == rv);
11752
11753   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11754                                 nghttp2_buf_len(&bufs.head->buf));
11755
11756   CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
11757
11758   nghttp2_bufs_reset(&bufs);
11759
11760   rv = pack_headers(&bufs, &deflater, 1,
11761                     NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM,
11762                     trailer_reqnv, ARRLEN(trailer_reqnv), mem);
11763   CU_ASSERT(0 == rv);
11764
11765   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11766                                 nghttp2_buf_len(&bufs.head->buf));
11767
11768   CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
11769
11770   CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
11771
11772   nghttp2_bufs_reset(&bufs);
11773
11774   /* trailer header without END_STREAM is illegal */
11775   rv = pack_headers(&bufs, &deflater, 3, NGHTTP2_FLAG_END_HEADERS, reqnv,
11776                     ARRLEN(reqnv), mem);
11777   CU_ASSERT(0 == rv);
11778
11779   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11780                                 nghttp2_buf_len(&bufs.head->buf));
11781
11782   CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
11783
11784   nghttp2_bufs_reset(&bufs);
11785
11786   rv = pack_headers(&bufs, &deflater, 3, NGHTTP2_FLAG_END_HEADERS,
11787                     trailer_reqnv, ARRLEN(trailer_reqnv), mem);
11788   CU_ASSERT(0 == rv);
11789
11790   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11791                                 nghttp2_buf_len(&bufs.head->buf));
11792
11793   CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
11794
11795   item = nghttp2_session_get_next_ob_item(session);
11796
11797   CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
11798
11799   CU_ASSERT(0 == nghttp2_session_send(session));
11800
11801   nghttp2_bufs_reset(&bufs);
11802
11803   /* trailer header including pseudo header field is illegal */
11804   rv = pack_headers(&bufs, &deflater, 5, NGHTTP2_FLAG_END_HEADERS, reqnv,
11805                     ARRLEN(reqnv), mem);
11806   CU_ASSERT(0 == rv);
11807
11808   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11809                                 nghttp2_buf_len(&bufs.head->buf));
11810
11811   CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
11812
11813   nghttp2_bufs_reset(&bufs);
11814
11815   rv = pack_headers(&bufs, &deflater, 5, NGHTTP2_FLAG_END_HEADERS, reqnv,
11816                     ARRLEN(reqnv), mem);
11817   CU_ASSERT(0 == rv);
11818
11819   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11820                                 nghttp2_buf_len(&bufs.head->buf));
11821
11822   CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
11823
11824   item = nghttp2_session_get_next_ob_item(session);
11825
11826   CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
11827
11828   CU_ASSERT(0 == nghttp2_session_send(session));
11829
11830   nghttp2_bufs_reset(&bufs);
11831
11832   nghttp2_hd_deflate_free(&deflater);
11833
11834   nghttp2_session_del(session);
11835
11836   nghttp2_bufs_free(&bufs);
11837 }
11838
11839 void test_nghttp2_http_ignore_regular_header(void) {
11840   nghttp2_session *session;
11841   nghttp2_session_callbacks callbacks;
11842   nghttp2_hd_deflater deflater;
11843   nghttp2_mem *mem;
11844   nghttp2_bufs bufs;
11845   ssize_t rv;
11846   my_user_data ud;
11847   const nghttp2_nv bad_reqnv[] = {
11848       MAKE_NV(":authority", "localhost"),
11849       MAKE_NV(":scheme", "https"),
11850       MAKE_NV(":path", "/"),
11851       MAKE_NV(":method", "GET"),
11852       MAKE_NV("foo", "\x0zzz"),
11853       MAKE_NV("bar", "buzz"),
11854   };
11855   const nghttp2_nv bad_ansnv[] = {
11856       MAKE_NV(":authority", "localhost"), MAKE_NV(":scheme", "https"),
11857       MAKE_NV(":path", "/"), MAKE_NV(":method", "GET"), MAKE_NV("bar", "buzz")};
11858   size_t proclen;
11859   size_t i;
11860   nghttp2_outbound_item *item;
11861
11862   mem = nghttp2_mem_default();
11863   frame_pack_bufs_init(&bufs);
11864
11865   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
11866   callbacks.send_callback = null_send_callback;
11867   callbacks.on_header_callback = pause_on_header_callback;
11868
11869   nghttp2_session_server_new(&session, &callbacks, &ud);
11870   nghttp2_hd_deflate_init(&deflater, mem);
11871
11872   rv = pack_headers(&bufs, &deflater, 1,
11873                     NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM,
11874                     bad_reqnv, ARRLEN(bad_reqnv), mem);
11875
11876   CU_ASSERT_FATAL(0 == rv);
11877
11878   nghttp2_hd_deflate_free(&deflater);
11879
11880   proclen = 0;
11881
11882   for (i = 0; i < 4; ++i) {
11883     rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos + proclen,
11884                                   nghttp2_buf_len(&bufs.head->buf) - proclen);
11885     CU_ASSERT_FATAL(rv > 0);
11886     proclen += (size_t)rv;
11887     CU_ASSERT(nghttp2_nv_equal(&bad_ansnv[i], &ud.nv));
11888   }
11889
11890   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos + proclen,
11891                                 nghttp2_buf_len(&bufs.head->buf) - proclen);
11892   CU_ASSERT_FATAL(rv > 0);
11893   /* Without on_invalid_frame_recv_callback, bad header causes stream
11894      reset */
11895   item = nghttp2_session_get_next_ob_item(session);
11896
11897   CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
11898
11899   proclen += (size_t)rv;
11900
11901   CU_ASSERT(nghttp2_buf_len(&bufs.head->buf) == proclen);
11902
11903   nghttp2_session_del(session);
11904
11905   /* use on_invalid_header_callback */
11906   callbacks.on_invalid_header_callback = pause_on_invalid_header_callback;
11907
11908   nghttp2_session_server_new(&session, &callbacks, &ud);
11909
11910   proclen = 0;
11911
11912   ud.invalid_header_cb_called = 0;
11913
11914   for (i = 0; i < 4; ++i) {
11915     rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos + proclen,
11916                                   nghttp2_buf_len(&bufs.head->buf) - proclen);
11917     CU_ASSERT_FATAL(rv > 0);
11918     proclen += (size_t)rv;
11919     CU_ASSERT(nghttp2_nv_equal(&bad_ansnv[i], &ud.nv));
11920   }
11921
11922   CU_ASSERT(0 == ud.invalid_header_cb_called);
11923
11924   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos + proclen,
11925                                 nghttp2_buf_len(&bufs.head->buf) - proclen);
11926
11927   CU_ASSERT_FATAL(rv > 0);
11928   CU_ASSERT(1 == ud.invalid_header_cb_called);
11929   CU_ASSERT(nghttp2_nv_equal(&bad_reqnv[4], &ud.nv));
11930
11931   proclen += (size_t)rv;
11932
11933   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos + proclen,
11934                                 nghttp2_buf_len(&bufs.head->buf) - proclen);
11935
11936   CU_ASSERT(rv > 0);
11937   CU_ASSERT(nghttp2_nv_equal(&bad_ansnv[4], &ud.nv));
11938
11939   nghttp2_session_del(session);
11940
11941   /* make sure that we can reset stream from
11942      on_invalid_header_callback */
11943   callbacks.on_header_callback = on_header_callback;
11944   callbacks.on_invalid_header_callback = reset_on_invalid_header_callback;
11945
11946   nghttp2_session_server_new(&session, &callbacks, &ud);
11947
11948   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11949                                 nghttp2_buf_len(&bufs.head->buf));
11950
11951   CU_ASSERT(rv == (ssize_t)nghttp2_buf_len(&bufs.head->buf));
11952
11953   item = nghttp2_session_get_next_ob_item(session);
11954
11955   CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
11956   CU_ASSERT(1 == item->frame.hd.stream_id);
11957
11958   nghttp2_session_del(session);
11959   nghttp2_bufs_free(&bufs);
11960 }
11961
11962 void test_nghttp2_http_ignore_content_length(void) {
11963   nghttp2_session *session;
11964   nghttp2_session_callbacks callbacks;
11965   nghttp2_hd_deflater deflater;
11966   nghttp2_mem *mem;
11967   nghttp2_bufs bufs;
11968   ssize_t rv;
11969   const nghttp2_nv cl_resnv[] = {MAKE_NV(":status", "304"),
11970                                  MAKE_NV("content-length", "20")};
11971   const nghttp2_nv conn_reqnv[] = {MAKE_NV(":authority", "localhost"),
11972                                    MAKE_NV(":method", "CONNECT"),
11973                                    MAKE_NV("content-length", "999999")};
11974   const nghttp2_nv conn_cl_resnv[] = {MAKE_NV(":status", "200"),
11975                                       MAKE_NV("content-length", "0")};
11976   nghttp2_stream *stream;
11977
11978   mem = nghttp2_mem_default();
11979   frame_pack_bufs_init(&bufs);
11980
11981   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
11982   callbacks.send_callback = null_send_callback;
11983
11984   nghttp2_session_client_new(&session, &callbacks, NULL);
11985
11986   nghttp2_hd_deflate_init(&deflater, mem);
11987
11988   /* If status 304, content-length must be ignored */
11989   open_sent_stream2(session, 1, NGHTTP2_STREAM_OPENING);
11990
11991   rv = pack_headers(&bufs, &deflater, 1,
11992                     NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM,
11993                     cl_resnv, ARRLEN(cl_resnv), mem);
11994   CU_ASSERT(0 == rv);
11995
11996   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11997                                 nghttp2_buf_len(&bufs.head->buf));
11998
11999   CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
12000
12001   CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
12002
12003   nghttp2_bufs_reset(&bufs);
12004
12005   /* Content-Length in 200 response to CONNECT is ignored */
12006   stream = open_sent_stream2(session, 3, NGHTTP2_STREAM_OPENING);
12007   stream->http_flags |= NGHTTP2_HTTP_FLAG_METH_CONNECT;
12008
12009   rv = pack_headers(&bufs, &deflater, 3, NGHTTP2_FLAG_END_HEADERS,
12010                     conn_cl_resnv, ARRLEN(conn_cl_resnv), mem);
12011   CU_ASSERT(0 == rv);
12012
12013   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
12014                                 nghttp2_buf_len(&bufs.head->buf));
12015
12016   CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
12017
12018   CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
12019   CU_ASSERT(-1 == stream->content_length);
12020
12021   nghttp2_bufs_reset(&bufs);
12022
12023   nghttp2_hd_deflate_free(&deflater);
12024   nghttp2_session_del(session);
12025
12026   /* If request method is CONNECT, content-length must be ignored */
12027   nghttp2_session_server_new(&session, &callbacks, NULL);
12028
12029   nghttp2_hd_deflate_init(&deflater, mem);
12030
12031   rv = pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, conn_reqnv,
12032                     ARRLEN(conn_reqnv), mem);
12033
12034   CU_ASSERT(0 == rv);
12035
12036   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
12037                                 nghttp2_buf_len(&bufs.head->buf));
12038
12039   CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
12040
12041   CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
12042
12043   stream = nghttp2_session_get_stream(session, 1);
12044
12045   CU_ASSERT(-1 == stream->content_length);
12046   CU_ASSERT((stream->http_flags & NGHTTP2_HTTP_FLAG_METH_CONNECT) > 0);
12047
12048   nghttp2_hd_deflate_free(&deflater);
12049   nghttp2_session_del(session);
12050   nghttp2_bufs_free(&bufs);
12051 }
12052
12053 void test_nghttp2_http_record_request_method(void) {
12054   nghttp2_session *session;
12055   nghttp2_session_callbacks callbacks;
12056   const nghttp2_nv conn_reqnv[] = {MAKE_NV(":method", "CONNECT"),
12057                                    MAKE_NV(":authority", "localhost")};
12058   const nghttp2_nv conn_resnv[] = {MAKE_NV(":status", "200"),
12059                                    MAKE_NV("content-length", "9999")};
12060   nghttp2_stream *stream;
12061   ssize_t rv;
12062   nghttp2_bufs bufs;
12063   nghttp2_hd_deflater deflater;
12064   nghttp2_mem *mem;
12065   nghttp2_outbound_item *item;
12066
12067   mem = nghttp2_mem_default();
12068   frame_pack_bufs_init(&bufs);
12069
12070   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
12071   callbacks.send_callback = null_send_callback;
12072
12073   nghttp2_session_client_new(&session, &callbacks, NULL);
12074
12075   nghttp2_hd_deflate_init(&deflater, mem);
12076
12077   CU_ASSERT(1 == nghttp2_submit_request(session, NULL, conn_reqnv,
12078                                         ARRLEN(conn_reqnv), NULL, NULL));
12079
12080   CU_ASSERT(0 == nghttp2_session_send(session));
12081
12082   stream = nghttp2_session_get_stream(session, 1);
12083
12084   CU_ASSERT(NGHTTP2_HTTP_FLAG_METH_CONNECT == stream->http_flags);
12085
12086   rv = pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, conn_resnv,
12087                     ARRLEN(conn_resnv), mem);
12088   CU_ASSERT(0 == rv);
12089
12090   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
12091                                 nghttp2_buf_len(&bufs.head->buf));
12092
12093   CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
12094
12095   CU_ASSERT((NGHTTP2_HTTP_FLAG_METH_CONNECT & stream->http_flags) > 0);
12096   CU_ASSERT(-1 == stream->content_length);
12097
12098   /* content-length is ignored in 200 response to a CONNECT request */
12099   item = nghttp2_session_get_next_ob_item(session);
12100
12101   CU_ASSERT(NULL == item);
12102
12103   nghttp2_hd_deflate_free(&deflater);
12104   nghttp2_session_del(session);
12105   nghttp2_bufs_free(&bufs);
12106 }
12107
12108 void test_nghttp2_http_push_promise(void) {
12109   nghttp2_session *session;
12110   nghttp2_session_callbacks callbacks;
12111   nghttp2_hd_deflater deflater;
12112   nghttp2_mem *mem;
12113   nghttp2_bufs bufs;
12114   ssize_t rv;
12115   nghttp2_stream *stream;
12116   const nghttp2_nv bad_reqnv[] = {MAKE_NV(":method", "GET")};
12117   nghttp2_outbound_item *item;
12118
12119   mem = nghttp2_mem_default();
12120   frame_pack_bufs_init(&bufs);
12121
12122   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
12123   callbacks.send_callback = null_send_callback;
12124
12125   /* good PUSH_PROMISE case */
12126   nghttp2_session_client_new(&session, &callbacks, NULL);
12127
12128   nghttp2_hd_deflate_init(&deflater, mem);
12129
12130   open_sent_stream2(session, 1, NGHTTP2_STREAM_OPENING);
12131
12132   rv = pack_push_promise(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, 2,
12133                          reqnv, ARRLEN(reqnv), mem);
12134   CU_ASSERT(0 == rv);
12135
12136   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
12137                                 nghttp2_buf_len(&bufs.head->buf));
12138
12139   CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
12140
12141   CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
12142
12143   stream = nghttp2_session_get_stream(session, 2);
12144   CU_ASSERT(NULL != stream);
12145
12146   nghttp2_bufs_reset(&bufs);
12147
12148   rv = pack_headers(&bufs, &deflater, 2, NGHTTP2_FLAG_END_HEADERS, resnv,
12149                     ARRLEN(resnv), mem);
12150
12151   CU_ASSERT(0 == rv);
12152
12153   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
12154                                 nghttp2_buf_len(&bufs.head->buf));
12155
12156   CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
12157
12158   CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
12159
12160   CU_ASSERT(200 == stream->status_code);
12161
12162   nghttp2_bufs_reset(&bufs);
12163
12164   /* PUSH_PROMISE lacks mandatory header */
12165   rv = pack_push_promise(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, 4,
12166                          bad_reqnv, ARRLEN(bad_reqnv), mem);
12167
12168   CU_ASSERT(0 == rv);
12169
12170   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
12171                                 nghttp2_buf_len(&bufs.head->buf));
12172
12173   CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
12174
12175   item = nghttp2_session_get_next_ob_item(session);
12176
12177   CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
12178   CU_ASSERT(4 == item->frame.hd.stream_id);
12179
12180   nghttp2_bufs_reset(&bufs);
12181
12182   nghttp2_hd_deflate_free(&deflater);
12183   nghttp2_session_del(session);
12184   nghttp2_bufs_free(&bufs);
12185 }
12186
12187 void test_nghttp2_http_head_method_upgrade_workaround(void) {
12188   nghttp2_session *session;
12189   nghttp2_session_callbacks callbacks;
12190   const nghttp2_nv cl_resnv[] = {MAKE_NV(":status", "200"),
12191                                  MAKE_NV("content-length", "1000000007")};
12192   nghttp2_bufs bufs;
12193   nghttp2_hd_deflater deflater;
12194   nghttp2_mem *mem;
12195   ssize_t rv;
12196   nghttp2_stream *stream;
12197
12198   mem = nghttp2_mem_default();
12199   frame_pack_bufs_init(&bufs);
12200
12201   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
12202   callbacks.send_callback = null_send_callback;
12203
12204   nghttp2_session_client_new(&session, &callbacks, NULL);
12205
12206   nghttp2_hd_deflate_init(&deflater, mem);
12207
12208   nghttp2_session_upgrade(session, NULL, 0, NULL);
12209
12210   rv = pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, cl_resnv,
12211                     ARRLEN(cl_resnv), mem);
12212
12213   CU_ASSERT(0 == rv);
12214
12215   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
12216                                 nghttp2_buf_len(&bufs.head->buf));
12217
12218   CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
12219
12220   stream = nghttp2_session_get_stream(session, 1);
12221
12222   CU_ASSERT(-1 == stream->content_length);
12223
12224   nghttp2_hd_deflate_free(&deflater);
12225   nghttp2_session_del(session);
12226   nghttp2_bufs_free(&bufs);
12227 }