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