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