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