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