• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "nghttp2_extpri.h"
39 
40 typedef struct {
41   uint8_t buf[65535];
42   size_t length;
43 } accumulator;
44 
45 typedef struct {
46   uint8_t data[8192];
47   uint8_t *datamark;
48   uint8_t *datalimit;
49   size_t feedseq[8192];
50   size_t seqidx;
51 } scripted_data_feed;
52 
53 typedef struct {
54   accumulator *acc;
55   scripted_data_feed *df;
56   int frame_recv_cb_called, invalid_frame_recv_cb_called;
57   uint8_t recv_frame_type;
58   nghttp2_frame_hd recv_frame_hd;
59   int frame_send_cb_called;
60   uint8_t sent_frame_type;
61   int before_frame_send_cb_called;
62   int frame_not_send_cb_called;
63   uint8_t not_sent_frame_type;
64   int not_sent_error;
65   int stream_close_cb_called;
66   uint32_t stream_close_error_code;
67   size_t data_source_length;
68   int32_t stream_id;
69   size_t block_count;
70   int data_chunk_recv_cb_called;
71   const nghttp2_frame *frame;
72   size_t fixed_sendlen;
73   int header_cb_called;
74   int invalid_header_cb_called;
75   int begin_headers_cb_called;
76   nghttp2_nv nv;
77   size_t data_chunk_len;
78   size_t padlen;
79   int begin_frame_cb_called;
80   nghttp2_buf scratchbuf;
81   size_t data_source_read_cb_paused;
82 } my_user_data;
83 
84 static const nghttp2_nv reqnv[] = {
85     MAKE_NV(":method", "GET"),
86     MAKE_NV(":path", "/"),
87     MAKE_NV(":scheme", "https"),
88     MAKE_NV(":authority", "localhost"),
89 };
90 
91 static const nghttp2_nv resnv[] = {
92     MAKE_NV(":status", "200"),
93 };
94 
95 static const nghttp2_nv trailernv[] = {
96     // from http://tools.ietf.org/html/rfc6249#section-7
97     MAKE_NV("digest", "SHA-256="
98                       "MWVkMWQxYTRiMzk5MDQ0MzI3NGU5NDEyZTk5OWY1ZGFmNzgyZTJlODYz"
99                       "YjRjYzFhOTlmNTQwYzI2M2QwM2U2MQ=="),
100 };
101 
scripted_data_feed_init2(scripted_data_feed * df,nghttp2_bufs * bufs)102 static void scripted_data_feed_init2(scripted_data_feed *df,
103                                      nghttp2_bufs *bufs) {
104   nghttp2_buf_chain *ci;
105   nghttp2_buf *buf;
106   uint8_t *ptr;
107   size_t len;
108 
109   memset(df, 0, sizeof(scripted_data_feed));
110   ptr = df->data;
111   len = 0;
112 
113   for (ci = bufs->head; ci; ci = ci->next) {
114     buf = &ci->buf;
115     ptr = nghttp2_cpymem(ptr, buf->pos, nghttp2_buf_len(buf));
116     len += nghttp2_buf_len(buf);
117   }
118 
119   df->datamark = df->data;
120   df->datalimit = df->data + len;
121   df->feedseq[0] = len;
122 }
123 
null_send_callback(nghttp2_session * session,const uint8_t * data,size_t len,int flags,void * user_data)124 static ssize_t null_send_callback(nghttp2_session *session, const uint8_t *data,
125                                   size_t len, int flags, void *user_data) {
126   (void)session;
127   (void)data;
128   (void)flags;
129   (void)user_data;
130 
131   return (ssize_t)len;
132 }
133 
fail_send_callback(nghttp2_session * session,const uint8_t * data,size_t len,int flags,void * user_data)134 static ssize_t fail_send_callback(nghttp2_session *session, const uint8_t *data,
135                                   size_t len, int flags, void *user_data) {
136   (void)session;
137   (void)data;
138   (void)len;
139   (void)flags;
140   (void)user_data;
141 
142   return NGHTTP2_ERR_CALLBACK_FAILURE;
143 }
144 
fixed_bytes_send_callback(nghttp2_session * session,const uint8_t * data,size_t len,int flags,void * user_data)145 static ssize_t fixed_bytes_send_callback(nghttp2_session *session,
146                                          const uint8_t *data, size_t len,
147                                          int flags, void *user_data) {
148   size_t fixed_sendlen = ((my_user_data *)user_data)->fixed_sendlen;
149   (void)session;
150   (void)data;
151   (void)flags;
152 
153   return (ssize_t)(fixed_sendlen < len ? fixed_sendlen : len);
154 }
155 
scripted_recv_callback(nghttp2_session * session,uint8_t * data,size_t len,int flags,void * user_data)156 static ssize_t scripted_recv_callback(nghttp2_session *session, uint8_t *data,
157                                       size_t len, int flags, void *user_data) {
158   scripted_data_feed *df = ((my_user_data *)user_data)->df;
159   size_t wlen = df->feedseq[df->seqidx] > len ? len : df->feedseq[df->seqidx];
160   (void)session;
161   (void)flags;
162 
163   memcpy(data, df->datamark, wlen);
164   df->datamark += wlen;
165   df->feedseq[df->seqidx] -= wlen;
166   if (df->feedseq[df->seqidx] == 0) {
167     ++df->seqidx;
168   }
169   return (ssize_t)wlen;
170 }
171 
eof_recv_callback(nghttp2_session * session,uint8_t * data,size_t len,int flags,void * user_data)172 static ssize_t eof_recv_callback(nghttp2_session *session, uint8_t *data,
173                                  size_t len, int flags, void *user_data) {
174   (void)session;
175   (void)data;
176   (void)len;
177   (void)flags;
178   (void)user_data;
179 
180   return NGHTTP2_ERR_EOF;
181 }
182 
accumulator_send_callback(nghttp2_session * session,const uint8_t * buf,size_t len,int flags,void * user_data)183 static ssize_t accumulator_send_callback(nghttp2_session *session,
184                                          const uint8_t *buf, size_t len,
185                                          int flags, void *user_data) {
186   accumulator *acc = ((my_user_data *)user_data)->acc;
187   (void)session;
188   (void)flags;
189 
190   assert(acc->length + len < sizeof(acc->buf));
191   memcpy(acc->buf + acc->length, buf, len);
192   acc->length += len;
193   return (ssize_t)len;
194 }
195 
on_begin_frame_callback(nghttp2_session * session,const nghttp2_frame_hd * hd,void * user_data)196 static int on_begin_frame_callback(nghttp2_session *session,
197                                    const nghttp2_frame_hd *hd,
198                                    void *user_data) {
199   my_user_data *ud = (my_user_data *)user_data;
200   (void)session;
201   (void)hd;
202 
203   ++ud->begin_frame_cb_called;
204   return 0;
205 }
206 
on_frame_recv_callback(nghttp2_session * session,const nghttp2_frame * frame,void * user_data)207 static int on_frame_recv_callback(nghttp2_session *session,
208                                   const nghttp2_frame *frame, void *user_data) {
209   my_user_data *ud = (my_user_data *)user_data;
210   (void)session;
211 
212   ++ud->frame_recv_cb_called;
213   ud->recv_frame_type = frame->hd.type;
214   ud->recv_frame_hd = frame->hd;
215 
216   return 0;
217 }
218 
on_invalid_frame_recv_callback(nghttp2_session * session,const nghttp2_frame * frame,int lib_error_code,void * user_data)219 static int on_invalid_frame_recv_callback(nghttp2_session *session,
220                                           const nghttp2_frame *frame,
221                                           int lib_error_code, void *user_data) {
222   my_user_data *ud = (my_user_data *)user_data;
223   (void)session;
224   (void)frame;
225   (void)lib_error_code;
226 
227   ++ud->invalid_frame_recv_cb_called;
228   return 0;
229 }
230 
on_frame_send_callback(nghttp2_session * session,const nghttp2_frame * frame,void * user_data)231 static int on_frame_send_callback(nghttp2_session *session,
232                                   const nghttp2_frame *frame, void *user_data) {
233   my_user_data *ud = (my_user_data *)user_data;
234   (void)session;
235 
236   ++ud->frame_send_cb_called;
237   ud->sent_frame_type = frame->hd.type;
238   return 0;
239 }
240 
on_frame_not_send_callback(nghttp2_session * session,const nghttp2_frame * frame,int lib_error,void * user_data)241 static int on_frame_not_send_callback(nghttp2_session *session,
242                                       const nghttp2_frame *frame, int lib_error,
243                                       void *user_data) {
244   my_user_data *ud = (my_user_data *)user_data;
245   (void)session;
246 
247   ++ud->frame_not_send_cb_called;
248   ud->not_sent_frame_type = frame->hd.type;
249   ud->not_sent_error = lib_error;
250   return 0;
251 }
252 
cancel_before_frame_send_callback(nghttp2_session * session,const nghttp2_frame * frame,void * user_data)253 static int cancel_before_frame_send_callback(nghttp2_session *session,
254                                              const nghttp2_frame *frame,
255                                              void *user_data) {
256   my_user_data *ud = (my_user_data *)user_data;
257   (void)session;
258   (void)frame;
259 
260   ++ud->before_frame_send_cb_called;
261   return NGHTTP2_ERR_CANCEL;
262 }
263 
on_data_chunk_recv_callback(nghttp2_session * session,uint8_t flags,int32_t stream_id,const uint8_t * data,size_t len,void * user_data)264 static int on_data_chunk_recv_callback(nghttp2_session *session, uint8_t flags,
265                                        int32_t stream_id, const uint8_t *data,
266                                        size_t len, void *user_data) {
267   my_user_data *ud = (my_user_data *)user_data;
268   (void)session;
269   (void)flags;
270   (void)stream_id;
271   (void)data;
272 
273   ++ud->data_chunk_recv_cb_called;
274   ud->data_chunk_len = len;
275   return 0;
276 }
277 
pause_on_data_chunk_recv_callback(nghttp2_session * session,uint8_t flags,int32_t stream_id,const uint8_t * data,size_t len,void * user_data)278 static int pause_on_data_chunk_recv_callback(nghttp2_session *session,
279                                              uint8_t flags, int32_t stream_id,
280                                              const uint8_t *data, size_t len,
281                                              void *user_data) {
282   my_user_data *ud = (my_user_data *)user_data;
283   (void)session;
284   (void)flags;
285   (void)stream_id;
286   (void)data;
287   (void)len;
288 
289   ++ud->data_chunk_recv_cb_called;
290   return NGHTTP2_ERR_PAUSE;
291 }
292 
select_padding_callback(nghttp2_session * session,const nghttp2_frame * frame,size_t max_payloadlen,void * user_data)293 static ssize_t select_padding_callback(nghttp2_session *session,
294                                        const nghttp2_frame *frame,
295                                        size_t max_payloadlen, void *user_data) {
296   my_user_data *ud = (my_user_data *)user_data;
297   (void)session;
298 
299   return (ssize_t)nghttp2_min(max_payloadlen, frame->hd.length + ud->padlen);
300 }
301 
too_large_data_source_length_callback(nghttp2_session * session,uint8_t frame_type,int32_t stream_id,int32_t session_remote_window_size,int32_t stream_remote_window_size,uint32_t remote_max_frame_size,void * user_data)302 static ssize_t too_large_data_source_length_callback(
303     nghttp2_session *session, uint8_t frame_type, int32_t stream_id,
304     int32_t session_remote_window_size, int32_t stream_remote_window_size,
305     uint32_t remote_max_frame_size, void *user_data) {
306   (void)session;
307   (void)frame_type;
308   (void)stream_id;
309   (void)session_remote_window_size;
310   (void)stream_remote_window_size;
311   (void)remote_max_frame_size;
312   (void)user_data;
313 
314   return NGHTTP2_MAX_FRAME_SIZE_MAX + 1;
315 }
316 
smallest_length_data_source_length_callback(nghttp2_session * session,uint8_t frame_type,int32_t stream_id,int32_t session_remote_window_size,int32_t stream_remote_window_size,uint32_t remote_max_frame_size,void * user_data)317 static ssize_t smallest_length_data_source_length_callback(
318     nghttp2_session *session, uint8_t frame_type, int32_t stream_id,
319     int32_t session_remote_window_size, int32_t stream_remote_window_size,
320     uint32_t remote_max_frame_size, void *user_data) {
321   (void)session;
322   (void)frame_type;
323   (void)stream_id;
324   (void)session_remote_window_size;
325   (void)stream_remote_window_size;
326   (void)remote_max_frame_size;
327   (void)user_data;
328 
329   return 1;
330 }
331 
fixed_length_data_source_read_callback(nghttp2_session * session,int32_t stream_id,uint8_t * buf,size_t len,uint32_t * data_flags,nghttp2_data_source * source,void * user_data)332 static ssize_t fixed_length_data_source_read_callback(
333     nghttp2_session *session, int32_t stream_id, uint8_t *buf, size_t len,
334     uint32_t *data_flags, nghttp2_data_source *source, void *user_data) {
335   my_user_data *ud = (my_user_data *)user_data;
336   size_t wlen;
337   (void)session;
338   (void)stream_id;
339   (void)buf;
340   (void)source;
341 
342   if (len < ud->data_source_length) {
343     wlen = len;
344   } else {
345     wlen = ud->data_source_length;
346   }
347   ud->data_source_length -= wlen;
348   if (ud->data_source_length == 0) {
349     *data_flags |= NGHTTP2_DATA_FLAG_EOF;
350   }
351   return (ssize_t)wlen;
352 }
353 
temporal_failure_data_source_read_callback(nghttp2_session * session,int32_t stream_id,uint8_t * buf,size_t len,uint32_t * data_flags,nghttp2_data_source * source,void * user_data)354 static ssize_t temporal_failure_data_source_read_callback(
355     nghttp2_session *session, int32_t stream_id, uint8_t *buf, size_t len,
356     uint32_t *data_flags, nghttp2_data_source *source, void *user_data) {
357   (void)session;
358   (void)stream_id;
359   (void)buf;
360   (void)len;
361   (void)data_flags;
362   (void)source;
363   (void)user_data;
364 
365   return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
366 }
367 
fail_data_source_read_callback(nghttp2_session * session,int32_t stream_id,uint8_t * buf,size_t len,uint32_t * data_flags,nghttp2_data_source * source,void * user_data)368 static ssize_t fail_data_source_read_callback(nghttp2_session *session,
369                                               int32_t stream_id, uint8_t *buf,
370                                               size_t len, uint32_t *data_flags,
371                                               nghttp2_data_source *source,
372                                               void *user_data) {
373   (void)session;
374   (void)stream_id;
375   (void)buf;
376   (void)len;
377   (void)data_flags;
378   (void)source;
379   (void)user_data;
380 
381   return NGHTTP2_ERR_CALLBACK_FAILURE;
382 }
383 
no_end_stream_data_source_read_callback(nghttp2_session * session,int32_t stream_id,uint8_t * buf,size_t len,uint32_t * data_flags,nghttp2_data_source * source,void * user_data)384 static ssize_t no_end_stream_data_source_read_callback(
385     nghttp2_session *session, int32_t stream_id, uint8_t *buf, size_t len,
386     uint32_t *data_flags, nghttp2_data_source *source, void *user_data) {
387   (void)session;
388   (void)stream_id;
389   (void)buf;
390   (void)len;
391   (void)source;
392   (void)user_data;
393 
394   *data_flags |= NGHTTP2_DATA_FLAG_EOF | NGHTTP2_DATA_FLAG_NO_END_STREAM;
395   return 0;
396 }
397 
no_copy_data_source_read_callback(nghttp2_session * session,int32_t stream_id,uint8_t * buf,size_t len,uint32_t * data_flags,nghttp2_data_source * source,void * user_data)398 static ssize_t no_copy_data_source_read_callback(
399     nghttp2_session *session, int32_t stream_id, uint8_t *buf, size_t len,
400     uint32_t *data_flags, nghttp2_data_source *source, void *user_data) {
401   my_user_data *ud = (my_user_data *)user_data;
402   size_t wlen;
403   (void)session;
404   (void)stream_id;
405   (void)buf;
406   (void)source;
407 
408   if (len < ud->data_source_length) {
409     wlen = len;
410   } else {
411     wlen = ud->data_source_length;
412   }
413 
414   ud->data_source_length -= wlen;
415 
416   *data_flags |= NGHTTP2_DATA_FLAG_NO_COPY;
417 
418   if (ud->data_source_length == 0) {
419     *data_flags |= NGHTTP2_DATA_FLAG_EOF;
420   }
421   return (ssize_t)wlen;
422 }
423 
send_data_callback(nghttp2_session * session,nghttp2_frame * frame,const uint8_t * framehd,size_t length,nghttp2_data_source * source,void * user_data)424 static int send_data_callback(nghttp2_session *session, nghttp2_frame *frame,
425                               const uint8_t *framehd, size_t length,
426                               nghttp2_data_source *source, void *user_data) {
427   accumulator *acc = ((my_user_data *)user_data)->acc;
428   (void)session;
429   (void)source;
430 
431   memcpy(acc->buf + acc->length, framehd, NGHTTP2_FRAME_HDLEN);
432   acc->length += NGHTTP2_FRAME_HDLEN;
433 
434   if (frame->data.padlen) {
435     *(acc->buf + acc->length++) = (uint8_t)(frame->data.padlen - 1);
436   }
437 
438   acc->length += length;
439 
440   if (frame->data.padlen) {
441     acc->length += frame->data.padlen - 1;
442   }
443 
444   return 0;
445 }
446 
block_count_send_callback(nghttp2_session * session,const uint8_t * data,size_t len,int flags,void * user_data)447 static ssize_t block_count_send_callback(nghttp2_session *session,
448                                          const uint8_t *data, size_t len,
449                                          int flags, void *user_data) {
450   my_user_data *ud = (my_user_data *)user_data;
451   (void)session;
452   (void)data;
453   (void)flags;
454 
455   if (ud->block_count == 0) {
456     return NGHTTP2_ERR_WOULDBLOCK;
457   }
458 
459   --ud->block_count;
460   return (ssize_t)len;
461 }
462 
on_header_callback(nghttp2_session * session,const nghttp2_frame * frame,const uint8_t * name,size_t namelen,const uint8_t * value,size_t valuelen,uint8_t flags,void * user_data)463 static int on_header_callback(nghttp2_session *session,
464                               const nghttp2_frame *frame, const uint8_t *name,
465                               size_t namelen, const uint8_t *value,
466                               size_t valuelen, uint8_t flags, void *user_data) {
467   my_user_data *ud = (my_user_data *)user_data;
468   (void)session;
469   (void)flags;
470 
471   ++ud->header_cb_called;
472   ud->nv.name = (uint8_t *)name;
473   ud->nv.namelen = namelen;
474   ud->nv.value = (uint8_t *)value;
475   ud->nv.valuelen = valuelen;
476 
477   ud->frame = frame;
478   return 0;
479 }
480 
pause_on_header_callback(nghttp2_session * session,const nghttp2_frame * frame,const uint8_t * name,size_t namelen,const uint8_t * value,size_t valuelen,uint8_t flags,void * user_data)481 static int pause_on_header_callback(nghttp2_session *session,
482                                     const nghttp2_frame *frame,
483                                     const uint8_t *name, size_t namelen,
484                                     const uint8_t *value, size_t valuelen,
485                                     uint8_t flags, void *user_data) {
486   on_header_callback(session, frame, name, namelen, value, valuelen, flags,
487                      user_data);
488   return NGHTTP2_ERR_PAUSE;
489 }
490 
temporal_failure_on_header_callback(nghttp2_session * session,const nghttp2_frame * frame,const uint8_t * name,size_t namelen,const uint8_t * value,size_t valuelen,uint8_t flags,void * user_data)491 static int temporal_failure_on_header_callback(
492     nghttp2_session *session, const nghttp2_frame *frame, const uint8_t *name,
493     size_t namelen, const uint8_t *value, size_t valuelen, uint8_t flags,
494     void *user_data) {
495   on_header_callback(session, frame, name, namelen, value, valuelen, flags,
496                      user_data);
497   return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
498 }
499 
on_invalid_header_callback(nghttp2_session * session,const nghttp2_frame * frame,const uint8_t * name,size_t namelen,const uint8_t * value,size_t valuelen,uint8_t flags,void * user_data)500 static int on_invalid_header_callback(nghttp2_session *session,
501                                       const nghttp2_frame *frame,
502                                       const uint8_t *name, size_t namelen,
503                                       const uint8_t *value, size_t valuelen,
504                                       uint8_t flags, void *user_data) {
505   my_user_data *ud = (my_user_data *)user_data;
506   (void)session;
507   (void)flags;
508 
509   ++ud->invalid_header_cb_called;
510   ud->nv.name = (uint8_t *)name;
511   ud->nv.namelen = namelen;
512   ud->nv.value = (uint8_t *)value;
513   ud->nv.valuelen = valuelen;
514 
515   ud->frame = frame;
516   return 0;
517 }
518 
pause_on_invalid_header_callback(nghttp2_session * session,const nghttp2_frame * frame,const uint8_t * name,size_t namelen,const uint8_t * value,size_t valuelen,uint8_t flags,void * user_data)519 static int pause_on_invalid_header_callback(nghttp2_session *session,
520                                             const nghttp2_frame *frame,
521                                             const uint8_t *name, size_t namelen,
522                                             const uint8_t *value,
523                                             size_t valuelen, uint8_t flags,
524                                             void *user_data) {
525   on_invalid_header_callback(session, frame, name, namelen, value, valuelen,
526                              flags, user_data);
527   return NGHTTP2_ERR_PAUSE;
528 }
529 
reset_on_invalid_header_callback(nghttp2_session * session,const nghttp2_frame * frame,const uint8_t * name,size_t namelen,const uint8_t * value,size_t valuelen,uint8_t flags,void * user_data)530 static int reset_on_invalid_header_callback(nghttp2_session *session,
531                                             const nghttp2_frame *frame,
532                                             const uint8_t *name, size_t namelen,
533                                             const uint8_t *value,
534                                             size_t valuelen, uint8_t flags,
535                                             void *user_data) {
536   on_invalid_header_callback(session, frame, name, namelen, value, valuelen,
537                              flags, user_data);
538   return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
539 }
540 
on_begin_headers_callback(nghttp2_session * session,const nghttp2_frame * frame,void * user_data)541 static int on_begin_headers_callback(nghttp2_session *session,
542                                      const nghttp2_frame *frame,
543                                      void *user_data) {
544   my_user_data *ud = (my_user_data *)user_data;
545   (void)session;
546   (void)frame;
547 
548   ++ud->begin_headers_cb_called;
549   return 0;
550 }
551 
temporal_failure_on_begin_headers_callback(nghttp2_session * session,const nghttp2_frame * frame,void * user_data)552 static int temporal_failure_on_begin_headers_callback(
553     nghttp2_session *session, const nghttp2_frame *frame, void *user_data) {
554   on_begin_headers_callback(session, frame, user_data);
555   return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
556 }
557 
defer_data_source_read_callback(nghttp2_session * session,int32_t stream_id,uint8_t * buf,size_t len,uint32_t * data_flags,nghttp2_data_source * source,void * user_data)558 static ssize_t defer_data_source_read_callback(nghttp2_session *session,
559                                                int32_t stream_id, uint8_t *buf,
560                                                size_t len, uint32_t *data_flags,
561                                                nghttp2_data_source *source,
562                                                void *user_data) {
563   (void)session;
564   (void)stream_id;
565   (void)buf;
566   (void)len;
567   (void)data_flags;
568   (void)source;
569   (void)user_data;
570 
571   return NGHTTP2_ERR_DEFERRED;
572 }
573 
on_stream_close_callback(nghttp2_session * session,int32_t stream_id,uint32_t error_code,void * user_data)574 static int on_stream_close_callback(nghttp2_session *session, int32_t stream_id,
575                                     uint32_t error_code, 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 
pack_extension_callback(nghttp2_session * session,uint8_t * buf,size_t len,const nghttp2_frame * frame,void * user_data)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 
on_extension_chunk_recv_callback(nghttp2_session * session,const nghttp2_frame_hd * hd,const uint8_t * data,size_t len,void * user_data)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 
cancel_on_extension_chunk_recv_callback(nghttp2_session * session,const nghttp2_frame_hd * hd,const uint8_t * data,size_t len,void * user_data)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 
unpack_extension_callback(nghttp2_session * session,void ** payload,const nghttp2_frame_hd * hd,void * user_data)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 
cancel_unpack_extension_callback(nghttp2_session * session,void ** payload,const nghttp2_frame_hd * hd,void * user_data)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 
dup_iv(const nghttp2_settings_entry * iv,size_t niv)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 
test_nghttp2_session_recv(void)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 
test_nghttp2_session_recv_invalid_stream_id(void)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 
test_nghttp2_session_recv_invalid_frame(void)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 
test_nghttp2_session_recv_eof(void)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 
test_nghttp2_session_recv_data(void)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 
test_nghttp2_session_recv_data_no_auto_flow_control(void)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 
test_nghttp2_session_recv_continuation(void)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 
test_nghttp2_session_recv_headers_with_priority(void)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 
test_nghttp2_session_recv_headers_with_padding(void)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 
response_on_begin_frame_callback(nghttp2_session * session,const nghttp2_frame_hd * hd,void * user_data)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 
test_nghttp2_session_recv_headers_early_response(void)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 
test_nghttp2_session_recv_headers_for_closed_stream(void)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 
test_nghttp2_session_recv_headers_with_extpri(void)1831 void test_nghttp2_session_recv_headers_with_extpri(void) {
1832   nghttp2_session *session;
1833   nghttp2_session_callbacks callbacks;
1834   nghttp2_nv *nva;
1835   size_t nvlen;
1836   nghttp2_frame frame;
1837   nghttp2_bufs bufs;
1838   nghttp2_buf *buf;
1839   ssize_t rv;
1840   nghttp2_hd_deflater deflater;
1841   nghttp2_stream *stream;
1842   nghttp2_mem *mem;
1843   const nghttp2_nv extpri_reqnv[] = {
1844       MAKE_NV(":method", "GET"),    MAKE_NV(":path", "/"),
1845       MAKE_NV(":scheme", "https"),  MAKE_NV(":authority", "localhost"),
1846       MAKE_NV("priority", "i,u=2"),
1847   };
1848   nghttp2_settings_entry iv;
1849 
1850   mem = nghttp2_mem_default();
1851   frame_pack_bufs_init(&bufs);
1852 
1853   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
1854 
1855   nghttp2_session_server_new(&session, &callbacks, NULL);
1856 
1857   iv.settings_id = NGHTTP2_SETTINGS_NO_RFC7540_PRIORITIES;
1858   iv.value = 1;
1859 
1860   nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, &iv, 1);
1861 
1862   nghttp2_hd_deflate_init(&deflater, mem);
1863 
1864   nvlen = ARRLEN(extpri_reqnv);
1865   nghttp2_nv_array_copy(&nva, extpri_reqnv, nvlen, mem);
1866 
1867   nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 1,
1868                              NGHTTP2_HCAT_HEADERS, NULL, nva, nvlen);
1869 
1870   rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
1871 
1872   CU_ASSERT(0 == rv);
1873   CU_ASSERT(nghttp2_bufs_len(&bufs) > 0);
1874 
1875   nghttp2_frame_headers_free(&frame.headers, mem);
1876 
1877   buf = &bufs.head->buf;
1878   assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
1879 
1880   rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
1881 
1882   stream = nghttp2_session_get_stream(session, 1);
1883 
1884   CU_ASSERT(2 == nghttp2_extpri_uint8_urgency(stream->extpri));
1885   CU_ASSERT(1 == nghttp2_extpri_uint8_inc(stream->extpri));
1886 
1887   nghttp2_hd_deflate_free(&deflater);
1888   nghttp2_session_del(session);
1889 
1890   nghttp2_bufs_reset(&bufs);
1891 
1892   /* Client should ignore priority header field included in
1893      PUSH_PROMISE. */
1894   nghttp2_session_client_new(&session, &callbacks, NULL);
1895 
1896   nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, &iv, 1);
1897 
1898   open_sent_stream(session, 1);
1899 
1900   nghttp2_hd_deflate_init(&deflater, mem);
1901 
1902   nvlen = ARRLEN(extpri_reqnv);
1903   nghttp2_nv_array_copy(&nva, extpri_reqnv, nvlen, mem);
1904 
1905   nghttp2_frame_push_promise_init(&frame.push_promise, NGHTTP2_FLAG_END_HEADERS,
1906                                   1, 2, nva, nvlen);
1907 
1908   rv = nghttp2_frame_pack_push_promise(&bufs, &frame.push_promise, &deflater);
1909 
1910   CU_ASSERT(0 == rv);
1911   CU_ASSERT(nghttp2_bufs_len(&bufs) > 0);
1912 
1913   nghttp2_frame_push_promise_free(&frame.push_promise, mem);
1914 
1915   buf = &bufs.head->buf;
1916   assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
1917 
1918   rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
1919 
1920   stream = nghttp2_session_get_stream(session, 2);
1921 
1922   CU_ASSERT(NGHTTP2_EXTPRI_DEFAULT_URGENCY ==
1923             nghttp2_extpri_uint8_urgency(stream->http_extpri));
1924   CU_ASSERT(NGHTTP2_EXTPRI_DEFAULT_URGENCY ==
1925             nghttp2_extpri_uint8_urgency(stream->extpri));
1926 
1927   nghttp2_hd_deflate_free(&deflater);
1928   nghttp2_session_del(session);
1929   nghttp2_bufs_free(&bufs);
1930 }
1931 
test_nghttp2_session_server_recv_push_response(void)1932 void test_nghttp2_session_server_recv_push_response(void) {
1933   nghttp2_session *session;
1934   nghttp2_session_callbacks callbacks;
1935   nghttp2_bufs bufs;
1936   nghttp2_buf *buf;
1937   ssize_t rv;
1938   my_user_data ud;
1939   nghttp2_mem *mem;
1940   nghttp2_frame frame;
1941   nghttp2_hd_deflater deflater;
1942   nghttp2_nv *nva;
1943   size_t nvlen;
1944 
1945   mem = nghttp2_mem_default();
1946   frame_pack_bufs_init(&bufs);
1947 
1948   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
1949   callbacks.on_invalid_frame_recv_callback = on_invalid_frame_recv_callback;
1950 
1951   nghttp2_session_server_new(&session, &callbacks, &ud);
1952 
1953   nghttp2_hd_deflate_init(&deflater, mem);
1954 
1955   open_sent_stream2(session, 2, NGHTTP2_STREAM_RESERVED);
1956 
1957   nvlen = ARRLEN(resnv);
1958   nghttp2_nv_array_copy(&nva, resnv, nvlen, mem);
1959   nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 2,
1960                              NGHTTP2_HCAT_HEADERS, &pri_spec_default, nva,
1961                              nvlen);
1962   rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
1963 
1964   CU_ASSERT(0 == rv);
1965   CU_ASSERT(nghttp2_bufs_len(&bufs) > 0);
1966 
1967   nghttp2_frame_headers_free(&frame.headers, mem);
1968 
1969   buf = &bufs.head->buf;
1970 
1971   ud.invalid_frame_recv_cb_called = 0;
1972 
1973   rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
1974 
1975   CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv);
1976   CU_ASSERT(1 == ud.invalid_frame_recv_cb_called);
1977 
1978   nghttp2_bufs_free(&bufs);
1979   nghttp2_hd_deflate_free(&deflater);
1980   nghttp2_session_del(session);
1981 }
1982 
test_nghttp2_session_recv_premature_headers(void)1983 void test_nghttp2_session_recv_premature_headers(void) {
1984   nghttp2_session *session;
1985   nghttp2_session_callbacks callbacks;
1986   nghttp2_bufs bufs;
1987   nghttp2_buf *buf;
1988   ssize_t rv;
1989   my_user_data ud;
1990   nghttp2_hd_deflater deflater;
1991   nghttp2_outbound_item *item;
1992   nghttp2_mem *mem;
1993   uint32_t payloadlen;
1994 
1995   mem = nghttp2_mem_default();
1996   frame_pack_bufs_init(&bufs);
1997 
1998   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
1999   callbacks.send_callback = null_send_callback;
2000 
2001   nghttp2_session_server_new(&session, &callbacks, &ud);
2002 
2003   nghttp2_hd_deflate_init(&deflater, mem);
2004 
2005   pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, reqnv,
2006                ARRLEN(reqnv), mem);
2007 
2008   buf = &bufs.head->buf;
2009   /* Intentionally feed payload cutting last 1 byte off */
2010   payloadlen = nghttp2_get_uint32(buf->pos) >> 8;
2011   nghttp2_put_uint32be(buf->pos, ((payloadlen - 1) << 8) + buf->pos[3]);
2012   rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf) - 1);
2013 
2014   CU_ASSERT((ssize_t)(nghttp2_buf_len(buf) - 1) == rv);
2015 
2016   item = nghttp2_session_get_next_ob_item(session);
2017 
2018   CU_ASSERT(NULL != item);
2019   CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
2020   CU_ASSERT(NGHTTP2_COMPRESSION_ERROR == item->frame.rst_stream.error_code);
2021   CU_ASSERT(1 == item->frame.hd.stream_id);
2022   CU_ASSERT(0 == nghttp2_session_send(session));
2023 
2024   nghttp2_bufs_reset(&bufs);
2025   nghttp2_hd_deflate_free(&deflater);
2026   nghttp2_session_del(session);
2027 
2028   /* Test for PUSH_PROMISE */
2029   nghttp2_session_client_new(&session, &callbacks, &ud);
2030   nghttp2_hd_deflate_init(&deflater, mem);
2031 
2032   open_sent_stream3(session, 1, NGHTTP2_STREAM_FLAG_NONE, &pri_spec_default,
2033                     NGHTTP2_STREAM_OPENING, NULL);
2034 
2035   rv = pack_push_promise(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, 2,
2036                          reqnv, ARRLEN(reqnv), mem);
2037 
2038   CU_ASSERT(0 == rv);
2039 
2040   buf = &bufs.head->buf;
2041   payloadlen = nghttp2_get_uint32(buf->pos) >> 8;
2042   /* Intentionally feed payload cutting last 1 byte off */
2043   nghttp2_put_uint32be(buf->pos, ((payloadlen - 1) << 8) + buf->pos[3]);
2044   rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf) - 1);
2045 
2046   CU_ASSERT((ssize_t)(nghttp2_buf_len(buf) - 1) == rv);
2047 
2048   item = nghttp2_session_get_next_ob_item(session);
2049 
2050   CU_ASSERT(NULL != item);
2051   CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
2052   CU_ASSERT(NGHTTP2_COMPRESSION_ERROR == item->frame.rst_stream.error_code);
2053   CU_ASSERT(2 == item->frame.hd.stream_id);
2054   CU_ASSERT(0 == nghttp2_session_send(session));
2055 
2056   nghttp2_hd_deflate_free(&deflater);
2057   nghttp2_session_del(session);
2058   nghttp2_bufs_free(&bufs);
2059 }
2060 
test_nghttp2_session_recv_unknown_frame(void)2061 void test_nghttp2_session_recv_unknown_frame(void) {
2062   nghttp2_session *session;
2063   nghttp2_session_callbacks callbacks;
2064   my_user_data ud;
2065   uint8_t data[16384];
2066   size_t datalen;
2067   nghttp2_frame_hd hd;
2068   ssize_t rv;
2069 
2070   nghttp2_frame_hd_init(&hd, 16000, 99, NGHTTP2_FLAG_NONE, 0);
2071 
2072   nghttp2_frame_pack_frame_hd(data, &hd);
2073   datalen = NGHTTP2_FRAME_HDLEN + hd.length;
2074 
2075   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
2076   callbacks.on_frame_recv_callback = on_frame_recv_callback;
2077 
2078   nghttp2_session_server_new(&session, &callbacks, &ud);
2079 
2080   ud.frame_recv_cb_called = 0;
2081 
2082   /* Unknown frame must be ignored */
2083   rv = nghttp2_session_mem_recv(session, data, datalen);
2084 
2085   CU_ASSERT(rv == (ssize_t)datalen);
2086   CU_ASSERT(0 == ud.frame_recv_cb_called);
2087   CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
2088 
2089   nghttp2_session_del(session);
2090 }
2091 
test_nghttp2_session_recv_unexpected_continuation(void)2092 void test_nghttp2_session_recv_unexpected_continuation(void) {
2093   nghttp2_session *session;
2094   nghttp2_session_callbacks callbacks;
2095   my_user_data ud;
2096   uint8_t data[16384];
2097   size_t datalen;
2098   nghttp2_frame_hd hd;
2099   ssize_t rv;
2100   nghttp2_outbound_item *item;
2101 
2102   nghttp2_frame_hd_init(&hd, 16000, NGHTTP2_CONTINUATION,
2103                         NGHTTP2_FLAG_END_HEADERS, 1);
2104 
2105   nghttp2_frame_pack_frame_hd(data, &hd);
2106   datalen = NGHTTP2_FRAME_HDLEN + hd.length;
2107 
2108   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
2109   callbacks.on_frame_recv_callback = on_frame_recv_callback;
2110 
2111   nghttp2_session_server_new(&session, &callbacks, &ud);
2112 
2113   open_recv_stream(session, 1);
2114 
2115   ud.frame_recv_cb_called = 0;
2116 
2117   /* unexpected CONTINUATION must be treated as connection error */
2118   rv = nghttp2_session_mem_recv(session, data, datalen);
2119 
2120   CU_ASSERT(rv == (ssize_t)datalen);
2121   CU_ASSERT(0 == ud.frame_recv_cb_called);
2122 
2123   item = nghttp2_session_get_next_ob_item(session);
2124 
2125   CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
2126 
2127   nghttp2_session_del(session);
2128 }
2129 
test_nghttp2_session_recv_settings_header_table_size(void)2130 void test_nghttp2_session_recv_settings_header_table_size(void) {
2131   nghttp2_session *session;
2132   nghttp2_session_callbacks callbacks;
2133   nghttp2_frame frame;
2134   nghttp2_bufs bufs;
2135   nghttp2_buf *buf;
2136   ssize_t rv;
2137   my_user_data ud;
2138   nghttp2_settings_entry iv[3];
2139   nghttp2_nv nv = MAKE_NV(":authority", "example.org");
2140   nghttp2_mem *mem;
2141 
2142   mem = nghttp2_mem_default();
2143   frame_pack_bufs_init(&bufs);
2144 
2145   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
2146   callbacks.on_frame_recv_callback = on_frame_recv_callback;
2147   callbacks.send_callback = null_send_callback;
2148 
2149   nghttp2_session_client_new(&session, &callbacks, &ud);
2150 
2151   iv[0].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
2152   iv[0].value = 3000;
2153 
2154   iv[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
2155   iv[1].value = 16384;
2156 
2157   nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE, dup_iv(iv, 2),
2158                               2);
2159 
2160   rv = nghttp2_frame_pack_settings(&bufs, &frame.settings);
2161 
2162   CU_ASSERT(0 == rv);
2163   CU_ASSERT(nghttp2_bufs_len(&bufs) > 0);
2164 
2165   nghttp2_frame_settings_free(&frame.settings, mem);
2166 
2167   buf = &bufs.head->buf;
2168   assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
2169 
2170   ud.frame_recv_cb_called = 0;
2171 
2172   rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
2173 
2174   CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv);
2175   CU_ASSERT(1 == ud.frame_recv_cb_called);
2176 
2177   CU_ASSERT(3000 == session->remote_settings.header_table_size);
2178   CU_ASSERT(16384 == session->remote_settings.initial_window_size);
2179 
2180   nghttp2_bufs_reset(&bufs);
2181 
2182   /* 2 SETTINGS_HEADER_TABLE_SIZE */
2183   iv[0].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
2184   iv[0].value = 3001;
2185 
2186   iv[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
2187   iv[1].value = 16383;
2188 
2189   iv[2].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
2190   iv[2].value = 3001;
2191 
2192   nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE, dup_iv(iv, 3),
2193                               3);
2194 
2195   rv = nghttp2_frame_pack_settings(&bufs, &frame.settings);
2196 
2197   CU_ASSERT(0 == rv);
2198   CU_ASSERT(nghttp2_bufs_len(&bufs) > 0);
2199 
2200   nghttp2_frame_settings_free(&frame.settings, mem);
2201 
2202   buf = &bufs.head->buf;
2203   assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
2204 
2205   ud.frame_recv_cb_called = 0;
2206 
2207   rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
2208 
2209   CU_ASSERT((ssize_t)(nghttp2_buf_len(buf)) == rv);
2210   CU_ASSERT(1 == ud.frame_recv_cb_called);
2211 
2212   CU_ASSERT(3001 == session->remote_settings.header_table_size);
2213   CU_ASSERT(16383 == session->remote_settings.initial_window_size);
2214 
2215   nghttp2_bufs_reset(&bufs);
2216 
2217   /* 2 SETTINGS_HEADER_TABLE_SIZE; first entry clears dynamic header
2218      table. */
2219 
2220   nghttp2_submit_request(session, NULL, &nv, 1, NULL, NULL);
2221   nghttp2_session_send(session);
2222 
2223   CU_ASSERT(0 < session->hd_deflater.ctx.hd_table.len);
2224 
2225   iv[0].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
2226   iv[0].value = 0;
2227 
2228   iv[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
2229   iv[1].value = 16382;
2230 
2231   iv[2].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
2232   iv[2].value = 4096;
2233 
2234   nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE, dup_iv(iv, 3),
2235                               3);
2236 
2237   rv = nghttp2_frame_pack_settings(&bufs, &frame.settings);
2238 
2239   CU_ASSERT(0 == rv);
2240   CU_ASSERT(nghttp2_bufs_len(&bufs) > 0);
2241 
2242   nghttp2_frame_settings_free(&frame.settings, mem);
2243 
2244   buf = &bufs.head->buf;
2245   assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
2246 
2247   ud.frame_recv_cb_called = 0;
2248 
2249   rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
2250 
2251   CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv);
2252   CU_ASSERT(1 == ud.frame_recv_cb_called);
2253 
2254   CU_ASSERT(4096 == session->remote_settings.header_table_size);
2255   CU_ASSERT(16382 == session->remote_settings.initial_window_size);
2256   CU_ASSERT(0 == session->hd_deflater.ctx.hd_table.len);
2257 
2258   nghttp2_bufs_reset(&bufs);
2259 
2260   /* 2 SETTINGS_HEADER_TABLE_SIZE; second entry clears dynamic header
2261      table. */
2262 
2263   nghttp2_submit_request(session, NULL, &nv, 1, NULL, NULL);
2264   nghttp2_session_send(session);
2265 
2266   CU_ASSERT(0 < session->hd_deflater.ctx.hd_table.len);
2267 
2268   iv[0].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
2269   iv[0].value = 3000;
2270 
2271   iv[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
2272   iv[1].value = 16381;
2273 
2274   iv[2].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
2275   iv[2].value = 0;
2276 
2277   nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE, dup_iv(iv, 3),
2278                               3);
2279 
2280   rv = nghttp2_frame_pack_settings(&bufs, &frame.settings);
2281 
2282   CU_ASSERT(0 == rv);
2283   CU_ASSERT(nghttp2_bufs_len(&bufs) > 0);
2284 
2285   nghttp2_frame_settings_free(&frame.settings, mem);
2286 
2287   buf = &bufs.head->buf;
2288   assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
2289 
2290   ud.frame_recv_cb_called = 0;
2291 
2292   rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
2293 
2294   CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv);
2295   CU_ASSERT(1 == ud.frame_recv_cb_called);
2296 
2297   CU_ASSERT(0 == session->remote_settings.header_table_size);
2298   CU_ASSERT(16381 == session->remote_settings.initial_window_size);
2299   CU_ASSERT(0 == session->hd_deflater.ctx.hd_table.len);
2300 
2301   nghttp2_bufs_reset(&bufs);
2302 
2303   nghttp2_bufs_free(&bufs);
2304   nghttp2_session_del(session);
2305 }
2306 
test_nghttp2_session_recv_too_large_frame_length(void)2307 void test_nghttp2_session_recv_too_large_frame_length(void) {
2308   nghttp2_session *session;
2309   nghttp2_session_callbacks callbacks;
2310   uint8_t buf[NGHTTP2_FRAME_HDLEN];
2311   nghttp2_outbound_item *item;
2312   nghttp2_frame_hd hd;
2313 
2314   /* Initial max frame size is NGHTTP2_MAX_FRAME_SIZE_MIN */
2315   nghttp2_frame_hd_init(&hd, NGHTTP2_MAX_FRAME_SIZE_MIN + 1, NGHTTP2_HEADERS,
2316                         NGHTTP2_FLAG_NONE, 1);
2317 
2318   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
2319 
2320   nghttp2_session_server_new(&session, &callbacks, NULL);
2321 
2322   nghttp2_frame_pack_frame_hd(buf, &hd);
2323 
2324   CU_ASSERT(sizeof(buf) == nghttp2_session_mem_recv(session, buf, sizeof(buf)));
2325 
2326   item = nghttp2_session_get_next_ob_item(session);
2327 
2328   CU_ASSERT(item != NULL);
2329   CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
2330 
2331   nghttp2_session_del(session);
2332 }
2333 
test_nghttp2_session_recv_extension(void)2334 void test_nghttp2_session_recv_extension(void) {
2335   nghttp2_session *session;
2336   nghttp2_session_callbacks callbacks;
2337   my_user_data ud;
2338   nghttp2_buf buf;
2339   nghttp2_frame_hd hd;
2340   nghttp2_mem *mem;
2341   const char data[] = "Hello World!";
2342   ssize_t rv;
2343   nghttp2_option *option;
2344 
2345   mem = nghttp2_mem_default();
2346 
2347   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
2348 
2349   callbacks.on_extension_chunk_recv_callback = on_extension_chunk_recv_callback;
2350   callbacks.unpack_extension_callback = unpack_extension_callback;
2351   callbacks.on_frame_recv_callback = on_frame_recv_callback;
2352 
2353   nghttp2_option_new(&option);
2354   nghttp2_option_set_user_recv_extension_type(option, 111);
2355 
2356   nghttp2_buf_init2(&ud.scratchbuf, 4096, mem);
2357   nghttp2_buf_init2(&buf, 4096, mem);
2358 
2359   nghttp2_frame_hd_init(&hd, sizeof(data), 111, 0xab, 1000000007);
2360   nghttp2_frame_pack_frame_hd(buf.last, &hd);
2361   buf.last += NGHTTP2_FRAME_HDLEN;
2362   buf.last = nghttp2_cpymem(buf.last, data, sizeof(data));
2363 
2364   nghttp2_session_client_new2(&session, &callbacks, &ud, option);
2365 
2366   nghttp2_frame_hd_init(&ud.recv_frame_hd, 0, 0, 0, 0);
2367   rv = nghttp2_session_mem_recv(session, buf.pos, nghttp2_buf_len(&buf));
2368 
2369   CU_ASSERT(NGHTTP2_FRAME_HDLEN + hd.length == (size_t)rv);
2370   CU_ASSERT(111 == ud.recv_frame_hd.type);
2371   CU_ASSERT(0xab == ud.recv_frame_hd.flags);
2372   CU_ASSERT(1000000007 == ud.recv_frame_hd.stream_id);
2373   CU_ASSERT(0 == memcmp(data, ud.scratchbuf.pos, sizeof(data)));
2374 
2375   nghttp2_session_del(session);
2376 
2377   /* cancel in on_extension_chunk_recv_callback */
2378   nghttp2_buf_reset(&ud.scratchbuf);
2379 
2380   callbacks.on_extension_chunk_recv_callback =
2381       cancel_on_extension_chunk_recv_callback;
2382 
2383   nghttp2_session_server_new2(&session, &callbacks, &ud, option);
2384 
2385   ud.frame_recv_cb_called = 0;
2386   rv = nghttp2_session_mem_recv(session, buf.pos, nghttp2_buf_len(&buf));
2387 
2388   CU_ASSERT(NGHTTP2_FRAME_HDLEN + hd.length == (size_t)rv);
2389   CU_ASSERT(0 == ud.frame_recv_cb_called);
2390 
2391   nghttp2_session_del(session);
2392 
2393   /* cancel in unpack_extension_callback */
2394   nghttp2_buf_reset(&ud.scratchbuf);
2395 
2396   callbacks.on_extension_chunk_recv_callback = on_extension_chunk_recv_callback;
2397   callbacks.unpack_extension_callback = cancel_unpack_extension_callback;
2398 
2399   nghttp2_session_server_new2(&session, &callbacks, &ud, option);
2400 
2401   ud.frame_recv_cb_called = 0;
2402   rv = nghttp2_session_mem_recv(session, buf.pos, nghttp2_buf_len(&buf));
2403 
2404   CU_ASSERT(NGHTTP2_FRAME_HDLEN + hd.length == (size_t)rv);
2405   CU_ASSERT(0 == ud.frame_recv_cb_called);
2406 
2407   nghttp2_session_del(session);
2408 
2409   nghttp2_buf_free(&buf, mem);
2410   nghttp2_buf_free(&ud.scratchbuf, mem);
2411 
2412   nghttp2_option_del(option);
2413 }
2414 
test_nghttp2_session_recv_altsvc(void)2415 void test_nghttp2_session_recv_altsvc(void) {
2416   nghttp2_session *session;
2417   nghttp2_session_callbacks callbacks;
2418   my_user_data ud;
2419   nghttp2_buf buf;
2420   nghttp2_frame_hd hd;
2421   nghttp2_mem *mem;
2422   ssize_t rv;
2423   nghttp2_option *option;
2424   static const uint8_t origin[] = "nghttp2.org";
2425   static const uint8_t field_value[] = "h2=\":443\"";
2426 
2427   mem = nghttp2_mem_default();
2428 
2429   nghttp2_buf_init2(&buf, NGHTTP2_FRAME_HDLEN + NGHTTP2_MAX_FRAME_SIZE_MIN,
2430                     mem);
2431 
2432   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
2433 
2434   callbacks.on_frame_recv_callback = on_frame_recv_callback;
2435   callbacks.on_invalid_frame_recv_callback = on_invalid_frame_recv_callback;
2436 
2437   nghttp2_option_new(&option);
2438   nghttp2_option_set_builtin_recv_extension_type(option, NGHTTP2_ALTSVC);
2439 
2440   nghttp2_session_client_new2(&session, &callbacks, &ud, option);
2441 
2442   nghttp2_frame_hd_init(&hd, 2 + sizeof(origin) - 1 + sizeof(field_value) - 1,
2443                         NGHTTP2_ALTSVC, NGHTTP2_FLAG_NONE, 0);
2444   nghttp2_frame_pack_frame_hd(buf.last, &hd);
2445   buf.last += NGHTTP2_FRAME_HDLEN;
2446   nghttp2_put_uint16be(buf.last, sizeof(origin) - 1);
2447   buf.last += 2;
2448   buf.last = nghttp2_cpymem(buf.last, origin, sizeof(origin) - 1);
2449   buf.last = nghttp2_cpymem(buf.last, field_value, sizeof(field_value) - 1);
2450 
2451   ud.frame_recv_cb_called = 0;
2452   rv = nghttp2_session_mem_recv(session, buf.pos, nghttp2_buf_len(&buf));
2453 
2454   CU_ASSERT((ssize_t)nghttp2_buf_len(&buf) == rv);
2455   CU_ASSERT(1 == ud.frame_recv_cb_called);
2456   CU_ASSERT(NGHTTP2_ALTSVC == ud.recv_frame_hd.type);
2457   CU_ASSERT(NGHTTP2_FLAG_NONE == ud.recv_frame_hd.flags);
2458   CU_ASSERT(0 == ud.recv_frame_hd.stream_id);
2459 
2460   nghttp2_session_del(session);
2461 
2462   /* size of origin is larger than frame length */
2463   nghttp2_buf_reset(&buf);
2464 
2465   nghttp2_session_client_new2(&session, &callbacks, &ud, option);
2466 
2467   nghttp2_frame_hd_init(&hd, 2 + sizeof(origin) - 1 - 1, NGHTTP2_ALTSVC,
2468                         NGHTTP2_FLAG_NONE, 0);
2469   nghttp2_frame_pack_frame_hd(buf.last, &hd);
2470   buf.last += NGHTTP2_FRAME_HDLEN;
2471   nghttp2_put_uint16be(buf.last, sizeof(origin) - 1);
2472   buf.last += 2;
2473   buf.last = nghttp2_cpymem(buf.last, origin, sizeof(origin) - 1 - 1);
2474 
2475   ud.frame_recv_cb_called = 0;
2476   rv = nghttp2_session_mem_recv(session, buf.pos, nghttp2_buf_len(&buf));
2477 
2478   CU_ASSERT((ssize_t)nghttp2_buf_len(&buf) == rv);
2479   CU_ASSERT(0 == ud.frame_recv_cb_called);
2480 
2481   nghttp2_session_del(session);
2482 
2483   /* zero-length value */
2484   nghttp2_buf_reset(&buf);
2485 
2486   nghttp2_session_client_new2(&session, &callbacks, &ud, option);
2487 
2488   nghttp2_frame_hd_init(&hd, 2 + sizeof(origin) - 1, NGHTTP2_ALTSVC,
2489                         NGHTTP2_FLAG_NONE, 0);
2490   nghttp2_frame_pack_frame_hd(buf.last, &hd);
2491   buf.last += NGHTTP2_FRAME_HDLEN;
2492   nghttp2_put_uint16be(buf.last, sizeof(origin) - 1);
2493   buf.last += 2;
2494   buf.last = nghttp2_cpymem(buf.last, origin, sizeof(origin) - 1);
2495 
2496   ud.invalid_frame_recv_cb_called = 0;
2497   rv = nghttp2_session_mem_recv(session, buf.pos, nghttp2_buf_len(&buf));
2498 
2499   CU_ASSERT((ssize_t)nghttp2_buf_len(&buf) == rv);
2500   CU_ASSERT(1 == ud.invalid_frame_recv_cb_called);
2501 
2502   nghttp2_session_del(session);
2503 
2504   /* non-empty origin to a stream other than 0 */
2505   nghttp2_buf_reset(&buf);
2506 
2507   nghttp2_session_client_new2(&session, &callbacks, &ud, option);
2508 
2509   open_sent_stream(session, 1);
2510 
2511   nghttp2_frame_hd_init(&hd, 2 + sizeof(origin) - 1 + sizeof(field_value) - 1,
2512                         NGHTTP2_ALTSVC, NGHTTP2_FLAG_NONE, 1);
2513   nghttp2_frame_pack_frame_hd(buf.last, &hd);
2514   buf.last += NGHTTP2_FRAME_HDLEN;
2515   nghttp2_put_uint16be(buf.last, sizeof(origin) - 1);
2516   buf.last += 2;
2517   buf.last = nghttp2_cpymem(buf.last, origin, sizeof(origin) - 1);
2518   buf.last = nghttp2_cpymem(buf.last, field_value, sizeof(field_value) - 1);
2519 
2520   ud.invalid_frame_recv_cb_called = 0;
2521   rv = nghttp2_session_mem_recv(session, buf.pos, nghttp2_buf_len(&buf));
2522 
2523   CU_ASSERT((ssize_t)nghttp2_buf_len(&buf) == rv);
2524   CU_ASSERT(1 == ud.invalid_frame_recv_cb_called);
2525 
2526   nghttp2_session_del(session);
2527 
2528   /* empty origin to stream 0 */
2529   nghttp2_buf_reset(&buf);
2530 
2531   nghttp2_session_client_new2(&session, &callbacks, &ud, option);
2532 
2533   nghttp2_frame_hd_init(&hd, 2 + sizeof(field_value) - 1, NGHTTP2_ALTSVC,
2534                         NGHTTP2_FLAG_NONE, 0);
2535   nghttp2_frame_pack_frame_hd(buf.last, &hd);
2536   buf.last += NGHTTP2_FRAME_HDLEN;
2537   nghttp2_put_uint16be(buf.last, 0);
2538   buf.last += 2;
2539   buf.last = nghttp2_cpymem(buf.last, field_value, sizeof(field_value) - 1);
2540 
2541   ud.invalid_frame_recv_cb_called = 0;
2542   rv = nghttp2_session_mem_recv(session, buf.pos, nghttp2_buf_len(&buf));
2543 
2544   CU_ASSERT((ssize_t)nghttp2_buf_len(&buf) == rv);
2545   CU_ASSERT(1 == ud.invalid_frame_recv_cb_called);
2546 
2547   nghttp2_session_del(session);
2548 
2549   /* send large frame (16KiB) */
2550   nghttp2_buf_reset(&buf);
2551 
2552   nghttp2_session_client_new2(&session, &callbacks, &ud, option);
2553 
2554   nghttp2_frame_hd_init(&hd, NGHTTP2_MAX_FRAME_SIZE_MIN, NGHTTP2_ALTSVC,
2555                         NGHTTP2_FLAG_NONE, 0);
2556   nghttp2_frame_pack_frame_hd(buf.last, &hd);
2557   buf.last += NGHTTP2_FRAME_HDLEN;
2558   nghttp2_put_uint16be(buf.last, sizeof(origin) - 1);
2559   buf.last += 2;
2560   buf.last = nghttp2_cpymem(buf.last, origin, sizeof(origin) - 1);
2561   memset(buf.last, 0, nghttp2_buf_avail(&buf));
2562   buf.last += nghttp2_buf_avail(&buf);
2563 
2564   ud.frame_recv_cb_called = 0;
2565   rv = nghttp2_session_mem_recv(session, buf.pos, nghttp2_buf_len(&buf));
2566 
2567   CU_ASSERT((ssize_t)nghttp2_buf_len(&buf) == rv);
2568   CU_ASSERT(1 == ud.frame_recv_cb_called);
2569   CU_ASSERT(NGHTTP2_ALTSVC == ud.recv_frame_hd.type);
2570   CU_ASSERT(NGHTTP2_MAX_FRAME_SIZE_MIN == ud.recv_frame_hd.length);
2571 
2572   nghttp2_session_del(session);
2573 
2574   /* send too large frame */
2575   nghttp2_buf_reset(&buf);
2576 
2577   nghttp2_session_client_new2(&session, &callbacks, &ud, option);
2578 
2579   session->local_settings.max_frame_size = NGHTTP2_MAX_FRAME_SIZE_MIN - 1;
2580 
2581   nghttp2_frame_hd_init(&hd, NGHTTP2_MAX_FRAME_SIZE_MIN + 1, NGHTTP2_ALTSVC,
2582                         NGHTTP2_FLAG_NONE, 0);
2583   nghttp2_frame_pack_frame_hd(buf.last, &hd);
2584   buf.last += NGHTTP2_FRAME_HDLEN;
2585   nghttp2_put_uint16be(buf.last, sizeof(origin) - 1);
2586   buf.last += 2;
2587   buf.last = nghttp2_cpymem(buf.last, origin, sizeof(origin) - 1);
2588   memset(buf.last, 0, nghttp2_buf_avail(&buf));
2589   buf.last += nghttp2_buf_avail(&buf);
2590 
2591   ud.frame_recv_cb_called = 0;
2592   rv = nghttp2_session_mem_recv(session, buf.pos, nghttp2_buf_len(&buf));
2593 
2594   CU_ASSERT((ssize_t)nghttp2_buf_len(&buf) == rv);
2595   CU_ASSERT(0 == ud.frame_recv_cb_called);
2596 
2597   nghttp2_session_del(session);
2598 
2599   /* received by server */
2600   nghttp2_buf_reset(&buf);
2601 
2602   nghttp2_session_server_new2(&session, &callbacks, &ud, option);
2603 
2604   nghttp2_frame_hd_init(&hd, 2 + sizeof(origin) - 1 + sizeof(field_value) - 1,
2605                         NGHTTP2_ALTSVC, NGHTTP2_FLAG_NONE, 0);
2606   nghttp2_frame_pack_frame_hd(buf.last, &hd);
2607   buf.last += NGHTTP2_FRAME_HDLEN;
2608   nghttp2_put_uint16be(buf.last, sizeof(origin) - 1);
2609   buf.last += 2;
2610   buf.last = nghttp2_cpymem(buf.last, origin, sizeof(origin) - 1);
2611   buf.last = nghttp2_cpymem(buf.last, field_value, sizeof(field_value) - 1);
2612 
2613   ud.frame_recv_cb_called = 0;
2614   rv = nghttp2_session_mem_recv(session, buf.pos, nghttp2_buf_len(&buf));
2615 
2616   CU_ASSERT((ssize_t)nghttp2_buf_len(&buf) == rv);
2617   CU_ASSERT(0 == ud.frame_recv_cb_called);
2618 
2619   nghttp2_session_del(session);
2620 
2621   nghttp2_buf_free(&buf, mem);
2622   nghttp2_option_del(option);
2623 }
2624 
test_nghttp2_session_recv_origin(void)2625 void test_nghttp2_session_recv_origin(void) {
2626   nghttp2_session *session;
2627   nghttp2_session_callbacks callbacks;
2628   my_user_data ud;
2629   nghttp2_bufs bufs;
2630   ssize_t rv;
2631   nghttp2_option *option;
2632   nghttp2_extension frame;
2633   nghttp2_ext_origin origin;
2634   nghttp2_origin_entry ov;
2635   static const uint8_t nghttp2[] = "https://nghttp2.org";
2636 
2637   frame_pack_bufs_init(&bufs);
2638 
2639   frame.payload = &origin;
2640 
2641   ov.origin = (uint8_t *)nghttp2;
2642   ov.origin_len = sizeof(nghttp2) - 1;
2643 
2644   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
2645 
2646   callbacks.on_frame_recv_callback = on_frame_recv_callback;
2647 
2648   nghttp2_option_new(&option);
2649   nghttp2_option_set_builtin_recv_extension_type(option, NGHTTP2_ORIGIN);
2650 
2651   nghttp2_session_client_new2(&session, &callbacks, &ud, option);
2652 
2653   nghttp2_frame_origin_init(&frame, &ov, 1);
2654 
2655   rv = nghttp2_frame_pack_origin(&bufs, &frame);
2656 
2657   CU_ASSERT(0 == rv);
2658 
2659   ud.frame_recv_cb_called = 0;
2660   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
2661                                 nghttp2_bufs_len(&bufs));
2662 
2663   CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == rv);
2664   CU_ASSERT(1 == ud.frame_recv_cb_called);
2665   CU_ASSERT(NGHTTP2_ORIGIN == ud.recv_frame_hd.type);
2666   CU_ASSERT(NGHTTP2_FLAG_NONE == ud.recv_frame_hd.flags);
2667   CU_ASSERT(0 == ud.recv_frame_hd.stream_id);
2668 
2669   nghttp2_session_del(session);
2670   nghttp2_bufs_reset(&bufs);
2671 
2672   /* The length of origin is larger than payload length. */
2673   nghttp2_session_client_new2(&session, &callbacks, &ud, option);
2674 
2675   nghttp2_frame_origin_init(&frame, &ov, 1);
2676   rv = nghttp2_frame_pack_origin(&bufs, &frame);
2677 
2678   CU_ASSERT(0 == rv);
2679 
2680   nghttp2_put_uint16be(bufs.head->buf.pos + NGHTTP2_FRAME_HDLEN,
2681                        (uint16_t)sizeof(nghttp2));
2682 
2683   ud.frame_recv_cb_called = 0;
2684   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
2685                                 nghttp2_bufs_len(&bufs));
2686 
2687   CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == rv);
2688   CU_ASSERT(0 == ud.frame_recv_cb_called);
2689 
2690   nghttp2_session_del(session);
2691   nghttp2_bufs_reset(&bufs);
2692 
2693   /* A frame should be ignored if it is sent to a stream other than
2694      stream 0. */
2695   nghttp2_session_client_new2(&session, &callbacks, &ud, option);
2696 
2697   nghttp2_frame_origin_init(&frame, &ov, 1);
2698   frame.hd.stream_id = 1;
2699   rv = nghttp2_frame_pack_origin(&bufs, &frame);
2700 
2701   CU_ASSERT(0 == rv);
2702 
2703   ud.frame_recv_cb_called = 0;
2704   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
2705                                 nghttp2_bufs_len(&bufs));
2706 
2707   CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == rv);
2708   CU_ASSERT(0 == ud.frame_recv_cb_called);
2709 
2710   nghttp2_session_del(session);
2711   nghttp2_bufs_reset(&bufs);
2712 
2713   /* A frame should be ignored if the reserved flag is set */
2714   nghttp2_session_client_new2(&session, &callbacks, &ud, option);
2715 
2716   nghttp2_frame_origin_init(&frame, &ov, 1);
2717   frame.hd.flags = 0xf0;
2718   rv = nghttp2_frame_pack_origin(&bufs, &frame);
2719 
2720   CU_ASSERT(0 == rv);
2721 
2722   ud.frame_recv_cb_called = 0;
2723   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
2724                                 nghttp2_bufs_len(&bufs));
2725 
2726   CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == rv);
2727   CU_ASSERT(0 == ud.frame_recv_cb_called);
2728 
2729   nghttp2_session_del(session);
2730   nghttp2_bufs_reset(&bufs);
2731 
2732   /* A frame should be ignored if it is received by a server. */
2733   nghttp2_session_server_new2(&session, &callbacks, &ud, option);
2734 
2735   nghttp2_frame_origin_init(&frame, &ov, 1);
2736   rv = nghttp2_frame_pack_origin(&bufs, &frame);
2737 
2738   CU_ASSERT(0 == rv);
2739 
2740   ud.frame_recv_cb_called = 0;
2741   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
2742                                 nghttp2_bufs_len(&bufs));
2743 
2744   CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == rv);
2745   CU_ASSERT(0 == ud.frame_recv_cb_called);
2746 
2747   nghttp2_session_del(session);
2748   nghttp2_bufs_reset(&bufs);
2749 
2750   /* Receiving empty ORIGIN frame */
2751   nghttp2_session_client_new2(&session, &callbacks, &ud, option);
2752 
2753   nghttp2_frame_origin_init(&frame, NULL, 0);
2754   rv = nghttp2_frame_pack_origin(&bufs, &frame);
2755 
2756   CU_ASSERT(0 == rv);
2757 
2758   ud.frame_recv_cb_called = 0;
2759   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
2760                                 nghttp2_bufs_len(&bufs));
2761 
2762   CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == rv);
2763   CU_ASSERT(1 == ud.frame_recv_cb_called);
2764   CU_ASSERT(NGHTTP2_ORIGIN == ud.recv_frame_hd.type);
2765 
2766   nghttp2_session_del(session);
2767 
2768   nghttp2_option_del(option);
2769   nghttp2_bufs_free(&bufs);
2770 }
2771 
test_nghttp2_session_recv_priority_update(void)2772 void test_nghttp2_session_recv_priority_update(void) {
2773   nghttp2_session *session;
2774   nghttp2_session_callbacks callbacks;
2775   my_user_data ud;
2776   nghttp2_bufs bufs;
2777   ssize_t rv;
2778   nghttp2_option *option;
2779   nghttp2_extension frame;
2780   nghttp2_ext_priority_update priority_update;
2781   nghttp2_stream *stream;
2782   nghttp2_hd_deflater deflater;
2783   nghttp2_mem *mem;
2784   uint8_t large_field_value[sizeof(session->iframe.raw_sbuf) + 1];
2785   nghttp2_outbound_item *item;
2786   size_t i;
2787   int32_t stream_id;
2788   static const uint8_t field_value[] = "u=2,i";
2789 
2790   mem = nghttp2_mem_default();
2791 
2792   memset(large_field_value, ' ', sizeof(large_field_value));
2793   memcpy(large_field_value, field_value, sizeof(field_value) - 1);
2794 
2795   frame_pack_bufs_init(&bufs);
2796 
2797   frame.payload = &priority_update;
2798 
2799   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
2800 
2801   callbacks.on_frame_recv_callback = on_frame_recv_callback;
2802 
2803   nghttp2_option_new(&option);
2804   nghttp2_option_set_builtin_recv_extension_type(option,
2805                                                  NGHTTP2_PRIORITY_UPDATE);
2806 
2807   nghttp2_session_server_new2(&session, &callbacks, &ud, option);
2808 
2809   session->pending_no_rfc7540_priorities = 1;
2810 
2811   nghttp2_frame_priority_update_init(&frame, 1, (uint8_t *)field_value,
2812                                      sizeof(field_value) - 1);
2813 
2814   nghttp2_frame_pack_priority_update(&bufs, &frame);
2815 
2816   open_recv_stream(session, 1);
2817 
2818   ud.frame_recv_cb_called = 0;
2819   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
2820                                 nghttp2_bufs_len(&bufs));
2821 
2822   CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == rv);
2823   CU_ASSERT(1 == ud.frame_recv_cb_called);
2824   CU_ASSERT(NGHTTP2_PRIORITY_UPDATE == ud.recv_frame_hd.type);
2825   CU_ASSERT(NGHTTP2_FLAG_NONE == ud.recv_frame_hd.flags);
2826   CU_ASSERT(0 == ud.recv_frame_hd.stream_id);
2827 
2828   stream = nghttp2_session_get_stream_raw(session, 1);
2829 
2830   CU_ASSERT(2 == nghttp2_extpri_uint8_urgency(stream->extpri));
2831   CU_ASSERT(1 == nghttp2_extpri_uint8_inc(stream->extpri));
2832 
2833   nghttp2_session_del(session);
2834   nghttp2_bufs_reset(&bufs);
2835 
2836   /* Check that priority which is received in idle state is
2837      retained. */
2838   nghttp2_session_server_new2(&session, &callbacks, &ud, option);
2839 
2840   session->pending_no_rfc7540_priorities = 1;
2841 
2842   nghttp2_frame_priority_update_init(&frame, 1, (uint8_t *)field_value,
2843                                      sizeof(field_value) - 1);
2844 
2845   nghttp2_frame_pack_priority_update(&bufs, &frame);
2846 
2847   ud.frame_recv_cb_called = 0;
2848   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
2849                                 nghttp2_bufs_len(&bufs));
2850 
2851   CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == rv);
2852   CU_ASSERT(1 == ud.frame_recv_cb_called);
2853   CU_ASSERT(NGHTTP2_PRIORITY_UPDATE == ud.recv_frame_hd.type);
2854   CU_ASSERT(NGHTTP2_FLAG_NONE == ud.recv_frame_hd.flags);
2855   CU_ASSERT(0 == ud.recv_frame_hd.stream_id);
2856 
2857   stream = nghttp2_session_get_stream_raw(session, 1);
2858 
2859   CU_ASSERT(NGHTTP2_STREAM_IDLE == stream->state);
2860   CU_ASSERT(2 == nghttp2_extpri_uint8_urgency(stream->extpri));
2861   CU_ASSERT(1 == nghttp2_extpri_uint8_inc(stream->extpri));
2862 
2863   nghttp2_hd_deflate_init(&deflater, mem);
2864   nghttp2_bufs_reset(&bufs);
2865   rv = pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, reqnv,
2866                     ARRLEN(reqnv), mem);
2867 
2868   CU_ASSERT(0 == rv);
2869 
2870   ud.frame_recv_cb_called = 0;
2871   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
2872                                 nghttp2_bufs_len(&bufs));
2873 
2874   CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == rv);
2875   CU_ASSERT(1 == ud.frame_recv_cb_called);
2876   CU_ASSERT(NGHTTP2_HEADERS == ud.recv_frame_hd.type);
2877   CU_ASSERT(NGHTTP2_STREAM_OPENING == stream->state);
2878   CU_ASSERT(2 == nghttp2_extpri_uint8_urgency(stream->extpri));
2879   CU_ASSERT(1 == nghttp2_extpri_uint8_inc(stream->extpri));
2880 
2881   nghttp2_hd_deflate_free(&deflater);
2882 
2883   nghttp2_session_del(session);
2884   nghttp2_bufs_reset(&bufs);
2885 
2886   /* PRIORITY_UPDATE with too large field_value is discarded */
2887   nghttp2_session_server_new2(&session, &callbacks, &ud, option);
2888 
2889   session->pending_no_rfc7540_priorities = 1;
2890 
2891   nghttp2_frame_priority_update_init(&frame, 1, large_field_value,
2892                                      sizeof(large_field_value));
2893 
2894   nghttp2_frame_pack_priority_update(&bufs, &frame);
2895 
2896   open_recv_stream(session, 1);
2897 
2898   ud.frame_recv_cb_called = 0;
2899   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
2900                                 nghttp2_bufs_len(&bufs));
2901 
2902   CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == rv);
2903   CU_ASSERT(0 == ud.frame_recv_cb_called);
2904 
2905   stream = nghttp2_session_get_stream_raw(session, 1);
2906 
2907   CU_ASSERT(NGHTTP2_EXTPRI_DEFAULT_URGENCY == stream->extpri);
2908 
2909   nghttp2_session_del(session);
2910   nghttp2_bufs_reset(&bufs);
2911 
2912   /* Connection error if client receives PRIORITY_UPDATE. */
2913   nghttp2_session_client_new2(&session, &callbacks, &ud, option);
2914 
2915   session->pending_no_rfc7540_priorities = 1;
2916 
2917   nghttp2_frame_priority_update_init(&frame, 1, (uint8_t *)field_value,
2918                                      sizeof(field_value) - 1);
2919 
2920   nghttp2_frame_pack_priority_update(&bufs, &frame);
2921 
2922   open_sent_stream(session, 1);
2923 
2924   ud.frame_recv_cb_called = 0;
2925   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
2926                                 nghttp2_bufs_len(&bufs));
2927 
2928   CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == rv);
2929   CU_ASSERT(0 == ud.frame_recv_cb_called);
2930 
2931   item = nghttp2_session_get_next_ob_item(session);
2932   CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
2933   CU_ASSERT(NGHTTP2_PROTOCOL_ERROR == item->frame.goaway.error_code);
2934 
2935   nghttp2_session_del(session);
2936   nghttp2_bufs_reset(&bufs);
2937 
2938   /* The number of idle streams exceeds the maximum. */
2939   nghttp2_session_server_new2(&session, &callbacks, &ud, option);
2940 
2941   session->pending_no_rfc7540_priorities = 1;
2942   session->local_settings.max_concurrent_streams = 100;
2943 
2944   for (i = 0; i < 101; ++i) {
2945     stream_id = (int32_t)(i * 2 + 1);
2946     nghttp2_frame_priority_update_init(
2947         &frame, stream_id, (uint8_t *)field_value, sizeof(field_value) - 1);
2948 
2949     nghttp2_frame_pack_priority_update(&bufs, &frame);
2950 
2951     ud.frame_recv_cb_called = 0;
2952     rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
2953                                   nghttp2_bufs_len(&bufs));
2954 
2955     if (i < 100) {
2956       CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == rv);
2957       CU_ASSERT(1 == ud.frame_recv_cb_called);
2958       CU_ASSERT(NGHTTP2_PRIORITY_UPDATE == ud.recv_frame_hd.type);
2959     } else {
2960       CU_ASSERT(0 == ud.frame_recv_cb_called);
2961     }
2962 
2963     nghttp2_bufs_reset(&bufs);
2964   }
2965 
2966   item = nghttp2_session_get_next_ob_item(session);
2967   CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
2968   CU_ASSERT(NGHTTP2_PROTOCOL_ERROR == item->frame.goaway.error_code);
2969 
2970   nghttp2_session_del(session);
2971   nghttp2_option_del(option);
2972   nghttp2_bufs_free(&bufs);
2973 }
2974 
test_nghttp2_session_continue(void)2975 void test_nghttp2_session_continue(void) {
2976   nghttp2_session *session;
2977   nghttp2_session_callbacks callbacks;
2978   my_user_data user_data;
2979   const nghttp2_nv nv1[] = {MAKE_NV(":method", "GET"), MAKE_NV(":path", "/")};
2980   const nghttp2_nv nv2[] = {MAKE_NV("user-agent", "nghttp2/1.0.0"),
2981                             MAKE_NV("alpha", "bravo")};
2982   nghttp2_bufs bufs;
2983   nghttp2_buf *buf;
2984   size_t framelen1, framelen2;
2985   ssize_t rv;
2986   uint8_t buffer[4096];
2987   nghttp2_buf databuf;
2988   nghttp2_frame frame;
2989   nghttp2_nv *nva;
2990   size_t nvlen;
2991   const nghttp2_frame *recv_frame;
2992   nghttp2_frame_hd data_hd;
2993   nghttp2_hd_deflater deflater;
2994   nghttp2_mem *mem;
2995 
2996   mem = nghttp2_mem_default();
2997   frame_pack_bufs_init(&bufs);
2998   nghttp2_buf_wrap_init(&databuf, buffer, sizeof(buffer));
2999 
3000   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
3001   callbacks.send_callback = null_send_callback;
3002   callbacks.on_frame_recv_callback = on_frame_recv_callback;
3003   callbacks.on_data_chunk_recv_callback = pause_on_data_chunk_recv_callback;
3004   callbacks.on_header_callback = pause_on_header_callback;
3005   callbacks.on_begin_headers_callback = on_begin_headers_callback;
3006 
3007   nghttp2_session_server_new(&session, &callbacks, &user_data);
3008   /* disable strict HTTP layering checks */
3009   session->opt_flags |= NGHTTP2_OPTMASK_NO_HTTP_MESSAGING;
3010 
3011   nghttp2_hd_deflate_init(&deflater, mem);
3012 
3013   /* Make 2 HEADERS frames */
3014   nvlen = ARRLEN(nv1);
3015   nghttp2_nv_array_copy(&nva, nv1, nvlen, mem);
3016   nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 1,
3017                              NGHTTP2_HCAT_HEADERS, NULL, nva, nvlen);
3018   rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
3019 
3020   CU_ASSERT(0 == rv);
3021   CU_ASSERT(nghttp2_bufs_len(&bufs) > 0);
3022 
3023   nghttp2_frame_headers_free(&frame.headers, mem);
3024 
3025   buf = &bufs.head->buf;
3026   assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
3027 
3028   framelen1 = nghttp2_buf_len(buf);
3029   databuf.last = nghttp2_cpymem(databuf.last, buf->pos, nghttp2_buf_len(buf));
3030 
3031   nvlen = ARRLEN(nv2);
3032   nghttp2_nv_array_copy(&nva, nv2, nvlen, mem);
3033   nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 3,
3034                              NGHTTP2_HCAT_HEADERS, NULL, nva, nvlen);
3035   nghttp2_bufs_reset(&bufs);
3036   rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
3037 
3038   CU_ASSERT(0 == rv);
3039   CU_ASSERT(nghttp2_bufs_len(&bufs) > 0);
3040 
3041   nghttp2_frame_headers_free(&frame.headers, mem);
3042 
3043   assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
3044 
3045   framelen2 = nghttp2_buf_len(buf);
3046   databuf.last = nghttp2_cpymem(databuf.last, buf->pos, nghttp2_buf_len(buf));
3047 
3048   /* Receive 1st HEADERS and pause */
3049   user_data.begin_headers_cb_called = 0;
3050   user_data.header_cb_called = 0;
3051   rv =
3052       nghttp2_session_mem_recv(session, databuf.pos, nghttp2_buf_len(&databuf));
3053 
3054   CU_ASSERT(rv >= 0);
3055   databuf.pos += rv;
3056 
3057   recv_frame = user_data.frame;
3058   CU_ASSERT(NGHTTP2_HEADERS == recv_frame->hd.type);
3059   CU_ASSERT(framelen1 - NGHTTP2_FRAME_HDLEN == recv_frame->hd.length);
3060 
3061   CU_ASSERT(1 == user_data.begin_headers_cb_called);
3062   CU_ASSERT(1 == user_data.header_cb_called);
3063 
3064   CU_ASSERT(nghttp2_nv_equal(&nv1[0], &user_data.nv));
3065 
3066   /* get 2nd header field */
3067   user_data.begin_headers_cb_called = 0;
3068   user_data.header_cb_called = 0;
3069   rv =
3070       nghttp2_session_mem_recv(session, databuf.pos, nghttp2_buf_len(&databuf));
3071 
3072   CU_ASSERT(rv >= 0);
3073   databuf.pos += rv;
3074 
3075   CU_ASSERT(0 == user_data.begin_headers_cb_called);
3076   CU_ASSERT(1 == user_data.header_cb_called);
3077 
3078   CU_ASSERT(nghttp2_nv_equal(&nv1[1], &user_data.nv));
3079 
3080   /* will call end_headers_callback and receive 2nd HEADERS and pause */
3081   user_data.begin_headers_cb_called = 0;
3082   user_data.header_cb_called = 0;
3083   rv =
3084       nghttp2_session_mem_recv(session, databuf.pos, nghttp2_buf_len(&databuf));
3085 
3086   CU_ASSERT(rv >= 0);
3087   databuf.pos += rv;
3088 
3089   recv_frame = user_data.frame;
3090   CU_ASSERT(NGHTTP2_HEADERS == recv_frame->hd.type);
3091   CU_ASSERT(framelen2 - NGHTTP2_FRAME_HDLEN == recv_frame->hd.length);
3092 
3093   CU_ASSERT(1 == user_data.begin_headers_cb_called);
3094   CU_ASSERT(1 == user_data.header_cb_called);
3095 
3096   CU_ASSERT(nghttp2_nv_equal(&nv2[0], &user_data.nv));
3097 
3098   /* get 2nd header field */
3099   user_data.begin_headers_cb_called = 0;
3100   user_data.header_cb_called = 0;
3101   rv =
3102       nghttp2_session_mem_recv(session, databuf.pos, nghttp2_buf_len(&databuf));
3103 
3104   CU_ASSERT(rv >= 0);
3105   databuf.pos += rv;
3106 
3107   CU_ASSERT(0 == user_data.begin_headers_cb_called);
3108   CU_ASSERT(1 == user_data.header_cb_called);
3109 
3110   CU_ASSERT(nghttp2_nv_equal(&nv2[1], &user_data.nv));
3111 
3112   /* No input data, frame_recv_callback is called */
3113   user_data.begin_headers_cb_called = 0;
3114   user_data.header_cb_called = 0;
3115   user_data.frame_recv_cb_called = 0;
3116   rv =
3117       nghttp2_session_mem_recv(session, databuf.pos, nghttp2_buf_len(&databuf));
3118 
3119   CU_ASSERT(rv >= 0);
3120   databuf.pos += rv;
3121 
3122   CU_ASSERT(0 == user_data.begin_headers_cb_called);
3123   CU_ASSERT(0 == user_data.header_cb_called);
3124   CU_ASSERT(1 == user_data.frame_recv_cb_called);
3125 
3126   /* Receive DATA */
3127   nghttp2_frame_hd_init(&data_hd, 16, NGHTTP2_DATA, NGHTTP2_FLAG_NONE, 1);
3128 
3129   nghttp2_buf_reset(&databuf);
3130   nghttp2_frame_pack_frame_hd(databuf.pos, &data_hd);
3131 
3132   /* Intentionally specify larger buffer size to see pause is kicked
3133      in. */
3134   databuf.last = databuf.end;
3135 
3136   user_data.frame_recv_cb_called = 0;
3137   rv =
3138       nghttp2_session_mem_recv(session, databuf.pos, nghttp2_buf_len(&databuf));
3139 
3140   CU_ASSERT(16 + NGHTTP2_FRAME_HDLEN == rv);
3141   CU_ASSERT(0 == user_data.frame_recv_cb_called);
3142 
3143   /* Next nghttp2_session_mem_recv invokes on_frame_recv_callback and
3144      pause again in on_data_chunk_recv_callback since we pass same
3145      DATA frame. */
3146   user_data.frame_recv_cb_called = 0;
3147   rv =
3148       nghttp2_session_mem_recv(session, databuf.pos, nghttp2_buf_len(&databuf));
3149   CU_ASSERT(16 + NGHTTP2_FRAME_HDLEN == rv);
3150   CU_ASSERT(1 == user_data.frame_recv_cb_called);
3151 
3152   /* And finally call on_frame_recv_callback with 0 size input */
3153   user_data.frame_recv_cb_called = 0;
3154   rv = nghttp2_session_mem_recv(session, NULL, 0);
3155   CU_ASSERT(0 == rv);
3156   CU_ASSERT(1 == user_data.frame_recv_cb_called);
3157 
3158   nghttp2_bufs_free(&bufs);
3159   nghttp2_hd_deflate_free(&deflater);
3160   nghttp2_session_del(session);
3161 }
3162 
test_nghttp2_session_add_frame(void)3163 void test_nghttp2_session_add_frame(void) {
3164   nghttp2_session *session;
3165   nghttp2_session_callbacks callbacks;
3166   accumulator acc;
3167   my_user_data user_data;
3168   nghttp2_outbound_item *item;
3169   nghttp2_frame *frame;
3170   nghttp2_nv *nva;
3171   size_t nvlen;
3172   nghttp2_mem *mem;
3173 
3174   mem = nghttp2_mem_default();
3175   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
3176   callbacks.send_callback = accumulator_send_callback;
3177 
3178   acc.length = 0;
3179   user_data.acc = &acc;
3180 
3181   CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, &user_data));
3182 
3183   item = mem->malloc(sizeof(nghttp2_outbound_item), NULL);
3184 
3185   nghttp2_outbound_item_init(item);
3186 
3187   frame = &item->frame;
3188 
3189   nvlen = ARRLEN(reqnv);
3190   nghttp2_nv_array_copy(&nva, reqnv, nvlen, mem);
3191 
3192   nghttp2_frame_headers_init(
3193       &frame->headers, NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PRIORITY,
3194       (int32_t)session->next_stream_id, NGHTTP2_HCAT_REQUEST, NULL, nva, nvlen);
3195 
3196   session->next_stream_id += 2;
3197 
3198   CU_ASSERT(0 == nghttp2_session_add_item(session, item));
3199   CU_ASSERT(NULL != nghttp2_outbound_queue_top(&session->ob_syn));
3200   CU_ASSERT(0 == nghttp2_session_send(session));
3201   CU_ASSERT(NGHTTP2_HEADERS == acc.buf[3]);
3202   CU_ASSERT((NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PRIORITY) == acc.buf[4]);
3203   /* check stream id */
3204   CU_ASSERT(1 == nghttp2_get_uint32(&acc.buf[5]));
3205 
3206   nghttp2_session_del(session);
3207 }
3208 
test_nghttp2_session_on_request_headers_received(void)3209 void test_nghttp2_session_on_request_headers_received(void) {
3210   nghttp2_session *session;
3211   nghttp2_session_callbacks callbacks;
3212   my_user_data user_data;
3213   nghttp2_frame frame;
3214   nghttp2_stream *stream;
3215   int32_t stream_id = 1;
3216   nghttp2_nv malformed_nva[] = {MAKE_NV(":path", "\x01")};
3217   nghttp2_nv *nva;
3218   size_t nvlen;
3219   nghttp2_priority_spec pri_spec;
3220   nghttp2_mem *mem;
3221 
3222   mem = nghttp2_mem_default();
3223   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
3224   callbacks.on_begin_headers_callback = on_begin_headers_callback;
3225   callbacks.on_invalid_frame_recv_callback = on_invalid_frame_recv_callback;
3226 
3227   nghttp2_session_server_new(&session, &callbacks, &user_data);
3228 
3229   nghttp2_priority_spec_init(&pri_spec, 0, 255, 0);
3230 
3231   nghttp2_frame_headers_init(
3232       &frame.headers, NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PRIORITY,
3233       stream_id, NGHTTP2_HCAT_REQUEST, &pri_spec, NULL, 0);
3234 
3235   user_data.begin_headers_cb_called = 0;
3236   user_data.invalid_frame_recv_cb_called = 0;
3237 
3238   CU_ASSERT(0 == nghttp2_session_on_request_headers_received(session, &frame));
3239   CU_ASSERT(1 == user_data.begin_headers_cb_called);
3240   stream = nghttp2_session_get_stream(session, stream_id);
3241   CU_ASSERT(NGHTTP2_STREAM_OPENING == stream->state);
3242   CU_ASSERT(255 == stream->weight);
3243 
3244   nghttp2_frame_headers_free(&frame.headers, mem);
3245 
3246   /* More than un-ACKed max concurrent streams leads REFUSED_STREAM */
3247   session->pending_local_max_concurrent_stream = 1;
3248   nghttp2_frame_headers_init(&frame.headers,
3249                              NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PRIORITY,
3250                              3, NGHTTP2_HCAT_HEADERS, NULL, NULL, 0);
3251   user_data.invalid_frame_recv_cb_called = 0;
3252   CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
3253             nghttp2_session_on_request_headers_received(session, &frame));
3254   CU_ASSERT(1 == user_data.invalid_frame_recv_cb_called);
3255   CU_ASSERT(0 == (session->goaway_flags & NGHTTP2_GOAWAY_TERM_ON_SEND));
3256 
3257   nghttp2_frame_headers_free(&frame.headers, mem);
3258   session->local_settings.max_concurrent_streams =
3259       NGHTTP2_DEFAULT_MAX_CONCURRENT_STREAMS;
3260 
3261   /* Stream ID less than or equal to the previously received request
3262      HEADERS is just ignored due to race condition */
3263   nghttp2_frame_headers_init(&frame.headers,
3264                              NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PRIORITY,
3265                              3, NGHTTP2_HCAT_HEADERS, NULL, NULL, 0);
3266   user_data.invalid_frame_recv_cb_called = 0;
3267   CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
3268             nghttp2_session_on_request_headers_received(session, &frame));
3269   CU_ASSERT(0 == user_data.invalid_frame_recv_cb_called);
3270   CU_ASSERT(0 == (session->goaway_flags & NGHTTP2_GOAWAY_TERM_ON_SEND));
3271 
3272   nghttp2_frame_headers_free(&frame.headers, mem);
3273 
3274   /* Stream ID is our side and it is idle stream ID, then treat it as
3275      connection error */
3276   nghttp2_frame_headers_init(&frame.headers,
3277                              NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PRIORITY,
3278                              2, NGHTTP2_HCAT_HEADERS, NULL, NULL, 0);
3279   user_data.invalid_frame_recv_cb_called = 0;
3280   CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
3281             nghttp2_session_on_request_headers_received(session, &frame));
3282   CU_ASSERT(1 == user_data.invalid_frame_recv_cb_called);
3283   CU_ASSERT(session->goaway_flags & NGHTTP2_GOAWAY_TERM_ON_SEND);
3284 
3285   nghttp2_frame_headers_free(&frame.headers, mem);
3286 
3287   nghttp2_session_del(session);
3288 
3289   /* Check malformed headers. The library accept it. */
3290   nghttp2_session_server_new(&session, &callbacks, &user_data);
3291 
3292   nvlen = ARRLEN(malformed_nva);
3293   nghttp2_nv_array_copy(&nva, malformed_nva, nvlen, mem);
3294   nghttp2_frame_headers_init(&frame.headers,
3295                              NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PRIORITY,
3296                              1, NGHTTP2_HCAT_HEADERS, NULL, nva, nvlen);
3297   user_data.begin_headers_cb_called = 0;
3298   user_data.invalid_frame_recv_cb_called = 0;
3299   CU_ASSERT(0 == nghttp2_session_on_request_headers_received(session, &frame));
3300   CU_ASSERT(1 == user_data.begin_headers_cb_called);
3301   CU_ASSERT(0 == user_data.invalid_frame_recv_cb_called);
3302 
3303   nghttp2_frame_headers_free(&frame.headers, mem);
3304 
3305   nghttp2_session_del(session);
3306 
3307   /* Check client side */
3308   nghttp2_session_client_new(&session, &callbacks, &user_data);
3309 
3310   /* Receiving peer's idle stream ID is subject to connection error */
3311   nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 2,
3312                              NGHTTP2_HCAT_REQUEST, NULL, NULL, 0);
3313 
3314   user_data.invalid_frame_recv_cb_called = 0;
3315   CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
3316             nghttp2_session_on_request_headers_received(session, &frame));
3317   CU_ASSERT(1 == user_data.invalid_frame_recv_cb_called);
3318   CU_ASSERT(session->goaway_flags & NGHTTP2_GOAWAY_TERM_ON_SEND);
3319 
3320   nghttp2_frame_headers_free(&frame.headers, mem);
3321 
3322   nghttp2_session_del(session);
3323 
3324   nghttp2_session_client_new(&session, &callbacks, &user_data);
3325 
3326   /* Receiving our's idle stream ID is subject to connection error */
3327   nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 1,
3328                              NGHTTP2_HCAT_REQUEST, NULL, NULL, 0);
3329 
3330   user_data.invalid_frame_recv_cb_called = 0;
3331   CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
3332             nghttp2_session_on_request_headers_received(session, &frame));
3333   CU_ASSERT(1 == user_data.invalid_frame_recv_cb_called);
3334   CU_ASSERT(session->goaway_flags & NGHTTP2_GOAWAY_TERM_ON_SEND);
3335 
3336   nghttp2_frame_headers_free(&frame.headers, mem);
3337 
3338   nghttp2_session_del(session);
3339 
3340   nghttp2_session_client_new(&session, &callbacks, &user_data);
3341 
3342   session->next_stream_id = 5;
3343   session->last_sent_stream_id = 3;
3344 
3345   /* Stream ID which is not idle and not in stream map is just
3346      ignored */
3347   nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 3,
3348                              NGHTTP2_HCAT_REQUEST, NULL, NULL, 0);
3349 
3350   user_data.invalid_frame_recv_cb_called = 0;
3351   CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
3352             nghttp2_session_on_request_headers_received(session, &frame));
3353   CU_ASSERT(0 == user_data.invalid_frame_recv_cb_called);
3354   CU_ASSERT(0 == (session->goaway_flags & NGHTTP2_GOAWAY_TERM_ON_SEND));
3355 
3356   nghttp2_frame_headers_free(&frame.headers, mem);
3357 
3358   nghttp2_session_del(session);
3359 
3360   nghttp2_session_server_new(&session, &callbacks, &user_data);
3361 
3362   /* Stream ID which is equal to local_last_stream_id is ok. */
3363   session->local_last_stream_id = 3;
3364 
3365   nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 3,
3366                              NGHTTP2_HCAT_REQUEST, NULL, NULL, 0);
3367 
3368   CU_ASSERT(0 == nghttp2_session_on_request_headers_received(session, &frame));
3369 
3370   nghttp2_frame_headers_free(&frame.headers, mem);
3371 
3372   /* If GOAWAY has been sent, new stream is ignored */
3373   nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 5,
3374                              NGHTTP2_HCAT_REQUEST, NULL, NULL, 0);
3375 
3376   session->goaway_flags |= NGHTTP2_GOAWAY_SENT;
3377   user_data.invalid_frame_recv_cb_called = 0;
3378   CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
3379             nghttp2_session_on_request_headers_received(session, &frame));
3380   CU_ASSERT(0 == user_data.invalid_frame_recv_cb_called);
3381   CU_ASSERT(0 == (session->goaway_flags & NGHTTP2_GOAWAY_TERM_ON_SEND));
3382 
3383   nghttp2_frame_headers_free(&frame.headers, mem);
3384 
3385   nghttp2_session_del(session);
3386 
3387   nghttp2_session_server_new(&session, &callbacks, &user_data);
3388 
3389   /* HEADERS to closed stream */
3390   stream = open_recv_stream(session, 1);
3391   nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_RD);
3392   nghttp2_session_close_stream(session, 1, NGHTTP2_NO_ERROR);
3393 
3394   nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 1,
3395                              NGHTTP2_HCAT_REQUEST, NULL, NULL, 0);
3396 
3397   CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
3398             nghttp2_session_on_request_headers_received(session, &frame));
3399   CU_ASSERT(session->goaway_flags & NGHTTP2_GOAWAY_TERM_ON_SEND);
3400 
3401   nghttp2_frame_headers_free(&frame.headers, mem);
3402 
3403   nghttp2_session_del(session);
3404 }
3405 
test_nghttp2_session_on_response_headers_received(void)3406 void test_nghttp2_session_on_response_headers_received(void) {
3407   nghttp2_session *session;
3408   nghttp2_session_callbacks callbacks;
3409   my_user_data user_data;
3410   nghttp2_frame frame;
3411   nghttp2_stream *stream;
3412   nghttp2_mem *mem;
3413 
3414   mem = nghttp2_mem_default();
3415   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
3416   callbacks.on_begin_headers_callback = on_begin_headers_callback;
3417   callbacks.on_invalid_frame_recv_callback = on_invalid_frame_recv_callback;
3418 
3419   nghttp2_session_client_new(&session, &callbacks, &user_data);
3420   stream = open_sent_stream2(session, 1, NGHTTP2_STREAM_OPENING);
3421   nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 1,
3422                              NGHTTP2_HCAT_HEADERS, NULL, NULL, 0);
3423 
3424   user_data.begin_headers_cb_called = 0;
3425   user_data.invalid_frame_recv_cb_called = 0;
3426 
3427   CU_ASSERT(0 == nghttp2_session_on_response_headers_received(session, &frame,
3428                                                               stream));
3429   CU_ASSERT(1 == user_data.begin_headers_cb_called);
3430   CU_ASSERT(NGHTTP2_STREAM_OPENED == stream->state);
3431 
3432   nghttp2_frame_headers_free(&frame.headers, mem);
3433   nghttp2_session_del(session);
3434 }
3435 
test_nghttp2_session_on_headers_received(void)3436 void test_nghttp2_session_on_headers_received(void) {
3437   nghttp2_session *session;
3438   nghttp2_session_callbacks callbacks;
3439   my_user_data user_data;
3440   nghttp2_frame frame;
3441   nghttp2_stream *stream;
3442   nghttp2_mem *mem;
3443 
3444   mem = nghttp2_mem_default();
3445   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
3446   callbacks.on_begin_headers_callback = on_begin_headers_callback;
3447   callbacks.on_invalid_frame_recv_callback = on_invalid_frame_recv_callback;
3448 
3449   nghttp2_session_client_new(&session, &callbacks, &user_data);
3450   stream = open_sent_stream2(session, 1, NGHTTP2_STREAM_OPENED);
3451   nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_WR);
3452   nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 1,
3453                              NGHTTP2_HCAT_HEADERS, NULL, NULL, 0);
3454 
3455   user_data.begin_headers_cb_called = 0;
3456   user_data.invalid_frame_recv_cb_called = 0;
3457 
3458   CU_ASSERT(0 == nghttp2_session_on_headers_received(session, &frame, stream));
3459   CU_ASSERT(1 == user_data.begin_headers_cb_called);
3460   CU_ASSERT(NGHTTP2_STREAM_OPENED == stream->state);
3461 
3462   /* stream closed */
3463   frame.hd.flags |= NGHTTP2_FLAG_END_STREAM;
3464 
3465   CU_ASSERT(0 == nghttp2_session_on_headers_received(session, &frame, stream));
3466   CU_ASSERT(2 == user_data.begin_headers_cb_called);
3467 
3468   /* Check to see when NGHTTP2_STREAM_CLOSING, incoming HEADERS is
3469      discarded. */
3470   stream = open_sent_stream2(session, 3, NGHTTP2_STREAM_CLOSING);
3471   frame.hd.stream_id = 3;
3472   frame.hd.flags = NGHTTP2_FLAG_END_HEADERS;
3473   CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
3474             nghttp2_session_on_headers_received(session, &frame, stream));
3475   /* See no counters are updated */
3476   CU_ASSERT(2 == user_data.begin_headers_cb_called);
3477   CU_ASSERT(0 == user_data.invalid_frame_recv_cb_called);
3478 
3479   /* Server initiated stream */
3480   stream = open_recv_stream(session, 2);
3481 
3482   frame.hd.flags = NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM;
3483   frame.hd.stream_id = 2;
3484 
3485   CU_ASSERT(0 == nghttp2_session_on_headers_received(session, &frame, stream));
3486   CU_ASSERT(3 == user_data.begin_headers_cb_called);
3487   CU_ASSERT(NGHTTP2_STREAM_OPENED == stream->state);
3488 
3489   nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_RD);
3490 
3491   /* Further reception of HEADERS is subject to stream error */
3492   CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
3493             nghttp2_session_on_headers_received(session, &frame, stream));
3494   CU_ASSERT(1 == user_data.invalid_frame_recv_cb_called);
3495 
3496   nghttp2_frame_headers_free(&frame.headers, mem);
3497 
3498   nghttp2_session_del(session);
3499 }
3500 
test_nghttp2_session_on_push_response_headers_received(void)3501 void test_nghttp2_session_on_push_response_headers_received(void) {
3502   nghttp2_session *session;
3503   nghttp2_session_callbacks callbacks;
3504   my_user_data user_data;
3505   nghttp2_frame frame;
3506   nghttp2_stream *stream;
3507   nghttp2_outbound_item *item;
3508   nghttp2_mem *mem;
3509 
3510   mem = nghttp2_mem_default();
3511   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
3512   callbacks.send_callback = null_send_callback;
3513   callbacks.on_begin_headers_callback = on_begin_headers_callback;
3514   callbacks.on_invalid_frame_recv_callback = on_invalid_frame_recv_callback;
3515 
3516   nghttp2_session_client_new(&session, &callbacks, &user_data);
3517   stream = open_recv_stream2(session, 2, NGHTTP2_STREAM_RESERVED);
3518   nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 2,
3519                              NGHTTP2_HCAT_HEADERS, NULL, NULL, 0);
3520   /* nghttp2_session_on_push_response_headers_received assumes
3521      stream's state is NGHTTP2_STREAM_RESERVED and session->server is
3522      0. */
3523 
3524   user_data.begin_headers_cb_called = 0;
3525   user_data.invalid_frame_recv_cb_called = 0;
3526 
3527   CU_ASSERT(1 == session->num_incoming_reserved_streams);
3528   CU_ASSERT(0 == nghttp2_session_on_push_response_headers_received(
3529                      session, &frame, stream));
3530   CU_ASSERT(1 == user_data.begin_headers_cb_called);
3531   CU_ASSERT(0 == session->num_incoming_reserved_streams);
3532   CU_ASSERT(NGHTTP2_STREAM_OPENED == stream->state);
3533   CU_ASSERT(1 == session->num_incoming_streams);
3534   CU_ASSERT(0 == (stream->flags & NGHTTP2_STREAM_FLAG_PUSH));
3535 
3536   /* If un-ACKed max concurrent streams limit is exceeded,
3537      RST_STREAMed */
3538   session->pending_local_max_concurrent_stream = 1;
3539   stream = open_recv_stream2(session, 4, NGHTTP2_STREAM_RESERVED);
3540   frame.hd.stream_id = 4;
3541   CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
3542             nghttp2_session_on_push_response_headers_received(session, &frame,
3543                                                               stream));
3544   item = nghttp2_session_get_next_ob_item(session);
3545   CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
3546   CU_ASSERT(NGHTTP2_REFUSED_STREAM == item->frame.rst_stream.error_code);
3547   CU_ASSERT(1 == session->num_incoming_streams);
3548   CU_ASSERT(1 == session->num_incoming_reserved_streams);
3549 
3550   CU_ASSERT(0 == nghttp2_session_send(session));
3551   CU_ASSERT(1 == session->num_incoming_streams);
3552 
3553   /* If ACKed max concurrent streams limit is exceeded, GOAWAY is
3554      issued */
3555   session->local_settings.max_concurrent_streams = 1;
3556 
3557   stream = open_recv_stream2(session, 6, NGHTTP2_STREAM_RESERVED);
3558   frame.hd.stream_id = 6;
3559 
3560   CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
3561             nghttp2_session_on_push_response_headers_received(session, &frame,
3562                                                               stream));
3563   item = nghttp2_session_get_next_ob_item(session);
3564   CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
3565   CU_ASSERT(NGHTTP2_PROTOCOL_ERROR == item->frame.goaway.error_code);
3566   CU_ASSERT(1 == session->num_incoming_streams);
3567   CU_ASSERT(1 == session->num_incoming_reserved_streams);
3568 
3569   nghttp2_frame_headers_free(&frame.headers, mem);
3570   nghttp2_session_del(session);
3571 }
3572 
test_nghttp2_session_on_priority_received(void)3573 void test_nghttp2_session_on_priority_received(void) {
3574   nghttp2_session *session;
3575   nghttp2_session_callbacks callbacks;
3576   my_user_data user_data;
3577   nghttp2_frame frame;
3578   nghttp2_stream *stream, *dep_stream;
3579   nghttp2_priority_spec pri_spec;
3580   nghttp2_outbound_item *item;
3581 
3582   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
3583   callbacks.on_frame_recv_callback = on_frame_recv_callback;
3584   callbacks.on_invalid_frame_recv_callback = on_invalid_frame_recv_callback;
3585 
3586   nghttp2_session_server_new(&session, &callbacks, &user_data);
3587   stream = open_recv_stream(session, 1);
3588 
3589   nghttp2_priority_spec_init(&pri_spec, 0, 2, 0);
3590 
3591   nghttp2_frame_priority_init(&frame.priority, 1, &pri_spec);
3592 
3593   /* depend on stream 0 */
3594   CU_ASSERT(0 == nghttp2_session_on_priority_received(session, &frame));
3595 
3596   CU_ASSERT(2 == stream->weight);
3597 
3598   stream = open_sent_stream(session, 2);
3599   dep_stream = open_recv_stream(session, 3);
3600 
3601   frame.hd.stream_id = 2;
3602 
3603   /* using dependency stream */
3604   nghttp2_priority_spec_init(&frame.priority.pri_spec, 3, 1, 0);
3605 
3606   CU_ASSERT(0 == nghttp2_session_on_priority_received(session, &frame));
3607   CU_ASSERT(dep_stream == stream->dep_prev);
3608 
3609   /* PRIORITY against idle stream */
3610 
3611   frame.hd.stream_id = 100;
3612 
3613   CU_ASSERT(0 == nghttp2_session_on_priority_received(session, &frame));
3614 
3615   stream = nghttp2_session_get_stream_raw(session, frame.hd.stream_id);
3616 
3617   CU_ASSERT(NGHTTP2_STREAM_IDLE == stream->state);
3618   CU_ASSERT(dep_stream == stream->dep_prev);
3619 
3620   nghttp2_frame_priority_free(&frame.priority);
3621   nghttp2_session_del(session);
3622 
3623   /* Check dep_stream_id == stream_id case */
3624   nghttp2_session_server_new(&session, &callbacks, &user_data);
3625   open_recv_stream(session, 1);
3626 
3627   nghttp2_priority_spec_init(&pri_spec, 1, 0, 0);
3628 
3629   nghttp2_frame_priority_init(&frame.priority, 1, &pri_spec);
3630 
3631   CU_ASSERT(0 == nghttp2_session_on_priority_received(session, &frame));
3632 
3633   item = nghttp2_session_get_next_ob_item(session);
3634 
3635   CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
3636 
3637   nghttp2_frame_priority_free(&frame.priority);
3638   nghttp2_session_del(session);
3639 
3640   /* Check again dep_stream_id == stream_id, and stream_id is idle */
3641   nghttp2_session_server_new(&session, &callbacks, &user_data);
3642 
3643   nghttp2_priority_spec_init(&pri_spec, 1, 16, 0);
3644 
3645   nghttp2_frame_priority_init(&frame.priority, 1, &pri_spec);
3646 
3647   CU_ASSERT(0 == nghttp2_session_on_priority_received(session, &frame));
3648 
3649   item = nghttp2_session_get_next_ob_item(session);
3650 
3651   CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
3652 
3653   nghttp2_frame_priority_free(&frame.priority);
3654   nghttp2_session_del(session);
3655 }
3656 
test_nghttp2_session_on_rst_stream_received(void)3657 void test_nghttp2_session_on_rst_stream_received(void) {
3658   nghttp2_session *session;
3659   nghttp2_session_callbacks callbacks;
3660   my_user_data user_data;
3661   nghttp2_frame frame;
3662   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
3663   nghttp2_session_server_new(&session, &callbacks, &user_data);
3664   open_recv_stream(session, 1);
3665 
3666   nghttp2_frame_rst_stream_init(&frame.rst_stream, 1, NGHTTP2_PROTOCOL_ERROR);
3667 
3668   CU_ASSERT(0 == nghttp2_session_on_rst_stream_received(session, &frame));
3669   CU_ASSERT(NULL == nghttp2_session_get_stream(session, 1));
3670 
3671   nghttp2_frame_rst_stream_free(&frame.rst_stream);
3672   nghttp2_session_del(session);
3673 }
3674 
test_nghttp2_session_on_settings_received(void)3675 void test_nghttp2_session_on_settings_received(void) {
3676   nghttp2_session *session;
3677   nghttp2_session_callbacks callbacks;
3678   my_user_data user_data;
3679   nghttp2_stream *stream1, *stream2;
3680   nghttp2_frame frame;
3681   const size_t niv = 5;
3682   nghttp2_settings_entry iv[255];
3683   nghttp2_outbound_item *item;
3684   nghttp2_nv nv = MAKE_NV(":authority", "example.org");
3685   nghttp2_mem *mem;
3686   nghttp2_option *option;
3687   uint8_t data[2048];
3688   nghttp2_frame_hd hd;
3689   int rv;
3690   ssize_t nread;
3691   nghttp2_stream *stream;
3692 
3693   mem = nghttp2_mem_default();
3694 
3695   iv[0].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS;
3696   iv[0].value = 50;
3697 
3698   iv[1].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS;
3699   iv[1].value = 1000000009;
3700 
3701   iv[2].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
3702   iv[2].value = 64 * 1024;
3703 
3704   iv[3].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
3705   iv[3].value = 1024;
3706 
3707   iv[4].settings_id = NGHTTP2_SETTINGS_ENABLE_PUSH;
3708   iv[4].value = 0;
3709 
3710   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
3711   callbacks.send_callback = null_send_callback;
3712 
3713   nghttp2_session_client_new(&session, &callbacks, &user_data);
3714   session->remote_settings.initial_window_size = 16 * 1024;
3715 
3716   stream1 = open_sent_stream(session, 1);
3717   stream2 = open_recv_stream(session, 2);
3718 
3719   /* Set window size for each streams and will see how settings
3720      updates these values */
3721   stream1->remote_window_size = 16 * 1024;
3722   stream2->remote_window_size = -48 * 1024;
3723 
3724   nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE,
3725                               dup_iv(iv, niv), niv);
3726 
3727   CU_ASSERT(0 == nghttp2_session_on_settings_received(session, &frame, 0));
3728   CU_ASSERT(1000000009 == session->remote_settings.max_concurrent_streams);
3729   CU_ASSERT(64 * 1024 == session->remote_settings.initial_window_size);
3730   CU_ASSERT(1024 == session->remote_settings.header_table_size);
3731   CU_ASSERT(0 == session->remote_settings.enable_push);
3732 
3733   CU_ASSERT(64 * 1024 == stream1->remote_window_size);
3734   CU_ASSERT(0 == stream2->remote_window_size);
3735 
3736   frame.settings.iv[2].value = 16 * 1024;
3737 
3738   CU_ASSERT(0 == nghttp2_session_on_settings_received(session, &frame, 0));
3739 
3740   CU_ASSERT(16 * 1024 == stream1->remote_window_size);
3741   CU_ASSERT(-48 * 1024 == stream2->remote_window_size);
3742 
3743   CU_ASSERT(16 * 1024 == nghttp2_session_get_stream_remote_window_size(
3744                              session, stream1->stream_id));
3745   CU_ASSERT(0 == nghttp2_session_get_stream_remote_window_size(
3746                      session, stream2->stream_id));
3747 
3748   nghttp2_frame_settings_free(&frame.settings, mem);
3749 
3750   nghttp2_session_del(session);
3751 
3752   /* Check ACK with niv > 0 */
3753   nghttp2_session_server_new(&session, &callbacks, NULL);
3754   nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_ACK, dup_iv(iv, 1),
3755                               1);
3756   CU_ASSERT(0 == nghttp2_session_on_settings_received(session, &frame, 0));
3757   item = nghttp2_session_get_next_ob_item(session);
3758   CU_ASSERT(item != NULL);
3759   CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
3760 
3761   nghttp2_frame_settings_free(&frame.settings, mem);
3762   nghttp2_session_del(session);
3763 
3764   /* Check ACK against no inflight SETTINGS */
3765   nghttp2_session_server_new(&session, &callbacks, NULL);
3766   nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_ACK, NULL, 0);
3767 
3768   CU_ASSERT(0 == nghttp2_session_on_settings_received(session, &frame, 0));
3769   item = nghttp2_session_get_next_ob_item(session);
3770   CU_ASSERT(item != NULL);
3771   CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
3772 
3773   nghttp2_frame_settings_free(&frame.settings, mem);
3774   nghttp2_session_del(session);
3775 
3776   /* Check that 2 SETTINGS_HEADER_TABLE_SIZE 0 and 4096 are included
3777      and header table size is once cleared to 0. */
3778   nghttp2_session_client_new(&session, &callbacks, NULL);
3779 
3780   nghttp2_submit_request(session, NULL, &nv, 1, NULL, NULL);
3781 
3782   nghttp2_session_send(session);
3783 
3784   CU_ASSERT(session->hd_deflater.ctx.hd_table.len > 0);
3785 
3786   iv[0].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
3787   iv[0].value = 0;
3788 
3789   iv[1].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
3790   iv[1].value = 2048;
3791 
3792   nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE, dup_iv(iv, 2),
3793                               2);
3794 
3795   CU_ASSERT(0 == nghttp2_session_on_settings_received(session, &frame, 0));
3796 
3797   CU_ASSERT(0 == session->hd_deflater.ctx.hd_table.len);
3798   CU_ASSERT(2048 == session->hd_deflater.ctx.hd_table_bufsize_max);
3799   CU_ASSERT(2048 == session->remote_settings.header_table_size);
3800 
3801   nghttp2_frame_settings_free(&frame.settings, mem);
3802   nghttp2_session_del(session);
3803 
3804   /* Check that remote SETTINGS_MAX_CONCURRENT_STREAMS is set to a value set by
3805      nghttp2_option_set_peer_max_concurrent_streams() and reset to the default
3806      value (unlimited) after receiving initial SETTINGS frame from the peer. */
3807   nghttp2_option_new(&option);
3808   nghttp2_option_set_peer_max_concurrent_streams(option, 1000);
3809   nghttp2_session_client_new2(&session, &callbacks, NULL, option);
3810   CU_ASSERT(1000 == session->remote_settings.max_concurrent_streams);
3811 
3812   nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE, NULL, 0);
3813   CU_ASSERT(0 == nghttp2_session_on_settings_received(session, &frame, 0));
3814   CU_ASSERT(NGHTTP2_DEFAULT_MAX_CONCURRENT_STREAMS ==
3815             session->remote_settings.max_concurrent_streams);
3816 
3817   nghttp2_frame_settings_free(&frame.settings, mem);
3818   nghttp2_session_del(session);
3819   nghttp2_option_del(option);
3820 
3821   /* Check too large SETTINGS_MAX_FRAME_SIZE */
3822   nghttp2_session_server_new(&session, &callbacks, NULL);
3823 
3824   iv[0].settings_id = NGHTTP2_SETTINGS_MAX_FRAME_SIZE;
3825   iv[0].value = NGHTTP2_MAX_FRAME_SIZE_MAX + 1;
3826 
3827   nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE, dup_iv(iv, 1),
3828                               1);
3829 
3830   CU_ASSERT(0 == nghttp2_session_on_settings_received(session, &frame, 0));
3831 
3832   item = nghttp2_session_get_next_ob_item(session);
3833 
3834   CU_ASSERT(item != NULL);
3835   CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
3836 
3837   nghttp2_frame_settings_free(&frame.settings, mem);
3838   nghttp2_session_del(session);
3839 
3840   /* Check the case where stream window size overflows */
3841   nghttp2_session_server_new(&session, &callbacks, NULL);
3842 
3843   stream1 = open_recv_stream(session, 1);
3844 
3845   /* This will increment window size by 1 */
3846   nghttp2_frame_window_update_init(&frame.window_update, NGHTTP2_FLAG_NONE, 1,
3847                                    1);
3848 
3849   CU_ASSERT(0 == nghttp2_session_on_window_update_received(session, &frame));
3850 
3851   nghttp2_frame_window_update_free(&frame.window_update);
3852 
3853   iv[0].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
3854   iv[0].value = NGHTTP2_MAX_WINDOW_SIZE;
3855 
3856   nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE, dup_iv(iv, 1),
3857                               1);
3858 
3859   /* Now window size gets NGHTTP2_MAX_WINDOW_SIZE + 1, which is
3860      unacceptable situation in protocol spec. */
3861   CU_ASSERT(0 == nghttp2_session_on_settings_received(session, &frame, 0));
3862 
3863   nghttp2_frame_settings_free(&frame.settings, mem);
3864 
3865   item = nghttp2_session_get_next_ob_item(session);
3866 
3867   CU_ASSERT(NULL != item);
3868   CU_ASSERT(NGHTTP2_SETTINGS == item->frame.hd.type);
3869 
3870   item = nghttp2_outbound_queue_top(&session->ob_reg);
3871 
3872   CU_ASSERT(NULL != item);
3873   CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
3874   CU_ASSERT(NGHTTP2_STREAM_CLOSING == stream1->state);
3875 
3876   nghttp2_session_del(session);
3877 
3878   /* It is invalid that peer disables ENABLE_CONNECT_PROTOCOL once it
3879      has been enabled. */
3880   nghttp2_session_client_new(&session, &callbacks, NULL);
3881 
3882   session->remote_settings.enable_connect_protocol = 1;
3883 
3884   iv[0].settings_id = NGHTTP2_SETTINGS_ENABLE_CONNECT_PROTOCOL;
3885   iv[0].value = 0;
3886 
3887   nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE, dup_iv(iv, 1),
3888                               1);
3889 
3890   CU_ASSERT(0 == nghttp2_session_on_settings_received(session, &frame, 0));
3891 
3892   nghttp2_frame_settings_free(&frame.settings, mem);
3893 
3894   item = nghttp2_session_get_next_ob_item(session);
3895 
3896   CU_ASSERT(NULL != item);
3897   CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
3898 
3899   nghttp2_session_del(session);
3900 
3901   /* Should send WINDOW_UPDATE with no_auto_window_update option on if
3902      the initial window size is decreased and becomes smaller than or
3903      equal to the amount of data that has already received. */
3904   nghttp2_option_new(&option);
3905   nghttp2_option_set_no_auto_window_update(option, 1);
3906 
3907   nghttp2_session_server_new2(&session, &callbacks, NULL, option);
3908 
3909   iv[0].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
3910   iv[0].value = 1024;
3911 
3912   rv = nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, iv, 1);
3913 
3914   CU_ASSERT(0 == rv);
3915 
3916   rv = nghttp2_session_send(session);
3917 
3918   CU_ASSERT(0 == rv);
3919 
3920   stream = open_recv_stream(session, 1);
3921 
3922   memset(data, 0, sizeof(data));
3923   hd.length = 1024;
3924   hd.type = NGHTTP2_DATA;
3925   hd.flags = NGHTTP2_FLAG_NONE;
3926   hd.stream_id = 1;
3927   nghttp2_frame_pack_frame_hd(data, &hd);
3928 
3929   nread =
3930       nghttp2_session_mem_recv(session, data, NGHTTP2_FRAME_HDLEN + hd.length);
3931 
3932   CU_ASSERT((ssize_t)(NGHTTP2_FRAME_HDLEN + hd.length) == nread);
3933 
3934   rv = nghttp2_session_consume(session, 1, hd.length);
3935 
3936   CU_ASSERT(0 == rv);
3937   CU_ASSERT((int32_t)hd.length == stream->recv_window_size);
3938   CU_ASSERT((int32_t)hd.length == stream->consumed_size);
3939 
3940   nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_ACK, NULL, 0);
3941 
3942   rv = nghttp2_session_on_settings_received(session, &frame, 0);
3943 
3944   CU_ASSERT(0 == rv);
3945   CU_ASSERT(1024 == stream->local_window_size);
3946   CU_ASSERT(0 == stream->recv_window_size);
3947   CU_ASSERT(0 == stream->consumed_size);
3948 
3949   item = nghttp2_session_get_next_ob_item(session);
3950 
3951   CU_ASSERT(NULL != item);
3952   CU_ASSERT(NGHTTP2_WINDOW_UPDATE == item->frame.hd.type);
3953   CU_ASSERT((int32_t)hd.length ==
3954             item->frame.window_update.window_size_increment);
3955 
3956   nghttp2_session_del(session);
3957   nghttp2_option_del(option);
3958 
3959   /* It is invalid to change SETTINGS_NO_RFC7540_PRIORITIES in the
3960      following SETTINGS. */
3961   nghttp2_session_client_new(&session, &callbacks, NULL);
3962 
3963   session->remote_settings.no_rfc7540_priorities = 1;
3964 
3965   iv[0].settings_id = NGHTTP2_SETTINGS_NO_RFC7540_PRIORITIES;
3966   iv[0].value = 0;
3967 
3968   nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE, dup_iv(iv, 1),
3969                               1);
3970 
3971   CU_ASSERT(0 == nghttp2_session_on_settings_received(session, &frame, 0));
3972 
3973   nghttp2_frame_settings_free(&frame.settings, mem);
3974 
3975   item = nghttp2_session_get_next_ob_item(session);
3976 
3977   CU_ASSERT(NULL != item);
3978   CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
3979 
3980   nghttp2_session_del(session);
3981 }
3982 
test_nghttp2_session_on_push_promise_received(void)3983 void test_nghttp2_session_on_push_promise_received(void) {
3984   nghttp2_session *session;
3985   nghttp2_session_callbacks callbacks;
3986   my_user_data user_data;
3987   nghttp2_frame frame;
3988   nghttp2_stream *stream, *promised_stream;
3989   nghttp2_outbound_item *item;
3990   nghttp2_nv malformed_nva[] = {MAKE_NV(":path", "\x01")};
3991   nghttp2_nv *nva;
3992   size_t nvlen;
3993   nghttp2_mem *mem;
3994   nghttp2_settings_entry iv = {NGHTTP2_SETTINGS_ENABLE_PUSH, 0};
3995 
3996   mem = nghttp2_mem_default();
3997   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
3998   callbacks.send_callback = null_send_callback;
3999   callbacks.on_begin_headers_callback = on_begin_headers_callback;
4000   callbacks.on_invalid_frame_recv_callback = on_invalid_frame_recv_callback;
4001 
4002   nghttp2_session_client_new(&session, &callbacks, &user_data);
4003 
4004   stream = open_sent_stream(session, 1);
4005 
4006   nghttp2_frame_push_promise_init(&frame.push_promise, NGHTTP2_FLAG_END_HEADERS,
4007                                   1, 2, NULL, 0);
4008 
4009   user_data.begin_headers_cb_called = 0;
4010   user_data.invalid_frame_recv_cb_called = 0;
4011 
4012   CU_ASSERT(0 == nghttp2_session_on_push_promise_received(session, &frame));
4013 
4014   CU_ASSERT(1 == user_data.begin_headers_cb_called);
4015   CU_ASSERT(1 == session->num_incoming_reserved_streams);
4016   promised_stream = nghttp2_session_get_stream(session, 2);
4017   CU_ASSERT(NGHTTP2_STREAM_RESERVED == promised_stream->state);
4018   CU_ASSERT(2 == session->last_recv_stream_id);
4019 
4020   /* Attempt to PUSH_PROMISE against half close (remote) */
4021   nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_RD);
4022   frame.push_promise.promised_stream_id = 4;
4023 
4024   user_data.begin_headers_cb_called = 0;
4025   user_data.invalid_frame_recv_cb_called = 0;
4026   CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
4027             nghttp2_session_on_push_promise_received(session, &frame));
4028 
4029   CU_ASSERT(0 == user_data.begin_headers_cb_called);
4030   CU_ASSERT(1 == user_data.invalid_frame_recv_cb_called);
4031   CU_ASSERT(1 == session->num_incoming_reserved_streams);
4032   CU_ASSERT(NULL == nghttp2_session_get_stream(session, 4));
4033   item = nghttp2_session_get_next_ob_item(session);
4034   CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
4035   CU_ASSERT(NGHTTP2_STREAM_CLOSED == item->frame.goaway.error_code);
4036   CU_ASSERT(0 == nghttp2_session_send(session));
4037   CU_ASSERT(4 == session->last_recv_stream_id);
4038 
4039   nghttp2_session_del(session);
4040 
4041   nghttp2_session_client_new(&session, &callbacks, &user_data);
4042 
4043   stream = open_sent_stream(session, 1);
4044 
4045   /* Attempt to PUSH_PROMISE against stream in closing state */
4046   stream->state = NGHTTP2_STREAM_CLOSING;
4047   frame.push_promise.promised_stream_id = 6;
4048 
4049   user_data.begin_headers_cb_called = 0;
4050   user_data.invalid_frame_recv_cb_called = 0;
4051   CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
4052             nghttp2_session_on_push_promise_received(session, &frame));
4053 
4054   CU_ASSERT(0 == user_data.begin_headers_cb_called);
4055   CU_ASSERT(0 == session->num_incoming_reserved_streams);
4056   CU_ASSERT(NULL == nghttp2_session_get_stream(session, 6));
4057   item = nghttp2_session_get_next_ob_item(session);
4058   CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
4059   CU_ASSERT(6 == item->frame.hd.stream_id);
4060   CU_ASSERT(NGHTTP2_CANCEL == item->frame.rst_stream.error_code);
4061   CU_ASSERT(0 == nghttp2_session_send(session));
4062 
4063   /* Attempt to PUSH_PROMISE against idle stream */
4064   frame.hd.stream_id = 3;
4065   frame.push_promise.promised_stream_id = 8;
4066 
4067   user_data.begin_headers_cb_called = 0;
4068   user_data.invalid_frame_recv_cb_called = 0;
4069   CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
4070             nghttp2_session_on_push_promise_received(session, &frame));
4071 
4072   CU_ASSERT(0 == user_data.begin_headers_cb_called);
4073   CU_ASSERT(0 == session->num_incoming_reserved_streams);
4074   CU_ASSERT(NULL == nghttp2_session_get_stream(session, 8));
4075   item = nghttp2_session_get_next_ob_item(session);
4076   CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
4077   CU_ASSERT(0 == item->frame.hd.stream_id);
4078   CU_ASSERT(NGHTTP2_PROTOCOL_ERROR == item->frame.goaway.error_code);
4079   CU_ASSERT(0 == nghttp2_session_send(session));
4080 
4081   nghttp2_session_del(session);
4082 
4083   nghttp2_session_client_new(&session, &callbacks, &user_data);
4084 
4085   stream = open_sent_stream(session, 1);
4086 
4087   /* Same ID twice */
4088   frame.hd.stream_id = 1;
4089   frame.push_promise.promised_stream_id = 2;
4090 
4091   user_data.begin_headers_cb_called = 0;
4092   user_data.invalid_frame_recv_cb_called = 0;
4093   CU_ASSERT(0 == nghttp2_session_on_push_promise_received(session, &frame));
4094 
4095   CU_ASSERT(1 == user_data.begin_headers_cb_called);
4096   CU_ASSERT(1 == session->num_incoming_reserved_streams);
4097   CU_ASSERT(NULL != nghttp2_session_get_stream(session, 2));
4098 
4099   user_data.begin_headers_cb_called = 0;
4100   user_data.invalid_frame_recv_cb_called = 0;
4101   CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
4102             nghttp2_session_on_push_promise_received(session, &frame));
4103 
4104   CU_ASSERT(0 == user_data.begin_headers_cb_called);
4105   CU_ASSERT(1 == session->num_incoming_reserved_streams);
4106   CU_ASSERT(NULL == nghttp2_session_get_stream(session, 8));
4107   item = nghttp2_session_get_next_ob_item(session);
4108   CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
4109   CU_ASSERT(NGHTTP2_PROTOCOL_ERROR == item->frame.goaway.error_code);
4110   CU_ASSERT(0 == nghttp2_session_send(session));
4111 
4112   /* After GOAWAY, PUSH_PROMISE will be discarded */
4113   frame.push_promise.promised_stream_id = 10;
4114 
4115   user_data.begin_headers_cb_called = 0;
4116   user_data.invalid_frame_recv_cb_called = 0;
4117   CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
4118             nghttp2_session_on_push_promise_received(session, &frame));
4119 
4120   CU_ASSERT(0 == user_data.begin_headers_cb_called);
4121   CU_ASSERT(1 == session->num_incoming_reserved_streams);
4122   CU_ASSERT(NULL == nghttp2_session_get_stream(session, 10));
4123   CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
4124 
4125   nghttp2_frame_push_promise_free(&frame.push_promise, mem);
4126   nghttp2_session_del(session);
4127 
4128   nghttp2_session_client_new(&session, &callbacks, &user_data);
4129 
4130   open_recv_stream2(session, 2, NGHTTP2_STREAM_RESERVED);
4131 
4132   /* Attempt to PUSH_PROMISE against reserved (remote) stream */
4133   nghttp2_frame_push_promise_init(&frame.push_promise, NGHTTP2_FLAG_END_HEADERS,
4134                                   2, 4, NULL, 0);
4135 
4136   user_data.begin_headers_cb_called = 0;
4137   user_data.invalid_frame_recv_cb_called = 0;
4138   CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
4139             nghttp2_session_on_push_promise_received(session, &frame));
4140 
4141   CU_ASSERT(0 == user_data.begin_headers_cb_called);
4142   CU_ASSERT(1 == user_data.invalid_frame_recv_cb_called);
4143   CU_ASSERT(1 == session->num_incoming_reserved_streams);
4144 
4145   nghttp2_frame_push_promise_free(&frame.push_promise, mem);
4146   nghttp2_session_del(session);
4147 
4148   /* Disable PUSH */
4149   nghttp2_session_client_new(&session, &callbacks, &user_data);
4150 
4151   open_sent_stream(session, 1);
4152 
4153   session->local_settings.enable_push = 0;
4154 
4155   nghttp2_frame_push_promise_init(&frame.push_promise, NGHTTP2_FLAG_END_HEADERS,
4156                                   1, 2, NULL, 0);
4157 
4158   user_data.begin_headers_cb_called = 0;
4159   user_data.invalid_frame_recv_cb_called = 0;
4160   CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
4161             nghttp2_session_on_push_promise_received(session, &frame));
4162 
4163   CU_ASSERT(0 == user_data.begin_headers_cb_called);
4164   CU_ASSERT(1 == user_data.invalid_frame_recv_cb_called);
4165   CU_ASSERT(0 == session->num_incoming_reserved_streams);
4166 
4167   nghttp2_frame_push_promise_free(&frame.push_promise, mem);
4168   nghttp2_session_del(session);
4169 
4170   /* Check malformed headers. We accept malformed headers */
4171   nghttp2_session_client_new(&session, &callbacks, &user_data);
4172 
4173   open_sent_stream(session, 1);
4174 
4175   nvlen = ARRLEN(malformed_nva);
4176   nghttp2_nv_array_copy(&nva, malformed_nva, nvlen, mem);
4177   nghttp2_frame_push_promise_init(&frame.push_promise, NGHTTP2_FLAG_END_HEADERS,
4178                                   1, 2, nva, nvlen);
4179   user_data.begin_headers_cb_called = 0;
4180   user_data.invalid_frame_recv_cb_called = 0;
4181   CU_ASSERT(0 == nghttp2_session_on_push_promise_received(session, &frame));
4182 
4183   CU_ASSERT(1 == user_data.begin_headers_cb_called);
4184   CU_ASSERT(0 == user_data.invalid_frame_recv_cb_called);
4185 
4186   nghttp2_frame_push_promise_free(&frame.push_promise, mem);
4187   nghttp2_session_del(session);
4188 
4189   /* If local_settings.enable_push = 0 is pending, but not acked from
4190      peer, incoming PUSH_PROMISE is rejected */
4191   nghttp2_session_client_new(&session, &callbacks, &user_data);
4192 
4193   open_sent_stream(session, 1);
4194 
4195   /* Submit settings with ENABLE_PUSH = 0 (thus disabling push) */
4196   nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, &iv, 1);
4197 
4198   nghttp2_frame_push_promise_init(&frame.push_promise, NGHTTP2_FLAG_END_HEADERS,
4199                                   1, 2, NULL, 0);
4200 
4201   CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
4202             nghttp2_session_on_push_promise_received(session, &frame));
4203 
4204   CU_ASSERT(0 == session->num_incoming_reserved_streams);
4205 
4206   nghttp2_frame_push_promise_free(&frame.push_promise, mem);
4207   nghttp2_session_del(session);
4208 
4209   /* Check max_incoming_reserved_streams */
4210   nghttp2_session_client_new(&session, &callbacks, &user_data);
4211   session->max_incoming_reserved_streams = 1;
4212 
4213   open_sent_stream(session, 1);
4214   open_recv_stream2(session, 2, NGHTTP2_STREAM_RESERVED);
4215 
4216   CU_ASSERT(1 == session->num_incoming_reserved_streams);
4217 
4218   nghttp2_frame_push_promise_init(&frame.push_promise, NGHTTP2_FLAG_END_HEADERS,
4219                                   1, 4, NULL, 0);
4220 
4221   CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
4222             nghttp2_session_on_push_promise_received(session, &frame));
4223 
4224   CU_ASSERT(1 == session->num_incoming_reserved_streams);
4225 
4226   item = nghttp2_session_get_next_ob_item(session);
4227 
4228   CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
4229   CU_ASSERT(NGHTTP2_CANCEL == item->frame.rst_stream.error_code);
4230 
4231   nghttp2_frame_push_promise_free(&frame.push_promise, mem);
4232   nghttp2_session_del(session);
4233 }
4234 
test_nghttp2_session_on_ping_received(void)4235 void test_nghttp2_session_on_ping_received(void) {
4236   nghttp2_session *session;
4237   nghttp2_session_callbacks callbacks;
4238   my_user_data user_data;
4239   nghttp2_frame frame;
4240   nghttp2_outbound_item *top;
4241   const uint8_t opaque_data[] = "01234567";
4242   nghttp2_option *option;
4243 
4244   user_data.frame_recv_cb_called = 0;
4245   user_data.invalid_frame_recv_cb_called = 0;
4246 
4247   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4248   callbacks.on_frame_recv_callback = on_frame_recv_callback;
4249   callbacks.on_invalid_frame_recv_callback = on_invalid_frame_recv_callback;
4250 
4251   nghttp2_session_client_new(&session, &callbacks, &user_data);
4252   nghttp2_frame_ping_init(&frame.ping, NGHTTP2_FLAG_ACK, opaque_data);
4253 
4254   CU_ASSERT(0 == nghttp2_session_on_ping_received(session, &frame));
4255   CU_ASSERT(1 == user_data.frame_recv_cb_called);
4256 
4257   /* Since this ping frame has ACK flag set, no further action is
4258      performed. */
4259   CU_ASSERT(NULL == nghttp2_outbound_queue_top(&session->ob_urgent));
4260 
4261   /* Clear the flag, and receive it again */
4262   frame.hd.flags = NGHTTP2_FLAG_NONE;
4263 
4264   CU_ASSERT(0 == nghttp2_session_on_ping_received(session, &frame));
4265   CU_ASSERT(2 == user_data.frame_recv_cb_called);
4266   top = nghttp2_outbound_queue_top(&session->ob_urgent);
4267   CU_ASSERT(NGHTTP2_PING == top->frame.hd.type);
4268   CU_ASSERT(NGHTTP2_FLAG_ACK == top->frame.hd.flags);
4269   CU_ASSERT(memcmp(opaque_data, top->frame.ping.opaque_data, 8) == 0);
4270 
4271   nghttp2_frame_ping_free(&frame.ping);
4272   nghttp2_session_del(session);
4273 
4274   /* Use nghttp2_option_set_no_auto_ping_ack() */
4275   nghttp2_option_new(&option);
4276   nghttp2_option_set_no_auto_ping_ack(option, 1);
4277 
4278   nghttp2_session_server_new2(&session, &callbacks, &user_data, option);
4279   nghttp2_frame_ping_init(&frame.ping, NGHTTP2_FLAG_NONE, NULL);
4280 
4281   user_data.frame_recv_cb_called = 0;
4282 
4283   CU_ASSERT(0 == nghttp2_session_on_ping_received(session, &frame));
4284   CU_ASSERT(1 == user_data.frame_recv_cb_called);
4285   CU_ASSERT(NULL == nghttp2_outbound_queue_top(&session->ob_urgent));
4286 
4287   nghttp2_frame_ping_free(&frame.ping);
4288   nghttp2_session_del(session);
4289   nghttp2_option_del(option);
4290 }
4291 
test_nghttp2_session_on_goaway_received(void)4292 void test_nghttp2_session_on_goaway_received(void) {
4293   nghttp2_session *session;
4294   nghttp2_session_callbacks callbacks;
4295   my_user_data user_data;
4296   nghttp2_frame frame;
4297   int i;
4298   nghttp2_mem *mem;
4299 
4300   mem = nghttp2_mem_default();
4301   user_data.frame_recv_cb_called = 0;
4302   user_data.invalid_frame_recv_cb_called = 0;
4303 
4304   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4305   callbacks.on_frame_recv_callback = on_frame_recv_callback;
4306   callbacks.on_invalid_frame_recv_callback = on_invalid_frame_recv_callback;
4307   callbacks.on_stream_close_callback = on_stream_close_callback;
4308 
4309   nghttp2_session_client_new(&session, &callbacks, &user_data);
4310 
4311   for (i = 1; i <= 7; ++i) {
4312     if (nghttp2_session_is_my_stream_id(session, i)) {
4313       open_sent_stream(session, i);
4314     } else {
4315       open_recv_stream(session, i);
4316     }
4317   }
4318 
4319   nghttp2_frame_goaway_init(&frame.goaway, 3, NGHTTP2_PROTOCOL_ERROR, NULL, 0);
4320 
4321   user_data.stream_close_cb_called = 0;
4322 
4323   CU_ASSERT(0 == nghttp2_session_on_goaway_received(session, &frame));
4324 
4325   CU_ASSERT(1 == user_data.frame_recv_cb_called);
4326   CU_ASSERT(3 == session->remote_last_stream_id);
4327   /* on_stream_close should be callsed for 2 times (stream 5 and 7) */
4328   CU_ASSERT(2 == user_data.stream_close_cb_called);
4329 
4330   CU_ASSERT(NULL != nghttp2_session_get_stream(session, 1));
4331   CU_ASSERT(NULL != nghttp2_session_get_stream(session, 2));
4332   CU_ASSERT(NULL != nghttp2_session_get_stream(session, 3));
4333   CU_ASSERT(NULL != nghttp2_session_get_stream(session, 4));
4334   CU_ASSERT(NULL == nghttp2_session_get_stream(session, 5));
4335   CU_ASSERT(NULL != nghttp2_session_get_stream(session, 6));
4336   CU_ASSERT(NULL == nghttp2_session_get_stream(session, 7));
4337 
4338   nghttp2_frame_goaway_free(&frame.goaway, mem);
4339   nghttp2_session_del(session);
4340 }
4341 
test_nghttp2_session_on_window_update_received(void)4342 void test_nghttp2_session_on_window_update_received(void) {
4343   nghttp2_session *session;
4344   nghttp2_session_callbacks callbacks;
4345   my_user_data user_data;
4346   nghttp2_frame frame;
4347   nghttp2_stream *stream;
4348   nghttp2_outbound_item *data_item;
4349   nghttp2_mem *mem;
4350 
4351   mem = nghttp2_mem_default();
4352 
4353   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4354   callbacks.on_frame_recv_callback = on_frame_recv_callback;
4355   callbacks.on_invalid_frame_recv_callback = on_invalid_frame_recv_callback;
4356   user_data.frame_recv_cb_called = 0;
4357   user_data.invalid_frame_recv_cb_called = 0;
4358 
4359   nghttp2_session_client_new(&session, &callbacks, &user_data);
4360 
4361   stream = open_sent_stream(session, 1);
4362 
4363   data_item = create_data_ob_item(mem);
4364 
4365   CU_ASSERT(0 == nghttp2_stream_attach_item(stream, data_item));
4366 
4367   nghttp2_frame_window_update_init(&frame.window_update, NGHTTP2_FLAG_NONE, 1,
4368                                    16 * 1024);
4369 
4370   CU_ASSERT(0 == nghttp2_session_on_window_update_received(session, &frame));
4371   CU_ASSERT(1 == user_data.frame_recv_cb_called);
4372   CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE + 16 * 1024 ==
4373             stream->remote_window_size);
4374 
4375   CU_ASSERT(0 == nghttp2_stream_defer_item(
4376                      stream, NGHTTP2_STREAM_FLAG_DEFERRED_FLOW_CONTROL));
4377 
4378   CU_ASSERT(0 == nghttp2_session_on_window_update_received(session, &frame));
4379   CU_ASSERT(2 == user_data.frame_recv_cb_called);
4380   CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE + 16 * 1024 * 2 ==
4381             stream->remote_window_size);
4382   CU_ASSERT(0 == (stream->flags & NGHTTP2_STREAM_FLAG_DEFERRED_ALL));
4383 
4384   nghttp2_frame_window_update_free(&frame.window_update);
4385 
4386   /* Receiving WINDOW_UPDATE on reserved (remote) stream is a
4387      connection error */
4388   open_recv_stream2(session, 2, NGHTTP2_STREAM_RESERVED);
4389 
4390   nghttp2_frame_window_update_init(&frame.window_update, NGHTTP2_FLAG_NONE, 2,
4391                                    4096);
4392 
4393   CU_ASSERT(!(session->goaway_flags & NGHTTP2_GOAWAY_TERM_ON_SEND));
4394   CU_ASSERT(0 == nghttp2_session_on_window_update_received(session, &frame));
4395   CU_ASSERT(session->goaway_flags & NGHTTP2_GOAWAY_TERM_ON_SEND);
4396 
4397   nghttp2_frame_window_update_free(&frame.window_update);
4398 
4399   nghttp2_session_del(session);
4400 
4401   /* Receiving WINDOW_UPDATE on reserved (local) stream is allowed */
4402   nghttp2_session_server_new(&session, &callbacks, &user_data);
4403 
4404   stream = open_sent_stream2(session, 2, NGHTTP2_STREAM_RESERVED);
4405 
4406   nghttp2_frame_window_update_init(&frame.window_update, NGHTTP2_FLAG_NONE, 2,
4407                                    4096);
4408 
4409   CU_ASSERT(0 == nghttp2_session_on_window_update_received(session, &frame));
4410   CU_ASSERT(!(session->goaway_flags & NGHTTP2_GOAWAY_TERM_ON_SEND));
4411 
4412   CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE + 4096 == stream->remote_window_size);
4413 
4414   nghttp2_frame_window_update_free(&frame.window_update);
4415 
4416   nghttp2_session_del(session);
4417 }
4418 
test_nghttp2_session_on_data_received(void)4419 void test_nghttp2_session_on_data_received(void) {
4420   nghttp2_session *session;
4421   nghttp2_session_callbacks callbacks;
4422   my_user_data user_data;
4423   nghttp2_outbound_item *top;
4424   nghttp2_stream *stream;
4425   nghttp2_frame frame;
4426 
4427   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4428 
4429   nghttp2_session_client_new(&session, &callbacks, &user_data);
4430   stream = open_recv_stream(session, 2);
4431 
4432   nghttp2_frame_hd_init(&frame.hd, 4096, NGHTTP2_DATA, NGHTTP2_FLAG_NONE, 2);
4433 
4434   CU_ASSERT(0 == nghttp2_session_on_data_received(session, &frame));
4435   CU_ASSERT(0 == stream->shut_flags);
4436 
4437   frame.hd.flags = NGHTTP2_FLAG_END_STREAM;
4438 
4439   CU_ASSERT(0 == nghttp2_session_on_data_received(session, &frame));
4440   CU_ASSERT(NGHTTP2_SHUT_RD == stream->shut_flags);
4441 
4442   /* If NGHTTP2_STREAM_CLOSING state, DATA frame is discarded. */
4443   open_sent_stream2(session, 1, NGHTTP2_STREAM_CLOSING);
4444 
4445   frame.hd.flags = NGHTTP2_FLAG_NONE;
4446   frame.hd.stream_id = 1;
4447 
4448   CU_ASSERT(0 == nghttp2_session_on_data_received(session, &frame));
4449   CU_ASSERT(NULL == nghttp2_outbound_queue_top(&session->ob_reg));
4450 
4451   /* Check INVALID_STREAM case: DATA frame with stream ID which does
4452      not exist. */
4453 
4454   frame.hd.stream_id = 3;
4455 
4456   CU_ASSERT(0 == nghttp2_session_on_data_received(session, &frame));
4457   top = nghttp2_outbound_queue_top(&session->ob_reg);
4458   /* DATA against nonexistent stream is just ignored for now. */
4459   CU_ASSERT(top == NULL);
4460 
4461   nghttp2_session_del(session);
4462 }
4463 
test_nghttp2_session_on_data_received_fail_fast(void)4464 void test_nghttp2_session_on_data_received_fail_fast(void) {
4465   nghttp2_session *session;
4466   nghttp2_session_callbacks callbacks;
4467   uint8_t buf[9];
4468   nghttp2_stream *stream;
4469   nghttp2_frame_hd hd;
4470   nghttp2_outbound_item *item;
4471 
4472   memset(&callbacks, 0, sizeof(callbacks));
4473 
4474   nghttp2_frame_hd_init(&hd, 0, NGHTTP2_DATA, NGHTTP2_FLAG_NONE, 1);
4475   nghttp2_frame_pack_frame_hd(buf, &hd);
4476 
4477   nghttp2_session_server_new(&session, &callbacks, NULL);
4478 
4479   /* DATA to closed (remote) */
4480   stream = open_recv_stream(session, 1);
4481   nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_RD);
4482 
4483   CU_ASSERT((ssize_t)sizeof(buf) ==
4484             nghttp2_session_mem_recv(session, buf, sizeof(buf)));
4485 
4486   item = nghttp2_session_get_next_ob_item(session);
4487 
4488   CU_ASSERT(NULL != item);
4489   CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
4490 
4491   nghttp2_session_del(session);
4492 
4493   nghttp2_session_server_new(&session, &callbacks, NULL);
4494 
4495   /* DATA to closed stream with explicit closed (remote) */
4496   stream = open_recv_stream(session, 1);
4497   nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_RD);
4498   nghttp2_session_close_stream(session, 1, NGHTTP2_NO_ERROR);
4499 
4500   CU_ASSERT((ssize_t)sizeof(buf) ==
4501             nghttp2_session_mem_recv(session, buf, sizeof(buf)));
4502 
4503   item = nghttp2_session_get_next_ob_item(session);
4504 
4505   CU_ASSERT(NULL != item);
4506   CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
4507 
4508   nghttp2_session_del(session);
4509 }
4510 
test_nghttp2_session_on_altsvc_received(void)4511 void test_nghttp2_session_on_altsvc_received(void) {
4512   nghttp2_session *session;
4513   nghttp2_session_callbacks callbacks;
4514   my_user_data ud;
4515   nghttp2_frame frame;
4516   nghttp2_option *option;
4517   uint8_t origin[] = "nghttp2.org";
4518   uint8_t field_value[] = "h2=\":443\"";
4519   int rv;
4520 
4521   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4522   callbacks.on_frame_recv_callback = on_frame_recv_callback;
4523 
4524   nghttp2_option_new(&option);
4525   nghttp2_option_set_builtin_recv_extension_type(option, NGHTTP2_ALTSVC);
4526 
4527   nghttp2_session_client_new2(&session, &callbacks, &ud, option);
4528 
4529   frame.ext.payload = &session->iframe.ext_frame_payload;
4530 
4531   /* We just pass the strings without making a copy.  This is OK,
4532      since we never call nghttp2_frame_altsvc_free(). */
4533   nghttp2_frame_altsvc_init(&frame.ext, 0, origin, sizeof(origin) - 1,
4534                             field_value, sizeof(field_value) - 1);
4535 
4536   ud.frame_recv_cb_called = 0;
4537   rv = nghttp2_session_on_altsvc_received(session, &frame);
4538 
4539   CU_ASSERT(0 == rv);
4540   CU_ASSERT(1 == ud.frame_recv_cb_called);
4541 
4542   nghttp2_session_del(session);
4543 
4544   /* Receiving empty origin with stream ID == 0 */
4545   nghttp2_session_client_new2(&session, &callbacks, &ud, option);
4546 
4547   frame.ext.payload = &session->iframe.ext_frame_payload;
4548 
4549   nghttp2_frame_altsvc_init(&frame.ext, 0, origin, 0, field_value,
4550                             sizeof(field_value) - 1);
4551 
4552   ud.frame_recv_cb_called = 0;
4553   rv = nghttp2_session_on_altsvc_received(session, &frame);
4554 
4555   CU_ASSERT(0 == rv);
4556   CU_ASSERT(0 == ud.frame_recv_cb_called);
4557 
4558   nghttp2_session_del(session);
4559 
4560   /* Receiving non-empty origin with stream ID != 0 */
4561   nghttp2_session_client_new2(&session, &callbacks, &ud, option);
4562 
4563   frame.ext.payload = &session->iframe.ext_frame_payload;
4564 
4565   open_sent_stream(session, 1);
4566 
4567   nghttp2_frame_altsvc_init(&frame.ext, 1, origin, sizeof(origin) - 1,
4568                             field_value, sizeof(field_value) - 1);
4569 
4570   ud.frame_recv_cb_called = 0;
4571   rv = nghttp2_session_on_altsvc_received(session, &frame);
4572 
4573   CU_ASSERT(0 == rv);
4574   CU_ASSERT(0 == ud.frame_recv_cb_called);
4575 
4576   nghttp2_session_del(session);
4577 
4578   /* Receiving empty origin with stream ID != 0; this is OK */
4579   nghttp2_session_client_new2(&session, &callbacks, &ud, option);
4580 
4581   frame.ext.payload = &session->iframe.ext_frame_payload;
4582 
4583   open_sent_stream(session, 1);
4584 
4585   nghttp2_frame_altsvc_init(&frame.ext, 1, origin, 0, field_value,
4586                             sizeof(field_value) - 1);
4587 
4588   ud.frame_recv_cb_called = 0;
4589   rv = nghttp2_session_on_altsvc_received(session, &frame);
4590 
4591   CU_ASSERT(0 == rv);
4592   CU_ASSERT(1 == ud.frame_recv_cb_called);
4593 
4594   nghttp2_session_del(session);
4595 
4596   /* Stream does not exist; ALTSVC will be ignored. */
4597   nghttp2_session_client_new2(&session, &callbacks, &ud, option);
4598 
4599   frame.ext.payload = &session->iframe.ext_frame_payload;
4600 
4601   nghttp2_frame_altsvc_init(&frame.ext, 1, origin, 0, field_value,
4602                             sizeof(field_value) - 1);
4603 
4604   ud.frame_recv_cb_called = 0;
4605   rv = nghttp2_session_on_altsvc_received(session, &frame);
4606 
4607   CU_ASSERT(0 == rv);
4608   CU_ASSERT(0 == ud.frame_recv_cb_called);
4609 
4610   nghttp2_session_del(session);
4611 
4612   nghttp2_option_del(option);
4613 }
4614 
test_nghttp2_session_send_headers_start_stream(void)4615 void test_nghttp2_session_send_headers_start_stream(void) {
4616   nghttp2_session *session;
4617   nghttp2_session_callbacks callbacks;
4618   nghttp2_outbound_item *item;
4619   nghttp2_frame *frame;
4620   nghttp2_stream *stream;
4621   nghttp2_mem *mem;
4622 
4623   mem = nghttp2_mem_default();
4624 
4625   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4626   callbacks.send_callback = null_send_callback;
4627 
4628   nghttp2_session_client_new(&session, &callbacks, NULL);
4629 
4630   item = mem->malloc(sizeof(nghttp2_outbound_item), NULL);
4631 
4632   nghttp2_outbound_item_init(item);
4633 
4634   frame = &item->frame;
4635 
4636   nghttp2_frame_headers_init(&frame->headers, NGHTTP2_FLAG_END_HEADERS,
4637                              (int32_t)session->next_stream_id,
4638                              NGHTTP2_HCAT_REQUEST, NULL, NULL, 0);
4639   session->next_stream_id += 2;
4640 
4641   nghttp2_session_add_item(session, item);
4642   CU_ASSERT(0 == nghttp2_session_send(session));
4643   stream = nghttp2_session_get_stream(session, 1);
4644   CU_ASSERT(NGHTTP2_STREAM_OPENING == stream->state);
4645 
4646   nghttp2_session_del(session);
4647 }
4648 
test_nghttp2_session_send_headers_reply(void)4649 void test_nghttp2_session_send_headers_reply(void) {
4650   nghttp2_session *session;
4651   nghttp2_session_callbacks callbacks;
4652   nghttp2_outbound_item *item;
4653   nghttp2_frame *frame;
4654   nghttp2_stream *stream;
4655   nghttp2_mem *mem;
4656 
4657   mem = nghttp2_mem_default();
4658 
4659   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4660   callbacks.send_callback = null_send_callback;
4661 
4662   CU_ASSERT(0 == nghttp2_session_server_new(&session, &callbacks, NULL));
4663   open_recv_stream2(session, 1, NGHTTP2_STREAM_OPENING);
4664 
4665   item = mem->malloc(sizeof(nghttp2_outbound_item), NULL);
4666 
4667   nghttp2_outbound_item_init(item);
4668 
4669   frame = &item->frame;
4670 
4671   nghttp2_frame_headers_init(&frame->headers, NGHTTP2_FLAG_END_HEADERS, 1,
4672                              NGHTTP2_HCAT_HEADERS, NULL, NULL, 0);
4673   nghttp2_session_add_item(session, item);
4674   CU_ASSERT(0 == nghttp2_session_send(session));
4675   stream = nghttp2_session_get_stream(session, 1);
4676   CU_ASSERT(NGHTTP2_STREAM_OPENED == stream->state);
4677 
4678   nghttp2_session_del(session);
4679 }
4680 
test_nghttp2_session_send_headers_frame_size_error(void)4681 void test_nghttp2_session_send_headers_frame_size_error(void) {
4682   nghttp2_session *session;
4683   nghttp2_session_callbacks callbacks;
4684   nghttp2_outbound_item *item;
4685   nghttp2_frame *frame;
4686   nghttp2_nv *nva;
4687   size_t nvlen;
4688   size_t vallen = NGHTTP2_HD_MAX_NV;
4689   nghttp2_nv nv[28];
4690   size_t nnv = ARRLEN(nv);
4691   size_t i;
4692   my_user_data ud;
4693   nghttp2_mem *mem;
4694 
4695   mem = nghttp2_mem_default();
4696 
4697   for (i = 0; i < nnv; ++i) {
4698     nv[i].name = (uint8_t *)"header";
4699     nv[i].namelen = strlen((const char *)nv[i].name);
4700     nv[i].value = mem->malloc(vallen + 1, NULL);
4701     memset(nv[i].value, '0' + (int)i, vallen);
4702     nv[i].value[vallen] = '\0';
4703     nv[i].valuelen = vallen;
4704     nv[i].flags = NGHTTP2_NV_FLAG_NONE;
4705   }
4706 
4707   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4708   callbacks.send_callback = null_send_callback;
4709   callbacks.on_frame_not_send_callback = on_frame_not_send_callback;
4710 
4711   nghttp2_session_client_new(&session, &callbacks, &ud);
4712   nvlen = nnv;
4713   nghttp2_nv_array_copy(&nva, nv, nvlen, mem);
4714 
4715   item = mem->malloc(sizeof(nghttp2_outbound_item), NULL);
4716 
4717   nghttp2_outbound_item_init(item);
4718 
4719   frame = &item->frame;
4720 
4721   nghttp2_frame_headers_init(&frame->headers, NGHTTP2_FLAG_END_HEADERS,
4722                              (int32_t)session->next_stream_id,
4723                              NGHTTP2_HCAT_REQUEST, NULL, nva, nvlen);
4724 
4725   session->next_stream_id += 2;
4726 
4727   nghttp2_session_add_item(session, item);
4728 
4729   ud.frame_not_send_cb_called = 0;
4730 
4731   CU_ASSERT(0 == nghttp2_session_send(session));
4732 
4733   CU_ASSERT(1 == ud.frame_not_send_cb_called);
4734   CU_ASSERT(NGHTTP2_HEADERS == ud.not_sent_frame_type);
4735   CU_ASSERT(NGHTTP2_ERR_FRAME_SIZE_ERROR == ud.not_sent_error);
4736 
4737   for (i = 0; i < nnv; ++i) {
4738     mem->free(nv[i].value, NULL);
4739   }
4740   nghttp2_session_del(session);
4741 }
4742 
test_nghttp2_session_send_headers_push_reply(void)4743 void test_nghttp2_session_send_headers_push_reply(void) {
4744   nghttp2_session *session;
4745   nghttp2_session_callbacks callbacks;
4746   nghttp2_outbound_item *item;
4747   nghttp2_frame *frame;
4748   nghttp2_stream *stream;
4749   nghttp2_mem *mem;
4750 
4751   mem = nghttp2_mem_default();
4752 
4753   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4754   callbacks.send_callback = null_send_callback;
4755 
4756   CU_ASSERT(0 == nghttp2_session_server_new(&session, &callbacks, NULL));
4757   open_sent_stream2(session, 2, NGHTTP2_STREAM_RESERVED);
4758 
4759   item = mem->malloc(sizeof(nghttp2_outbound_item), NULL);
4760 
4761   nghttp2_outbound_item_init(item);
4762 
4763   frame = &item->frame;
4764 
4765   nghttp2_frame_headers_init(&frame->headers, NGHTTP2_FLAG_END_HEADERS, 2,
4766                              NGHTTP2_HCAT_HEADERS, NULL, NULL, 0);
4767   nghttp2_session_add_item(session, item);
4768   CU_ASSERT(0 == session->num_outgoing_streams);
4769   CU_ASSERT(0 == nghttp2_session_send(session));
4770   CU_ASSERT(1 == session->num_outgoing_streams);
4771   stream = nghttp2_session_get_stream(session, 2);
4772   CU_ASSERT(NGHTTP2_STREAM_OPENED == stream->state);
4773   CU_ASSERT(0 == (stream->flags & NGHTTP2_STREAM_FLAG_PUSH));
4774   nghttp2_session_del(session);
4775 }
4776 
test_nghttp2_session_send_rst_stream(void)4777 void test_nghttp2_session_send_rst_stream(void) {
4778   nghttp2_session *session;
4779   nghttp2_session_callbacks callbacks;
4780   my_user_data user_data;
4781   nghttp2_outbound_item *item;
4782   nghttp2_frame *frame;
4783   nghttp2_mem *mem;
4784 
4785   mem = nghttp2_mem_default();
4786 
4787   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4788   callbacks.send_callback = null_send_callback;
4789   nghttp2_session_client_new(&session, &callbacks, &user_data);
4790   open_sent_stream(session, 1);
4791 
4792   item = mem->malloc(sizeof(nghttp2_outbound_item), NULL);
4793 
4794   nghttp2_outbound_item_init(item);
4795 
4796   frame = &item->frame;
4797 
4798   nghttp2_frame_rst_stream_init(&frame->rst_stream, 1, NGHTTP2_PROTOCOL_ERROR);
4799   nghttp2_session_add_item(session, item);
4800   CU_ASSERT(0 == nghttp2_session_send(session));
4801 
4802   CU_ASSERT(NULL == nghttp2_session_get_stream(session, 1));
4803 
4804   nghttp2_session_del(session);
4805 }
4806 
test_nghttp2_session_send_push_promise(void)4807 void test_nghttp2_session_send_push_promise(void) {
4808   nghttp2_session *session;
4809   nghttp2_session_callbacks callbacks;
4810   nghttp2_outbound_item *item;
4811   nghttp2_frame *frame;
4812   nghttp2_stream *stream;
4813   nghttp2_settings_entry iv;
4814   my_user_data ud;
4815   nghttp2_mem *mem;
4816 
4817   mem = nghttp2_mem_default();
4818   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4819   callbacks.send_callback = null_send_callback;
4820   callbacks.on_frame_not_send_callback = on_frame_not_send_callback;
4821 
4822   nghttp2_session_server_new(&session, &callbacks, &ud);
4823   open_recv_stream(session, 1);
4824 
4825   item = mem->malloc(sizeof(nghttp2_outbound_item), NULL);
4826 
4827   nghttp2_outbound_item_init(item);
4828 
4829   frame = &item->frame;
4830 
4831   nghttp2_frame_push_promise_init(&frame->push_promise,
4832                                   NGHTTP2_FLAG_END_HEADERS, 1,
4833                                   (int32_t)session->next_stream_id, NULL, 0);
4834 
4835   session->next_stream_id += 2;
4836 
4837   nghttp2_session_add_item(session, item);
4838 
4839   CU_ASSERT(0 == nghttp2_session_send(session));
4840   stream = nghttp2_session_get_stream(session, 2);
4841   CU_ASSERT(NGHTTP2_STREAM_RESERVED == stream->state);
4842 
4843   /* Received ENABLE_PUSH = 0 */
4844   iv.settings_id = NGHTTP2_SETTINGS_ENABLE_PUSH;
4845   iv.value = 0;
4846   frame = mem->malloc(sizeof(nghttp2_frame), NULL);
4847   nghttp2_frame_settings_init(&frame->settings, NGHTTP2_FLAG_NONE,
4848                               dup_iv(&iv, 1), 1);
4849   nghttp2_session_on_settings_received(session, frame, 1);
4850   nghttp2_frame_settings_free(&frame->settings, mem);
4851   mem->free(frame, NULL);
4852 
4853   item = mem->malloc(sizeof(nghttp2_outbound_item), NULL);
4854 
4855   nghttp2_outbound_item_init(item);
4856 
4857   frame = &item->frame;
4858 
4859   nghttp2_frame_push_promise_init(&frame->push_promise,
4860                                   NGHTTP2_FLAG_END_HEADERS, 1, -1, NULL, 0);
4861   nghttp2_session_add_item(session, item);
4862 
4863   ud.frame_not_send_cb_called = 0;
4864   CU_ASSERT(0 == nghttp2_session_send(session));
4865 
4866   CU_ASSERT(1 == ud.frame_not_send_cb_called);
4867   CU_ASSERT(NGHTTP2_PUSH_PROMISE == ud.not_sent_frame_type);
4868   CU_ASSERT(NGHTTP2_ERR_PUSH_DISABLED == ud.not_sent_error);
4869 
4870   nghttp2_session_del(session);
4871 
4872   /* PUSH_PROMISE from client is error */
4873   nghttp2_session_client_new(&session, &callbacks, &ud);
4874   open_sent_stream(session, 1);
4875   item = mem->malloc(sizeof(nghttp2_outbound_item), NULL);
4876 
4877   nghttp2_outbound_item_init(item);
4878 
4879   frame = &item->frame;
4880 
4881   nghttp2_frame_push_promise_init(&frame->push_promise,
4882                                   NGHTTP2_FLAG_END_HEADERS, 1, -1, NULL, 0);
4883   nghttp2_session_add_item(session, item);
4884 
4885   CU_ASSERT(0 == nghttp2_session_send(session));
4886   CU_ASSERT(NULL == nghttp2_session_get_stream(session, 3));
4887 
4888   nghttp2_session_del(session);
4889 }
4890 
test_nghttp2_session_is_my_stream_id(void)4891 void test_nghttp2_session_is_my_stream_id(void) {
4892   nghttp2_session *session;
4893   nghttp2_session_callbacks callbacks;
4894   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4895   nghttp2_session_server_new(&session, &callbacks, NULL);
4896 
4897   CU_ASSERT(0 == nghttp2_session_is_my_stream_id(session, 0));
4898   CU_ASSERT(0 == nghttp2_session_is_my_stream_id(session, 1));
4899   CU_ASSERT(1 == nghttp2_session_is_my_stream_id(session, 2));
4900 
4901   nghttp2_session_del(session);
4902 
4903   nghttp2_session_client_new(&session, &callbacks, NULL);
4904 
4905   CU_ASSERT(0 == nghttp2_session_is_my_stream_id(session, 0));
4906   CU_ASSERT(1 == nghttp2_session_is_my_stream_id(session, 1));
4907   CU_ASSERT(0 == nghttp2_session_is_my_stream_id(session, 2));
4908 
4909   nghttp2_session_del(session);
4910 }
4911 
test_nghttp2_session_upgrade2(void)4912 void test_nghttp2_session_upgrade2(void) {
4913   nghttp2_session *session;
4914   nghttp2_session_callbacks callbacks;
4915   uint8_t settings_payload[128];
4916   size_t settings_payloadlen;
4917   nghttp2_settings_entry iv[16];
4918   nghttp2_stream *stream;
4919   nghttp2_outbound_item *item;
4920   ssize_t rv;
4921   nghttp2_bufs bufs;
4922   nghttp2_buf *buf;
4923   nghttp2_hd_deflater deflater;
4924   nghttp2_mem *mem;
4925 
4926   mem = nghttp2_mem_default();
4927   frame_pack_bufs_init(&bufs);
4928 
4929   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4930   callbacks.send_callback = null_send_callback;
4931   iv[0].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS;
4932   iv[0].value = 1;
4933   iv[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
4934   iv[1].value = 4095;
4935   settings_payloadlen = (size_t)nghttp2_pack_settings_payload(
4936       settings_payload, sizeof(settings_payload), iv, 2);
4937 
4938   /* Check client side */
4939   nghttp2_session_client_new(&session, &callbacks, NULL);
4940   CU_ASSERT(0 == nghttp2_session_upgrade2(session, settings_payload,
4941                                           settings_payloadlen, 0, &callbacks));
4942   CU_ASSERT(1 == session->last_sent_stream_id);
4943   stream = nghttp2_session_get_stream(session, 1);
4944   CU_ASSERT(stream != NULL);
4945   CU_ASSERT(&callbacks == stream->stream_user_data);
4946   CU_ASSERT(NGHTTP2_SHUT_WR == stream->shut_flags);
4947   item = nghttp2_session_get_next_ob_item(session);
4948   CU_ASSERT(NGHTTP2_SETTINGS == item->frame.hd.type);
4949   CU_ASSERT(2 == item->frame.settings.niv);
4950   CU_ASSERT(NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS ==
4951             item->frame.settings.iv[0].settings_id);
4952   CU_ASSERT(1 == item->frame.settings.iv[0].value);
4953   CU_ASSERT(NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE ==
4954             item->frame.settings.iv[1].settings_id);
4955   CU_ASSERT(4095 == item->frame.settings.iv[1].value);
4956 
4957   /* Call nghttp2_session_upgrade2() again is error */
4958   CU_ASSERT(NGHTTP2_ERR_PROTO ==
4959             nghttp2_session_upgrade2(session, settings_payload,
4960                                      settings_payloadlen, 0, &callbacks));
4961   nghttp2_session_del(session);
4962 
4963   /* Make sure that response from server can be received */
4964   nghttp2_session_client_new(&session, &callbacks, NULL);
4965 
4966   CU_ASSERT(0 == nghttp2_session_upgrade2(session, settings_payload,
4967                                           settings_payloadlen, 0, &callbacks));
4968 
4969   stream = nghttp2_session_get_stream(session, 1);
4970 
4971   CU_ASSERT(NGHTTP2_STREAM_OPENING == stream->state);
4972 
4973   nghttp2_hd_deflate_init(&deflater, mem);
4974   rv = pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, resnv,
4975                     ARRLEN(resnv), mem);
4976 
4977   CU_ASSERT(0 == rv);
4978 
4979   buf = &bufs.head->buf;
4980 
4981   rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
4982 
4983   CU_ASSERT(rv == (ssize_t)nghttp2_buf_len(buf));
4984   CU_ASSERT(NGHTTP2_STREAM_OPENED == stream->state);
4985 
4986   nghttp2_hd_deflate_free(&deflater);
4987   nghttp2_session_del(session);
4988 
4989   nghttp2_bufs_reset(&bufs);
4990 
4991   /* Check server side */
4992   nghttp2_session_server_new(&session, &callbacks, NULL);
4993   CU_ASSERT(0 == nghttp2_session_upgrade2(session, settings_payload,
4994                                           settings_payloadlen, 0, &callbacks));
4995   CU_ASSERT(1 == session->last_recv_stream_id);
4996   stream = nghttp2_session_get_stream(session, 1);
4997   CU_ASSERT(stream != NULL);
4998   CU_ASSERT(NULL == stream->stream_user_data);
4999   CU_ASSERT(NGHTTP2_SHUT_RD == stream->shut_flags);
5000   CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
5001   CU_ASSERT(1 == session->remote_settings.max_concurrent_streams);
5002   CU_ASSERT(4095 == session->remote_settings.initial_window_size);
5003   /* Call nghttp2_session_upgrade2() again is error */
5004   CU_ASSERT(NGHTTP2_ERR_PROTO ==
5005             nghttp2_session_upgrade2(session, settings_payload,
5006                                      settings_payloadlen, 0, &callbacks));
5007   nghttp2_session_del(session);
5008 
5009   /* Empty SETTINGS is OK */
5010   settings_payloadlen = (size_t)nghttp2_pack_settings_payload(
5011       settings_payload, sizeof(settings_payload), NULL, 0);
5012 
5013   nghttp2_session_client_new(&session, &callbacks, NULL);
5014   CU_ASSERT(0 == nghttp2_session_upgrade2(session, settings_payload,
5015                                           settings_payloadlen, 0, NULL));
5016   nghttp2_session_del(session);
5017   nghttp2_bufs_free(&bufs);
5018 }
5019 
test_nghttp2_session_reprioritize_stream(void)5020 void test_nghttp2_session_reprioritize_stream(void) {
5021   nghttp2_session *session;
5022   nghttp2_session_callbacks callbacks;
5023   nghttp2_stream *stream;
5024   nghttp2_stream *dep_stream;
5025   nghttp2_priority_spec pri_spec;
5026   int rv;
5027 
5028   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
5029   callbacks.send_callback = block_count_send_callback;
5030 
5031   nghttp2_session_server_new(&session, &callbacks, NULL);
5032 
5033   stream = open_recv_stream(session, 1);
5034 
5035   nghttp2_priority_spec_init(&pri_spec, 0, 10, 0);
5036 
5037   rv = nghttp2_session_reprioritize_stream(session, stream, &pri_spec);
5038 
5039   CU_ASSERT(0 == rv);
5040   CU_ASSERT(10 == stream->weight);
5041   CU_ASSERT(&session->root == stream->dep_prev);
5042 
5043   /* If dependency to idle stream which is not in dependency tree yet */
5044 
5045   nghttp2_priority_spec_init(&pri_spec, 3, 99, 0);
5046 
5047   rv = nghttp2_session_reprioritize_stream(session, stream, &pri_spec);
5048 
5049   CU_ASSERT(0 == rv);
5050   CU_ASSERT(99 == stream->weight);
5051   CU_ASSERT(3 == stream->dep_prev->stream_id);
5052 
5053   dep_stream = nghttp2_session_get_stream_raw(session, 3);
5054 
5055   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == dep_stream->weight);
5056 
5057   dep_stream = open_recv_stream(session, 3);
5058 
5059   /* Change weight */
5060   pri_spec.weight = 128;
5061 
5062   rv = nghttp2_session_reprioritize_stream(session, stream, &pri_spec);
5063 
5064   CU_ASSERT(0 == rv);
5065   CU_ASSERT(128 == stream->weight);
5066   CU_ASSERT(dep_stream == stream->dep_prev);
5067 
5068   /* Change weight again to test short-path case */
5069   pri_spec.weight = 100;
5070 
5071   rv = nghttp2_session_reprioritize_stream(session, stream, &pri_spec);
5072 
5073   CU_ASSERT(0 == rv);
5074   CU_ASSERT(100 == stream->weight);
5075   CU_ASSERT(dep_stream == stream->dep_prev);
5076   CU_ASSERT(100 == dep_stream->sum_dep_weight);
5077 
5078   /* Test circular dependency; stream 1 is first removed and becomes
5079      root.  Then stream 3 depends on it. */
5080   nghttp2_priority_spec_init(&pri_spec, 1, 1, 0);
5081 
5082   rv = nghttp2_session_reprioritize_stream(session, dep_stream, &pri_spec);
5083 
5084   CU_ASSERT(0 == rv);
5085   CU_ASSERT(1 == dep_stream->weight);
5086   CU_ASSERT(stream == dep_stream->dep_prev);
5087 
5088   /* Making priority to closed stream will result in default
5089      priority */
5090   session->last_recv_stream_id = 9;
5091 
5092   nghttp2_priority_spec_init(&pri_spec, 5, 5, 0);
5093 
5094   rv = nghttp2_session_reprioritize_stream(session, stream, &pri_spec);
5095 
5096   CU_ASSERT(0 == rv);
5097   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == stream->weight);
5098 
5099   nghttp2_session_del(session);
5100 
5101   nghttp2_session_server_new(&session, &callbacks, NULL);
5102 
5103   /* circular dependency; in case of stream which is not a direct
5104      descendant of root.  Use exclusive dependency. */
5105   stream = open_recv_stream(session, 1);
5106   stream = open_recv_stream_with_dep(session, 3, stream);
5107   stream = open_recv_stream_with_dep(session, 5, stream);
5108   stream = open_recv_stream_with_dep(session, 7, stream);
5109   open_recv_stream_with_dep(session, 9, stream);
5110 
5111   nghttp2_priority_spec_init(&pri_spec, 7, 1, 1);
5112 
5113   stream = nghttp2_session_get_stream(session, 3);
5114   rv = nghttp2_session_reprioritize_stream(session, stream, &pri_spec);
5115 
5116   CU_ASSERT(0 == rv);
5117   CU_ASSERT(7 == stream->dep_prev->stream_id);
5118 
5119   stream = nghttp2_session_get_stream(session, 7);
5120 
5121   CU_ASSERT(1 == stream->dep_prev->stream_id);
5122 
5123   stream = nghttp2_session_get_stream(session, 9);
5124 
5125   CU_ASSERT(3 == stream->dep_prev->stream_id);
5126 
5127   stream = nghttp2_session_get_stream(session, 5);
5128 
5129   CU_ASSERT(3 == stream->dep_prev->stream_id);
5130 
5131   nghttp2_session_del(session);
5132 
5133   nghttp2_session_server_new(&session, &callbacks, NULL);
5134 
5135   /* circular dependency; in case of stream which is not a direct
5136      descendant of root.  Without exclusive dependency. */
5137   stream = open_recv_stream(session, 1);
5138   stream = open_recv_stream_with_dep(session, 3, stream);
5139   stream = open_recv_stream_with_dep(session, 5, stream);
5140   stream = open_recv_stream_with_dep(session, 7, stream);
5141   open_recv_stream_with_dep(session, 9, stream);
5142 
5143   nghttp2_priority_spec_init(&pri_spec, 7, 1, 0);
5144 
5145   stream = nghttp2_session_get_stream(session, 3);
5146   rv = nghttp2_session_reprioritize_stream(session, stream, &pri_spec);
5147 
5148   CU_ASSERT(0 == rv);
5149   CU_ASSERT(7 == stream->dep_prev->stream_id);
5150 
5151   stream = nghttp2_session_get_stream(session, 7);
5152 
5153   CU_ASSERT(1 == stream->dep_prev->stream_id);
5154 
5155   stream = nghttp2_session_get_stream(session, 9);
5156 
5157   CU_ASSERT(7 == stream->dep_prev->stream_id);
5158 
5159   stream = nghttp2_session_get_stream(session, 5);
5160 
5161   CU_ASSERT(3 == stream->dep_prev->stream_id);
5162 
5163   nghttp2_session_del(session);
5164 }
5165 
test_nghttp2_session_reprioritize_stream_with_idle_stream_dep(void)5166 void test_nghttp2_session_reprioritize_stream_with_idle_stream_dep(void) {
5167   nghttp2_session *session;
5168   nghttp2_session_callbacks callbacks;
5169   nghttp2_stream *stream;
5170   nghttp2_priority_spec pri_spec;
5171 
5172   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
5173   callbacks.send_callback = block_count_send_callback;
5174 
5175   nghttp2_session_server_new(&session, &callbacks, NULL);
5176 
5177   stream = open_recv_stream(session, 1);
5178 
5179   session->pending_local_max_concurrent_stream = 1;
5180 
5181   nghttp2_priority_spec_init(&pri_spec, 101, 10, 0);
5182 
5183   nghttp2_session_reprioritize_stream(session, stream, &pri_spec);
5184 
5185   /* idle stream is not counteed to max concurrent streams */
5186 
5187   CU_ASSERT(10 == stream->weight);
5188   CU_ASSERT(101 == stream->dep_prev->stream_id);
5189 
5190   stream = nghttp2_session_get_stream_raw(session, 101);
5191 
5192   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == stream->weight);
5193 
5194   nghttp2_session_del(session);
5195 }
5196 
test_nghttp2_submit_data(void)5197 void test_nghttp2_submit_data(void) {
5198   nghttp2_session *session;
5199   nghttp2_session_callbacks callbacks;
5200   nghttp2_data_provider data_prd;
5201   my_user_data ud;
5202   nghttp2_frame *frame;
5203   nghttp2_frame_hd hd;
5204   nghttp2_active_outbound_item *aob;
5205   nghttp2_bufs *framebufs;
5206   nghttp2_buf *buf;
5207 
5208   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
5209   callbacks.send_callback = block_count_send_callback;
5210 
5211   data_prd.read_callback = fixed_length_data_source_read_callback;
5212   ud.data_source_length = NGHTTP2_DATA_PAYLOADLEN * 2;
5213   CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, &ud));
5214   aob = &session->aob;
5215   framebufs = &aob->framebufs;
5216 
5217   open_sent_stream(session, 1);
5218 
5219   CU_ASSERT(
5220       0 == nghttp2_submit_data(session, NGHTTP2_FLAG_END_STREAM, 1, &data_prd));
5221 
5222   ud.block_count = 0;
5223   CU_ASSERT(0 == nghttp2_session_send(session));
5224   frame = &aob->item->frame;
5225 
5226   buf = &framebufs->head->buf;
5227   nghttp2_frame_unpack_frame_hd(&hd, buf->pos);
5228 
5229   CU_ASSERT(NGHTTP2_FLAG_NONE == hd.flags);
5230   CU_ASSERT(NGHTTP2_FLAG_NONE == frame->hd.flags);
5231   /* aux_data.data.flags has these flags */
5232   CU_ASSERT(NGHTTP2_FLAG_END_STREAM == aob->item->aux_data.data.flags);
5233 
5234   nghttp2_session_del(session);
5235 }
5236 
test_nghttp2_submit_data_read_length_too_large(void)5237 void test_nghttp2_submit_data_read_length_too_large(void) {
5238   nghttp2_session *session;
5239   nghttp2_session_callbacks callbacks;
5240   nghttp2_data_provider data_prd;
5241   my_user_data ud;
5242   nghttp2_frame *frame;
5243   nghttp2_frame_hd hd;
5244   nghttp2_active_outbound_item *aob;
5245   nghttp2_bufs *framebufs;
5246   nghttp2_buf *buf;
5247   size_t payloadlen;
5248 
5249   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
5250   callbacks.send_callback = block_count_send_callback;
5251   callbacks.read_length_callback = too_large_data_source_length_callback;
5252 
5253   data_prd.read_callback = fixed_length_data_source_read_callback;
5254   ud.data_source_length = NGHTTP2_DATA_PAYLOADLEN * 2;
5255   CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, &ud));
5256   aob = &session->aob;
5257   framebufs = &aob->framebufs;
5258 
5259   open_sent_stream(session, 1);
5260 
5261   CU_ASSERT(
5262       0 == nghttp2_submit_data(session, NGHTTP2_FLAG_END_STREAM, 1, &data_prd));
5263 
5264   ud.block_count = 0;
5265   CU_ASSERT(0 == nghttp2_session_send(session));
5266   frame = &aob->item->frame;
5267 
5268   buf = &framebufs->head->buf;
5269   nghttp2_frame_unpack_frame_hd(&hd, buf->pos);
5270 
5271   CU_ASSERT(NGHTTP2_FLAG_NONE == hd.flags);
5272   CU_ASSERT(NGHTTP2_FLAG_NONE == frame->hd.flags);
5273   CU_ASSERT(16384 == hd.length)
5274   /* aux_data.data.flags has these flags */
5275   CU_ASSERT(NGHTTP2_FLAG_END_STREAM == aob->item->aux_data.data.flags);
5276 
5277   nghttp2_session_del(session);
5278 
5279   /* Check that buffers are expanded */
5280   CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, &ud));
5281 
5282   ud.data_source_length = NGHTTP2_MAX_FRAME_SIZE_MAX;
5283 
5284   session->remote_settings.max_frame_size = NGHTTP2_MAX_FRAME_SIZE_MAX;
5285 
5286   open_sent_stream(session, 1);
5287 
5288   CU_ASSERT(
5289       0 == nghttp2_submit_data(session, NGHTTP2_FLAG_END_STREAM, 1, &data_prd));
5290 
5291   ud.block_count = 0;
5292   CU_ASSERT(0 == nghttp2_session_send(session));
5293 
5294   aob = &session->aob;
5295 
5296   frame = &aob->item->frame;
5297 
5298   framebufs = &aob->framebufs;
5299 
5300   buf = &framebufs->head->buf;
5301   nghttp2_frame_unpack_frame_hd(&hd, buf->pos);
5302 
5303   payloadlen = nghttp2_min(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE,
5304                            NGHTTP2_INITIAL_WINDOW_SIZE);
5305 
5306   CU_ASSERT(NGHTTP2_FRAME_HDLEN + 1 + payloadlen ==
5307             (size_t)nghttp2_buf_cap(buf));
5308   CU_ASSERT(NGHTTP2_FLAG_NONE == hd.flags);
5309   CU_ASSERT(NGHTTP2_FLAG_NONE == frame->hd.flags);
5310   CU_ASSERT(payloadlen == hd.length);
5311   /* aux_data.data.flags has these flags */
5312   CU_ASSERT(NGHTTP2_FLAG_END_STREAM == aob->item->aux_data.data.flags);
5313 
5314   nghttp2_session_del(session);
5315 }
5316 
test_nghttp2_submit_data_read_length_smallest(void)5317 void test_nghttp2_submit_data_read_length_smallest(void) {
5318   nghttp2_session *session;
5319   nghttp2_session_callbacks callbacks;
5320   nghttp2_data_provider data_prd;
5321   my_user_data ud;
5322   nghttp2_frame *frame;
5323   nghttp2_frame_hd hd;
5324   nghttp2_active_outbound_item *aob;
5325   nghttp2_bufs *framebufs;
5326   nghttp2_buf *buf;
5327 
5328   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
5329   callbacks.send_callback = block_count_send_callback;
5330   callbacks.read_length_callback = smallest_length_data_source_length_callback;
5331 
5332   data_prd.read_callback = fixed_length_data_source_read_callback;
5333   ud.data_source_length = NGHTTP2_DATA_PAYLOADLEN * 2;
5334   CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, &ud));
5335   aob = &session->aob;
5336   framebufs = &aob->framebufs;
5337 
5338   open_sent_stream(session, 1);
5339 
5340   CU_ASSERT(
5341       0 == nghttp2_submit_data(session, NGHTTP2_FLAG_END_STREAM, 1, &data_prd));
5342 
5343   ud.block_count = 0;
5344   CU_ASSERT(0 == nghttp2_session_send(session));
5345   frame = &aob->item->frame;
5346 
5347   buf = &framebufs->head->buf;
5348   nghttp2_frame_unpack_frame_hd(&hd, buf->pos);
5349 
5350   CU_ASSERT(NGHTTP2_FLAG_NONE == hd.flags);
5351   CU_ASSERT(NGHTTP2_FLAG_NONE == frame->hd.flags);
5352   CU_ASSERT(1 == hd.length)
5353   /* aux_data.data.flags has these flags */
5354   CU_ASSERT(NGHTTP2_FLAG_END_STREAM == aob->item->aux_data.data.flags);
5355 
5356   nghttp2_session_del(session);
5357 }
5358 
submit_data_twice_data_source_read_callback(nghttp2_session * session,int32_t stream_id,uint8_t * buf,size_t len,uint32_t * data_flags,nghttp2_data_source * source,void * user_data)5359 static ssize_t submit_data_twice_data_source_read_callback(
5360     nghttp2_session *session, int32_t stream_id, uint8_t *buf, size_t len,
5361     uint32_t *data_flags, nghttp2_data_source *source, void *user_data) {
5362   (void)session;
5363   (void)stream_id;
5364   (void)buf;
5365   (void)source;
5366   (void)user_data;
5367 
5368   *data_flags |= NGHTTP2_DATA_FLAG_EOF;
5369   return (ssize_t)nghttp2_min(len, 16);
5370 }
5371 
submit_data_twice_on_frame_send_callback(nghttp2_session * session,const nghttp2_frame * frame,void * user_data)5372 static int submit_data_twice_on_frame_send_callback(nghttp2_session *session,
5373                                                     const nghttp2_frame *frame,
5374                                                     void *user_data) {
5375   static int called = 0;
5376   int rv;
5377   nghttp2_data_provider data_prd;
5378   (void)user_data;
5379 
5380   if (called == 0) {
5381     called = 1;
5382 
5383     data_prd.read_callback = submit_data_twice_data_source_read_callback;
5384 
5385     rv = nghttp2_submit_data(session, NGHTTP2_FLAG_END_STREAM,
5386                              frame->hd.stream_id, &data_prd);
5387     CU_ASSERT(0 == rv);
5388   }
5389 
5390   return 0;
5391 }
5392 
test_nghttp2_submit_data_twice(void)5393 void test_nghttp2_submit_data_twice(void) {
5394   nghttp2_session *session;
5395   nghttp2_session_callbacks callbacks;
5396   nghttp2_data_provider data_prd;
5397   my_user_data ud;
5398   accumulator acc;
5399 
5400   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
5401   callbacks.send_callback = accumulator_send_callback;
5402   callbacks.on_frame_send_callback = submit_data_twice_on_frame_send_callback;
5403 
5404   data_prd.read_callback = submit_data_twice_data_source_read_callback;
5405 
5406   acc.length = 0;
5407   ud.acc = &acc;
5408 
5409   CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, &ud));
5410 
5411   open_sent_stream(session, 1);
5412 
5413   CU_ASSERT(0 == nghttp2_submit_data(session, NGHTTP2_FLAG_NONE, 1, &data_prd));
5414   CU_ASSERT(0 == nghttp2_session_send(session));
5415 
5416   /* We should have sent 2 DATA frame with 16 bytes payload each */
5417   CU_ASSERT(NGHTTP2_FRAME_HDLEN * 2 + 16 * 2 == acc.length);
5418 
5419   nghttp2_session_del(session);
5420 }
5421 
test_nghttp2_submit_request_with_data(void)5422 void test_nghttp2_submit_request_with_data(void) {
5423   nghttp2_session *session;
5424   nghttp2_session_callbacks callbacks;
5425   nghttp2_data_provider data_prd;
5426   my_user_data ud;
5427   nghttp2_outbound_item *item;
5428   nghttp2_mem *mem;
5429 
5430   mem = nghttp2_mem_default();
5431 
5432   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
5433   callbacks.send_callback = null_send_callback;
5434 
5435   data_prd.read_callback = fixed_length_data_source_read_callback;
5436   ud.data_source_length = 64 * 1024 - 1;
5437   CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, &ud));
5438   CU_ASSERT(1 == nghttp2_submit_request(session, NULL, reqnv, ARRLEN(reqnv),
5439                                         &data_prd, NULL));
5440   item = nghttp2_session_get_next_ob_item(session);
5441   CU_ASSERT(ARRLEN(reqnv) == item->frame.headers.nvlen);
5442   assert_nv_equal(reqnv, item->frame.headers.nva, item->frame.headers.nvlen,
5443                   mem);
5444   CU_ASSERT(0 == nghttp2_session_send(session));
5445   CU_ASSERT(0 == ud.data_source_length);
5446 
5447   nghttp2_session_del(session);
5448 
5449   /* nghttp2_submit_request() with server session is error */
5450   nghttp2_session_server_new(&session, &callbacks, NULL);
5451 
5452   CU_ASSERT(NGHTTP2_ERR_PROTO == nghttp2_submit_request(session, NULL, reqnv,
5453                                                         ARRLEN(reqnv), NULL,
5454                                                         NULL));
5455 
5456   nghttp2_session_del(session);
5457 }
5458 
test_nghttp2_submit_request_without_data(void)5459 void test_nghttp2_submit_request_without_data(void) {
5460   nghttp2_session *session;
5461   nghttp2_session_callbacks callbacks;
5462   accumulator acc;
5463   nghttp2_data_provider data_prd = {{-1}, NULL};
5464   nghttp2_outbound_item *item;
5465   my_user_data ud;
5466   nghttp2_frame frame;
5467   nghttp2_hd_inflater inflater;
5468   nva_out out;
5469   nghttp2_bufs bufs;
5470   nghttp2_mem *mem;
5471   nghttp2_priority_spec pri_spec;
5472 
5473   mem = nghttp2_mem_default();
5474   frame_pack_bufs_init(&bufs);
5475 
5476   nva_out_init(&out);
5477   acc.length = 0;
5478   ud.acc = &acc;
5479   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
5480   callbacks.send_callback = accumulator_send_callback;
5481   CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, &ud));
5482 
5483   nghttp2_hd_inflate_init(&inflater, mem);
5484   CU_ASSERT(1 == nghttp2_submit_request(session, NULL, reqnv, ARRLEN(reqnv),
5485                                         &data_prd, NULL));
5486   item = nghttp2_session_get_next_ob_item(session);
5487   CU_ASSERT(ARRLEN(reqnv) == item->frame.headers.nvlen);
5488   assert_nv_equal(reqnv, item->frame.headers.nva, item->frame.headers.nvlen,
5489                   mem);
5490   CU_ASSERT(item->frame.hd.flags & NGHTTP2_FLAG_END_STREAM);
5491 
5492   CU_ASSERT(0 == nghttp2_session_send(session));
5493   CU_ASSERT(0 == unpack_frame(&frame, acc.buf, acc.length));
5494 
5495   nghttp2_bufs_add(&bufs, acc.buf, acc.length);
5496   inflate_hd(&inflater, &out, &bufs, NGHTTP2_FRAME_HDLEN, mem);
5497 
5498   CU_ASSERT(ARRLEN(reqnv) == out.nvlen);
5499   assert_nv_equal(reqnv, out.nva, out.nvlen, mem);
5500   nghttp2_frame_headers_free(&frame.headers, mem);
5501   nva_out_reset(&out, mem);
5502 
5503   nghttp2_bufs_free(&bufs);
5504   nghttp2_hd_inflate_free(&inflater);
5505 
5506   /* Try to depend on itself is error */
5507   nghttp2_priority_spec_init(&pri_spec, (int32_t)session->next_stream_id, 16,
5508                              0);
5509 
5510   CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT ==
5511             nghttp2_submit_request(session, &pri_spec, reqnv, ARRLEN(reqnv),
5512                                    NULL, NULL));
5513 
5514   nghttp2_session_del(session);
5515 }
5516 
test_nghttp2_submit_response_with_data(void)5517 void test_nghttp2_submit_response_with_data(void) {
5518   nghttp2_session *session;
5519   nghttp2_session_callbacks callbacks;
5520   nghttp2_data_provider data_prd;
5521   my_user_data ud;
5522   nghttp2_outbound_item *item;
5523   nghttp2_mem *mem;
5524 
5525   mem = nghttp2_mem_default();
5526 
5527   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
5528   callbacks.send_callback = null_send_callback;
5529 
5530   data_prd.read_callback = fixed_length_data_source_read_callback;
5531   ud.data_source_length = 64 * 1024 - 1;
5532   CU_ASSERT(0 == nghttp2_session_server_new(&session, &callbacks, &ud));
5533   open_recv_stream2(session, 1, NGHTTP2_STREAM_OPENING);
5534   CU_ASSERT(0 == nghttp2_submit_response(session, 1, resnv, ARRLEN(resnv),
5535                                          &data_prd));
5536   item = nghttp2_session_get_next_ob_item(session);
5537   CU_ASSERT(ARRLEN(resnv) == item->frame.headers.nvlen);
5538   assert_nv_equal(resnv, item->frame.headers.nva, item->frame.headers.nvlen,
5539                   mem);
5540   CU_ASSERT(0 == nghttp2_session_send(session));
5541   CU_ASSERT(0 == ud.data_source_length);
5542 
5543   nghttp2_session_del(session);
5544 
5545   /* Various error cases */
5546   nghttp2_session_client_new(&session, &callbacks, NULL);
5547 
5548   /* Calling nghttp2_submit_response() with client session is error */
5549   CU_ASSERT(NGHTTP2_ERR_PROTO ==
5550             nghttp2_submit_response(session, 1, resnv, ARRLEN(resnv), NULL));
5551 
5552   /* Stream ID <= 0 is error */
5553   CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT ==
5554             nghttp2_submit_response(session, 0, resnv, ARRLEN(resnv), NULL));
5555 
5556   nghttp2_session_del(session);
5557 }
5558 
test_nghttp2_submit_response_without_data(void)5559 void test_nghttp2_submit_response_without_data(void) {
5560   nghttp2_session *session;
5561   nghttp2_session_callbacks callbacks;
5562   accumulator acc;
5563   nghttp2_data_provider data_prd = {{-1}, NULL};
5564   nghttp2_outbound_item *item;
5565   my_user_data ud;
5566   nghttp2_frame frame;
5567   nghttp2_hd_inflater inflater;
5568   nva_out out;
5569   nghttp2_bufs bufs;
5570   nghttp2_mem *mem;
5571 
5572   mem = nghttp2_mem_default();
5573   frame_pack_bufs_init(&bufs);
5574 
5575   nva_out_init(&out);
5576   acc.length = 0;
5577   ud.acc = &acc;
5578   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
5579   callbacks.send_callback = accumulator_send_callback;
5580   CU_ASSERT(0 == nghttp2_session_server_new(&session, &callbacks, &ud));
5581 
5582   nghttp2_hd_inflate_init(&inflater, mem);
5583   open_recv_stream2(session, 1, NGHTTP2_STREAM_OPENING);
5584   CU_ASSERT(0 == nghttp2_submit_response(session, 1, resnv, ARRLEN(resnv),
5585                                          &data_prd));
5586   item = nghttp2_session_get_next_ob_item(session);
5587   CU_ASSERT(ARRLEN(resnv) == item->frame.headers.nvlen);
5588   assert_nv_equal(resnv, item->frame.headers.nva, item->frame.headers.nvlen,
5589                   mem);
5590   CU_ASSERT(item->frame.hd.flags & NGHTTP2_FLAG_END_STREAM);
5591 
5592   CU_ASSERT(0 == nghttp2_session_send(session));
5593   CU_ASSERT(0 == unpack_frame(&frame, acc.buf, acc.length));
5594 
5595   nghttp2_bufs_add(&bufs, acc.buf, acc.length);
5596   inflate_hd(&inflater, &out, &bufs, NGHTTP2_FRAME_HDLEN, mem);
5597 
5598   CU_ASSERT(ARRLEN(resnv) == out.nvlen);
5599   assert_nv_equal(resnv, out.nva, out.nvlen, mem);
5600 
5601   nva_out_reset(&out, mem);
5602   nghttp2_bufs_free(&bufs);
5603   nghttp2_frame_headers_free(&frame.headers, mem);
5604   nghttp2_hd_inflate_free(&inflater);
5605   nghttp2_session_del(session);
5606 }
5607 
test_nghttp2_submit_response_push_response(void)5608 void test_nghttp2_submit_response_push_response(void) {
5609   nghttp2_session *session;
5610   nghttp2_session_callbacks callbacks;
5611   my_user_data ud;
5612 
5613   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
5614   callbacks.send_callback = null_send_callback;
5615   callbacks.on_frame_not_send_callback = on_frame_not_send_callback;
5616 
5617   nghttp2_session_server_new(&session, &callbacks, &ud);
5618 
5619   open_sent_stream2(session, 2, NGHTTP2_STREAM_RESERVED);
5620 
5621   session->goaway_flags |= NGHTTP2_GOAWAY_RECV;
5622 
5623   CU_ASSERT(0 ==
5624             nghttp2_submit_response(session, 2, resnv, ARRLEN(resnv), NULL));
5625 
5626   ud.frame_not_send_cb_called = 0;
5627 
5628   CU_ASSERT(0 == nghttp2_session_send(session));
5629   CU_ASSERT(1 == ud.frame_not_send_cb_called);
5630 
5631   nghttp2_session_del(session);
5632 }
5633 
test_nghttp2_submit_trailer(void)5634 void test_nghttp2_submit_trailer(void) {
5635   nghttp2_session *session;
5636   nghttp2_session_callbacks callbacks;
5637   accumulator acc;
5638   nghttp2_data_provider data_prd;
5639   nghttp2_outbound_item *item;
5640   my_user_data ud;
5641   nghttp2_frame frame;
5642   nghttp2_hd_inflater inflater;
5643   nva_out out;
5644   nghttp2_bufs bufs;
5645   nghttp2_mem *mem;
5646 
5647   mem = nghttp2_mem_default();
5648   frame_pack_bufs_init(&bufs);
5649 
5650   data_prd.read_callback = no_end_stream_data_source_read_callback;
5651   nva_out_init(&out);
5652   acc.length = 0;
5653   ud.acc = &acc;
5654   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
5655   callbacks.send_callback = null_send_callback;
5656   CU_ASSERT(0 == nghttp2_session_server_new(&session, &callbacks, &ud));
5657 
5658   nghttp2_hd_inflate_init(&inflater, mem);
5659   open_recv_stream2(session, 1, NGHTTP2_STREAM_OPENING);
5660   CU_ASSERT(0 == nghttp2_submit_response(session, 1, resnv, ARRLEN(resnv),
5661                                          &data_prd));
5662   CU_ASSERT(0 == nghttp2_session_send(session));
5663 
5664   CU_ASSERT(0 ==
5665             nghttp2_submit_trailer(session, 1, trailernv, ARRLEN(trailernv)));
5666 
5667   session->callbacks.send_callback = accumulator_send_callback;
5668 
5669   item = nghttp2_session_get_next_ob_item(session);
5670   CU_ASSERT(NGHTTP2_HEADERS == item->frame.hd.type);
5671   CU_ASSERT(NGHTTP2_HCAT_HEADERS == item->frame.headers.cat);
5672   CU_ASSERT(item->frame.hd.flags & NGHTTP2_FLAG_END_STREAM);
5673 
5674   CU_ASSERT(0 == nghttp2_session_send(session));
5675   CU_ASSERT(0 == unpack_frame(&frame, acc.buf, acc.length));
5676 
5677   nghttp2_bufs_add(&bufs, acc.buf, acc.length);
5678   inflate_hd(&inflater, &out, &bufs, NGHTTP2_FRAME_HDLEN, mem);
5679 
5680   CU_ASSERT(ARRLEN(trailernv) == out.nvlen);
5681   assert_nv_equal(trailernv, out.nva, out.nvlen, mem);
5682 
5683   nva_out_reset(&out, mem);
5684   nghttp2_bufs_free(&bufs);
5685   nghttp2_frame_headers_free(&frame.headers, mem);
5686   nghttp2_hd_inflate_free(&inflater);
5687   nghttp2_session_del(session);
5688 
5689   /* Specifying stream ID <= 0 is error */
5690   nghttp2_session_server_new(&session, &callbacks, NULL);
5691   open_recv_stream(session, 1);
5692 
5693   CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT ==
5694             nghttp2_submit_trailer(session, 0, trailernv, ARRLEN(trailernv)));
5695 
5696   CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT ==
5697             nghttp2_submit_trailer(session, -1, trailernv, ARRLEN(trailernv)));
5698 
5699   nghttp2_session_del(session);
5700 }
5701 
test_nghttp2_submit_headers_start_stream(void)5702 void test_nghttp2_submit_headers_start_stream(void) {
5703   nghttp2_session *session;
5704   nghttp2_session_callbacks callbacks;
5705   nghttp2_outbound_item *item;
5706   nghttp2_mem *mem;
5707 
5708   mem = nghttp2_mem_default();
5709 
5710   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
5711   CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, NULL));
5712   CU_ASSERT(1 == nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, -1,
5713                                         NULL, reqnv, ARRLEN(reqnv), NULL));
5714   item = nghttp2_session_get_next_ob_item(session);
5715   CU_ASSERT(ARRLEN(reqnv) == item->frame.headers.nvlen);
5716   assert_nv_equal(reqnv, item->frame.headers.nva, item->frame.headers.nvlen,
5717                   mem);
5718   CU_ASSERT((NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM) ==
5719             item->frame.hd.flags);
5720   CU_ASSERT(0 == (item->frame.hd.flags & NGHTTP2_FLAG_PRIORITY));
5721 
5722   nghttp2_session_del(session);
5723 }
5724 
test_nghttp2_submit_headers_reply(void)5725 void test_nghttp2_submit_headers_reply(void) {
5726   nghttp2_session *session;
5727   nghttp2_session_callbacks callbacks;
5728   my_user_data ud;
5729   nghttp2_outbound_item *item;
5730   nghttp2_stream *stream;
5731   nghttp2_mem *mem;
5732 
5733   mem = nghttp2_mem_default();
5734 
5735   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
5736   callbacks.send_callback = null_send_callback;
5737   callbacks.on_frame_send_callback = on_frame_send_callback;
5738 
5739   CU_ASSERT(0 == nghttp2_session_server_new(&session, &callbacks, &ud));
5740   CU_ASSERT(0 == nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, 1,
5741                                         NULL, resnv, ARRLEN(resnv), NULL));
5742   item = nghttp2_session_get_next_ob_item(session);
5743   CU_ASSERT(ARRLEN(resnv) == item->frame.headers.nvlen);
5744   assert_nv_equal(resnv, item->frame.headers.nva, item->frame.headers.nvlen,
5745                   mem);
5746   CU_ASSERT((NGHTTP2_FLAG_END_STREAM | NGHTTP2_FLAG_END_HEADERS) ==
5747             item->frame.hd.flags);
5748 
5749   ud.frame_send_cb_called = 0;
5750   ud.sent_frame_type = 0;
5751   /* The transimission will be canceled because the stream 1 is not
5752      open. */
5753   CU_ASSERT(0 == nghttp2_session_send(session));
5754   CU_ASSERT(0 == ud.frame_send_cb_called);
5755 
5756   stream = open_recv_stream2(session, 1, NGHTTP2_STREAM_OPENING);
5757 
5758   CU_ASSERT(0 == nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, 1,
5759                                         NULL, resnv, ARRLEN(resnv), NULL));
5760   CU_ASSERT(0 == nghttp2_session_send(session));
5761   CU_ASSERT(1 == ud.frame_send_cb_called);
5762   CU_ASSERT(NGHTTP2_HEADERS == ud.sent_frame_type);
5763   CU_ASSERT(stream->shut_flags & NGHTTP2_SHUT_WR);
5764 
5765   nghttp2_session_del(session);
5766 }
5767 
test_nghttp2_submit_headers_push_reply(void)5768 void test_nghttp2_submit_headers_push_reply(void) {
5769   nghttp2_session *session;
5770   nghttp2_session_callbacks callbacks;
5771   my_user_data ud;
5772   nghttp2_stream *stream;
5773   int foo;
5774 
5775   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
5776   callbacks.send_callback = null_send_callback;
5777   callbacks.on_frame_send_callback = on_frame_send_callback;
5778 
5779   CU_ASSERT(0 == nghttp2_session_server_new(&session, &callbacks, &ud));
5780   stream = open_sent_stream2(session, 2, NGHTTP2_STREAM_RESERVED);
5781   CU_ASSERT(0 == nghttp2_submit_headers(session, NGHTTP2_FLAG_NONE, 2, NULL,
5782                                         resnv, ARRLEN(resnv), &foo));
5783 
5784   ud.frame_send_cb_called = 0;
5785   ud.sent_frame_type = 0;
5786   CU_ASSERT(0 == nghttp2_session_send(session));
5787   CU_ASSERT(1 == ud.frame_send_cb_called);
5788   CU_ASSERT(NGHTTP2_HEADERS == ud.sent_frame_type);
5789   CU_ASSERT(NGHTTP2_STREAM_OPENED == stream->state);
5790   CU_ASSERT(&foo == stream->stream_user_data);
5791 
5792   nghttp2_session_del(session);
5793 
5794   /* Sending HEADERS from client against stream in reserved state is
5795      error */
5796   CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, &ud));
5797   open_recv_stream2(session, 2, NGHTTP2_STREAM_RESERVED);
5798   CU_ASSERT(0 == nghttp2_submit_headers(session, NGHTTP2_FLAG_NONE, 2, NULL,
5799                                         reqnv, ARRLEN(reqnv), NULL));
5800 
5801   ud.frame_send_cb_called = 0;
5802   ud.sent_frame_type = 0;
5803   CU_ASSERT(0 == nghttp2_session_send(session));
5804   CU_ASSERT(0 == ud.frame_send_cb_called);
5805 
5806   nghttp2_session_del(session);
5807 }
5808 
test_nghttp2_submit_headers(void)5809 void test_nghttp2_submit_headers(void) {
5810   nghttp2_session *session;
5811   nghttp2_session_callbacks callbacks;
5812   my_user_data ud;
5813   nghttp2_outbound_item *item;
5814   nghttp2_stream *stream;
5815   accumulator acc;
5816   nghttp2_frame frame;
5817   nghttp2_hd_inflater inflater;
5818   nva_out out;
5819   nghttp2_bufs bufs;
5820   nghttp2_mem *mem;
5821   nghttp2_priority_spec pri_spec;
5822 
5823   mem = nghttp2_mem_default();
5824   frame_pack_bufs_init(&bufs);
5825 
5826   nva_out_init(&out);
5827   acc.length = 0;
5828   ud.acc = &acc;
5829   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
5830   callbacks.send_callback = accumulator_send_callback;
5831   callbacks.on_frame_send_callback = on_frame_send_callback;
5832 
5833   CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, &ud));
5834 
5835   nghttp2_hd_inflate_init(&inflater, mem);
5836   CU_ASSERT(0 == nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, 1,
5837                                         NULL, reqnv, ARRLEN(reqnv), NULL));
5838   item = nghttp2_session_get_next_ob_item(session);
5839   CU_ASSERT(ARRLEN(reqnv) == item->frame.headers.nvlen);
5840   assert_nv_equal(reqnv, item->frame.headers.nva, item->frame.headers.nvlen,
5841                   mem);
5842   CU_ASSERT((NGHTTP2_FLAG_END_STREAM | NGHTTP2_FLAG_END_HEADERS) ==
5843             item->frame.hd.flags);
5844 
5845   ud.frame_send_cb_called = 0;
5846   ud.sent_frame_type = 0;
5847   /* The transimission will be canceled because the stream 1 is not
5848      open. */
5849   CU_ASSERT(0 == nghttp2_session_send(session));
5850   CU_ASSERT(0 == ud.frame_send_cb_called);
5851 
5852   stream = open_sent_stream(session, 1);
5853 
5854   CU_ASSERT(0 == nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, 1,
5855                                         NULL, reqnv, ARRLEN(reqnv), NULL));
5856   CU_ASSERT(0 == nghttp2_session_send(session));
5857   CU_ASSERT(1 == ud.frame_send_cb_called);
5858   CU_ASSERT(NGHTTP2_HEADERS == ud.sent_frame_type);
5859   CU_ASSERT(stream->shut_flags & NGHTTP2_SHUT_WR);
5860 
5861   CU_ASSERT(0 == unpack_frame(&frame, acc.buf, acc.length));
5862 
5863   nghttp2_bufs_add(&bufs, acc.buf, acc.length);
5864   inflate_hd(&inflater, &out, &bufs, NGHTTP2_FRAME_HDLEN, mem);
5865 
5866   CU_ASSERT(ARRLEN(reqnv) == out.nvlen);
5867   assert_nv_equal(reqnv, out.nva, out.nvlen, mem);
5868 
5869   nva_out_reset(&out, mem);
5870   nghttp2_bufs_free(&bufs);
5871   nghttp2_frame_headers_free(&frame.headers, mem);
5872 
5873   nghttp2_hd_inflate_free(&inflater);
5874 
5875   /* Try to depend on itself */
5876   nghttp2_priority_spec_init(&pri_spec, 3, 16, 0);
5877 
5878   CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT ==
5879             nghttp2_submit_headers(session, NGHTTP2_FLAG_NONE, 3, &pri_spec,
5880                                    reqnv, ARRLEN(reqnv), NULL));
5881 
5882   session->next_stream_id = 5;
5883   nghttp2_priority_spec_init(&pri_spec, 5, 16, 0);
5884 
5885   CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT ==
5886             nghttp2_submit_headers(session, NGHTTP2_FLAG_NONE, -1, &pri_spec,
5887                                    reqnv, ARRLEN(reqnv), NULL));
5888 
5889   nghttp2_session_del(session);
5890 
5891   /* Error cases with invalid stream ID */
5892   nghttp2_session_server_new(&session, &callbacks, NULL);
5893 
5894   /* Sending nghttp2_submit_headers() with stream_id == 1 and server
5895      session is error */
5896   CU_ASSERT(NGHTTP2_ERR_PROTO ==
5897             nghttp2_submit_headers(session, NGHTTP2_FLAG_NONE, -1, NULL, reqnv,
5898                                    ARRLEN(reqnv), NULL));
5899 
5900   /* Sending stream ID <= 0 is error */
5901   CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT ==
5902             nghttp2_submit_headers(session, NGHTTP2_FLAG_NONE, 0, NULL, resnv,
5903                                    ARRLEN(resnv), NULL));
5904 
5905   nghttp2_session_del(session);
5906 }
5907 
test_nghttp2_submit_headers_continuation(void)5908 void test_nghttp2_submit_headers_continuation(void) {
5909   nghttp2_session *session;
5910   nghttp2_session_callbacks callbacks;
5911   nghttp2_nv nv[] = {
5912       MAKE_NV("h1", ""), MAKE_NV("h1", ""), MAKE_NV("h1", ""),
5913       MAKE_NV("h1", ""), MAKE_NV("h1", ""), MAKE_NV("h1", ""),
5914       MAKE_NV("h1", ""),
5915   };
5916   nghttp2_outbound_item *item;
5917   uint8_t data[4096];
5918   size_t i;
5919   my_user_data ud;
5920 
5921   memset(data, '0', sizeof(data));
5922   for (i = 0; i < ARRLEN(nv); ++i) {
5923     nv[i].valuelen = sizeof(data);
5924     nv[i].value = data;
5925   }
5926 
5927   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
5928   callbacks.send_callback = null_send_callback;
5929   callbacks.on_frame_send_callback = on_frame_send_callback;
5930 
5931   CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, &ud));
5932   CU_ASSERT(1 == nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, -1,
5933                                         NULL, nv, ARRLEN(nv), NULL));
5934   item = nghttp2_session_get_next_ob_item(session);
5935   CU_ASSERT(NGHTTP2_HEADERS == item->frame.hd.type);
5936   CU_ASSERT((NGHTTP2_FLAG_END_STREAM | NGHTTP2_FLAG_END_HEADERS) ==
5937             item->frame.hd.flags);
5938   CU_ASSERT(0 == (item->frame.hd.flags & NGHTTP2_FLAG_PRIORITY));
5939 
5940   ud.frame_send_cb_called = 0;
5941   CU_ASSERT(0 == nghttp2_session_send(session));
5942   CU_ASSERT(1 == ud.frame_send_cb_called);
5943 
5944   nghttp2_session_del(session);
5945 }
5946 
test_nghttp2_submit_headers_continuation_extra_large(void)5947 void test_nghttp2_submit_headers_continuation_extra_large(void) {
5948   nghttp2_session *session;
5949   nghttp2_session_callbacks callbacks;
5950   nghttp2_nv nv[] = {
5951       MAKE_NV("h1", ""), MAKE_NV("h1", ""), MAKE_NV("h1", ""),
5952       MAKE_NV("h1", ""), MAKE_NV("h1", ""), MAKE_NV("h1", ""),
5953   };
5954   nghttp2_outbound_item *item;
5955   uint8_t data[16384];
5956   size_t i;
5957   my_user_data ud;
5958   nghttp2_option *opt;
5959 
5960   memset(data, '0', sizeof(data));
5961   for (i = 0; i < ARRLEN(nv); ++i) {
5962     nv[i].valuelen = sizeof(data);
5963     nv[i].value = data;
5964   }
5965 
5966   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
5967   callbacks.send_callback = null_send_callback;
5968   callbacks.on_frame_send_callback = on_frame_send_callback;
5969 
5970   /* The default size of max send header block length is too small to
5971      send these header fields.  Expand it. */
5972   nghttp2_option_new(&opt);
5973   nghttp2_option_set_max_send_header_block_length(opt, 102400);
5974 
5975   CU_ASSERT(0 == nghttp2_session_client_new2(&session, &callbacks, &ud, opt));
5976   CU_ASSERT(1 == nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, -1,
5977                                         NULL, nv, ARRLEN(nv), NULL));
5978   item = nghttp2_session_get_next_ob_item(session);
5979   CU_ASSERT(NGHTTP2_HEADERS == item->frame.hd.type);
5980   CU_ASSERT((NGHTTP2_FLAG_END_STREAM | NGHTTP2_FLAG_END_HEADERS) ==
5981             item->frame.hd.flags);
5982   CU_ASSERT(0 == (item->frame.hd.flags & NGHTTP2_FLAG_PRIORITY));
5983 
5984   ud.frame_send_cb_called = 0;
5985   CU_ASSERT(0 == nghttp2_session_send(session));
5986   CU_ASSERT(1 == ud.frame_send_cb_called);
5987 
5988   nghttp2_session_del(session);
5989   nghttp2_option_del(opt);
5990 }
5991 
test_nghttp2_submit_priority(void)5992 void test_nghttp2_submit_priority(void) {
5993   nghttp2_session *session;
5994   nghttp2_session_callbacks callbacks;
5995   nghttp2_stream *stream;
5996   my_user_data ud;
5997   nghttp2_priority_spec pri_spec;
5998 
5999   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6000   callbacks.send_callback = null_send_callback;
6001   callbacks.on_frame_send_callback = on_frame_send_callback;
6002 
6003   nghttp2_session_client_new(&session, &callbacks, &ud);
6004   stream = open_sent_stream(session, 1);
6005 
6006   nghttp2_priority_spec_init(&pri_spec, 0, 3, 0);
6007 
6008   /* depends on stream 0 */
6009   CU_ASSERT(0 ==
6010             nghttp2_submit_priority(session, NGHTTP2_FLAG_NONE, 1, &pri_spec));
6011   CU_ASSERT(0 == nghttp2_session_send(session));
6012   CU_ASSERT(3 == stream->weight);
6013 
6014   /* submit against idle stream */
6015   CU_ASSERT(0 ==
6016             nghttp2_submit_priority(session, NGHTTP2_FLAG_NONE, 3, &pri_spec));
6017 
6018   ud.frame_send_cb_called = 0;
6019   CU_ASSERT(0 == nghttp2_session_send(session));
6020   CU_ASSERT(1 == ud.frame_send_cb_called);
6021 
6022   nghttp2_session_del(session);
6023 }
6024 
test_nghttp2_submit_settings(void)6025 void test_nghttp2_submit_settings(void) {
6026   nghttp2_session *session;
6027   nghttp2_session_callbacks callbacks;
6028   my_user_data ud;
6029   nghttp2_outbound_item *item;
6030   nghttp2_frame *frame;
6031   nghttp2_settings_entry iv[7];
6032   nghttp2_frame ack_frame;
6033   const int32_t UNKNOWN_ID = 1000000007;
6034   nghttp2_mem *mem;
6035 
6036   mem = nghttp2_mem_default();
6037 
6038   iv[0].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS;
6039   iv[0].value = 5;
6040 
6041   iv[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
6042   iv[1].value = 16 * 1024;
6043 
6044   iv[2].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS;
6045   iv[2].value = 50;
6046 
6047   iv[3].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
6048   iv[3].value = 111;
6049 
6050   iv[4].settings_id = UNKNOWN_ID;
6051   iv[4].value = 999;
6052 
6053   iv[5].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
6054   iv[5].value = 1023;
6055 
6056   iv[6].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
6057   iv[6].value = (uint32_t)NGHTTP2_MAX_WINDOW_SIZE + 1;
6058 
6059   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6060   callbacks.send_callback = null_send_callback;
6061   callbacks.on_frame_send_callback = on_frame_send_callback;
6062   nghttp2_session_server_new(&session, &callbacks, &ud);
6063 
6064   CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT ==
6065             nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, iv, 7));
6066 
6067   /* Make sure that local settings are not changed */
6068   CU_ASSERT(NGHTTP2_DEFAULT_MAX_CONCURRENT_STREAMS ==
6069             session->local_settings.max_concurrent_streams);
6070   CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE ==
6071             session->local_settings.initial_window_size);
6072 
6073   /* Now sends without 6th one */
6074   CU_ASSERT(0 == nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, iv, 6));
6075 
6076   item = nghttp2_session_get_next_ob_item(session);
6077 
6078   CU_ASSERT(NGHTTP2_SETTINGS == item->frame.hd.type);
6079 
6080   frame = &item->frame;
6081   CU_ASSERT(6 == frame->settings.niv);
6082   CU_ASSERT(5 == frame->settings.iv[0].value);
6083   CU_ASSERT(NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS ==
6084             frame->settings.iv[0].settings_id);
6085 
6086   CU_ASSERT(16 * 1024 == frame->settings.iv[1].value);
6087   CU_ASSERT(NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE ==
6088             frame->settings.iv[1].settings_id);
6089 
6090   CU_ASSERT(UNKNOWN_ID == frame->settings.iv[4].settings_id);
6091   CU_ASSERT(999 == frame->settings.iv[4].value);
6092 
6093   ud.frame_send_cb_called = 0;
6094   CU_ASSERT(0 == nghttp2_session_send(session));
6095   CU_ASSERT(1 == ud.frame_send_cb_called);
6096 
6097   CU_ASSERT(50 == session->pending_local_max_concurrent_stream);
6098 
6099   /* before receiving SETTINGS ACK, local settings have still default
6100      values */
6101   CU_ASSERT(NGHTTP2_DEFAULT_MAX_CONCURRENT_STREAMS ==
6102             nghttp2_session_get_local_settings(
6103                 session, NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS));
6104   CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE ==
6105             nghttp2_session_get_local_settings(
6106                 session, NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE));
6107 
6108   nghttp2_frame_settings_init(&ack_frame.settings, NGHTTP2_FLAG_ACK, NULL, 0);
6109   CU_ASSERT(0 == nghttp2_session_on_settings_received(session, &ack_frame, 0));
6110   nghttp2_frame_settings_free(&ack_frame.settings, mem);
6111 
6112   CU_ASSERT(16 * 1024 == session->local_settings.initial_window_size);
6113   CU_ASSERT(111 == session->hd_inflater.ctx.hd_table_bufsize_max);
6114   CU_ASSERT(111 == session->hd_inflater.min_hd_table_bufsize_max);
6115   CU_ASSERT(50 == session->local_settings.max_concurrent_streams);
6116 
6117   CU_ASSERT(50 == nghttp2_session_get_local_settings(
6118                       session, NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS));
6119   CU_ASSERT(16 * 1024 == nghttp2_session_get_local_settings(
6120                              session, NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE));
6121 
6122   /* We just keep the last seen value */
6123   CU_ASSERT(50 == session->pending_local_max_concurrent_stream);
6124 
6125   nghttp2_session_del(session);
6126 
6127   /* Bail out if there are contradicting
6128      SETTINGS_NO_RFC7540_PRIORITIES in one SETTINGS. */
6129   nghttp2_session_server_new(&session, &callbacks, &ud);
6130 
6131   iv[0].settings_id = NGHTTP2_SETTINGS_NO_RFC7540_PRIORITIES;
6132   iv[0].value = 1;
6133   iv[1].settings_id = NGHTTP2_SETTINGS_NO_RFC7540_PRIORITIES;
6134   iv[1].value = 0;
6135 
6136   CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT ==
6137             nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, iv, 2));
6138 
6139   nghttp2_session_del(session);
6140 
6141   /* Attempt to change SETTINGS_NO_RFC7540_PRIORITIES in the 2nd
6142      SETTINGS. */
6143   nghttp2_session_server_new(&session, &callbacks, &ud);
6144 
6145   iv[0].settings_id = NGHTTP2_SETTINGS_NO_RFC7540_PRIORITIES;
6146   iv[0].value = 1;
6147 
6148   CU_ASSERT(0 == nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, iv, 1));
6149 
6150   iv[0].settings_id = NGHTTP2_SETTINGS_NO_RFC7540_PRIORITIES;
6151   iv[0].value = 0;
6152 
6153   CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT ==
6154             nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, iv, 1));
6155 
6156   nghttp2_session_del(session);
6157 }
6158 
test_nghttp2_submit_settings_update_local_window_size(void)6159 void test_nghttp2_submit_settings_update_local_window_size(void) {
6160   nghttp2_session *session;
6161   nghttp2_session_callbacks callbacks;
6162   nghttp2_outbound_item *item;
6163   nghttp2_settings_entry iv[4];
6164   nghttp2_stream *stream;
6165   nghttp2_frame ack_frame;
6166   nghttp2_mem *mem;
6167   nghttp2_option *option;
6168 
6169   mem = nghttp2_mem_default();
6170   nghttp2_frame_settings_init(&ack_frame.settings, NGHTTP2_FLAG_ACK, NULL, 0);
6171 
6172   iv[0].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
6173   iv[0].value = 16 * 1024;
6174 
6175   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6176   callbacks.send_callback = null_send_callback;
6177 
6178   nghttp2_session_server_new(&session, &callbacks, NULL);
6179 
6180   stream = open_recv_stream(session, 1);
6181   stream->local_window_size = NGHTTP2_INITIAL_WINDOW_SIZE + 100;
6182   stream->recv_window_size = 32768;
6183 
6184   open_recv_stream(session, 3);
6185 
6186   CU_ASSERT(0 == nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, iv, 1));
6187   CU_ASSERT(0 == nghttp2_session_send(session));
6188   CU_ASSERT(0 == nghttp2_session_on_settings_received(session, &ack_frame, 0));
6189 
6190   stream = nghttp2_session_get_stream(session, 1);
6191   CU_ASSERT(0 == stream->recv_window_size);
6192   CU_ASSERT(16 * 1024 + 100 == stream->local_window_size);
6193 
6194   stream = nghttp2_session_get_stream(session, 3);
6195   CU_ASSERT(16 * 1024 == stream->local_window_size);
6196 
6197   item = nghttp2_session_get_next_ob_item(session);
6198   CU_ASSERT(NGHTTP2_WINDOW_UPDATE == item->frame.hd.type);
6199   CU_ASSERT(32768 == item->frame.window_update.window_size_increment);
6200 
6201   nghttp2_session_del(session);
6202 
6203   /* Without auto-window update */
6204   nghttp2_option_new(&option);
6205   nghttp2_option_set_no_auto_window_update(option, 1);
6206 
6207   nghttp2_session_server_new2(&session, &callbacks, NULL, option);
6208 
6209   nghttp2_option_del(option);
6210 
6211   stream = open_recv_stream(session, 1);
6212   stream->local_window_size = NGHTTP2_INITIAL_WINDOW_SIZE + 100;
6213   stream->recv_window_size = 32768;
6214 
6215   CU_ASSERT(0 == nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, iv, 1));
6216   CU_ASSERT(0 == nghttp2_session_send(session));
6217   CU_ASSERT(0 == nghttp2_session_on_settings_received(session, &ack_frame, 0));
6218 
6219   stream = nghttp2_session_get_stream(session, 1);
6220 
6221   CU_ASSERT(32768 == stream->recv_window_size);
6222   CU_ASSERT(16 * 1024 + 100 == stream->local_window_size);
6223   /* Check that we can handle the case where local_window_size <
6224      recv_window_size */
6225   CU_ASSERT(0 == nghttp2_session_get_stream_local_window_size(session, 1));
6226 
6227   nghttp2_session_del(session);
6228 
6229   /* Check overflow case */
6230   iv[0].value = 128 * 1024;
6231   nghttp2_session_server_new(&session, &callbacks, NULL);
6232   stream = open_recv_stream(session, 1);
6233   stream->local_window_size = NGHTTP2_MAX_WINDOW_SIZE;
6234 
6235   CU_ASSERT(0 == nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, iv, 1));
6236   CU_ASSERT(0 == nghttp2_session_send(session));
6237   CU_ASSERT(0 == nghttp2_session_on_settings_received(session, &ack_frame, 0));
6238 
6239   item = nghttp2_session_get_next_ob_item(session);
6240   CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
6241   CU_ASSERT(NGHTTP2_FLOW_CONTROL_ERROR == item->frame.rst_stream.error_code);
6242 
6243   nghttp2_session_del(session);
6244   nghttp2_frame_settings_free(&ack_frame.settings, mem);
6245 }
6246 
test_nghttp2_submit_settings_multiple_times(void)6247 void test_nghttp2_submit_settings_multiple_times(void) {
6248   nghttp2_session *session;
6249   nghttp2_session_callbacks callbacks;
6250   nghttp2_settings_entry iv[4];
6251   nghttp2_frame frame;
6252   nghttp2_inflight_settings *inflight_settings;
6253 
6254   memset(&callbacks, 0, sizeof(callbacks));
6255   callbacks.send_callback = null_send_callback;
6256 
6257   nghttp2_session_client_new(&session, &callbacks, NULL);
6258 
6259   /* first SETTINGS */
6260   iv[0].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS;
6261   iv[0].value = 100;
6262 
6263   iv[1].settings_id = NGHTTP2_SETTINGS_ENABLE_PUSH;
6264   iv[1].value = 0;
6265 
6266   CU_ASSERT(0 == nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, iv, 2));
6267 
6268   inflight_settings = session->inflight_settings_head;
6269 
6270   CU_ASSERT(NULL != inflight_settings);
6271   CU_ASSERT(NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS ==
6272             inflight_settings->iv[0].settings_id);
6273   CU_ASSERT(100 == inflight_settings->iv[0].value);
6274   CU_ASSERT(2 == inflight_settings->niv);
6275   CU_ASSERT(NULL == inflight_settings->next);
6276 
6277   CU_ASSERT(100 == session->pending_local_max_concurrent_stream);
6278   CU_ASSERT(0 == session->pending_enable_push);
6279 
6280   /* second SETTINGS */
6281   iv[0].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS;
6282   iv[0].value = 99;
6283 
6284   CU_ASSERT(0 == nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, iv, 1));
6285 
6286   inflight_settings = session->inflight_settings_head->next;
6287 
6288   CU_ASSERT(NULL != inflight_settings);
6289   CU_ASSERT(NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS ==
6290             inflight_settings->iv[0].settings_id);
6291   CU_ASSERT(99 == inflight_settings->iv[0].value);
6292   CU_ASSERT(1 == inflight_settings->niv);
6293   CU_ASSERT(NULL == inflight_settings->next);
6294 
6295   CU_ASSERT(99 == session->pending_local_max_concurrent_stream);
6296   CU_ASSERT(0 == session->pending_enable_push);
6297 
6298   nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_ACK, NULL, 0);
6299 
6300   /* receive SETTINGS ACK */
6301   CU_ASSERT(0 == nghttp2_session_on_settings_received(session, &frame, 0));
6302 
6303   inflight_settings = session->inflight_settings_head;
6304 
6305   /* first inflight SETTINGS was removed */
6306   CU_ASSERT(NULL != inflight_settings);
6307   CU_ASSERT(NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS ==
6308             inflight_settings->iv[0].settings_id);
6309   CU_ASSERT(99 == inflight_settings->iv[0].value);
6310   CU_ASSERT(1 == inflight_settings->niv);
6311   CU_ASSERT(NULL == inflight_settings->next);
6312 
6313   CU_ASSERT(100 == session->local_settings.max_concurrent_streams);
6314 
6315   /* receive SETTINGS ACK again */
6316   CU_ASSERT(0 == nghttp2_session_on_settings_received(session, &frame, 0));
6317 
6318   CU_ASSERT(NULL == session->inflight_settings_head);
6319   CU_ASSERT(99 == session->local_settings.max_concurrent_streams);
6320 
6321   nghttp2_session_del(session);
6322 }
6323 
test_nghttp2_submit_push_promise(void)6324 void test_nghttp2_submit_push_promise(void) {
6325   nghttp2_session *session;
6326   nghttp2_session_callbacks callbacks;
6327   my_user_data ud;
6328   nghttp2_stream *stream;
6329 
6330   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6331   callbacks.send_callback = null_send_callback;
6332   callbacks.on_frame_send_callback = on_frame_send_callback;
6333   callbacks.on_frame_not_send_callback = on_frame_not_send_callback;
6334 
6335   CU_ASSERT(0 == nghttp2_session_server_new(&session, &callbacks, &ud));
6336   open_recv_stream(session, 1);
6337   CU_ASSERT(2 == nghttp2_submit_push_promise(session, NGHTTP2_FLAG_NONE, 1,
6338                                              reqnv, ARRLEN(reqnv), &ud));
6339 
6340   stream = nghttp2_session_get_stream(session, 2);
6341 
6342   CU_ASSERT(NULL != stream);
6343   CU_ASSERT(NGHTTP2_STREAM_RESERVED == stream->state);
6344   CU_ASSERT(&ud == nghttp2_session_get_stream_user_data(session, 2));
6345 
6346   ud.frame_send_cb_called = 0;
6347   ud.sent_frame_type = 0;
6348 
6349   CU_ASSERT(0 == nghttp2_session_send(session));
6350   CU_ASSERT(1 == ud.frame_send_cb_called);
6351   CU_ASSERT(NGHTTP2_PUSH_PROMISE == ud.sent_frame_type);
6352 
6353   stream = nghttp2_session_get_stream(session, 2);
6354 
6355   CU_ASSERT(NGHTTP2_STREAM_RESERVED == stream->state);
6356   CU_ASSERT(&ud == nghttp2_session_get_stream_user_data(session, 2));
6357 
6358   /* submit PUSH_PROMISE while associated stream is not opened */
6359   CU_ASSERT(NGHTTP2_ERR_STREAM_CLOSED ==
6360             nghttp2_submit_push_promise(session, NGHTTP2_FLAG_NONE, 3, reqnv,
6361                                         ARRLEN(reqnv), NULL));
6362 
6363   /* Stream ID <= 0 is error */
6364   CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT ==
6365             nghttp2_submit_push_promise(session, NGHTTP2_FLAG_NONE, 0, reqnv,
6366                                         ARRLEN(reqnv), NULL));
6367 
6368   nghttp2_session_del(session);
6369 }
6370 
test_nghttp2_submit_window_update(void)6371 void test_nghttp2_submit_window_update(void) {
6372   nghttp2_session *session;
6373   nghttp2_session_callbacks callbacks;
6374   my_user_data ud;
6375   nghttp2_outbound_item *item;
6376   nghttp2_stream *stream;
6377 
6378   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6379   callbacks.send_callback = null_send_callback;
6380 
6381   nghttp2_session_client_new(&session, &callbacks, &ud);
6382   stream = open_recv_stream(session, 2);
6383   stream->recv_window_size = 4096;
6384 
6385   CU_ASSERT(0 ==
6386             nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 2, 1024));
6387   item = nghttp2_session_get_next_ob_item(session);
6388   CU_ASSERT(NGHTTP2_WINDOW_UPDATE == item->frame.hd.type);
6389   CU_ASSERT(1024 == item->frame.window_update.window_size_increment);
6390   CU_ASSERT(0 == nghttp2_session_send(session));
6391   CU_ASSERT(3072 == stream->recv_window_size);
6392 
6393   CU_ASSERT(0 ==
6394             nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 2, 4096));
6395   item = nghttp2_session_get_next_ob_item(session);
6396   CU_ASSERT(NGHTTP2_WINDOW_UPDATE == item->frame.hd.type);
6397   CU_ASSERT(4096 == item->frame.window_update.window_size_increment);
6398   CU_ASSERT(0 == nghttp2_session_send(session));
6399   CU_ASSERT(0 == stream->recv_window_size);
6400 
6401   CU_ASSERT(0 ==
6402             nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 2, 4096));
6403   item = nghttp2_session_get_next_ob_item(session);
6404   CU_ASSERT(NGHTTP2_WINDOW_UPDATE == item->frame.hd.type);
6405   CU_ASSERT(4096 == item->frame.window_update.window_size_increment);
6406   CU_ASSERT(0 == nghttp2_session_send(session));
6407   CU_ASSERT(0 == stream->recv_window_size);
6408 
6409   CU_ASSERT(0 ==
6410             nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 2, 0));
6411   /* It is ok if stream is closed or does not exist at the call
6412      time */
6413   CU_ASSERT(0 ==
6414             nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 4, 4096));
6415 
6416   nghttp2_session_del(session);
6417 }
6418 
test_nghttp2_submit_window_update_local_window_size(void)6419 void test_nghttp2_submit_window_update_local_window_size(void) {
6420   nghttp2_session *session;
6421   nghttp2_session_callbacks callbacks;
6422   nghttp2_outbound_item *item;
6423   nghttp2_stream *stream;
6424 
6425   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6426   callbacks.send_callback = null_send_callback;
6427 
6428   nghttp2_session_client_new(&session, &callbacks, NULL);
6429   stream = open_recv_stream(session, 2);
6430   stream->recv_window_size = 4096;
6431 
6432   CU_ASSERT(0 == nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 2,
6433                                               stream->recv_window_size + 1));
6434   CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE + 1 == stream->local_window_size);
6435   CU_ASSERT(0 == stream->recv_window_size);
6436   item = nghttp2_session_get_next_ob_item(session);
6437   CU_ASSERT(NGHTTP2_WINDOW_UPDATE == item->frame.hd.type);
6438   CU_ASSERT(4097 == item->frame.window_update.window_size_increment);
6439 
6440   CU_ASSERT(0 == nghttp2_session_send(session));
6441 
6442   /* Let's decrement local window size */
6443   stream->recv_window_size = 4096;
6444   CU_ASSERT(0 == nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 2,
6445                                               -stream->local_window_size / 2));
6446   CU_ASSERT(32768 == stream->local_window_size);
6447   CU_ASSERT(-28672 == stream->recv_window_size);
6448   CU_ASSERT(32768 == stream->recv_reduction);
6449 
6450   item = nghttp2_session_get_next_ob_item(session);
6451   CU_ASSERT(item == NULL);
6452 
6453   /* Increase local window size */
6454   CU_ASSERT(0 ==
6455             nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 2, 16384));
6456   CU_ASSERT(49152 == stream->local_window_size);
6457   CU_ASSERT(-12288 == stream->recv_window_size);
6458   CU_ASSERT(16384 == stream->recv_reduction);
6459   CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
6460 
6461   CU_ASSERT(NGHTTP2_ERR_FLOW_CONTROL ==
6462             nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 2,
6463                                          NGHTTP2_MAX_WINDOW_SIZE));
6464 
6465   CU_ASSERT(0 == nghttp2_session_send(session));
6466 
6467   /* Check connection-level flow control */
6468   session->recv_window_size = 4096;
6469   CU_ASSERT(0 == nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 0,
6470                                               session->recv_window_size + 1));
6471   CU_ASSERT(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE + 1 ==
6472             session->local_window_size);
6473   CU_ASSERT(0 == session->recv_window_size);
6474   item = nghttp2_session_get_next_ob_item(session);
6475   CU_ASSERT(NGHTTP2_WINDOW_UPDATE == item->frame.hd.type);
6476   CU_ASSERT(4097 == item->frame.window_update.window_size_increment);
6477 
6478   CU_ASSERT(0 == nghttp2_session_send(session));
6479 
6480   /* Go decrement part */
6481   session->recv_window_size = 4096;
6482   CU_ASSERT(0 == nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 0,
6483                                               -session->local_window_size / 2));
6484   CU_ASSERT(32768 == session->local_window_size);
6485   CU_ASSERT(-28672 == session->recv_window_size);
6486   CU_ASSERT(32768 == session->recv_reduction);
6487   item = nghttp2_session_get_next_ob_item(session);
6488   CU_ASSERT(item == NULL);
6489 
6490   /* Increase local window size */
6491   CU_ASSERT(0 ==
6492             nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 0, 16384));
6493   CU_ASSERT(49152 == session->local_window_size);
6494   CU_ASSERT(-12288 == session->recv_window_size);
6495   CU_ASSERT(16384 == session->recv_reduction);
6496   CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
6497 
6498   CU_ASSERT(NGHTTP2_ERR_FLOW_CONTROL ==
6499             nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 0,
6500                                          NGHTTP2_MAX_WINDOW_SIZE));
6501 
6502   nghttp2_session_del(session);
6503 }
6504 
test_nghttp2_submit_shutdown_notice(void)6505 void test_nghttp2_submit_shutdown_notice(void) {
6506   nghttp2_session *session;
6507   nghttp2_session_callbacks callbacks;
6508   my_user_data ud;
6509 
6510   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6511   callbacks.send_callback = null_send_callback;
6512   callbacks.on_frame_send_callback = on_frame_send_callback;
6513   callbacks.on_frame_not_send_callback = on_frame_not_send_callback;
6514 
6515   nghttp2_session_server_new(&session, &callbacks, &ud);
6516 
6517   CU_ASSERT(0 == nghttp2_submit_shutdown_notice(session));
6518 
6519   ud.frame_send_cb_called = 0;
6520 
6521   nghttp2_session_send(session);
6522 
6523   CU_ASSERT(1 == ud.frame_send_cb_called);
6524   CU_ASSERT(NGHTTP2_GOAWAY == ud.sent_frame_type);
6525   CU_ASSERT((1u << 31) - 1 == session->local_last_stream_id);
6526 
6527   /* After another GOAWAY, nghttp2_submit_shutdown_notice() is
6528      noop. */
6529   CU_ASSERT(0 == nghttp2_session_terminate_session(session, NGHTTP2_NO_ERROR));
6530 
6531   ud.frame_send_cb_called = 0;
6532 
6533   nghttp2_session_send(session);
6534 
6535   CU_ASSERT(1 == ud.frame_send_cb_called);
6536   CU_ASSERT(NGHTTP2_GOAWAY == ud.sent_frame_type);
6537   CU_ASSERT(0 == session->local_last_stream_id);
6538 
6539   CU_ASSERT(0 == nghttp2_submit_shutdown_notice(session));
6540 
6541   ud.frame_send_cb_called = 0;
6542   ud.frame_not_send_cb_called = 0;
6543 
6544   nghttp2_session_send(session);
6545 
6546   CU_ASSERT(0 == ud.frame_send_cb_called);
6547   CU_ASSERT(0 == ud.frame_not_send_cb_called);
6548 
6549   nghttp2_session_del(session);
6550 
6551   /* Using nghttp2_submit_shutdown_notice() with client side session
6552      is error */
6553   nghttp2_session_client_new(&session, &callbacks, NULL);
6554 
6555   CU_ASSERT(NGHTTP2_ERR_INVALID_STATE ==
6556             nghttp2_submit_shutdown_notice(session));
6557 
6558   nghttp2_session_del(session);
6559 }
6560 
test_nghttp2_submit_invalid_nv(void)6561 void test_nghttp2_submit_invalid_nv(void) {
6562   nghttp2_session *session;
6563   nghttp2_session_callbacks callbacks;
6564   nghttp2_nv empty_name_nv[] = {MAKE_NV("Version", "HTTP/1.1"),
6565                                 MAKE_NV("", "empty name")};
6566 
6567   /* Now invalid header name/value pair in HTTP/1.1 is accepted in
6568      nghttp2 */
6569 
6570   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6571 
6572   CU_ASSERT(0 == nghttp2_session_server_new(&session, &callbacks, NULL));
6573 
6574   /* nghttp2_submit_response */
6575   CU_ASSERT(0 == nghttp2_submit_response(session, 2, empty_name_nv,
6576                                          ARRLEN(empty_name_nv), NULL));
6577 
6578   /* nghttp2_submit_push_promise */
6579   open_recv_stream(session, 1);
6580 
6581   CU_ASSERT(0 < nghttp2_submit_push_promise(session, NGHTTP2_FLAG_NONE, 1,
6582                                             empty_name_nv,
6583                                             ARRLEN(empty_name_nv), NULL));
6584 
6585   nghttp2_session_del(session);
6586 
6587   CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, NULL));
6588 
6589   /* nghttp2_submit_request */
6590   CU_ASSERT(0 < nghttp2_submit_request(session, NULL, empty_name_nv,
6591                                        ARRLEN(empty_name_nv), NULL, NULL));
6592 
6593   /* nghttp2_submit_headers */
6594   CU_ASSERT(0 < nghttp2_submit_headers(session, NGHTTP2_FLAG_NONE, -1, NULL,
6595                                        empty_name_nv, ARRLEN(empty_name_nv),
6596                                        NULL));
6597 
6598   nghttp2_session_del(session);
6599 }
6600 
test_nghttp2_submit_extension(void)6601 void test_nghttp2_submit_extension(void) {
6602   nghttp2_session *session;
6603   nghttp2_session_callbacks callbacks;
6604   my_user_data ud;
6605   accumulator acc;
6606   nghttp2_mem *mem;
6607   const char data[] = "Hello World!";
6608   size_t len;
6609   int32_t stream_id;
6610   int rv;
6611 
6612   mem = nghttp2_mem_default();
6613 
6614   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6615 
6616   callbacks.pack_extension_callback = pack_extension_callback;
6617   callbacks.send_callback = accumulator_send_callback;
6618 
6619   nghttp2_buf_init2(&ud.scratchbuf, 4096, mem);
6620 
6621   nghttp2_session_client_new(&session, &callbacks, &ud);
6622 
6623   ud.scratchbuf.last = nghttp2_cpymem(ud.scratchbuf.last, data, sizeof(data));
6624   ud.acc = &acc;
6625 
6626   rv = nghttp2_submit_extension(session, 211, 0x01, 3, &ud.scratchbuf);
6627 
6628   CU_ASSERT(0 == rv);
6629 
6630   acc.length = 0;
6631 
6632   rv = nghttp2_session_send(session);
6633 
6634   CU_ASSERT(0 == rv);
6635   CU_ASSERT(NGHTTP2_FRAME_HDLEN + sizeof(data) == acc.length);
6636 
6637   len = nghttp2_get_uint32(acc.buf) >> 8;
6638 
6639   CU_ASSERT(sizeof(data) == len);
6640   CU_ASSERT(211 == acc.buf[3]);
6641   CU_ASSERT(0x01 == acc.buf[4]);
6642 
6643   stream_id = (int32_t)nghttp2_get_uint32(acc.buf + 5);
6644 
6645   CU_ASSERT(3 == stream_id);
6646   CU_ASSERT(0 == memcmp(data, &acc.buf[NGHTTP2_FRAME_HDLEN], sizeof(data)));
6647 
6648   nghttp2_session_del(session);
6649 
6650   /* submitting standard HTTP/2 frame is error */
6651   nghttp2_session_server_new(&session, &callbacks, &ud);
6652 
6653   rv = nghttp2_submit_extension(session, NGHTTP2_GOAWAY, NGHTTP2_FLAG_NONE, 0,
6654                                 NULL);
6655 
6656   CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT == rv);
6657 
6658   nghttp2_session_del(session);
6659   nghttp2_buf_free(&ud.scratchbuf, mem);
6660 }
6661 
test_nghttp2_submit_altsvc(void)6662 void test_nghttp2_submit_altsvc(void) {
6663   nghttp2_session *session;
6664   nghttp2_session_callbacks callbacks;
6665   my_user_data ud;
6666   int rv;
6667   ssize_t len;
6668   const uint8_t *data;
6669   nghttp2_frame_hd hd;
6670   size_t origin_len;
6671   const uint8_t origin[] = "nghttp2.org";
6672   const uint8_t field_value[] = "h2=\":443\"";
6673 
6674   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6675 
6676   nghttp2_session_server_new(&session, &callbacks, &ud);
6677 
6678   rv = nghttp2_submit_altsvc(session, NGHTTP2_FLAG_NONE, 0, origin,
6679                              sizeof(origin) - 1, field_value,
6680                              sizeof(field_value) - 1);
6681 
6682   CU_ASSERT(0 == rv);
6683 
6684   ud.frame_send_cb_called = 0;
6685 
6686   len = nghttp2_session_mem_send(session, &data);
6687 
6688   CU_ASSERT(len == NGHTTP2_FRAME_HDLEN + 2 + sizeof(origin) - 1 +
6689                        sizeof(field_value) - 1);
6690 
6691   nghttp2_frame_unpack_frame_hd(&hd, data);
6692 
6693   CU_ASSERT(2 + sizeof(origin) - 1 + sizeof(field_value) - 1 == hd.length);
6694   CU_ASSERT(NGHTTP2_ALTSVC == hd.type);
6695   CU_ASSERT(NGHTTP2_FLAG_NONE == hd.flags);
6696 
6697   origin_len = nghttp2_get_uint16(data + NGHTTP2_FRAME_HDLEN);
6698 
6699   CU_ASSERT(sizeof(origin) - 1 == origin_len);
6700   CU_ASSERT(0 ==
6701             memcmp(origin, data + NGHTTP2_FRAME_HDLEN + 2, sizeof(origin) - 1));
6702   CU_ASSERT(0 == memcmp(field_value,
6703                         data + NGHTTP2_FRAME_HDLEN + 2 + sizeof(origin) - 1,
6704                         hd.length - (sizeof(origin) - 1) - 2));
6705 
6706   /* submitting empty origin with stream_id == 0 is error */
6707   rv = nghttp2_submit_altsvc(session, NGHTTP2_FLAG_NONE, 0, NULL, 0,
6708                              field_value, sizeof(field_value) - 1);
6709 
6710   CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT == rv);
6711 
6712   /* submitting non-empty origin with stream_id != 0 is error */
6713   rv = nghttp2_submit_altsvc(session, NGHTTP2_FLAG_NONE, 1, origin,
6714                              sizeof(origin) - 1, field_value,
6715                              sizeof(field_value) - 1);
6716 
6717   CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT == rv);
6718 
6719   nghttp2_session_del(session);
6720 
6721   /* submitting from client side session is error */
6722   nghttp2_session_client_new(&session, &callbacks, NULL);
6723 
6724   rv = nghttp2_submit_altsvc(session, NGHTTP2_FLAG_NONE, 0, origin,
6725                              sizeof(origin) - 1, field_value,
6726                              sizeof(field_value) - 1);
6727 
6728   CU_ASSERT(NGHTTP2_ERR_INVALID_STATE == rv);
6729 
6730   nghttp2_session_del(session);
6731 }
6732 
test_nghttp2_submit_origin(void)6733 void test_nghttp2_submit_origin(void) {
6734   nghttp2_session *session;
6735   nghttp2_session_callbacks callbacks;
6736   my_user_data ud;
6737   int rv;
6738   ssize_t len;
6739   const uint8_t *data;
6740   static const uint8_t nghttp2[] = "https://nghttp2.org";
6741   static const uint8_t examples[] = "https://examples.com";
6742   static const nghttp2_origin_entry ov[] = {
6743       {
6744           (uint8_t *)nghttp2,
6745           sizeof(nghttp2) - 1,
6746       },
6747       {
6748           (uint8_t *)examples,
6749           sizeof(examples) - 1,
6750       },
6751   };
6752   nghttp2_frame frame;
6753   nghttp2_ext_origin origin;
6754   nghttp2_mem *mem;
6755 
6756   mem = nghttp2_mem_default();
6757 
6758   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6759   callbacks.on_frame_send_callback = on_frame_send_callback;
6760 
6761   frame.ext.payload = &origin;
6762 
6763   nghttp2_session_server_new(&session, &callbacks, &ud);
6764 
6765   rv = nghttp2_submit_origin(session, NGHTTP2_FLAG_NONE, ov, 2);
6766 
6767   CU_ASSERT(0 == rv);
6768 
6769   ud.frame_send_cb_called = 0;
6770   len = nghttp2_session_mem_send(session, &data);
6771 
6772   CU_ASSERT(len > 0);
6773   CU_ASSERT(1 == ud.frame_send_cb_called);
6774 
6775   nghttp2_frame_unpack_frame_hd(&frame.hd, data);
6776   rv = nghttp2_frame_unpack_origin_payload(
6777       &frame.ext, data + NGHTTP2_FRAME_HDLEN, (size_t)len - NGHTTP2_FRAME_HDLEN,
6778       mem);
6779 
6780   CU_ASSERT(0 == rv);
6781   CU_ASSERT(0 == frame.hd.stream_id);
6782   CU_ASSERT(NGHTTP2_ORIGIN == frame.hd.type);
6783   CU_ASSERT(2 == origin.nov);
6784   CU_ASSERT(0 == memcmp(nghttp2, origin.ov[0].origin, sizeof(nghttp2) - 1));
6785   CU_ASSERT(sizeof(nghttp2) - 1 == origin.ov[0].origin_len);
6786   CU_ASSERT(0 == memcmp(examples, origin.ov[1].origin, sizeof(examples) - 1));
6787   CU_ASSERT(sizeof(examples) - 1 == origin.ov[1].origin_len);
6788 
6789   nghttp2_frame_origin_free(&frame.ext, mem);
6790 
6791   nghttp2_session_del(session);
6792 
6793   /* Submitting ORIGIN frame from client session is error */
6794   nghttp2_session_client_new(&session, &callbacks, NULL);
6795 
6796   rv = nghttp2_submit_origin(session, NGHTTP2_FLAG_NONE, ov, 1);
6797 
6798   CU_ASSERT(NGHTTP2_ERR_INVALID_STATE == rv);
6799 
6800   nghttp2_session_del(session);
6801 
6802   /* Submitting empty ORIGIN frame */
6803   nghttp2_session_server_new(&session, &callbacks, &ud);
6804 
6805   rv = nghttp2_submit_origin(session, NGHTTP2_FLAG_NONE, NULL, 0);
6806 
6807   CU_ASSERT(0 == rv);
6808 
6809   ud.frame_send_cb_called = 0;
6810   len = nghttp2_session_mem_send(session, &data);
6811 
6812   CU_ASSERT(len == NGHTTP2_FRAME_HDLEN);
6813   CU_ASSERT(1 == ud.frame_send_cb_called);
6814 
6815   nghttp2_frame_unpack_frame_hd(&frame.hd, data);
6816 
6817   CU_ASSERT(NGHTTP2_ORIGIN == frame.hd.type);
6818 
6819   nghttp2_session_del(session);
6820 }
6821 
test_nghttp2_submit_priority_update(void)6822 void test_nghttp2_submit_priority_update(void) {
6823   nghttp2_session *session;
6824   nghttp2_session_callbacks callbacks;
6825   const uint8_t field_value[] = "i";
6826   my_user_data ud;
6827   const uint8_t *data;
6828   int rv;
6829   nghttp2_frame frame;
6830   nghttp2_ext_priority_update priority_update;
6831   ssize_t len;
6832   int32_t stream_id;
6833 
6834   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6835   callbacks.on_frame_send_callback = on_frame_send_callback;
6836 
6837   nghttp2_session_client_new(&session, &callbacks, &ud);
6838 
6839   session->pending_no_rfc7540_priorities = 1;
6840 
6841   stream_id =
6842       nghttp2_submit_request(session, NULL, reqnv, ARRLEN(reqnv), NULL, NULL);
6843 
6844   CU_ASSERT(1 == stream_id);
6845 
6846   len = nghttp2_session_mem_send(session, &data);
6847 
6848   CU_ASSERT(len > 0);
6849 
6850   rv = nghttp2_submit_priority_update(session, NGHTTP2_FLAG_NONE, stream_id,
6851                                       field_value, sizeof(field_value) - 1);
6852 
6853   CU_ASSERT(0 == rv);
6854 
6855   frame.ext.payload = &priority_update;
6856 
6857   ud.frame_send_cb_called = 0;
6858   len = nghttp2_session_mem_send(session, &data);
6859 
6860   CU_ASSERT(len > 0);
6861   CU_ASSERT(1 == ud.frame_send_cb_called);
6862 
6863   nghttp2_frame_unpack_frame_hd(&frame.hd, data);
6864   nghttp2_frame_unpack_priority_update_payload(
6865       &frame.ext, (uint8_t *)(data + NGHTTP2_FRAME_HDLEN),
6866       (size_t)len - NGHTTP2_FRAME_HDLEN);
6867 
6868   CU_ASSERT(0 == frame.hd.stream_id);
6869   CU_ASSERT(NGHTTP2_PRIORITY_UPDATE == frame.hd.type);
6870   CU_ASSERT(stream_id == priority_update.stream_id);
6871   CU_ASSERT(sizeof(field_value) - 1 == priority_update.field_value_len);
6872   CU_ASSERT(0 == memcmp(field_value, priority_update.field_value,
6873                         sizeof(field_value) - 1));
6874 
6875   nghttp2_session_del(session);
6876 
6877   /* Submitting PRIORITY_UPDATE frame from server session is error */
6878   nghttp2_session_server_new(&session, &callbacks, &ud);
6879 
6880   open_recv_stream(session, 1);
6881 
6882   rv = nghttp2_submit_priority_update(session, NGHTTP2_FLAG_NONE, 1,
6883                                       field_value, sizeof(field_value) - 1);
6884 
6885   CU_ASSERT(NGHTTP2_ERR_INVALID_STATE == rv);
6886 
6887   nghttp2_session_del(session);
6888 
6889   /* Submitting PRIORITY_UPDATE with empty field_value */
6890   nghttp2_session_client_new(&session, &callbacks, &ud);
6891 
6892   stream_id =
6893       nghttp2_submit_request(session, NULL, reqnv, ARRLEN(reqnv), NULL, NULL);
6894 
6895   CU_ASSERT(1 == stream_id);
6896 
6897   len = nghttp2_session_mem_send(session, &data);
6898 
6899   CU_ASSERT(len > 0);
6900 
6901   rv = nghttp2_submit_priority_update(session, NGHTTP2_FLAG_NONE, stream_id,
6902                                       NULL, 0);
6903 
6904   CU_ASSERT(0 == rv);
6905 
6906   frame.ext.payload = &priority_update;
6907 
6908   len = nghttp2_session_mem_send(session, &data);
6909 
6910   CU_ASSERT(len > 0);
6911 
6912   nghttp2_frame_unpack_frame_hd(&frame.hd, data);
6913   nghttp2_frame_unpack_priority_update_payload(
6914       &frame.ext, (uint8_t *)(data + NGHTTP2_FRAME_HDLEN),
6915       (size_t)len - NGHTTP2_FRAME_HDLEN);
6916 
6917   CU_ASSERT(0 == frame.hd.stream_id);
6918   CU_ASSERT(NGHTTP2_PRIORITY_UPDATE == frame.hd.type);
6919   CU_ASSERT(stream_id == priority_update.stream_id);
6920   CU_ASSERT(0 == priority_update.field_value_len);
6921   CU_ASSERT(NULL == priority_update.field_value);
6922 
6923   nghttp2_session_del(session);
6924 }
6925 
test_nghttp2_submit_rst_stream(void)6926 void test_nghttp2_submit_rst_stream(void) {
6927   nghttp2_session *session;
6928   nghttp2_session_callbacks callbacks;
6929   nghttp2_outbound_item *item;
6930   int rv;
6931   int32_t stream_id;
6932 
6933   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6934 
6935   /* Sending RST_STREAM to idle stream (local) is ignored */
6936   nghttp2_session_client_new(&session, &callbacks, NULL);
6937 
6938   rv = nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, 1,
6939                                  NGHTTP2_NO_ERROR);
6940 
6941   CU_ASSERT(0 == rv);
6942 
6943   item = nghttp2_outbound_queue_top(&session->ob_reg);
6944 
6945   CU_ASSERT(NULL == item);
6946 
6947   nghttp2_session_del(session);
6948 
6949   /* Sending RST_STREAM to idle stream (remote) is ignored */
6950   nghttp2_session_client_new(&session, &callbacks, NULL);
6951 
6952   rv = nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, 2,
6953                                  NGHTTP2_NO_ERROR);
6954 
6955   CU_ASSERT(0 == rv);
6956 
6957   item = nghttp2_outbound_queue_top(&session->ob_reg);
6958 
6959   CU_ASSERT(NULL == item);
6960 
6961   nghttp2_session_del(session);
6962 
6963   /* Sending RST_STREAM to non-idle stream (local) */
6964   nghttp2_session_client_new(&session, &callbacks, NULL);
6965 
6966   open_sent_stream(session, 1);
6967 
6968   rv = nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, 1,
6969                                  NGHTTP2_NO_ERROR);
6970 
6971   CU_ASSERT(0 == rv);
6972 
6973   item = nghttp2_outbound_queue_top(&session->ob_reg);
6974 
6975   CU_ASSERT(NULL != item);
6976   CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
6977   CU_ASSERT(1 == item->frame.hd.stream_id);
6978 
6979   nghttp2_session_del(session);
6980 
6981   /* Sending RST_STREAM to non-idle stream (remote) */
6982   nghttp2_session_client_new(&session, &callbacks, NULL);
6983 
6984   open_recv_stream(session, 2);
6985 
6986   rv = nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, 2,
6987                                  NGHTTP2_NO_ERROR);
6988 
6989   CU_ASSERT(0 == rv);
6990 
6991   item = nghttp2_outbound_queue_top(&session->ob_reg);
6992 
6993   CU_ASSERT(NULL != item);
6994   CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
6995   CU_ASSERT(2 == item->frame.hd.stream_id);
6996 
6997   nghttp2_session_del(session);
6998 
6999   /* Sending RST_STREAM to pending stream */
7000   nghttp2_session_client_new(&session, &callbacks, NULL);
7001 
7002   stream_id =
7003       nghttp2_submit_request(session, NULL, reqnv, ARRLEN(reqnv), NULL, NULL);
7004 
7005   CU_ASSERT(stream_id > 0);
7006 
7007   item = nghttp2_outbound_queue_top(&session->ob_syn);
7008 
7009   CU_ASSERT(NULL != item);
7010   CU_ASSERT(NGHTTP2_HEADERS == item->frame.hd.type);
7011   CU_ASSERT(0 == item->aux_data.headers.canceled);
7012 
7013   rv = nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, stream_id,
7014                                  NGHTTP2_NO_ERROR);
7015 
7016   CU_ASSERT(0 == rv);
7017 
7018   item = nghttp2_outbound_queue_top(&session->ob_syn);
7019 
7020   CU_ASSERT(NULL != item);
7021   CU_ASSERT(NGHTTP2_HEADERS == item->frame.hd.type);
7022   CU_ASSERT(1 == item->aux_data.headers.canceled);
7023 
7024   nghttp2_session_del(session);
7025 }
7026 
test_nghttp2_session_open_stream(void)7027 void test_nghttp2_session_open_stream(void) {
7028   nghttp2_session *session;
7029   nghttp2_session_callbacks callbacks;
7030   nghttp2_stream *stream;
7031   nghttp2_priority_spec pri_spec;
7032 
7033   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7034   nghttp2_session_server_new(&session, &callbacks, NULL);
7035 
7036   nghttp2_priority_spec_init(&pri_spec, 0, 245, 0);
7037 
7038   stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
7039                                        &pri_spec, NGHTTP2_STREAM_OPENED, NULL);
7040   CU_ASSERT(1 == session->num_incoming_streams);
7041   CU_ASSERT(0 == session->num_outgoing_streams);
7042   CU_ASSERT(NGHTTP2_STREAM_OPENED == stream->state);
7043   CU_ASSERT(245 == stream->weight);
7044   CU_ASSERT(&session->root == stream->dep_prev);
7045   CU_ASSERT(NGHTTP2_SHUT_NONE == stream->shut_flags);
7046 
7047   stream = nghttp2_session_open_stream(session, 2, NGHTTP2_STREAM_FLAG_NONE,
7048                                        &pri_spec_default,
7049                                        NGHTTP2_STREAM_OPENING, NULL);
7050   CU_ASSERT(1 == session->num_incoming_streams);
7051   CU_ASSERT(1 == session->num_outgoing_streams);
7052   CU_ASSERT(&session->root == stream->dep_prev);
7053   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == stream->weight);
7054   CU_ASSERT(NGHTTP2_SHUT_NONE == stream->shut_flags);
7055 
7056   stream = nghttp2_session_open_stream(session, 4, NGHTTP2_STREAM_FLAG_NONE,
7057                                        &pri_spec_default,
7058                                        NGHTTP2_STREAM_RESERVED, NULL);
7059   CU_ASSERT(1 == session->num_incoming_streams);
7060   CU_ASSERT(1 == session->num_outgoing_streams);
7061   CU_ASSERT(&session->root == stream->dep_prev);
7062   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == stream->weight);
7063   CU_ASSERT(NGHTTP2_SHUT_RD == stream->shut_flags);
7064 
7065   nghttp2_priority_spec_init(&pri_spec, 1, 17, 1);
7066 
7067   stream = nghttp2_session_open_stream(session, 3, NGHTTP2_STREAM_FLAG_NONE,
7068                                        &pri_spec, NGHTTP2_STREAM_OPENED, NULL);
7069   CU_ASSERT(17 == stream->weight);
7070   CU_ASSERT(1 == stream->dep_prev->stream_id);
7071 
7072   /* Dependency to idle stream */
7073   nghttp2_priority_spec_init(&pri_spec, 1000000007, 240, 1);
7074 
7075   stream = nghttp2_session_open_stream(session, 5, NGHTTP2_STREAM_FLAG_NONE,
7076                                        &pri_spec, NGHTTP2_STREAM_OPENED, NULL);
7077   CU_ASSERT(240 == stream->weight);
7078   CU_ASSERT(1000000007 == stream->dep_prev->stream_id);
7079 
7080   stream = nghttp2_session_get_stream_raw(session, 1000000007);
7081 
7082   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == stream->weight);
7083   CU_ASSERT(&session->root == stream->dep_prev);
7084 
7085   /* Dependency to closed stream which is not in dependency tree */
7086   session->last_recv_stream_id = 7;
7087 
7088   nghttp2_priority_spec_init(&pri_spec, 7, 10, 0);
7089 
7090   stream = nghttp2_session_open_stream(session, 9, NGHTTP2_FLAG_NONE, &pri_spec,
7091                                        NGHTTP2_STREAM_OPENED, NULL);
7092 
7093   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == stream->weight);
7094   CU_ASSERT(&session->root == stream->dep_prev);
7095 
7096   nghttp2_session_del(session);
7097 
7098   nghttp2_session_client_new(&session, &callbacks, NULL);
7099   stream = nghttp2_session_open_stream(session, 4, NGHTTP2_STREAM_FLAG_NONE,
7100                                        &pri_spec_default,
7101                                        NGHTTP2_STREAM_RESERVED, NULL);
7102   CU_ASSERT(0 == session->num_incoming_streams);
7103   CU_ASSERT(0 == session->num_outgoing_streams);
7104   CU_ASSERT(&session->root == stream->dep_prev);
7105   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == stream->weight);
7106   CU_ASSERT(NGHTTP2_SHUT_WR == stream->shut_flags);
7107 
7108   nghttp2_session_del(session);
7109 }
7110 
test_nghttp2_session_open_stream_with_idle_stream_dep(void)7111 void test_nghttp2_session_open_stream_with_idle_stream_dep(void) {
7112   nghttp2_session *session;
7113   nghttp2_session_callbacks callbacks;
7114   nghttp2_stream *stream;
7115   nghttp2_priority_spec pri_spec;
7116 
7117   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7118   nghttp2_session_server_new(&session, &callbacks, NULL);
7119 
7120   /* Dependency to idle stream */
7121   nghttp2_priority_spec_init(&pri_spec, 101, 245, 0);
7122 
7123   stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
7124                                        &pri_spec, NGHTTP2_STREAM_OPENED, NULL);
7125 
7126   CU_ASSERT(245 == stream->weight);
7127   CU_ASSERT(101 == stream->dep_prev->stream_id);
7128 
7129   stream = nghttp2_session_get_stream_raw(session, 101);
7130 
7131   CU_ASSERT(NGHTTP2_STREAM_IDLE == stream->state);
7132   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == stream->weight);
7133 
7134   nghttp2_priority_spec_init(&pri_spec, 211, 1, 0);
7135 
7136   /* stream 101 was already created as idle. */
7137   stream = nghttp2_session_open_stream(session, 101, NGHTTP2_STREAM_FLAG_NONE,
7138                                        &pri_spec, NGHTTP2_STREAM_OPENED, NULL);
7139 
7140   CU_ASSERT(1 == stream->weight);
7141   CU_ASSERT(211 == stream->dep_prev->stream_id);
7142 
7143   stream = nghttp2_session_get_stream_raw(session, 211);
7144 
7145   CU_ASSERT(NGHTTP2_STREAM_IDLE == stream->state);
7146   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == stream->weight);
7147 
7148   nghttp2_session_del(session);
7149 }
7150 
test_nghttp2_session_get_next_ob_item(void)7151 void test_nghttp2_session_get_next_ob_item(void) {
7152   nghttp2_session *session;
7153   nghttp2_session_callbacks callbacks;
7154   nghttp2_priority_spec pri_spec;
7155 
7156   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7157   callbacks.send_callback = null_send_callback;
7158 
7159   nghttp2_session_client_new(&session, &callbacks, NULL);
7160   session->remote_settings.max_concurrent_streams = 2;
7161 
7162   CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
7163   nghttp2_submit_ping(session, NGHTTP2_FLAG_NONE, NULL);
7164   CU_ASSERT(NGHTTP2_PING ==
7165             nghttp2_session_get_next_ob_item(session)->frame.hd.type);
7166 
7167   CU_ASSERT(1 == nghttp2_submit_request(session, NULL, NULL, 0, NULL, NULL));
7168   CU_ASSERT(NGHTTP2_PING ==
7169             nghttp2_session_get_next_ob_item(session)->frame.hd.type);
7170 
7171   CU_ASSERT(0 == nghttp2_session_send(session));
7172   CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
7173 
7174   /* Incoming stream does not affect the number of outgoing max
7175      concurrent streams. */
7176   open_recv_stream(session, 2);
7177 
7178   nghttp2_priority_spec_init(&pri_spec, 0, NGHTTP2_MAX_WEIGHT, 0);
7179 
7180   CU_ASSERT(3 ==
7181             nghttp2_submit_request(session, &pri_spec, NULL, 0, NULL, NULL));
7182   CU_ASSERT(NGHTTP2_HEADERS ==
7183             nghttp2_session_get_next_ob_item(session)->frame.hd.type);
7184   CU_ASSERT(0 == nghttp2_session_send(session));
7185 
7186   CU_ASSERT(5 ==
7187             nghttp2_submit_request(session, &pri_spec, NULL, 0, NULL, NULL));
7188   CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
7189 
7190   session->remote_settings.max_concurrent_streams = 3;
7191 
7192   CU_ASSERT(NGHTTP2_HEADERS ==
7193             nghttp2_session_get_next_ob_item(session)->frame.hd.type);
7194 
7195   nghttp2_session_del(session);
7196 
7197   /* Check that push reply HEADERS are queued into ob_ss_pq */
7198   nghttp2_session_server_new(&session, &callbacks, NULL);
7199   session->remote_settings.max_concurrent_streams = 0;
7200   open_sent_stream2(session, 2, NGHTTP2_STREAM_RESERVED);
7201   CU_ASSERT(0 == nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, 2,
7202                                         NULL, NULL, 0, NULL));
7203   CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
7204   CU_ASSERT(1 == nghttp2_outbound_queue_size(&session->ob_syn));
7205   nghttp2_session_del(session);
7206 }
7207 
test_nghttp2_session_pop_next_ob_item(void)7208 void test_nghttp2_session_pop_next_ob_item(void) {
7209   nghttp2_session *session;
7210   nghttp2_session_callbacks callbacks;
7211   nghttp2_outbound_item *item;
7212   nghttp2_priority_spec pri_spec;
7213   nghttp2_mem *mem;
7214 
7215   mem = nghttp2_mem_default();
7216   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7217   callbacks.send_callback = null_send_callback;
7218 
7219   nghttp2_session_client_new(&session, &callbacks, NULL);
7220   session->remote_settings.max_concurrent_streams = 1;
7221 
7222   CU_ASSERT(NULL == nghttp2_session_pop_next_ob_item(session));
7223 
7224   nghttp2_submit_ping(session, NGHTTP2_FLAG_NONE, NULL);
7225 
7226   nghttp2_priority_spec_init(&pri_spec, 0, 254, 0);
7227 
7228   nghttp2_submit_request(session, &pri_spec, NULL, 0, NULL, NULL);
7229 
7230   item = nghttp2_session_pop_next_ob_item(session);
7231   CU_ASSERT(NGHTTP2_PING == item->frame.hd.type);
7232   nghttp2_outbound_item_free(item, mem);
7233   mem->free(item, NULL);
7234 
7235   item = nghttp2_session_pop_next_ob_item(session);
7236   CU_ASSERT(NGHTTP2_HEADERS == item->frame.hd.type);
7237   nghttp2_outbound_item_free(item, mem);
7238   mem->free(item, NULL);
7239 
7240   CU_ASSERT(NULL == nghttp2_session_pop_next_ob_item(session));
7241 
7242   /* Incoming stream does not affect the number of outgoing max
7243      concurrent streams. */
7244   open_recv_stream(session, 4);
7245   /* In-flight outgoing stream */
7246   open_sent_stream(session, 1);
7247 
7248   nghttp2_priority_spec_init(&pri_spec, 0, NGHTTP2_MAX_WEIGHT, 0);
7249 
7250   nghttp2_submit_request(session, &pri_spec, NULL, 0, NULL, NULL);
7251 
7252   CU_ASSERT(NULL == nghttp2_session_pop_next_ob_item(session));
7253 
7254   session->remote_settings.max_concurrent_streams = 2;
7255 
7256   item = nghttp2_session_pop_next_ob_item(session);
7257   CU_ASSERT(NGHTTP2_HEADERS == item->frame.hd.type);
7258   nghttp2_outbound_item_free(item, mem);
7259   mem->free(item, NULL);
7260 
7261   nghttp2_session_del(session);
7262 
7263   /* Check that push reply HEADERS are queued into ob_ss_pq */
7264   nghttp2_session_server_new(&session, &callbacks, NULL);
7265   session->remote_settings.max_concurrent_streams = 0;
7266   open_sent_stream2(session, 2, NGHTTP2_STREAM_RESERVED);
7267   CU_ASSERT(0 == nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, 2,
7268                                         NULL, NULL, 0, NULL));
7269   CU_ASSERT(NULL == nghttp2_session_pop_next_ob_item(session));
7270   CU_ASSERT(1 == nghttp2_outbound_queue_size(&session->ob_syn));
7271   nghttp2_session_del(session);
7272 }
7273 
test_nghttp2_session_reply_fail(void)7274 void test_nghttp2_session_reply_fail(void) {
7275   nghttp2_session *session;
7276   nghttp2_session_callbacks callbacks;
7277   nghttp2_data_provider data_prd;
7278   my_user_data ud;
7279 
7280   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7281   callbacks.send_callback = fail_send_callback;
7282 
7283   data_prd.read_callback = fixed_length_data_source_read_callback;
7284   ud.data_source_length = 4 * 1024;
7285   CU_ASSERT(0 == nghttp2_session_server_new(&session, &callbacks, &ud));
7286   open_recv_stream2(session, 1, NGHTTP2_STREAM_OPENING);
7287   CU_ASSERT(0 == nghttp2_submit_response(session, 1, NULL, 0, &data_prd));
7288   CU_ASSERT(NGHTTP2_ERR_CALLBACK_FAILURE == nghttp2_session_send(session));
7289   nghttp2_session_del(session);
7290 }
7291 
test_nghttp2_session_max_concurrent_streams(void)7292 void test_nghttp2_session_max_concurrent_streams(void) {
7293   nghttp2_session *session;
7294   nghttp2_session_callbacks callbacks;
7295   nghttp2_frame frame;
7296   nghttp2_outbound_item *item;
7297   nghttp2_mem *mem;
7298 
7299   mem = nghttp2_mem_default();
7300   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7301   callbacks.send_callback = null_send_callback;
7302 
7303   nghttp2_session_server_new(&session, &callbacks, NULL);
7304   open_recv_stream(session, 1);
7305 
7306   /* Check un-ACKed SETTINGS_MAX_CONCURRENT_STREAMS */
7307   nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 3,
7308                              NGHTTP2_HCAT_HEADERS, NULL, NULL, 0);
7309   session->pending_local_max_concurrent_stream = 1;
7310 
7311   CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
7312             nghttp2_session_on_request_headers_received(session, &frame));
7313 
7314   item = nghttp2_outbound_queue_top(&session->ob_reg);
7315   CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
7316   CU_ASSERT(NGHTTP2_REFUSED_STREAM == item->frame.rst_stream.error_code);
7317 
7318   CU_ASSERT(0 == nghttp2_session_send(session));
7319 
7320   /* Check ACKed SETTINGS_MAX_CONCURRENT_STREAMS */
7321   session->local_settings.max_concurrent_streams = 1;
7322   frame.hd.stream_id = 5;
7323 
7324   CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
7325             nghttp2_session_on_request_headers_received(session, &frame));
7326 
7327   item = nghttp2_outbound_queue_top(&session->ob_reg);
7328   CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
7329   CU_ASSERT(NGHTTP2_PROTOCOL_ERROR == item->frame.goaway.error_code);
7330 
7331   nghttp2_frame_headers_free(&frame.headers, mem);
7332   nghttp2_session_del(session);
7333 }
7334 
test_nghttp2_session_stop_data_with_rst_stream(void)7335 void test_nghttp2_session_stop_data_with_rst_stream(void) {
7336   nghttp2_session *session;
7337   nghttp2_session_callbacks callbacks;
7338   my_user_data ud;
7339   nghttp2_data_provider data_prd;
7340   nghttp2_frame frame;
7341 
7342   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7343   callbacks.on_frame_send_callback = on_frame_send_callback;
7344   callbacks.send_callback = block_count_send_callback;
7345   data_prd.read_callback = fixed_length_data_source_read_callback;
7346 
7347   ud.frame_send_cb_called = 0;
7348   ud.data_source_length = NGHTTP2_DATA_PAYLOADLEN * 4;
7349 
7350   nghttp2_session_server_new(&session, &callbacks, &ud);
7351   open_recv_stream2(session, 1, NGHTTP2_STREAM_OPENING);
7352   nghttp2_submit_response(session, 1, NULL, 0, &data_prd);
7353 
7354   ud.block_count = 2;
7355   /* Sends response HEADERS + DATA[0] */
7356   CU_ASSERT(0 == nghttp2_session_send(session));
7357   CU_ASSERT(NGHTTP2_DATA == ud.sent_frame_type);
7358   /* data for DATA[1] is read from data_prd but it is not sent */
7359   CU_ASSERT(ud.data_source_length == NGHTTP2_DATA_PAYLOADLEN * 2);
7360 
7361   nghttp2_frame_rst_stream_init(&frame.rst_stream, 1, NGHTTP2_CANCEL);
7362   CU_ASSERT(0 == nghttp2_session_on_rst_stream_received(session, &frame));
7363   nghttp2_frame_rst_stream_free(&frame.rst_stream);
7364 
7365   /* Big enough number to send all DATA frames potentially. */
7366   ud.block_count = 100;
7367   /* Nothing will be sent in the following call. */
7368   CU_ASSERT(0 == nghttp2_session_send(session));
7369   /* With RST_STREAM, stream is canceled and further DATA on that
7370      stream are not sent. */
7371   CU_ASSERT(ud.data_source_length == NGHTTP2_DATA_PAYLOADLEN * 2);
7372 
7373   CU_ASSERT(NULL == nghttp2_session_get_stream(session, 1));
7374 
7375   nghttp2_session_del(session);
7376 }
7377 
test_nghttp2_session_defer_data(void)7378 void test_nghttp2_session_defer_data(void) {
7379   nghttp2_session *session;
7380   nghttp2_session_callbacks callbacks;
7381   my_user_data ud;
7382   nghttp2_data_provider data_prd;
7383   nghttp2_outbound_item *item;
7384   nghttp2_stream *stream;
7385 
7386   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7387   callbacks.on_frame_send_callback = on_frame_send_callback;
7388   callbacks.send_callback = block_count_send_callback;
7389   data_prd.read_callback = defer_data_source_read_callback;
7390 
7391   ud.frame_send_cb_called = 0;
7392   ud.data_source_length = NGHTTP2_DATA_PAYLOADLEN * 4;
7393 
7394   nghttp2_session_server_new(&session, &callbacks, &ud);
7395   stream = open_recv_stream2(session, 1, NGHTTP2_STREAM_OPENING);
7396 
7397   session->remote_window_size = 1 << 20;
7398   stream->remote_window_size = 1 << 20;
7399 
7400   nghttp2_submit_response(session, 1, NULL, 0, &data_prd);
7401 
7402   ud.block_count = 1;
7403   /* Sends HEADERS reply */
7404   CU_ASSERT(0 == nghttp2_session_send(session));
7405   CU_ASSERT(NGHTTP2_HEADERS == ud.sent_frame_type);
7406   /* No data is read */
7407   CU_ASSERT(ud.data_source_length == NGHTTP2_DATA_PAYLOADLEN * 4);
7408 
7409   ud.block_count = 1;
7410   nghttp2_submit_ping(session, NGHTTP2_FLAG_NONE, NULL);
7411   /* Sends PING */
7412   CU_ASSERT(0 == nghttp2_session_send(session));
7413   CU_ASSERT(NGHTTP2_PING == ud.sent_frame_type);
7414 
7415   /* Resume deferred DATA */
7416   CU_ASSERT(0 == nghttp2_session_resume_data(session, 1));
7417   item = stream->item;
7418   item->aux_data.data.data_prd.read_callback =
7419       fixed_length_data_source_read_callback;
7420   ud.block_count = 1;
7421   /* Reads 2 DATA chunks */
7422   CU_ASSERT(0 == nghttp2_session_send(session));
7423   CU_ASSERT(ud.data_source_length == NGHTTP2_DATA_PAYLOADLEN * 2);
7424 
7425   /* Deferred again */
7426   item->aux_data.data.data_prd.read_callback = defer_data_source_read_callback;
7427   /* This is needed since 16KiB block is already read and waiting to be
7428      sent. No read_callback invocation. */
7429   ud.block_count = 1;
7430   CU_ASSERT(0 == nghttp2_session_send(session));
7431   CU_ASSERT(ud.data_source_length == NGHTTP2_DATA_PAYLOADLEN * 2);
7432 
7433   /* Resume deferred DATA */
7434   CU_ASSERT(0 == nghttp2_session_resume_data(session, 1));
7435   item->aux_data.data.data_prd.read_callback =
7436       fixed_length_data_source_read_callback;
7437   ud.block_count = 1;
7438   /* Reads 2 16KiB blocks */
7439   CU_ASSERT(0 == nghttp2_session_send(session));
7440   CU_ASSERT(ud.data_source_length == 0);
7441 
7442   nghttp2_session_del(session);
7443 }
7444 
test_nghttp2_session_flow_control(void)7445 void test_nghttp2_session_flow_control(void) {
7446   nghttp2_session *session;
7447   nghttp2_session_callbacks callbacks;
7448   my_user_data ud;
7449   nghttp2_data_provider data_prd;
7450   nghttp2_frame frame;
7451   nghttp2_stream *stream;
7452   int32_t new_initial_window_size;
7453   nghttp2_settings_entry iv[1];
7454   nghttp2_frame settings_frame;
7455   nghttp2_mem *mem;
7456 
7457   mem = nghttp2_mem_default();
7458   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7459   callbacks.send_callback = fixed_bytes_send_callback;
7460   callbacks.on_frame_send_callback = on_frame_send_callback;
7461   data_prd.read_callback = fixed_length_data_source_read_callback;
7462 
7463   ud.frame_send_cb_called = 0;
7464   ud.data_source_length = 128 * 1024;
7465   /* Use smaller emission count so that we can check outbound flow
7466      control window calculation is correct. */
7467   ud.fixed_sendlen = 2 * 1024;
7468 
7469   /* Initial window size to 64KiB - 1*/
7470   nghttp2_session_client_new(&session, &callbacks, &ud);
7471   /* Change it to 64KiB for easy calculation */
7472   session->remote_window_size = 64 * 1024;
7473   session->remote_settings.initial_window_size = 64 * 1024;
7474 
7475   nghttp2_submit_request(session, NULL, NULL, 0, &data_prd, NULL);
7476 
7477   /* Sends 64KiB - 1 data */
7478   CU_ASSERT(0 == nghttp2_session_send(session));
7479   CU_ASSERT(64 * 1024 == ud.data_source_length);
7480 
7481   /* Back 32KiB in stream window */
7482   nghttp2_frame_window_update_init(&frame.window_update, NGHTTP2_FLAG_NONE, 1,
7483                                    32 * 1024);
7484   nghttp2_session_on_window_update_received(session, &frame);
7485 
7486   /* Send nothing because of connection-level window */
7487   CU_ASSERT(0 == nghttp2_session_send(session));
7488   CU_ASSERT(64 * 1024 == ud.data_source_length);
7489 
7490   /* Back 32KiB in connection-level window */
7491   frame.hd.stream_id = 0;
7492   nghttp2_session_on_window_update_received(session, &frame);
7493 
7494   /* Sends another 32KiB data */
7495   CU_ASSERT(0 == nghttp2_session_send(session));
7496   CU_ASSERT(32 * 1024 == ud.data_source_length);
7497 
7498   stream = nghttp2_session_get_stream(session, 1);
7499   /* Change initial window size to 16KiB. The window_size becomes
7500      negative. */
7501   new_initial_window_size = 16 * 1024;
7502   stream->remote_window_size =
7503       new_initial_window_size -
7504       ((int32_t)session->remote_settings.initial_window_size -
7505        stream->remote_window_size);
7506   session->remote_settings.initial_window_size =
7507       (uint32_t)new_initial_window_size;
7508   CU_ASSERT(-48 * 1024 == stream->remote_window_size);
7509 
7510   /* Back 48KiB to stream window */
7511   frame.hd.stream_id = 1;
7512   frame.window_update.window_size_increment = 48 * 1024;
7513   nghttp2_session_on_window_update_received(session, &frame);
7514 
7515   /* Nothing is sent because window_size is 0 */
7516   CU_ASSERT(0 == nghttp2_session_send(session));
7517   CU_ASSERT(32 * 1024 == ud.data_source_length);
7518 
7519   /* Back 16KiB in stream window */
7520   frame.hd.stream_id = 1;
7521   frame.window_update.window_size_increment = 16 * 1024;
7522   nghttp2_session_on_window_update_received(session, &frame);
7523 
7524   /* Back 24KiB in connection-level window */
7525   frame.hd.stream_id = 0;
7526   frame.window_update.window_size_increment = 24 * 1024;
7527   nghttp2_session_on_window_update_received(session, &frame);
7528 
7529   /* Sends another 16KiB data */
7530   CU_ASSERT(0 == nghttp2_session_send(session));
7531   CU_ASSERT(16 * 1024 == ud.data_source_length);
7532 
7533   /* Increase initial window size to 32KiB */
7534   iv[0].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
7535   iv[0].value = 32 * 1024;
7536 
7537   nghttp2_frame_settings_init(&settings_frame.settings, NGHTTP2_FLAG_NONE,
7538                               dup_iv(iv, 1), 1);
7539   nghttp2_session_on_settings_received(session, &settings_frame, 1);
7540   nghttp2_frame_settings_free(&settings_frame.settings, mem);
7541 
7542   /* Sends another 8KiB data */
7543   CU_ASSERT(0 == nghttp2_session_send(session));
7544   CU_ASSERT(8 * 1024 == ud.data_source_length);
7545 
7546   /* Back 8KiB in connection-level window */
7547   frame.hd.stream_id = 0;
7548   frame.window_update.window_size_increment = 8 * 1024;
7549   nghttp2_session_on_window_update_received(session, &frame);
7550 
7551   /* Sends last 8KiB data */
7552   CU_ASSERT(0 == nghttp2_session_send(session));
7553   CU_ASSERT(0 == ud.data_source_length);
7554   CU_ASSERT(nghttp2_session_get_stream(session, 1)->shut_flags &
7555             NGHTTP2_SHUT_WR);
7556 
7557   nghttp2_frame_window_update_free(&frame.window_update);
7558   nghttp2_session_del(session);
7559 }
7560 
test_nghttp2_session_flow_control_data_recv(void)7561 void test_nghttp2_session_flow_control_data_recv(void) {
7562   nghttp2_session *session;
7563   nghttp2_session_callbacks callbacks;
7564   uint8_t data[64 * 1024 + 16];
7565   nghttp2_frame_hd hd;
7566   nghttp2_outbound_item *item;
7567   nghttp2_stream *stream;
7568 
7569   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7570   callbacks.send_callback = null_send_callback;
7571 
7572   /* Initial window size to 64KiB - 1*/
7573   nghttp2_session_client_new(&session, &callbacks, NULL);
7574 
7575   stream = open_sent_stream(session, 1);
7576 
7577   nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_WR);
7578 
7579   session->local_window_size = NGHTTP2_MAX_PAYLOADLEN;
7580   stream->local_window_size = NGHTTP2_MAX_PAYLOADLEN;
7581 
7582   /* Create DATA frame */
7583   memset(data, 0, sizeof(data));
7584   nghttp2_frame_hd_init(&hd, NGHTTP2_MAX_PAYLOADLEN, NGHTTP2_DATA,
7585                         NGHTTP2_FLAG_END_STREAM, 1);
7586 
7587   nghttp2_frame_pack_frame_hd(data, &hd);
7588   CU_ASSERT(NGHTTP2_MAX_PAYLOADLEN + NGHTTP2_FRAME_HDLEN ==
7589             nghttp2_session_mem_recv(
7590                 session, data, NGHTTP2_MAX_PAYLOADLEN + NGHTTP2_FRAME_HDLEN));
7591 
7592   item = nghttp2_session_get_next_ob_item(session);
7593   /* Since this is the last frame, stream-level WINDOW_UPDATE is not
7594      issued, but connection-level is. */
7595   CU_ASSERT(NGHTTP2_WINDOW_UPDATE == item->frame.hd.type);
7596   CU_ASSERT(0 == item->frame.hd.stream_id);
7597   CU_ASSERT(NGHTTP2_MAX_PAYLOADLEN ==
7598             item->frame.window_update.window_size_increment);
7599 
7600   CU_ASSERT(0 == nghttp2_session_send(session));
7601 
7602   /* Receive DATA for closed stream. They are still subject to under
7603      connection-level flow control, since this situation arises when
7604      RST_STREAM is issued by the remote, but the local side keeps
7605      sending DATA frames. Without calculating connection-level window,
7606      the subsequent flow control gets confused. */
7607   CU_ASSERT(NGHTTP2_MAX_PAYLOADLEN + NGHTTP2_FRAME_HDLEN ==
7608             nghttp2_session_mem_recv(
7609                 session, data, NGHTTP2_MAX_PAYLOADLEN + NGHTTP2_FRAME_HDLEN));
7610 
7611   item = nghttp2_session_get_next_ob_item(session);
7612   CU_ASSERT(NGHTTP2_WINDOW_UPDATE == item->frame.hd.type);
7613   CU_ASSERT(0 == item->frame.hd.stream_id);
7614   CU_ASSERT(NGHTTP2_MAX_PAYLOADLEN ==
7615             item->frame.window_update.window_size_increment);
7616 
7617   nghttp2_session_del(session);
7618 }
7619 
test_nghttp2_session_flow_control_data_with_padding_recv(void)7620 void test_nghttp2_session_flow_control_data_with_padding_recv(void) {
7621   nghttp2_session *session;
7622   nghttp2_session_callbacks callbacks;
7623   uint8_t data[1024];
7624   nghttp2_frame_hd hd;
7625   nghttp2_stream *stream;
7626   nghttp2_option *option;
7627 
7628   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7629   callbacks.send_callback = null_send_callback;
7630 
7631   nghttp2_option_new(&option);
7632   /* Disable auto window update so that we can check padding is
7633      consumed automatically */
7634   nghttp2_option_set_no_auto_window_update(option, 1);
7635 
7636   /* Initial window size to 64KiB - 1*/
7637   nghttp2_session_client_new2(&session, &callbacks, NULL, option);
7638 
7639   nghttp2_option_del(option);
7640 
7641   stream = open_sent_stream(session, 1);
7642 
7643   /* Create DATA frame */
7644   memset(data, 0, sizeof(data));
7645   nghttp2_frame_hd_init(&hd, 357, NGHTTP2_DATA, NGHTTP2_FLAG_PADDED, 1);
7646 
7647   nghttp2_frame_pack_frame_hd(data, &hd);
7648   /* Set Pad Length field, which itself is padding */
7649   data[NGHTTP2_FRAME_HDLEN] = 255;
7650 
7651   CU_ASSERT(
7652       (ssize_t)(NGHTTP2_FRAME_HDLEN + hd.length) ==
7653       nghttp2_session_mem_recv(session, data, NGHTTP2_FRAME_HDLEN + hd.length));
7654 
7655   CU_ASSERT((int32_t)hd.length == session->recv_window_size);
7656   CU_ASSERT((int32_t)hd.length == stream->recv_window_size);
7657   CU_ASSERT(256 == session->consumed_size);
7658   CU_ASSERT(256 == stream->consumed_size);
7659   CU_ASSERT(357 == session->recv_window_size);
7660   CU_ASSERT(357 == stream->recv_window_size);
7661 
7662   /* Receive the same DATA frame, but in 2 parts: first 9 + 1 + 102
7663      bytes which includes 1st padding byte, and remainder */
7664   CU_ASSERT((ssize_t)(NGHTTP2_FRAME_HDLEN + 103) ==
7665             nghttp2_session_mem_recv(session, data, NGHTTP2_FRAME_HDLEN + 103));
7666   CU_ASSERT(258 == session->consumed_size);
7667   CU_ASSERT(258 == stream->consumed_size);
7668   CU_ASSERT(460 == session->recv_window_size);
7669   CU_ASSERT(460 == stream->recv_window_size);
7670 
7671   /* 357 - 103 = 254 bytes left */
7672   CU_ASSERT(254 == nghttp2_session_mem_recv(session, data, 254));
7673   CU_ASSERT(512 == session->consumed_size);
7674   CU_ASSERT(512 == stream->consumed_size);
7675   CU_ASSERT(714 == session->recv_window_size);
7676   CU_ASSERT(714 == stream->recv_window_size);
7677 
7678   /* Receive the same DATA frame, but in 2 parts: first 9 = 1 + 101
7679      bytes which only includes data without padding, 2nd part is
7680      padding only */
7681   CU_ASSERT((ssize_t)(NGHTTP2_FRAME_HDLEN + 102) ==
7682             nghttp2_session_mem_recv(session, data, NGHTTP2_FRAME_HDLEN + 102));
7683   CU_ASSERT(513 == session->consumed_size);
7684   CU_ASSERT(513 == stream->consumed_size);
7685   CU_ASSERT(816 == session->recv_window_size);
7686   CU_ASSERT(816 == stream->recv_window_size);
7687 
7688   /* 357 - 102 = 255 bytes left */
7689   CU_ASSERT(255 == nghttp2_session_mem_recv(session, data, 255));
7690   CU_ASSERT(768 == session->consumed_size);
7691   CU_ASSERT(768 == stream->consumed_size);
7692   CU_ASSERT(1071 == session->recv_window_size);
7693   CU_ASSERT(1071 == stream->recv_window_size);
7694 
7695   /* Receive the same DATA frame, but in 2 parts: first 9 = 1 + 50
7696      bytes which includes byte up to middle of data, 2nd part is the
7697      remainder */
7698   CU_ASSERT((ssize_t)(NGHTTP2_FRAME_HDLEN + 51) ==
7699             nghttp2_session_mem_recv(session, data, NGHTTP2_FRAME_HDLEN + 51));
7700   CU_ASSERT(769 == session->consumed_size);
7701   CU_ASSERT(769 == stream->consumed_size);
7702   CU_ASSERT(1122 == session->recv_window_size);
7703   CU_ASSERT(1122 == stream->recv_window_size);
7704 
7705   /* 357 - 51 = 306 bytes left */
7706   CU_ASSERT(306 == nghttp2_session_mem_recv(session, data, 306));
7707   CU_ASSERT(1024 == session->consumed_size);
7708   CU_ASSERT(1024 == stream->consumed_size);
7709   CU_ASSERT(1428 == session->recv_window_size);
7710   CU_ASSERT(1428 == stream->recv_window_size);
7711 
7712   nghttp2_session_del(session);
7713 }
7714 
test_nghttp2_session_data_read_temporal_failure(void)7715 void test_nghttp2_session_data_read_temporal_failure(void) {
7716   nghttp2_session *session;
7717   nghttp2_session_callbacks callbacks;
7718   my_user_data ud;
7719   nghttp2_data_provider data_prd;
7720   nghttp2_frame frame;
7721   nghttp2_stream *stream;
7722   size_t data_size = 128 * 1024;
7723 
7724   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7725   callbacks.send_callback = null_send_callback;
7726   callbacks.on_frame_send_callback = on_frame_send_callback;
7727   data_prd.read_callback = fixed_length_data_source_read_callback;
7728 
7729   ud.data_source_length = data_size;
7730 
7731   /* Initial window size is 64KiB - 1 */
7732   nghttp2_session_client_new(&session, &callbacks, &ud);
7733   nghttp2_submit_request(session, NULL, NULL, 0, &data_prd, NULL);
7734 
7735   /* Sends NGHTTP2_INITIAL_WINDOW_SIZE data, assuming, it is equal to
7736      or smaller than NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE */
7737   CU_ASSERT(0 == nghttp2_session_send(session));
7738   CU_ASSERT(data_size - NGHTTP2_INITIAL_WINDOW_SIZE == ud.data_source_length);
7739 
7740   stream = nghttp2_session_get_stream(session, 1);
7741   CU_ASSERT(NGHTTP2_DATA == stream->item->frame.hd.type);
7742 
7743   stream->item->aux_data.data.data_prd.read_callback =
7744       temporal_failure_data_source_read_callback;
7745 
7746   /* Back NGHTTP2_INITIAL_WINDOW_SIZE to both connection-level and
7747      stream-wise window */
7748   nghttp2_frame_window_update_init(&frame.window_update, NGHTTP2_FLAG_NONE, 1,
7749                                    NGHTTP2_INITIAL_WINDOW_SIZE);
7750   nghttp2_session_on_window_update_received(session, &frame);
7751   frame.hd.stream_id = 0;
7752   nghttp2_session_on_window_update_received(session, &frame);
7753   nghttp2_frame_window_update_free(&frame.window_update);
7754 
7755   /* Sending data will fail (soft fail) and treated as stream error */
7756   ud.frame_send_cb_called = 0;
7757   CU_ASSERT(0 == nghttp2_session_send(session));
7758   CU_ASSERT(data_size - NGHTTP2_INITIAL_WINDOW_SIZE == ud.data_source_length);
7759 
7760   CU_ASSERT(1 == ud.frame_send_cb_called);
7761   CU_ASSERT(NGHTTP2_RST_STREAM == ud.sent_frame_type);
7762 
7763   data_prd.read_callback = fail_data_source_read_callback;
7764   nghttp2_submit_request(session, NULL, NULL, 0, &data_prd, NULL);
7765   /* Sending data will fail (hard fail) and session tear down */
7766   CU_ASSERT(NGHTTP2_ERR_CALLBACK_FAILURE == nghttp2_session_send(session));
7767 
7768   nghttp2_session_del(session);
7769 }
7770 
test_nghttp2_session_on_stream_close(void)7771 void test_nghttp2_session_on_stream_close(void) {
7772   nghttp2_session *session;
7773   nghttp2_session_callbacks callbacks;
7774   my_user_data user_data;
7775   nghttp2_stream *stream;
7776 
7777   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7778   callbacks.on_stream_close_callback = on_stream_close_callback;
7779   user_data.stream_close_cb_called = 0;
7780 
7781   nghttp2_session_client_new(&session, &callbacks, &user_data);
7782   stream =
7783       open_sent_stream3(session, 1, NGHTTP2_STREAM_FLAG_NONE, &pri_spec_default,
7784                         NGHTTP2_STREAM_OPENED, &user_data);
7785   CU_ASSERT(stream != NULL);
7786   CU_ASSERT(nghttp2_session_close_stream(session, 1, NGHTTP2_NO_ERROR) == 0);
7787   CU_ASSERT(user_data.stream_close_cb_called == 1);
7788   nghttp2_session_del(session);
7789 }
7790 
test_nghttp2_session_on_ctrl_not_send(void)7791 void test_nghttp2_session_on_ctrl_not_send(void) {
7792   nghttp2_session *session;
7793   nghttp2_session_callbacks callbacks;
7794   my_user_data user_data;
7795   nghttp2_stream *stream;
7796 
7797   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7798   callbacks.on_frame_not_send_callback = on_frame_not_send_callback;
7799   callbacks.send_callback = null_send_callback;
7800   user_data.frame_not_send_cb_called = 0;
7801   user_data.not_sent_frame_type = 0;
7802   user_data.not_sent_error = 0;
7803 
7804   nghttp2_session_server_new(&session, &callbacks, &user_data);
7805   stream =
7806       open_recv_stream3(session, 1, NGHTTP2_STREAM_FLAG_NONE, &pri_spec_default,
7807                         NGHTTP2_STREAM_OPENING, &user_data);
7808 
7809   /* Check response HEADERS */
7810   /* Send bogus stream ID */
7811   CU_ASSERT(0 == nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, 3,
7812                                         NULL, NULL, 0, NULL));
7813   CU_ASSERT(0 == nghttp2_session_send(session));
7814   CU_ASSERT(1 == user_data.frame_not_send_cb_called);
7815   CU_ASSERT(NGHTTP2_HEADERS == user_data.not_sent_frame_type);
7816   CU_ASSERT(NGHTTP2_ERR_STREAM_CLOSED == user_data.not_sent_error);
7817 
7818   user_data.frame_not_send_cb_called = 0;
7819   /* Shutdown transmission */
7820   stream->shut_flags |= NGHTTP2_SHUT_WR;
7821   CU_ASSERT(0 == nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, 1,
7822                                         NULL, NULL, 0, NULL));
7823   CU_ASSERT(0 == nghttp2_session_send(session));
7824   CU_ASSERT(1 == user_data.frame_not_send_cb_called);
7825   CU_ASSERT(NGHTTP2_HEADERS == user_data.not_sent_frame_type);
7826   CU_ASSERT(NGHTTP2_ERR_STREAM_SHUT_WR == user_data.not_sent_error);
7827 
7828   stream->shut_flags = NGHTTP2_SHUT_NONE;
7829   user_data.frame_not_send_cb_called = 0;
7830   /* Queue RST_STREAM */
7831   CU_ASSERT(0 == nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, 1,
7832                                         NULL, NULL, 0, NULL));
7833   CU_ASSERT(0 == nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, 1,
7834                                            NGHTTP2_INTERNAL_ERROR));
7835   CU_ASSERT(0 == nghttp2_session_send(session));
7836   CU_ASSERT(1 == user_data.frame_not_send_cb_called);
7837   CU_ASSERT(NGHTTP2_HEADERS == user_data.not_sent_frame_type);
7838   CU_ASSERT(NGHTTP2_ERR_STREAM_CLOSING == user_data.not_sent_error);
7839 
7840   nghttp2_session_del(session);
7841 
7842   /* Check request HEADERS */
7843   user_data.frame_not_send_cb_called = 0;
7844   CU_ASSERT(nghttp2_session_client_new(&session, &callbacks, &user_data) == 0);
7845   /* Maximum Stream ID is reached */
7846   session->next_stream_id = (1u << 31) + 1;
7847   CU_ASSERT(NGHTTP2_ERR_STREAM_ID_NOT_AVAILABLE ==
7848             nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, -1, NULL,
7849                                    NULL, 0, NULL));
7850 
7851   user_data.frame_not_send_cb_called = 0;
7852   /* GOAWAY received */
7853   session->goaway_flags |= NGHTTP2_GOAWAY_RECV;
7854   session->next_stream_id = 9;
7855 
7856   CU_ASSERT(0 < nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, -1,
7857                                        NULL, NULL, 0, NULL));
7858   CU_ASSERT(0 == nghttp2_session_send(session));
7859   CU_ASSERT(1 == user_data.frame_not_send_cb_called);
7860   CU_ASSERT(NGHTTP2_HEADERS == user_data.not_sent_frame_type);
7861   CU_ASSERT(NGHTTP2_ERR_START_STREAM_NOT_ALLOWED == user_data.not_sent_error);
7862 
7863   nghttp2_session_del(session);
7864 }
7865 
test_nghttp2_session_get_outbound_queue_size(void)7866 void test_nghttp2_session_get_outbound_queue_size(void) {
7867   nghttp2_session *session;
7868   nghttp2_session_callbacks callbacks;
7869 
7870   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7871   CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, NULL));
7872   CU_ASSERT(0 == nghttp2_session_get_outbound_queue_size(session));
7873 
7874   CU_ASSERT(0 == nghttp2_submit_ping(session, NGHTTP2_FLAG_NONE, NULL));
7875   CU_ASSERT(1 == nghttp2_session_get_outbound_queue_size(session));
7876 
7877   CU_ASSERT(0 == nghttp2_submit_goaway(session, NGHTTP2_FLAG_NONE, 2,
7878                                        NGHTTP2_NO_ERROR, NULL, 0));
7879   CU_ASSERT(2 == nghttp2_session_get_outbound_queue_size(session));
7880 
7881   nghttp2_session_del(session);
7882 }
7883 
test_nghttp2_session_get_effective_local_window_size(void)7884 void test_nghttp2_session_get_effective_local_window_size(void) {
7885   nghttp2_session *session;
7886   nghttp2_session_callbacks callbacks;
7887   nghttp2_stream *stream;
7888 
7889   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7890   CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, NULL));
7891 
7892   stream = open_sent_stream(session, 1);
7893 
7894   CU_ASSERT(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE ==
7895             nghttp2_session_get_effective_local_window_size(session));
7896   CU_ASSERT(0 == nghttp2_session_get_effective_recv_data_length(session));
7897 
7898   CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE ==
7899             nghttp2_session_get_stream_effective_local_window_size(session, 1));
7900   CU_ASSERT(0 ==
7901             nghttp2_session_get_stream_effective_recv_data_length(session, 1));
7902 
7903   /* Check connection flow control */
7904   session->recv_window_size = 100;
7905   nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 0, 1100);
7906 
7907   CU_ASSERT(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE + 1000 ==
7908             nghttp2_session_get_effective_local_window_size(session));
7909   CU_ASSERT(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE + 1000 ==
7910             nghttp2_session_get_local_window_size(session));
7911   CU_ASSERT(0 == nghttp2_session_get_effective_recv_data_length(session));
7912 
7913   nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 0, -50);
7914   /* Now session->recv_window_size = -50 */
7915   CU_ASSERT(-50 == session->recv_window_size);
7916   CU_ASSERT(50 == session->recv_reduction);
7917   CU_ASSERT(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE + 950 ==
7918             nghttp2_session_get_effective_local_window_size(session));
7919   CU_ASSERT(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE + 1000 ==
7920             nghttp2_session_get_local_window_size(session));
7921   CU_ASSERT(0 == nghttp2_session_get_effective_recv_data_length(session));
7922 
7923   session->recv_window_size += 50;
7924 
7925   /* Now session->recv_window_size = 0 */
7926 
7927   CU_ASSERT(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE + 950 ==
7928             nghttp2_session_get_local_window_size(session));
7929 
7930   nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 0, 100);
7931   CU_ASSERT(50 == session->recv_window_size);
7932   CU_ASSERT(0 == session->recv_reduction);
7933   CU_ASSERT(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE + 1050 ==
7934             nghttp2_session_get_effective_local_window_size(session));
7935   CU_ASSERT(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE + 1000 ==
7936             nghttp2_session_get_local_window_size(session));
7937   CU_ASSERT(50 == nghttp2_session_get_effective_recv_data_length(session));
7938 
7939   /* Check stream flow control */
7940   stream->recv_window_size = 100;
7941   nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 1, 1100);
7942 
7943   CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE + 1000 ==
7944             nghttp2_session_get_stream_effective_local_window_size(session, 1));
7945   CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE + 1000 ==
7946             nghttp2_session_get_stream_local_window_size(session, 1));
7947   CU_ASSERT(0 ==
7948             nghttp2_session_get_stream_effective_recv_data_length(session, 1));
7949 
7950   nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 1, -50);
7951   /* Now stream->recv_window_size = -50 */
7952   CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE + 950 ==
7953             nghttp2_session_get_stream_effective_local_window_size(session, 1));
7954   CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE + 1000 ==
7955             nghttp2_session_get_stream_local_window_size(session, 1));
7956   CU_ASSERT(0 ==
7957             nghttp2_session_get_stream_effective_recv_data_length(session, 1));
7958 
7959   stream->recv_window_size += 50;
7960   /* Now stream->recv_window_size = 0 */
7961   nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 1, 100);
7962   CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE + 1050 ==
7963             nghttp2_session_get_stream_effective_local_window_size(session, 1));
7964   CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE + 1000 ==
7965             nghttp2_session_get_stream_local_window_size(session, 1));
7966   CU_ASSERT(50 ==
7967             nghttp2_session_get_stream_effective_recv_data_length(session, 1));
7968 
7969   nghttp2_session_del(session);
7970 }
7971 
test_nghttp2_session_set_option(void)7972 void test_nghttp2_session_set_option(void) {
7973   nghttp2_session *session;
7974   nghttp2_session_callbacks callbacks;
7975   nghttp2_option *option;
7976   nghttp2_hd_deflater *deflater;
7977   int rv;
7978 
7979   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7980   callbacks.send_callback = null_send_callback;
7981 
7982   /* Test for nghttp2_option_set_no_auto_window_update */
7983   nghttp2_option_new(&option);
7984   nghttp2_option_set_no_auto_window_update(option, 1);
7985 
7986   nghttp2_session_client_new2(&session, &callbacks, NULL, option);
7987 
7988   CU_ASSERT(session->opt_flags & NGHTTP2_OPTMASK_NO_AUTO_WINDOW_UPDATE);
7989 
7990   nghttp2_session_del(session);
7991   nghttp2_option_del(option);
7992 
7993   /* Test for nghttp2_option_set_peer_max_concurrent_streams */
7994   nghttp2_option_new(&option);
7995   nghttp2_option_set_peer_max_concurrent_streams(option, 100);
7996 
7997   nghttp2_session_client_new2(&session, &callbacks, NULL, option);
7998 
7999   CU_ASSERT(100 == session->remote_settings.max_concurrent_streams);
8000   nghttp2_session_del(session);
8001   nghttp2_option_del(option);
8002 
8003   /* Test for nghttp2_option_set_max_reserved_remote_streams */
8004   nghttp2_option_new(&option);
8005   nghttp2_option_set_max_reserved_remote_streams(option, 99);
8006 
8007   nghttp2_session_client_new2(&session, &callbacks, NULL, option);
8008 
8009   CU_ASSERT(99 == session->max_incoming_reserved_streams);
8010   nghttp2_session_del(session);
8011   nghttp2_option_del(option);
8012 
8013   /* Test for nghttp2_option_set_no_auto_ping_ack */
8014   nghttp2_option_new(&option);
8015   nghttp2_option_set_no_auto_ping_ack(option, 1);
8016 
8017   nghttp2_session_client_new2(&session, &callbacks, NULL, option);
8018 
8019   CU_ASSERT(session->opt_flags & NGHTTP2_OPTMASK_NO_AUTO_PING_ACK);
8020 
8021   nghttp2_session_del(session);
8022   nghttp2_option_del(option);
8023 
8024   /* Test for nghttp2_option_set_max_deflate_dynamic_table_size */
8025   nghttp2_option_new(&option);
8026   nghttp2_option_set_max_deflate_dynamic_table_size(option, 0);
8027 
8028   nghttp2_session_client_new2(&session, &callbacks, NULL, option);
8029 
8030   deflater = &session->hd_deflater;
8031 
8032   rv = nghttp2_submit_request(session, NULL, reqnv, ARRLEN(reqnv), NULL, NULL);
8033 
8034   CU_ASSERT(1 == rv);
8035 
8036   rv = nghttp2_session_send(session);
8037 
8038   CU_ASSERT(0 == rv);
8039   CU_ASSERT(0 == deflater->deflate_hd_table_bufsize_max);
8040   CU_ASSERT(0 == deflater->ctx.hd_table_bufsize);
8041 
8042   nghttp2_session_del(session);
8043   nghttp2_option_del(option);
8044 }
8045 
test_nghttp2_session_data_backoff_by_high_pri_frame(void)8046 void test_nghttp2_session_data_backoff_by_high_pri_frame(void) {
8047   nghttp2_session *session;
8048   nghttp2_session_callbacks callbacks;
8049   my_user_data ud;
8050   nghttp2_data_provider data_prd;
8051   nghttp2_stream *stream;
8052 
8053   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
8054   callbacks.send_callback = block_count_send_callback;
8055   callbacks.on_frame_send_callback = on_frame_send_callback;
8056   data_prd.read_callback = fixed_length_data_source_read_callback;
8057 
8058   ud.frame_send_cb_called = 0;
8059   ud.data_source_length = NGHTTP2_DATA_PAYLOADLEN * 4;
8060 
8061   nghttp2_session_client_new(&session, &callbacks, &ud);
8062   nghttp2_submit_request(session, NULL, NULL, 0, &data_prd, NULL);
8063 
8064   session->remote_window_size = 1 << 20;
8065 
8066   ud.block_count = 2;
8067   /* Sends request HEADERS + DATA[0] */
8068   CU_ASSERT(0 == nghttp2_session_send(session));
8069 
8070   stream = nghttp2_session_get_stream(session, 1);
8071   stream->remote_window_size = 1 << 20;
8072 
8073   CU_ASSERT(NGHTTP2_DATA == ud.sent_frame_type);
8074   /* data for DATA[1] is read from data_prd but it is not sent */
8075   CU_ASSERT(ud.data_source_length == NGHTTP2_DATA_PAYLOADLEN * 2);
8076 
8077   nghttp2_submit_ping(session, NGHTTP2_FLAG_NONE, NULL);
8078   ud.block_count = 2;
8079   /* Sends DATA[1] + PING, PING is interleaved in DATA sequence */
8080   CU_ASSERT(0 == nghttp2_session_send(session));
8081   CU_ASSERT(NGHTTP2_PING == ud.sent_frame_type);
8082   /* data for DATA[2] is read from data_prd but it is not sent */
8083   CU_ASSERT(ud.data_source_length == NGHTTP2_DATA_PAYLOADLEN);
8084 
8085   ud.block_count = 2;
8086   /* Sends DATA[2..3] */
8087   CU_ASSERT(0 == nghttp2_session_send(session));
8088 
8089   CU_ASSERT(stream->shut_flags & NGHTTP2_SHUT_WR);
8090 
8091   nghttp2_session_del(session);
8092 }
8093 
check_session_recv_data_with_padding(nghttp2_bufs * bufs,size_t datalen,nghttp2_mem * mem)8094 static void check_session_recv_data_with_padding(nghttp2_bufs *bufs,
8095                                                  size_t datalen,
8096                                                  nghttp2_mem *mem) {
8097   nghttp2_session *session;
8098   my_user_data ud;
8099   nghttp2_session_callbacks callbacks;
8100   uint8_t *in;
8101   size_t inlen;
8102 
8103   memset(&callbacks, 0, sizeof(callbacks));
8104   callbacks.on_frame_recv_callback = on_frame_recv_callback;
8105   callbacks.on_data_chunk_recv_callback = on_data_chunk_recv_callback;
8106   nghttp2_session_server_new(&session, &callbacks, &ud);
8107 
8108   open_recv_stream(session, 1);
8109 
8110   inlen = (size_t)nghttp2_bufs_remove(bufs, &in);
8111 
8112   ud.frame_recv_cb_called = 0;
8113   ud.data_chunk_len = 0;
8114 
8115   CU_ASSERT((ssize_t)inlen == nghttp2_session_mem_recv(session, in, inlen));
8116 
8117   CU_ASSERT(1 == ud.frame_recv_cb_called);
8118   CU_ASSERT(datalen == ud.data_chunk_len);
8119 
8120   mem->free(in, NULL);
8121   nghttp2_session_del(session);
8122 }
8123 
test_nghttp2_session_pack_data_with_padding(void)8124 void test_nghttp2_session_pack_data_with_padding(void) {
8125   nghttp2_session *session;
8126   my_user_data ud;
8127   nghttp2_session_callbacks callbacks;
8128   nghttp2_data_provider data_prd;
8129   nghttp2_frame *frame;
8130   size_t datalen = 55;
8131   nghttp2_mem *mem;
8132 
8133   mem = nghttp2_mem_default();
8134 
8135   memset(&callbacks, 0, sizeof(callbacks));
8136   callbacks.send_callback = block_count_send_callback;
8137   callbacks.on_frame_send_callback = on_frame_send_callback;
8138   callbacks.select_padding_callback = select_padding_callback;
8139 
8140   data_prd.read_callback = fixed_length_data_source_read_callback;
8141 
8142   nghttp2_session_client_new(&session, &callbacks, &ud);
8143 
8144   ud.padlen = 63;
8145 
8146   nghttp2_submit_request(session, NULL, NULL, 0, &data_prd, NULL);
8147   ud.block_count = 1;
8148   ud.data_source_length = datalen;
8149   /* Sends HEADERS */
8150   CU_ASSERT(0 == nghttp2_session_send(session));
8151   CU_ASSERT(NGHTTP2_HEADERS == ud.sent_frame_type);
8152 
8153   frame = &session->aob.item->frame;
8154 
8155   CU_ASSERT(ud.padlen == frame->data.padlen);
8156   CU_ASSERT(frame->hd.flags & NGHTTP2_FLAG_PADDED);
8157 
8158   /* Check reception of this DATA frame */
8159   check_session_recv_data_with_padding(&session->aob.framebufs, datalen, mem);
8160 
8161   nghttp2_session_del(session);
8162 }
8163 
test_nghttp2_session_pack_headers_with_padding(void)8164 void test_nghttp2_session_pack_headers_with_padding(void) {
8165   nghttp2_session *session, *sv_session;
8166   accumulator acc;
8167   my_user_data ud;
8168   nghttp2_session_callbacks callbacks;
8169 
8170   memset(&callbacks, 0, sizeof(callbacks));
8171   callbacks.send_callback = accumulator_send_callback;
8172   callbacks.on_frame_send_callback = on_frame_send_callback;
8173   callbacks.select_padding_callback = select_padding_callback;
8174   callbacks.on_frame_recv_callback = on_frame_recv_callback;
8175 
8176   acc.length = 0;
8177   ud.acc = &acc;
8178 
8179   nghttp2_session_client_new(&session, &callbacks, &ud);
8180   nghttp2_session_server_new(&sv_session, &callbacks, &ud);
8181 
8182   ud.padlen = 163;
8183 
8184   CU_ASSERT(1 == nghttp2_submit_request(session, NULL, reqnv, ARRLEN(reqnv),
8185                                         NULL, NULL));
8186   CU_ASSERT(0 == nghttp2_session_send(session));
8187 
8188   CU_ASSERT(acc.length < NGHTTP2_MAX_PAYLOADLEN);
8189   ud.frame_recv_cb_called = 0;
8190   CU_ASSERT((ssize_t)acc.length ==
8191             nghttp2_session_mem_recv(sv_session, acc.buf, acc.length));
8192   CU_ASSERT(1 == ud.frame_recv_cb_called);
8193   CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(sv_session));
8194 
8195   nghttp2_session_del(sv_session);
8196   nghttp2_session_del(session);
8197 }
8198 
test_nghttp2_pack_settings_payload(void)8199 void test_nghttp2_pack_settings_payload(void) {
8200   nghttp2_settings_entry iv[2];
8201   uint8_t buf[64];
8202   ssize_t len;
8203   nghttp2_settings_entry *resiv;
8204   size_t resniv;
8205   nghttp2_mem *mem;
8206 
8207   mem = nghttp2_mem_default();
8208 
8209   iv[0].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
8210   iv[0].value = 1023;
8211   iv[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
8212   iv[1].value = 4095;
8213 
8214   len = nghttp2_pack_settings_payload(buf, sizeof(buf), iv, 2);
8215   CU_ASSERT(2 * NGHTTP2_FRAME_SETTINGS_ENTRY_LENGTH == len);
8216   CU_ASSERT(0 == nghttp2_frame_unpack_settings_payload2(&resiv, &resniv, buf,
8217                                                         (size_t)len, mem));
8218   CU_ASSERT(2 == resniv);
8219   CU_ASSERT(NGHTTP2_SETTINGS_HEADER_TABLE_SIZE == resiv[0].settings_id);
8220   CU_ASSERT(1023 == resiv[0].value);
8221   CU_ASSERT(NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE == resiv[1].settings_id);
8222   CU_ASSERT(4095 == resiv[1].value);
8223 
8224   mem->free(resiv, NULL);
8225 
8226   len = nghttp2_pack_settings_payload(buf, 9 /* too small */, iv, 2);
8227   CU_ASSERT(NGHTTP2_ERR_INSUFF_BUFSIZE == len);
8228 }
8229 
8230 #define check_stream_dep_sib(STREAM, DEP_PREV, DEP_NEXT, SIB_PREV, SIB_NEXT)   \
8231   do {                                                                         \
8232     CU_ASSERT(DEP_PREV == STREAM->dep_prev);                                   \
8233     CU_ASSERT(DEP_NEXT == STREAM->dep_next);                                   \
8234     CU_ASSERT(SIB_PREV == STREAM->sib_prev);                                   \
8235     CU_ASSERT(SIB_NEXT == STREAM->sib_next);                                   \
8236   } while (0)
8237 
8238 /* nghttp2_stream_dep_add() and its families functions should be
8239    tested in nghttp2_stream_test.c, but it is easier to use
8240    nghttp2_session_open_stream().  Therefore, we test them here. */
test_nghttp2_session_stream_dep_add(void)8241 void test_nghttp2_session_stream_dep_add(void) {
8242   nghttp2_session *session;
8243   nghttp2_session_callbacks callbacks;
8244   nghttp2_stream *a, *b, *c, *d, *e, *root;
8245 
8246   memset(&callbacks, 0, sizeof(callbacks));
8247 
8248   nghttp2_session_server_new(&session, &callbacks, NULL);
8249 
8250   root = &session->root;
8251 
8252   a = open_stream(session, 1);
8253 
8254   c = open_stream_with_dep(session, 5, a);
8255   b = open_stream_with_dep(session, 3, a);
8256   d = open_stream_with_dep(session, 7, c);
8257 
8258   /* a
8259    * |
8260    * b--c
8261    *    |
8262    *    d
8263    */
8264 
8265   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 2 == a->sum_dep_weight);
8266   CU_ASSERT(0 == b->sum_dep_weight);
8267   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == c->sum_dep_weight);
8268   CU_ASSERT(0 == d->sum_dep_weight);
8269 
8270   check_stream_dep_sib(a, root, b, NULL, NULL);
8271   check_stream_dep_sib(b, a, NULL, NULL, c);
8272   check_stream_dep_sib(c, a, d, b, NULL);
8273   check_stream_dep_sib(d, c, NULL, NULL, NULL);
8274 
8275   CU_ASSERT(a == session->root.dep_next);
8276 
8277   e = open_stream_with_dep_excl(session, 9, a);
8278 
8279   /* a
8280    * |
8281    * e
8282    * |
8283    * b--c
8284    *    |
8285    *    d
8286    */
8287 
8288   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == a->sum_dep_weight);
8289   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 2 == e->sum_dep_weight);
8290   CU_ASSERT(0 == b->sum_dep_weight);
8291   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == c->sum_dep_weight);
8292   CU_ASSERT(0 == d->sum_dep_weight);
8293 
8294   check_stream_dep_sib(a, root, e, NULL, NULL);
8295   check_stream_dep_sib(e, a, b, NULL, NULL);
8296   check_stream_dep_sib(b, e, NULL, NULL, c);
8297   check_stream_dep_sib(c, e, d, b, NULL);
8298   check_stream_dep_sib(d, c, NULL, NULL, NULL);
8299 
8300   CU_ASSERT(a == session->root.dep_next);
8301 
8302   nghttp2_session_del(session);
8303 }
8304 
test_nghttp2_session_stream_dep_remove(void)8305 void test_nghttp2_session_stream_dep_remove(void) {
8306   nghttp2_session *session;
8307   nghttp2_session_callbacks callbacks;
8308   nghttp2_stream *a, *b, *c, *d, *e, *f, *root;
8309 
8310   memset(&callbacks, 0, sizeof(callbacks));
8311 
8312   /* Remove root */
8313   nghttp2_session_server_new(&session, &callbacks, NULL);
8314 
8315   root = &session->root;
8316 
8317   a = open_stream(session, 1);
8318   b = open_stream_with_dep(session, 3, a);
8319   c = open_stream_with_dep(session, 5, a);
8320   d = open_stream_with_dep(session, 7, c);
8321 
8322   /* a
8323    * |
8324    * c--b
8325    * |
8326    * d
8327    */
8328 
8329   nghttp2_stream_dep_remove(a);
8330 
8331   /* becomes:
8332    * c    b
8333    * |
8334    * d
8335    */
8336 
8337   CU_ASSERT(0 == a->sum_dep_weight);
8338   CU_ASSERT(0 == b->sum_dep_weight);
8339   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == c->sum_dep_weight);
8340   CU_ASSERT(0 == d->sum_dep_weight);
8341 
8342   check_stream_dep_sib(a, NULL, NULL, NULL, NULL);
8343   check_stream_dep_sib(b, root, NULL, c, NULL);
8344   check_stream_dep_sib(c, root, d, NULL, b);
8345   check_stream_dep_sib(d, c, NULL, NULL, NULL);
8346 
8347   CU_ASSERT(c == session->root.dep_next);
8348 
8349   nghttp2_session_del(session);
8350 
8351   /* Remove right most stream */
8352   nghttp2_session_server_new(&session, &callbacks, NULL);
8353 
8354   root = &session->root;
8355 
8356   a = open_stream(session, 1);
8357   b = open_stream_with_dep(session, 3, a);
8358   c = open_stream_with_dep(session, 5, a);
8359   d = open_stream_with_dep(session, 7, c);
8360 
8361   /* a
8362    * |
8363    * c--b
8364    * |
8365    * d
8366    */
8367 
8368   nghttp2_stream_dep_remove(b);
8369 
8370   /* becomes:
8371    * a
8372    * |
8373    * c
8374    * |
8375    * d
8376    */
8377 
8378   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == a->sum_dep_weight);
8379   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == c->sum_dep_weight);
8380   CU_ASSERT(0 == d->sum_dep_weight);
8381   CU_ASSERT(0 == b->sum_dep_weight);
8382 
8383   check_stream_dep_sib(a, root, c, NULL, NULL);
8384   check_stream_dep_sib(b, NULL, NULL, NULL, NULL);
8385   check_stream_dep_sib(c, a, d, NULL, NULL);
8386   check_stream_dep_sib(d, c, NULL, NULL, NULL);
8387 
8388   CU_ASSERT(a == session->root.dep_next);
8389 
8390   nghttp2_session_del(session);
8391 
8392   /* Remove left most stream */
8393   nghttp2_session_server_new(&session, &callbacks, NULL);
8394 
8395   root = &session->root;
8396 
8397   a = open_stream(session, 1);
8398   b = open_stream_with_dep(session, 3, a);
8399   c = open_stream_with_dep(session, 5, a);
8400   d = open_stream_with_dep(session, 7, c);
8401   e = open_stream_with_dep(session, 9, c);
8402 
8403   /* a
8404    * |
8405    * c--b
8406    * |
8407    * e--d
8408    */
8409 
8410   nghttp2_stream_dep_remove(c);
8411 
8412   /* becomes:
8413    * a
8414    * |
8415    * e--d--b
8416    */
8417 
8418   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 2 == a->sum_dep_weight);
8419   CU_ASSERT(0 == b->sum_dep_weight);
8420   CU_ASSERT(0 == d->sum_dep_weight);
8421   CU_ASSERT(0 == c->sum_dep_weight);
8422   CU_ASSERT(0 == e->sum_dep_weight);
8423 
8424   check_stream_dep_sib(a, root, e, NULL, NULL);
8425   check_stream_dep_sib(b, a, NULL, d, NULL);
8426   check_stream_dep_sib(c, NULL, NULL, NULL, NULL);
8427   check_stream_dep_sib(d, a, NULL, e, b);
8428   check_stream_dep_sib(e, a, NULL, NULL, d);
8429 
8430   nghttp2_session_del(session);
8431 
8432   /* Remove middle stream */
8433   nghttp2_session_server_new(&session, &callbacks, NULL);
8434 
8435   root = &session->root;
8436 
8437   a = open_stream(session, 1);
8438   b = open_stream_with_dep(session, 3, a);
8439   c = open_stream_with_dep(session, 5, a);
8440   d = open_stream_with_dep(session, 7, a);
8441   e = open_stream_with_dep(session, 9, c);
8442   f = open_stream_with_dep(session, 11, c);
8443 
8444   /* a
8445    * |
8446    * d--c--b
8447    *    |
8448    *    f--e
8449    */
8450 
8451   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 3 == a->sum_dep_weight);
8452   CU_ASSERT(0 == b->sum_dep_weight);
8453   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 2 == c->sum_dep_weight);
8454   CU_ASSERT(0 == d->sum_dep_weight);
8455   CU_ASSERT(0 == e->sum_dep_weight);
8456   CU_ASSERT(0 == f->sum_dep_weight);
8457 
8458   nghttp2_stream_dep_remove(c);
8459 
8460   /* becomes:
8461    * a
8462    * |
8463    * d--f--e--b
8464    */
8465 
8466   /* c's weight 16 is distributed evenly to e and f.  Each weight of e
8467      and f becomes 8. */
8468   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 2 + 8 * 2 == a->sum_dep_weight);
8469   CU_ASSERT(0 == b->sum_dep_weight);
8470   CU_ASSERT(0 == c->sum_dep_weight);
8471   CU_ASSERT(0 == d->sum_dep_weight);
8472   CU_ASSERT(0 == e->sum_dep_weight);
8473   CU_ASSERT(0 == f->sum_dep_weight);
8474 
8475   check_stream_dep_sib(a, root, d, NULL, NULL);
8476   check_stream_dep_sib(b, a, NULL, e, NULL);
8477   check_stream_dep_sib(c, NULL, NULL, NULL, NULL);
8478   check_stream_dep_sib(e, a, NULL, f, b);
8479   check_stream_dep_sib(f, a, NULL, d, e);
8480   check_stream_dep_sib(d, a, NULL, NULL, f);
8481 
8482   nghttp2_session_del(session);
8483 }
8484 
test_nghttp2_session_stream_dep_add_subtree(void)8485 void test_nghttp2_session_stream_dep_add_subtree(void) {
8486   nghttp2_session *session;
8487   nghttp2_session_callbacks callbacks;
8488   nghttp2_stream *a, *b, *c, *d, *e, *f, *root;
8489 
8490   memset(&callbacks, 0, sizeof(callbacks));
8491 
8492   /* dep_stream has dep_next */
8493   nghttp2_session_server_new(&session, &callbacks, NULL);
8494 
8495   root = &session->root;
8496 
8497   a = open_stream(session, 1);
8498   b = open_stream_with_dep(session, 3, a);
8499   c = open_stream_with_dep(session, 5, a);
8500   d = open_stream_with_dep(session, 7, c);
8501 
8502   e = open_stream(session, 9);
8503   f = open_stream_with_dep(session, 11, e);
8504 
8505   /* a         e
8506    * |         |
8507    * c--b      f
8508    * |
8509    * d
8510    */
8511 
8512   nghttp2_stream_dep_remove_subtree(e);
8513   nghttp2_stream_dep_add_subtree(a, e);
8514 
8515   /* becomes
8516    * a
8517    * |
8518    * e--c--b
8519    * |  |
8520    * f  d
8521    */
8522 
8523   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 3 == a->sum_dep_weight);
8524   CU_ASSERT(0 == b->sum_dep_weight);
8525   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == c->sum_dep_weight);
8526   CU_ASSERT(0 == d->sum_dep_weight);
8527   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == e->sum_dep_weight);
8528   CU_ASSERT(0 == f->sum_dep_weight);
8529 
8530   check_stream_dep_sib(a, root, e, NULL, NULL);
8531   check_stream_dep_sib(b, a, NULL, c, NULL);
8532   check_stream_dep_sib(c, a, d, e, b);
8533   check_stream_dep_sib(d, c, NULL, NULL, NULL);
8534   check_stream_dep_sib(e, a, f, NULL, c);
8535   check_stream_dep_sib(f, e, NULL, NULL, NULL);
8536 
8537   nghttp2_session_del(session);
8538 
8539   /* dep_stream has dep_next and now we insert subtree */
8540   nghttp2_session_server_new(&session, &callbacks, NULL);
8541 
8542   root = &session->root;
8543 
8544   a = open_stream(session, 1);
8545   b = open_stream_with_dep(session, 3, a);
8546   c = open_stream_with_dep(session, 5, a);
8547   d = open_stream_with_dep(session, 7, c);
8548 
8549   e = open_stream(session, 9);
8550   f = open_stream_with_dep(session, 11, e);
8551 
8552   /* a         e
8553    * |         |
8554    * c--b      f
8555    * |
8556    * d
8557    */
8558 
8559   nghttp2_stream_dep_remove_subtree(e);
8560   nghttp2_stream_dep_insert_subtree(a, e);
8561 
8562   /* becomes
8563    * a
8564    * |
8565    * e
8566    * |
8567    * f--c--b
8568    *    |
8569    *    d
8570    */
8571 
8572   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == a->sum_dep_weight);
8573   CU_ASSERT(0 == b->sum_dep_weight);
8574   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == c->sum_dep_weight);
8575   CU_ASSERT(0 == d->sum_dep_weight);
8576   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 3 == e->sum_dep_weight);
8577   CU_ASSERT(0 == f->sum_dep_weight);
8578 
8579   check_stream_dep_sib(a, root, e, NULL, NULL);
8580   check_stream_dep_sib(e, a, f, NULL, NULL);
8581   check_stream_dep_sib(f, e, NULL, NULL, c);
8582   check_stream_dep_sib(b, e, NULL, c, NULL);
8583   check_stream_dep_sib(c, e, d, f, b);
8584   check_stream_dep_sib(d, c, NULL, NULL, NULL);
8585 
8586   nghttp2_session_del(session);
8587 }
8588 
test_nghttp2_session_stream_dep_remove_subtree(void)8589 void test_nghttp2_session_stream_dep_remove_subtree(void) {
8590   nghttp2_session *session;
8591   nghttp2_session_callbacks callbacks;
8592   nghttp2_stream *a, *b, *c, *d, *e, *root;
8593 
8594   memset(&callbacks, 0, sizeof(callbacks));
8595 
8596   /* Remove left most stream */
8597   nghttp2_session_server_new(&session, &callbacks, NULL);
8598 
8599   root = &session->root;
8600 
8601   a = open_stream(session, 1);
8602   b = open_stream_with_dep(session, 3, a);
8603   c = open_stream_with_dep(session, 5, a);
8604   d = open_stream_with_dep(session, 7, c);
8605 
8606   /* a
8607    * |
8608    * c--b
8609    * |
8610    * d
8611    */
8612 
8613   nghttp2_stream_dep_remove_subtree(c);
8614 
8615   /* becomes
8616    * a  c
8617    * |  |
8618    * b  d
8619    */
8620 
8621   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == a->sum_dep_weight);
8622   CU_ASSERT(0 == b->sum_dep_weight);
8623   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == c->sum_dep_weight);
8624   CU_ASSERT(0 == d->sum_dep_weight);
8625 
8626   check_stream_dep_sib(a, root, b, NULL, NULL);
8627   check_stream_dep_sib(b, a, NULL, NULL, NULL);
8628   check_stream_dep_sib(c, NULL, d, NULL, NULL);
8629   check_stream_dep_sib(d, c, NULL, NULL, NULL);
8630 
8631   nghttp2_session_del(session);
8632 
8633   /* Remove right most stream */
8634   nghttp2_session_server_new(&session, &callbacks, NULL);
8635 
8636   root = &session->root;
8637 
8638   a = open_stream(session, 1);
8639   b = open_stream_with_dep(session, 3, a);
8640   c = open_stream_with_dep(session, 5, a);
8641   d = open_stream_with_dep(session, 7, c);
8642 
8643   /* a
8644    * |
8645    * c--b
8646    * |
8647    * d
8648    */
8649 
8650   nghttp2_stream_dep_remove_subtree(b);
8651 
8652   /* becomes
8653    * a  b
8654    * |
8655    * c
8656    * |
8657    * d
8658    */
8659 
8660   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == a->sum_dep_weight);
8661   CU_ASSERT(0 == b->sum_dep_weight);
8662   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == c->sum_dep_weight);
8663   CU_ASSERT(0 == d->sum_dep_weight);
8664 
8665   check_stream_dep_sib(a, root, c, NULL, NULL);
8666   check_stream_dep_sib(c, a, d, NULL, NULL);
8667   check_stream_dep_sib(d, c, NULL, NULL, NULL);
8668   check_stream_dep_sib(b, NULL, NULL, NULL, NULL);
8669 
8670   nghttp2_session_del(session);
8671 
8672   /* Remove middle stream */
8673   nghttp2_session_server_new(&session, &callbacks, NULL);
8674 
8675   root = &session->root;
8676 
8677   a = open_stream(session, 1);
8678   e = open_stream_with_dep(session, 9, a);
8679   c = open_stream_with_dep(session, 5, a);
8680   b = open_stream_with_dep(session, 3, a);
8681   d = open_stream_with_dep(session, 7, c);
8682 
8683   /* a
8684    * |
8685    * b--c--e
8686    *    |
8687    *    d
8688    */
8689 
8690   nghttp2_stream_dep_remove_subtree(c);
8691 
8692   /* becomes
8693    * a     c
8694    * |     |
8695    * b--e  d
8696    */
8697 
8698   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 2 == a->sum_dep_weight);
8699   CU_ASSERT(0 == b->sum_dep_weight);
8700   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == c->sum_dep_weight);
8701   CU_ASSERT(0 == d->sum_dep_weight);
8702   CU_ASSERT(0 == e->sum_dep_weight);
8703 
8704   check_stream_dep_sib(a, root, b, NULL, NULL);
8705   check_stream_dep_sib(b, a, NULL, NULL, e);
8706   check_stream_dep_sib(e, a, NULL, b, NULL);
8707   check_stream_dep_sib(c, NULL, d, NULL, NULL);
8708   check_stream_dep_sib(d, c, NULL, NULL, NULL);
8709 
8710   nghttp2_session_del(session);
8711 }
8712 
test_nghttp2_session_stream_dep_all_your_stream_are_belong_to_us(void)8713 void test_nghttp2_session_stream_dep_all_your_stream_are_belong_to_us(void) {
8714   nghttp2_session *session;
8715   nghttp2_session_callbacks callbacks;
8716   nghttp2_stream *a, *b, *c, *d, *root;
8717   nghttp2_outbound_item *db, *dc;
8718   nghttp2_mem *mem;
8719 
8720   mem = nghttp2_mem_default();
8721 
8722   memset(&callbacks, 0, sizeof(callbacks));
8723 
8724   nghttp2_session_server_new(&session, &callbacks, NULL);
8725 
8726   root = &session->root;
8727 
8728   a = open_stream(session, 1);
8729   b = open_stream_with_dep(session, 3, a);
8730 
8731   c = open_stream(session, 5);
8732 
8733   /* a     c
8734    * |
8735    * b
8736    */
8737 
8738   nghttp2_stream_dep_remove_subtree(c);
8739   CU_ASSERT(0 == nghttp2_stream_dep_insert_subtree(&session->root, c));
8740 
8741   /*
8742    * c
8743    * |
8744    * a
8745    * |
8746    * b
8747    */
8748 
8749   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == c->sum_dep_weight);
8750   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == a->sum_dep_weight);
8751   CU_ASSERT(0 == b->sum_dep_weight);
8752 
8753   CU_ASSERT(nghttp2_pq_empty(&a->obq));
8754   CU_ASSERT(nghttp2_pq_empty(&b->obq));
8755   CU_ASSERT(nghttp2_pq_empty(&c->obq));
8756 
8757   check_stream_dep_sib(c, root, a, NULL, NULL);
8758   check_stream_dep_sib(a, c, b, NULL, NULL);
8759   check_stream_dep_sib(b, a, NULL, NULL, NULL);
8760 
8761   nghttp2_session_del(session);
8762 
8763   nghttp2_session_server_new(&session, &callbacks, NULL);
8764 
8765   root = &session->root;
8766 
8767   a = open_stream(session, 1);
8768   b = open_stream(session, 3);
8769   c = open_stream(session, 5);
8770 
8771   /*
8772    * a  b   c
8773    */
8774 
8775   nghttp2_stream_dep_remove_subtree(c);
8776   CU_ASSERT(0 == nghttp2_stream_dep_insert_subtree(&session->root, c));
8777 
8778   /*
8779    * c
8780    * |
8781    * b--a
8782    */
8783 
8784   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 2 == c->sum_dep_weight);
8785   CU_ASSERT(0 == b->sum_dep_weight);
8786   CU_ASSERT(0 == a->sum_dep_weight);
8787 
8788   CU_ASSERT(nghttp2_pq_empty(&a->obq));
8789   CU_ASSERT(nghttp2_pq_empty(&b->obq));
8790   CU_ASSERT(nghttp2_pq_empty(&c->obq));
8791 
8792   check_stream_dep_sib(c, root, b, NULL, NULL);
8793   check_stream_dep_sib(b, c, NULL, NULL, a);
8794   check_stream_dep_sib(a, c, NULL, b, NULL);
8795 
8796   nghttp2_session_del(session);
8797 
8798   nghttp2_session_server_new(&session, &callbacks, NULL);
8799 
8800   root = &session->root;
8801 
8802   a = open_stream(session, 1);
8803   b = open_stream_with_dep(session, 3, a);
8804 
8805   c = open_stream(session, 5);
8806   d = open_stream_with_dep(session, 7, c);
8807 
8808   /* a     c
8809    * |     |
8810    * b     d
8811    */
8812 
8813   nghttp2_stream_dep_remove_subtree(c);
8814   CU_ASSERT(0 == nghttp2_stream_dep_insert_subtree(&session->root, c));
8815 
8816   /*
8817    * c
8818    * |
8819    * d--a
8820    *    |
8821    *    b
8822    */
8823 
8824   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 2 == c->sum_dep_weight);
8825   CU_ASSERT(0 == d->sum_dep_weight);
8826   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == a->sum_dep_weight);
8827   CU_ASSERT(0 == b->sum_dep_weight);
8828 
8829   CU_ASSERT(nghttp2_pq_empty(&a->obq));
8830   CU_ASSERT(nghttp2_pq_empty(&b->obq));
8831   CU_ASSERT(nghttp2_pq_empty(&c->obq));
8832   CU_ASSERT(nghttp2_pq_empty(&d->obq));
8833 
8834   check_stream_dep_sib(c, root, d, NULL, NULL);
8835   check_stream_dep_sib(d, c, NULL, NULL, a);
8836   check_stream_dep_sib(a, c, b, d, NULL);
8837   check_stream_dep_sib(b, a, NULL, NULL, NULL);
8838 
8839   nghttp2_session_del(session);
8840 
8841   nghttp2_session_server_new(&session, &callbacks, NULL);
8842 
8843   root = &session->root;
8844 
8845   a = open_stream(session, 1);
8846   b = open_stream_with_dep(session, 3, a);
8847 
8848   c = open_stream(session, 5);
8849   d = open_stream_with_dep(session, 7, c);
8850 
8851   /* a     c
8852    * |     |
8853    * b     d
8854    */
8855 
8856   db = create_data_ob_item(mem);
8857 
8858   nghttp2_stream_attach_item(b, db);
8859 
8860   nghttp2_stream_dep_remove_subtree(c);
8861   CU_ASSERT(0 == nghttp2_stream_dep_insert_subtree(&session->root, c));
8862 
8863   /*
8864    * c
8865    * |
8866    * d--a
8867    *    |
8868    *    b
8869    */
8870 
8871   CU_ASSERT(c->queued);
8872   CU_ASSERT(a->queued);
8873   CU_ASSERT(b->queued);
8874   CU_ASSERT(!d->queued);
8875 
8876   CU_ASSERT(1 == nghttp2_pq_size(&a->obq));
8877   CU_ASSERT(1 == nghttp2_pq_size(&c->obq));
8878   CU_ASSERT(nghttp2_pq_empty(&d->obq));
8879 
8880   check_stream_dep_sib(c, root, d, NULL, NULL);
8881   check_stream_dep_sib(d, c, NULL, NULL, a);
8882   check_stream_dep_sib(a, c, b, d, NULL);
8883   check_stream_dep_sib(b, a, NULL, NULL, NULL);
8884 
8885   nghttp2_session_del(session);
8886 
8887   nghttp2_session_server_new(&session, &callbacks, NULL);
8888 
8889   root = &session->root;
8890 
8891   a = open_stream(session, 1);
8892   b = open_stream_with_dep(session, 3, a);
8893 
8894   c = open_stream(session, 5);
8895   d = open_stream_with_dep(session, 7, c);
8896 
8897   /* a     c
8898    * |     |
8899    * b     d
8900    */
8901 
8902   db = create_data_ob_item(mem);
8903   dc = create_data_ob_item(mem);
8904 
8905   nghttp2_stream_attach_item(b, db);
8906   nghttp2_stream_attach_item(c, dc);
8907 
8908   nghttp2_stream_dep_remove_subtree(c);
8909   CU_ASSERT(0 == nghttp2_stream_dep_insert_subtree(&session->root, c));
8910 
8911   /*
8912    * c
8913    * |
8914    * d--a
8915    *    |
8916    *    b
8917    */
8918 
8919   CU_ASSERT(c->queued);
8920   CU_ASSERT(a->queued);
8921   CU_ASSERT(b->queued);
8922   CU_ASSERT(!d->queued);
8923 
8924   check_stream_dep_sib(c, root, d, NULL, NULL);
8925   check_stream_dep_sib(d, c, NULL, NULL, a);
8926   check_stream_dep_sib(a, c, b, d, NULL);
8927   check_stream_dep_sib(b, a, NULL, NULL, NULL);
8928 
8929   nghttp2_session_del(session);
8930 }
8931 
test_nghttp2_session_stream_attach_item(void)8932 void test_nghttp2_session_stream_attach_item(void) {
8933   nghttp2_session *session;
8934   nghttp2_session_callbacks callbacks;
8935   nghttp2_stream *a, *b, *c, *d, *e;
8936   nghttp2_outbound_item *da, *db, *dc, *dd;
8937   nghttp2_mem *mem;
8938 
8939   mem = nghttp2_mem_default();
8940 
8941   memset(&callbacks, 0, sizeof(callbacks));
8942 
8943   nghttp2_session_server_new(&session, &callbacks, NULL);
8944 
8945   a = open_stream(session, 1);
8946   b = open_stream_with_dep(session, 3, a);
8947   c = open_stream_with_dep(session, 5, a);
8948   d = open_stream_with_dep(session, 7, c);
8949 
8950   /* a
8951    * |
8952    * c--b
8953    * |
8954    * d
8955    */
8956 
8957   db = create_data_ob_item(mem);
8958 
8959   nghttp2_stream_attach_item(b, db);
8960 
8961   CU_ASSERT(a->queued);
8962   CU_ASSERT(b->queued);
8963   CU_ASSERT(!c->queued);
8964   CU_ASSERT(!d->queued);
8965 
8966   CU_ASSERT(1 == nghttp2_pq_size(&a->obq));
8967 
8968   /* Attach item to c */
8969   dc = create_data_ob_item(mem);
8970 
8971   nghttp2_stream_attach_item(c, dc);
8972 
8973   CU_ASSERT(a->queued);
8974   CU_ASSERT(b->queued);
8975   CU_ASSERT(c->queued);
8976   CU_ASSERT(!d->queued);
8977 
8978   CU_ASSERT(2 == nghttp2_pq_size(&a->obq));
8979 
8980   /* Attach item to a */
8981   da = create_data_ob_item(mem);
8982 
8983   nghttp2_stream_attach_item(a, da);
8984 
8985   CU_ASSERT(a->queued);
8986   CU_ASSERT(b->queued);
8987   CU_ASSERT(c->queued);
8988   CU_ASSERT(!d->queued);
8989 
8990   CU_ASSERT(2 == nghttp2_pq_size(&a->obq));
8991 
8992   /* Detach item from a */
8993   nghttp2_stream_detach_item(a);
8994 
8995   CU_ASSERT(a->queued);
8996   CU_ASSERT(b->queued);
8997   CU_ASSERT(c->queued);
8998   CU_ASSERT(!d->queued);
8999 
9000   CU_ASSERT(2 == nghttp2_pq_size(&a->obq));
9001 
9002   /* Attach item to d */
9003   dd = create_data_ob_item(mem);
9004 
9005   nghttp2_stream_attach_item(d, dd);
9006 
9007   CU_ASSERT(a->queued);
9008   CU_ASSERT(b->queued);
9009   CU_ASSERT(c->queued);
9010   CU_ASSERT(d->queued);
9011 
9012   CU_ASSERT(2 == nghttp2_pq_size(&a->obq));
9013   CU_ASSERT(1 == nghttp2_pq_size(&c->obq));
9014 
9015   /* Detach item from c */
9016   nghttp2_stream_detach_item(c);
9017 
9018   CU_ASSERT(a->queued);
9019   CU_ASSERT(b->queued);
9020   CU_ASSERT(c->queued);
9021   CU_ASSERT(d->queued);
9022 
9023   CU_ASSERT(2 == nghttp2_pq_size(&a->obq));
9024   CU_ASSERT(1 == nghttp2_pq_size(&c->obq));
9025 
9026   /* Detach item from b */
9027   nghttp2_stream_detach_item(b);
9028 
9029   CU_ASSERT(a->queued);
9030   CU_ASSERT(!b->queued);
9031   CU_ASSERT(c->queued);
9032   CU_ASSERT(d->queued);
9033 
9034   CU_ASSERT(1 == nghttp2_pq_size(&a->obq));
9035 
9036   /* exercises insertion */
9037   e = open_stream_with_dep_excl(session, 9, a);
9038 
9039   /* a
9040    * |
9041    * e
9042    * |
9043    * c--b
9044    * |
9045    * d
9046    */
9047 
9048   CU_ASSERT(a->queued);
9049   CU_ASSERT(e->queued);
9050   CU_ASSERT(!b->queued);
9051   CU_ASSERT(c->queued);
9052   CU_ASSERT(d->queued);
9053 
9054   CU_ASSERT(1 == nghttp2_pq_size(&a->obq));
9055   CU_ASSERT(1 == nghttp2_pq_size(&e->obq));
9056   CU_ASSERT(nghttp2_pq_empty(&b->obq));
9057   CU_ASSERT(1 == nghttp2_pq_size(&c->obq));
9058   CU_ASSERT(nghttp2_pq_empty(&d->obq));
9059 
9060   /* exercises deletion */
9061   nghttp2_stream_dep_remove(e);
9062 
9063   /* a
9064    * |
9065    * c--b
9066    * |
9067    * d
9068    */
9069 
9070   CU_ASSERT(a->queued);
9071   CU_ASSERT(!b->queued);
9072   CU_ASSERT(c->queued);
9073   CU_ASSERT(d->queued);
9074 
9075   CU_ASSERT(1 == nghttp2_pq_size(&a->obq));
9076   CU_ASSERT(nghttp2_pq_empty(&b->obq));
9077   CU_ASSERT(1 == nghttp2_pq_size(&c->obq));
9078   CU_ASSERT(nghttp2_pq_empty(&d->obq));
9079 
9080   /* e's weight 16 is distributed equally among c and b, both now have
9081      weight 8 each. */
9082   CU_ASSERT(8 == b->weight);
9083   CU_ASSERT(8 == c->weight);
9084 
9085   /* da, db, dc have been detached */
9086   nghttp2_outbound_item_free(da, mem);
9087   nghttp2_outbound_item_free(db, mem);
9088   nghttp2_outbound_item_free(dc, mem);
9089   free(da);
9090   free(db);
9091   free(dc);
9092 
9093   nghttp2_session_del(session);
9094 
9095   nghttp2_session_server_new(&session, &callbacks, NULL);
9096 
9097   a = open_stream(session, 1);
9098   b = open_stream_with_dep(session, 3, a);
9099   c = open_stream_with_dep(session, 5, a);
9100   d = open_stream_with_dep(session, 7, c);
9101 
9102   /* a
9103    * |
9104    * c--b
9105    * |
9106    * d
9107    */
9108 
9109   da = create_data_ob_item(mem);
9110   db = create_data_ob_item(mem);
9111   dc = create_data_ob_item(mem);
9112 
9113   nghttp2_stream_attach_item(a, da);
9114   nghttp2_stream_attach_item(b, db);
9115   nghttp2_stream_attach_item(c, dc);
9116 
9117   CU_ASSERT(a->queued);
9118   CU_ASSERT(b->queued);
9119   CU_ASSERT(c->queued);
9120   CU_ASSERT(!d->queued);
9121 
9122   CU_ASSERT(2 == nghttp2_pq_size(&a->obq));
9123   CU_ASSERT(nghttp2_pq_empty(&b->obq));
9124   CU_ASSERT(nghttp2_pq_empty(&c->obq));
9125   CU_ASSERT(nghttp2_pq_empty(&d->obq));
9126 
9127   /* Detach item from a */
9128   nghttp2_stream_detach_item(a);
9129 
9130   CU_ASSERT(a->queued);
9131   CU_ASSERT(b->queued);
9132   CU_ASSERT(c->queued);
9133   CU_ASSERT(!d->queued);
9134 
9135   CU_ASSERT(2 == nghttp2_pq_size(&a->obq));
9136   CU_ASSERT(nghttp2_pq_empty(&b->obq));
9137   CU_ASSERT(nghttp2_pq_empty(&c->obq));
9138   CU_ASSERT(nghttp2_pq_empty(&d->obq));
9139 
9140   /* da has been detached */
9141   nghttp2_outbound_item_free(da, mem);
9142   free(da);
9143 
9144   nghttp2_session_del(session);
9145 }
9146 
test_nghttp2_session_stream_attach_item_subtree(void)9147 void test_nghttp2_session_stream_attach_item_subtree(void) {
9148   nghttp2_session *session;
9149   nghttp2_session_callbacks callbacks;
9150   nghttp2_stream *a, *b, *c, *d, *e, *f;
9151   nghttp2_outbound_item *da, *db, *dd, *de;
9152   nghttp2_mem *mem;
9153 
9154   mem = nghttp2_mem_default();
9155 
9156   memset(&callbacks, 0, sizeof(callbacks));
9157 
9158   nghttp2_session_server_new(&session, &callbacks, NULL);
9159 
9160   a = open_stream(session, 1);
9161   b = open_stream_with_dep(session, 3, a);
9162   c = open_stream_with_dep(session, 5, a);
9163   d = open_stream_with_dep(session, 7, c);
9164 
9165   e = open_stream_with_dep_weight(session, 9, 32, &session->root);
9166   f = open_stream_with_dep(session, 11, e);
9167 
9168   /*
9169    * a        e
9170    * |        |
9171    * c--b     f
9172    * |
9173    * d
9174    */
9175 
9176   de = create_data_ob_item(mem);
9177 
9178   nghttp2_stream_attach_item(e, de);
9179 
9180   db = create_data_ob_item(mem);
9181 
9182   nghttp2_stream_attach_item(b, db);
9183 
9184   CU_ASSERT(a->queued);
9185   CU_ASSERT(b->queued);
9186   CU_ASSERT(!c->queued);
9187   CU_ASSERT(!d->queued);
9188   CU_ASSERT(e->queued);
9189   CU_ASSERT(!f->queued);
9190 
9191   CU_ASSERT(1 == nghttp2_pq_size(&a->obq));
9192   CU_ASSERT(nghttp2_pq_empty(&b->obq));
9193   CU_ASSERT(nghttp2_pq_empty(&c->obq));
9194   CU_ASSERT(nghttp2_pq_empty(&d->obq));
9195   CU_ASSERT(nghttp2_pq_empty(&e->obq));
9196   CU_ASSERT(nghttp2_pq_empty(&f->obq));
9197 
9198   /* Insert subtree e under a */
9199 
9200   nghttp2_stream_dep_remove_subtree(e);
9201   nghttp2_stream_dep_insert_subtree(a, e);
9202 
9203   /*
9204    * a
9205    * |
9206    * e
9207    * |
9208    * f--c--b
9209    *    |
9210    *    d
9211    */
9212 
9213   CU_ASSERT(a->queued);
9214   CU_ASSERT(b->queued);
9215   CU_ASSERT(!c->queued);
9216   CU_ASSERT(!d->queued);
9217   CU_ASSERT(e->queued);
9218   CU_ASSERT(!f->queued);
9219 
9220   CU_ASSERT(1 == nghttp2_pq_size(&a->obq));
9221   CU_ASSERT(nghttp2_pq_empty(&b->obq));
9222   CU_ASSERT(nghttp2_pq_empty(&c->obq));
9223   CU_ASSERT(nghttp2_pq_empty(&d->obq));
9224   CU_ASSERT(1 == nghttp2_pq_size(&e->obq));
9225   CU_ASSERT(nghttp2_pq_empty(&f->obq));
9226 
9227   /* Remove subtree b */
9228 
9229   nghttp2_stream_dep_remove_subtree(b);
9230 
9231   CU_ASSERT(0 == nghttp2_stream_dep_add_subtree(&session->root, b));
9232 
9233   /*
9234    * a       b
9235    * |
9236    * e
9237    * |
9238    * f--c
9239    *    |
9240    *    d
9241    */
9242 
9243   CU_ASSERT(a->queued);
9244   CU_ASSERT(b->queued);
9245   CU_ASSERT(!c->queued);
9246   CU_ASSERT(!d->queued);
9247   CU_ASSERT(e->queued);
9248   CU_ASSERT(!f->queued);
9249 
9250   CU_ASSERT(1 == nghttp2_pq_size(&a->obq));
9251   CU_ASSERT(nghttp2_pq_empty(&b->obq));
9252   CU_ASSERT(nghttp2_pq_empty(&c->obq));
9253   CU_ASSERT(nghttp2_pq_empty(&d->obq));
9254   CU_ASSERT(nghttp2_pq_empty(&e->obq));
9255   CU_ASSERT(nghttp2_pq_empty(&f->obq));
9256 
9257   /* Remove subtree a, and add it to root again */
9258 
9259   nghttp2_stream_dep_remove_subtree(a);
9260 
9261   CU_ASSERT(0 == nghttp2_stream_dep_add_subtree(&session->root, a));
9262 
9263   CU_ASSERT(a->queued);
9264   CU_ASSERT(b->queued);
9265   CU_ASSERT(!c->queued);
9266   CU_ASSERT(!d->queued);
9267   CU_ASSERT(e->queued);
9268   CU_ASSERT(!f->queued);
9269 
9270   CU_ASSERT(1 == nghttp2_pq_size(&a->obq));
9271   CU_ASSERT(nghttp2_pq_empty(&b->obq));
9272   CU_ASSERT(nghttp2_pq_empty(&c->obq));
9273   CU_ASSERT(nghttp2_pq_empty(&d->obq));
9274   CU_ASSERT(nghttp2_pq_empty(&e->obq));
9275   CU_ASSERT(nghttp2_pq_empty(&f->obq));
9276 
9277   /* Remove subtree c */
9278 
9279   nghttp2_stream_dep_remove_subtree(c);
9280 
9281   CU_ASSERT(0 == nghttp2_stream_dep_add_subtree(&session->root, c));
9282 
9283   /*
9284    * a       b     c
9285    * |             |
9286    * e             d
9287    * |
9288    * f
9289    */
9290 
9291   CU_ASSERT(a->queued);
9292   CU_ASSERT(b->queued);
9293   CU_ASSERT(!c->queued);
9294   CU_ASSERT(!d->queued);
9295   CU_ASSERT(e->queued);
9296   CU_ASSERT(!f->queued);
9297 
9298   CU_ASSERT(1 == nghttp2_pq_size(&a->obq));
9299   CU_ASSERT(nghttp2_pq_empty(&b->obq));
9300   CU_ASSERT(nghttp2_pq_empty(&c->obq));
9301   CU_ASSERT(nghttp2_pq_empty(&d->obq));
9302   CU_ASSERT(nghttp2_pq_empty(&e->obq));
9303   CU_ASSERT(nghttp2_pq_empty(&f->obq));
9304 
9305   dd = create_data_ob_item(mem);
9306 
9307   nghttp2_stream_attach_item(d, dd);
9308 
9309   /* Add subtree c to a */
9310 
9311   nghttp2_stream_dep_remove_subtree(c);
9312   nghttp2_stream_dep_add_subtree(a, c);
9313 
9314   /*
9315    * a       b
9316    * |
9317    * c--e
9318    * |  |
9319    * d  f
9320    */
9321 
9322   CU_ASSERT(a->queued);
9323   CU_ASSERT(b->queued);
9324   CU_ASSERT(c->queued);
9325   CU_ASSERT(d->queued);
9326   CU_ASSERT(e->queued);
9327   CU_ASSERT(!f->queued);
9328 
9329   CU_ASSERT(2 == nghttp2_pq_size(&a->obq));
9330   CU_ASSERT(nghttp2_pq_empty(&b->obq));
9331   CU_ASSERT(1 == nghttp2_pq_size(&c->obq));
9332   CU_ASSERT(nghttp2_pq_empty(&d->obq));
9333   CU_ASSERT(nghttp2_pq_empty(&e->obq));
9334   CU_ASSERT(nghttp2_pq_empty(&f->obq));
9335 
9336   /* Insert b under a */
9337 
9338   nghttp2_stream_dep_remove_subtree(b);
9339   nghttp2_stream_dep_insert_subtree(a, b);
9340 
9341   /*
9342    * a
9343    * |
9344    * b
9345    * |
9346    * c--e
9347    * |  |
9348    * d  f
9349    */
9350 
9351   CU_ASSERT(a->queued);
9352   CU_ASSERT(b->queued);
9353   CU_ASSERT(c->queued);
9354   CU_ASSERT(d->queued);
9355   CU_ASSERT(e->queued);
9356   CU_ASSERT(!f->queued);
9357 
9358   CU_ASSERT(1 == nghttp2_pq_size(&a->obq));
9359   CU_ASSERT(2 == nghttp2_pq_size(&b->obq));
9360   CU_ASSERT(1 == nghttp2_pq_size(&c->obq));
9361   CU_ASSERT(nghttp2_pq_empty(&d->obq));
9362   CU_ASSERT(nghttp2_pq_empty(&e->obq));
9363   CU_ASSERT(nghttp2_pq_empty(&f->obq));
9364 
9365   /* Remove subtree b */
9366 
9367   nghttp2_stream_dep_remove_subtree(b);
9368   CU_ASSERT(0 == nghttp2_stream_dep_add_subtree(&session->root, b));
9369 
9370   /*
9371    * b       a
9372    * |
9373    * e--c
9374    * |  |
9375    * f  d
9376    */
9377 
9378   CU_ASSERT(!a->queued);
9379   CU_ASSERT(b->queued);
9380   CU_ASSERT(c->queued);
9381   CU_ASSERT(d->queued);
9382   CU_ASSERT(e->queued);
9383   CU_ASSERT(!f->queued);
9384 
9385   CU_ASSERT(nghttp2_pq_empty(&a->obq));
9386   CU_ASSERT(2 == nghttp2_pq_size(&b->obq));
9387   CU_ASSERT(1 == nghttp2_pq_size(&c->obq));
9388   CU_ASSERT(nghttp2_pq_empty(&d->obq));
9389   CU_ASSERT(nghttp2_pq_empty(&e->obq));
9390   CU_ASSERT(nghttp2_pq_empty(&f->obq));
9391 
9392   /* Remove subtree c, and detach item from b, and then re-add
9393      subtree c under b */
9394 
9395   nghttp2_stream_dep_remove_subtree(c);
9396   nghttp2_stream_detach_item(b);
9397   nghttp2_stream_dep_add_subtree(b, c);
9398 
9399   /*
9400    * b       a
9401    * |
9402    * e--c
9403    * |  |
9404    * f  d
9405    */
9406 
9407   CU_ASSERT(!a->queued);
9408   CU_ASSERT(b->queued);
9409   CU_ASSERT(c->queued);
9410   CU_ASSERT(d->queued);
9411   CU_ASSERT(e->queued);
9412   CU_ASSERT(!f->queued);
9413 
9414   CU_ASSERT(nghttp2_pq_empty(&a->obq));
9415   CU_ASSERT(2 == nghttp2_pq_size(&b->obq));
9416   CU_ASSERT(1 == nghttp2_pq_size(&c->obq));
9417   CU_ASSERT(nghttp2_pq_empty(&d->obq));
9418   CU_ASSERT(nghttp2_pq_empty(&e->obq));
9419   CU_ASSERT(nghttp2_pq_empty(&f->obq));
9420 
9421   /* Attach data to a, and add subtree a under b */
9422 
9423   da = create_data_ob_item(mem);
9424   nghttp2_stream_attach_item(a, da);
9425   nghttp2_stream_dep_remove_subtree(a);
9426   nghttp2_stream_dep_add_subtree(b, a);
9427 
9428   /*
9429    * b
9430    * |
9431    * a--e--c
9432    *    |  |
9433    *    f  d
9434    */
9435 
9436   CU_ASSERT(a->queued);
9437   CU_ASSERT(b->queued);
9438   CU_ASSERT(c->queued);
9439   CU_ASSERT(d->queued);
9440   CU_ASSERT(e->queued);
9441   CU_ASSERT(!f->queued);
9442 
9443   CU_ASSERT(nghttp2_pq_empty(&a->obq));
9444   CU_ASSERT(3 == nghttp2_pq_size(&b->obq));
9445   CU_ASSERT(1 == nghttp2_pq_size(&c->obq));
9446   CU_ASSERT(nghttp2_pq_empty(&d->obq));
9447   CU_ASSERT(nghttp2_pq_empty(&e->obq));
9448   CU_ASSERT(nghttp2_pq_empty(&f->obq));
9449 
9450   /* Remove subtree c, and add under f */
9451   nghttp2_stream_dep_remove_subtree(c);
9452   nghttp2_stream_dep_insert_subtree(f, c);
9453 
9454   /*
9455    * b
9456    * |
9457    * a--e
9458    *    |
9459    *    f
9460    *    |
9461    *    c
9462    *    |
9463    *    d
9464    */
9465 
9466   CU_ASSERT(a->queued);
9467   CU_ASSERT(b->queued);
9468   CU_ASSERT(c->queued);
9469   CU_ASSERT(d->queued);
9470   CU_ASSERT(e->queued);
9471   CU_ASSERT(f->queued);
9472 
9473   CU_ASSERT(nghttp2_pq_empty(&a->obq));
9474   CU_ASSERT(2 == nghttp2_pq_size(&b->obq));
9475   CU_ASSERT(1 == nghttp2_pq_size(&c->obq));
9476   CU_ASSERT(nghttp2_pq_empty(&d->obq));
9477   CU_ASSERT(1 == nghttp2_pq_size(&e->obq));
9478   CU_ASSERT(1 == nghttp2_pq_size(&f->obq));
9479 
9480   /* db has been detached */
9481   nghttp2_outbound_item_free(db, mem);
9482   free(db);
9483 
9484   nghttp2_session_del(session);
9485 }
9486 
test_nghttp2_session_stream_get_state(void)9487 void test_nghttp2_session_stream_get_state(void) {
9488   nghttp2_session *session;
9489   nghttp2_session_callbacks callbacks;
9490   nghttp2_mem *mem;
9491   nghttp2_hd_deflater deflater;
9492   nghttp2_bufs bufs;
9493   nghttp2_buf *buf;
9494   nghttp2_stream *stream;
9495   ssize_t rv;
9496   nghttp2_data_provider data_prd;
9497   nghttp2_frame frame;
9498 
9499   mem = nghttp2_mem_default();
9500   frame_pack_bufs_init(&bufs);
9501   memset(&data_prd, 0, sizeof(data_prd));
9502 
9503   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
9504   callbacks.send_callback = null_send_callback;
9505 
9506   nghttp2_session_server_new(&session, &callbacks, NULL);
9507   nghttp2_hd_deflate_init(&deflater, mem);
9508 
9509   CU_ASSERT(NGHTTP2_STREAM_STATE_IDLE ==
9510             nghttp2_stream_get_state(nghttp2_session_get_root_stream(session)));
9511 
9512   /* stream 1 HEADERS; without END_STREAM flag set */
9513   pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, reqnv,
9514                ARRLEN(reqnv), mem);
9515 
9516   buf = &bufs.head->buf;
9517   rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
9518 
9519   CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv);
9520 
9521   stream = nghttp2_session_find_stream(session, 1);
9522 
9523   CU_ASSERT(NULL != stream);
9524   CU_ASSERT(1 == stream->stream_id);
9525   CU_ASSERT(NGHTTP2_STREAM_STATE_OPEN == nghttp2_stream_get_state(stream));
9526 
9527   nghttp2_bufs_reset(&bufs);
9528 
9529   /* stream 3 HEADERS; with END_STREAM flag set */
9530   pack_headers(&bufs, &deflater, 3,
9531                NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM, reqnv,
9532                ARRLEN(reqnv), mem);
9533 
9534   buf = &bufs.head->buf;
9535   rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
9536 
9537   CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv);
9538 
9539   stream = nghttp2_session_find_stream(session, 3);
9540 
9541   CU_ASSERT(NULL != stream);
9542   CU_ASSERT(3 == stream->stream_id);
9543   CU_ASSERT(NGHTTP2_STREAM_STATE_HALF_CLOSED_REMOTE ==
9544             nghttp2_stream_get_state(stream));
9545 
9546   nghttp2_bufs_reset(&bufs);
9547 
9548   /* Respond to stream 1 */
9549   nghttp2_submit_response(session, 1, resnv, ARRLEN(resnv), NULL);
9550 
9551   rv = nghttp2_session_send(session);
9552 
9553   CU_ASSERT(0 == rv);
9554 
9555   stream = nghttp2_session_find_stream(session, 1);
9556 
9557   CU_ASSERT(NGHTTP2_STREAM_STATE_HALF_CLOSED_LOCAL ==
9558             nghttp2_stream_get_state(stream));
9559 
9560   /* Respond to stream 3 */
9561   nghttp2_submit_response(session, 3, resnv, ARRLEN(resnv), NULL);
9562 
9563   rv = nghttp2_session_send(session);
9564 
9565   CU_ASSERT(0 == rv);
9566 
9567   stream = nghttp2_session_find_stream(session, 3);
9568 
9569   CU_ASSERT(NGHTTP2_STREAM_STATE_CLOSED == nghttp2_stream_get_state(stream));
9570 
9571   /* stream 5 HEADERS; with END_STREAM flag set */
9572   pack_headers(&bufs, &deflater, 5,
9573                NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM, reqnv,
9574                ARRLEN(reqnv), mem);
9575 
9576   buf = &bufs.head->buf;
9577   rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
9578 
9579   CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv);
9580 
9581   nghttp2_bufs_reset(&bufs);
9582 
9583   /* Push stream 2 associated to stream 5 */
9584   rv = nghttp2_submit_push_promise(session, NGHTTP2_FLAG_NONE, 5, reqnv,
9585                                    ARRLEN(reqnv), NULL);
9586 
9587   CU_ASSERT(2 == rv);
9588 
9589   rv = nghttp2_session_send(session);
9590 
9591   CU_ASSERT(0 == rv);
9592 
9593   stream = nghttp2_session_find_stream(session, 2);
9594 
9595   CU_ASSERT(NGHTTP2_STREAM_STATE_RESERVED_LOCAL ==
9596             nghttp2_stream_get_state(stream));
9597 
9598   /* Send response to push stream 2 with END_STREAM set */
9599   nghttp2_submit_response(session, 2, resnv, ARRLEN(resnv), NULL);
9600 
9601   rv = nghttp2_session_send(session);
9602 
9603   CU_ASSERT(0 == rv);
9604 
9605   stream = nghttp2_session_find_stream(session, 2);
9606 
9607   /* At server, pushed stream object is not retained after closed */
9608   CU_ASSERT(NULL == stream);
9609 
9610   /* Push stream 4 associated to stream 5 */
9611   rv = nghttp2_submit_push_promise(session, NGHTTP2_FLAG_NONE, 5, reqnv,
9612                                    ARRLEN(reqnv), NULL);
9613 
9614   CU_ASSERT(4 == rv);
9615 
9616   rv = nghttp2_session_send(session);
9617 
9618   CU_ASSERT(0 == rv);
9619 
9620   stream = nghttp2_session_find_stream(session, 4);
9621 
9622   CU_ASSERT(NGHTTP2_STREAM_STATE_RESERVED_LOCAL ==
9623             nghttp2_stream_get_state(stream));
9624 
9625   /* Send response to push stream 4 without closing */
9626   data_prd.read_callback = defer_data_source_read_callback;
9627 
9628   nghttp2_submit_response(session, 4, resnv, ARRLEN(resnv), &data_prd);
9629 
9630   rv = nghttp2_session_send(session);
9631 
9632   CU_ASSERT(0 == rv);
9633 
9634   stream = nghttp2_session_find_stream(session, 4);
9635 
9636   CU_ASSERT(NGHTTP2_STREAM_STATE_HALF_CLOSED_REMOTE ==
9637             nghttp2_stream_get_state(stream));
9638 
9639   /* Create idle stream by PRIORITY frame */
9640   nghttp2_frame_priority_init(&frame.priority, 7, &pri_spec_default);
9641 
9642   rv = nghttp2_frame_pack_priority(&bufs, &frame.priority);
9643 
9644   CU_ASSERT(0 == rv);
9645 
9646   nghttp2_frame_priority_free(&frame.priority);
9647 
9648   buf = &bufs.head->buf;
9649   rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
9650 
9651   CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv);
9652 
9653   stream = nghttp2_session_find_stream(session, 7);
9654 
9655   CU_ASSERT(NGHTTP2_STREAM_STATE_IDLE == nghttp2_stream_get_state(stream));
9656 
9657   nghttp2_bufs_reset(&bufs);
9658 
9659   nghttp2_hd_deflate_free(&deflater);
9660   nghttp2_session_del(session);
9661 
9662   /* Test for client side */
9663 
9664   nghttp2_session_client_new(&session, &callbacks, NULL);
9665   nghttp2_hd_deflate_init(&deflater, mem);
9666 
9667   nghttp2_submit_request(session, NULL, reqnv, ARRLEN(reqnv), NULL, NULL);
9668 
9669   rv = nghttp2_session_send(session);
9670 
9671   CU_ASSERT(0 == rv);
9672 
9673   /* Receive PUSH_PROMISE 2 associated to stream 1 */
9674   pack_push_promise(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, 2, reqnv,
9675                     ARRLEN(reqnv), mem);
9676 
9677   buf = &bufs.head->buf;
9678   rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
9679 
9680   CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv);
9681 
9682   stream = nghttp2_session_find_stream(session, 2);
9683 
9684   CU_ASSERT(NGHTTP2_STREAM_STATE_RESERVED_REMOTE ==
9685             nghttp2_stream_get_state(stream));
9686 
9687   nghttp2_bufs_reset(&bufs);
9688 
9689   /* Receive push response for stream 2 without END_STREAM set */
9690   pack_headers(&bufs, &deflater, 2, NGHTTP2_FLAG_END_HEADERS, resnv,
9691                ARRLEN(resnv), mem);
9692 
9693   buf = &bufs.head->buf;
9694   rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
9695 
9696   CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv);
9697 
9698   stream = nghttp2_session_find_stream(session, 2);
9699 
9700   CU_ASSERT(NGHTTP2_STREAM_STATE_HALF_CLOSED_LOCAL ==
9701             nghttp2_stream_get_state(stream));
9702 
9703   nghttp2_bufs_reset(&bufs);
9704 
9705   nghttp2_hd_deflate_free(&deflater);
9706   nghttp2_session_del(session);
9707 
9708   nghttp2_bufs_free(&bufs);
9709 }
9710 
test_nghttp2_session_stream_get_something(void)9711 void test_nghttp2_session_stream_get_something(void) {
9712   nghttp2_session *session;
9713   nghttp2_session_callbacks callbacks;
9714   nghttp2_stream *a, *b, *c;
9715 
9716   memset(&callbacks, 0, sizeof(callbacks));
9717 
9718   nghttp2_session_server_new(&session, &callbacks, NULL);
9719 
9720   a = open_stream(session, 1);
9721 
9722   CU_ASSERT(nghttp2_session_get_root_stream(session) ==
9723             nghttp2_stream_get_parent(a));
9724   CU_ASSERT(NULL == nghttp2_stream_get_previous_sibling(a));
9725   CU_ASSERT(NULL == nghttp2_stream_get_next_sibling(a));
9726   CU_ASSERT(NULL == nghttp2_stream_get_first_child(a));
9727 
9728   b = open_stream_with_dep(session, 3, a);
9729   c = open_stream_with_dep_weight(session, 5, 11, a);
9730 
9731   CU_ASSERT(a == nghttp2_stream_get_parent(c));
9732   CU_ASSERT(a == nghttp2_stream_get_parent(b));
9733 
9734   CU_ASSERT(c == nghttp2_stream_get_first_child(a));
9735 
9736   CU_ASSERT(b == nghttp2_stream_get_next_sibling(c));
9737   CU_ASSERT(c == nghttp2_stream_get_previous_sibling(b));
9738 
9739   CU_ASSERT(27 == nghttp2_stream_get_sum_dependency_weight(a));
9740 
9741   CU_ASSERT(11 == nghttp2_stream_get_weight(c));
9742   CU_ASSERT(5 == nghttp2_stream_get_stream_id(c));
9743   CU_ASSERT(0 == nghttp2_stream_get_stream_id(&session->root));
9744 
9745   nghttp2_session_del(session);
9746 }
9747 
test_nghttp2_session_find_stream(void)9748 void test_nghttp2_session_find_stream(void) {
9749   nghttp2_session *session;
9750   nghttp2_session_callbacks callbacks;
9751   nghttp2_stream *stream;
9752 
9753   memset(&callbacks, 0, sizeof(callbacks));
9754 
9755   nghttp2_session_server_new(&session, &callbacks, NULL);
9756 
9757   open_recv_stream(session, 1);
9758 
9759   stream = nghttp2_session_find_stream(session, 1);
9760 
9761   CU_ASSERT(NULL != stream);
9762   CU_ASSERT(1 == stream->stream_id);
9763 
9764   stream = nghttp2_session_find_stream(session, 0);
9765 
9766   CU_ASSERT(&session->root == stream);
9767   CU_ASSERT(0 == stream->stream_id);
9768 
9769   stream = nghttp2_session_find_stream(session, 2);
9770 
9771   CU_ASSERT(NULL == stream);
9772 
9773   nghttp2_session_del(session);
9774 }
9775 
test_nghttp2_session_keep_closed_stream(void)9776 void test_nghttp2_session_keep_closed_stream(void) {
9777   nghttp2_session *session;
9778   nghttp2_session_callbacks callbacks;
9779   const size_t max_concurrent_streams = 5;
9780   nghttp2_settings_entry iv = {NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS,
9781                                (uint32_t)max_concurrent_streams};
9782   size_t i;
9783 
9784   memset(&callbacks, 0, sizeof(callbacks));
9785   callbacks.send_callback = null_send_callback;
9786 
9787   nghttp2_session_server_new(&session, &callbacks, NULL);
9788 
9789   nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, &iv, 1);
9790 
9791   for (i = 0; i < max_concurrent_streams; ++i) {
9792     open_recv_stream(session, (int32_t)i * 2 + 1);
9793   }
9794 
9795   CU_ASSERT(0 == session->num_closed_streams);
9796 
9797   nghttp2_session_close_stream(session, 1, NGHTTP2_NO_ERROR);
9798 
9799   CU_ASSERT(1 == session->num_closed_streams);
9800   CU_ASSERT(1 == session->closed_stream_tail->stream_id);
9801   CU_ASSERT(session->closed_stream_tail == session->closed_stream_head);
9802 
9803   nghttp2_session_close_stream(session, 5, NGHTTP2_NO_ERROR);
9804 
9805   CU_ASSERT(2 == session->num_closed_streams);
9806   CU_ASSERT(5 == session->closed_stream_tail->stream_id);
9807   CU_ASSERT(1 == session->closed_stream_head->stream_id);
9808   CU_ASSERT(session->closed_stream_head ==
9809             session->closed_stream_tail->closed_prev);
9810   CU_ASSERT(NULL == session->closed_stream_tail->closed_next);
9811   CU_ASSERT(session->closed_stream_tail ==
9812             session->closed_stream_head->closed_next);
9813   CU_ASSERT(NULL == session->closed_stream_head->closed_prev);
9814 
9815   open_recv_stream(session, 11);
9816   nghttp2_session_adjust_closed_stream(session);
9817 
9818   CU_ASSERT(1 == session->num_closed_streams);
9819   CU_ASSERT(5 == session->closed_stream_tail->stream_id);
9820   CU_ASSERT(session->closed_stream_tail == session->closed_stream_head);
9821   CU_ASSERT(NULL == session->closed_stream_head->closed_prev);
9822   CU_ASSERT(NULL == session->closed_stream_head->closed_next);
9823 
9824   open_recv_stream(session, 13);
9825   nghttp2_session_adjust_closed_stream(session);
9826 
9827   CU_ASSERT(0 == session->num_closed_streams);
9828   CU_ASSERT(NULL == session->closed_stream_tail);
9829   CU_ASSERT(NULL == session->closed_stream_head);
9830 
9831   nghttp2_session_close_stream(session, 3, NGHTTP2_NO_ERROR);
9832 
9833   CU_ASSERT(1 == session->num_closed_streams);
9834   CU_ASSERT(3 == session->closed_stream_head->stream_id);
9835 
9836   /* server initiated stream is not counted to max concurrent limit */
9837   open_sent_stream(session, 2);
9838   nghttp2_session_adjust_closed_stream(session);
9839 
9840   CU_ASSERT(1 == session->num_closed_streams);
9841   CU_ASSERT(3 == session->closed_stream_head->stream_id);
9842 
9843   nghttp2_session_close_stream(session, 2, NGHTTP2_NO_ERROR);
9844 
9845   CU_ASSERT(1 == session->num_closed_streams);
9846   CU_ASSERT(3 == session->closed_stream_head->stream_id);
9847 
9848   nghttp2_session_del(session);
9849 }
9850 
test_nghttp2_session_keep_idle_stream(void)9851 void test_nghttp2_session_keep_idle_stream(void) {
9852   nghttp2_session *session;
9853   nghttp2_session_callbacks callbacks;
9854   const size_t max_concurrent_streams = 1;
9855   nghttp2_settings_entry iv = {NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS,
9856                                (uint32_t)max_concurrent_streams};
9857   int i;
9858   int32_t stream_id;
9859 
9860   memset(&callbacks, 0, sizeof(callbacks));
9861   callbacks.send_callback = null_send_callback;
9862 
9863   nghttp2_session_server_new(&session, &callbacks, NULL);
9864 
9865   nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, &iv, 1);
9866 
9867   /* We at least allow NGHTTP2_MIN_IDLE_STREAM idle streams even if
9868      max concurrent streams is very low. */
9869   for (i = 0; i < NGHTTP2_MIN_IDLE_STREAMS; ++i) {
9870     open_recv_stream2(session, i * 2 + 1, NGHTTP2_STREAM_IDLE);
9871     nghttp2_session_adjust_idle_stream(session);
9872   }
9873 
9874   CU_ASSERT(NGHTTP2_MIN_IDLE_STREAMS == session->num_idle_streams);
9875 
9876   stream_id = (NGHTTP2_MIN_IDLE_STREAMS - 1) * 2 + 1;
9877   CU_ASSERT(1 == session->idle_stream_head->stream_id);
9878   CU_ASSERT(stream_id == session->idle_stream_tail->stream_id);
9879 
9880   stream_id += 2;
9881 
9882   open_recv_stream2(session, stream_id, NGHTTP2_STREAM_IDLE);
9883   nghttp2_session_adjust_idle_stream(session);
9884 
9885   CU_ASSERT(NGHTTP2_MIN_IDLE_STREAMS == session->num_idle_streams);
9886   CU_ASSERT(3 == session->idle_stream_head->stream_id);
9887   CU_ASSERT(stream_id == session->idle_stream_tail->stream_id);
9888 
9889   nghttp2_session_del(session);
9890 }
9891 
test_nghttp2_session_detach_idle_stream(void)9892 void test_nghttp2_session_detach_idle_stream(void) {
9893   nghttp2_session *session;
9894   nghttp2_session_callbacks callbacks;
9895   int i;
9896   nghttp2_stream *stream;
9897 
9898   memset(&callbacks, 0, sizeof(callbacks));
9899   callbacks.send_callback = null_send_callback;
9900 
9901   nghttp2_session_server_new(&session, &callbacks, NULL);
9902 
9903   for (i = 1; i <= 3; ++i) {
9904     nghttp2_session_open_stream(session, i, NGHTTP2_STREAM_FLAG_NONE,
9905                                 &pri_spec_default, NGHTTP2_STREAM_IDLE, NULL);
9906   }
9907 
9908   CU_ASSERT(3 == session->num_idle_streams);
9909 
9910   /* Detach middle stream */
9911   stream = nghttp2_session_get_stream_raw(session, 2);
9912 
9913   CU_ASSERT(session->idle_stream_head == stream->closed_prev);
9914   CU_ASSERT(session->idle_stream_tail == stream->closed_next);
9915   CU_ASSERT(stream == session->idle_stream_head->closed_next);
9916   CU_ASSERT(stream == session->idle_stream_tail->closed_prev);
9917 
9918   nghttp2_session_detach_idle_stream(session, stream);
9919 
9920   CU_ASSERT(2 == session->num_idle_streams);
9921 
9922   CU_ASSERT(NULL == stream->closed_prev);
9923   CU_ASSERT(NULL == stream->closed_next);
9924 
9925   CU_ASSERT(session->idle_stream_head ==
9926             session->idle_stream_tail->closed_prev);
9927   CU_ASSERT(session->idle_stream_tail ==
9928             session->idle_stream_head->closed_next);
9929 
9930   /* Detach head stream */
9931   stream = session->idle_stream_head;
9932 
9933   nghttp2_session_detach_idle_stream(session, stream);
9934 
9935   CU_ASSERT(1 == session->num_idle_streams);
9936 
9937   CU_ASSERT(session->idle_stream_head == session->idle_stream_tail);
9938   CU_ASSERT(NULL == session->idle_stream_head->closed_prev);
9939   CU_ASSERT(NULL == session->idle_stream_head->closed_next);
9940 
9941   /* Detach last stream */
9942 
9943   stream = session->idle_stream_head;
9944 
9945   nghttp2_session_detach_idle_stream(session, stream);
9946 
9947   CU_ASSERT(0 == session->num_idle_streams);
9948 
9949   CU_ASSERT(NULL == session->idle_stream_head);
9950   CU_ASSERT(NULL == session->idle_stream_tail);
9951 
9952   for (i = 4; i <= 5; ++i) {
9953     nghttp2_session_open_stream(session, i, NGHTTP2_STREAM_FLAG_NONE,
9954                                 &pri_spec_default, NGHTTP2_STREAM_IDLE, NULL);
9955   }
9956 
9957   CU_ASSERT(2 == session->num_idle_streams);
9958 
9959   /* Detach tail stream */
9960 
9961   stream = session->idle_stream_tail;
9962 
9963   nghttp2_session_detach_idle_stream(session, stream);
9964 
9965   CU_ASSERT(1 == session->num_idle_streams);
9966 
9967   CU_ASSERT(session->idle_stream_head == session->idle_stream_tail);
9968   CU_ASSERT(NULL == session->idle_stream_head->closed_prev);
9969   CU_ASSERT(NULL == session->idle_stream_head->closed_next);
9970 
9971   nghttp2_session_del(session);
9972 }
9973 
test_nghttp2_session_large_dep_tree(void)9974 void test_nghttp2_session_large_dep_tree(void) {
9975   nghttp2_session *session;
9976   nghttp2_session_callbacks callbacks;
9977   size_t i;
9978   nghttp2_stream *dep_stream = NULL;
9979   nghttp2_stream *stream;
9980   int32_t stream_id;
9981 
9982   memset(&callbacks, 0, sizeof(callbacks));
9983   callbacks.send_callback = null_send_callback;
9984 
9985   nghttp2_session_server_new(&session, &callbacks, NULL);
9986 
9987   stream_id = 1;
9988   for (i = 0; i < 250; ++i, stream_id += 2) {
9989     dep_stream = open_stream_with_dep(session, stream_id, dep_stream);
9990   }
9991 
9992   stream_id = 1;
9993   for (i = 0; i < 250; ++i, stream_id += 2) {
9994     stream = nghttp2_session_get_stream(session, stream_id);
9995     CU_ASSERT(nghttp2_stream_dep_find_ancestor(stream, &session->root));
9996     CU_ASSERT(nghttp2_stream_in_dep_tree(stream));
9997   }
9998 
9999   nghttp2_session_del(session);
10000 }
10001 
test_nghttp2_session_graceful_shutdown(void)10002 void test_nghttp2_session_graceful_shutdown(void) {
10003   nghttp2_session *session;
10004   nghttp2_session_callbacks callbacks;
10005   my_user_data ud;
10006 
10007   memset(&callbacks, 0, sizeof(callbacks));
10008   callbacks.send_callback = null_send_callback;
10009   callbacks.on_frame_send_callback = on_frame_send_callback;
10010   callbacks.on_stream_close_callback = on_stream_close_callback;
10011 
10012   nghttp2_session_server_new(&session, &callbacks, &ud);
10013 
10014   open_recv_stream(session, 301);
10015   open_sent_stream(session, 302);
10016   open_recv_stream(session, 309);
10017   open_recv_stream(session, 311);
10018   open_recv_stream(session, 319);
10019 
10020   CU_ASSERT(0 == nghttp2_submit_shutdown_notice(session));
10021 
10022   ud.frame_send_cb_called = 0;
10023 
10024   CU_ASSERT(0 == nghttp2_session_send(session));
10025 
10026   CU_ASSERT(1 == ud.frame_send_cb_called);
10027   CU_ASSERT((1u << 31) - 1 == session->local_last_stream_id);
10028 
10029   CU_ASSERT(0 == nghttp2_submit_goaway(session, NGHTTP2_FLAG_NONE, 311,
10030                                        NGHTTP2_NO_ERROR, NULL, 0));
10031 
10032   ud.frame_send_cb_called = 0;
10033   ud.stream_close_cb_called = 0;
10034 
10035   CU_ASSERT(0 == nghttp2_session_send(session));
10036 
10037   CU_ASSERT(1 == ud.frame_send_cb_called);
10038   CU_ASSERT(311 == session->local_last_stream_id);
10039   CU_ASSERT(1 == ud.stream_close_cb_called);
10040 
10041   CU_ASSERT(0 ==
10042             nghttp2_session_terminate_session2(session, 301, NGHTTP2_NO_ERROR));
10043 
10044   ud.frame_send_cb_called = 0;
10045   ud.stream_close_cb_called = 0;
10046 
10047   CU_ASSERT(0 == nghttp2_session_send(session));
10048 
10049   CU_ASSERT(1 == ud.frame_send_cb_called);
10050   CU_ASSERT(301 == session->local_last_stream_id);
10051   CU_ASSERT(2 == ud.stream_close_cb_called);
10052 
10053   CU_ASSERT(NULL != nghttp2_session_get_stream(session, 301));
10054   CU_ASSERT(NULL != nghttp2_session_get_stream(session, 302));
10055   CU_ASSERT(NULL == nghttp2_session_get_stream(session, 309));
10056   CU_ASSERT(NULL == nghttp2_session_get_stream(session, 311));
10057   CU_ASSERT(NULL == nghttp2_session_get_stream(session, 319));
10058 
10059   nghttp2_session_del(session);
10060 }
10061 
test_nghttp2_session_on_header_temporal_failure(void)10062 void test_nghttp2_session_on_header_temporal_failure(void) {
10063   nghttp2_session *session;
10064   nghttp2_session_callbacks callbacks;
10065   my_user_data ud;
10066   nghttp2_bufs bufs;
10067   nghttp2_buf *buf;
10068   nghttp2_hd_deflater deflater;
10069   nghttp2_nv nv[] = {MAKE_NV("alpha", "bravo"), MAKE_NV("charlie", "delta")};
10070   nghttp2_nv *nva;
10071   size_t hdpos;
10072   ssize_t rv;
10073   nghttp2_frame frame;
10074   nghttp2_frame_hd hd;
10075   nghttp2_outbound_item *item;
10076   nghttp2_mem *mem;
10077 
10078   mem = nghttp2_mem_default();
10079   memset(&callbacks, 0, sizeof(callbacks));
10080   callbacks.on_header_callback = temporal_failure_on_header_callback;
10081 
10082   nghttp2_session_server_new(&session, &callbacks, &ud);
10083 
10084   frame_pack_bufs_init(&bufs);
10085 
10086   nghttp2_hd_deflate_init(&deflater, mem);
10087 
10088   nghttp2_nv_array_copy(&nva, reqnv, ARRLEN(reqnv), mem);
10089 
10090   nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_STREAM, 1,
10091                              NGHTTP2_HCAT_REQUEST, NULL, nva, ARRLEN(reqnv));
10092   nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
10093   nghttp2_frame_headers_free(&frame.headers, mem);
10094 
10095   /* We are going to create CONTINUATION.  First serialize header
10096      block, and then frame header. */
10097   hdpos = nghttp2_bufs_len(&bufs);
10098 
10099   buf = &bufs.head->buf;
10100   buf->last += NGHTTP2_FRAME_HDLEN;
10101 
10102   nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, &nv[1], 1);
10103 
10104   nghttp2_frame_hd_init(&hd,
10105                         nghttp2_bufs_len(&bufs) - hdpos - NGHTTP2_FRAME_HDLEN,
10106                         NGHTTP2_CONTINUATION, NGHTTP2_FLAG_END_HEADERS, 1);
10107 
10108   nghttp2_frame_pack_frame_hd(&buf->pos[hdpos], &hd);
10109 
10110   ud.header_cb_called = 0;
10111   rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_bufs_len(&bufs));
10112 
10113   CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == rv);
10114   CU_ASSERT(1 == ud.header_cb_called);
10115 
10116   item = nghttp2_session_get_next_ob_item(session);
10117 
10118   CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
10119   CU_ASSERT(1 == item->frame.hd.stream_id);
10120 
10121   /* Make sure no header decompression error occurred */
10122   CU_ASSERT(NGHTTP2_GOAWAY_NONE == session->goaway_flags);
10123 
10124   nghttp2_hd_deflate_free(&deflater);
10125   nghttp2_session_del(session);
10126 
10127   nghttp2_bufs_reset(&bufs);
10128 
10129   /* Check for PUSH_PROMISE */
10130   nghttp2_hd_deflate_init(&deflater, mem);
10131   nghttp2_session_client_new(&session, &callbacks, &ud);
10132 
10133   open_sent_stream(session, 1);
10134 
10135   rv = pack_push_promise(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, 2,
10136                          reqnv, ARRLEN(reqnv), mem);
10137   CU_ASSERT(0 == rv);
10138 
10139   ud.header_cb_called = 0;
10140   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
10141                                 nghttp2_bufs_len(&bufs));
10142   CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == rv);
10143   CU_ASSERT(1 == ud.header_cb_called);
10144 
10145   item = nghttp2_session_get_next_ob_item(session);
10146   CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
10147   CU_ASSERT(2 == item->frame.hd.stream_id);
10148   CU_ASSERT(NGHTTP2_INTERNAL_ERROR == item->frame.rst_stream.error_code);
10149 
10150   nghttp2_session_del(session);
10151   nghttp2_hd_deflate_free(&deflater);
10152   nghttp2_bufs_free(&bufs);
10153 }
10154 
test_nghttp2_session_recv_client_magic(void)10155 void test_nghttp2_session_recv_client_magic(void) {
10156   nghttp2_session *session;
10157   nghttp2_session_callbacks callbacks;
10158   ssize_t rv;
10159   nghttp2_frame ping_frame;
10160   uint8_t buf[16];
10161 
10162   /* enable global nghttp2_enable_strict_preface here */
10163   nghttp2_enable_strict_preface = 1;
10164 
10165   memset(&callbacks, 0, sizeof(callbacks));
10166 
10167   /* Check success case */
10168   nghttp2_session_server_new(&session, &callbacks, NULL);
10169 
10170   rv = nghttp2_session_mem_recv(session, (const uint8_t *)NGHTTP2_CLIENT_MAGIC,
10171                                 NGHTTP2_CLIENT_MAGIC_LEN);
10172 
10173   CU_ASSERT(rv == NGHTTP2_CLIENT_MAGIC_LEN);
10174   CU_ASSERT(NGHTTP2_IB_READ_FIRST_SETTINGS == session->iframe.state);
10175 
10176   /* Receiving PING is error because we want SETTINGS. */
10177   nghttp2_frame_ping_init(&ping_frame.ping, NGHTTP2_FLAG_NONE, NULL);
10178 
10179   nghttp2_frame_pack_frame_hd(buf, &ping_frame.ping.hd);
10180 
10181   rv = nghttp2_session_mem_recv(session, buf, NGHTTP2_FRAME_HDLEN);
10182   CU_ASSERT(NGHTTP2_FRAME_HDLEN == rv);
10183   CU_ASSERT(NGHTTP2_IB_IGN_ALL == session->iframe.state);
10184   CU_ASSERT(0 == session->iframe.payloadleft);
10185 
10186   nghttp2_frame_ping_free(&ping_frame.ping);
10187 
10188   nghttp2_session_del(session);
10189 
10190   /* Check bad case */
10191   nghttp2_session_server_new(&session, &callbacks, NULL);
10192 
10193   /* Feed magic with one byte less */
10194   rv = nghttp2_session_mem_recv(session, (const uint8_t *)NGHTTP2_CLIENT_MAGIC,
10195                                 NGHTTP2_CLIENT_MAGIC_LEN - 1);
10196 
10197   CU_ASSERT(rv == NGHTTP2_CLIENT_MAGIC_LEN - 1);
10198   CU_ASSERT(NGHTTP2_IB_READ_CLIENT_MAGIC == session->iframe.state);
10199   CU_ASSERT(1 == session->iframe.payloadleft);
10200 
10201   rv = nghttp2_session_mem_recv(session, (const uint8_t *)"\0", 1);
10202 
10203   CU_ASSERT(NGHTTP2_ERR_BAD_CLIENT_MAGIC == rv);
10204 
10205   nghttp2_session_del(session);
10206 
10207   /* disable global nghttp2_enable_strict_preface here */
10208   nghttp2_enable_strict_preface = 0;
10209 }
10210 
test_nghttp2_session_delete_data_item(void)10211 void test_nghttp2_session_delete_data_item(void) {
10212   nghttp2_session *session;
10213   nghttp2_session_callbacks callbacks;
10214   nghttp2_stream *a;
10215   nghttp2_data_provider prd;
10216 
10217   memset(&callbacks, 0, sizeof(callbacks));
10218 
10219   nghttp2_session_server_new(&session, &callbacks, NULL);
10220 
10221   a = open_recv_stream(session, 1);
10222   open_recv_stream_with_dep(session, 3, a);
10223 
10224   /* We don't care about these members, since we won't send data */
10225   prd.source.ptr = NULL;
10226   prd.read_callback = fail_data_source_read_callback;
10227 
10228   CU_ASSERT(0 == nghttp2_submit_data(session, NGHTTP2_FLAG_NONE, 1, &prd));
10229   CU_ASSERT(0 == nghttp2_submit_data(session, NGHTTP2_FLAG_NONE, 3, &prd));
10230 
10231   nghttp2_session_del(session);
10232 }
10233 
test_nghttp2_session_open_idle_stream(void)10234 void test_nghttp2_session_open_idle_stream(void) {
10235   nghttp2_session *session;
10236   nghttp2_session_callbacks callbacks;
10237   nghttp2_stream *stream;
10238   nghttp2_stream *opened_stream;
10239   nghttp2_priority_spec pri_spec;
10240   nghttp2_frame frame;
10241 
10242   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
10243 
10244   nghttp2_session_server_new(&session, &callbacks, NULL);
10245 
10246   nghttp2_priority_spec_init(&pri_spec, 0, 3, 0);
10247 
10248   nghttp2_frame_priority_init(&frame.priority, 1, &pri_spec);
10249 
10250   CU_ASSERT(0 == nghttp2_session_on_priority_received(session, &frame));
10251 
10252   stream = nghttp2_session_get_stream_raw(session, 1);
10253 
10254   CU_ASSERT(NGHTTP2_STREAM_IDLE == stream->state);
10255   CU_ASSERT(NULL == stream->closed_prev);
10256   CU_ASSERT(NULL == stream->closed_next);
10257   CU_ASSERT(1 == session->num_idle_streams);
10258   CU_ASSERT(session->idle_stream_head == stream);
10259   CU_ASSERT(session->idle_stream_tail == stream);
10260 
10261   opened_stream = open_recv_stream2(session, 1, NGHTTP2_STREAM_OPENING);
10262 
10263   CU_ASSERT(stream == opened_stream);
10264   CU_ASSERT(NGHTTP2_STREAM_OPENING == stream->state);
10265   CU_ASSERT(0 == session->num_idle_streams);
10266   CU_ASSERT(NULL == session->idle_stream_head);
10267   CU_ASSERT(NULL == session->idle_stream_tail);
10268 
10269   nghttp2_frame_priority_free(&frame.priority);
10270 
10271   nghttp2_session_del(session);
10272 }
10273 
test_nghttp2_session_cancel_reserved_remote(void)10274 void test_nghttp2_session_cancel_reserved_remote(void) {
10275   nghttp2_session *session;
10276   nghttp2_session_callbacks callbacks;
10277   nghttp2_stream *stream;
10278   nghttp2_frame frame;
10279   nghttp2_nv *nva;
10280   size_t nvlen;
10281   nghttp2_hd_deflater deflater;
10282   nghttp2_mem *mem;
10283   nghttp2_bufs bufs;
10284   ssize_t rv;
10285 
10286   mem = nghttp2_mem_default();
10287   frame_pack_bufs_init(&bufs);
10288 
10289   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
10290   callbacks.send_callback = null_send_callback;
10291 
10292   nghttp2_session_client_new(&session, &callbacks, NULL);
10293 
10294   nghttp2_hd_deflate_init(&deflater, mem);
10295 
10296   stream = open_recv_stream2(session, 2, NGHTTP2_STREAM_RESERVED);
10297 
10298   nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, 2, NGHTTP2_CANCEL);
10299 
10300   CU_ASSERT(NGHTTP2_STREAM_CLOSING == stream->state);
10301 
10302   CU_ASSERT(0 == nghttp2_session_send(session));
10303 
10304   nvlen = ARRLEN(resnv);
10305   nghttp2_nv_array_copy(&nva, resnv, nvlen, mem);
10306 
10307   nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 2,
10308                              NGHTTP2_HCAT_PUSH_RESPONSE, NULL, nva, nvlen);
10309   rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
10310 
10311   CU_ASSERT(0 == rv);
10312 
10313   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
10314                                 nghttp2_buf_len(&bufs.head->buf));
10315 
10316   CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
10317 
10318   /* stream is not dangling, so assign NULL */
10319   stream = NULL;
10320 
10321   /* No RST_STREAM or GOAWAY is generated since stream should be in
10322      NGHTTP2_STREAM_CLOSING and push response should be ignored. */
10323   CU_ASSERT(0 == nghttp2_outbound_queue_size(&session->ob_reg));
10324 
10325   /* Check that we can receive push response HEADERS while RST_STREAM
10326      is just queued. */
10327   open_recv_stream2(session, 4, NGHTTP2_STREAM_RESERVED);
10328 
10329   nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, 2, NGHTTP2_CANCEL);
10330 
10331   nghttp2_bufs_reset(&bufs);
10332 
10333   frame.hd.stream_id = 4;
10334   rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
10335 
10336   CU_ASSERT(0 == rv);
10337 
10338   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
10339                                 nghttp2_buf_len(&bufs.head->buf));
10340 
10341   CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
10342 
10343   CU_ASSERT(1 == nghttp2_outbound_queue_size(&session->ob_reg));
10344 
10345   nghttp2_frame_headers_free(&frame.headers, mem);
10346 
10347   nghttp2_hd_deflate_free(&deflater);
10348 
10349   nghttp2_session_del(session);
10350 
10351   nghttp2_bufs_free(&bufs);
10352 }
10353 
test_nghttp2_session_reset_pending_headers(void)10354 void test_nghttp2_session_reset_pending_headers(void) {
10355   nghttp2_session *session;
10356   nghttp2_session_callbacks callbacks;
10357   nghttp2_stream *stream;
10358   int32_t stream_id;
10359   my_user_data ud;
10360 
10361   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
10362   callbacks.send_callback = null_send_callback;
10363   callbacks.on_frame_send_callback = on_frame_send_callback;
10364   callbacks.on_frame_not_send_callback = on_frame_not_send_callback;
10365   callbacks.on_stream_close_callback = on_stream_close_callback;
10366 
10367   nghttp2_session_client_new(&session, &callbacks, &ud);
10368 
10369   stream_id = nghttp2_submit_request(session, NULL, NULL, 0, NULL, NULL);
10370   CU_ASSERT(stream_id >= 1);
10371 
10372   nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, stream_id,
10373                             NGHTTP2_CANCEL);
10374 
10375   session->remote_settings.max_concurrent_streams = 0;
10376 
10377   /* RST_STREAM cancels pending HEADERS and is not actually sent. */
10378   ud.frame_send_cb_called = 0;
10379   CU_ASSERT(0 == nghttp2_session_send(session));
10380 
10381   CU_ASSERT(0 == ud.frame_send_cb_called);
10382 
10383   stream = nghttp2_session_get_stream(session, stream_id);
10384 
10385   CU_ASSERT(NULL == stream);
10386 
10387   /* See HEADERS is not sent.  on_stream_close is called just like
10388      transmission failure. */
10389   session->remote_settings.max_concurrent_streams = 1;
10390 
10391   ud.frame_not_send_cb_called = 0;
10392   ud.stream_close_error_code = 0;
10393   CU_ASSERT(0 == nghttp2_session_send(session));
10394 
10395   CU_ASSERT(1 == ud.frame_not_send_cb_called);
10396   CU_ASSERT(NGHTTP2_HEADERS == ud.not_sent_frame_type);
10397   CU_ASSERT(NGHTTP2_CANCEL == ud.stream_close_error_code);
10398 
10399   stream = nghttp2_session_get_stream(session, stream_id);
10400 
10401   CU_ASSERT(NULL == stream);
10402 
10403   nghttp2_session_del(session);
10404 }
10405 
test_nghttp2_session_send_data_callback(void)10406 void test_nghttp2_session_send_data_callback(void) {
10407   nghttp2_session *session;
10408   nghttp2_session_callbacks callbacks;
10409   nghttp2_data_provider data_prd;
10410   my_user_data ud;
10411   accumulator acc;
10412   nghttp2_frame_hd hd;
10413 
10414   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
10415   callbacks.send_callback = accumulator_send_callback;
10416   callbacks.send_data_callback = send_data_callback;
10417 
10418   data_prd.read_callback = no_copy_data_source_read_callback;
10419 
10420   acc.length = 0;
10421   ud.acc = &acc;
10422 
10423   ud.data_source_length = NGHTTP2_DATA_PAYLOADLEN * 2;
10424 
10425   nghttp2_session_client_new(&session, &callbacks, &ud);
10426 
10427   open_sent_stream(session, 1);
10428 
10429   nghttp2_submit_data(session, NGHTTP2_FLAG_END_STREAM, 1, &data_prd);
10430 
10431   CU_ASSERT(0 == nghttp2_session_send(session));
10432 
10433   CU_ASSERT((NGHTTP2_FRAME_HDLEN + NGHTTP2_DATA_PAYLOADLEN) * 2 == acc.length);
10434 
10435   nghttp2_frame_unpack_frame_hd(&hd, acc.buf);
10436 
10437   CU_ASSERT(16384 == hd.length);
10438   CU_ASSERT(NGHTTP2_DATA == hd.type);
10439   CU_ASSERT(NGHTTP2_FLAG_NONE == hd.flags);
10440 
10441   nghttp2_frame_unpack_frame_hd(&hd, acc.buf + NGHTTP2_FRAME_HDLEN + hd.length);
10442 
10443   CU_ASSERT(16384 == hd.length);
10444   CU_ASSERT(NGHTTP2_DATA == hd.type);
10445   CU_ASSERT(NGHTTP2_FLAG_END_STREAM == hd.flags);
10446 
10447   nghttp2_session_del(session);
10448 }
10449 
test_nghttp2_session_on_begin_headers_temporal_failure(void)10450 void test_nghttp2_session_on_begin_headers_temporal_failure(void) {
10451   nghttp2_session *session;
10452   nghttp2_session_callbacks callbacks;
10453   my_user_data ud;
10454   nghttp2_bufs bufs;
10455   nghttp2_mem *mem;
10456   ssize_t rv;
10457   nghttp2_hd_deflater deflater;
10458   nghttp2_outbound_item *item;
10459 
10460   mem = nghttp2_mem_default();
10461   frame_pack_bufs_init(&bufs);
10462   nghttp2_hd_deflate_init(&deflater, mem);
10463 
10464   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
10465   callbacks.on_begin_headers_callback =
10466       temporal_failure_on_begin_headers_callback;
10467   callbacks.on_header_callback = on_header_callback;
10468   callbacks.on_frame_recv_callback = on_frame_recv_callback;
10469   callbacks.send_callback = null_send_callback;
10470   nghttp2_session_server_new(&session, &callbacks, &ud);
10471 
10472   rv = pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, reqnv,
10473                     ARRLEN(reqnv), mem);
10474   CU_ASSERT(0 == rv);
10475 
10476   ud.header_cb_called = 0;
10477   ud.frame_recv_cb_called = 0;
10478   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
10479                                 nghttp2_bufs_len(&bufs));
10480   CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == rv);
10481   CU_ASSERT(0 == ud.header_cb_called);
10482   CU_ASSERT(0 == ud.frame_recv_cb_called);
10483 
10484   item = nghttp2_session_get_next_ob_item(session);
10485   CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
10486   CU_ASSERT(1 == item->frame.hd.stream_id);
10487   CU_ASSERT(NGHTTP2_INTERNAL_ERROR == item->frame.rst_stream.error_code);
10488 
10489   nghttp2_session_del(session);
10490   nghttp2_hd_deflate_free(&deflater);
10491 
10492   nghttp2_bufs_reset(&bufs);
10493   /* check for PUSH_PROMISE */
10494   nghttp2_hd_deflate_init(&deflater, mem);
10495   nghttp2_session_client_new(&session, &callbacks, &ud);
10496 
10497   open_sent_stream(session, 1);
10498 
10499   rv = pack_push_promise(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, 2,
10500                          reqnv, ARRLEN(reqnv), mem);
10501   CU_ASSERT(0 == rv);
10502 
10503   ud.header_cb_called = 0;
10504   ud.frame_recv_cb_called = 0;
10505   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
10506                                 nghttp2_bufs_len(&bufs));
10507   CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == rv);
10508   CU_ASSERT(0 == ud.header_cb_called);
10509   CU_ASSERT(0 == ud.frame_recv_cb_called);
10510 
10511   item = nghttp2_session_get_next_ob_item(session);
10512   CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
10513   CU_ASSERT(2 == item->frame.hd.stream_id);
10514   CU_ASSERT(NGHTTP2_INTERNAL_ERROR == item->frame.rst_stream.error_code);
10515 
10516   nghttp2_session_del(session);
10517   nghttp2_hd_deflate_free(&deflater);
10518   nghttp2_bufs_free(&bufs);
10519 }
10520 
test_nghttp2_session_defer_then_close(void)10521 void test_nghttp2_session_defer_then_close(void) {
10522   nghttp2_session *session;
10523   nghttp2_session_callbacks callbacks;
10524   nghttp2_data_provider prd;
10525   int rv;
10526   const uint8_t *datap;
10527   ssize_t datalen;
10528   nghttp2_frame frame;
10529 
10530   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
10531   callbacks.send_callback = null_send_callback;
10532 
10533   nghttp2_session_client_new(&session, &callbacks, NULL);
10534 
10535   prd.read_callback = defer_data_source_read_callback;
10536 
10537   rv = nghttp2_submit_request(session, NULL, reqnv, ARRLEN(reqnv), &prd, NULL);
10538   CU_ASSERT(rv > 0);
10539 
10540   /* This sends HEADERS */
10541   datalen = nghttp2_session_mem_send(session, &datap);
10542 
10543   CU_ASSERT(datalen > 0);
10544 
10545   /* This makes DATA item deferred */
10546   datalen = nghttp2_session_mem_send(session, &datap);
10547 
10548   CU_ASSERT(datalen == 0);
10549 
10550   nghttp2_frame_rst_stream_init(&frame.rst_stream, 1, NGHTTP2_CANCEL);
10551 
10552   /* Assertion failure; GH-264 */
10553   rv = nghttp2_session_on_rst_stream_received(session, &frame);
10554 
10555   CU_ASSERT(rv == 0);
10556 
10557   nghttp2_session_del(session);
10558 }
10559 
submit_response_on_stream_close(nghttp2_session * session,int32_t stream_id,uint32_t error_code,void * user_data)10560 static int submit_response_on_stream_close(nghttp2_session *session,
10561                                            int32_t stream_id,
10562                                            uint32_t error_code,
10563                                            void *user_data) {
10564   nghttp2_data_provider data_prd;
10565   (void)error_code;
10566   (void)user_data;
10567 
10568   data_prd.read_callback = temporal_failure_data_source_read_callback;
10569 
10570   // Attempt to submit response or data to the stream being closed
10571   switch (stream_id) {
10572   case 1:
10573     CU_ASSERT(0 == nghttp2_submit_response(session, stream_id, resnv,
10574                                            ARRLEN(resnv), &data_prd));
10575     break;
10576   case 3:
10577     CU_ASSERT(0 == nghttp2_submit_data(session, NGHTTP2_FLAG_NONE, stream_id,
10578                                        &data_prd));
10579     break;
10580   }
10581 
10582   return 0;
10583 }
10584 
test_nghttp2_session_detach_item_from_closed_stream(void)10585 void test_nghttp2_session_detach_item_from_closed_stream(void) {
10586   nghttp2_session *session;
10587   nghttp2_session_callbacks callbacks;
10588 
10589   memset(&callbacks, 0, sizeof(callbacks));
10590 
10591   callbacks.send_callback = null_send_callback;
10592   callbacks.on_stream_close_callback = submit_response_on_stream_close;
10593 
10594   nghttp2_session_server_new(&session, &callbacks, NULL);
10595 
10596   open_recv_stream(session, 1);
10597   open_recv_stream(session, 3);
10598 
10599   nghttp2_session_close_stream(session, 1, NGHTTP2_NO_ERROR);
10600   nghttp2_session_close_stream(session, 3, NGHTTP2_NO_ERROR);
10601 
10602   CU_ASSERT(0 == nghttp2_session_send(session));
10603 
10604   nghttp2_session_del(session);
10605 }
10606 
test_nghttp2_session_flooding(void)10607 void test_nghttp2_session_flooding(void) {
10608   nghttp2_session *session;
10609   nghttp2_session_callbacks callbacks;
10610   nghttp2_bufs bufs;
10611   nghttp2_buf *buf;
10612   nghttp2_frame frame;
10613   nghttp2_mem *mem;
10614   size_t i;
10615 
10616   mem = nghttp2_mem_default();
10617 
10618   frame_pack_bufs_init(&bufs);
10619 
10620   memset(&callbacks, 0, sizeof(callbacks));
10621 
10622   /* PING ACK */
10623   nghttp2_session_server_new(&session, &callbacks, NULL);
10624 
10625   nghttp2_frame_ping_init(&frame.ping, NGHTTP2_FLAG_NONE, NULL);
10626   nghttp2_frame_pack_ping(&bufs, &frame.ping);
10627   nghttp2_frame_ping_free(&frame.ping);
10628 
10629   buf = &bufs.head->buf;
10630 
10631   for (i = 0; i < NGHTTP2_DEFAULT_MAX_OBQ_FLOOD_ITEM; ++i) {
10632     CU_ASSERT(
10633         (ssize_t)nghttp2_buf_len(buf) ==
10634         nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf)));
10635   }
10636 
10637   CU_ASSERT(NGHTTP2_ERR_FLOODED ==
10638             nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf)));
10639 
10640   nghttp2_session_del(session);
10641 
10642   /* SETTINGS ACK */
10643   nghttp2_bufs_reset(&bufs);
10644 
10645   nghttp2_session_server_new(&session, &callbacks, NULL);
10646 
10647   nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE, NULL, 0);
10648   nghttp2_frame_pack_settings(&bufs, &frame.settings);
10649   nghttp2_frame_settings_free(&frame.settings, mem);
10650 
10651   buf = &bufs.head->buf;
10652 
10653   for (i = 0; i < NGHTTP2_DEFAULT_MAX_OBQ_FLOOD_ITEM; ++i) {
10654     CU_ASSERT(
10655         (ssize_t)nghttp2_buf_len(buf) ==
10656         nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf)));
10657   }
10658 
10659   CU_ASSERT(NGHTTP2_ERR_FLOODED ==
10660             nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf)));
10661 
10662   nghttp2_session_del(session);
10663   nghttp2_bufs_free(&bufs);
10664 }
10665 
test_nghttp2_session_change_stream_priority(void)10666 void test_nghttp2_session_change_stream_priority(void) {
10667   nghttp2_session *session;
10668   nghttp2_session_callbacks callbacks;
10669   nghttp2_stream *stream1, *stream2, *stream3, *stream5;
10670   nghttp2_priority_spec pri_spec;
10671   int rv;
10672 
10673   memset(&callbacks, 0, sizeof(callbacks));
10674 
10675   nghttp2_session_server_new(&session, &callbacks, NULL);
10676 
10677   stream1 = open_recv_stream(session, 1);
10678   stream3 = open_recv_stream_with_dep_weight(session, 3, 199, stream1);
10679   stream2 = open_sent_stream_with_dep_weight(session, 2, 101, stream3);
10680 
10681   nghttp2_priority_spec_init(&pri_spec, 1, 256, 0);
10682 
10683   rv = nghttp2_session_change_stream_priority(session, 2, &pri_spec);
10684 
10685   CU_ASSERT(0 == rv);
10686 
10687   CU_ASSERT(stream1 == stream2->dep_prev);
10688   CU_ASSERT(256 == stream2->weight);
10689 
10690   /* Cannot change stream which does not exist */
10691   rv = nghttp2_session_change_stream_priority(session, 5, &pri_spec);
10692   CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT == rv);
10693 
10694   /* It is an error to depend on itself */
10695   rv = nghttp2_session_change_stream_priority(session, 1, &pri_spec);
10696   CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT == rv);
10697 
10698   /* It is an error to change priority of root stream (0) */
10699   rv = nghttp2_session_change_stream_priority(session, 0, &pri_spec);
10700   CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT == rv);
10701 
10702   /* Depends on the non-existing idle stream.  This creates that idle
10703      stream. */
10704   nghttp2_priority_spec_init(&pri_spec, 5, 9, 1);
10705 
10706   rv = nghttp2_session_change_stream_priority(session, 2, &pri_spec);
10707 
10708   CU_ASSERT(0 == rv);
10709 
10710   stream5 = nghttp2_session_get_stream_raw(session, 5);
10711 
10712   CU_ASSERT(NULL != stream5);
10713   CU_ASSERT(&session->root == stream5->dep_prev);
10714   CU_ASSERT(stream5 == stream2->dep_prev);
10715   CU_ASSERT(9 == stream2->weight);
10716 
10717   nghttp2_session_del(session);
10718 
10719   /* Check that this works in client session too */
10720   nghttp2_session_client_new(&session, &callbacks, NULL);
10721 
10722   stream1 = open_sent_stream(session, 1);
10723 
10724   nghttp2_priority_spec_init(&pri_spec, 5, 9, 1);
10725 
10726   rv = nghttp2_session_change_stream_priority(session, 1, &pri_spec);
10727 
10728   CU_ASSERT(0 == rv);
10729 
10730   stream5 = nghttp2_session_get_stream_raw(session, 5);
10731 
10732   CU_ASSERT(NULL != stream5);
10733   CU_ASSERT(&session->root == stream5->dep_prev);
10734   CU_ASSERT(stream5 == stream1->dep_prev);
10735   CU_ASSERT(9 == stream1->weight);
10736 
10737   nghttp2_session_del(session);
10738 }
10739 
test_nghttp2_session_change_extpri_stream_priority(void)10740 void test_nghttp2_session_change_extpri_stream_priority(void) {
10741   nghttp2_session *session;
10742   nghttp2_session_callbacks callbacks;
10743   nghttp2_bufs bufs;
10744   nghttp2_buf *buf;
10745   ssize_t rv;
10746   nghttp2_option *option;
10747   nghttp2_extension frame;
10748   nghttp2_ext_priority_update priority_update;
10749   nghttp2_extpri extpri;
10750   nghttp2_stream *stream;
10751   static const uint8_t field_value[] = "u=2";
10752 
10753   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
10754 
10755   frame_pack_bufs_init(&bufs);
10756 
10757   nghttp2_option_new(&option);
10758   nghttp2_option_set_builtin_recv_extension_type(option,
10759                                                  NGHTTP2_PRIORITY_UPDATE);
10760 
10761   nghttp2_session_server_new2(&session, &callbacks, NULL, option);
10762 
10763   session->pending_no_rfc7540_priorities = 1;
10764 
10765   open_recv_stream(session, 1);
10766 
10767   extpri.urgency = NGHTTP2_EXTPRI_URGENCY_LOW + 1;
10768   extpri.inc = 1;
10769 
10770   rv = nghttp2_session_change_extpri_stream_priority(
10771       session, 1, &extpri, /* ignore_client_signal = */ 0);
10772 
10773   CU_ASSERT(0 == rv);
10774 
10775   stream = nghttp2_session_get_stream(session, 1);
10776 
10777   CU_ASSERT(NGHTTP2_EXTPRI_URGENCY_LOW ==
10778             nghttp2_extpri_uint8_urgency(stream->extpri));
10779   CU_ASSERT(1 == nghttp2_extpri_uint8_inc(stream->extpri));
10780 
10781   /* Client can still update stream priority. */
10782   frame.payload = &priority_update;
10783   nghttp2_frame_priority_update_init(&frame, 1, (uint8_t *)field_value,
10784                                      sizeof(field_value) - 1);
10785   nghttp2_frame_pack_priority_update(&bufs, &frame);
10786 
10787   buf = &bufs.head->buf;
10788   rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
10789 
10790   CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv);
10791   CU_ASSERT(2 == stream->extpri);
10792 
10793   /* Start to ignore client priority signal for this stream. */
10794   rv = nghttp2_session_change_extpri_stream_priority(
10795       session, 1, &extpri, /* ignore_client_signal = */ 1);
10796 
10797   CU_ASSERT(0 == rv);
10798 
10799   stream = nghttp2_session_get_stream(session, 1);
10800 
10801   CU_ASSERT(NGHTTP2_EXTPRI_URGENCY_LOW ==
10802             nghttp2_extpri_uint8_urgency(stream->extpri));
10803   CU_ASSERT(1 == nghttp2_extpri_uint8_inc(stream->extpri));
10804 
10805   buf = &bufs.head->buf;
10806   rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
10807 
10808   CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv);
10809   CU_ASSERT(NGHTTP2_EXTPRI_URGENCY_LOW ==
10810             nghttp2_extpri_uint8_urgency(stream->extpri));
10811   CU_ASSERT(1 == nghttp2_extpri_uint8_inc(stream->extpri));
10812 
10813   nghttp2_session_del(session);
10814   nghttp2_option_del(option);
10815   nghttp2_bufs_free(&bufs);
10816 }
10817 
test_nghttp2_session_create_idle_stream(void)10818 void test_nghttp2_session_create_idle_stream(void) {
10819   nghttp2_session *session;
10820   nghttp2_session_callbacks callbacks;
10821   nghttp2_stream *stream2, *stream4, *stream8, *stream10;
10822   nghttp2_priority_spec pri_spec;
10823   int rv;
10824   int i;
10825 
10826   memset(&callbacks, 0, sizeof(callbacks));
10827   callbacks.send_callback = null_send_callback;
10828 
10829   nghttp2_session_server_new(&session, &callbacks, NULL);
10830 
10831   stream2 = open_sent_stream(session, 2);
10832 
10833   nghttp2_priority_spec_init(&pri_spec, 2, 111, 1);
10834 
10835   rv = nghttp2_session_create_idle_stream(session, 4, &pri_spec);
10836 
10837   CU_ASSERT(0 == rv);
10838 
10839   stream4 = nghttp2_session_get_stream_raw(session, 4);
10840 
10841   CU_ASSERT(4 == stream4->stream_id);
10842   CU_ASSERT(111 == stream4->weight);
10843   CU_ASSERT(stream2 == stream4->dep_prev);
10844   CU_ASSERT(stream4 == stream2->dep_next);
10845 
10846   /* If pri_spec->stream_id does not exist, and it is idle stream, it
10847      is created too */
10848   nghttp2_priority_spec_init(&pri_spec, 10, 109, 0);
10849 
10850   rv = nghttp2_session_create_idle_stream(session, 8, &pri_spec);
10851 
10852   CU_ASSERT(0 == rv);
10853 
10854   stream8 = nghttp2_session_get_stream_raw(session, 8);
10855   stream10 = nghttp2_session_get_stream_raw(session, 10);
10856 
10857   CU_ASSERT(8 == stream8->stream_id);
10858   CU_ASSERT(109 == stream8->weight);
10859   CU_ASSERT(10 == stream10->stream_id);
10860   CU_ASSERT(16 == stream10->weight);
10861   CU_ASSERT(stream10 == stream8->dep_prev);
10862   CU_ASSERT(&session->root == stream10->dep_prev);
10863 
10864   /* It is an error to attempt to create already existing idle
10865      stream */
10866   rv = nghttp2_session_create_idle_stream(session, 4, &pri_spec);
10867 
10868   CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT == rv);
10869 
10870   /* It is an error to depend on itself */
10871   pri_spec.stream_id = 6;
10872 
10873   rv = nghttp2_session_create_idle_stream(session, 6, &pri_spec);
10874   CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT == rv);
10875 
10876   /* It is an error to create root stream (0) as idle stream */
10877   rv = nghttp2_session_create_idle_stream(session, 0, &pri_spec);
10878   CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT == rv);
10879 
10880   /* It is an error to create non-idle stream */
10881   session->last_sent_stream_id = 20;
10882   pri_spec.stream_id = 2;
10883 
10884   rv = nghttp2_session_create_idle_stream(session, 18, &pri_spec);
10885 
10886   CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT == rv);
10887 
10888   nghttp2_session_del(session);
10889 
10890   /* Check that this works in client session too */
10891   nghttp2_session_client_new(&session, &callbacks, NULL);
10892 
10893   nghttp2_priority_spec_init(&pri_spec, 4, 99, 1);
10894 
10895   rv = nghttp2_session_create_idle_stream(session, 2, &pri_spec);
10896 
10897   CU_ASSERT(0 == rv);
10898 
10899   stream4 = nghttp2_session_get_stream_raw(session, 4);
10900   stream2 = nghttp2_session_get_stream_raw(session, 2);
10901 
10902   CU_ASSERT(NULL != stream4);
10903   CU_ASSERT(NULL != stream2);
10904   CU_ASSERT(&session->root == stream4->dep_prev);
10905   CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == stream4->weight);
10906   CU_ASSERT(stream4 == stream2->dep_prev);
10907   CU_ASSERT(99 == stream2->weight);
10908 
10909   nghttp2_session_del(session);
10910 
10911   /* Check that idle stream is reduced when nghttp2_session_send() is
10912      called. */
10913   nghttp2_session_server_new(&session, &callbacks, NULL);
10914 
10915   session->local_settings.max_concurrent_streams = 30;
10916 
10917   nghttp2_priority_spec_init(&pri_spec, 0, 16, 0);
10918   for (i = 0; i < 100; ++i) {
10919     rv = nghttp2_session_create_idle_stream(session, i * 2 + 1, &pri_spec);
10920 
10921     CU_ASSERT(0 == rv);
10922 
10923     nghttp2_priority_spec_init(&pri_spec, i * 2 + 1, 16, 0);
10924   }
10925 
10926   CU_ASSERT(100 == session->num_idle_streams);
10927   CU_ASSERT(0 == nghttp2_session_send(session));
10928   CU_ASSERT(30 == session->num_idle_streams);
10929   CU_ASSERT(141 == session->idle_stream_head->stream_id);
10930 
10931   nghttp2_session_del(session);
10932 
10933   /* Check that idle stream is reduced when nghttp2_session_mem_recv() is
10934      called. */
10935   nghttp2_session_client_new(&session, &callbacks, NULL);
10936 
10937   session->local_settings.max_concurrent_streams = 30;
10938 
10939   nghttp2_priority_spec_init(&pri_spec, 0, 16, 0);
10940   for (i = 0; i < 100; ++i) {
10941     rv = nghttp2_session_create_idle_stream(session, i * 2 + 1, &pri_spec);
10942 
10943     CU_ASSERT(0 == rv);
10944 
10945     nghttp2_priority_spec_init(&pri_spec, i * 2 + 1, 16, 0);
10946   }
10947 
10948   CU_ASSERT(100 == session->num_idle_streams);
10949   CU_ASSERT(0 == nghttp2_session_mem_recv(session, NULL, 0));
10950   CU_ASSERT(30 == session->num_idle_streams);
10951   CU_ASSERT(141 == session->idle_stream_head->stream_id);
10952 
10953   nghttp2_session_del(session);
10954 }
10955 
test_nghttp2_session_repeated_priority_change(void)10956 void test_nghttp2_session_repeated_priority_change(void) {
10957   nghttp2_session *session;
10958   nghttp2_session_callbacks callbacks;
10959   nghttp2_frame frame;
10960   nghttp2_priority_spec pri_spec;
10961   int32_t stream_id, last_stream_id;
10962   int32_t max_streams = 20;
10963 
10964   memset(&callbacks, 0, sizeof(callbacks));
10965 
10966   nghttp2_session_server_new(&session, &callbacks, NULL);
10967 
10968   session->local_settings.max_concurrent_streams = (uint32_t)max_streams;
10969 
10970   /* 1 -> 0 */
10971   nghttp2_priority_spec_init(&pri_spec, 0, 16, 0);
10972   nghttp2_frame_priority_init(&frame.priority, 1, &pri_spec);
10973 
10974   CU_ASSERT(0 == nghttp2_session_on_priority_received(session, &frame));
10975 
10976   nghttp2_frame_priority_free(&frame.priority);
10977 
10978   last_stream_id = max_streams * 2 + 1;
10979 
10980   for (stream_id = 3; stream_id < last_stream_id; stream_id += 2) {
10981     /* 1 -> stream_id */
10982     nghttp2_priority_spec_init(&pri_spec, stream_id, 16, 0);
10983     nghttp2_frame_priority_init(&frame.priority, 1, &pri_spec);
10984 
10985     CU_ASSERT(0 == nghttp2_session_on_priority_received(session, &frame));
10986 
10987     nghttp2_frame_priority_free(&frame.priority);
10988   }
10989 
10990   CU_ASSERT(20 == session->num_idle_streams);
10991   CU_ASSERT(1 == session->idle_stream_head->stream_id);
10992 
10993   /* 1 -> last_stream_id */
10994   nghttp2_priority_spec_init(&pri_spec, last_stream_id, 16, 0);
10995   nghttp2_frame_priority_init(&frame.priority, 1, &pri_spec);
10996 
10997   CU_ASSERT(0 == nghttp2_session_on_priority_received(session, &frame));
10998 
10999   nghttp2_frame_priority_free(&frame.priority);
11000 
11001   CU_ASSERT(20 == session->num_idle_streams);
11002   CU_ASSERT(3 == session->idle_stream_head->stream_id);
11003 
11004   nghttp2_session_del(session);
11005 }
11006 
test_nghttp2_session_repeated_priority_submission(void)11007 void test_nghttp2_session_repeated_priority_submission(void) {
11008   nghttp2_session *session;
11009   nghttp2_session_callbacks callbacks;
11010   nghttp2_priority_spec pri_spec;
11011   int32_t stream_id, last_stream_id;
11012   uint32_t max_streams = NGHTTP2_MIN_IDLE_STREAMS;
11013 
11014   memset(&callbacks, 0, sizeof(callbacks));
11015 
11016   callbacks.send_callback = null_send_callback;
11017 
11018   nghttp2_session_client_new(&session, &callbacks, NULL);
11019 
11020   session->local_settings.max_concurrent_streams = max_streams;
11021 
11022   /* 1 -> 0 */
11023   nghttp2_priority_spec_init(&pri_spec, 0, 16, 0);
11024 
11025   CU_ASSERT(0 ==
11026             nghttp2_submit_priority(session, NGHTTP2_FLAG_NONE, 1, &pri_spec));
11027 
11028   last_stream_id = (int32_t)(max_streams * 2 + 1);
11029 
11030   for (stream_id = 3; stream_id < last_stream_id; stream_id += 2) {
11031     /* 1 -> stream_id */
11032     nghttp2_priority_spec_init(&pri_spec, stream_id, 16, 0);
11033 
11034     CU_ASSERT(
11035         0 == nghttp2_submit_priority(session, NGHTTP2_FLAG_NONE, 1, &pri_spec));
11036   }
11037 
11038   CU_ASSERT(0 == nghttp2_session_send(session));
11039   CU_ASSERT(max_streams == session->num_idle_streams);
11040   CU_ASSERT(1 == session->idle_stream_head->stream_id);
11041 
11042   /* 1 -> last_stream_id */
11043   nghttp2_priority_spec_init(&pri_spec, last_stream_id, 16, 0);
11044 
11045   CU_ASSERT(0 ==
11046             nghttp2_submit_priority(session, NGHTTP2_FLAG_NONE, 1, &pri_spec));
11047 
11048   CU_ASSERT(0 == nghttp2_session_send(session));
11049   CU_ASSERT(max_streams == session->num_idle_streams);
11050   CU_ASSERT(3 == session->idle_stream_head->stream_id);
11051 
11052   nghttp2_session_del(session);
11053 }
11054 
test_nghttp2_session_set_local_window_size(void)11055 void test_nghttp2_session_set_local_window_size(void) {
11056   nghttp2_session *session;
11057   nghttp2_session_callbacks callbacks;
11058   nghttp2_outbound_item *item;
11059   nghttp2_stream *stream;
11060 
11061   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
11062   callbacks.send_callback = null_send_callback;
11063 
11064   nghttp2_session_client_new(&session, &callbacks, NULL);
11065   stream = open_sent_stream(session, 1);
11066   stream->recv_window_size = 4096;
11067 
11068   CU_ASSERT(0 == nghttp2_session_set_local_window_size(
11069                      session, NGHTTP2_FLAG_NONE, 1, 65536));
11070   CU_ASSERT(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE + 1 ==
11071             stream->local_window_size);
11072   CU_ASSERT(4096 == stream->recv_window_size);
11073   CU_ASSERT(65536 - 4096 ==
11074             nghttp2_session_get_stream_local_window_size(session, 1));
11075 
11076   item = nghttp2_session_get_next_ob_item(session);
11077 
11078   CU_ASSERT(NGHTTP2_WINDOW_UPDATE == item->frame.hd.type);
11079   CU_ASSERT(1 == item->frame.window_update.hd.stream_id);
11080   CU_ASSERT(1 == item->frame.window_update.window_size_increment);
11081 
11082   CU_ASSERT(0 == nghttp2_session_send(session));
11083 
11084   /* Go decrement part */
11085   CU_ASSERT(0 == nghttp2_session_set_local_window_size(
11086                      session, NGHTTP2_FLAG_NONE, 1, 32768));
11087   CU_ASSERT(32768 == stream->local_window_size);
11088   CU_ASSERT(-28672 == stream->recv_window_size);
11089   CU_ASSERT(32768 == stream->recv_reduction);
11090   CU_ASSERT(65536 - 4096 ==
11091             nghttp2_session_get_stream_local_window_size(session, 1));
11092 
11093   item = nghttp2_session_get_next_ob_item(session);
11094 
11095   CU_ASSERT(item == NULL);
11096 
11097   /* Increase local window size */
11098   CU_ASSERT(0 == nghttp2_session_set_local_window_size(
11099                      session, NGHTTP2_FLAG_NONE, 1, 49152));
11100   CU_ASSERT(49152 == stream->local_window_size);
11101   CU_ASSERT(-12288 == stream->recv_window_size);
11102   CU_ASSERT(16384 == stream->recv_reduction);
11103   CU_ASSERT(65536 - 4096 ==
11104             nghttp2_session_get_stream_local_window_size(session, 1));
11105   CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
11106 
11107   /* Increase local window again */
11108   CU_ASSERT(0 == nghttp2_session_set_local_window_size(
11109                      session, NGHTTP2_FLAG_NONE, 1, 65537));
11110   CU_ASSERT(65537 == stream->local_window_size);
11111   CU_ASSERT(4096 == stream->recv_window_size);
11112   CU_ASSERT(0 == stream->recv_reduction);
11113   CU_ASSERT(65537 - 4096 ==
11114             nghttp2_session_get_stream_local_window_size(session, 1));
11115 
11116   item = nghttp2_session_get_next_ob_item(session);
11117 
11118   CU_ASSERT(1 == item->frame.window_update.window_size_increment);
11119 
11120   CU_ASSERT(0 == nghttp2_session_send(session));
11121 
11122   /* Check connection-level flow control */
11123   session->recv_window_size = 4096;
11124   CU_ASSERT(0 == nghttp2_session_set_local_window_size(
11125                      session, NGHTTP2_FLAG_NONE, 0, 65536));
11126   CU_ASSERT(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE + 1 ==
11127             session->local_window_size);
11128   CU_ASSERT(4096 == session->recv_window_size);
11129   CU_ASSERT(65536 - 4096 == nghttp2_session_get_local_window_size(session));
11130 
11131   item = nghttp2_session_get_next_ob_item(session);
11132 
11133   CU_ASSERT(NGHTTP2_WINDOW_UPDATE == item->frame.hd.type);
11134   CU_ASSERT(0 == item->frame.window_update.hd.stream_id);
11135   CU_ASSERT(1 == item->frame.window_update.window_size_increment);
11136 
11137   CU_ASSERT(0 == nghttp2_session_send(session));
11138 
11139   /* Go decrement part */
11140   CU_ASSERT(0 == nghttp2_session_set_local_window_size(
11141                      session, NGHTTP2_FLAG_NONE, 0, 32768));
11142   CU_ASSERT(32768 == session->local_window_size);
11143   CU_ASSERT(-28672 == session->recv_window_size);
11144   CU_ASSERT(32768 == session->recv_reduction);
11145   CU_ASSERT(65536 - 4096 == nghttp2_session_get_local_window_size(session));
11146 
11147   item = nghttp2_session_get_next_ob_item(session);
11148 
11149   CU_ASSERT(item == NULL);
11150 
11151   /* Increase local window size */
11152   CU_ASSERT(0 == nghttp2_session_set_local_window_size(
11153                      session, NGHTTP2_FLAG_NONE, 0, 49152));
11154   CU_ASSERT(49152 == session->local_window_size);
11155   CU_ASSERT(-12288 == session->recv_window_size);
11156   CU_ASSERT(16384 == session->recv_reduction);
11157   CU_ASSERT(65536 - 4096 == nghttp2_session_get_local_window_size(session));
11158   CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
11159 
11160   /* Increase local window again */
11161   CU_ASSERT(0 == nghttp2_session_set_local_window_size(
11162                      session, NGHTTP2_FLAG_NONE, 0, 65537));
11163   CU_ASSERT(65537 == session->local_window_size);
11164   CU_ASSERT(4096 == session->recv_window_size);
11165   CU_ASSERT(0 == session->recv_reduction);
11166   CU_ASSERT(65537 - 4096 == nghttp2_session_get_local_window_size(session));
11167 
11168   item = nghttp2_session_get_next_ob_item(session);
11169 
11170   CU_ASSERT(1 == item->frame.window_update.window_size_increment);
11171 
11172   CU_ASSERT(0 == nghttp2_session_send(session));
11173 
11174   nghttp2_session_del(session);
11175 
11176   /* Make sure that nghttp2_session_set_local_window_size submits
11177      WINDOW_UPDATE if necessary to increase stream-level window. */
11178   nghttp2_session_client_new(&session, &callbacks, NULL);
11179   stream = open_sent_stream(session, 1);
11180   stream->recv_window_size = NGHTTP2_INITIAL_WINDOW_SIZE;
11181 
11182   CU_ASSERT(0 == nghttp2_session_set_local_window_size(
11183                      session, NGHTTP2_FLAG_NONE, 1, 0));
11184   CU_ASSERT(0 == stream->recv_window_size);
11185   CU_ASSERT(0 == nghttp2_session_get_stream_local_window_size(session, 1));
11186   /* This should submit WINDOW_UPDATE frame because stream-level
11187      receiving window is now full. */
11188   CU_ASSERT(0 ==
11189             nghttp2_session_set_local_window_size(session, NGHTTP2_FLAG_NONE, 1,
11190                                                   NGHTTP2_INITIAL_WINDOW_SIZE));
11191   CU_ASSERT(0 == stream->recv_window_size);
11192   CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE ==
11193             nghttp2_session_get_stream_local_window_size(session, 1));
11194 
11195   item = nghttp2_session_get_next_ob_item(session);
11196 
11197   CU_ASSERT(NGHTTP2_WINDOW_UPDATE == item->frame.hd.type);
11198   CU_ASSERT(1 == item->frame.hd.stream_id);
11199   CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE ==
11200             item->frame.window_update.window_size_increment);
11201 
11202   nghttp2_session_del(session);
11203 
11204   /* Make sure that nghttp2_session_set_local_window_size submits
11205      WINDOW_UPDATE if necessary to increase connection-level
11206      window. */
11207   nghttp2_session_client_new(&session, &callbacks, NULL);
11208   session->recv_window_size = NGHTTP2_INITIAL_WINDOW_SIZE;
11209 
11210   CU_ASSERT(0 == nghttp2_session_set_local_window_size(
11211                      session, NGHTTP2_FLAG_NONE, 0, 0));
11212   CU_ASSERT(0 == session->recv_window_size);
11213   CU_ASSERT(0 == nghttp2_session_get_local_window_size(session));
11214   /* This should submit WINDOW_UPDATE frame because connection-level
11215      receiving window is now full. */
11216   CU_ASSERT(0 ==
11217             nghttp2_session_set_local_window_size(session, NGHTTP2_FLAG_NONE, 0,
11218                                                   NGHTTP2_INITIAL_WINDOW_SIZE));
11219   CU_ASSERT(0 == session->recv_window_size);
11220   CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE ==
11221             nghttp2_session_get_local_window_size(session));
11222 
11223   item = nghttp2_session_get_next_ob_item(session);
11224 
11225   CU_ASSERT(NGHTTP2_WINDOW_UPDATE == item->frame.hd.type);
11226   CU_ASSERT(0 == item->frame.hd.stream_id);
11227   CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE ==
11228             item->frame.window_update.window_size_increment);
11229 
11230   nghttp2_session_del(session);
11231 }
11232 
test_nghttp2_session_cancel_from_before_frame_send(void)11233 void test_nghttp2_session_cancel_from_before_frame_send(void) {
11234   int rv;
11235   nghttp2_session *session;
11236   nghttp2_session_callbacks callbacks;
11237   my_user_data ud;
11238   nghttp2_settings_entry iv;
11239   nghttp2_data_provider data_prd;
11240   int32_t stream_id;
11241   nghttp2_stream *stream;
11242 
11243   memset(&callbacks, 0, sizeof(callbacks));
11244 
11245   callbacks.before_frame_send_callback = cancel_before_frame_send_callback;
11246   callbacks.on_frame_not_send_callback = on_frame_not_send_callback;
11247   callbacks.send_callback = null_send_callback;
11248 
11249   nghttp2_session_client_new(&session, &callbacks, &ud);
11250 
11251   iv.settings_id = 0;
11252   iv.value = 1000000009;
11253 
11254   rv = nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, &iv, 1);
11255 
11256   CU_ASSERT(0 == rv);
11257 
11258   ud.frame_send_cb_called = 0;
11259   ud.before_frame_send_cb_called = 0;
11260   ud.frame_not_send_cb_called = 0;
11261 
11262   rv = nghttp2_session_send(session);
11263 
11264   CU_ASSERT(0 == rv);
11265   CU_ASSERT(0 == ud.frame_send_cb_called);
11266   CU_ASSERT(1 == ud.before_frame_send_cb_called);
11267   CU_ASSERT(1 == ud.frame_not_send_cb_called);
11268 
11269   data_prd.source.ptr = NULL;
11270   data_prd.read_callback = temporal_failure_data_source_read_callback;
11271 
11272   stream_id = nghttp2_submit_request(session, NULL, reqnv, ARRLEN(reqnv),
11273                                      &data_prd, NULL);
11274 
11275   CU_ASSERT(stream_id > 0);
11276 
11277   ud.frame_send_cb_called = 0;
11278   ud.before_frame_send_cb_called = 0;
11279   ud.frame_not_send_cb_called = 0;
11280 
11281   rv = nghttp2_session_send(session);
11282 
11283   CU_ASSERT(0 == rv);
11284   CU_ASSERT(0 == ud.frame_send_cb_called);
11285   CU_ASSERT(1 == ud.before_frame_send_cb_called);
11286   CU_ASSERT(1 == ud.frame_not_send_cb_called);
11287 
11288   stream = nghttp2_session_get_stream_raw(session, stream_id);
11289 
11290   CU_ASSERT(NULL == stream);
11291 
11292   nghttp2_session_del(session);
11293 
11294   nghttp2_session_server_new(&session, &callbacks, &ud);
11295 
11296   open_recv_stream(session, 1);
11297 
11298   stream_id = nghttp2_submit_push_promise(session, NGHTTP2_FLAG_NONE, 1, reqnv,
11299                                           ARRLEN(reqnv), NULL);
11300 
11301   CU_ASSERT(stream_id > 0);
11302 
11303   ud.frame_send_cb_called = 0;
11304   ud.before_frame_send_cb_called = 0;
11305   ud.frame_not_send_cb_called = 0;
11306 
11307   rv = nghttp2_session_send(session);
11308 
11309   CU_ASSERT(0 == rv);
11310   CU_ASSERT(0 == ud.frame_send_cb_called);
11311   CU_ASSERT(1 == ud.before_frame_send_cb_called);
11312   CU_ASSERT(1 == ud.frame_not_send_cb_called);
11313 
11314   stream = nghttp2_session_get_stream_raw(session, stream_id);
11315 
11316   CU_ASSERT(NULL == stream);
11317 
11318   nghttp2_session_del(session);
11319 }
11320 
test_nghttp2_session_too_many_settings(void)11321 void test_nghttp2_session_too_many_settings(void) {
11322   nghttp2_session *session;
11323   nghttp2_option *option;
11324   nghttp2_session_callbacks callbacks;
11325   nghttp2_frame frame;
11326   nghttp2_bufs bufs;
11327   nghttp2_buf *buf;
11328   ssize_t rv;
11329   my_user_data ud;
11330   nghttp2_settings_entry iv[3];
11331   nghttp2_mem *mem;
11332   nghttp2_outbound_item *item;
11333 
11334   mem = nghttp2_mem_default();
11335   frame_pack_bufs_init(&bufs);
11336 
11337   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
11338   callbacks.on_frame_recv_callback = on_frame_recv_callback;
11339   callbacks.send_callback = null_send_callback;
11340 
11341   nghttp2_option_new(&option);
11342   nghttp2_option_set_max_settings(option, 1);
11343 
11344   nghttp2_session_client_new2(&session, &callbacks, &ud, option);
11345 
11346   CU_ASSERT(1 == session->max_settings);
11347 
11348   nghttp2_option_del(option);
11349 
11350   iv[0].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
11351   iv[0].value = 3000;
11352 
11353   iv[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
11354   iv[1].value = 16384;
11355 
11356   nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE, dup_iv(iv, 2),
11357                               2);
11358 
11359   rv = nghttp2_frame_pack_settings(&bufs, &frame.settings);
11360 
11361   CU_ASSERT(0 == rv);
11362   CU_ASSERT(nghttp2_bufs_len(&bufs) > 0);
11363 
11364   nghttp2_frame_settings_free(&frame.settings, mem);
11365 
11366   buf = &bufs.head->buf;
11367   assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
11368 
11369   ud.frame_recv_cb_called = 0;
11370 
11371   rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
11372   CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv);
11373 
11374   item = nghttp2_session_get_next_ob_item(session);
11375   CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
11376 
11377   nghttp2_bufs_reset(&bufs);
11378   nghttp2_bufs_free(&bufs);
11379   nghttp2_session_del(session);
11380 }
11381 
11382 static void
prepare_session_removed_closed_stream(nghttp2_session * session,nghttp2_hd_deflater * deflater)11383 prepare_session_removed_closed_stream(nghttp2_session *session,
11384                                       nghttp2_hd_deflater *deflater) {
11385   int rv;
11386   nghttp2_settings_entry iv;
11387   nghttp2_bufs bufs;
11388   nghttp2_mem *mem;
11389   ssize_t nread;
11390   int i;
11391   nghttp2_stream *stream;
11392   nghttp2_frame_hd hd;
11393 
11394   mem = nghttp2_mem_default();
11395 
11396   frame_pack_bufs_init(&bufs);
11397 
11398   iv.settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS;
11399   iv.value = 2;
11400 
11401   rv = nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, &iv, 1);
11402 
11403   CU_ASSERT(0 == rv);
11404 
11405   rv = nghttp2_session_send(session);
11406 
11407   CU_ASSERT(0 == rv);
11408 
11409   for (i = 1; i <= 3; i += 2) {
11410     rv = pack_headers(&bufs, deflater, i,
11411                       NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM, reqnv,
11412                       ARRLEN(reqnv), mem);
11413 
11414     CU_ASSERT(0 == rv);
11415 
11416     nread = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11417                                      nghttp2_bufs_len(&bufs));
11418 
11419     CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == nread);
11420 
11421     nghttp2_bufs_reset(&bufs);
11422   }
11423 
11424   nghttp2_session_close_stream(session, 3, NGHTTP2_NO_ERROR);
11425 
11426   rv = pack_headers(&bufs, deflater, 5,
11427                     NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM, reqnv,
11428                     ARRLEN(reqnv), mem);
11429 
11430   CU_ASSERT(0 == rv);
11431 
11432   /* Receiving stream 5 will erase stream 3 from closed stream list */
11433   nread = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11434                                    nghttp2_bufs_len(&bufs));
11435 
11436   CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == nread);
11437 
11438   stream = nghttp2_session_get_stream_raw(session, 3);
11439 
11440   CU_ASSERT(NULL == stream);
11441 
11442   /* Since the current max concurrent streams is
11443      NGHTTP2_DEFAULT_MAX_CONCURRENT_STREAMS, receiving frame on stream
11444      3 is ignored. */
11445   nghttp2_bufs_reset(&bufs);
11446   rv = pack_headers(&bufs, deflater, 3,
11447                     NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM,
11448                     trailernv, ARRLEN(trailernv), mem);
11449 
11450   CU_ASSERT(0 == rv);
11451 
11452   nread = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11453                                    nghttp2_bufs_len(&bufs));
11454 
11455   CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == nread);
11456   CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
11457 
11458   nghttp2_frame_hd_init(&hd, 0, NGHTTP2_DATA, NGHTTP2_FLAG_NONE, 3);
11459   nghttp2_bufs_reset(&bufs);
11460   nghttp2_frame_pack_frame_hd(bufs.head->buf.last, &hd);
11461   bufs.head->buf.last += NGHTTP2_FRAME_HDLEN;
11462 
11463   nread = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11464                                    nghttp2_bufs_len(&bufs));
11465 
11466   CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == nread);
11467   CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
11468 
11469   /* Now server receives SETTINGS ACK */
11470   nghttp2_frame_hd_init(&hd, 0, NGHTTP2_SETTINGS, NGHTTP2_FLAG_ACK, 0);
11471   nghttp2_bufs_reset(&bufs);
11472   nghttp2_frame_pack_frame_hd(bufs.head->buf.last, &hd);
11473   bufs.head->buf.last += NGHTTP2_FRAME_HDLEN;
11474 
11475   nread = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11476                                    nghttp2_bufs_len(&bufs));
11477 
11478   CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == nread);
11479 
11480   nghttp2_bufs_free(&bufs);
11481 }
11482 
test_nghttp2_session_removed_closed_stream(void)11483 void test_nghttp2_session_removed_closed_stream(void) {
11484   nghttp2_session *session;
11485   nghttp2_session_callbacks callbacks;
11486   int rv;
11487   nghttp2_hd_deflater deflater;
11488   nghttp2_bufs bufs;
11489   nghttp2_mem *mem;
11490   ssize_t nread;
11491   nghttp2_frame_hd hd;
11492   nghttp2_outbound_item *item;
11493 
11494   mem = nghttp2_mem_default();
11495 
11496   frame_pack_bufs_init(&bufs);
11497 
11498   memset(&callbacks, 0, sizeof(callbacks));
11499 
11500   callbacks.send_callback = null_send_callback;
11501 
11502   nghttp2_session_server_new(&session, &callbacks, NULL);
11503 
11504   /* Now local max concurrent streams is still unlimited, pending max
11505      concurrent streams is now 2. */
11506 
11507   nghttp2_hd_deflate_init(&deflater, mem);
11508 
11509   prepare_session_removed_closed_stream(session, &deflater);
11510 
11511   /* Now current max concurrent streams is 2.  Receiving frame on
11512      stream 3 is ignored because we have no stream object for stream
11513      3. */
11514   nghttp2_bufs_reset(&bufs);
11515   rv = pack_headers(&bufs, &deflater, 3,
11516                     NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM,
11517                     trailernv, ARRLEN(trailernv), mem);
11518 
11519   CU_ASSERT(0 == rv);
11520 
11521   nread = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11522                                    nghttp2_bufs_len(&bufs));
11523 
11524   CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == nread);
11525 
11526   item = nghttp2_session_get_next_ob_item(session);
11527 
11528   CU_ASSERT(NULL == item);
11529 
11530   nghttp2_hd_deflate_free(&deflater);
11531   nghttp2_session_del(session);
11532 
11533   nghttp2_session_server_new(&session, &callbacks, NULL);
11534   nghttp2_hd_deflate_init(&deflater, mem);
11535   /* Same setup, and then receive DATA instead of HEADERS */
11536 
11537   prepare_session_removed_closed_stream(session, &deflater);
11538 
11539   nghttp2_frame_hd_init(&hd, 0, NGHTTP2_DATA, NGHTTP2_FLAG_NONE, 3);
11540   nghttp2_bufs_reset(&bufs);
11541   nghttp2_frame_pack_frame_hd(bufs.head->buf.last, &hd);
11542   bufs.head->buf.last += NGHTTP2_FRAME_HDLEN;
11543 
11544   nread = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11545                                    nghttp2_bufs_len(&bufs));
11546 
11547   CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == nread);
11548 
11549   item = nghttp2_session_get_next_ob_item(session);
11550 
11551   CU_ASSERT(NULL == item);
11552 
11553   nghttp2_hd_deflate_free(&deflater);
11554   nghttp2_session_del(session);
11555 
11556   nghttp2_bufs_free(&bufs);
11557 }
11558 
pause_once_data_source_read_callback(nghttp2_session * session,int32_t stream_id,uint8_t * buf,size_t len,uint32_t * data_flags,nghttp2_data_source * source,void * user_data)11559 static ssize_t pause_once_data_source_read_callback(
11560     nghttp2_session *session, int32_t stream_id, uint8_t *buf, size_t len,
11561     uint32_t *data_flags, nghttp2_data_source *source, void *user_data) {
11562   my_user_data *ud = user_data;
11563   if (ud->data_source_read_cb_paused == 0) {
11564     ++ud->data_source_read_cb_paused;
11565     return NGHTTP2_ERR_PAUSE;
11566   }
11567 
11568   return fixed_length_data_source_read_callback(session, stream_id, buf, len,
11569                                                 data_flags, source, user_data);
11570 }
11571 
test_nghttp2_session_pause_data(void)11572 void test_nghttp2_session_pause_data(void) {
11573   nghttp2_session *session;
11574   nghttp2_session_callbacks callbacks;
11575   nghttp2_data_provider data_prd;
11576   my_user_data ud;
11577 
11578   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
11579   callbacks.send_callback = null_send_callback;
11580   callbacks.on_frame_send_callback = on_frame_send_callback;
11581 
11582   data_prd.read_callback = pause_once_data_source_read_callback;
11583   ud.data_source_length = NGHTTP2_DATA_PAYLOADLEN;
11584 
11585   nghttp2_session_server_new(&session, &callbacks, &ud);
11586 
11587   open_recv_stream(session, 1);
11588 
11589   CU_ASSERT(
11590       0 == nghttp2_submit_data(session, NGHTTP2_FLAG_END_STREAM, 1, &data_prd));
11591 
11592   ud.frame_send_cb_called = 0;
11593   ud.data_source_read_cb_paused = 0;
11594 
11595   CU_ASSERT(0 == nghttp2_session_send(session));
11596   CU_ASSERT(0 == ud.frame_send_cb_called);
11597   CU_ASSERT(NULL == session->aob.item);
11598   CU_ASSERT(0 == nghttp2_session_send(session));
11599   CU_ASSERT(1 == ud.frame_send_cb_called);
11600   CU_ASSERT(NGHTTP2_DATA == ud.sent_frame_type);
11601   CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
11602 
11603   nghttp2_session_del(session);
11604 }
11605 
test_nghttp2_session_no_closed_streams(void)11606 void test_nghttp2_session_no_closed_streams(void) {
11607   nghttp2_session *session;
11608   nghttp2_session_callbacks callbacks;
11609   nghttp2_option *option;
11610 
11611   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
11612 
11613   nghttp2_option_new(&option);
11614   nghttp2_option_set_no_closed_streams(option, 1);
11615 
11616   nghttp2_session_server_new2(&session, &callbacks, NULL, option);
11617 
11618   open_recv_stream(session, 1);
11619 
11620   nghttp2_session_close_stream(session, 1, NGHTTP2_NO_ERROR);
11621 
11622   CU_ASSERT(0 == session->num_closed_streams);
11623 
11624   nghttp2_session_del(session);
11625   nghttp2_option_del(option);
11626 }
11627 
test_nghttp2_session_set_stream_user_data(void)11628 void test_nghttp2_session_set_stream_user_data(void) {
11629   nghttp2_session *session;
11630   nghttp2_session_callbacks callbacks;
11631   int32_t stream_id;
11632   int user_data1, user_data2;
11633   int rv;
11634   const uint8_t *datap;
11635   ssize_t datalen;
11636 
11637   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
11638 
11639   nghttp2_session_client_new(&session, &callbacks, NULL);
11640 
11641   stream_id = nghttp2_submit_request(session, NULL, reqnv, ARRLEN(reqnv), NULL,
11642                                      &user_data1);
11643 
11644   rv = nghttp2_session_set_stream_user_data(session, stream_id, &user_data2);
11645 
11646   CU_ASSERT(0 == rv);
11647 
11648   datalen = nghttp2_session_mem_send(session, &datap);
11649 
11650   CU_ASSERT(datalen > 0);
11651 
11652   CU_ASSERT(&user_data2 ==
11653             nghttp2_session_get_stream_user_data(session, stream_id));
11654 
11655   CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT ==
11656             nghttp2_session_set_stream_user_data(session, 2, NULL));
11657 
11658   nghttp2_session_del(session);
11659 }
11660 
test_nghttp2_session_no_rfc7540_priorities(void)11661 void test_nghttp2_session_no_rfc7540_priorities(void) {
11662   nghttp2_session *session;
11663   nghttp2_session_callbacks callbacks;
11664   nghttp2_data_provider data_prd;
11665   my_user_data ud;
11666   nghttp2_outbound_item *item;
11667   nghttp2_mem *mem;
11668   nghttp2_settings_entry iv;
11669   nghttp2_priority_spec pri_spec;
11670 
11671   mem = nghttp2_mem_default();
11672 
11673   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
11674   callbacks.send_callback = null_send_callback;
11675 
11676   /* Do not use a dependency tree if SETTINGS_NO_RFC7540_PRIORITIES =
11677      1. */
11678   data_prd.read_callback = fixed_length_data_source_read_callback;
11679 
11680   ud.data_source_length = 128 * 1024;
11681   CU_ASSERT(0 == nghttp2_session_server_new(&session, &callbacks, &ud));
11682 
11683   iv.settings_id = NGHTTP2_SETTINGS_NO_RFC7540_PRIORITIES;
11684   iv.value = 1;
11685 
11686   CU_ASSERT(0 == nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, &iv, 1));
11687   CU_ASSERT(0 == nghttp2_session_send(session));
11688 
11689   open_recv_stream2(session, 1, NGHTTP2_STREAM_OPENING);
11690   CU_ASSERT(0 == nghttp2_submit_response(session, 1, resnv, ARRLEN(resnv),
11691                                          &data_prd));
11692   item = nghttp2_session_get_next_ob_item(session);
11693   CU_ASSERT(ARRLEN(resnv) == item->frame.headers.nvlen);
11694   assert_nv_equal(resnv, item->frame.headers.nva, item->frame.headers.nvlen,
11695                   mem);
11696 
11697   CU_ASSERT(0 == nghttp2_session_send(session));
11698   CU_ASSERT(1 == nghttp2_pq_size(
11699                      &session->sched[NGHTTP2_EXTPRI_DEFAULT_URGENCY].ob_data));
11700   CU_ASSERT(nghttp2_pq_empty(&session->root.obq));
11701 
11702   nghttp2_session_del(session);
11703 
11704   /* Priorities are sent as is before client receives
11705      SETTINGS_NO_RFC7540_PRIORITIES = 1 from server. */
11706   CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, NULL));
11707 
11708   iv.settings_id = NGHTTP2_SETTINGS_NO_RFC7540_PRIORITIES;
11709   iv.value = 1;
11710 
11711   CU_ASSERT(0 == nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, &iv, 1));
11712 
11713   pri_spec.stream_id = 5;
11714   pri_spec.weight = 111;
11715   pri_spec.exclusive = 1;
11716 
11717   CU_ASSERT(1 == nghttp2_submit_request(session, &pri_spec, reqnv,
11718                                         ARRLEN(reqnv), NULL, NULL));
11719 
11720   item = nghttp2_outbound_queue_top(&session->ob_syn);
11721 
11722   CU_ASSERT(NULL != item);
11723   CU_ASSERT(NGHTTP2_HEADERS == item->frame.hd.type);
11724   CU_ASSERT(pri_spec.stream_id == item->frame.headers.pri_spec.stream_id);
11725   CU_ASSERT(pri_spec.weight == item->frame.headers.pri_spec.weight);
11726   CU_ASSERT(pri_spec.exclusive == item->frame.headers.pri_spec.exclusive);
11727 
11728   nghttp2_session_del(session);
11729 
11730   /* Priorities are defaulted if client received
11731      SETTINGS_NO_RFC7540_PRIORITIES = 1 from server. */
11732   CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, NULL));
11733 
11734   iv.settings_id = NGHTTP2_SETTINGS_NO_RFC7540_PRIORITIES;
11735   iv.value = 1;
11736 
11737   CU_ASSERT(0 == nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, &iv, 1));
11738 
11739   session->remote_settings.no_rfc7540_priorities = 1;
11740 
11741   pri_spec.stream_id = 5;
11742   pri_spec.weight = 111;
11743   pri_spec.exclusive = 1;
11744 
11745   CU_ASSERT(1 == nghttp2_submit_request(session, &pri_spec, reqnv,
11746                                         ARRLEN(reqnv), NULL, NULL));
11747 
11748   item = nghttp2_outbound_queue_top(&session->ob_syn);
11749 
11750   CU_ASSERT(NULL != item);
11751   CU_ASSERT(NGHTTP2_HEADERS == item->frame.hd.type);
11752   CU_ASSERT(nghttp2_priority_spec_check_default(&item->frame.headers.pri_spec));
11753 
11754   nghttp2_session_del(session);
11755 }
11756 
test_nghttp2_session_server_fallback_rfc7540_priorities(void)11757 void test_nghttp2_session_server_fallback_rfc7540_priorities(void) {
11758   nghttp2_session *session;
11759   nghttp2_option *option;
11760   nghttp2_session_callbacks callbacks;
11761   nghttp2_frame frame;
11762   nghttp2_bufs bufs;
11763   nghttp2_buf *buf;
11764   ssize_t rv;
11765   nghttp2_settings_entry iv;
11766   nghttp2_mem *mem;
11767   nghttp2_hd_deflater deflater;
11768   nghttp2_nv *nva;
11769   size_t nvlen;
11770   nghttp2_priority_spec pri_spec;
11771   nghttp2_stream *anchor_stream, *stream;
11772   my_user_data ud;
11773   nghttp2_ext_priority_update priority_update;
11774   static const uint8_t field_value[] = "u=0";
11775 
11776   mem = nghttp2_mem_default();
11777   frame_pack_bufs_init(&bufs);
11778 
11779   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
11780   callbacks.send_callback = null_send_callback;
11781   callbacks.on_frame_recv_callback = on_frame_recv_callback;
11782 
11783   nghttp2_option_new(&option);
11784   nghttp2_option_set_server_fallback_rfc7540_priorities(option, 1);
11785 
11786   iv.settings_id = NGHTTP2_SETTINGS_NO_RFC7540_PRIORITIES;
11787   iv.value = 1;
11788 
11789   /* Server falls back to RFC 7540 priorities. */
11790   nghttp2_session_server_new2(&session, &callbacks, &ud, option);
11791 
11792   rv = nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, &iv, 1);
11793 
11794   CU_ASSERT(0 == rv);
11795 
11796   rv = nghttp2_session_send(session);
11797 
11798   CU_ASSERT(0 == rv);
11799 
11800   nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE, NULL, 0);
11801   rv = nghttp2_frame_pack_settings(&bufs, &frame.settings);
11802 
11803   CU_ASSERT(0 == rv);
11804 
11805   nghttp2_frame_settings_free(&frame.settings, mem);
11806 
11807   buf = &bufs.head->buf;
11808   rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
11809 
11810   CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv);
11811   CU_ASSERT(1 == session->fallback_rfc7540_priorities);
11812 
11813   nghttp2_hd_deflate_init(&deflater, mem);
11814 
11815   nvlen = ARRLEN(reqnv);
11816   nghttp2_nv_array_copy(&nva, reqnv, nvlen, mem);
11817   nghttp2_priority_spec_init(&pri_spec, 3, 111, 1);
11818   nghttp2_frame_headers_init(&frame.headers,
11819                              NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PRIORITY,
11820                              1, NGHTTP2_HCAT_HEADERS, &pri_spec, nva, nvlen);
11821   nghttp2_bufs_reset(&bufs);
11822   rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
11823 
11824   CU_ASSERT(0 == rv);
11825 
11826   nghttp2_frame_headers_free(&frame.headers, mem);
11827 
11828   buf = &bufs.head->buf;
11829   rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
11830 
11831   CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv);
11832 
11833   anchor_stream = nghttp2_session_get_stream_raw(session, 3);
11834 
11835   CU_ASSERT(NGHTTP2_STREAM_IDLE == anchor_stream->state);
11836   CU_ASSERT(
11837       !(anchor_stream->flags & NGHTTP2_STREAM_FLAG_NO_RFC7540_PRIORITIES));
11838   CU_ASSERT(&session->root == anchor_stream->dep_prev);
11839 
11840   stream = nghttp2_session_get_stream(session, 1);
11841 
11842   CU_ASSERT(NGHTTP2_STREAM_OPENING == stream->state);
11843   CU_ASSERT(!(stream->flags & NGHTTP2_STREAM_FLAG_NO_RFC7540_PRIORITIES));
11844   CU_ASSERT(anchor_stream == stream->dep_prev);
11845 
11846   /* Make sure that PRIORITY frame updates stream priority. */
11847   nghttp2_priority_spec_init(&pri_spec, 5, 1, 0);
11848   nghttp2_frame_priority_init(&frame.priority, 1, &pri_spec);
11849   nghttp2_bufs_reset(&bufs);
11850   rv = nghttp2_frame_pack_priority(&bufs, &frame.priority);
11851 
11852   CU_ASSERT(0 == rv);
11853 
11854   nghttp2_frame_priority_free(&frame.priority);
11855 
11856   buf = &bufs.head->buf;
11857   rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
11858 
11859   CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv);
11860 
11861   anchor_stream = nghttp2_session_get_stream_raw(session, 5);
11862 
11863   CU_ASSERT(NGHTTP2_STREAM_IDLE == anchor_stream->state);
11864   CU_ASSERT(&session->root == anchor_stream->dep_prev);
11865   CU_ASSERT(anchor_stream == stream->dep_prev);
11866 
11867   /* Make sure that PRIORITY_UPDATE frame is ignored. */
11868   frame.ext.payload = &priority_update;
11869   nghttp2_frame_priority_update_init(&frame.ext, 1, (uint8_t *)field_value,
11870                                      sizeof(field_value) - 1);
11871   nghttp2_bufs_reset(&bufs);
11872   nghttp2_frame_pack_priority_update(&bufs, &frame.ext);
11873 
11874   ud.frame_recv_cb_called = 0;
11875   buf = &bufs.head->buf;
11876   rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
11877 
11878   CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv);
11879   CU_ASSERT(0 == ud.frame_recv_cb_called);
11880   CU_ASSERT(NGHTTP2_EXTPRI_DEFAULT_URGENCY == stream->extpri);
11881 
11882   nghttp2_hd_deflate_free(&deflater);
11883   nghttp2_session_del(session);
11884 
11885   /* Server does not fallback to RFC 7540 priorities. */
11886   nghttp2_session_server_new2(&session, &callbacks, &ud, option);
11887 
11888   rv = nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, &iv, 1);
11889 
11890   CU_ASSERT(0 == rv);
11891 
11892   rv = nghttp2_session_send(session);
11893 
11894   CU_ASSERT(0 == rv);
11895 
11896   iv.settings_id = NGHTTP2_SETTINGS_NO_RFC7540_PRIORITIES;
11897   iv.value = 0;
11898 
11899   nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE,
11900                               dup_iv(&iv, 1), 1);
11901   nghttp2_bufs_reset(&bufs);
11902   rv = nghttp2_frame_pack_settings(&bufs, &frame.settings);
11903 
11904   CU_ASSERT(0 == rv);
11905 
11906   nghttp2_frame_settings_free(&frame.settings, mem);
11907 
11908   buf = &bufs.head->buf;
11909   rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
11910 
11911   CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv);
11912   CU_ASSERT(0 == session->fallback_rfc7540_priorities);
11913 
11914   nghttp2_hd_deflate_init(&deflater, mem);
11915 
11916   nvlen = ARRLEN(reqnv);
11917   nghttp2_nv_array_copy(&nva, reqnv, nvlen, mem);
11918   nghttp2_priority_spec_init(&pri_spec, 3, 111, 1);
11919   nghttp2_frame_headers_init(&frame.headers,
11920                              NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PRIORITY,
11921                              1, NGHTTP2_HCAT_HEADERS, &pri_spec, nva, nvlen);
11922   nghttp2_bufs_reset(&bufs);
11923   rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
11924 
11925   CU_ASSERT(0 == rv);
11926 
11927   nghttp2_frame_headers_free(&frame.headers, mem);
11928 
11929   buf = &bufs.head->buf;
11930   rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
11931 
11932   CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv);
11933   CU_ASSERT(NULL == nghttp2_session_get_stream_raw(session, 3));
11934 
11935   stream = nghttp2_session_get_stream(session, 1);
11936 
11937   CU_ASSERT(NGHTTP2_STREAM_OPENING == stream->state);
11938   CU_ASSERT(stream->flags & NGHTTP2_STREAM_FLAG_NO_RFC7540_PRIORITIES);
11939 
11940   nghttp2_hd_deflate_free(&deflater);
11941   nghttp2_session_del(session);
11942 
11943   nghttp2_option_del(option);
11944   nghttp2_bufs_free(&bufs);
11945 }
11946 
test_nghttp2_session_stream_reset_ratelim(void)11947 void test_nghttp2_session_stream_reset_ratelim(void) {
11948   nghttp2_session *session;
11949   nghttp2_session_callbacks callbacks;
11950   nghttp2_frame frame;
11951   ssize_t rv;
11952   nghttp2_bufs bufs;
11953   nghttp2_buf *buf;
11954   nghttp2_mem *mem;
11955   size_t i;
11956   nghttp2_hd_deflater deflater;
11957   size_t nvlen;
11958   nghttp2_nv *nva;
11959   int32_t stream_id;
11960   nghttp2_outbound_item *item;
11961   nghttp2_option *option;
11962 
11963   mem = nghttp2_mem_default();
11964   frame_pack_bufs_init(&bufs);
11965 
11966   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
11967   callbacks.send_callback = null_send_callback;
11968 
11969   nghttp2_option_new(&option);
11970   nghttp2_option_set_stream_reset_rate_limit(
11971       option, NGHTTP2_DEFAULT_STREAM_RESET_BURST, 0);
11972 
11973   nghttp2_session_server_new2(&session, &callbacks, NULL, option);
11974 
11975   nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE, NULL, 0);
11976   rv = nghttp2_frame_pack_settings(&bufs, &frame.settings);
11977 
11978   CU_ASSERT(0 == rv);
11979 
11980   nghttp2_frame_settings_free(&frame.settings, mem);
11981 
11982   buf = &bufs.head->buf;
11983   rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
11984 
11985   CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv);
11986 
11987   /* Send SETTINGS ACK */
11988   rv = nghttp2_session_send(session);
11989 
11990   CU_ASSERT(0 == rv);
11991 
11992   nghttp2_hd_deflate_init(&deflater, mem);
11993 
11994   for (i = 0; i < NGHTTP2_DEFAULT_STREAM_RESET_BURST + 2; ++i) {
11995     stream_id = (int32_t)(i * 2 + 1);
11996 
11997     nghttp2_bufs_reset(&bufs);
11998 
11999     /* HEADERS */
12000     nvlen = ARRLEN(reqnv);
12001     nghttp2_nv_array_copy(&nva, reqnv, nvlen, mem);
12002     nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS,
12003                                stream_id, NGHTTP2_HCAT_HEADERS, NULL, nva,
12004                                nvlen);
12005     rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
12006 
12007     CU_ASSERT(0 == rv);
12008 
12009     nghttp2_frame_headers_free(&frame.headers, mem);
12010 
12011     buf = &bufs.head->buf;
12012     rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
12013 
12014     CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv);
12015 
12016     nghttp2_bufs_reset(&bufs);
12017 
12018     /* RST_STREAM */
12019     nghttp2_frame_rst_stream_init(&frame.rst_stream, stream_id,
12020                                   NGHTTP2_NO_ERROR);
12021     nghttp2_frame_pack_rst_stream(&bufs, &frame.rst_stream);
12022     nghttp2_frame_rst_stream_free(&frame.rst_stream);
12023 
12024     buf = &bufs.head->buf;
12025     rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
12026 
12027     CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv);
12028 
12029     if (i < NGHTTP2_DEFAULT_STREAM_RESET_BURST) {
12030       CU_ASSERT(0 == nghttp2_outbound_queue_size(&session->ob_reg));
12031 
12032       continue;
12033     }
12034 
12035     CU_ASSERT(1 == nghttp2_outbound_queue_size(&session->ob_reg));
12036 
12037     item = nghttp2_session_get_next_ob_item(session);
12038 
12039     CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
12040     CU_ASSERT(NGHTTP2_DEFAULT_STREAM_RESET_BURST * 2 + 1 ==
12041               item->frame.goaway.last_stream_id);
12042   }
12043 
12044   nghttp2_hd_deflate_free(&deflater);
12045   nghttp2_session_del(session);
12046   nghttp2_bufs_free(&bufs);
12047   nghttp2_option_del(option);
12048 }
12049 
check_nghttp2_http_recv_headers_fail(nghttp2_session * session,nghttp2_hd_deflater * deflater,int32_t stream_id,int stream_state,const nghttp2_nv * nva,size_t nvlen)12050 static void check_nghttp2_http_recv_headers_fail(
12051     nghttp2_session *session, nghttp2_hd_deflater *deflater, int32_t stream_id,
12052     int stream_state, const nghttp2_nv *nva, size_t nvlen) {
12053   nghttp2_mem *mem;
12054   ssize_t rv;
12055   nghttp2_outbound_item *item;
12056   nghttp2_bufs bufs;
12057   my_user_data *ud;
12058 
12059   mem = nghttp2_mem_default();
12060   frame_pack_bufs_init(&bufs);
12061 
12062   ud = session->user_data;
12063 
12064   if (stream_state != -1) {
12065     if (nghttp2_session_is_my_stream_id(session, stream_id)) {
12066       open_sent_stream2(session, stream_id, (nghttp2_stream_state)stream_state);
12067     } else {
12068       open_recv_stream2(session, stream_id, (nghttp2_stream_state)stream_state);
12069     }
12070   }
12071 
12072   rv = pack_headers(&bufs, deflater, stream_id, NGHTTP2_FLAG_END_HEADERS, nva,
12073                     nvlen, mem);
12074   CU_ASSERT(0 == rv);
12075 
12076   ud->invalid_frame_recv_cb_called = 0;
12077 
12078   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
12079                                 nghttp2_buf_len(&bufs.head->buf));
12080 
12081   CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
12082 
12083   item = nghttp2_session_get_next_ob_item(session);
12084 
12085   CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
12086   CU_ASSERT(1 == ud->invalid_frame_recv_cb_called);
12087 
12088   CU_ASSERT(0 == nghttp2_session_send(session));
12089 
12090   nghttp2_bufs_free(&bufs);
12091 }
12092 
check_nghttp2_http_recv_headers_ok(nghttp2_session * session,nghttp2_hd_deflater * deflater,int32_t stream_id,int stream_state,const nghttp2_nv * nva,size_t nvlen)12093 static void check_nghttp2_http_recv_headers_ok(
12094     nghttp2_session *session, nghttp2_hd_deflater *deflater, int32_t stream_id,
12095     int stream_state, const nghttp2_nv *nva, size_t nvlen) {
12096   nghttp2_mem *mem;
12097   ssize_t rv;
12098   nghttp2_bufs bufs;
12099   my_user_data *ud;
12100 
12101   mem = nghttp2_mem_default();
12102   frame_pack_bufs_init(&bufs);
12103 
12104   ud = session->user_data;
12105 
12106   if (stream_state != -1) {
12107     if (nghttp2_session_is_my_stream_id(session, stream_id)) {
12108       open_sent_stream2(session, stream_id, (nghttp2_stream_state)stream_state);
12109     } else {
12110       open_recv_stream2(session, stream_id, (nghttp2_stream_state)stream_state);
12111     }
12112   }
12113 
12114   rv = pack_headers(&bufs, deflater, stream_id, NGHTTP2_FLAG_END_HEADERS, nva,
12115                     nvlen, mem);
12116   CU_ASSERT(0 == rv);
12117 
12118   ud->frame_recv_cb_called = 0;
12119 
12120   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
12121                                 nghttp2_buf_len(&bufs.head->buf));
12122 
12123   CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
12124   CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
12125   CU_ASSERT(1 == ud->frame_recv_cb_called);
12126 
12127   nghttp2_bufs_free(&bufs);
12128 }
12129 
test_nghttp2_http_mandatory_headers(void)12130 void test_nghttp2_http_mandatory_headers(void) {
12131   nghttp2_session *session;
12132   nghttp2_session_callbacks callbacks;
12133   nghttp2_hd_deflater deflater;
12134   nghttp2_mem *mem;
12135   my_user_data ud;
12136   /* test case for response */
12137   const nghttp2_nv nostatus_resnv[] = {MAKE_NV("server", "foo")};
12138   const nghttp2_nv dupstatus_resnv[] = {MAKE_NV(":status", "200"),
12139                                         MAKE_NV(":status", "200")};
12140   const nghttp2_nv badpseudo_resnv[] = {MAKE_NV(":status", "200"),
12141                                         MAKE_NV(":scheme", "https")};
12142   const nghttp2_nv latepseudo_resnv[] = {MAKE_NV("server", "foo"),
12143                                          MAKE_NV(":status", "200")};
12144   const nghttp2_nv badstatus_resnv[] = {MAKE_NV(":status", "2000")};
12145   const nghttp2_nv badcl_resnv[] = {MAKE_NV(":status", "200"),
12146                                     MAKE_NV("content-length", "-1")};
12147   const nghttp2_nv dupcl_resnv[] = {MAKE_NV(":status", "200"),
12148                                     MAKE_NV("content-length", "0"),
12149                                     MAKE_NV("content-length", "0")};
12150   const nghttp2_nv badhd_resnv[] = {MAKE_NV(":status", "200"),
12151                                     MAKE_NV("connection", "close")};
12152   const nghttp2_nv cl1xx_resnv[] = {MAKE_NV(":status", "100"),
12153                                     MAKE_NV("content-length", "0")};
12154   const nghttp2_nv cl204_resnv[] = {MAKE_NV(":status", "204"),
12155                                     MAKE_NV("content-length", "0")};
12156   const nghttp2_nv clnonzero204_resnv[] = {MAKE_NV(":status", "204"),
12157                                            MAKE_NV("content-length", "100")};
12158   const nghttp2_nv status101_resnv[] = {MAKE_NV(":status", "101")};
12159   const nghttp2_nv unexpectedhost_resnv[] = {MAKE_NV(":status", "200"),
12160                                              MAKE_NV("host", "/localhost")};
12161 
12162   /* test case for request */
12163   const nghttp2_nv nopath_reqnv[] = {MAKE_NV(":scheme", "https"),
12164                                      MAKE_NV(":method", "GET"),
12165                                      MAKE_NV(":authority", "localhost")};
12166   const nghttp2_nv earlyconnect_reqnv[] = {
12167       MAKE_NV(":method", "CONNECT"), MAKE_NV(":scheme", "https"),
12168       MAKE_NV(":path", "/"), MAKE_NV(":authority", "localhost")};
12169   const nghttp2_nv lateconnect_reqnv[] = {
12170       MAKE_NV(":scheme", "https"), MAKE_NV(":path", "/"),
12171       MAKE_NV(":method", "CONNECT"), MAKE_NV(":authority", "localhost")};
12172   const nghttp2_nv duppath_reqnv[] = {
12173       MAKE_NV(":scheme", "https"), MAKE_NV(":method", "GET"),
12174       MAKE_NV(":authority", "localhost"), MAKE_NV(":path", "/"),
12175       MAKE_NV(":path", "/")};
12176   const nghttp2_nv badcl_reqnv[] = {
12177       MAKE_NV(":scheme", "https"), MAKE_NV(":method", "POST"),
12178       MAKE_NV(":authority", "localhost"), MAKE_NV(":path", "/"),
12179       MAKE_NV("content-length", "-1")};
12180   const nghttp2_nv dupcl_reqnv[] = {
12181       MAKE_NV(":scheme", "https"),        MAKE_NV(":method", "POST"),
12182       MAKE_NV(":authority", "localhost"), MAKE_NV(":path", "/"),
12183       MAKE_NV("content-length", "0"),     MAKE_NV("content-length", "0")};
12184   const nghttp2_nv badhd_reqnv[] = {
12185       MAKE_NV(":scheme", "https"), MAKE_NV(":method", "GET"),
12186       MAKE_NV(":authority", "localhost"), MAKE_NV(":path", "/"),
12187       MAKE_NV("connection", "close")};
12188   const nghttp2_nv badauthority_reqnv[] = {
12189       MAKE_NV(":scheme", "https"), MAKE_NV(":method", "GET"),
12190       MAKE_NV(":authority", "\x0d\x0alocalhost"), MAKE_NV(":path", "/")};
12191   const nghttp2_nv badhdbtw_reqnv[] = {
12192       MAKE_NV(":scheme", "https"), MAKE_NV(":method", "GET"),
12193       MAKE_NV("foo", "\x0d\x0a"), MAKE_NV(":authority", "localhost"),
12194       MAKE_NV(":path", "/")};
12195   const nghttp2_nv asteriskget1_reqnv[] = {
12196       MAKE_NV(":path", "*"), MAKE_NV(":scheme", "https"),
12197       MAKE_NV(":authority", "localhost"), MAKE_NV(":method", "GET")};
12198   const nghttp2_nv asteriskget2_reqnv[] = {
12199       MAKE_NV(":scheme", "https"), MAKE_NV(":authority", "localhost"),
12200       MAKE_NV(":method", "GET"), MAKE_NV(":path", "*")};
12201   const nghttp2_nv asteriskoptions1_reqnv[] = {
12202       MAKE_NV(":path", "*"), MAKE_NV(":scheme", "https"),
12203       MAKE_NV(":authority", "localhost"), MAKE_NV(":method", "OPTIONS")};
12204   const nghttp2_nv asteriskoptions2_reqnv[] = {
12205       MAKE_NV(":scheme", "https"), MAKE_NV(":authority", "localhost"),
12206       MAKE_NV(":method", "OPTIONS"), MAKE_NV(":path", "*")};
12207   const nghttp2_nv connectproto_reqnv[] = {
12208       MAKE_NV(":scheme", "https"), MAKE_NV(":path", "/"),
12209       MAKE_NV(":method", "CONNECT"), MAKE_NV(":authority", "localhost"),
12210       MAKE_NV(":protocol", "websocket")};
12211   const nghttp2_nv connectprotoget_reqnv[] = {
12212       MAKE_NV(":scheme", "https"), MAKE_NV(":path", "/"),
12213       MAKE_NV(":method", "GET"), MAKE_NV(":authority", "localhost"),
12214       MAKE_NV(":protocol", "websocket")};
12215   const nghttp2_nv connectprotonopath_reqnv[] = {
12216       MAKE_NV(":scheme", "https"), MAKE_NV(":method", "CONNECT"),
12217       MAKE_NV(":authority", "localhost"), MAKE_NV(":protocol", "websocket")};
12218   const nghttp2_nv connectprotonoauth_reqnv[] = {
12219       MAKE_NV(":scheme", "http"), MAKE_NV(":path", "/"),
12220       MAKE_NV(":method", "CONNECT"), MAKE_NV("host", "localhost"),
12221       MAKE_NV(":protocol", "websocket")};
12222   const nghttp2_nv regularconnect_reqnv[] = {
12223       MAKE_NV(":method", "CONNECT"), MAKE_NV(":authority", "localhost")};
12224 
12225   mem = nghttp2_mem_default();
12226 
12227   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
12228   callbacks.send_callback = null_send_callback;
12229   callbacks.on_frame_recv_callback = on_frame_recv_callback;
12230   callbacks.on_invalid_frame_recv_callback = on_invalid_frame_recv_callback;
12231 
12232   nghttp2_session_client_new(&session, &callbacks, &ud);
12233 
12234   nghttp2_hd_deflate_init(&deflater, mem);
12235 
12236   /* response header lacks :status */
12237   check_nghttp2_http_recv_headers_fail(session, &deflater, 1,
12238                                        NGHTTP2_STREAM_OPENING, nostatus_resnv,
12239                                        ARRLEN(nostatus_resnv));
12240 
12241   /* response header has 2 :status */
12242   check_nghttp2_http_recv_headers_fail(session, &deflater, 3,
12243                                        NGHTTP2_STREAM_OPENING, dupstatus_resnv,
12244                                        ARRLEN(dupstatus_resnv));
12245 
12246   /* response header has bad pseudo header :scheme */
12247   check_nghttp2_http_recv_headers_fail(session, &deflater, 5,
12248                                        NGHTTP2_STREAM_OPENING, badpseudo_resnv,
12249                                        ARRLEN(badpseudo_resnv));
12250 
12251   /* response header has :status after regular header field */
12252   check_nghttp2_http_recv_headers_fail(session, &deflater, 7,
12253                                        NGHTTP2_STREAM_OPENING, latepseudo_resnv,
12254                                        ARRLEN(latepseudo_resnv));
12255 
12256   /* response header has bad status code */
12257   check_nghttp2_http_recv_headers_fail(session, &deflater, 9,
12258                                        NGHTTP2_STREAM_OPENING, badstatus_resnv,
12259                                        ARRLEN(badstatus_resnv));
12260 
12261   /* response header has bad content-length */
12262   check_nghttp2_http_recv_headers_fail(session, &deflater, 11,
12263                                        NGHTTP2_STREAM_OPENING, badcl_resnv,
12264                                        ARRLEN(badcl_resnv));
12265 
12266   /* response header has multiple content-length */
12267   check_nghttp2_http_recv_headers_fail(session, &deflater, 13,
12268                                        NGHTTP2_STREAM_OPENING, dupcl_resnv,
12269                                        ARRLEN(dupcl_resnv));
12270 
12271   /* response header has disallowed header field */
12272   check_nghttp2_http_recv_headers_fail(session, &deflater, 15,
12273                                        NGHTTP2_STREAM_OPENING, badhd_resnv,
12274                                        ARRLEN(badhd_resnv));
12275 
12276   /* response header has content-length with 100 status code */
12277   check_nghttp2_http_recv_headers_fail(session, &deflater, 17,
12278                                        NGHTTP2_STREAM_OPENING, cl1xx_resnv,
12279                                        ARRLEN(cl1xx_resnv));
12280 
12281   /* response header has 0 content-length with 204 status code */
12282   check_nghttp2_http_recv_headers_ok(session, &deflater, 19,
12283                                      NGHTTP2_STREAM_OPENING, cl204_resnv,
12284                                      ARRLEN(cl204_resnv));
12285 
12286   /* response header has nonzero content-length with 204 status
12287      code */
12288   check_nghttp2_http_recv_headers_fail(
12289       session, &deflater, 21, NGHTTP2_STREAM_OPENING, clnonzero204_resnv,
12290       ARRLEN(clnonzero204_resnv));
12291 
12292   /* status code 101 should not be used in HTTP/2 because it is used
12293      for HTTP Upgrade which HTTP/2 removes. */
12294   check_nghttp2_http_recv_headers_fail(session, &deflater, 23,
12295                                        NGHTTP2_STREAM_OPENING, status101_resnv,
12296                                        ARRLEN(status101_resnv));
12297 
12298   /* Specific characters check for host field in response header
12299      should not be done as its use is undefined. */
12300   check_nghttp2_http_recv_headers_ok(
12301       session, &deflater, 25, NGHTTP2_STREAM_OPENING, unexpectedhost_resnv,
12302       ARRLEN(unexpectedhost_resnv));
12303 
12304   nghttp2_hd_deflate_free(&deflater);
12305 
12306   nghttp2_session_del(session);
12307 
12308   /* check server side */
12309   nghttp2_session_server_new(&session, &callbacks, &ud);
12310 
12311   nghttp2_hd_deflate_init(&deflater, mem);
12312 
12313   /* request header has no :path */
12314   check_nghttp2_http_recv_headers_fail(session, &deflater, 1, -1, nopath_reqnv,
12315                                        ARRLEN(nopath_reqnv));
12316 
12317   /* request header has CONNECT method, but followed by :path */
12318   check_nghttp2_http_recv_headers_fail(session, &deflater, 3, -1,
12319                                        earlyconnect_reqnv,
12320                                        ARRLEN(earlyconnect_reqnv));
12321 
12322   /* request header has CONNECT method following :path */
12323   check_nghttp2_http_recv_headers_fail(
12324       session, &deflater, 5, -1, lateconnect_reqnv, ARRLEN(lateconnect_reqnv));
12325 
12326   /* request header has multiple :path */
12327   check_nghttp2_http_recv_headers_fail(session, &deflater, 7, -1, duppath_reqnv,
12328                                        ARRLEN(duppath_reqnv));
12329 
12330   /* request header has bad content-length */
12331   check_nghttp2_http_recv_headers_fail(session, &deflater, 9, -1, badcl_reqnv,
12332                                        ARRLEN(badcl_reqnv));
12333 
12334   /* request header has multiple content-length */
12335   check_nghttp2_http_recv_headers_fail(session, &deflater, 11, -1, dupcl_reqnv,
12336                                        ARRLEN(dupcl_reqnv));
12337 
12338   /* request header has disallowed header field */
12339   check_nghttp2_http_recv_headers_fail(session, &deflater, 13, -1, badhd_reqnv,
12340                                        ARRLEN(badhd_reqnv));
12341 
12342   /* request header has :authority header field containing illegal
12343      characters */
12344   check_nghttp2_http_recv_headers_fail(session, &deflater, 15, -1,
12345                                        badauthority_reqnv,
12346                                        ARRLEN(badauthority_reqnv));
12347 
12348   /* request header has regular header field containing illegal
12349      character before all mandatory header fields are seen. */
12350   check_nghttp2_http_recv_headers_fail(session, &deflater, 17, -1,
12351                                        badhdbtw_reqnv, ARRLEN(badhdbtw_reqnv));
12352 
12353   /* request header has "*" in :path header field while method is GET.
12354      :path is received before :method */
12355   check_nghttp2_http_recv_headers_fail(session, &deflater, 19, -1,
12356                                        asteriskget1_reqnv,
12357                                        ARRLEN(asteriskget1_reqnv));
12358 
12359   /* request header has "*" in :path header field while method is GET.
12360      :method is received before :path */
12361   check_nghttp2_http_recv_headers_fail(session, &deflater, 21, -1,
12362                                        asteriskget2_reqnv,
12363                                        ARRLEN(asteriskget2_reqnv));
12364 
12365   /* OPTIONS method can include "*" in :path header field.  :path is
12366      received before :method. */
12367   check_nghttp2_http_recv_headers_ok(session, &deflater, 23, -1,
12368                                      asteriskoptions1_reqnv,
12369                                      ARRLEN(asteriskoptions1_reqnv));
12370 
12371   /* OPTIONS method can include "*" in :path header field.  :method is
12372      received before :path. */
12373   check_nghttp2_http_recv_headers_ok(session, &deflater, 25, -1,
12374                                      asteriskoptions2_reqnv,
12375                                      ARRLEN(asteriskoptions2_reqnv));
12376 
12377   /* :protocol is not allowed unless it is enabled by the local
12378      endpoint. */
12379   check_nghttp2_http_recv_headers_fail(session, &deflater, 27, -1,
12380                                        connectproto_reqnv,
12381                                        ARRLEN(connectproto_reqnv));
12382 
12383   nghttp2_hd_deflate_free(&deflater);
12384 
12385   nghttp2_session_del(session);
12386 
12387   /* enable SETTINGS_CONNECT_PROTOCOL */
12388   nghttp2_session_server_new(&session, &callbacks, &ud);
12389 
12390   session->pending_enable_connect_protocol = 1;
12391 
12392   nghttp2_hd_deflate_init(&deflater, mem);
12393 
12394   /* :protocol is allowed if SETTINGS_CONNECT_PROTOCOL is enabled by
12395      the local endpoint. */
12396   check_nghttp2_http_recv_headers_ok(session, &deflater, 1, -1,
12397                                      connectproto_reqnv,
12398                                      ARRLEN(connectproto_reqnv));
12399 
12400   /* :protocol is only allowed with CONNECT method. */
12401   check_nghttp2_http_recv_headers_fail(session, &deflater, 3, -1,
12402                                        connectprotoget_reqnv,
12403                                        ARRLEN(connectprotoget_reqnv));
12404 
12405   /* CONNECT method with :protocol requires :path. */
12406   check_nghttp2_http_recv_headers_fail(session, &deflater, 5, -1,
12407                                        connectprotonopath_reqnv,
12408                                        ARRLEN(connectprotonopath_reqnv));
12409 
12410   /* CONNECT method with :protocol requires :authority. */
12411   check_nghttp2_http_recv_headers_fail(session, &deflater, 7, -1,
12412                                        connectprotonoauth_reqnv,
12413                                        ARRLEN(connectprotonoauth_reqnv));
12414 
12415   /* regular CONNECT method should succeed with
12416      SETTINGS_CONNECT_PROTOCOL */
12417   check_nghttp2_http_recv_headers_ok(session, &deflater, 9, -1,
12418                                      regularconnect_reqnv,
12419                                      ARRLEN(regularconnect_reqnv));
12420 
12421   nghttp2_hd_deflate_free(&deflater);
12422 
12423   nghttp2_session_del(session);
12424 }
12425 
test_nghttp2_http_content_length(void)12426 void test_nghttp2_http_content_length(void) {
12427   nghttp2_session *session;
12428   nghttp2_session_callbacks callbacks;
12429   nghttp2_hd_deflater deflater;
12430   nghttp2_mem *mem;
12431   nghttp2_bufs bufs;
12432   ssize_t rv;
12433   nghttp2_stream *stream;
12434   const nghttp2_nv cl_resnv[] = {MAKE_NV(":status", "200"),
12435                                  MAKE_NV("te", "trailers"),
12436                                  MAKE_NV("content-length", "9000000000")};
12437   const nghttp2_nv cl_reqnv[] = {
12438       MAKE_NV(":path", "/"),        MAKE_NV(":method", "PUT"),
12439       MAKE_NV(":scheme", "https"),  MAKE_NV("te", "trailers"),
12440       MAKE_NV("host", "localhost"), MAKE_NV("content-length", "9000000000")};
12441 
12442   mem = nghttp2_mem_default();
12443   frame_pack_bufs_init(&bufs);
12444 
12445   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
12446   callbacks.send_callback = null_send_callback;
12447 
12448   nghttp2_session_client_new(&session, &callbacks, NULL);
12449 
12450   nghttp2_hd_deflate_init(&deflater, mem);
12451 
12452   stream = open_sent_stream2(session, 1, NGHTTP2_STREAM_OPENING);
12453 
12454   rv = pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, cl_resnv,
12455                     ARRLEN(cl_resnv), mem);
12456   CU_ASSERT(0 == rv);
12457 
12458   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
12459                                 nghttp2_buf_len(&bufs.head->buf));
12460 
12461   CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
12462   CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
12463   CU_ASSERT(9000000000LL == stream->content_length);
12464   CU_ASSERT(200 == stream->status_code);
12465 
12466   nghttp2_hd_deflate_free(&deflater);
12467 
12468   nghttp2_session_del(session);
12469 
12470   nghttp2_bufs_reset(&bufs);
12471 
12472   /* check server side */
12473   nghttp2_session_server_new(&session, &callbacks, NULL);
12474 
12475   nghttp2_hd_deflate_init(&deflater, mem);
12476 
12477   rv = pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, cl_reqnv,
12478                     ARRLEN(cl_reqnv), mem);
12479   CU_ASSERT(0 == rv);
12480 
12481   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
12482                                 nghttp2_buf_len(&bufs.head->buf));
12483 
12484   CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
12485 
12486   stream = nghttp2_session_get_stream(session, 1);
12487 
12488   CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
12489   CU_ASSERT(9000000000LL == stream->content_length);
12490 
12491   nghttp2_hd_deflate_free(&deflater);
12492 
12493   nghttp2_session_del(session);
12494 
12495   nghttp2_bufs_free(&bufs);
12496 }
12497 
test_nghttp2_http_content_length_mismatch(void)12498 void test_nghttp2_http_content_length_mismatch(void) {
12499   nghttp2_session *session;
12500   nghttp2_session_callbacks callbacks;
12501   nghttp2_hd_deflater deflater;
12502   nghttp2_mem *mem;
12503   nghttp2_bufs bufs;
12504   ssize_t rv;
12505   const nghttp2_nv cl_reqnv[] = {
12506       MAKE_NV(":path", "/"), MAKE_NV(":method", "PUT"),
12507       MAKE_NV(":authority", "localhost"), MAKE_NV(":scheme", "https"),
12508       MAKE_NV("content-length", "20")};
12509   const nghttp2_nv cl_resnv[] = {MAKE_NV(":status", "200"),
12510                                  MAKE_NV("content-length", "20")};
12511   nghttp2_outbound_item *item;
12512   nghttp2_frame_hd hd;
12513 
12514   mem = nghttp2_mem_default();
12515   frame_pack_bufs_init(&bufs);
12516 
12517   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
12518   callbacks.send_callback = null_send_callback;
12519 
12520   nghttp2_session_server_new(&session, &callbacks, NULL);
12521 
12522   nghttp2_hd_deflate_init(&deflater, mem);
12523 
12524   /* header says content-length: 20, but HEADERS has END_STREAM flag set */
12525   rv = pack_headers(&bufs, &deflater, 1,
12526                     NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM,
12527                     cl_reqnv, ARRLEN(cl_reqnv), mem);
12528   CU_ASSERT(0 == rv);
12529 
12530   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
12531                                 nghttp2_buf_len(&bufs.head->buf));
12532 
12533   CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
12534 
12535   item = nghttp2_session_get_next_ob_item(session);
12536   CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
12537 
12538   CU_ASSERT(0 == nghttp2_session_send(session));
12539 
12540   nghttp2_bufs_reset(&bufs);
12541 
12542   /* header says content-length: 20, but DATA has 0 byte */
12543   rv = pack_headers(&bufs, &deflater, 3, NGHTTP2_FLAG_END_HEADERS, cl_reqnv,
12544                     ARRLEN(cl_reqnv), mem);
12545   CU_ASSERT(0 == rv);
12546 
12547   nghttp2_frame_hd_init(&hd, 0, NGHTTP2_DATA, NGHTTP2_FLAG_END_STREAM, 3);
12548   nghttp2_frame_pack_frame_hd(bufs.head->buf.last, &hd);
12549   bufs.head->buf.last += NGHTTP2_FRAME_HDLEN;
12550 
12551   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
12552                                 nghttp2_buf_len(&bufs.head->buf));
12553 
12554   CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
12555 
12556   item = nghttp2_session_get_next_ob_item(session);
12557   CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
12558 
12559   CU_ASSERT(0 == nghttp2_session_send(session));
12560 
12561   nghttp2_bufs_reset(&bufs);
12562 
12563   /* header says content-length: 20, but DATA has 21 bytes */
12564   rv = pack_headers(&bufs, &deflater, 5, NGHTTP2_FLAG_END_HEADERS, cl_reqnv,
12565                     ARRLEN(cl_reqnv), mem);
12566   CU_ASSERT(0 == rv);
12567 
12568   nghttp2_frame_hd_init(&hd, 21, NGHTTP2_DATA, NGHTTP2_FLAG_END_STREAM, 5);
12569   nghttp2_frame_pack_frame_hd(bufs.head->buf.last, &hd);
12570   bufs.head->buf.last += NGHTTP2_FRAME_HDLEN + 21;
12571 
12572   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
12573                                 nghttp2_buf_len(&bufs.head->buf));
12574 
12575   CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
12576 
12577   item = nghttp2_session_get_next_ob_item(session);
12578   CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
12579 
12580   CU_ASSERT(0 == nghttp2_session_send(session));
12581 
12582   nghttp2_bufs_reset(&bufs);
12583 
12584   nghttp2_hd_deflate_free(&deflater);
12585 
12586   nghttp2_session_del(session);
12587 
12588   /* Check for client */
12589   nghttp2_session_client_new(&session, &callbacks, NULL);
12590 
12591   nghttp2_hd_deflate_init(&deflater, mem);
12592 
12593   /* header says content-length: 20, but HEADERS has END_STREAM flag set */
12594   nghttp2_submit_request(session, NULL, reqnv, ARRLEN(reqnv), NULL, NULL);
12595 
12596   CU_ASSERT(0 == nghttp2_session_send(session));
12597 
12598   rv = pack_headers(&bufs, &deflater, 1,
12599                     NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM,
12600                     cl_resnv, ARRLEN(cl_resnv), mem);
12601   CU_ASSERT(0 == rv);
12602 
12603   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
12604                                 nghttp2_buf_len(&bufs.head->buf));
12605 
12606   CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
12607 
12608   item = nghttp2_session_get_next_ob_item(session);
12609   CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
12610 
12611   CU_ASSERT(NULL != nghttp2_session_get_stream(session, 1));
12612   CU_ASSERT(0 == nghttp2_session_send(session));
12613   /* After sending RST_STREAM, stream must be closed */
12614   CU_ASSERT(NULL == nghttp2_session_get_stream(session, 1));
12615 
12616   nghttp2_bufs_reset(&bufs);
12617 
12618   /* header says content-length: 20, but DATA has 0 byte */
12619   nghttp2_submit_request(session, NULL, reqnv, ARRLEN(reqnv), NULL, NULL);
12620 
12621   CU_ASSERT(0 == nghttp2_session_send(session));
12622 
12623   rv = pack_headers(&bufs, &deflater, 3, NGHTTP2_FLAG_END_HEADERS, cl_resnv,
12624                     ARRLEN(cl_resnv), mem);
12625   CU_ASSERT(0 == rv);
12626 
12627   nghttp2_frame_hd_init(&hd, 0, NGHTTP2_DATA, NGHTTP2_FLAG_END_STREAM, 3);
12628   nghttp2_frame_pack_frame_hd(bufs.head->buf.last, &hd);
12629   bufs.head->buf.last += NGHTTP2_FRAME_HDLEN;
12630 
12631   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
12632                                 nghttp2_buf_len(&bufs.head->buf));
12633 
12634   CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
12635 
12636   item = nghttp2_session_get_next_ob_item(session);
12637   CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
12638 
12639   CU_ASSERT(NULL != nghttp2_session_get_stream(session, 3));
12640   CU_ASSERT(0 == nghttp2_session_send(session));
12641   /* After sending RST_STREAM, stream must be closed */
12642   CU_ASSERT(NULL == nghttp2_session_get_stream(session, 3));
12643 
12644   nghttp2_bufs_reset(&bufs);
12645 
12646   /* header says content-length: 20, but DATA has 21 bytes */
12647   nghttp2_submit_request(session, NULL, reqnv, ARRLEN(reqnv), NULL, NULL);
12648 
12649   CU_ASSERT(0 == nghttp2_session_send(session));
12650 
12651   rv = pack_headers(&bufs, &deflater, 5, NGHTTP2_FLAG_END_HEADERS, cl_resnv,
12652                     ARRLEN(cl_resnv), mem);
12653   CU_ASSERT(0 == rv);
12654 
12655   nghttp2_frame_hd_init(&hd, 21, NGHTTP2_DATA, NGHTTP2_FLAG_END_STREAM, 5);
12656   nghttp2_frame_pack_frame_hd(bufs.head->buf.last, &hd);
12657   bufs.head->buf.last += NGHTTP2_FRAME_HDLEN + 21;
12658 
12659   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
12660                                 nghttp2_buf_len(&bufs.head->buf));
12661 
12662   CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
12663 
12664   item = nghttp2_session_get_next_ob_item(session);
12665   CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
12666 
12667   CU_ASSERT(NULL != nghttp2_session_get_stream(session, 5));
12668   CU_ASSERT(0 == nghttp2_session_send(session));
12669   /* After sending RST_STREAM, stream must be closed */
12670   CU_ASSERT(NULL == nghttp2_session_get_stream(session, 5));
12671 
12672   nghttp2_bufs_reset(&bufs);
12673 
12674   nghttp2_bufs_free(&bufs);
12675 
12676   nghttp2_hd_deflate_free(&deflater);
12677 
12678   nghttp2_session_del(session);
12679 }
12680 
test_nghttp2_http_non_final_response(void)12681 void test_nghttp2_http_non_final_response(void) {
12682   nghttp2_session *session;
12683   nghttp2_session_callbacks callbacks;
12684   nghttp2_hd_deflater deflater;
12685   nghttp2_mem *mem;
12686   nghttp2_bufs bufs;
12687   ssize_t rv;
12688   const nghttp2_nv nonfinal_resnv[] = {
12689       MAKE_NV(":status", "100"),
12690   };
12691   nghttp2_outbound_item *item;
12692   nghttp2_frame_hd hd;
12693 
12694   mem = nghttp2_mem_default();
12695   frame_pack_bufs_init(&bufs);
12696 
12697   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
12698   callbacks.send_callback = null_send_callback;
12699 
12700   nghttp2_session_client_new(&session, &callbacks, NULL);
12701 
12702   nghttp2_hd_deflate_init(&deflater, mem);
12703 
12704   /* non-final HEADERS with END_STREAM is illegal */
12705   open_sent_stream2(session, 1, NGHTTP2_STREAM_OPENING);
12706 
12707   rv = pack_headers(&bufs, &deflater, 1,
12708                     NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM,
12709                     nonfinal_resnv, ARRLEN(nonfinal_resnv), mem);
12710   CU_ASSERT(0 == rv);
12711 
12712   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
12713                                 nghttp2_buf_len(&bufs.head->buf));
12714 
12715   CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
12716 
12717   item = nghttp2_session_get_next_ob_item(session);
12718   CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
12719 
12720   CU_ASSERT(0 == nghttp2_session_send(session));
12721 
12722   nghttp2_bufs_reset(&bufs);
12723 
12724   /* non-final HEADERS followed by non-empty DATA is illegal */
12725   open_sent_stream2(session, 3, NGHTTP2_STREAM_OPENING);
12726 
12727   rv = pack_headers(&bufs, &deflater, 3, NGHTTP2_FLAG_END_HEADERS,
12728                     nonfinal_resnv, ARRLEN(nonfinal_resnv), mem);
12729   CU_ASSERT(0 == rv);
12730 
12731   nghttp2_frame_hd_init(&hd, 10, NGHTTP2_DATA, NGHTTP2_FLAG_END_STREAM, 3);
12732   nghttp2_frame_pack_frame_hd(bufs.head->buf.last, &hd);
12733   bufs.head->buf.last += NGHTTP2_FRAME_HDLEN + 10;
12734 
12735   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
12736                                 nghttp2_buf_len(&bufs.head->buf));
12737 
12738   CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
12739 
12740   item = nghttp2_session_get_next_ob_item(session);
12741   CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
12742 
12743   CU_ASSERT(0 == nghttp2_session_send(session));
12744 
12745   nghttp2_bufs_reset(&bufs);
12746 
12747   /* non-final HEADERS followed by empty DATA (without END_STREAM) is
12748      ok */
12749   open_sent_stream2(session, 5, NGHTTP2_STREAM_OPENING);
12750 
12751   rv = pack_headers(&bufs, &deflater, 5, NGHTTP2_FLAG_END_HEADERS,
12752                     nonfinal_resnv, ARRLEN(nonfinal_resnv), mem);
12753   CU_ASSERT(0 == rv);
12754 
12755   nghttp2_frame_hd_init(&hd, 0, NGHTTP2_DATA, NGHTTP2_FLAG_NONE, 5);
12756   nghttp2_frame_pack_frame_hd(bufs.head->buf.last, &hd);
12757   bufs.head->buf.last += NGHTTP2_FRAME_HDLEN;
12758 
12759   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
12760                                 nghttp2_buf_len(&bufs.head->buf));
12761 
12762   CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
12763 
12764   CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
12765 
12766   nghttp2_bufs_reset(&bufs);
12767 
12768   /* non-final HEADERS followed by empty DATA (with END_STREAM) is
12769      illegal */
12770   open_sent_stream2(session, 7, NGHTTP2_STREAM_OPENING);
12771 
12772   rv = pack_headers(&bufs, &deflater, 7, NGHTTP2_FLAG_END_HEADERS,
12773                     nonfinal_resnv, ARRLEN(nonfinal_resnv), mem);
12774   CU_ASSERT(0 == rv);
12775 
12776   nghttp2_frame_hd_init(&hd, 0, NGHTTP2_DATA, NGHTTP2_FLAG_END_STREAM, 7);
12777   nghttp2_frame_pack_frame_hd(bufs.head->buf.last, &hd);
12778   bufs.head->buf.last += NGHTTP2_FRAME_HDLEN;
12779 
12780   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
12781                                 nghttp2_buf_len(&bufs.head->buf));
12782 
12783   CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
12784 
12785   item = nghttp2_session_get_next_ob_item(session);
12786 
12787   CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
12788 
12789   CU_ASSERT(0 == nghttp2_session_send(session));
12790 
12791   nghttp2_bufs_reset(&bufs);
12792 
12793   /* non-final HEADERS followed by final HEADERS is OK */
12794   open_sent_stream2(session, 9, NGHTTP2_STREAM_OPENING);
12795 
12796   rv = pack_headers(&bufs, &deflater, 9, NGHTTP2_FLAG_END_HEADERS,
12797                     nonfinal_resnv, ARRLEN(nonfinal_resnv), mem);
12798   CU_ASSERT(0 == rv);
12799 
12800   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
12801                                 nghttp2_buf_len(&bufs.head->buf));
12802 
12803   CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
12804 
12805   nghttp2_bufs_reset(&bufs);
12806 
12807   rv = pack_headers(&bufs, &deflater, 9, NGHTTP2_FLAG_END_HEADERS, resnv,
12808                     ARRLEN(resnv), mem);
12809   CU_ASSERT(0 == rv);
12810 
12811   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
12812                                 nghttp2_buf_len(&bufs.head->buf));
12813 
12814   CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
12815 
12816   CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
12817 
12818   nghttp2_bufs_reset(&bufs);
12819 
12820   nghttp2_hd_deflate_free(&deflater);
12821 
12822   nghttp2_session_del(session);
12823 
12824   nghttp2_bufs_free(&bufs);
12825 }
12826 
test_nghttp2_http_trailer_headers(void)12827 void test_nghttp2_http_trailer_headers(void) {
12828   nghttp2_session *session;
12829   nghttp2_session_callbacks callbacks;
12830   nghttp2_hd_deflater deflater;
12831   nghttp2_mem *mem;
12832   nghttp2_bufs bufs;
12833   ssize_t rv;
12834   const nghttp2_nv trailer_reqnv[] = {
12835       MAKE_NV("foo", "bar"),
12836   };
12837   nghttp2_outbound_item *item;
12838 
12839   mem = nghttp2_mem_default();
12840   frame_pack_bufs_init(&bufs);
12841 
12842   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
12843   callbacks.send_callback = null_send_callback;
12844 
12845   nghttp2_session_server_new(&session, &callbacks, NULL);
12846 
12847   nghttp2_hd_deflate_init(&deflater, mem);
12848 
12849   /* good trailer header */
12850   rv = pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, reqnv,
12851                     ARRLEN(reqnv), mem);
12852   CU_ASSERT(0 == rv);
12853 
12854   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
12855                                 nghttp2_buf_len(&bufs.head->buf));
12856 
12857   CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
12858 
12859   nghttp2_bufs_reset(&bufs);
12860 
12861   rv = pack_headers(&bufs, &deflater, 1,
12862                     NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM,
12863                     trailer_reqnv, ARRLEN(trailer_reqnv), mem);
12864   CU_ASSERT(0 == rv);
12865 
12866   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
12867                                 nghttp2_buf_len(&bufs.head->buf));
12868 
12869   CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
12870 
12871   CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
12872 
12873   nghttp2_bufs_reset(&bufs);
12874 
12875   /* trailer header without END_STREAM is illegal */
12876   rv = pack_headers(&bufs, &deflater, 3, NGHTTP2_FLAG_END_HEADERS, reqnv,
12877                     ARRLEN(reqnv), mem);
12878   CU_ASSERT(0 == rv);
12879 
12880   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
12881                                 nghttp2_buf_len(&bufs.head->buf));
12882 
12883   CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
12884 
12885   nghttp2_bufs_reset(&bufs);
12886 
12887   rv = pack_headers(&bufs, &deflater, 3, NGHTTP2_FLAG_END_HEADERS,
12888                     trailer_reqnv, ARRLEN(trailer_reqnv), mem);
12889   CU_ASSERT(0 == rv);
12890 
12891   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
12892                                 nghttp2_buf_len(&bufs.head->buf));
12893 
12894   CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
12895 
12896   item = nghttp2_session_get_next_ob_item(session);
12897 
12898   CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
12899 
12900   CU_ASSERT(0 == nghttp2_session_send(session));
12901 
12902   nghttp2_bufs_reset(&bufs);
12903 
12904   /* trailer header including pseudo header field is illegal */
12905   rv = pack_headers(&bufs, &deflater, 5, NGHTTP2_FLAG_END_HEADERS, reqnv,
12906                     ARRLEN(reqnv), mem);
12907   CU_ASSERT(0 == rv);
12908 
12909   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
12910                                 nghttp2_buf_len(&bufs.head->buf));
12911 
12912   CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
12913 
12914   nghttp2_bufs_reset(&bufs);
12915 
12916   rv = pack_headers(&bufs, &deflater, 5, NGHTTP2_FLAG_END_HEADERS, reqnv,
12917                     ARRLEN(reqnv), mem);
12918   CU_ASSERT(0 == rv);
12919 
12920   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
12921                                 nghttp2_buf_len(&bufs.head->buf));
12922 
12923   CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
12924 
12925   item = nghttp2_session_get_next_ob_item(session);
12926 
12927   CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
12928 
12929   CU_ASSERT(0 == nghttp2_session_send(session));
12930 
12931   nghttp2_bufs_reset(&bufs);
12932 
12933   nghttp2_hd_deflate_free(&deflater);
12934 
12935   nghttp2_session_del(session);
12936 
12937   nghttp2_bufs_free(&bufs);
12938 }
12939 
test_nghttp2_http_ignore_regular_header(void)12940 void test_nghttp2_http_ignore_regular_header(void) {
12941   nghttp2_session *session;
12942   nghttp2_session_callbacks callbacks;
12943   nghttp2_hd_deflater deflater;
12944   nghttp2_mem *mem;
12945   nghttp2_bufs bufs;
12946   ssize_t rv;
12947   my_user_data ud;
12948   const nghttp2_nv bad_reqnv[] = {
12949       MAKE_NV(":authority", "localhost"),
12950       MAKE_NV(":scheme", "https"),
12951       MAKE_NV(":path", "/"),
12952       MAKE_NV(":method", "GET"),
12953       MAKE_NV("foo", "\x0zzz"),
12954       MAKE_NV("bar", "buzz"),
12955   };
12956   const nghttp2_nv bad_ansnv[] = {
12957       MAKE_NV(":authority", "localhost"), MAKE_NV(":scheme", "https"),
12958       MAKE_NV(":path", "/"), MAKE_NV(":method", "GET"), MAKE_NV("bar", "buzz")};
12959   size_t proclen;
12960   size_t i;
12961   nghttp2_outbound_item *item;
12962 
12963   mem = nghttp2_mem_default();
12964   frame_pack_bufs_init(&bufs);
12965 
12966   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
12967   callbacks.send_callback = null_send_callback;
12968   callbacks.on_header_callback = pause_on_header_callback;
12969 
12970   nghttp2_session_server_new(&session, &callbacks, &ud);
12971   nghttp2_hd_deflate_init(&deflater, mem);
12972 
12973   rv = pack_headers(&bufs, &deflater, 1,
12974                     NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM,
12975                     bad_reqnv, ARRLEN(bad_reqnv), mem);
12976 
12977   CU_ASSERT_FATAL(0 == rv);
12978 
12979   nghttp2_hd_deflate_free(&deflater);
12980 
12981   proclen = 0;
12982 
12983   for (i = 0; i < 4; ++i) {
12984     rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos + proclen,
12985                                   nghttp2_buf_len(&bufs.head->buf) - proclen);
12986     CU_ASSERT_FATAL(rv > 0);
12987     proclen += (size_t)rv;
12988     CU_ASSERT(nghttp2_nv_equal(&bad_ansnv[i], &ud.nv));
12989   }
12990 
12991   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos + proclen,
12992                                 nghttp2_buf_len(&bufs.head->buf) - proclen);
12993   CU_ASSERT_FATAL(rv > 0);
12994   /* Without on_invalid_frame_recv_callback, bad header causes stream
12995      reset */
12996   item = nghttp2_session_get_next_ob_item(session);
12997 
12998   CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
12999 
13000   proclen += (size_t)rv;
13001 
13002   CU_ASSERT(nghttp2_buf_len(&bufs.head->buf) == proclen);
13003 
13004   nghttp2_session_del(session);
13005 
13006   /* use on_invalid_header_callback */
13007   callbacks.on_invalid_header_callback = pause_on_invalid_header_callback;
13008 
13009   nghttp2_session_server_new(&session, &callbacks, &ud);
13010 
13011   proclen = 0;
13012 
13013   ud.invalid_header_cb_called = 0;
13014 
13015   for (i = 0; i < 4; ++i) {
13016     rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos + proclen,
13017                                   nghttp2_buf_len(&bufs.head->buf) - proclen);
13018     CU_ASSERT_FATAL(rv > 0);
13019     proclen += (size_t)rv;
13020     CU_ASSERT(nghttp2_nv_equal(&bad_ansnv[i], &ud.nv));
13021   }
13022 
13023   CU_ASSERT(0 == ud.invalid_header_cb_called);
13024 
13025   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos + proclen,
13026                                 nghttp2_buf_len(&bufs.head->buf) - proclen);
13027 
13028   CU_ASSERT_FATAL(rv > 0);
13029   CU_ASSERT(1 == ud.invalid_header_cb_called);
13030   CU_ASSERT(nghttp2_nv_equal(&bad_reqnv[4], &ud.nv));
13031 
13032   proclen += (size_t)rv;
13033 
13034   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos + proclen,
13035                                 nghttp2_buf_len(&bufs.head->buf) - proclen);
13036 
13037   CU_ASSERT(rv > 0);
13038   CU_ASSERT(nghttp2_nv_equal(&bad_ansnv[4], &ud.nv));
13039 
13040   nghttp2_session_del(session);
13041 
13042   /* make sure that we can reset stream from
13043      on_invalid_header_callback */
13044   callbacks.on_header_callback = on_header_callback;
13045   callbacks.on_invalid_header_callback = reset_on_invalid_header_callback;
13046 
13047   nghttp2_session_server_new(&session, &callbacks, &ud);
13048 
13049   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
13050                                 nghttp2_buf_len(&bufs.head->buf));
13051 
13052   CU_ASSERT(rv == (ssize_t)nghttp2_buf_len(&bufs.head->buf));
13053 
13054   item = nghttp2_session_get_next_ob_item(session);
13055 
13056   CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
13057   CU_ASSERT(1 == item->frame.hd.stream_id);
13058 
13059   nghttp2_session_del(session);
13060   nghttp2_bufs_free(&bufs);
13061 }
13062 
test_nghttp2_http_ignore_content_length(void)13063 void test_nghttp2_http_ignore_content_length(void) {
13064   nghttp2_session *session;
13065   nghttp2_session_callbacks callbacks;
13066   nghttp2_hd_deflater deflater;
13067   nghttp2_mem *mem;
13068   nghttp2_bufs bufs;
13069   ssize_t rv;
13070   const nghttp2_nv cl_resnv[] = {MAKE_NV(":status", "304"),
13071                                  MAKE_NV("content-length", "20")};
13072   const nghttp2_nv conn_reqnv[] = {MAKE_NV(":authority", "localhost"),
13073                                    MAKE_NV(":method", "CONNECT"),
13074                                    MAKE_NV("content-length", "999999")};
13075   const nghttp2_nv conn_cl_resnv[] = {MAKE_NV(":status", "200"),
13076                                       MAKE_NV("content-length", "0")};
13077   nghttp2_stream *stream;
13078 
13079   mem = nghttp2_mem_default();
13080   frame_pack_bufs_init(&bufs);
13081 
13082   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
13083   callbacks.send_callback = null_send_callback;
13084 
13085   nghttp2_session_client_new(&session, &callbacks, NULL);
13086 
13087   nghttp2_hd_deflate_init(&deflater, mem);
13088 
13089   /* If status 304, content-length must be ignored */
13090   open_sent_stream2(session, 1, NGHTTP2_STREAM_OPENING);
13091 
13092   rv = pack_headers(&bufs, &deflater, 1,
13093                     NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM,
13094                     cl_resnv, ARRLEN(cl_resnv), mem);
13095   CU_ASSERT(0 == rv);
13096 
13097   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
13098                                 nghttp2_buf_len(&bufs.head->buf));
13099 
13100   CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
13101 
13102   CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
13103 
13104   nghttp2_bufs_reset(&bufs);
13105 
13106   /* Content-Length in 200 response to CONNECT is ignored */
13107   stream = open_sent_stream2(session, 3, NGHTTP2_STREAM_OPENING);
13108   stream->http_flags |= NGHTTP2_HTTP_FLAG_METH_CONNECT;
13109 
13110   rv = pack_headers(&bufs, &deflater, 3, NGHTTP2_FLAG_END_HEADERS,
13111                     conn_cl_resnv, ARRLEN(conn_cl_resnv), mem);
13112   CU_ASSERT(0 == rv);
13113 
13114   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
13115                                 nghttp2_buf_len(&bufs.head->buf));
13116 
13117   CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
13118 
13119   CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
13120   CU_ASSERT(-1 == stream->content_length);
13121 
13122   nghttp2_bufs_reset(&bufs);
13123 
13124   nghttp2_hd_deflate_free(&deflater);
13125   nghttp2_session_del(session);
13126 
13127   /* If request method is CONNECT, content-length must be ignored */
13128   nghttp2_session_server_new(&session, &callbacks, NULL);
13129 
13130   nghttp2_hd_deflate_init(&deflater, mem);
13131 
13132   rv = pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, conn_reqnv,
13133                     ARRLEN(conn_reqnv), mem);
13134 
13135   CU_ASSERT(0 == rv);
13136 
13137   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
13138                                 nghttp2_buf_len(&bufs.head->buf));
13139 
13140   CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
13141 
13142   CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
13143 
13144   stream = nghttp2_session_get_stream(session, 1);
13145 
13146   CU_ASSERT(-1 == stream->content_length);
13147   CU_ASSERT((stream->http_flags & NGHTTP2_HTTP_FLAG_METH_CONNECT) > 0);
13148 
13149   nghttp2_hd_deflate_free(&deflater);
13150   nghttp2_session_del(session);
13151   nghttp2_bufs_free(&bufs);
13152 }
13153 
test_nghttp2_http_record_request_method(void)13154 void test_nghttp2_http_record_request_method(void) {
13155   nghttp2_session *session;
13156   nghttp2_session_callbacks callbacks;
13157   const nghttp2_nv conn_reqnv[] = {MAKE_NV(":method", "CONNECT"),
13158                                    MAKE_NV(":authority", "localhost")};
13159   const nghttp2_nv conn_resnv[] = {MAKE_NV(":status", "200"),
13160                                    MAKE_NV("content-length", "9999")};
13161   nghttp2_stream *stream;
13162   ssize_t rv;
13163   nghttp2_bufs bufs;
13164   nghttp2_hd_deflater deflater;
13165   nghttp2_mem *mem;
13166   nghttp2_outbound_item *item;
13167 
13168   mem = nghttp2_mem_default();
13169   frame_pack_bufs_init(&bufs);
13170 
13171   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
13172   callbacks.send_callback = null_send_callback;
13173 
13174   nghttp2_session_client_new(&session, &callbacks, NULL);
13175 
13176   nghttp2_hd_deflate_init(&deflater, mem);
13177 
13178   CU_ASSERT(1 == nghttp2_submit_request(session, NULL, conn_reqnv,
13179                                         ARRLEN(conn_reqnv), NULL, NULL));
13180 
13181   CU_ASSERT(0 == nghttp2_session_send(session));
13182 
13183   stream = nghttp2_session_get_stream(session, 1);
13184 
13185   CU_ASSERT(NGHTTP2_HTTP_FLAG_METH_CONNECT == stream->http_flags);
13186 
13187   rv = pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, conn_resnv,
13188                     ARRLEN(conn_resnv), mem);
13189   CU_ASSERT(0 == rv);
13190 
13191   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
13192                                 nghttp2_buf_len(&bufs.head->buf));
13193 
13194   CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
13195 
13196   CU_ASSERT((NGHTTP2_HTTP_FLAG_METH_CONNECT & stream->http_flags) > 0);
13197   CU_ASSERT(-1 == stream->content_length);
13198 
13199   /* content-length is ignored in 200 response to a CONNECT request */
13200   item = nghttp2_session_get_next_ob_item(session);
13201 
13202   CU_ASSERT(NULL == item);
13203 
13204   nghttp2_hd_deflate_free(&deflater);
13205   nghttp2_session_del(session);
13206   nghttp2_bufs_free(&bufs);
13207 }
13208 
test_nghttp2_http_push_promise(void)13209 void test_nghttp2_http_push_promise(void) {
13210   nghttp2_session *session;
13211   nghttp2_session_callbacks callbacks;
13212   nghttp2_hd_deflater deflater;
13213   nghttp2_mem *mem;
13214   nghttp2_bufs bufs;
13215   ssize_t rv;
13216   nghttp2_stream *stream;
13217   const nghttp2_nv bad_reqnv[] = {MAKE_NV(":method", "GET")};
13218   nghttp2_outbound_item *item;
13219 
13220   mem = nghttp2_mem_default();
13221   frame_pack_bufs_init(&bufs);
13222 
13223   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
13224   callbacks.send_callback = null_send_callback;
13225 
13226   /* good PUSH_PROMISE case */
13227   nghttp2_session_client_new(&session, &callbacks, NULL);
13228 
13229   nghttp2_hd_deflate_init(&deflater, mem);
13230 
13231   open_sent_stream2(session, 1, NGHTTP2_STREAM_OPENING);
13232 
13233   rv = pack_push_promise(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, 2,
13234                          reqnv, ARRLEN(reqnv), mem);
13235   CU_ASSERT(0 == rv);
13236 
13237   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
13238                                 nghttp2_buf_len(&bufs.head->buf));
13239 
13240   CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
13241 
13242   CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
13243 
13244   stream = nghttp2_session_get_stream(session, 2);
13245   CU_ASSERT(NULL != stream);
13246 
13247   nghttp2_bufs_reset(&bufs);
13248 
13249   rv = pack_headers(&bufs, &deflater, 2, NGHTTP2_FLAG_END_HEADERS, resnv,
13250                     ARRLEN(resnv), mem);
13251 
13252   CU_ASSERT(0 == rv);
13253 
13254   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
13255                                 nghttp2_buf_len(&bufs.head->buf));
13256 
13257   CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
13258 
13259   CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
13260 
13261   CU_ASSERT(200 == stream->status_code);
13262 
13263   nghttp2_bufs_reset(&bufs);
13264 
13265   /* PUSH_PROMISE lacks mandatory header */
13266   rv = pack_push_promise(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, 4,
13267                          bad_reqnv, ARRLEN(bad_reqnv), mem);
13268 
13269   CU_ASSERT(0 == rv);
13270 
13271   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
13272                                 nghttp2_buf_len(&bufs.head->buf));
13273 
13274   CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
13275 
13276   item = nghttp2_session_get_next_ob_item(session);
13277 
13278   CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
13279   CU_ASSERT(4 == item->frame.hd.stream_id);
13280 
13281   nghttp2_bufs_reset(&bufs);
13282 
13283   nghttp2_hd_deflate_free(&deflater);
13284   nghttp2_session_del(session);
13285   nghttp2_bufs_free(&bufs);
13286 }
13287 
test_nghttp2_http_head_method_upgrade_workaround(void)13288 void test_nghttp2_http_head_method_upgrade_workaround(void) {
13289   nghttp2_session *session;
13290   nghttp2_session_callbacks callbacks;
13291   const nghttp2_nv cl_resnv[] = {MAKE_NV(":status", "200"),
13292                                  MAKE_NV("content-length", "1000000007")};
13293   nghttp2_bufs bufs;
13294   nghttp2_hd_deflater deflater;
13295   nghttp2_mem *mem;
13296   ssize_t rv;
13297   nghttp2_stream *stream;
13298 
13299   mem = nghttp2_mem_default();
13300   frame_pack_bufs_init(&bufs);
13301 
13302   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
13303   callbacks.send_callback = null_send_callback;
13304 
13305   nghttp2_session_client_new(&session, &callbacks, NULL);
13306 
13307   nghttp2_hd_deflate_init(&deflater, mem);
13308 
13309   nghttp2_session_upgrade(session, NULL, 0, NULL);
13310 
13311   rv = pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, cl_resnv,
13312                     ARRLEN(cl_resnv), mem);
13313 
13314   CU_ASSERT(0 == rv);
13315 
13316   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
13317                                 nghttp2_buf_len(&bufs.head->buf));
13318 
13319   CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
13320 
13321   stream = nghttp2_session_get_stream(session, 1);
13322 
13323   CU_ASSERT(-1 == stream->content_length);
13324 
13325   nghttp2_hd_deflate_free(&deflater);
13326   nghttp2_session_del(session);
13327   nghttp2_bufs_free(&bufs);
13328 }
13329 
test_nghttp2_http_no_rfc9113_leading_and_trailing_ws_validation(void)13330 void test_nghttp2_http_no_rfc9113_leading_and_trailing_ws_validation(void) {
13331   nghttp2_session *session;
13332   nghttp2_session_callbacks callbacks;
13333   nghttp2_hd_deflater deflater;
13334   nghttp2_mem *mem;
13335   nghttp2_bufs bufs;
13336   ssize_t rv;
13337   const nghttp2_nv ws_reqnv[] = {
13338       MAKE_NV(":path", "/"),
13339       MAKE_NV(":method", "GET"),
13340       MAKE_NV(":authority", "localhost"),
13341       MAKE_NV(":scheme", "https"),
13342       MAKE_NV("foo", "bar "),
13343   };
13344   nghttp2_outbound_item *item;
13345   nghttp2_option *option;
13346 
13347   mem = nghttp2_mem_default();
13348   frame_pack_bufs_init(&bufs);
13349 
13350   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
13351   callbacks.send_callback = null_send_callback;
13352 
13353   /* By default, the leading and trailing white spaces validation is
13354      enabled as per RFC 9113. */
13355   nghttp2_session_server_new(&session, &callbacks, NULL);
13356 
13357   nghttp2_hd_deflate_init(&deflater, mem);
13358 
13359   rv = pack_headers(&bufs, &deflater, 1,
13360                     NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM,
13361                     ws_reqnv, ARRLEN(ws_reqnv), mem);
13362 
13363   CU_ASSERT(0 == rv);
13364 
13365   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
13366                                 nghttp2_buf_len(&bufs.head->buf));
13367 
13368   CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
13369 
13370   item = nghttp2_session_get_next_ob_item(session);
13371 
13372   CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
13373   CU_ASSERT(0 == nghttp2_session_send(session));
13374 
13375   nghttp2_bufs_reset(&bufs);
13376   nghttp2_hd_deflate_free(&deflater);
13377   nghttp2_session_del(session);
13378 
13379   /* Turn off the validation */
13380   nghttp2_option_new(&option);
13381   nghttp2_option_set_no_rfc9113_leading_and_trailing_ws_validation(option, 1);
13382 
13383   nghttp2_session_server_new2(&session, &callbacks, NULL, option);
13384 
13385   nghttp2_hd_deflate_init(&deflater, mem);
13386 
13387   rv = pack_headers(&bufs, &deflater, 1,
13388                     NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM,
13389                     ws_reqnv, ARRLEN(ws_reqnv), mem);
13390 
13391   CU_ASSERT(0 == rv);
13392 
13393   rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
13394                                 nghttp2_buf_len(&bufs.head->buf));
13395 
13396   CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
13397 
13398   item = nghttp2_session_get_next_ob_item(session);
13399 
13400   CU_ASSERT(NULL == item);
13401 
13402   nghttp2_bufs_reset(&bufs);
13403   nghttp2_hd_deflate_free(&deflater);
13404   nghttp2_session_del(session);
13405   nghttp2_option_del(option);
13406 
13407   nghttp2_bufs_free(&bufs);
13408 }
13409