• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * nghttp2 - HTTP/2 C Library
3  *
4  * Copyright (c) 2013 Tatsuhiro Tsujikawa
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining
7  * a copy of this software and associated documentation files (the
8  * "Software"), to deal in the Software without restriction, including
9  * without limitation the rights to use, copy, modify, merge, publish,
10  * distribute, sublicense, and/or sell copies of the Software, and to
11  * permit persons to whom the Software is furnished to do so, subject to
12  * the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be
15  * included in all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24  */
25 #include "nghttp2_session_test.h"
26 
27 #include <stdio.h>
28 #include <assert.h>
29 
30 #include "munit.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_assertion.h"
38 #include "nghttp2_priority_spec.h"
39 #include "nghttp2_extpri.h"
40 
41 static const MunitTest tests[] = {
42   munit_void_test(test_nghttp2_session_recv),
43   munit_void_test(test_nghttp2_session_recv_invalid_stream_id),
44   munit_void_test(test_nghttp2_session_recv_invalid_frame),
45   munit_void_test(test_nghttp2_session_recv_eof),
46   munit_void_test(test_nghttp2_session_recv_data),
47   munit_void_test(test_nghttp2_session_recv_data_no_auto_flow_control),
48   munit_void_test(test_nghttp2_session_recv_continuation),
49   munit_void_test(test_nghttp2_session_recv_headers_with_priority),
50   munit_void_test(test_nghttp2_session_recv_headers_with_padding),
51   munit_void_test(test_nghttp2_session_recv_headers_early_response),
52   munit_void_test(test_nghttp2_session_recv_headers_for_closed_stream),
53   munit_void_test(test_nghttp2_session_recv_headers_with_extpri),
54   munit_void_test(test_nghttp2_session_server_recv_push_response),
55   munit_void_test(test_nghttp2_session_recv_premature_headers),
56   munit_void_test(test_nghttp2_session_recv_unknown_frame),
57   munit_void_test(test_nghttp2_session_recv_unexpected_continuation),
58   munit_void_test(test_nghttp2_session_recv_settings_header_table_size),
59   munit_void_test(test_nghttp2_session_recv_too_large_frame_length),
60   munit_void_test(test_nghttp2_session_recv_extension),
61   munit_void_test(test_nghttp2_session_recv_altsvc),
62   munit_void_test(test_nghttp2_session_recv_origin),
63   munit_void_test(test_nghttp2_session_recv_priority_update),
64   munit_void_test(test_nghttp2_session_continue),
65   munit_void_test(test_nghttp2_session_add_frame),
66   munit_void_test(test_nghttp2_session_on_request_headers_received),
67   munit_void_test(test_nghttp2_session_on_response_headers_received),
68   munit_void_test(test_nghttp2_session_on_headers_received),
69   munit_void_test(test_nghttp2_session_on_push_response_headers_received),
70   munit_void_test(test_nghttp2_session_on_priority_received),
71   munit_void_test(test_nghttp2_session_on_rst_stream_received),
72   munit_void_test(test_nghttp2_session_on_settings_received),
73   munit_void_test(test_nghttp2_session_on_push_promise_received),
74   munit_void_test(test_nghttp2_session_on_ping_received),
75   munit_void_test(test_nghttp2_session_on_goaway_received),
76   munit_void_test(test_nghttp2_session_on_window_update_received),
77   munit_void_test(test_nghttp2_session_on_data_received),
78   munit_void_test(test_nghttp2_session_on_data_received_fail_fast),
79   munit_void_test(test_nghttp2_session_on_altsvc_received),
80   munit_void_test(test_nghttp2_session_send_headers_start_stream),
81   munit_void_test(test_nghttp2_session_send_headers_reply),
82   munit_void_test(test_nghttp2_session_send_headers_frame_size_error),
83   munit_void_test(test_nghttp2_session_send_headers_push_reply),
84   munit_void_test(test_nghttp2_session_send_rst_stream),
85   munit_void_test(test_nghttp2_session_send_push_promise),
86   munit_void_test(test_nghttp2_session_is_my_stream_id),
87   munit_void_test(test_nghttp2_session_upgrade2),
88   munit_void_test(test_nghttp2_session_reprioritize_stream),
89   munit_void_test(
90     test_nghttp2_session_reprioritize_stream_with_idle_stream_dep),
91   munit_void_test(test_nghttp2_submit_data),
92   munit_void_test(test_nghttp2_submit_data_read_length_too_large),
93   munit_void_test(test_nghttp2_submit_data_read_length_smallest),
94   munit_void_test(test_nghttp2_submit_data_twice),
95   munit_void_test(test_nghttp2_submit_request_with_data),
96   munit_void_test(test_nghttp2_submit_request_without_data),
97   munit_void_test(test_nghttp2_submit_response_with_data),
98   munit_void_test(test_nghttp2_submit_response_without_data),
99   munit_void_test(test_nghttp2_submit_response_push_response),
100   munit_void_test(test_nghttp2_submit_trailer),
101   munit_void_test(test_nghttp2_submit_headers_start_stream),
102   munit_void_test(test_nghttp2_submit_headers_reply),
103   munit_void_test(test_nghttp2_submit_headers_push_reply),
104   munit_void_test(test_nghttp2_submit_headers),
105   munit_void_test(test_nghttp2_submit_headers_continuation),
106   munit_void_test(test_nghttp2_submit_headers_continuation_extra_large),
107   munit_void_test(test_nghttp2_submit_priority),
108   munit_void_test(test_nghttp2_submit_settings),
109   munit_void_test(test_nghttp2_submit_settings_update_local_window_size),
110   munit_void_test(test_nghttp2_submit_settings_multiple_times),
111   munit_void_test(test_nghttp2_submit_push_promise),
112   munit_void_test(test_nghttp2_submit_window_update),
113   munit_void_test(test_nghttp2_submit_window_update_local_window_size),
114   munit_void_test(test_nghttp2_submit_shutdown_notice),
115   munit_void_test(test_nghttp2_submit_invalid_nv),
116   munit_void_test(test_nghttp2_submit_extension),
117   munit_void_test(test_nghttp2_submit_altsvc),
118   munit_void_test(test_nghttp2_submit_origin),
119   munit_void_test(test_nghttp2_submit_priority_update),
120   munit_void_test(test_nghttp2_submit_rst_stream),
121   munit_void_test(test_nghttp2_session_open_stream),
122   munit_void_test(test_nghttp2_session_open_stream_with_idle_stream_dep),
123   munit_void_test(test_nghttp2_session_get_next_ob_item),
124   munit_void_test(test_nghttp2_session_pop_next_ob_item),
125   munit_void_test(test_nghttp2_session_reply_fail),
126   munit_void_test(test_nghttp2_session_max_concurrent_streams),
127   munit_void_test(test_nghttp2_session_stop_data_with_rst_stream),
128   munit_void_test(test_nghttp2_session_defer_data),
129   munit_void_test(test_nghttp2_session_flow_control),
130   munit_void_test(test_nghttp2_session_flow_control_data_recv),
131   munit_void_test(test_nghttp2_session_flow_control_data_with_padding_recv),
132   munit_void_test(test_nghttp2_session_data_read_temporal_failure),
133   munit_void_test(test_nghttp2_session_on_stream_close),
134   munit_void_test(test_nghttp2_session_on_ctrl_not_send),
135   munit_void_test(test_nghttp2_session_get_outbound_queue_size),
136   munit_void_test(test_nghttp2_session_get_effective_local_window_size),
137   munit_void_test(test_nghttp2_session_set_option),
138   munit_void_test(test_nghttp2_session_data_backoff_by_high_pri_frame),
139   munit_void_test(test_nghttp2_session_pack_data_with_padding),
140   munit_void_test(test_nghttp2_session_pack_headers_with_padding),
141   munit_void_test(test_nghttp2_pack_settings_payload),
142   munit_void_test(test_nghttp2_session_stream_dep_add),
143   munit_void_test(test_nghttp2_session_stream_dep_remove),
144   munit_void_test(test_nghttp2_session_stream_dep_add_subtree),
145   munit_void_test(test_nghttp2_session_stream_dep_remove_subtree),
146   munit_void_test(
147     test_nghttp2_session_stream_dep_all_your_stream_are_belong_to_us),
148   munit_void_test(test_nghttp2_session_stream_attach_item),
149   munit_void_test(test_nghttp2_session_stream_attach_item_subtree),
150   munit_void_test(test_nghttp2_session_stream_get_state),
151   munit_void_test(test_nghttp2_session_stream_get_something),
152   munit_void_test(test_nghttp2_session_find_stream),
153   munit_void_test(test_nghttp2_session_keep_closed_stream),
154   munit_void_test(test_nghttp2_session_keep_idle_stream),
155   munit_void_test(test_nghttp2_session_detach_idle_stream),
156   munit_void_test(test_nghttp2_session_large_dep_tree),
157   munit_void_test(test_nghttp2_session_graceful_shutdown),
158   munit_void_test(test_nghttp2_session_on_header_temporal_failure),
159   munit_void_test(test_nghttp2_session_recv_client_magic),
160   munit_void_test(test_nghttp2_session_delete_data_item),
161   munit_void_test(test_nghttp2_session_open_idle_stream),
162   munit_void_test(test_nghttp2_session_cancel_reserved_remote),
163   munit_void_test(test_nghttp2_session_reset_pending_headers),
164   munit_void_test(test_nghttp2_session_send_data_callback),
165   munit_void_test(test_nghttp2_session_on_begin_headers_temporal_failure),
166   munit_void_test(test_nghttp2_session_defer_then_close),
167   munit_void_test(test_nghttp2_session_detach_item_from_closed_stream),
168   munit_void_test(test_nghttp2_session_flooding),
169   munit_void_test(test_nghttp2_session_change_stream_priority),
170   munit_void_test(test_nghttp2_session_change_extpri_stream_priority),
171   munit_void_test(test_nghttp2_session_create_idle_stream),
172   munit_void_test(test_nghttp2_session_repeated_priority_change),
173   munit_void_test(test_nghttp2_session_repeated_priority_submission),
174   munit_void_test(test_nghttp2_session_set_local_window_size),
175   munit_void_test(test_nghttp2_session_cancel_from_before_frame_send),
176   munit_void_test(test_nghttp2_session_too_many_settings),
177   munit_void_test(test_nghttp2_session_removed_closed_stream),
178   munit_void_test(test_nghttp2_session_pause_data),
179   munit_void_test(test_nghttp2_session_no_closed_streams),
180   munit_void_test(test_nghttp2_session_set_stream_user_data),
181   munit_void_test(test_nghttp2_session_no_rfc7540_priorities),
182   munit_void_test(test_nghttp2_session_server_fallback_rfc7540_priorities),
183   munit_void_test(test_nghttp2_session_stream_reset_ratelim),
184   munit_void_test(test_nghttp2_http_mandatory_headers),
185   munit_void_test(test_nghttp2_http_content_length),
186   munit_void_test(test_nghttp2_http_content_length_mismatch),
187   munit_void_test(test_nghttp2_http_non_final_response),
188   munit_void_test(test_nghttp2_http_trailer_headers),
189   munit_void_test(test_nghttp2_http_ignore_regular_header),
190   munit_void_test(test_nghttp2_http_ignore_content_length),
191   munit_void_test(test_nghttp2_http_record_request_method),
192   munit_void_test(test_nghttp2_http_push_promise),
193   munit_void_test(test_nghttp2_http_head_method_upgrade_workaround),
194   munit_void_test(
195     test_nghttp2_http_no_rfc9113_leading_and_trailing_ws_validation),
196   munit_test_end(),
197 };
198 
199 const MunitSuite session_suite = {
200   "/session", tests, NULL, 1, MUNIT_SUITE_OPTION_NONE,
201 };
202 
203 typedef struct {
204   uint8_t buf[65535];
205   size_t length;
206 } accumulator;
207 
208 typedef struct {
209   uint8_t data[8192];
210   uint8_t *datamark;
211   uint8_t *datalimit;
212   size_t feedseq[8192];
213   size_t seqidx;
214 } scripted_data_feed;
215 
216 typedef struct {
217   accumulator *acc;
218   scripted_data_feed *df;
219   int frame_recv_cb_called, invalid_frame_recv_cb_called;
220   uint8_t recv_frame_type;
221   nghttp2_frame_hd recv_frame_hd;
222   int frame_send_cb_called;
223   uint8_t sent_frame_type;
224   int before_frame_send_cb_called;
225   int frame_not_send_cb_called;
226   uint8_t not_sent_frame_type;
227   int not_sent_error;
228   int stream_close_cb_called;
229   uint32_t stream_close_error_code;
230   size_t data_source_length;
231   int32_t stream_id;
232   size_t block_count;
233   int data_chunk_recv_cb_called;
234   const nghttp2_frame *frame;
235   size_t fixed_sendlen;
236   int header_cb_called;
237   int invalid_header_cb_called;
238   int begin_headers_cb_called;
239   nghttp2_nv nv;
240   size_t data_chunk_len;
241   size_t padlen;
242   int begin_frame_cb_called;
243   nghttp2_buf scratchbuf;
244   size_t data_source_read_cb_paused;
245 } my_user_data;
246 
247 static const nghttp2_nv reqnv[] = {
248   MAKE_NV(":method", "GET"),
249   MAKE_NV(":path", "/"),
250   MAKE_NV(":scheme", "https"),
251   MAKE_NV(":authority", "localhost"),
252 };
253 
254 static const nghttp2_nv resnv[] = {
255   MAKE_NV(":status", "200"),
256 };
257 
258 static const nghttp2_nv trailernv[] = {
259   // from http://tools.ietf.org/html/rfc6249#section-7
260   MAKE_NV("digest", "SHA-256="
261                     "MWVkMWQxYTRiMzk5MDQ0MzI3NGU5NDEyZTk5OWY1ZGFmNzgyZTJlODYz"
262                     "YjRjYzFhOTlmNTQwYzI2M2QwM2U2MQ=="),
263 };
264 
scripted_data_feed_init2(scripted_data_feed * df,nghttp2_bufs * bufs)265 static void scripted_data_feed_init2(scripted_data_feed *df,
266                                      nghttp2_bufs *bufs) {
267   nghttp2_buf_chain *ci;
268   nghttp2_buf *buf;
269   uint8_t *ptr;
270   size_t len;
271 
272   memset(df, 0, sizeof(scripted_data_feed));
273   ptr = df->data;
274   len = 0;
275 
276   for (ci = bufs->head; ci; ci = ci->next) {
277     buf = &ci->buf;
278     ptr = nghttp2_cpymem(ptr, buf->pos, nghttp2_buf_len(buf));
279     len += nghttp2_buf_len(buf);
280   }
281 
282   df->datamark = df->data;
283   df->datalimit = df->data + len;
284   df->feedseq[0] = len;
285 }
286 
null_send_callback(nghttp2_session * session,const uint8_t * data,size_t len,int flags,void * user_data)287 static nghttp2_ssize null_send_callback(nghttp2_session *session,
288                                         const uint8_t *data, size_t len,
289                                         int flags, void *user_data) {
290   (void)session;
291   (void)data;
292   (void)flags;
293   (void)user_data;
294 
295   return (nghttp2_ssize)len;
296 }
297 
fail_send_callback(nghttp2_session * session,const uint8_t * data,size_t len,int flags,void * user_data)298 static nghttp2_ssize fail_send_callback(nghttp2_session *session,
299                                         const uint8_t *data, size_t len,
300                                         int flags, void *user_data) {
301   (void)session;
302   (void)data;
303   (void)len;
304   (void)flags;
305   (void)user_data;
306 
307   return NGHTTP2_ERR_CALLBACK_FAILURE;
308 }
309 
fixed_bytes_send_callback(nghttp2_session * session,const uint8_t * data,size_t len,int flags,void * user_data)310 static nghttp2_ssize fixed_bytes_send_callback(nghttp2_session *session,
311                                                const uint8_t *data, size_t len,
312                                                int flags, void *user_data) {
313   size_t fixed_sendlen = ((my_user_data *)user_data)->fixed_sendlen;
314   (void)session;
315   (void)data;
316   (void)flags;
317 
318   return (nghttp2_ssize)(fixed_sendlen < len ? fixed_sendlen : len);
319 }
320 
scripted_recv_callback(nghttp2_session * session,uint8_t * data,size_t len,int flags,void * user_data)321 static nghttp2_ssize scripted_recv_callback(nghttp2_session *session,
322                                             uint8_t *data, size_t len,
323                                             int flags, void *user_data) {
324   scripted_data_feed *df = ((my_user_data *)user_data)->df;
325   size_t wlen = df->feedseq[df->seqidx] > len ? len : df->feedseq[df->seqidx];
326   (void)session;
327   (void)flags;
328 
329   memcpy(data, df->datamark, wlen);
330   df->datamark += wlen;
331   df->feedseq[df->seqidx] -= wlen;
332   if (df->feedseq[df->seqidx] == 0) {
333     ++df->seqidx;
334   }
335   return (nghttp2_ssize)wlen;
336 }
337 
eof_recv_callback(nghttp2_session * session,uint8_t * data,size_t len,int flags,void * user_data)338 static nghttp2_ssize eof_recv_callback(nghttp2_session *session, uint8_t *data,
339                                        size_t len, int flags, void *user_data) {
340   (void)session;
341   (void)data;
342   (void)len;
343   (void)flags;
344   (void)user_data;
345 
346   return NGHTTP2_ERR_EOF;
347 }
348 
accumulator_send_callback(nghttp2_session * session,const uint8_t * buf,size_t len,int flags,void * user_data)349 static nghttp2_ssize accumulator_send_callback(nghttp2_session *session,
350                                                const uint8_t *buf, size_t len,
351                                                int flags, void *user_data) {
352   accumulator *acc = ((my_user_data *)user_data)->acc;
353   (void)session;
354   (void)flags;
355 
356   assert(acc->length + len < sizeof(acc->buf));
357   memcpy(acc->buf + acc->length, buf, len);
358   acc->length += len;
359   return (nghttp2_ssize)len;
360 }
361 
on_begin_frame_callback(nghttp2_session * session,const nghttp2_frame_hd * hd,void * user_data)362 static int on_begin_frame_callback(nghttp2_session *session,
363                                    const nghttp2_frame_hd *hd,
364                                    void *user_data) {
365   my_user_data *ud = (my_user_data *)user_data;
366   (void)session;
367   (void)hd;
368 
369   ++ud->begin_frame_cb_called;
370   return 0;
371 }
372 
on_frame_recv_callback(nghttp2_session * session,const nghttp2_frame * frame,void * user_data)373 static int on_frame_recv_callback(nghttp2_session *session,
374                                   const nghttp2_frame *frame, void *user_data) {
375   my_user_data *ud = (my_user_data *)user_data;
376   (void)session;
377 
378   ++ud->frame_recv_cb_called;
379   ud->recv_frame_type = frame->hd.type;
380   ud->recv_frame_hd = frame->hd;
381 
382   return 0;
383 }
384 
on_invalid_frame_recv_callback(nghttp2_session * session,const nghttp2_frame * frame,int lib_error_code,void * user_data)385 static int on_invalid_frame_recv_callback(nghttp2_session *session,
386                                           const nghttp2_frame *frame,
387                                           int lib_error_code, void *user_data) {
388   my_user_data *ud = (my_user_data *)user_data;
389   (void)session;
390   (void)frame;
391   (void)lib_error_code;
392 
393   ++ud->invalid_frame_recv_cb_called;
394   return 0;
395 }
396 
on_frame_send_callback(nghttp2_session * session,const nghttp2_frame * frame,void * user_data)397 static int on_frame_send_callback(nghttp2_session *session,
398                                   const nghttp2_frame *frame, void *user_data) {
399   my_user_data *ud = (my_user_data *)user_data;
400   (void)session;
401 
402   ++ud->frame_send_cb_called;
403   ud->sent_frame_type = frame->hd.type;
404   return 0;
405 }
406 
on_frame_not_send_callback(nghttp2_session * session,const nghttp2_frame * frame,int lib_error,void * user_data)407 static int on_frame_not_send_callback(nghttp2_session *session,
408                                       const nghttp2_frame *frame, int lib_error,
409                                       void *user_data) {
410   my_user_data *ud = (my_user_data *)user_data;
411   (void)session;
412 
413   ++ud->frame_not_send_cb_called;
414   ud->not_sent_frame_type = frame->hd.type;
415   ud->not_sent_error = lib_error;
416   return 0;
417 }
418 
cancel_before_frame_send_callback(nghttp2_session * session,const nghttp2_frame * frame,void * user_data)419 static int cancel_before_frame_send_callback(nghttp2_session *session,
420                                              const nghttp2_frame *frame,
421                                              void *user_data) {
422   my_user_data *ud = (my_user_data *)user_data;
423   (void)session;
424   (void)frame;
425 
426   ++ud->before_frame_send_cb_called;
427   return NGHTTP2_ERR_CANCEL;
428 }
429 
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)430 static int on_data_chunk_recv_callback(nghttp2_session *session, uint8_t flags,
431                                        int32_t stream_id, const uint8_t *data,
432                                        size_t len, void *user_data) {
433   my_user_data *ud = (my_user_data *)user_data;
434   (void)session;
435   (void)flags;
436   (void)stream_id;
437   (void)data;
438 
439   ++ud->data_chunk_recv_cb_called;
440   ud->data_chunk_len = len;
441   return 0;
442 }
443 
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)444 static int pause_on_data_chunk_recv_callback(nghttp2_session *session,
445                                              uint8_t flags, int32_t stream_id,
446                                              const uint8_t *data, size_t len,
447                                              void *user_data) {
448   my_user_data *ud = (my_user_data *)user_data;
449   (void)session;
450   (void)flags;
451   (void)stream_id;
452   (void)data;
453   (void)len;
454 
455   ++ud->data_chunk_recv_cb_called;
456   return NGHTTP2_ERR_PAUSE;
457 }
458 
select_padding_callback(nghttp2_session * session,const nghttp2_frame * frame,size_t max_payloadlen,void * user_data)459 static nghttp2_ssize select_padding_callback(nghttp2_session *session,
460                                              const nghttp2_frame *frame,
461                                              size_t max_payloadlen,
462                                              void *user_data) {
463   my_user_data *ud = (my_user_data *)user_data;
464   (void)session;
465 
466   return (nghttp2_ssize)nghttp2_min_size(max_payloadlen,
467                                          frame->hd.length + ud->padlen);
468 }
469 
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)470 static nghttp2_ssize too_large_data_source_length_callback(
471   nghttp2_session *session, uint8_t frame_type, int32_t stream_id,
472   int32_t session_remote_window_size, int32_t stream_remote_window_size,
473   uint32_t remote_max_frame_size, void *user_data) {
474   (void)session;
475   (void)frame_type;
476   (void)stream_id;
477   (void)session_remote_window_size;
478   (void)stream_remote_window_size;
479   (void)remote_max_frame_size;
480   (void)user_data;
481 
482   return NGHTTP2_MAX_FRAME_SIZE_MAX + 1;
483 }
484 
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)485 static nghttp2_ssize smallest_length_data_source_length_callback(
486   nghttp2_session *session, uint8_t frame_type, int32_t stream_id,
487   int32_t session_remote_window_size, int32_t stream_remote_window_size,
488   uint32_t remote_max_frame_size, void *user_data) {
489   (void)session;
490   (void)frame_type;
491   (void)stream_id;
492   (void)session_remote_window_size;
493   (void)stream_remote_window_size;
494   (void)remote_max_frame_size;
495   (void)user_data;
496 
497   return 1;
498 }
499 
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)500 static nghttp2_ssize fixed_length_data_source_read_callback(
501   nghttp2_session *session, int32_t stream_id, uint8_t *buf, size_t len,
502   uint32_t *data_flags, nghttp2_data_source *source, void *user_data) {
503   my_user_data *ud = (my_user_data *)user_data;
504   size_t wlen;
505   (void)session;
506   (void)stream_id;
507   (void)buf;
508   (void)source;
509 
510   if (len < ud->data_source_length) {
511     wlen = len;
512   } else {
513     wlen = ud->data_source_length;
514   }
515   ud->data_source_length -= wlen;
516   if (ud->data_source_length == 0) {
517     *data_flags |= NGHTTP2_DATA_FLAG_EOF;
518   }
519   return (nghttp2_ssize)wlen;
520 }
521 
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)522 static nghttp2_ssize temporal_failure_data_source_read_callback(
523   nghttp2_session *session, int32_t stream_id, uint8_t *buf, size_t len,
524   uint32_t *data_flags, nghttp2_data_source *source, void *user_data) {
525   (void)session;
526   (void)stream_id;
527   (void)buf;
528   (void)len;
529   (void)data_flags;
530   (void)source;
531   (void)user_data;
532 
533   return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
534 }
535 
536 static nghttp2_ssize
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)537 fail_data_source_read_callback(nghttp2_session *session, int32_t stream_id,
538                                uint8_t *buf, size_t len, uint32_t *data_flags,
539                                nghttp2_data_source *source, void *user_data) {
540   (void)session;
541   (void)stream_id;
542   (void)buf;
543   (void)len;
544   (void)data_flags;
545   (void)source;
546   (void)user_data;
547 
548   return NGHTTP2_ERR_CALLBACK_FAILURE;
549 }
550 
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)551 static nghttp2_ssize no_end_stream_data_source_read_callback(
552   nghttp2_session *session, int32_t stream_id, uint8_t *buf, size_t len,
553   uint32_t *data_flags, nghttp2_data_source *source, void *user_data) {
554   (void)session;
555   (void)stream_id;
556   (void)buf;
557   (void)len;
558   (void)source;
559   (void)user_data;
560 
561   *data_flags |= NGHTTP2_DATA_FLAG_EOF | NGHTTP2_DATA_FLAG_NO_END_STREAM;
562   return 0;
563 }
564 
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)565 static nghttp2_ssize no_copy_data_source_read_callback(
566   nghttp2_session *session, int32_t stream_id, uint8_t *buf, size_t len,
567   uint32_t *data_flags, nghttp2_data_source *source, void *user_data) {
568   my_user_data *ud = (my_user_data *)user_data;
569   size_t wlen;
570   (void)session;
571   (void)stream_id;
572   (void)buf;
573   (void)source;
574 
575   if (len < ud->data_source_length) {
576     wlen = len;
577   } else {
578     wlen = ud->data_source_length;
579   }
580 
581   ud->data_source_length -= wlen;
582 
583   *data_flags |= NGHTTP2_DATA_FLAG_NO_COPY;
584 
585   if (ud->data_source_length == 0) {
586     *data_flags |= NGHTTP2_DATA_FLAG_EOF;
587   }
588   return (nghttp2_ssize)wlen;
589 }
590 
send_data_callback(nghttp2_session * session,nghttp2_frame * frame,const uint8_t * framehd,size_t length,nghttp2_data_source * source,void * user_data)591 static int send_data_callback(nghttp2_session *session, nghttp2_frame *frame,
592                               const uint8_t *framehd, size_t length,
593                               nghttp2_data_source *source, void *user_data) {
594   accumulator *acc = ((my_user_data *)user_data)->acc;
595   (void)session;
596   (void)source;
597 
598   memcpy(acc->buf + acc->length, framehd, NGHTTP2_FRAME_HDLEN);
599   acc->length += NGHTTP2_FRAME_HDLEN;
600 
601   if (frame->data.padlen) {
602     *(acc->buf + acc->length++) = (uint8_t)(frame->data.padlen - 1);
603   }
604 
605   acc->length += length;
606 
607   if (frame->data.padlen) {
608     acc->length += frame->data.padlen - 1;
609   }
610 
611   return 0;
612 }
613 
block_count_send_callback(nghttp2_session * session,const uint8_t * data,size_t len,int flags,void * user_data)614 static nghttp2_ssize block_count_send_callback(nghttp2_session *session,
615                                                const uint8_t *data, size_t len,
616                                                int flags, void *user_data) {
617   my_user_data *ud = (my_user_data *)user_data;
618   (void)session;
619   (void)data;
620   (void)flags;
621 
622   if (ud->block_count == 0) {
623     return NGHTTP2_ERR_WOULDBLOCK;
624   }
625 
626   --ud->block_count;
627   return (nghttp2_ssize)len;
628 }
629 
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)630 static int on_header_callback(nghttp2_session *session,
631                               const nghttp2_frame *frame, const uint8_t *name,
632                               size_t namelen, const uint8_t *value,
633                               size_t valuelen, uint8_t flags, void *user_data) {
634   my_user_data *ud = (my_user_data *)user_data;
635   (void)session;
636   (void)flags;
637 
638   ++ud->header_cb_called;
639   ud->nv.name = (uint8_t *)name;
640   ud->nv.namelen = namelen;
641   ud->nv.value = (uint8_t *)value;
642   ud->nv.valuelen = valuelen;
643 
644   ud->frame = frame;
645   return 0;
646 }
647 
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)648 static int pause_on_header_callback(nghttp2_session *session,
649                                     const nghttp2_frame *frame,
650                                     const uint8_t *name, size_t namelen,
651                                     const uint8_t *value, size_t valuelen,
652                                     uint8_t flags, void *user_data) {
653   on_header_callback(session, frame, name, namelen, value, valuelen, flags,
654                      user_data);
655   return NGHTTP2_ERR_PAUSE;
656 }
657 
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)658 static int temporal_failure_on_header_callback(
659   nghttp2_session *session, const nghttp2_frame *frame, const uint8_t *name,
660   size_t namelen, const uint8_t *value, size_t valuelen, uint8_t flags,
661   void *user_data) {
662   on_header_callback(session, frame, name, namelen, value, valuelen, flags,
663                      user_data);
664   return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
665 }
666 
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)667 static int on_invalid_header_callback(nghttp2_session *session,
668                                       const nghttp2_frame *frame,
669                                       const uint8_t *name, size_t namelen,
670                                       const uint8_t *value, size_t valuelen,
671                                       uint8_t flags, void *user_data) {
672   my_user_data *ud = (my_user_data *)user_data;
673   (void)session;
674   (void)flags;
675 
676   ++ud->invalid_header_cb_called;
677   ud->nv.name = (uint8_t *)name;
678   ud->nv.namelen = namelen;
679   ud->nv.value = (uint8_t *)value;
680   ud->nv.valuelen = valuelen;
681 
682   ud->frame = frame;
683   return 0;
684 }
685 
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)686 static int pause_on_invalid_header_callback(nghttp2_session *session,
687                                             const nghttp2_frame *frame,
688                                             const uint8_t *name, size_t namelen,
689                                             const uint8_t *value,
690                                             size_t valuelen, uint8_t flags,
691                                             void *user_data) {
692   on_invalid_header_callback(session, frame, name, namelen, value, valuelen,
693                              flags, user_data);
694   return NGHTTP2_ERR_PAUSE;
695 }
696 
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)697 static int reset_on_invalid_header_callback(nghttp2_session *session,
698                                             const nghttp2_frame *frame,
699                                             const uint8_t *name, size_t namelen,
700                                             const uint8_t *value,
701                                             size_t valuelen, uint8_t flags,
702                                             void *user_data) {
703   on_invalid_header_callback(session, frame, name, namelen, value, valuelen,
704                              flags, user_data);
705   return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
706 }
707 
on_begin_headers_callback(nghttp2_session * session,const nghttp2_frame * frame,void * user_data)708 static int on_begin_headers_callback(nghttp2_session *session,
709                                      const nghttp2_frame *frame,
710                                      void *user_data) {
711   my_user_data *ud = (my_user_data *)user_data;
712   (void)session;
713   (void)frame;
714 
715   ++ud->begin_headers_cb_called;
716   return 0;
717 }
718 
temporal_failure_on_begin_headers_callback(nghttp2_session * session,const nghttp2_frame * frame,void * user_data)719 static int temporal_failure_on_begin_headers_callback(
720   nghttp2_session *session, const nghttp2_frame *frame, void *user_data) {
721   on_begin_headers_callback(session, frame, user_data);
722   return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
723 }
724 
725 static nghttp2_ssize
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)726 defer_data_source_read_callback(nghttp2_session *session, int32_t stream_id,
727                                 uint8_t *buf, size_t len, uint32_t *data_flags,
728                                 nghttp2_data_source *source, void *user_data) {
729   (void)session;
730   (void)stream_id;
731   (void)buf;
732   (void)len;
733   (void)data_flags;
734   (void)source;
735   (void)user_data;
736 
737   return NGHTTP2_ERR_DEFERRED;
738 }
739 
on_stream_close_callback(nghttp2_session * session,int32_t stream_id,uint32_t error_code,void * user_data)740 static int on_stream_close_callback(nghttp2_session *session, int32_t stream_id,
741                                     uint32_t error_code, void *user_data) {
742   my_user_data *my_data = (my_user_data *)user_data;
743   (void)session;
744   (void)stream_id;
745   (void)error_code;
746 
747   ++my_data->stream_close_cb_called;
748   my_data->stream_close_error_code = error_code;
749 
750   return 0;
751 }
752 
fatal_error_on_stream_close_callback(nghttp2_session * session,int32_t stream_id,uint32_t error_code,void * user_data)753 static int fatal_error_on_stream_close_callback(nghttp2_session *session,
754                                                 int32_t stream_id,
755                                                 uint32_t error_code,
756                                                 void *user_data) {
757   on_stream_close_callback(session, stream_id, error_code, user_data);
758 
759   return NGHTTP2_ERR_CALLBACK_FAILURE;
760 }
761 
pack_extension_callback(nghttp2_session * session,uint8_t * buf,size_t len,const nghttp2_frame * frame,void * user_data)762 static nghttp2_ssize pack_extension_callback(nghttp2_session *session,
763                                              uint8_t *buf, size_t len,
764                                              const nghttp2_frame *frame,
765                                              void *user_data) {
766   nghttp2_buf *p = frame->ext.payload;
767   (void)session;
768   (void)len;
769   (void)user_data;
770 
771   memcpy(buf, p->pos, nghttp2_buf_len(p));
772 
773   return (nghttp2_ssize)nghttp2_buf_len(p);
774 }
775 
on_extension_chunk_recv_callback(nghttp2_session * session,const nghttp2_frame_hd * hd,const uint8_t * data,size_t len,void * user_data)776 static int on_extension_chunk_recv_callback(nghttp2_session *session,
777                                             const nghttp2_frame_hd *hd,
778                                             const uint8_t *data, size_t len,
779                                             void *user_data) {
780   my_user_data *my_data = (my_user_data *)user_data;
781   nghttp2_buf *buf = &my_data->scratchbuf;
782   (void)session;
783   (void)hd;
784 
785   buf->last = nghttp2_cpymem(buf->last, data, len);
786 
787   return 0;
788 }
789 
cancel_on_extension_chunk_recv_callback(nghttp2_session * session,const nghttp2_frame_hd * hd,const uint8_t * data,size_t len,void * user_data)790 static int cancel_on_extension_chunk_recv_callback(nghttp2_session *session,
791                                                    const nghttp2_frame_hd *hd,
792                                                    const uint8_t *data,
793                                                    size_t len,
794                                                    void *user_data) {
795   (void)session;
796   (void)hd;
797   (void)data;
798   (void)len;
799   (void)user_data;
800 
801   return NGHTTP2_ERR_CANCEL;
802 }
803 
unpack_extension_callback(nghttp2_session * session,void ** payload,const nghttp2_frame_hd * hd,void * user_data)804 static int unpack_extension_callback(nghttp2_session *session, void **payload,
805                                      const nghttp2_frame_hd *hd,
806                                      void *user_data) {
807   my_user_data *my_data = (my_user_data *)user_data;
808   nghttp2_buf *buf = &my_data->scratchbuf;
809   (void)session;
810   (void)hd;
811 
812   *payload = buf;
813 
814   return 0;
815 }
816 
cancel_unpack_extension_callback(nghttp2_session * session,void ** payload,const nghttp2_frame_hd * hd,void * user_data)817 static int cancel_unpack_extension_callback(nghttp2_session *session,
818                                             void **payload,
819                                             const nghttp2_frame_hd *hd,
820                                             void *user_data) {
821   (void)session;
822   (void)payload;
823   (void)hd;
824   (void)user_data;
825 
826   return NGHTTP2_ERR_CANCEL;
827 }
828 
dup_iv(const nghttp2_settings_entry * iv,size_t niv)829 static nghttp2_settings_entry *dup_iv(const nghttp2_settings_entry *iv,
830                                       size_t niv) {
831   return nghttp2_frame_iv_copy(iv, niv, nghttp2_mem_default());
832 }
833 
834 static nghttp2_priority_spec pri_spec_default = {0, NGHTTP2_DEFAULT_WEIGHT, 0};
835 
test_nghttp2_session_recv(void)836 void test_nghttp2_session_recv(void) {
837   nghttp2_session *session;
838   nghttp2_session_callbacks callbacks;
839   scripted_data_feed df;
840   my_user_data user_data;
841   nghttp2_bufs bufs;
842   size_t framelen;
843   nghttp2_frame frame;
844   size_t i;
845   nghttp2_outbound_item *item;
846   nghttp2_nv *nva;
847   size_t nvlen;
848   nghttp2_hd_deflater deflater;
849   int rv;
850   nghttp2_mem *mem;
851 
852   mem = nghttp2_mem_default();
853   frame_pack_bufs_init(&bufs);
854 
855   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
856   callbacks.send_callback2 = null_send_callback;
857   callbacks.recv_callback2 = scripted_recv_callback;
858   callbacks.on_frame_recv_callback = on_frame_recv_callback;
859   callbacks.on_begin_frame_callback = on_begin_frame_callback;
860 
861   user_data.df = &df;
862 
863   nghttp2_session_server_new(&session, &callbacks, &user_data);
864   nghttp2_hd_deflate_init(&deflater, mem);
865 
866   nvlen = ARRLEN(reqnv);
867   nghttp2_nv_array_copy(&nva, reqnv, nvlen, mem);
868   nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 1,
869                              NGHTTP2_HCAT_HEADERS, NULL, nva, nvlen);
870   rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
871 
872   assert_int(0, ==, rv);
873 
874   scripted_data_feed_init2(&df, &bufs);
875 
876   framelen = nghttp2_bufs_len(&bufs);
877 
878   /* Send 1 byte per each read */
879   for (i = 0; i < framelen; ++i) {
880     df.feedseq[i] = 1;
881   }
882 
883   nghttp2_frame_headers_free(&frame.headers, mem);
884 
885   user_data.frame_recv_cb_called = 0;
886   user_data.begin_frame_cb_called = 0;
887 
888   while (df.seqidx < framelen) {
889     assert_int(0, ==, nghttp2_session_recv(session));
890   }
891   assert_int(1, ==, user_data.frame_recv_cb_called);
892   assert_int(1, ==, user_data.begin_frame_cb_called);
893 
894   nghttp2_bufs_reset(&bufs);
895 
896   /* Receive PRIORITY */
897   nghttp2_frame_priority_init(&frame.priority, 5, &pri_spec_default);
898 
899   nghttp2_frame_pack_priority(&bufs, &frame.priority);
900 
901   nghttp2_frame_priority_free(&frame.priority);
902 
903   scripted_data_feed_init2(&df, &bufs);
904 
905   user_data.frame_recv_cb_called = 0;
906   user_data.begin_frame_cb_called = 0;
907 
908   assert_int(0, ==, nghttp2_session_recv(session));
909   assert_int(1, ==, user_data.frame_recv_cb_called);
910   assert_int(1, ==, user_data.begin_frame_cb_called);
911 
912   nghttp2_bufs_reset(&bufs);
913 
914   nghttp2_hd_deflate_free(&deflater);
915   nghttp2_session_del(session);
916 
917   /* Some tests for frame too large */
918   nghttp2_session_server_new(&session, &callbacks, &user_data);
919 
920   /* Receive PING with too large payload */
921   nghttp2_frame_ping_init(&frame.ping, NGHTTP2_FLAG_NONE, NULL);
922 
923   nghttp2_frame_pack_ping(&bufs, &frame.ping);
924 
925   /* Add extra 16 bytes */
926   nghttp2_bufs_seek_last_present(&bufs);
927   assert(nghttp2_buf_len(&bufs.cur->buf) >= 16);
928 
929   bufs.cur->buf.last += 16;
930   nghttp2_put_uint32be(
931     bufs.cur->buf.pos,
932     (uint32_t)(((frame.hd.length + 16) << 8) + bufs.cur->buf.pos[3]));
933 
934   nghttp2_frame_ping_free(&frame.ping);
935 
936   scripted_data_feed_init2(&df, &bufs);
937   user_data.frame_recv_cb_called = 0;
938   user_data.begin_frame_cb_called = 0;
939 
940   assert_int(0, ==, nghttp2_session_recv(session));
941   assert_int(0, ==, user_data.frame_recv_cb_called);
942   assert_int(0, ==, user_data.begin_frame_cb_called);
943 
944   item = nghttp2_session_get_next_ob_item(session);
945   assert_uint8(NGHTTP2_GOAWAY, ==, item->frame.hd.type);
946   assert_uint32(NGHTTP2_FRAME_SIZE_ERROR, ==, item->frame.goaway.error_code);
947   assert_int(0, ==, nghttp2_session_send(session));
948 
949   nghttp2_bufs_free(&bufs);
950   nghttp2_session_del(session);
951 }
952 
test_nghttp2_session_recv_invalid_stream_id(void)953 void test_nghttp2_session_recv_invalid_stream_id(void) {
954   nghttp2_session *session;
955   nghttp2_session_callbacks callbacks;
956   scripted_data_feed df;
957   my_user_data user_data;
958   nghttp2_bufs bufs;
959   nghttp2_frame frame;
960   nghttp2_hd_deflater deflater;
961   int rv;
962   nghttp2_mem *mem;
963   nghttp2_nv *nva;
964   size_t nvlen;
965 
966   mem = nghttp2_mem_default();
967   frame_pack_bufs_init(&bufs);
968 
969   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
970   callbacks.recv_callback2 = scripted_recv_callback;
971   callbacks.on_invalid_frame_recv_callback = on_invalid_frame_recv_callback;
972 
973   user_data.df = &df;
974   user_data.invalid_frame_recv_cb_called = 0;
975   nghttp2_session_server_new(&session, &callbacks, &user_data);
976   nghttp2_hd_deflate_init(&deflater, mem);
977 
978   nvlen = ARRLEN(reqnv);
979   nghttp2_nv_array_copy(&nva, reqnv, nvlen, mem);
980   nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 2,
981                              NGHTTP2_HCAT_HEADERS, NULL, nva, nvlen);
982   rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
983 
984   assert_int(0, ==, rv);
985   assert_size(0, <, nghttp2_bufs_len(&bufs));
986 
987   scripted_data_feed_init2(&df, &bufs);
988   nghttp2_frame_headers_free(&frame.headers, mem);
989 
990   assert_int(0, ==, nghttp2_session_recv(session));
991   assert_int(1, ==, user_data.invalid_frame_recv_cb_called);
992 
993   nghttp2_bufs_free(&bufs);
994   nghttp2_hd_deflate_free(&deflater);
995   nghttp2_session_del(session);
996 }
997 
test_nghttp2_session_recv_invalid_frame(void)998 void test_nghttp2_session_recv_invalid_frame(void) {
999   nghttp2_session *session;
1000   nghttp2_session_callbacks callbacks;
1001   scripted_data_feed df;
1002   my_user_data user_data;
1003   nghttp2_bufs bufs;
1004   nghttp2_frame frame;
1005   nghttp2_nv *nva;
1006   size_t nvlen;
1007   nghttp2_hd_deflater deflater;
1008   int rv;
1009   nghttp2_mem *mem;
1010 
1011   mem = nghttp2_mem_default();
1012   frame_pack_bufs_init(&bufs);
1013 
1014   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
1015   callbacks.recv_callback2 = scripted_recv_callback;
1016   callbacks.send_callback2 = null_send_callback;
1017   callbacks.on_frame_send_callback = on_frame_send_callback;
1018 
1019   user_data.df = &df;
1020   user_data.frame_send_cb_called = 0;
1021   nghttp2_session_server_new(&session, &callbacks, &user_data);
1022   nghttp2_hd_deflate_init(&deflater, mem);
1023   nvlen = ARRLEN(reqnv);
1024   nghttp2_nv_array_copy(&nva, reqnv, nvlen, mem);
1025   nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 1,
1026                              NGHTTP2_HCAT_HEADERS, NULL, nva, nvlen);
1027   rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
1028 
1029   assert_int(0, ==, rv);
1030   assert_size(0, <, nghttp2_bufs_len(&bufs));
1031 
1032   scripted_data_feed_init2(&df, &bufs);
1033 
1034   assert_int(0, ==, nghttp2_session_recv(session));
1035   assert_int(0, ==, nghttp2_session_send(session));
1036   assert_int(0, ==, user_data.frame_send_cb_called);
1037 
1038   /* Receive exactly same bytes of HEADERS is treated as error, because it has
1039    * pseudo headers and without END_STREAM flag set */
1040   scripted_data_feed_init2(&df, &bufs);
1041 
1042   assert_int(0, ==, nghttp2_session_recv(session));
1043   assert_int(0, ==, nghttp2_session_send(session));
1044   assert_int(1, ==, user_data.frame_send_cb_called);
1045   assert_uint8(NGHTTP2_RST_STREAM, ==, user_data.sent_frame_type);
1046 
1047   nghttp2_bufs_free(&bufs);
1048   nghttp2_frame_headers_free(&frame.headers, mem);
1049 
1050   nghttp2_hd_deflate_free(&deflater);
1051   nghttp2_session_del(session);
1052 }
1053 
test_nghttp2_session_recv_eof(void)1054 void test_nghttp2_session_recv_eof(void) {
1055   nghttp2_session *session;
1056   nghttp2_session_callbacks callbacks;
1057 
1058   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
1059   callbacks.send_callback2 = null_send_callback;
1060   callbacks.recv_callback2 = eof_recv_callback;
1061 
1062   nghttp2_session_client_new(&session, &callbacks, NULL);
1063   assert_int(NGHTTP2_ERR_EOF, ==, nghttp2_session_recv(session));
1064 
1065   nghttp2_session_del(session);
1066 }
1067 
test_nghttp2_session_recv_data(void)1068 void test_nghttp2_session_recv_data(void) {
1069   nghttp2_session *session;
1070   nghttp2_session_callbacks callbacks;
1071   my_user_data ud;
1072   uint8_t data[8092];
1073   nghttp2_ssize rv;
1074   nghttp2_outbound_item *item;
1075   nghttp2_stream *stream;
1076   nghttp2_frame_hd hd;
1077   int i;
1078 
1079   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
1080   callbacks.send_callback2 = null_send_callback;
1081   callbacks.on_data_chunk_recv_callback = on_data_chunk_recv_callback;
1082   callbacks.on_frame_recv_callback = on_frame_recv_callback;
1083   callbacks.on_frame_send_callback = on_frame_send_callback;
1084 
1085   nghttp2_session_client_new(&session, &callbacks, &ud);
1086 
1087   /* Create DATA frame with length 4KiB */
1088   memset(data, 0, sizeof(data));
1089   hd.length = 4096;
1090   hd.type = NGHTTP2_DATA;
1091   hd.flags = NGHTTP2_FLAG_NONE;
1092   hd.stream_id = 1;
1093   nghttp2_frame_pack_frame_hd(data, &hd);
1094 
1095   /* stream 1 is not opened, so it must be responded with connection
1096      error.  This is not mandated by the spec */
1097   ud.data_chunk_recv_cb_called = 0;
1098   ud.frame_recv_cb_called = 0;
1099   rv = nghttp2_session_mem_recv2(session, data, NGHTTP2_FRAME_HDLEN + 4096);
1100   assert_ptrdiff(NGHTTP2_FRAME_HDLEN + 4096, ==, rv);
1101 
1102   assert_int(0, ==, ud.data_chunk_recv_cb_called);
1103   assert_int(0, ==, ud.frame_recv_cb_called);
1104   item = nghttp2_session_get_next_ob_item(session);
1105   assert_uint8(NGHTTP2_GOAWAY, ==, item->frame.hd.type);
1106 
1107   nghttp2_session_del(session);
1108 
1109   nghttp2_session_client_new(&session, &callbacks, &ud);
1110 
1111   /* Create stream 1 with CLOSING state. DATA is ignored. */
1112   stream = open_sent_stream2(session, 1, NGHTTP2_STREAM_CLOSING);
1113 
1114   /* Set initial window size 16383 to check stream flow control,
1115      isolating it from the connection flow control */
1116   stream->local_window_size = 16383;
1117 
1118   ud.data_chunk_recv_cb_called = 0;
1119   ud.frame_recv_cb_called = 0;
1120   rv = nghttp2_session_mem_recv2(session, data, NGHTTP2_FRAME_HDLEN + 4096);
1121   assert_ptrdiff(NGHTTP2_FRAME_HDLEN + 4096, ==, rv);
1122 
1123   assert_int(0, ==, ud.data_chunk_recv_cb_called);
1124   assert_int(0, ==, ud.frame_recv_cb_called);
1125   item = nghttp2_session_get_next_ob_item(session);
1126   assert_null(item);
1127 
1128   /* This is normal case. DATA is acceptable. */
1129   stream->state = NGHTTP2_STREAM_OPENED;
1130 
1131   ud.data_chunk_recv_cb_called = 0;
1132   ud.frame_recv_cb_called = 0;
1133   rv = nghttp2_session_mem_recv2(session, data, NGHTTP2_FRAME_HDLEN + 4096);
1134   assert_ptrdiff(NGHTTP2_FRAME_HDLEN + 4096, ==, rv);
1135 
1136   assert_int(1, ==, ud.data_chunk_recv_cb_called);
1137   assert_int(1, ==, ud.frame_recv_cb_called);
1138 
1139   assert_null(nghttp2_session_get_next_ob_item(session));
1140 
1141   ud.data_chunk_recv_cb_called = 0;
1142   ud.frame_recv_cb_called = 0;
1143   rv = nghttp2_session_mem_recv2(session, data, NGHTTP2_FRAME_HDLEN + 4096);
1144   assert_ptrdiff(NGHTTP2_FRAME_HDLEN + 4096, ==, rv);
1145 
1146   /* Now we got data more than initial-window-size / 2, WINDOW_UPDATE
1147      must be queued */
1148   assert_int(1, ==, ud.data_chunk_recv_cb_called);
1149   assert_int(1, ==, ud.frame_recv_cb_called);
1150   item = nghttp2_session_get_next_ob_item(session);
1151   assert_uint8(NGHTTP2_WINDOW_UPDATE, ==, item->frame.hd.type);
1152   assert_int32(1, ==, item->frame.window_update.hd.stream_id);
1153   assert_int(0, ==, nghttp2_session_send(session));
1154 
1155   /* Set initial window size to 1MiB, so that we can check connection
1156      flow control individually */
1157   stream->local_window_size = 1 << 20;
1158   /* Connection flow control takes into account DATA which is received
1159      in the error condition. We have received 4096 * 4 bytes of
1160      DATA. Additional 4 DATA frames, connection flow control will kick
1161      in. */
1162   for (i = 0; i < 5; ++i) {
1163     rv = nghttp2_session_mem_recv2(session, data, NGHTTP2_FRAME_HDLEN + 4096);
1164     assert_ptrdiff(NGHTTP2_FRAME_HDLEN + 4096, ==, rv);
1165   }
1166   item = nghttp2_session_get_next_ob_item(session);
1167   assert_uint8(NGHTTP2_WINDOW_UPDATE, ==, item->frame.hd.type);
1168   assert_int32(0, ==, item->frame.window_update.hd.stream_id);
1169   assert_int(0, ==, nghttp2_session_send(session));
1170 
1171   /* Reception of DATA with stream ID = 0 causes connection error */
1172   hd.length = 4096;
1173   hd.type = NGHTTP2_DATA;
1174   hd.flags = NGHTTP2_FLAG_NONE;
1175   hd.stream_id = 0;
1176   nghttp2_frame_pack_frame_hd(data, &hd);
1177 
1178   ud.data_chunk_recv_cb_called = 0;
1179   ud.frame_recv_cb_called = 0;
1180   rv = nghttp2_session_mem_recv2(session, data, NGHTTP2_FRAME_HDLEN + 4096);
1181   assert_ptrdiff(NGHTTP2_FRAME_HDLEN + 4096, ==, rv);
1182 
1183   assert_int(0, ==, ud.data_chunk_recv_cb_called);
1184   assert_int(0, ==, ud.frame_recv_cb_called);
1185   item = nghttp2_session_get_next_ob_item(session);
1186   assert_uint8(NGHTTP2_GOAWAY, ==, item->frame.hd.type);
1187   assert_uint32(NGHTTP2_PROTOCOL_ERROR, ==, item->frame.goaway.error_code);
1188 
1189   nghttp2_session_del(session);
1190 
1191   /* Check window_update_queued flag in both session and stream */
1192   nghttp2_session_server_new(&session, &callbacks, &ud);
1193 
1194   hd.length = 4096;
1195   hd.type = NGHTTP2_DATA;
1196   hd.flags = NGHTTP2_FLAG_NONE;
1197   hd.stream_id = 1;
1198   nghttp2_frame_pack_frame_hd(data, &hd);
1199 
1200   stream = open_recv_stream(session, 1);
1201 
1202   /* Send 32767 bytes of DATA.  In our current flow control algorithm,
1203      it triggers first WINDOW_UPDATE of window_size_increment
1204      32767. */
1205   for (i = 0; i < 7; ++i) {
1206     rv = nghttp2_session_mem_recv2(session, data, NGHTTP2_FRAME_HDLEN + 4096);
1207     assert_ptrdiff(NGHTTP2_FRAME_HDLEN + 4096, ==, rv);
1208   }
1209 
1210   hd.length = 4095;
1211   nghttp2_frame_pack_frame_hd(data, &hd);
1212   rv = nghttp2_session_mem_recv2(session, data, NGHTTP2_FRAME_HDLEN + 4095);
1213   assert_ptrdiff(NGHTTP2_FRAME_HDLEN + 4095, ==, rv);
1214 
1215   /* Now 2 WINDOW_UPDATEs for session and stream should be queued. */
1216   assert_int32(0, ==, stream->recv_window_size);
1217   assert_int32(0, ==, session->recv_window_size);
1218   assert_true(stream->window_update_queued);
1219   assert_true(session->window_update_queued);
1220 
1221   /* Then send 32768 bytes of DATA.  Since we have not sent queued
1222      WINDOW_UDPATE frame, recv_window_size should not be decreased */
1223   hd.length = 4096;
1224   nghttp2_frame_pack_frame_hd(data, &hd);
1225 
1226   for (i = 0; i < 8; ++i) {
1227     rv = nghttp2_session_mem_recv2(session, data, NGHTTP2_FRAME_HDLEN + 4096);
1228     assert_ptrdiff(NGHTTP2_FRAME_HDLEN + 4096, ==, rv);
1229   }
1230 
1231   /* WINDOW_UPDATE is blocked for session and stream, so
1232      recv_window_size must not be decreased. */
1233   assert_int32(32768, ==, stream->recv_window_size);
1234   assert_int32(32768, ==, session->recv_window_size);
1235   assert_true(stream->window_update_queued);
1236   assert_true(session->window_update_queued);
1237 
1238   ud.frame_send_cb_called = 0;
1239 
1240   /* This sends queued WINDOW_UPDATES.  And then check
1241      recv_window_size, and queue WINDOW_UPDATEs for both session and
1242      stream, and send them at once. */
1243   assert_int(0, ==, nghttp2_session_send(session));
1244 
1245   assert_int(4, ==, ud.frame_send_cb_called);
1246   assert_int32(0, ==, stream->recv_window_size);
1247   assert_int32(0, ==, session->recv_window_size);
1248   assert_false(stream->window_update_queued);
1249   assert_false(session->window_update_queued);
1250 
1251   nghttp2_session_del(session);
1252 }
1253 
test_nghttp2_session_recv_data_no_auto_flow_control(void)1254 void test_nghttp2_session_recv_data_no_auto_flow_control(void) {
1255   nghttp2_session *session;
1256   nghttp2_session_callbacks callbacks;
1257   my_user_data ud;
1258   nghttp2_option *option;
1259   nghttp2_frame_hd hd;
1260   size_t padlen;
1261   uint8_t data[8192];
1262   nghttp2_ssize rv;
1263   size_t sendlen;
1264   nghttp2_stream *stream;
1265   size_t i;
1266 
1267   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
1268   callbacks.send_callback2 = null_send_callback;
1269   callbacks.on_frame_send_callback = on_frame_send_callback;
1270 
1271   nghttp2_option_new(&option);
1272   nghttp2_option_set_no_auto_window_update(option, 1);
1273 
1274   nghttp2_session_server_new2(&session, &callbacks, &ud, option);
1275 
1276   /* Create DATA frame with length 4KiB + 11 bytes padding*/
1277   padlen = 11;
1278   memset(data, 0, sizeof(data));
1279   hd.length = 4096 + 1 + padlen;
1280   hd.type = NGHTTP2_DATA;
1281   hd.flags = NGHTTP2_FLAG_PADDED;
1282   hd.stream_id = 1;
1283   nghttp2_frame_pack_frame_hd(data, &hd);
1284   data[NGHTTP2_FRAME_HDLEN] = (uint8_t)padlen;
1285 
1286   /* First create stream 1, then close it.  Check that data is
1287      consumed for connection in this situation */
1288   open_recv_stream(session, 1);
1289 
1290   /* Receive first 100 bytes */
1291   sendlen = 100;
1292   rv = nghttp2_session_mem_recv2(session, data, sendlen);
1293   assert_ptrdiff((nghttp2_ssize)sendlen, ==, rv);
1294 
1295   /* We consumed pad length field (1 byte) */
1296   assert_int32(1, ==, session->consumed_size);
1297 
1298   /* close stream here */
1299   nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, 1, NGHTTP2_NO_ERROR);
1300   nghttp2_session_send(session);
1301 
1302   /* stream 1 has been closed, and we disabled auto flow-control, so
1303      data must be immediately consumed for connection. */
1304   rv = nghttp2_session_mem_recv2(session, data + sendlen,
1305                                  NGHTTP2_FRAME_HDLEN + hd.length - sendlen);
1306   assert_ptrdiff((nghttp2_ssize)(NGHTTP2_FRAME_HDLEN + hd.length - sendlen), ==,
1307                  rv);
1308 
1309   /* We already consumed pad length field (1 byte), so do +1 here */
1310   assert_int32((int32_t)(NGHTTP2_FRAME_HDLEN + hd.length - sendlen + 1), ==,
1311                session->consumed_size);
1312 
1313   nghttp2_session_del(session);
1314 
1315   /* Reuse DATA created previously. */
1316 
1317   nghttp2_session_server_new2(&session, &callbacks, &ud, option);
1318 
1319   /* Now we are expecting final response header, which means receiving
1320      DATA for that stream is illegal. */
1321   stream = open_recv_stream(session, 1);
1322   stream->http_flags |= NGHTTP2_HTTP_FLAG_EXPECT_FINAL_RESPONSE;
1323 
1324   rv =
1325     nghttp2_session_mem_recv2(session, data, NGHTTP2_FRAME_HDLEN + hd.length);
1326   assert_ptrdiff((nghttp2_ssize)(NGHTTP2_FRAME_HDLEN + hd.length), ==, rv);
1327 
1328   /* Whole payload must be consumed now because HTTP messaging rule
1329      was not honored. */
1330   assert_int32((int32_t)hd.length, ==, session->consumed_size);
1331 
1332   nghttp2_session_del(session);
1333 
1334   /* Check window_update_queued flag in both session and stream */
1335   nghttp2_session_server_new2(&session, &callbacks, &ud, option);
1336 
1337   stream = open_recv_stream(session, 1);
1338 
1339   hd.length = 4096;
1340   hd.type = NGHTTP2_DATA;
1341   hd.flags = NGHTTP2_FLAG_NONE;
1342   hd.stream_id = 1;
1343   nghttp2_frame_pack_frame_hd(data, &hd);
1344 
1345   /* Receive up to 65535 bytes of DATA */
1346   for (i = 0; i < 15; ++i) {
1347     rv = nghttp2_session_mem_recv2(session, data, NGHTTP2_FRAME_HDLEN + 4096);
1348     assert_ptrdiff(NGHTTP2_FRAME_HDLEN + 4096, ==, rv);
1349   }
1350 
1351   hd.length = 4095;
1352   nghttp2_frame_pack_frame_hd(data, &hd);
1353 
1354   rv = nghttp2_session_mem_recv2(session, data, NGHTTP2_FRAME_HDLEN + 4095);
1355   assert_ptrdiff(NGHTTP2_FRAME_HDLEN + 4095, ==, rv);
1356 
1357   assert_int32(65535, ==, session->recv_window_size);
1358   assert_int32(65535, ==, stream->recv_window_size);
1359 
1360   /* The first call of nghttp2_session_consume_connection() will queue
1361      WINDOW_UPDATE.  Next call does not. */
1362   nghttp2_session_consume_connection(session, 32767);
1363   nghttp2_session_consume_connection(session, 32768);
1364 
1365   assert_int32(32768, ==, session->recv_window_size);
1366   assert_int32(65535, ==, stream->recv_window_size);
1367   assert_true(session->window_update_queued);
1368   assert_false(stream->window_update_queued);
1369 
1370   ud.frame_send_cb_called = 0;
1371 
1372   /* This will send WINDOW_UPDATE, and check whether we should send
1373      WINDOW_UPDATE, and queue and send it at once. */
1374   assert_int(0, ==, nghttp2_session_send(session));
1375   assert_int32(0, ==, session->recv_window_size);
1376   assert_int32(65535, ==, stream->recv_window_size);
1377   assert_false(session->window_update_queued);
1378   assert_false(stream->window_update_queued);
1379   assert_int(2, ==, ud.frame_send_cb_called);
1380 
1381   /* Do the same for stream */
1382   nghttp2_session_consume_stream(session, 1, 32767);
1383   nghttp2_session_consume_stream(session, 1, 32768);
1384 
1385   assert_int32(0, ==, session->recv_window_size);
1386   assert_int32(32768, ==, stream->recv_window_size);
1387   assert_false(session->window_update_queued);
1388   assert_true(stream->window_update_queued);
1389 
1390   ud.frame_send_cb_called = 0;
1391 
1392   assert_int(0, ==, nghttp2_session_send(session));
1393   assert_int32(0, ==, session->recv_window_size);
1394   assert_int32(0, ==, stream->recv_window_size);
1395   assert_false(session->window_update_queued);
1396   assert_false(stream->window_update_queued);
1397   assert_int(2, ==, ud.frame_send_cb_called);
1398 
1399   nghttp2_session_del(session);
1400   nghttp2_option_del(option);
1401 }
1402 
test_nghttp2_session_recv_continuation(void)1403 void test_nghttp2_session_recv_continuation(void) {
1404   nghttp2_session *session;
1405   nghttp2_session_callbacks callbacks;
1406   nghttp2_nv *nva;
1407   size_t nvlen;
1408   nghttp2_frame frame;
1409   nghttp2_bufs bufs;
1410   nghttp2_buf *buf;
1411   nghttp2_ssize rv;
1412   my_user_data ud;
1413   nghttp2_hd_deflater deflater;
1414   uint8_t data[1024];
1415   size_t datalen;
1416   nghttp2_frame_hd cont_hd;
1417   nghttp2_priority_spec pri_spec;
1418   nghttp2_mem *mem;
1419 
1420   mem = nghttp2_mem_default();
1421   frame_pack_bufs_init(&bufs);
1422 
1423   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
1424   callbacks.on_header_callback = on_header_callback;
1425   callbacks.on_begin_headers_callback = on_begin_headers_callback;
1426   callbacks.on_begin_frame_callback = on_begin_frame_callback;
1427 
1428   nghttp2_session_server_new(&session, &callbacks, &ud);
1429 
1430   nghttp2_hd_deflate_init(&deflater, mem);
1431 
1432   /* Make 1 HEADERS and insert CONTINUATION header */
1433   nvlen = ARRLEN(reqnv);
1434   nghttp2_nv_array_copy(&nva, reqnv, nvlen, mem);
1435   nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_NONE, 1,
1436                              NGHTTP2_HCAT_HEADERS, NULL, nva, nvlen);
1437   rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
1438 
1439   assert_ptrdiff(0, ==, rv);
1440   assert_size(0, <, nghttp2_bufs_len(&bufs));
1441 
1442   /* make sure that all data is in the first buf */
1443   buf = &bufs.head->buf;
1444   assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
1445 
1446   nghttp2_frame_headers_free(&frame.headers, mem);
1447 
1448   /* HEADERS's payload is 1 byte */
1449   memcpy(data, buf->pos, NGHTTP2_FRAME_HDLEN + 1);
1450   datalen = NGHTTP2_FRAME_HDLEN + 1;
1451   buf->pos += NGHTTP2_FRAME_HDLEN + 1;
1452 
1453   nghttp2_put_uint32be(data, (uint32_t)((1 << 8) + data[3]));
1454 
1455   /* First CONTINUATION, 2 bytes */
1456   nghttp2_frame_hd_init(&cont_hd, 2, NGHTTP2_CONTINUATION, NGHTTP2_FLAG_NONE,
1457                         1);
1458 
1459   nghttp2_frame_pack_frame_hd(data + datalen, &cont_hd);
1460   datalen += NGHTTP2_FRAME_HDLEN;
1461 
1462   memcpy(data + datalen, buf->pos, cont_hd.length);
1463   datalen += cont_hd.length;
1464   buf->pos += cont_hd.length;
1465 
1466   /* Second CONTINUATION, rest of the bytes */
1467   nghttp2_frame_hd_init(&cont_hd, nghttp2_buf_len(buf), NGHTTP2_CONTINUATION,
1468                         NGHTTP2_FLAG_END_HEADERS, 1);
1469 
1470   nghttp2_frame_pack_frame_hd(data + datalen, &cont_hd);
1471   datalen += NGHTTP2_FRAME_HDLEN;
1472 
1473   memcpy(data + datalen, buf->pos, cont_hd.length);
1474   datalen += cont_hd.length;
1475   buf->pos += cont_hd.length;
1476 
1477   assert_size(0, ==, nghttp2_buf_len(buf));
1478 
1479   ud.header_cb_called = 0;
1480   ud.begin_frame_cb_called = 0;
1481 
1482   rv = nghttp2_session_mem_recv2(session, data, datalen);
1483   assert_ptrdiff((nghttp2_ssize)datalen, ==, rv);
1484   assert_int(4, ==, ud.header_cb_called);
1485   assert_int(3, ==, ud.begin_frame_cb_called);
1486 
1487   nghttp2_hd_deflate_free(&deflater);
1488   nghttp2_session_del(session);
1489 
1490   /* HEADERS with padding followed by CONTINUATION */
1491   nghttp2_session_server_new(&session, &callbacks, &ud);
1492 
1493   nghttp2_hd_deflate_init(&deflater, mem);
1494 
1495   nvlen = ARRLEN(reqnv);
1496   nghttp2_nv_array_copy(&nva, reqnv, nvlen, mem);
1497   nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_NONE, 1,
1498                              NGHTTP2_HCAT_HEADERS, NULL, nva, nvlen);
1499 
1500   nghttp2_bufs_reset(&bufs);
1501   rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
1502 
1503   assert_ptrdiff(0, ==, rv);
1504 
1505   nghttp2_frame_headers_free(&frame.headers, mem);
1506 
1507   /* make sure that all data is in the first buf */
1508   buf = &bufs.head->buf;
1509   assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
1510 
1511   /* HEADERS payload is 3 byte (1 for padding field, 1 for padding) */
1512   memcpy(data, buf->pos, NGHTTP2_FRAME_HDLEN);
1513   nghttp2_put_uint32be(data, (uint32_t)((3 << 8) + data[3]));
1514   data[4] |= NGHTTP2_FLAG_PADDED;
1515   /* padding field */
1516   data[NGHTTP2_FRAME_HDLEN] = 1;
1517   data[NGHTTP2_FRAME_HDLEN + 1] = buf->pos[NGHTTP2_FRAME_HDLEN];
1518   /* padding */
1519   data[NGHTTP2_FRAME_HDLEN + 2] = 0;
1520   datalen = NGHTTP2_FRAME_HDLEN + 3;
1521   buf->pos += NGHTTP2_FRAME_HDLEN + 1;
1522 
1523   /* CONTINUATION, rest of the bytes */
1524   nghttp2_frame_hd_init(&cont_hd, nghttp2_buf_len(buf), NGHTTP2_CONTINUATION,
1525                         NGHTTP2_FLAG_END_HEADERS, 1);
1526   nghttp2_frame_pack_frame_hd(data + datalen, &cont_hd);
1527   datalen += NGHTTP2_FRAME_HDLEN;
1528 
1529   memcpy(data + datalen, buf->pos, cont_hd.length);
1530   datalen += cont_hd.length;
1531   buf->pos += cont_hd.length;
1532 
1533   assert_size(0, ==, nghttp2_buf_len(buf));
1534 
1535   ud.header_cb_called = 0;
1536   ud.begin_frame_cb_called = 0;
1537 
1538   rv = nghttp2_session_mem_recv2(session, data, datalen);
1539 
1540   assert_ptrdiff((nghttp2_ssize)datalen, ==, rv);
1541   assert_int(4, ==, ud.header_cb_called);
1542   assert_int(2, ==, ud.begin_frame_cb_called);
1543 
1544   nghttp2_hd_deflate_free(&deflater);
1545   nghttp2_session_del(session);
1546 
1547   /* Expecting CONTINUATION, but get the other frame */
1548   nghttp2_session_server_new(&session, &callbacks, &ud);
1549 
1550   nghttp2_hd_deflate_init(&deflater, mem);
1551 
1552   /* HEADERS without END_HEADERS flag */
1553   nvlen = ARRLEN(reqnv);
1554   nghttp2_nv_array_copy(&nva, reqnv, nvlen, mem);
1555   nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_NONE, 1,
1556                              NGHTTP2_HCAT_HEADERS, NULL, nva, nvlen);
1557   nghttp2_bufs_reset(&bufs);
1558   rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
1559 
1560   assert_ptrdiff(0, ==, rv);
1561   assert_size(0, <, nghttp2_bufs_len(&bufs));
1562 
1563   nghttp2_frame_headers_free(&frame.headers, mem);
1564 
1565   /* make sure that all data is in the first buf */
1566   buf = &bufs.head->buf;
1567   assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
1568 
1569   memcpy(data, buf->pos, nghttp2_buf_len(buf));
1570   datalen = nghttp2_buf_len(buf);
1571 
1572   /* Followed by PRIORITY */
1573   nghttp2_priority_spec_default_init(&pri_spec);
1574 
1575   nghttp2_frame_priority_init(&frame.priority, 1, &pri_spec);
1576   nghttp2_bufs_reset(&bufs);
1577 
1578   nghttp2_frame_pack_priority(&bufs, &frame.priority);
1579 
1580   assert_size(0, <, nghttp2_bufs_len(&bufs));
1581 
1582   memcpy(data + datalen, buf->pos, nghttp2_buf_len(buf));
1583   datalen += nghttp2_buf_len(buf);
1584 
1585   ud.begin_headers_cb_called = 0;
1586   rv = nghttp2_session_mem_recv2(session, data, datalen);
1587   assert_ptrdiff((nghttp2_ssize)datalen, ==, rv);
1588 
1589   assert_int(1, ==, ud.begin_headers_cb_called);
1590   assert_uint8(NGHTTP2_GOAWAY, ==,
1591                nghttp2_session_get_next_ob_item(session)->frame.hd.type);
1592 
1593   nghttp2_bufs_free(&bufs);
1594   nghttp2_hd_deflate_free(&deflater);
1595   nghttp2_session_del(session);
1596 }
1597 
test_nghttp2_session_recv_headers_with_priority(void)1598 void test_nghttp2_session_recv_headers_with_priority(void) {
1599   nghttp2_session *session;
1600   nghttp2_session_callbacks callbacks;
1601   nghttp2_nv *nva;
1602   size_t nvlen;
1603   nghttp2_frame frame;
1604   nghttp2_bufs bufs;
1605   nghttp2_buf *buf;
1606   nghttp2_ssize rv;
1607   my_user_data ud;
1608   nghttp2_hd_deflater deflater;
1609   nghttp2_outbound_item *item;
1610   nghttp2_priority_spec pri_spec;
1611   nghttp2_stream *stream;
1612   nghttp2_mem *mem;
1613 
1614   mem = nghttp2_mem_default();
1615   frame_pack_bufs_init(&bufs);
1616 
1617   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
1618   callbacks.on_frame_recv_callback = on_frame_recv_callback;
1619 
1620   nghttp2_session_server_new(&session, &callbacks, &ud);
1621 
1622   nghttp2_hd_deflate_init(&deflater, mem);
1623 
1624   open_recv_stream(session, 1);
1625 
1626   /* With NGHTTP2_FLAG_PRIORITY without exclusive flag set */
1627   nvlen = ARRLEN(reqnv);
1628   nghttp2_nv_array_copy(&nva, reqnv, nvlen, mem);
1629 
1630   nghttp2_priority_spec_init(&pri_spec, 1, 99, 0);
1631 
1632   nghttp2_frame_headers_init(&frame.headers,
1633                              NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PRIORITY,
1634                              3, NGHTTP2_HCAT_HEADERS, &pri_spec, nva, nvlen);
1635 
1636   rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
1637 
1638   assert_ptrdiff(0, ==, rv);
1639   assert_size(0, <, nghttp2_bufs_len(&bufs));
1640 
1641   nghttp2_frame_headers_free(&frame.headers, mem);
1642 
1643   buf = &bufs.head->buf;
1644   assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
1645 
1646   ud.frame_recv_cb_called = 0;
1647 
1648   rv = nghttp2_session_mem_recv2(session, buf->pos, nghttp2_buf_len(buf));
1649 
1650   assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(buf), ==, rv);
1651   assert_int(1, ==, ud.frame_recv_cb_called);
1652 
1653   stream = nghttp2_session_get_stream(session, 3);
1654 
1655   assert_int32(99, ==, stream->weight);
1656   assert_int32(1, ==, stream->dep_prev->stream_id);
1657 
1658   nghttp2_bufs_reset(&bufs);
1659 
1660   /* With NGHTTP2_FLAG_PRIORITY, but cut last 1 byte to make it
1661      invalid. */
1662   nvlen = ARRLEN(reqnv);
1663   nghttp2_nv_array_copy(&nva, reqnv, nvlen, mem);
1664 
1665   nghttp2_priority_spec_init(&pri_spec, 0, 99, 0);
1666 
1667   nghttp2_frame_headers_init(&frame.headers,
1668                              NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PRIORITY,
1669                              5, NGHTTP2_HCAT_HEADERS, &pri_spec, nva, nvlen);
1670 
1671   rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
1672 
1673   assert_ptrdiff(0, ==, rv);
1674   assert_size(NGHTTP2_FRAME_HDLEN + 5, <, nghttp2_bufs_len(&bufs));
1675 
1676   nghttp2_frame_headers_free(&frame.headers, mem);
1677 
1678   buf = &bufs.head->buf;
1679   /* Make payload shorter than required length to store priority
1680      group */
1681   nghttp2_put_uint32be(buf->pos, (uint32_t)((4 << 8) + buf->pos[3]));
1682 
1683   ud.frame_recv_cb_called = 0;
1684 
1685   rv = nghttp2_session_mem_recv2(session, buf->pos, nghttp2_buf_len(buf));
1686 
1687   assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(buf), ==, rv);
1688   assert_int(0, ==, ud.frame_recv_cb_called);
1689 
1690   stream = nghttp2_session_get_stream(session, 5);
1691 
1692   assert_null(stream);
1693 
1694   item = nghttp2_session_get_next_ob_item(session);
1695   assert_not_null(item);
1696   assert_uint8(NGHTTP2_GOAWAY, ==, item->frame.hd.type);
1697   assert_uint32(NGHTTP2_FRAME_SIZE_ERROR, ==, item->frame.goaway.error_code);
1698 
1699   nghttp2_bufs_reset(&bufs);
1700 
1701   nghttp2_hd_deflate_free(&deflater);
1702   nghttp2_session_del(session);
1703 
1704   /* Check dep_stream_id == stream_id */
1705   nghttp2_session_server_new(&session, &callbacks, &ud);
1706 
1707   nghttp2_hd_deflate_init(&deflater, mem);
1708 
1709   nvlen = ARRLEN(reqnv);
1710   nghttp2_nv_array_copy(&nva, reqnv, nvlen, mem);
1711 
1712   nghttp2_priority_spec_init(&pri_spec, 1, 0, 0);
1713 
1714   nghttp2_frame_headers_init(&frame.headers,
1715                              NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PRIORITY,
1716                              1, NGHTTP2_HCAT_HEADERS, &pri_spec, nva, nvlen);
1717 
1718   rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
1719 
1720   assert_ptrdiff(0, ==, rv);
1721   assert_size(0, <, nghttp2_bufs_len(&bufs));
1722 
1723   nghttp2_frame_headers_free(&frame.headers, mem);
1724 
1725   buf = &bufs.head->buf;
1726   assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
1727 
1728   ud.frame_recv_cb_called = 0;
1729 
1730   rv = nghttp2_session_mem_recv2(session, buf->pos, nghttp2_buf_len(buf));
1731 
1732   assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(buf), ==, rv);
1733   assert_int(0, ==, ud.frame_recv_cb_called);
1734 
1735   stream = nghttp2_session_get_stream(session, 1);
1736 
1737   assert_null(stream);
1738 
1739   item = nghttp2_session_get_next_ob_item(session);
1740   assert_not_null(item);
1741   assert_uint8(NGHTTP2_GOAWAY, ==, item->frame.hd.type);
1742   assert_uint32(NGHTTP2_PROTOCOL_ERROR, ==, item->frame.goaway.error_code);
1743 
1744   nghttp2_bufs_reset(&bufs);
1745 
1746   nghttp2_bufs_free(&bufs);
1747   nghttp2_hd_deflate_free(&deflater);
1748   nghttp2_session_del(session);
1749 }
1750 
test_nghttp2_session_recv_headers_with_padding(void)1751 void test_nghttp2_session_recv_headers_with_padding(void) {
1752   nghttp2_session *session;
1753   nghttp2_session_callbacks callbacks;
1754   nghttp2_bufs bufs;
1755   nghttp2_buf *buf;
1756   nghttp2_frame_hd hd;
1757   nghttp2_outbound_item *item;
1758   my_user_data ud;
1759   nghttp2_ssize rv;
1760 
1761   frame_pack_bufs_init(&bufs);
1762 
1763   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
1764   callbacks.on_frame_recv_callback = on_frame_recv_callback;
1765   callbacks.send_callback2 = null_send_callback;
1766 
1767   /* HEADERS: Wrong padding length */
1768   nghttp2_session_server_new(&session, &callbacks, &ud);
1769   nghttp2_session_send(session);
1770 
1771   nghttp2_frame_hd_init(
1772     &hd, 10, NGHTTP2_HEADERS,
1773     NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PRIORITY | NGHTTP2_FLAG_PADDED, 1);
1774   buf = &bufs.head->buf;
1775   nghttp2_frame_pack_frame_hd(buf->last, &hd);
1776   buf->last += NGHTTP2_FRAME_HDLEN;
1777   /* padding is 6 bytes */
1778   *buf->last++ = 5;
1779   /* priority field */
1780   nghttp2_put_uint32be(buf->last, 3);
1781   buf->last += sizeof(uint32_t);
1782   *buf->last++ = 1;
1783   /* rest is garbage */
1784   memset(buf->last, 0, 4);
1785   buf->last += 4;
1786 
1787   ud.frame_recv_cb_called = 0;
1788 
1789   rv = nghttp2_session_mem_recv2(session, buf->pos, nghttp2_buf_len(buf));
1790 
1791   assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(buf), ==, rv);
1792   assert_int(0, ==, ud.frame_recv_cb_called);
1793 
1794   item = nghttp2_session_get_next_ob_item(session);
1795 
1796   assert_not_null(item);
1797   assert_uint8(NGHTTP2_GOAWAY, ==, item->frame.hd.type);
1798 
1799   nghttp2_bufs_reset(&bufs);
1800   nghttp2_session_del(session);
1801 
1802   /* PUSH_PROMISE: Wrong padding length */
1803   nghttp2_session_client_new(&session, &callbacks, &ud);
1804   nghttp2_session_send(session);
1805 
1806   open_sent_stream(session, 1);
1807 
1808   nghttp2_frame_hd_init(&hd, 9, NGHTTP2_PUSH_PROMISE,
1809                         NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PADDED, 1);
1810   buf = &bufs.head->buf;
1811   nghttp2_frame_pack_frame_hd(buf->last, &hd);
1812   buf->last += NGHTTP2_FRAME_HDLEN;
1813   /* padding is 6 bytes */
1814   *buf->last++ = 5;
1815   /* promised stream ID field */
1816   nghttp2_put_uint32be(buf->last, 2);
1817   buf->last += sizeof(uint32_t);
1818   /* rest is garbage */
1819   memset(buf->last, 0, 4);
1820   buf->last += 4;
1821 
1822   ud.frame_recv_cb_called = 0;
1823 
1824   rv = nghttp2_session_mem_recv2(session, buf->pos, nghttp2_buf_len(buf));
1825 
1826   assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(buf), ==, rv);
1827   assert_int(0, ==, ud.frame_recv_cb_called);
1828 
1829   item = nghttp2_session_get_next_ob_item(session);
1830 
1831   assert_not_null(item);
1832   assert_uint8(NGHTTP2_GOAWAY, ==, item->frame.hd.type);
1833 
1834   nghttp2_bufs_free(&bufs);
1835   nghttp2_session_del(session);
1836 }
1837 
response_on_begin_frame_callback(nghttp2_session * session,const nghttp2_frame_hd * hd,void * user_data)1838 static int response_on_begin_frame_callback(nghttp2_session *session,
1839                                             const nghttp2_frame_hd *hd,
1840                                             void *user_data) {
1841   int rv;
1842   (void)user_data;
1843 
1844   if (hd->type != NGHTTP2_HEADERS) {
1845     return 0;
1846   }
1847 
1848   rv = nghttp2_submit_response2(session, hd->stream_id, resnv, ARRLEN(resnv),
1849                                 NULL);
1850 
1851   assert_int(0, ==, rv);
1852 
1853   return 0;
1854 }
1855 
test_nghttp2_session_recv_headers_early_response(void)1856 void test_nghttp2_session_recv_headers_early_response(void) {
1857   nghttp2_session *session;
1858   nghttp2_session_callbacks callbacks;
1859   nghttp2_bufs bufs;
1860   nghttp2_buf *buf;
1861   nghttp2_hd_deflater deflater;
1862   nghttp2_mem *mem;
1863   nghttp2_nv *nva;
1864   size_t nvlen;
1865   nghttp2_frame frame;
1866   nghttp2_ssize rv;
1867   nghttp2_stream *stream;
1868 
1869   mem = nghttp2_mem_default();
1870   frame_pack_bufs_init(&bufs);
1871 
1872   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
1873   callbacks.send_callback2 = null_send_callback;
1874   callbacks.on_begin_frame_callback = response_on_begin_frame_callback;
1875 
1876   nghttp2_session_server_new(&session, &callbacks, NULL);
1877 
1878   nghttp2_hd_deflate_init(&deflater, mem);
1879 
1880   nvlen = ARRLEN(reqnv);
1881   nghttp2_nv_array_copy(&nva, reqnv, nvlen, mem);
1882   nghttp2_frame_headers_init(&frame.headers,
1883                              NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM,
1884                              1, NGHTTP2_HCAT_REQUEST, NULL, nva, nvlen);
1885 
1886   rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
1887 
1888   assert_ptrdiff(0, ==, rv);
1889 
1890   nghttp2_frame_headers_free(&frame.headers, mem);
1891 
1892   buf = &bufs.head->buf;
1893 
1894   /* Only receive 9 bytes headers, and invoke
1895      on_begin_frame_callback */
1896   rv = nghttp2_session_mem_recv2(session, buf->pos, 9);
1897 
1898   assert_ptrdiff(9, ==, rv);
1899 
1900   rv = nghttp2_session_send(session);
1901 
1902   assert_ptrdiff(0, ==, rv);
1903 
1904   rv =
1905     nghttp2_session_mem_recv2(session, buf->pos + 9, nghttp2_buf_len(buf) - 9);
1906 
1907   assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(buf) - 9, ==, rv);
1908 
1909   stream = nghttp2_session_get_stream_raw(session, 1);
1910 
1911   assert_true(stream->flags & NGHTTP2_STREAM_FLAG_CLOSED);
1912 
1913   nghttp2_hd_deflate_free(&deflater);
1914   nghttp2_session_del(session);
1915   nghttp2_bufs_free(&bufs);
1916 }
1917 
test_nghttp2_session_recv_headers_for_closed_stream(void)1918 void test_nghttp2_session_recv_headers_for_closed_stream(void) {
1919   nghttp2_session *session;
1920   nghttp2_session_callbacks callbacks;
1921   nghttp2_nv *nva;
1922   size_t nvlen;
1923   nghttp2_frame frame;
1924   nghttp2_bufs bufs;
1925   nghttp2_buf *buf;
1926   nghttp2_ssize rv;
1927   my_user_data ud;
1928   nghttp2_hd_deflater deflater;
1929   nghttp2_stream *stream;
1930   nghttp2_mem *mem;
1931   const uint8_t *data;
1932 
1933   mem = nghttp2_mem_default();
1934   frame_pack_bufs_init(&bufs);
1935 
1936   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
1937   callbacks.on_frame_recv_callback = on_frame_recv_callback;
1938   callbacks.on_header_callback = on_header_callback;
1939 
1940   nghttp2_session_server_new(&session, &callbacks, &ud);
1941 
1942   nghttp2_hd_deflate_init(&deflater, mem);
1943 
1944   /* Make sure that on_header callback never be invoked for closed
1945      stream */
1946   nvlen = ARRLEN(reqnv);
1947   nghttp2_nv_array_copy(&nva, reqnv, nvlen, mem);
1948 
1949   nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 1,
1950                              NGHTTP2_HCAT_HEADERS, NULL, nva, nvlen);
1951 
1952   rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
1953 
1954   assert_ptrdiff(0, ==, rv);
1955   assert_size(0, <, nghttp2_bufs_len(&bufs));
1956 
1957   nghttp2_frame_headers_free(&frame.headers, mem);
1958 
1959   buf = &bufs.head->buf;
1960   assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
1961 
1962   ud.header_cb_called = 0;
1963   ud.frame_recv_cb_called = 0;
1964 
1965   rv = nghttp2_session_mem_recv2(session, buf->pos, NGHTTP2_FRAME_HDLEN);
1966 
1967   assert_ptrdiff(NGHTTP2_FRAME_HDLEN, ==, rv);
1968   assert_int(0, ==, ud.header_cb_called);
1969   assert_int(0, ==, ud.frame_recv_cb_called);
1970 
1971   stream = nghttp2_session_get_stream(session, 1);
1972 
1973   assert_not_null(stream);
1974 
1975   rv =
1976     nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, 1, NGHTTP2_NO_ERROR);
1977 
1978   assert_ptrdiff(0, ==, rv);
1979 
1980   rv = nghttp2_session_mem_send2(session, &data);
1981 
1982   assert_ptrdiff(0, <, rv);
1983 
1984   stream = nghttp2_session_get_stream(session, 1);
1985 
1986   assert_null(stream);
1987 
1988   ud.header_cb_called = 0;
1989   ud.frame_recv_cb_called = 0;
1990 
1991   rv = nghttp2_session_mem_recv2(session, buf->pos + NGHTTP2_FRAME_HDLEN,
1992                                  nghttp2_buf_len(buf) - NGHTTP2_FRAME_HDLEN);
1993 
1994   assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(buf) - NGHTTP2_FRAME_HDLEN, ==,
1995                  rv);
1996   assert_int(0, ==, ud.header_cb_called);
1997   assert_int(0, ==, ud.frame_recv_cb_called);
1998 
1999   nghttp2_bufs_free(&bufs);
2000   nghttp2_hd_deflate_free(&deflater);
2001   nghttp2_session_del(session);
2002 }
2003 
test_nghttp2_session_recv_headers_with_extpri(void)2004 void test_nghttp2_session_recv_headers_with_extpri(void) {
2005   nghttp2_session *session;
2006   nghttp2_session_callbacks callbacks;
2007   nghttp2_nv *nva;
2008   size_t nvlen;
2009   nghttp2_frame frame;
2010   nghttp2_bufs bufs;
2011   nghttp2_buf *buf;
2012   nghttp2_ssize rv;
2013   nghttp2_hd_deflater deflater;
2014   nghttp2_stream *stream;
2015   nghttp2_mem *mem;
2016   const nghttp2_nv extpri_reqnv[] = {
2017     MAKE_NV(":method", "GET"),    MAKE_NV(":path", "/"),
2018     MAKE_NV(":scheme", "https"),  MAKE_NV(":authority", "localhost"),
2019     MAKE_NV("priority", "i,u=2"),
2020   };
2021   nghttp2_settings_entry iv;
2022 
2023   mem = nghttp2_mem_default();
2024   frame_pack_bufs_init(&bufs);
2025 
2026   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
2027 
2028   nghttp2_session_server_new(&session, &callbacks, NULL);
2029 
2030   iv.settings_id = NGHTTP2_SETTINGS_NO_RFC7540_PRIORITIES;
2031   iv.value = 1;
2032 
2033   nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, &iv, 1);
2034 
2035   nghttp2_hd_deflate_init(&deflater, mem);
2036 
2037   nvlen = ARRLEN(extpri_reqnv);
2038   nghttp2_nv_array_copy(&nva, extpri_reqnv, nvlen, mem);
2039 
2040   nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 1,
2041                              NGHTTP2_HCAT_HEADERS, NULL, nva, nvlen);
2042 
2043   rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
2044 
2045   assert_ptrdiff(0, ==, rv);
2046   assert_size(0, <, nghttp2_bufs_len(&bufs));
2047 
2048   nghttp2_frame_headers_free(&frame.headers, mem);
2049 
2050   buf = &bufs.head->buf;
2051   assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
2052 
2053   rv = nghttp2_session_mem_recv2(session, buf->pos, nghttp2_buf_len(buf));
2054 
2055   stream = nghttp2_session_get_stream(session, 1);
2056 
2057   assert_uint32(2, ==, nghttp2_extpri_uint8_urgency(stream->extpri));
2058   assert_true(nghttp2_extpri_uint8_inc(stream->extpri));
2059 
2060   nghttp2_hd_deflate_free(&deflater);
2061   nghttp2_session_del(session);
2062 
2063   nghttp2_bufs_reset(&bufs);
2064 
2065   /* Client should ignore priority header field included in
2066      PUSH_PROMISE. */
2067   nghttp2_session_client_new(&session, &callbacks, NULL);
2068 
2069   nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, &iv, 1);
2070 
2071   open_sent_stream(session, 1);
2072 
2073   nghttp2_hd_deflate_init(&deflater, mem);
2074 
2075   nvlen = ARRLEN(extpri_reqnv);
2076   nghttp2_nv_array_copy(&nva, extpri_reqnv, nvlen, mem);
2077 
2078   nghttp2_frame_push_promise_init(&frame.push_promise, NGHTTP2_FLAG_END_HEADERS,
2079                                   1, 2, nva, nvlen);
2080 
2081   rv = nghttp2_frame_pack_push_promise(&bufs, &frame.push_promise, &deflater);
2082 
2083   assert_ptrdiff(0, ==, rv);
2084   assert_size(0, <, nghttp2_bufs_len(&bufs));
2085 
2086   nghttp2_frame_push_promise_free(&frame.push_promise, mem);
2087 
2088   buf = &bufs.head->buf;
2089   assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
2090 
2091   rv = nghttp2_session_mem_recv2(session, buf->pos, nghttp2_buf_len(buf));
2092 
2093   stream = nghttp2_session_get_stream(session, 2);
2094 
2095   assert_uint32(NGHTTP2_EXTPRI_DEFAULT_URGENCY, ==,
2096                 nghttp2_extpri_uint8_urgency(stream->http_extpri));
2097   assert_uint32(NGHTTP2_EXTPRI_DEFAULT_URGENCY, ==,
2098                 nghttp2_extpri_uint8_urgency(stream->extpri));
2099 
2100   nghttp2_hd_deflate_free(&deflater);
2101   nghttp2_session_del(session);
2102   nghttp2_bufs_free(&bufs);
2103 }
2104 
test_nghttp2_session_server_recv_push_response(void)2105 void test_nghttp2_session_server_recv_push_response(void) {
2106   nghttp2_session *session;
2107   nghttp2_session_callbacks callbacks;
2108   nghttp2_bufs bufs;
2109   nghttp2_buf *buf;
2110   nghttp2_ssize rv;
2111   my_user_data ud;
2112   nghttp2_mem *mem;
2113   nghttp2_frame frame;
2114   nghttp2_hd_deflater deflater;
2115   nghttp2_nv *nva;
2116   size_t nvlen;
2117 
2118   mem = nghttp2_mem_default();
2119   frame_pack_bufs_init(&bufs);
2120 
2121   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
2122   callbacks.on_invalid_frame_recv_callback = on_invalid_frame_recv_callback;
2123 
2124   nghttp2_session_server_new(&session, &callbacks, &ud);
2125 
2126   nghttp2_hd_deflate_init(&deflater, mem);
2127 
2128   open_sent_stream2(session, 2, NGHTTP2_STREAM_RESERVED);
2129 
2130   nvlen = ARRLEN(resnv);
2131   nghttp2_nv_array_copy(&nva, resnv, nvlen, mem);
2132   nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 2,
2133                              NGHTTP2_HCAT_HEADERS, &pri_spec_default, nva,
2134                              nvlen);
2135   rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
2136 
2137   assert_ptrdiff(0, ==, rv);
2138   assert_size(0, <, nghttp2_bufs_len(&bufs));
2139 
2140   nghttp2_frame_headers_free(&frame.headers, mem);
2141 
2142   buf = &bufs.head->buf;
2143 
2144   ud.invalid_frame_recv_cb_called = 0;
2145 
2146   rv = nghttp2_session_mem_recv2(session, buf->pos, nghttp2_buf_len(buf));
2147 
2148   assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(buf), ==, rv);
2149   assert_int(1, ==, ud.invalid_frame_recv_cb_called);
2150 
2151   nghttp2_bufs_free(&bufs);
2152   nghttp2_hd_deflate_free(&deflater);
2153   nghttp2_session_del(session);
2154 }
2155 
test_nghttp2_session_recv_premature_headers(void)2156 void test_nghttp2_session_recv_premature_headers(void) {
2157   nghttp2_session *session;
2158   nghttp2_session_callbacks callbacks;
2159   nghttp2_bufs bufs;
2160   nghttp2_buf *buf;
2161   nghttp2_ssize rv;
2162   my_user_data ud;
2163   nghttp2_hd_deflater deflater;
2164   nghttp2_outbound_item *item;
2165   nghttp2_mem *mem;
2166   uint32_t payloadlen;
2167 
2168   mem = nghttp2_mem_default();
2169   frame_pack_bufs_init(&bufs);
2170 
2171   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
2172   callbacks.send_callback2 = null_send_callback;
2173 
2174   nghttp2_session_server_new(&session, &callbacks, &ud);
2175 
2176   nghttp2_hd_deflate_init(&deflater, mem);
2177 
2178   pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, reqnv,
2179                ARRLEN(reqnv), mem);
2180 
2181   buf = &bufs.head->buf;
2182   /* Intentionally feed payload cutting last 1 byte off */
2183   payloadlen = nghttp2_get_uint32(buf->pos) >> 8;
2184   nghttp2_put_uint32be(buf->pos, ((payloadlen - 1) << 8) + buf->pos[3]);
2185   rv = nghttp2_session_mem_recv2(session, buf->pos, nghttp2_buf_len(buf) - 1);
2186 
2187   assert_ptrdiff((nghttp2_ssize)(nghttp2_buf_len(buf) - 1), ==, rv);
2188 
2189   item = nghttp2_session_get_next_ob_item(session);
2190 
2191   assert_not_null(item);
2192   assert_uint8(NGHTTP2_RST_STREAM, ==, item->frame.hd.type);
2193   assert_uint32(NGHTTP2_COMPRESSION_ERROR, ==,
2194                 item->frame.rst_stream.error_code);
2195   assert_int32(1, ==, item->frame.hd.stream_id);
2196   assert_int(0, ==, nghttp2_session_send(session));
2197 
2198   nghttp2_bufs_reset(&bufs);
2199   nghttp2_hd_deflate_free(&deflater);
2200   nghttp2_session_del(session);
2201 
2202   /* Test for PUSH_PROMISE */
2203   nghttp2_session_client_new(&session, &callbacks, &ud);
2204   nghttp2_hd_deflate_init(&deflater, mem);
2205 
2206   open_sent_stream3(session, 1, NGHTTP2_STREAM_FLAG_NONE, &pri_spec_default,
2207                     NGHTTP2_STREAM_OPENING, NULL);
2208 
2209   rv = pack_push_promise(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, 2,
2210                          reqnv, ARRLEN(reqnv), mem);
2211 
2212   assert_ptrdiff(0, ==, rv);
2213 
2214   buf = &bufs.head->buf;
2215   payloadlen = nghttp2_get_uint32(buf->pos) >> 8;
2216   /* Intentionally feed payload cutting last 1 byte off */
2217   nghttp2_put_uint32be(buf->pos, ((payloadlen - 1) << 8) + buf->pos[3]);
2218   rv = nghttp2_session_mem_recv2(session, buf->pos, nghttp2_buf_len(buf) - 1);
2219 
2220   assert_ptrdiff((nghttp2_ssize)(nghttp2_buf_len(buf) - 1), ==, rv);
2221 
2222   item = nghttp2_session_get_next_ob_item(session);
2223 
2224   assert_not_null(item);
2225   assert_uint8(NGHTTP2_RST_STREAM, ==, item->frame.hd.type);
2226   assert_uint32(NGHTTP2_COMPRESSION_ERROR, ==,
2227                 item->frame.rst_stream.error_code);
2228   assert_int32(2, ==, item->frame.hd.stream_id);
2229   assert_int(0, ==, nghttp2_session_send(session));
2230 
2231   nghttp2_hd_deflate_free(&deflater);
2232   nghttp2_session_del(session);
2233   nghttp2_bufs_free(&bufs);
2234 }
2235 
test_nghttp2_session_recv_unknown_frame(void)2236 void test_nghttp2_session_recv_unknown_frame(void) {
2237   nghttp2_session *session;
2238   nghttp2_session_callbacks callbacks;
2239   my_user_data ud;
2240   uint8_t data[16384];
2241   size_t datalen;
2242   nghttp2_frame_hd hd;
2243   nghttp2_ssize rv;
2244 
2245   nghttp2_frame_hd_init(&hd, 16000, 99, NGHTTP2_FLAG_NONE, 0);
2246 
2247   nghttp2_frame_pack_frame_hd(data, &hd);
2248   datalen = NGHTTP2_FRAME_HDLEN + hd.length;
2249 
2250   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
2251   callbacks.on_frame_recv_callback = on_frame_recv_callback;
2252 
2253   nghttp2_session_server_new(&session, &callbacks, &ud);
2254 
2255   ud.frame_recv_cb_called = 0;
2256 
2257   /* Unknown frame must be ignored */
2258   rv = nghttp2_session_mem_recv2(session, data, datalen);
2259 
2260   assert_ptrdiff(rv, ==, (nghttp2_ssize)datalen);
2261   assert_int(0, ==, ud.frame_recv_cb_called);
2262   assert_null(nghttp2_session_get_next_ob_item(session));
2263 
2264   nghttp2_session_del(session);
2265 }
2266 
test_nghttp2_session_recv_unexpected_continuation(void)2267 void test_nghttp2_session_recv_unexpected_continuation(void) {
2268   nghttp2_session *session;
2269   nghttp2_session_callbacks callbacks;
2270   my_user_data ud;
2271   uint8_t data[16384];
2272   size_t datalen;
2273   nghttp2_frame_hd hd;
2274   nghttp2_ssize rv;
2275   nghttp2_outbound_item *item;
2276 
2277   nghttp2_frame_hd_init(&hd, 16000, NGHTTP2_CONTINUATION,
2278                         NGHTTP2_FLAG_END_HEADERS, 1);
2279 
2280   nghttp2_frame_pack_frame_hd(data, &hd);
2281   datalen = NGHTTP2_FRAME_HDLEN + hd.length;
2282 
2283   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
2284   callbacks.on_frame_recv_callback = on_frame_recv_callback;
2285 
2286   nghttp2_session_server_new(&session, &callbacks, &ud);
2287 
2288   open_recv_stream(session, 1);
2289 
2290   ud.frame_recv_cb_called = 0;
2291 
2292   /* unexpected CONTINUATION must be treated as connection error */
2293   rv = nghttp2_session_mem_recv2(session, data, datalen);
2294 
2295   assert_ptrdiff(rv, ==, (nghttp2_ssize)datalen);
2296   assert_int(0, ==, ud.frame_recv_cb_called);
2297 
2298   item = nghttp2_session_get_next_ob_item(session);
2299 
2300   assert_uint8(NGHTTP2_GOAWAY, ==, item->frame.hd.type);
2301 
2302   nghttp2_session_del(session);
2303 }
2304 
test_nghttp2_session_recv_settings_header_table_size(void)2305 void test_nghttp2_session_recv_settings_header_table_size(void) {
2306   nghttp2_session *session;
2307   nghttp2_session_callbacks callbacks;
2308   nghttp2_frame frame;
2309   nghttp2_bufs bufs;
2310   nghttp2_buf *buf;
2311   nghttp2_ssize rv;
2312   my_user_data ud;
2313   nghttp2_settings_entry iv[3];
2314   nghttp2_nv nv = MAKE_NV(":authority", "example.org");
2315   nghttp2_mem *mem;
2316 
2317   mem = nghttp2_mem_default();
2318   frame_pack_bufs_init(&bufs);
2319 
2320   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
2321   callbacks.on_frame_recv_callback = on_frame_recv_callback;
2322   callbacks.send_callback2 = null_send_callback;
2323 
2324   nghttp2_session_client_new(&session, &callbacks, &ud);
2325 
2326   iv[0].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
2327   iv[0].value = 3000;
2328 
2329   iv[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
2330   iv[1].value = 16384;
2331 
2332   nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE, dup_iv(iv, 2),
2333                               2);
2334 
2335   rv = nghttp2_frame_pack_settings(&bufs, &frame.settings);
2336 
2337   assert_ptrdiff(0, ==, rv);
2338   assert_size(0, <, nghttp2_bufs_len(&bufs));
2339 
2340   nghttp2_frame_settings_free(&frame.settings, mem);
2341 
2342   buf = &bufs.head->buf;
2343   assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
2344 
2345   ud.frame_recv_cb_called = 0;
2346 
2347   rv = nghttp2_session_mem_recv2(session, buf->pos, nghttp2_buf_len(buf));
2348 
2349   assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(buf), ==, rv);
2350   assert_int(1, ==, ud.frame_recv_cb_called);
2351 
2352   assert_uint32(3000, ==, session->remote_settings.header_table_size);
2353   assert_uint32(16384, ==, session->remote_settings.initial_window_size);
2354 
2355   nghttp2_bufs_reset(&bufs);
2356 
2357   /* 2 SETTINGS_HEADER_TABLE_SIZE */
2358   iv[0].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
2359   iv[0].value = 3001;
2360 
2361   iv[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
2362   iv[1].value = 16383;
2363 
2364   iv[2].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
2365   iv[2].value = 3001;
2366 
2367   nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE, dup_iv(iv, 3),
2368                               3);
2369 
2370   rv = nghttp2_frame_pack_settings(&bufs, &frame.settings);
2371 
2372   assert_ptrdiff(0, ==, rv);
2373   assert_size(0, <, nghttp2_bufs_len(&bufs));
2374 
2375   nghttp2_frame_settings_free(&frame.settings, mem);
2376 
2377   buf = &bufs.head->buf;
2378   assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
2379 
2380   ud.frame_recv_cb_called = 0;
2381 
2382   rv = nghttp2_session_mem_recv2(session, buf->pos, nghttp2_buf_len(buf));
2383 
2384   assert_ptrdiff((nghttp2_ssize)(nghttp2_buf_len(buf)), ==, rv);
2385   assert_int(1, ==, ud.frame_recv_cb_called);
2386 
2387   assert_uint32(3001, ==, session->remote_settings.header_table_size);
2388   assert_uint32(16383, ==, session->remote_settings.initial_window_size);
2389 
2390   nghttp2_bufs_reset(&bufs);
2391 
2392   /* 2 SETTINGS_HEADER_TABLE_SIZE; first entry clears dynamic header
2393      table. */
2394 
2395   nghttp2_submit_request2(session, NULL, &nv, 1, NULL, NULL);
2396   nghttp2_session_send(session);
2397 
2398   assert_size(0, <, session->hd_deflater.ctx.hd_table.len);
2399 
2400   iv[0].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
2401   iv[0].value = 0;
2402 
2403   iv[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
2404   iv[1].value = 16382;
2405 
2406   iv[2].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
2407   iv[2].value = 4096;
2408 
2409   nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE, dup_iv(iv, 3),
2410                               3);
2411 
2412   rv = nghttp2_frame_pack_settings(&bufs, &frame.settings);
2413 
2414   assert_ptrdiff(0, ==, rv);
2415   assert_size(0, <, nghttp2_bufs_len(&bufs));
2416 
2417   nghttp2_frame_settings_free(&frame.settings, mem);
2418 
2419   buf = &bufs.head->buf;
2420   assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
2421 
2422   ud.frame_recv_cb_called = 0;
2423 
2424   rv = nghttp2_session_mem_recv2(session, buf->pos, nghttp2_buf_len(buf));
2425 
2426   assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(buf), ==, rv);
2427   assert_int(1, ==, ud.frame_recv_cb_called);
2428 
2429   assert_uint32(4096, ==, session->remote_settings.header_table_size);
2430   assert_uint32(16382, ==, session->remote_settings.initial_window_size);
2431   assert_size(0, ==, session->hd_deflater.ctx.hd_table.len);
2432 
2433   nghttp2_bufs_reset(&bufs);
2434 
2435   /* 2 SETTINGS_HEADER_TABLE_SIZE; second entry clears dynamic header
2436      table. */
2437 
2438   nghttp2_submit_request2(session, NULL, &nv, 1, NULL, NULL);
2439   nghttp2_session_send(session);
2440 
2441   assert_size(0, <, session->hd_deflater.ctx.hd_table.len);
2442 
2443   iv[0].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
2444   iv[0].value = 3000;
2445 
2446   iv[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
2447   iv[1].value = 16381;
2448 
2449   iv[2].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
2450   iv[2].value = 0;
2451 
2452   nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE, dup_iv(iv, 3),
2453                               3);
2454 
2455   rv = nghttp2_frame_pack_settings(&bufs, &frame.settings);
2456 
2457   assert_ptrdiff(0, ==, rv);
2458   assert_size(0, <, nghttp2_bufs_len(&bufs));
2459 
2460   nghttp2_frame_settings_free(&frame.settings, mem);
2461 
2462   buf = &bufs.head->buf;
2463   assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
2464 
2465   ud.frame_recv_cb_called = 0;
2466 
2467   rv = nghttp2_session_mem_recv2(session, buf->pos, nghttp2_buf_len(buf));
2468 
2469   assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(buf), ==, rv);
2470   assert_int(1, ==, ud.frame_recv_cb_called);
2471 
2472   assert_uint32(0, ==, session->remote_settings.header_table_size);
2473   assert_uint32(16381, ==, session->remote_settings.initial_window_size);
2474   assert_size(0, ==, session->hd_deflater.ctx.hd_table.len);
2475 
2476   nghttp2_bufs_reset(&bufs);
2477 
2478   nghttp2_bufs_free(&bufs);
2479   nghttp2_session_del(session);
2480 }
2481 
test_nghttp2_session_recv_too_large_frame_length(void)2482 void test_nghttp2_session_recv_too_large_frame_length(void) {
2483   nghttp2_session *session;
2484   nghttp2_session_callbacks callbacks;
2485   uint8_t buf[NGHTTP2_FRAME_HDLEN];
2486   nghttp2_outbound_item *item;
2487   nghttp2_frame_hd hd;
2488 
2489   /* Initial max frame size is NGHTTP2_MAX_FRAME_SIZE_MIN */
2490   nghttp2_frame_hd_init(&hd, NGHTTP2_MAX_FRAME_SIZE_MIN + 1, NGHTTP2_HEADERS,
2491                         NGHTTP2_FLAG_NONE, 1);
2492 
2493   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
2494 
2495   nghttp2_session_server_new(&session, &callbacks, NULL);
2496 
2497   nghttp2_frame_pack_frame_hd(buf, &hd);
2498 
2499   assert_ptrdiff(sizeof(buf), ==,
2500                  nghttp2_session_mem_recv2(session, buf, sizeof(buf)));
2501 
2502   item = nghttp2_session_get_next_ob_item(session);
2503 
2504   assert_not_null(item);
2505   assert_uint8(NGHTTP2_GOAWAY, ==, item->frame.hd.type);
2506 
2507   nghttp2_session_del(session);
2508 }
2509 
test_nghttp2_session_recv_extension(void)2510 void test_nghttp2_session_recv_extension(void) {
2511   nghttp2_session *session;
2512   nghttp2_session_callbacks callbacks;
2513   my_user_data ud;
2514   nghttp2_buf buf;
2515   nghttp2_frame_hd hd;
2516   nghttp2_mem *mem;
2517   const char data[] = "Hello World!";
2518   nghttp2_ssize rv;
2519   nghttp2_option *option;
2520 
2521   mem = nghttp2_mem_default();
2522 
2523   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
2524 
2525   callbacks.on_extension_chunk_recv_callback = on_extension_chunk_recv_callback;
2526   callbacks.unpack_extension_callback = unpack_extension_callback;
2527   callbacks.on_frame_recv_callback = on_frame_recv_callback;
2528 
2529   nghttp2_option_new(&option);
2530   nghttp2_option_set_user_recv_extension_type(option, 111);
2531 
2532   nghttp2_buf_init2(&ud.scratchbuf, 4096, mem);
2533   nghttp2_buf_init2(&buf, 4096, mem);
2534 
2535   nghttp2_frame_hd_init(&hd, sizeof(data), 111, 0xab, 1000000007);
2536   nghttp2_frame_pack_frame_hd(buf.last, &hd);
2537   buf.last += NGHTTP2_FRAME_HDLEN;
2538   buf.last = nghttp2_cpymem(buf.last, data, sizeof(data));
2539 
2540   nghttp2_session_client_new2(&session, &callbacks, &ud, option);
2541 
2542   nghttp2_frame_hd_init(&ud.recv_frame_hd, 0, 0, 0, 0);
2543   rv = nghttp2_session_mem_recv2(session, buf.pos, nghttp2_buf_len(&buf));
2544 
2545   assert_size(NGHTTP2_FRAME_HDLEN + hd.length, ==, (size_t)rv);
2546   assert_uint8(111, ==, ud.recv_frame_hd.type);
2547   assert_uint8(0xab, ==, ud.recv_frame_hd.flags);
2548   assert_int32(1000000007, ==, ud.recv_frame_hd.stream_id);
2549   assert_memory_equal(sizeof(data), data, ud.scratchbuf.pos);
2550 
2551   nghttp2_session_del(session);
2552 
2553   /* cancel in on_extension_chunk_recv_callback */
2554   nghttp2_buf_reset(&ud.scratchbuf);
2555 
2556   callbacks.on_extension_chunk_recv_callback =
2557     cancel_on_extension_chunk_recv_callback;
2558 
2559   nghttp2_session_server_new2(&session, &callbacks, &ud, option);
2560 
2561   ud.frame_recv_cb_called = 0;
2562   rv = nghttp2_session_mem_recv2(session, buf.pos, nghttp2_buf_len(&buf));
2563 
2564   assert_size(NGHTTP2_FRAME_HDLEN + hd.length, ==, (size_t)rv);
2565   assert_int(0, ==, ud.frame_recv_cb_called);
2566 
2567   nghttp2_session_del(session);
2568 
2569   /* cancel in unpack_extension_callback */
2570   nghttp2_buf_reset(&ud.scratchbuf);
2571 
2572   callbacks.on_extension_chunk_recv_callback = on_extension_chunk_recv_callback;
2573   callbacks.unpack_extension_callback = cancel_unpack_extension_callback;
2574 
2575   nghttp2_session_server_new2(&session, &callbacks, &ud, option);
2576 
2577   ud.frame_recv_cb_called = 0;
2578   rv = nghttp2_session_mem_recv2(session, buf.pos, nghttp2_buf_len(&buf));
2579 
2580   assert_size(NGHTTP2_FRAME_HDLEN + hd.length, ==, (size_t)rv);
2581   assert_int(0, ==, ud.frame_recv_cb_called);
2582 
2583   nghttp2_session_del(session);
2584 
2585   nghttp2_buf_free(&buf, mem);
2586   nghttp2_buf_free(&ud.scratchbuf, mem);
2587 
2588   nghttp2_option_del(option);
2589 }
2590 
test_nghttp2_session_recv_altsvc(void)2591 void test_nghttp2_session_recv_altsvc(void) {
2592   nghttp2_session *session;
2593   nghttp2_session_callbacks callbacks;
2594   my_user_data ud;
2595   nghttp2_buf buf;
2596   nghttp2_frame_hd hd;
2597   nghttp2_mem *mem;
2598   nghttp2_ssize rv;
2599   nghttp2_option *option;
2600   static const uint8_t origin[] = "nghttp2.org";
2601   static const uint8_t field_value[] = "h2=\":443\"";
2602 
2603   mem = nghttp2_mem_default();
2604 
2605   nghttp2_buf_init2(&buf, NGHTTP2_FRAME_HDLEN + NGHTTP2_MAX_FRAME_SIZE_MIN,
2606                     mem);
2607 
2608   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
2609 
2610   callbacks.on_frame_recv_callback = on_frame_recv_callback;
2611   callbacks.on_invalid_frame_recv_callback = on_invalid_frame_recv_callback;
2612 
2613   nghttp2_option_new(&option);
2614   nghttp2_option_set_builtin_recv_extension_type(option, NGHTTP2_ALTSVC);
2615 
2616   nghttp2_session_client_new2(&session, &callbacks, &ud, option);
2617 
2618   nghttp2_frame_hd_init(&hd, 2 + sizeof(origin) - 1 + sizeof(field_value) - 1,
2619                         NGHTTP2_ALTSVC, NGHTTP2_FLAG_NONE, 0);
2620   nghttp2_frame_pack_frame_hd(buf.last, &hd);
2621   buf.last += NGHTTP2_FRAME_HDLEN;
2622   nghttp2_put_uint16be(buf.last, sizeof(origin) - 1);
2623   buf.last += 2;
2624   buf.last = nghttp2_cpymem(buf.last, origin, sizeof(origin) - 1);
2625   buf.last = nghttp2_cpymem(buf.last, field_value, sizeof(field_value) - 1);
2626 
2627   ud.frame_recv_cb_called = 0;
2628   rv = nghttp2_session_mem_recv2(session, buf.pos, nghttp2_buf_len(&buf));
2629 
2630   assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(&buf), ==, rv);
2631   assert_int(1, ==, ud.frame_recv_cb_called);
2632   assert_uint8(NGHTTP2_ALTSVC, ==, ud.recv_frame_hd.type);
2633   assert_uint8(NGHTTP2_FLAG_NONE, ==, ud.recv_frame_hd.flags);
2634   assert_int32(0, ==, ud.recv_frame_hd.stream_id);
2635 
2636   nghttp2_session_del(session);
2637 
2638   /* size of origin is larger than frame length */
2639   nghttp2_buf_reset(&buf);
2640 
2641   nghttp2_session_client_new2(&session, &callbacks, &ud, option);
2642 
2643   nghttp2_frame_hd_init(&hd, 2 + sizeof(origin) - 1 - 1, NGHTTP2_ALTSVC,
2644                         NGHTTP2_FLAG_NONE, 0);
2645   nghttp2_frame_pack_frame_hd(buf.last, &hd);
2646   buf.last += NGHTTP2_FRAME_HDLEN;
2647   nghttp2_put_uint16be(buf.last, sizeof(origin) - 1);
2648   buf.last += 2;
2649   buf.last = nghttp2_cpymem(buf.last, origin, sizeof(origin) - 1 - 1);
2650 
2651   ud.frame_recv_cb_called = 0;
2652   rv = nghttp2_session_mem_recv2(session, buf.pos, nghttp2_buf_len(&buf));
2653 
2654   assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(&buf), ==, rv);
2655   assert_int(0, ==, ud.frame_recv_cb_called);
2656 
2657   nghttp2_session_del(session);
2658 
2659   /* zero-length value */
2660   nghttp2_buf_reset(&buf);
2661 
2662   nghttp2_session_client_new2(&session, &callbacks, &ud, option);
2663 
2664   nghttp2_frame_hd_init(&hd, 2 + sizeof(origin) - 1, NGHTTP2_ALTSVC,
2665                         NGHTTP2_FLAG_NONE, 0);
2666   nghttp2_frame_pack_frame_hd(buf.last, &hd);
2667   buf.last += NGHTTP2_FRAME_HDLEN;
2668   nghttp2_put_uint16be(buf.last, sizeof(origin) - 1);
2669   buf.last += 2;
2670   buf.last = nghttp2_cpymem(buf.last, origin, sizeof(origin) - 1);
2671 
2672   ud.invalid_frame_recv_cb_called = 0;
2673   rv = nghttp2_session_mem_recv2(session, buf.pos, nghttp2_buf_len(&buf));
2674 
2675   assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(&buf), ==, rv);
2676   assert_int(1, ==, ud.invalid_frame_recv_cb_called);
2677 
2678   nghttp2_session_del(session);
2679 
2680   /* non-empty origin to a stream other than 0 */
2681   nghttp2_buf_reset(&buf);
2682 
2683   nghttp2_session_client_new2(&session, &callbacks, &ud, option);
2684 
2685   open_sent_stream(session, 1);
2686 
2687   nghttp2_frame_hd_init(&hd, 2 + sizeof(origin) - 1 + sizeof(field_value) - 1,
2688                         NGHTTP2_ALTSVC, NGHTTP2_FLAG_NONE, 1);
2689   nghttp2_frame_pack_frame_hd(buf.last, &hd);
2690   buf.last += NGHTTP2_FRAME_HDLEN;
2691   nghttp2_put_uint16be(buf.last, sizeof(origin) - 1);
2692   buf.last += 2;
2693   buf.last = nghttp2_cpymem(buf.last, origin, sizeof(origin) - 1);
2694   buf.last = nghttp2_cpymem(buf.last, field_value, sizeof(field_value) - 1);
2695 
2696   ud.invalid_frame_recv_cb_called = 0;
2697   rv = nghttp2_session_mem_recv2(session, buf.pos, nghttp2_buf_len(&buf));
2698 
2699   assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(&buf), ==, rv);
2700   assert_int(1, ==, ud.invalid_frame_recv_cb_called);
2701 
2702   nghttp2_session_del(session);
2703 
2704   /* empty origin to stream 0 */
2705   nghttp2_buf_reset(&buf);
2706 
2707   nghttp2_session_client_new2(&session, &callbacks, &ud, option);
2708 
2709   nghttp2_frame_hd_init(&hd, 2 + sizeof(field_value) - 1, NGHTTP2_ALTSVC,
2710                         NGHTTP2_FLAG_NONE, 0);
2711   nghttp2_frame_pack_frame_hd(buf.last, &hd);
2712   buf.last += NGHTTP2_FRAME_HDLEN;
2713   nghttp2_put_uint16be(buf.last, 0);
2714   buf.last += 2;
2715   buf.last = nghttp2_cpymem(buf.last, field_value, sizeof(field_value) - 1);
2716 
2717   ud.invalid_frame_recv_cb_called = 0;
2718   rv = nghttp2_session_mem_recv2(session, buf.pos, nghttp2_buf_len(&buf));
2719 
2720   assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(&buf), ==, rv);
2721   assert_int(1, ==, ud.invalid_frame_recv_cb_called);
2722 
2723   nghttp2_session_del(session);
2724 
2725   /* send large frame (16KiB) */
2726   nghttp2_buf_reset(&buf);
2727 
2728   nghttp2_session_client_new2(&session, &callbacks, &ud, option);
2729 
2730   nghttp2_frame_hd_init(&hd, NGHTTP2_MAX_FRAME_SIZE_MIN, NGHTTP2_ALTSVC,
2731                         NGHTTP2_FLAG_NONE, 0);
2732   nghttp2_frame_pack_frame_hd(buf.last, &hd);
2733   buf.last += NGHTTP2_FRAME_HDLEN;
2734   nghttp2_put_uint16be(buf.last, sizeof(origin) - 1);
2735   buf.last += 2;
2736   buf.last = nghttp2_cpymem(buf.last, origin, sizeof(origin) - 1);
2737   memset(buf.last, 0, nghttp2_buf_avail(&buf));
2738   buf.last += nghttp2_buf_avail(&buf);
2739 
2740   ud.frame_recv_cb_called = 0;
2741   rv = nghttp2_session_mem_recv2(session, buf.pos, nghttp2_buf_len(&buf));
2742 
2743   assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(&buf), ==, rv);
2744   assert_int(1, ==, ud.frame_recv_cb_called);
2745   assert_uint8(NGHTTP2_ALTSVC, ==, ud.recv_frame_hd.type);
2746   assert_size(NGHTTP2_MAX_FRAME_SIZE_MIN, ==, ud.recv_frame_hd.length);
2747 
2748   nghttp2_session_del(session);
2749 
2750   /* send too large frame */
2751   nghttp2_buf_reset(&buf);
2752 
2753   nghttp2_session_client_new2(&session, &callbacks, &ud, option);
2754 
2755   session->local_settings.max_frame_size = NGHTTP2_MAX_FRAME_SIZE_MIN - 1;
2756 
2757   nghttp2_frame_hd_init(&hd, NGHTTP2_MAX_FRAME_SIZE_MIN + 1, NGHTTP2_ALTSVC,
2758                         NGHTTP2_FLAG_NONE, 0);
2759   nghttp2_frame_pack_frame_hd(buf.last, &hd);
2760   buf.last += NGHTTP2_FRAME_HDLEN;
2761   nghttp2_put_uint16be(buf.last, sizeof(origin) - 1);
2762   buf.last += 2;
2763   buf.last = nghttp2_cpymem(buf.last, origin, sizeof(origin) - 1);
2764   memset(buf.last, 0, nghttp2_buf_avail(&buf));
2765   buf.last += nghttp2_buf_avail(&buf);
2766 
2767   ud.frame_recv_cb_called = 0;
2768   rv = nghttp2_session_mem_recv2(session, buf.pos, nghttp2_buf_len(&buf));
2769 
2770   assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(&buf), ==, rv);
2771   assert_int(0, ==, ud.frame_recv_cb_called);
2772 
2773   nghttp2_session_del(session);
2774 
2775   /* received by server */
2776   nghttp2_buf_reset(&buf);
2777 
2778   nghttp2_session_server_new2(&session, &callbacks, &ud, option);
2779 
2780   nghttp2_frame_hd_init(&hd, 2 + sizeof(origin) - 1 + sizeof(field_value) - 1,
2781                         NGHTTP2_ALTSVC, NGHTTP2_FLAG_NONE, 0);
2782   nghttp2_frame_pack_frame_hd(buf.last, &hd);
2783   buf.last += NGHTTP2_FRAME_HDLEN;
2784   nghttp2_put_uint16be(buf.last, sizeof(origin) - 1);
2785   buf.last += 2;
2786   buf.last = nghttp2_cpymem(buf.last, origin, sizeof(origin) - 1);
2787   buf.last = nghttp2_cpymem(buf.last, field_value, sizeof(field_value) - 1);
2788 
2789   ud.frame_recv_cb_called = 0;
2790   rv = nghttp2_session_mem_recv2(session, buf.pos, nghttp2_buf_len(&buf));
2791 
2792   assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(&buf), ==, rv);
2793   assert_int(0, ==, ud.frame_recv_cb_called);
2794 
2795   nghttp2_session_del(session);
2796 
2797   nghttp2_buf_free(&buf, mem);
2798   nghttp2_option_del(option);
2799 }
2800 
test_nghttp2_session_recv_origin(void)2801 void test_nghttp2_session_recv_origin(void) {
2802   nghttp2_session *session;
2803   nghttp2_session_callbacks callbacks;
2804   my_user_data ud;
2805   nghttp2_bufs bufs;
2806   nghttp2_ssize rv;
2807   nghttp2_option *option;
2808   nghttp2_extension frame;
2809   nghttp2_ext_origin origin;
2810   nghttp2_origin_entry ov;
2811   static const uint8_t nghttp2[] = "https://nghttp2.org";
2812 
2813   frame_pack_bufs_init(&bufs);
2814 
2815   frame.payload = &origin;
2816 
2817   ov.origin = (uint8_t *)nghttp2;
2818   ov.origin_len = sizeof(nghttp2) - 1;
2819 
2820   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
2821 
2822   callbacks.on_frame_recv_callback = on_frame_recv_callback;
2823 
2824   nghttp2_option_new(&option);
2825   nghttp2_option_set_builtin_recv_extension_type(option, NGHTTP2_ORIGIN);
2826 
2827   nghttp2_session_client_new2(&session, &callbacks, &ud, option);
2828 
2829   nghttp2_frame_origin_init(&frame, &ov, 1);
2830 
2831   rv = nghttp2_frame_pack_origin(&bufs, &frame);
2832 
2833   assert_ptrdiff(0, ==, rv);
2834 
2835   ud.frame_recv_cb_called = 0;
2836   rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
2837                                  nghttp2_bufs_len(&bufs));
2838 
2839   assert_ptrdiff((nghttp2_ssize)nghttp2_bufs_len(&bufs), ==, rv);
2840   assert_int(1, ==, ud.frame_recv_cb_called);
2841   assert_uint8(NGHTTP2_ORIGIN, ==, ud.recv_frame_hd.type);
2842   assert_uint8(NGHTTP2_FLAG_NONE, ==, ud.recv_frame_hd.flags);
2843   assert_int32(0, ==, ud.recv_frame_hd.stream_id);
2844 
2845   nghttp2_session_del(session);
2846   nghttp2_bufs_reset(&bufs);
2847 
2848   /* The length of origin is larger than payload length. */
2849   nghttp2_session_client_new2(&session, &callbacks, &ud, option);
2850 
2851   nghttp2_frame_origin_init(&frame, &ov, 1);
2852   rv = nghttp2_frame_pack_origin(&bufs, &frame);
2853 
2854   assert_ptrdiff(0, ==, rv);
2855 
2856   nghttp2_put_uint16be(bufs.head->buf.pos + NGHTTP2_FRAME_HDLEN,
2857                        (uint16_t)sizeof(nghttp2));
2858 
2859   ud.frame_recv_cb_called = 0;
2860   rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
2861                                  nghttp2_bufs_len(&bufs));
2862 
2863   assert_ptrdiff((nghttp2_ssize)nghttp2_bufs_len(&bufs), ==, rv);
2864   assert_int(0, ==, ud.frame_recv_cb_called);
2865 
2866   nghttp2_session_del(session);
2867   nghttp2_bufs_reset(&bufs);
2868 
2869   /* A frame should be ignored if it is sent to a stream other than
2870      stream 0. */
2871   nghttp2_session_client_new2(&session, &callbacks, &ud, option);
2872 
2873   nghttp2_frame_origin_init(&frame, &ov, 1);
2874   frame.hd.stream_id = 1;
2875   rv = nghttp2_frame_pack_origin(&bufs, &frame);
2876 
2877   assert_ptrdiff(0, ==, rv);
2878 
2879   ud.frame_recv_cb_called = 0;
2880   rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
2881                                  nghttp2_bufs_len(&bufs));
2882 
2883   assert_ptrdiff((nghttp2_ssize)nghttp2_bufs_len(&bufs), ==, rv);
2884   assert_int(0, ==, ud.frame_recv_cb_called);
2885 
2886   nghttp2_session_del(session);
2887   nghttp2_bufs_reset(&bufs);
2888 
2889   /* A frame should be ignored if the reserved flag is set */
2890   nghttp2_session_client_new2(&session, &callbacks, &ud, option);
2891 
2892   nghttp2_frame_origin_init(&frame, &ov, 1);
2893   frame.hd.flags = 0xf0;
2894   rv = nghttp2_frame_pack_origin(&bufs, &frame);
2895 
2896   assert_ptrdiff(0, ==, rv);
2897 
2898   ud.frame_recv_cb_called = 0;
2899   rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
2900                                  nghttp2_bufs_len(&bufs));
2901 
2902   assert_ptrdiff((nghttp2_ssize)nghttp2_bufs_len(&bufs), ==, rv);
2903   assert_int(0, ==, ud.frame_recv_cb_called);
2904 
2905   nghttp2_session_del(session);
2906   nghttp2_bufs_reset(&bufs);
2907 
2908   /* A frame should be ignored if it is received by a server. */
2909   nghttp2_session_server_new2(&session, &callbacks, &ud, option);
2910 
2911   nghttp2_frame_origin_init(&frame, &ov, 1);
2912   rv = nghttp2_frame_pack_origin(&bufs, &frame);
2913 
2914   assert_ptrdiff(0, ==, rv);
2915 
2916   ud.frame_recv_cb_called = 0;
2917   rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
2918                                  nghttp2_bufs_len(&bufs));
2919 
2920   assert_ptrdiff((nghttp2_ssize)nghttp2_bufs_len(&bufs), ==, rv);
2921   assert_int(0, ==, ud.frame_recv_cb_called);
2922 
2923   nghttp2_session_del(session);
2924   nghttp2_bufs_reset(&bufs);
2925 
2926   /* Receiving empty ORIGIN frame */
2927   nghttp2_session_client_new2(&session, &callbacks, &ud, option);
2928 
2929   nghttp2_frame_origin_init(&frame, NULL, 0);
2930   rv = nghttp2_frame_pack_origin(&bufs, &frame);
2931 
2932   assert_ptrdiff(0, ==, rv);
2933 
2934   ud.frame_recv_cb_called = 0;
2935   rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
2936                                  nghttp2_bufs_len(&bufs));
2937 
2938   assert_ptrdiff((nghttp2_ssize)nghttp2_bufs_len(&bufs), ==, rv);
2939   assert_int(1, ==, ud.frame_recv_cb_called);
2940   assert_uint8(NGHTTP2_ORIGIN, ==, ud.recv_frame_hd.type);
2941 
2942   nghttp2_session_del(session);
2943 
2944   nghttp2_option_del(option);
2945   nghttp2_bufs_free(&bufs);
2946 }
2947 
test_nghttp2_session_recv_priority_update(void)2948 void test_nghttp2_session_recv_priority_update(void) {
2949   nghttp2_session *session;
2950   nghttp2_session_callbacks callbacks;
2951   my_user_data ud;
2952   nghttp2_bufs bufs;
2953   nghttp2_ssize rv;
2954   nghttp2_option *option;
2955   nghttp2_extension frame;
2956   nghttp2_ext_priority_update priority_update;
2957   nghttp2_stream *stream;
2958   nghttp2_hd_deflater deflater;
2959   nghttp2_mem *mem;
2960   uint8_t large_field_value[sizeof(session->iframe.raw_sbuf) + 1];
2961   nghttp2_outbound_item *item;
2962   size_t i;
2963   int32_t stream_id;
2964   static const uint8_t field_value[] = "u=2,i";
2965 
2966   mem = nghttp2_mem_default();
2967 
2968   memset(large_field_value, ' ', sizeof(large_field_value));
2969   memcpy(large_field_value, field_value, sizeof(field_value) - 1);
2970 
2971   frame_pack_bufs_init(&bufs);
2972 
2973   frame.payload = &priority_update;
2974 
2975   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
2976 
2977   callbacks.on_frame_recv_callback = on_frame_recv_callback;
2978 
2979   nghttp2_option_new(&option);
2980   nghttp2_option_set_builtin_recv_extension_type(option,
2981                                                  NGHTTP2_PRIORITY_UPDATE);
2982 
2983   nghttp2_session_server_new2(&session, &callbacks, &ud, option);
2984 
2985   session->pending_no_rfc7540_priorities = 1;
2986 
2987   nghttp2_frame_priority_update_init(&frame, 1, (uint8_t *)field_value,
2988                                      sizeof(field_value) - 1);
2989 
2990   nghttp2_frame_pack_priority_update(&bufs, &frame);
2991 
2992   open_recv_stream(session, 1);
2993 
2994   ud.frame_recv_cb_called = 0;
2995   rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
2996                                  nghttp2_bufs_len(&bufs));
2997 
2998   assert_ptrdiff((nghttp2_ssize)nghttp2_bufs_len(&bufs), ==, rv);
2999   assert_int(1, ==, ud.frame_recv_cb_called);
3000   assert_uint8(NGHTTP2_PRIORITY_UPDATE, ==, ud.recv_frame_hd.type);
3001   assert_uint8(NGHTTP2_FLAG_NONE, ==, ud.recv_frame_hd.flags);
3002   assert_int32(0, ==, ud.recv_frame_hd.stream_id);
3003 
3004   stream = nghttp2_session_get_stream_raw(session, 1);
3005 
3006   assert_uint32(2, ==, nghttp2_extpri_uint8_urgency(stream->extpri));
3007   assert_true(nghttp2_extpri_uint8_inc(stream->extpri));
3008 
3009   nghttp2_session_del(session);
3010   nghttp2_bufs_reset(&bufs);
3011 
3012   /* Check that priority which is received in idle state is
3013      retained. */
3014   nghttp2_session_server_new2(&session, &callbacks, &ud, option);
3015 
3016   session->pending_no_rfc7540_priorities = 1;
3017 
3018   nghttp2_frame_priority_update_init(&frame, 1, (uint8_t *)field_value,
3019                                      sizeof(field_value) - 1);
3020 
3021   nghttp2_frame_pack_priority_update(&bufs, &frame);
3022 
3023   ud.frame_recv_cb_called = 0;
3024   rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
3025                                  nghttp2_bufs_len(&bufs));
3026 
3027   assert_ptrdiff((nghttp2_ssize)nghttp2_bufs_len(&bufs), ==, rv);
3028   assert_int(1, ==, ud.frame_recv_cb_called);
3029   assert_uint8(NGHTTP2_PRIORITY_UPDATE, ==, ud.recv_frame_hd.type);
3030   assert_uint8(NGHTTP2_FLAG_NONE, ==, ud.recv_frame_hd.flags);
3031   assert_int32(0, ==, ud.recv_frame_hd.stream_id);
3032 
3033   stream = nghttp2_session_get_stream_raw(session, 1);
3034 
3035   assert_enum(nghttp2_stream_state, NGHTTP2_STREAM_IDLE, ==, stream->state);
3036   assert_uint32(2, ==, nghttp2_extpri_uint8_urgency(stream->extpri));
3037   assert_true(nghttp2_extpri_uint8_inc(stream->extpri));
3038 
3039   nghttp2_hd_deflate_init(&deflater, mem);
3040   nghttp2_bufs_reset(&bufs);
3041   rv = pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, reqnv,
3042                     ARRLEN(reqnv), mem);
3043 
3044   assert_ptrdiff(0, ==, rv);
3045 
3046   ud.frame_recv_cb_called = 0;
3047   rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
3048                                  nghttp2_bufs_len(&bufs));
3049 
3050   assert_ptrdiff((nghttp2_ssize)nghttp2_bufs_len(&bufs), ==, rv);
3051   assert_int(1, ==, ud.frame_recv_cb_called);
3052   assert_uint8(NGHTTP2_HEADERS, ==, ud.recv_frame_hd.type);
3053   assert_enum(nghttp2_stream_state, NGHTTP2_STREAM_OPENING, ==, stream->state);
3054   assert_uint32(2, ==, nghttp2_extpri_uint8_urgency(stream->extpri));
3055   assert_true(nghttp2_extpri_uint8_inc(stream->extpri));
3056 
3057   nghttp2_hd_deflate_free(&deflater);
3058 
3059   nghttp2_session_del(session);
3060   nghttp2_bufs_reset(&bufs);
3061 
3062   /* PRIORITY_UPDATE with too large field_value is discarded */
3063   nghttp2_session_server_new2(&session, &callbacks, &ud, option);
3064 
3065   session->pending_no_rfc7540_priorities = 1;
3066 
3067   nghttp2_frame_priority_update_init(&frame, 1, large_field_value,
3068                                      sizeof(large_field_value));
3069 
3070   nghttp2_frame_pack_priority_update(&bufs, &frame);
3071 
3072   open_recv_stream(session, 1);
3073 
3074   ud.frame_recv_cb_called = 0;
3075   rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
3076                                  nghttp2_bufs_len(&bufs));
3077 
3078   assert_ptrdiff((nghttp2_ssize)nghttp2_bufs_len(&bufs), ==, rv);
3079   assert_int(0, ==, ud.frame_recv_cb_called);
3080 
3081   stream = nghttp2_session_get_stream_raw(session, 1);
3082 
3083   assert_uint32(NGHTTP2_EXTPRI_DEFAULT_URGENCY, ==, stream->extpri);
3084 
3085   nghttp2_session_del(session);
3086   nghttp2_bufs_reset(&bufs);
3087 
3088   /* Connection error if client receives PRIORITY_UPDATE. */
3089   nghttp2_session_client_new2(&session, &callbacks, &ud, option);
3090 
3091   session->pending_no_rfc7540_priorities = 1;
3092 
3093   nghttp2_frame_priority_update_init(&frame, 1, (uint8_t *)field_value,
3094                                      sizeof(field_value) - 1);
3095 
3096   nghttp2_frame_pack_priority_update(&bufs, &frame);
3097 
3098   open_sent_stream(session, 1);
3099 
3100   ud.frame_recv_cb_called = 0;
3101   rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
3102                                  nghttp2_bufs_len(&bufs));
3103 
3104   assert_ptrdiff((nghttp2_ssize)nghttp2_bufs_len(&bufs), ==, rv);
3105   assert_int(0, ==, ud.frame_recv_cb_called);
3106 
3107   item = nghttp2_session_get_next_ob_item(session);
3108   assert_uint8(NGHTTP2_GOAWAY, ==, item->frame.hd.type);
3109   assert_uint32(NGHTTP2_PROTOCOL_ERROR, ==, item->frame.goaway.error_code);
3110 
3111   nghttp2_session_del(session);
3112   nghttp2_bufs_reset(&bufs);
3113 
3114   /* The number of idle streams exceeds the maximum. */
3115   nghttp2_session_server_new2(&session, &callbacks, &ud, option);
3116 
3117   session->pending_no_rfc7540_priorities = 1;
3118   session->local_settings.max_concurrent_streams = 100;
3119 
3120   for (i = 0; i < 101; ++i) {
3121     stream_id = (int32_t)(i * 2 + 1);
3122     nghttp2_frame_priority_update_init(
3123       &frame, stream_id, (uint8_t *)field_value, sizeof(field_value) - 1);
3124 
3125     nghttp2_frame_pack_priority_update(&bufs, &frame);
3126 
3127     ud.frame_recv_cb_called = 0;
3128     rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
3129                                    nghttp2_bufs_len(&bufs));
3130 
3131     if (i < 100) {
3132       assert_ptrdiff((nghttp2_ssize)nghttp2_bufs_len(&bufs), ==, rv);
3133       assert_int(1, ==, ud.frame_recv_cb_called);
3134       assert_uint8(NGHTTP2_PRIORITY_UPDATE, ==, ud.recv_frame_hd.type);
3135     } else {
3136       assert_int(0, ==, ud.frame_recv_cb_called);
3137     }
3138 
3139     nghttp2_bufs_reset(&bufs);
3140   }
3141 
3142   item = nghttp2_session_get_next_ob_item(session);
3143   assert_uint8(NGHTTP2_GOAWAY, ==, item->frame.hd.type);
3144   assert_uint32(NGHTTP2_PROTOCOL_ERROR, ==, item->frame.goaway.error_code);
3145 
3146   nghttp2_session_del(session);
3147   nghttp2_option_del(option);
3148   nghttp2_bufs_free(&bufs);
3149 }
3150 
test_nghttp2_session_continue(void)3151 void test_nghttp2_session_continue(void) {
3152   nghttp2_session *session;
3153   nghttp2_session_callbacks callbacks;
3154   my_user_data user_data;
3155   const nghttp2_nv nv1[] = {MAKE_NV(":method", "GET"), MAKE_NV(":path", "/")};
3156   const nghttp2_nv nv2[] = {MAKE_NV("user-agent", "nghttp2/1.0.0"),
3157                             MAKE_NV("alpha", "bravo")};
3158   nghttp2_bufs bufs;
3159   nghttp2_buf *buf;
3160   size_t framelen1, framelen2;
3161   nghttp2_ssize rv;
3162   uint8_t buffer[4096];
3163   nghttp2_buf databuf;
3164   nghttp2_frame frame;
3165   nghttp2_nv *nva;
3166   size_t nvlen;
3167   const nghttp2_frame *recv_frame;
3168   nghttp2_frame_hd data_hd;
3169   nghttp2_hd_deflater deflater;
3170   nghttp2_mem *mem;
3171 
3172   mem = nghttp2_mem_default();
3173   frame_pack_bufs_init(&bufs);
3174   nghttp2_buf_wrap_init(&databuf, buffer, sizeof(buffer));
3175 
3176   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
3177   callbacks.send_callback2 = null_send_callback;
3178   callbacks.on_frame_recv_callback = on_frame_recv_callback;
3179   callbacks.on_data_chunk_recv_callback = pause_on_data_chunk_recv_callback;
3180   callbacks.on_header_callback = pause_on_header_callback;
3181   callbacks.on_begin_headers_callback = on_begin_headers_callback;
3182 
3183   nghttp2_session_server_new(&session, &callbacks, &user_data);
3184   /* disable strict HTTP layering checks */
3185   session->opt_flags |= NGHTTP2_OPTMASK_NO_HTTP_MESSAGING;
3186 
3187   nghttp2_hd_deflate_init(&deflater, mem);
3188 
3189   /* Make 2 HEADERS frames */
3190   nvlen = ARRLEN(nv1);
3191   nghttp2_nv_array_copy(&nva, nv1, nvlen, mem);
3192   nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 1,
3193                              NGHTTP2_HCAT_HEADERS, NULL, nva, nvlen);
3194   rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
3195 
3196   assert_ptrdiff(0, ==, rv);
3197   assert_size(0, <, nghttp2_bufs_len(&bufs));
3198 
3199   nghttp2_frame_headers_free(&frame.headers, mem);
3200 
3201   buf = &bufs.head->buf;
3202   assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
3203 
3204   framelen1 = nghttp2_buf_len(buf);
3205   databuf.last = nghttp2_cpymem(databuf.last, buf->pos, nghttp2_buf_len(buf));
3206 
3207   nvlen = ARRLEN(nv2);
3208   nghttp2_nv_array_copy(&nva, nv2, nvlen, mem);
3209   nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 3,
3210                              NGHTTP2_HCAT_HEADERS, NULL, nva, nvlen);
3211   nghttp2_bufs_reset(&bufs);
3212   rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
3213 
3214   assert_ptrdiff(0, ==, rv);
3215   assert_size(0, <, nghttp2_bufs_len(&bufs));
3216 
3217   nghttp2_frame_headers_free(&frame.headers, mem);
3218 
3219   assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
3220 
3221   framelen2 = nghttp2_buf_len(buf);
3222   databuf.last = nghttp2_cpymem(databuf.last, buf->pos, nghttp2_buf_len(buf));
3223 
3224   /* Receive 1st HEADERS and pause */
3225   user_data.begin_headers_cb_called = 0;
3226   user_data.header_cb_called = 0;
3227   rv =
3228     nghttp2_session_mem_recv2(session, databuf.pos, nghttp2_buf_len(&databuf));
3229 
3230   assert_ptrdiff(0, <=, rv);
3231   databuf.pos += rv;
3232 
3233   recv_frame = user_data.frame;
3234   assert_uint8(NGHTTP2_HEADERS, ==, recv_frame->hd.type);
3235   assert_size(framelen1 - NGHTTP2_FRAME_HDLEN, ==, recv_frame->hd.length);
3236 
3237   assert_int(1, ==, user_data.begin_headers_cb_called);
3238   assert_int(1, ==, user_data.header_cb_called);
3239 
3240   assert_true(nghttp2_nv_equal(&nv1[0], &user_data.nv));
3241 
3242   /* get 2nd header field */
3243   user_data.begin_headers_cb_called = 0;
3244   user_data.header_cb_called = 0;
3245   rv =
3246     nghttp2_session_mem_recv2(session, databuf.pos, nghttp2_buf_len(&databuf));
3247 
3248   assert_ptrdiff(0, <=, rv);
3249   databuf.pos += rv;
3250 
3251   assert_int(0, ==, user_data.begin_headers_cb_called);
3252   assert_int(1, ==, user_data.header_cb_called);
3253 
3254   assert_true(nghttp2_nv_equal(&nv1[1], &user_data.nv));
3255 
3256   /* will call end_headers_callback and receive 2nd HEADERS and pause */
3257   user_data.begin_headers_cb_called = 0;
3258   user_data.header_cb_called = 0;
3259   rv =
3260     nghttp2_session_mem_recv2(session, databuf.pos, nghttp2_buf_len(&databuf));
3261 
3262   assert_ptrdiff(0, <=, rv);
3263   databuf.pos += rv;
3264 
3265   recv_frame = user_data.frame;
3266   assert_uint8(NGHTTP2_HEADERS, ==, recv_frame->hd.type);
3267   assert_size(framelen2 - NGHTTP2_FRAME_HDLEN, ==, recv_frame->hd.length);
3268 
3269   assert_int(1, ==, user_data.begin_headers_cb_called);
3270   assert_int(1, ==, user_data.header_cb_called);
3271 
3272   assert_true(nghttp2_nv_equal(&nv2[0], &user_data.nv));
3273 
3274   /* get 2nd header field */
3275   user_data.begin_headers_cb_called = 0;
3276   user_data.header_cb_called = 0;
3277   rv =
3278     nghttp2_session_mem_recv2(session, databuf.pos, nghttp2_buf_len(&databuf));
3279 
3280   assert_ptrdiff(0, <=, rv);
3281   databuf.pos += rv;
3282 
3283   assert_int(0, ==, user_data.begin_headers_cb_called);
3284   assert_int(1, ==, user_data.header_cb_called);
3285 
3286   assert_true(nghttp2_nv_equal(&nv2[1], &user_data.nv));
3287 
3288   /* No input data, frame_recv_callback is called */
3289   user_data.begin_headers_cb_called = 0;
3290   user_data.header_cb_called = 0;
3291   user_data.frame_recv_cb_called = 0;
3292   rv =
3293     nghttp2_session_mem_recv2(session, databuf.pos, nghttp2_buf_len(&databuf));
3294 
3295   assert_ptrdiff(0, <=, rv);
3296   databuf.pos += rv;
3297 
3298   assert_int(0, ==, user_data.begin_headers_cb_called);
3299   assert_int(0, ==, user_data.header_cb_called);
3300   assert_int(1, ==, user_data.frame_recv_cb_called);
3301 
3302   /* Receive DATA */
3303   nghttp2_frame_hd_init(&data_hd, 16, NGHTTP2_DATA, NGHTTP2_FLAG_NONE, 1);
3304 
3305   nghttp2_buf_reset(&databuf);
3306   nghttp2_frame_pack_frame_hd(databuf.pos, &data_hd);
3307 
3308   /* Intentionally specify larger buffer size to see pause is kicked
3309      in. */
3310   databuf.last = databuf.end;
3311 
3312   user_data.frame_recv_cb_called = 0;
3313   rv =
3314     nghttp2_session_mem_recv2(session, databuf.pos, nghttp2_buf_len(&databuf));
3315 
3316   assert_ptrdiff(16 + NGHTTP2_FRAME_HDLEN, ==, rv);
3317   assert_int(0, ==, user_data.frame_recv_cb_called);
3318 
3319   /* Next nghttp2_session_mem_recv2 invokes on_frame_recv_callback and
3320      pause again in on_data_chunk_recv_callback since we pass same
3321      DATA frame. */
3322   user_data.frame_recv_cb_called = 0;
3323   rv =
3324     nghttp2_session_mem_recv2(session, databuf.pos, nghttp2_buf_len(&databuf));
3325   assert_ptrdiff(16 + NGHTTP2_FRAME_HDLEN, ==, rv);
3326   assert_int(1, ==, user_data.frame_recv_cb_called);
3327 
3328   /* And finally call on_frame_recv_callback with 0 size input */
3329   user_data.frame_recv_cb_called = 0;
3330   rv = nghttp2_session_mem_recv2(session, NULL, 0);
3331   assert_ptrdiff(0, ==, rv);
3332   assert_int(1, ==, user_data.frame_recv_cb_called);
3333 
3334   nghttp2_bufs_free(&bufs);
3335   nghttp2_hd_deflate_free(&deflater);
3336   nghttp2_session_del(session);
3337 }
3338 
test_nghttp2_session_add_frame(void)3339 void test_nghttp2_session_add_frame(void) {
3340   nghttp2_session *session;
3341   nghttp2_session_callbacks callbacks;
3342   accumulator acc;
3343   my_user_data user_data;
3344   nghttp2_outbound_item *item;
3345   nghttp2_frame *frame;
3346   nghttp2_nv *nva;
3347   size_t nvlen;
3348   nghttp2_mem *mem;
3349 
3350   mem = nghttp2_mem_default();
3351   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
3352   callbacks.send_callback2 = accumulator_send_callback;
3353 
3354   acc.length = 0;
3355   user_data.acc = &acc;
3356 
3357   assert_int(0, ==,
3358              nghttp2_session_client_new(&session, &callbacks, &user_data));
3359 
3360   item = mem->malloc(sizeof(nghttp2_outbound_item), NULL);
3361 
3362   nghttp2_outbound_item_init(item);
3363 
3364   frame = &item->frame;
3365 
3366   nvlen = ARRLEN(reqnv);
3367   nghttp2_nv_array_copy(&nva, reqnv, nvlen, mem);
3368 
3369   nghttp2_frame_headers_init(
3370     &frame->headers, NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PRIORITY,
3371     (int32_t)session->next_stream_id, NGHTTP2_HCAT_REQUEST, NULL, nva, nvlen);
3372 
3373   session->next_stream_id += 2;
3374 
3375   assert_int(0, ==, nghttp2_session_add_item(session, item));
3376   assert_not_null(nghttp2_outbound_queue_top(&session->ob_syn));
3377   assert_int(0, ==, nghttp2_session_send(session));
3378   assert_uint8(NGHTTP2_HEADERS, ==, acc.buf[3]);
3379   assert_uint8((NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PRIORITY), ==,
3380                acc.buf[4]);
3381   /* check stream id */
3382   assert_uint32(1, ==, nghttp2_get_uint32(&acc.buf[5]));
3383 
3384   nghttp2_session_del(session);
3385 }
3386 
test_nghttp2_session_on_request_headers_received(void)3387 void test_nghttp2_session_on_request_headers_received(void) {
3388   nghttp2_session *session;
3389   nghttp2_session_callbacks callbacks;
3390   my_user_data user_data;
3391   nghttp2_frame frame;
3392   nghttp2_stream *stream;
3393   int32_t stream_id = 1;
3394   nghttp2_nv malformed_nva[] = {MAKE_NV(":path", "\x01")};
3395   nghttp2_nv *nva;
3396   size_t nvlen;
3397   nghttp2_priority_spec pri_spec;
3398   nghttp2_mem *mem;
3399 
3400   mem = nghttp2_mem_default();
3401   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
3402   callbacks.on_begin_headers_callback = on_begin_headers_callback;
3403   callbacks.on_invalid_frame_recv_callback = on_invalid_frame_recv_callback;
3404 
3405   nghttp2_session_server_new(&session, &callbacks, &user_data);
3406 
3407   nghttp2_priority_spec_init(&pri_spec, 0, 255, 0);
3408 
3409   nghttp2_frame_headers_init(
3410     &frame.headers, NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PRIORITY, stream_id,
3411     NGHTTP2_HCAT_REQUEST, &pri_spec, NULL, 0);
3412 
3413   user_data.begin_headers_cb_called = 0;
3414   user_data.invalid_frame_recv_cb_called = 0;
3415 
3416   assert_int(0, ==,
3417              nghttp2_session_on_request_headers_received(session, &frame));
3418   assert_int(1, ==, user_data.begin_headers_cb_called);
3419   stream = nghttp2_session_get_stream(session, stream_id);
3420   assert_enum(nghttp2_stream_state, NGHTTP2_STREAM_OPENING, ==, stream->state);
3421   assert_int32(255, ==, stream->weight);
3422 
3423   nghttp2_frame_headers_free(&frame.headers, mem);
3424 
3425   /* More than un-ACKed max concurrent streams leads REFUSED_STREAM */
3426   session->pending_local_max_concurrent_stream = 1;
3427   nghttp2_frame_headers_init(&frame.headers,
3428                              NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PRIORITY,
3429                              3, NGHTTP2_HCAT_HEADERS, NULL, NULL, 0);
3430   user_data.invalid_frame_recv_cb_called = 0;
3431   assert_int(NGHTTP2_ERR_IGN_HEADER_BLOCK, ==,
3432              nghttp2_session_on_request_headers_received(session, &frame));
3433   assert_int(1, ==, user_data.invalid_frame_recv_cb_called);
3434   assert_false(session->goaway_flags & NGHTTP2_GOAWAY_TERM_ON_SEND);
3435 
3436   nghttp2_frame_headers_free(&frame.headers, mem);
3437   session->local_settings.max_concurrent_streams =
3438     NGHTTP2_DEFAULT_MAX_CONCURRENT_STREAMS;
3439 
3440   /* Stream ID less than or equal to the previously received request
3441      HEADERS is just ignored due to race condition */
3442   nghttp2_frame_headers_init(&frame.headers,
3443                              NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PRIORITY,
3444                              3, NGHTTP2_HCAT_HEADERS, NULL, NULL, 0);
3445   user_data.invalid_frame_recv_cb_called = 0;
3446   assert_int(NGHTTP2_ERR_IGN_HEADER_BLOCK, ==,
3447              nghttp2_session_on_request_headers_received(session, &frame));
3448   assert_int(0, ==, user_data.invalid_frame_recv_cb_called);
3449   assert_false(session->goaway_flags & NGHTTP2_GOAWAY_TERM_ON_SEND);
3450 
3451   nghttp2_frame_headers_free(&frame.headers, mem);
3452 
3453   /* Stream ID is our side and it is idle stream ID, then treat it as
3454      connection error */
3455   nghttp2_frame_headers_init(&frame.headers,
3456                              NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PRIORITY,
3457                              2, NGHTTP2_HCAT_HEADERS, NULL, NULL, 0);
3458   user_data.invalid_frame_recv_cb_called = 0;
3459   assert_int(NGHTTP2_ERR_IGN_HEADER_BLOCK, ==,
3460              nghttp2_session_on_request_headers_received(session, &frame));
3461   assert_int(1, ==, user_data.invalid_frame_recv_cb_called);
3462   assert_true(session->goaway_flags & NGHTTP2_GOAWAY_TERM_ON_SEND);
3463 
3464   nghttp2_frame_headers_free(&frame.headers, mem);
3465 
3466   nghttp2_session_del(session);
3467 
3468   /* Check malformed headers. The library accept it. */
3469   nghttp2_session_server_new(&session, &callbacks, &user_data);
3470 
3471   nvlen = ARRLEN(malformed_nva);
3472   nghttp2_nv_array_copy(&nva, malformed_nva, nvlen, mem);
3473   nghttp2_frame_headers_init(&frame.headers,
3474                              NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PRIORITY,
3475                              1, NGHTTP2_HCAT_HEADERS, NULL, nva, nvlen);
3476   user_data.begin_headers_cb_called = 0;
3477   user_data.invalid_frame_recv_cb_called = 0;
3478   assert_int(0, ==,
3479              nghttp2_session_on_request_headers_received(session, &frame));
3480   assert_int(1, ==, user_data.begin_headers_cb_called);
3481   assert_int(0, ==, user_data.invalid_frame_recv_cb_called);
3482 
3483   nghttp2_frame_headers_free(&frame.headers, mem);
3484 
3485   nghttp2_session_del(session);
3486 
3487   /* Check client side */
3488   nghttp2_session_client_new(&session, &callbacks, &user_data);
3489 
3490   /* Receiving peer's idle stream ID is subject to connection error */
3491   nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 2,
3492                              NGHTTP2_HCAT_REQUEST, NULL, NULL, 0);
3493 
3494   user_data.invalid_frame_recv_cb_called = 0;
3495   assert_int(NGHTTP2_ERR_IGN_HEADER_BLOCK, ==,
3496              nghttp2_session_on_request_headers_received(session, &frame));
3497   assert_int(1, ==, user_data.invalid_frame_recv_cb_called);
3498   assert_true(session->goaway_flags & NGHTTP2_GOAWAY_TERM_ON_SEND);
3499 
3500   nghttp2_frame_headers_free(&frame.headers, mem);
3501 
3502   nghttp2_session_del(session);
3503 
3504   nghttp2_session_client_new(&session, &callbacks, &user_data);
3505 
3506   /* Receiving our's idle stream ID is subject to connection error */
3507   nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 1,
3508                              NGHTTP2_HCAT_REQUEST, NULL, NULL, 0);
3509 
3510   user_data.invalid_frame_recv_cb_called = 0;
3511   assert_int(NGHTTP2_ERR_IGN_HEADER_BLOCK, ==,
3512              nghttp2_session_on_request_headers_received(session, &frame));
3513   assert_int(1, ==, user_data.invalid_frame_recv_cb_called);
3514   assert_true(session->goaway_flags & NGHTTP2_GOAWAY_TERM_ON_SEND);
3515 
3516   nghttp2_frame_headers_free(&frame.headers, mem);
3517 
3518   nghttp2_session_del(session);
3519 
3520   nghttp2_session_client_new(&session, &callbacks, &user_data);
3521 
3522   session->next_stream_id = 5;
3523   session->last_sent_stream_id = 3;
3524 
3525   /* Stream ID which is not idle and not in stream map is just
3526      ignored */
3527   nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 3,
3528                              NGHTTP2_HCAT_REQUEST, NULL, NULL, 0);
3529 
3530   user_data.invalid_frame_recv_cb_called = 0;
3531   assert_int(NGHTTP2_ERR_IGN_HEADER_BLOCK, ==,
3532              nghttp2_session_on_request_headers_received(session, &frame));
3533   assert_int(0, ==, user_data.invalid_frame_recv_cb_called);
3534   assert_false(session->goaway_flags & NGHTTP2_GOAWAY_TERM_ON_SEND);
3535 
3536   nghttp2_frame_headers_free(&frame.headers, mem);
3537 
3538   nghttp2_session_del(session);
3539 
3540   nghttp2_session_server_new(&session, &callbacks, &user_data);
3541 
3542   /* Stream ID which is equal to local_last_stream_id is ok. */
3543   session->local_last_stream_id = 3;
3544 
3545   nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 3,
3546                              NGHTTP2_HCAT_REQUEST, NULL, NULL, 0);
3547 
3548   assert_int(0, ==,
3549              nghttp2_session_on_request_headers_received(session, &frame));
3550 
3551   nghttp2_frame_headers_free(&frame.headers, mem);
3552 
3553   /* If GOAWAY has been sent, new stream is ignored */
3554   nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 5,
3555                              NGHTTP2_HCAT_REQUEST, NULL, NULL, 0);
3556 
3557   session->goaway_flags |= NGHTTP2_GOAWAY_SENT;
3558   user_data.invalid_frame_recv_cb_called = 0;
3559   assert_int(NGHTTP2_ERR_IGN_HEADER_BLOCK, ==,
3560              nghttp2_session_on_request_headers_received(session, &frame));
3561   assert_int(0, ==, user_data.invalid_frame_recv_cb_called);
3562   assert_false(session->goaway_flags & NGHTTP2_GOAWAY_TERM_ON_SEND);
3563 
3564   nghttp2_frame_headers_free(&frame.headers, mem);
3565 
3566   nghttp2_session_del(session);
3567 
3568   nghttp2_session_server_new(&session, &callbacks, &user_data);
3569 
3570   /* HEADERS to closed stream */
3571   stream = open_recv_stream(session, 1);
3572   nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_RD);
3573   nghttp2_session_close_stream(session, 1, NGHTTP2_NO_ERROR);
3574 
3575   nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 1,
3576                              NGHTTP2_HCAT_REQUEST, NULL, NULL, 0);
3577 
3578   assert_int(NGHTTP2_ERR_IGN_HEADER_BLOCK, ==,
3579              nghttp2_session_on_request_headers_received(session, &frame));
3580   assert_true(session->goaway_flags & NGHTTP2_GOAWAY_TERM_ON_SEND);
3581 
3582   nghttp2_frame_headers_free(&frame.headers, mem);
3583 
3584   nghttp2_session_del(session);
3585 }
3586 
test_nghttp2_session_on_response_headers_received(void)3587 void test_nghttp2_session_on_response_headers_received(void) {
3588   nghttp2_session *session;
3589   nghttp2_session_callbacks callbacks;
3590   my_user_data user_data;
3591   nghttp2_frame frame;
3592   nghttp2_stream *stream;
3593   nghttp2_mem *mem;
3594 
3595   mem = nghttp2_mem_default();
3596   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
3597   callbacks.on_begin_headers_callback = on_begin_headers_callback;
3598   callbacks.on_invalid_frame_recv_callback = on_invalid_frame_recv_callback;
3599 
3600   nghttp2_session_client_new(&session, &callbacks, &user_data);
3601   stream = open_sent_stream2(session, 1, NGHTTP2_STREAM_OPENING);
3602   nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 1,
3603                              NGHTTP2_HCAT_HEADERS, NULL, NULL, 0);
3604 
3605   user_data.begin_headers_cb_called = 0;
3606   user_data.invalid_frame_recv_cb_called = 0;
3607 
3608   assert_int(
3609     0, ==,
3610     nghttp2_session_on_response_headers_received(session, &frame, stream));
3611   assert_int(1, ==, user_data.begin_headers_cb_called);
3612   assert_enum(nghttp2_stream_state, NGHTTP2_STREAM_OPENED, ==, stream->state);
3613 
3614   nghttp2_frame_headers_free(&frame.headers, mem);
3615   nghttp2_session_del(session);
3616 }
3617 
test_nghttp2_session_on_headers_received(void)3618 void test_nghttp2_session_on_headers_received(void) {
3619   nghttp2_session *session;
3620   nghttp2_session_callbacks callbacks;
3621   my_user_data user_data;
3622   nghttp2_frame frame;
3623   nghttp2_stream *stream;
3624   nghttp2_mem *mem;
3625 
3626   mem = nghttp2_mem_default();
3627   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
3628   callbacks.on_begin_headers_callback = on_begin_headers_callback;
3629   callbacks.on_invalid_frame_recv_callback = on_invalid_frame_recv_callback;
3630 
3631   nghttp2_session_client_new(&session, &callbacks, &user_data);
3632   stream = open_sent_stream2(session, 1, NGHTTP2_STREAM_OPENED);
3633   nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_WR);
3634   nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 1,
3635                              NGHTTP2_HCAT_HEADERS, NULL, NULL, 0);
3636 
3637   user_data.begin_headers_cb_called = 0;
3638   user_data.invalid_frame_recv_cb_called = 0;
3639 
3640   assert_int(0, ==,
3641              nghttp2_session_on_headers_received(session, &frame, stream));
3642   assert_int(1, ==, user_data.begin_headers_cb_called);
3643   assert_enum(nghttp2_stream_state, NGHTTP2_STREAM_OPENED, ==, stream->state);
3644 
3645   /* stream closed */
3646   frame.hd.flags |= NGHTTP2_FLAG_END_STREAM;
3647 
3648   assert_int(0, ==,
3649              nghttp2_session_on_headers_received(session, &frame, stream));
3650   assert_int(2, ==, user_data.begin_headers_cb_called);
3651 
3652   /* Check to see when NGHTTP2_STREAM_CLOSING, incoming HEADERS is
3653      discarded. */
3654   stream = open_sent_stream2(session, 3, NGHTTP2_STREAM_CLOSING);
3655   frame.hd.stream_id = 3;
3656   frame.hd.flags = NGHTTP2_FLAG_END_HEADERS;
3657   assert_int(NGHTTP2_ERR_IGN_HEADER_BLOCK, ==,
3658              nghttp2_session_on_headers_received(session, &frame, stream));
3659   /* See no counters are updated */
3660   assert_int(2, ==, user_data.begin_headers_cb_called);
3661   assert_int(0, ==, user_data.invalid_frame_recv_cb_called);
3662 
3663   /* Server initiated stream */
3664   stream = open_recv_stream(session, 2);
3665 
3666   frame.hd.flags = NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM;
3667   frame.hd.stream_id = 2;
3668 
3669   assert_int(0, ==,
3670              nghttp2_session_on_headers_received(session, &frame, stream));
3671   assert_int(3, ==, user_data.begin_headers_cb_called);
3672   assert_enum(nghttp2_stream_state, NGHTTP2_STREAM_OPENED, ==, stream->state);
3673 
3674   nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_RD);
3675 
3676   /* Further reception of HEADERS is subject to stream error */
3677   assert_int(NGHTTP2_ERR_IGN_HEADER_BLOCK, ==,
3678              nghttp2_session_on_headers_received(session, &frame, stream));
3679   assert_int(1, ==, user_data.invalid_frame_recv_cb_called);
3680 
3681   nghttp2_frame_headers_free(&frame.headers, mem);
3682 
3683   nghttp2_session_del(session);
3684 }
3685 
test_nghttp2_session_on_push_response_headers_received(void)3686 void test_nghttp2_session_on_push_response_headers_received(void) {
3687   nghttp2_session *session;
3688   nghttp2_session_callbacks callbacks;
3689   my_user_data user_data;
3690   nghttp2_frame frame;
3691   nghttp2_stream *stream;
3692   nghttp2_outbound_item *item;
3693   nghttp2_mem *mem;
3694 
3695   mem = nghttp2_mem_default();
3696   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
3697   callbacks.send_callback2 = null_send_callback;
3698   callbacks.on_begin_headers_callback = on_begin_headers_callback;
3699   callbacks.on_invalid_frame_recv_callback = on_invalid_frame_recv_callback;
3700 
3701   nghttp2_session_client_new(&session, &callbacks, &user_data);
3702   stream = open_recv_stream2(session, 2, NGHTTP2_STREAM_RESERVED);
3703   nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 2,
3704                              NGHTTP2_HCAT_HEADERS, NULL, NULL, 0);
3705   /* nghttp2_session_on_push_response_headers_received assumes
3706      stream's state is NGHTTP2_STREAM_RESERVED and session->server is
3707      0. */
3708 
3709   user_data.begin_headers_cb_called = 0;
3710   user_data.invalid_frame_recv_cb_called = 0;
3711 
3712   assert_size(1, ==, session->num_incoming_reserved_streams);
3713   assert_int(
3714     0, ==,
3715     nghttp2_session_on_push_response_headers_received(session, &frame, stream));
3716   assert_int(1, ==, user_data.begin_headers_cb_called);
3717   assert_size(0, ==, session->num_incoming_reserved_streams);
3718   assert_enum(nghttp2_stream_state, NGHTTP2_STREAM_OPENED, ==, stream->state);
3719   assert_size(1, ==, session->num_incoming_streams);
3720   assert_false(stream->flags & NGHTTP2_STREAM_FLAG_PUSH);
3721 
3722   /* If un-ACKed max concurrent streams limit is exceeded,
3723      RST_STREAMed */
3724   session->pending_local_max_concurrent_stream = 1;
3725   stream = open_recv_stream2(session, 4, NGHTTP2_STREAM_RESERVED);
3726   frame.hd.stream_id = 4;
3727   assert_int(
3728     NGHTTP2_ERR_IGN_HEADER_BLOCK, ==,
3729     nghttp2_session_on_push_response_headers_received(session, &frame, stream));
3730   item = nghttp2_session_get_next_ob_item(session);
3731   assert_uint8(NGHTTP2_RST_STREAM, ==, item->frame.hd.type);
3732   assert_uint32(NGHTTP2_REFUSED_STREAM, ==, item->frame.rst_stream.error_code);
3733   assert_size(1, ==, session->num_incoming_streams);
3734   assert_size(1, ==, session->num_incoming_reserved_streams);
3735 
3736   assert_int(0, ==, nghttp2_session_send(session));
3737   assert_size(1, ==, session->num_incoming_streams);
3738 
3739   /* If ACKed max concurrent streams limit is exceeded, GOAWAY is
3740      issued */
3741   session->local_settings.max_concurrent_streams = 1;
3742 
3743   stream = open_recv_stream2(session, 6, NGHTTP2_STREAM_RESERVED);
3744   frame.hd.stream_id = 6;
3745 
3746   assert_int(
3747     NGHTTP2_ERR_IGN_HEADER_BLOCK, ==,
3748     nghttp2_session_on_push_response_headers_received(session, &frame, stream));
3749   item = nghttp2_session_get_next_ob_item(session);
3750   assert_uint8(NGHTTP2_GOAWAY, ==, item->frame.hd.type);
3751   assert_uint32(NGHTTP2_PROTOCOL_ERROR, ==, item->frame.goaway.error_code);
3752   assert_size(1, ==, session->num_incoming_streams);
3753   assert_size(1, ==, session->num_incoming_reserved_streams);
3754 
3755   nghttp2_frame_headers_free(&frame.headers, mem);
3756   nghttp2_session_del(session);
3757 }
3758 
test_nghttp2_session_on_priority_received(void)3759 void test_nghttp2_session_on_priority_received(void) {
3760   nghttp2_session *session;
3761   nghttp2_session_callbacks callbacks;
3762   my_user_data user_data;
3763   nghttp2_frame frame;
3764   nghttp2_stream *stream, *dep_stream;
3765   nghttp2_priority_spec pri_spec;
3766   nghttp2_outbound_item *item;
3767 
3768   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
3769   callbacks.on_frame_recv_callback = on_frame_recv_callback;
3770   callbacks.on_invalid_frame_recv_callback = on_invalid_frame_recv_callback;
3771 
3772   nghttp2_session_server_new(&session, &callbacks, &user_data);
3773   stream = open_recv_stream(session, 1);
3774 
3775   nghttp2_priority_spec_init(&pri_spec, 0, 2, 0);
3776 
3777   nghttp2_frame_priority_init(&frame.priority, 1, &pri_spec);
3778 
3779   /* depend on stream 0 */
3780   assert_int(0, ==, nghttp2_session_on_priority_received(session, &frame));
3781 
3782   assert_int32(2, ==, stream->weight);
3783 
3784   stream = open_sent_stream(session, 2);
3785   dep_stream = open_recv_stream(session, 3);
3786 
3787   frame.hd.stream_id = 2;
3788 
3789   /* using dependency stream */
3790   nghttp2_priority_spec_init(&frame.priority.pri_spec, 3, 1, 0);
3791 
3792   assert_int(0, ==, nghttp2_session_on_priority_received(session, &frame));
3793   assert_ptr_equal(dep_stream, stream->dep_prev);
3794 
3795   /* PRIORITY against idle stream */
3796 
3797   frame.hd.stream_id = 100;
3798 
3799   assert_int(0, ==, nghttp2_session_on_priority_received(session, &frame));
3800 
3801   stream = nghttp2_session_get_stream_raw(session, frame.hd.stream_id);
3802 
3803   assert_enum(nghttp2_stream_state, NGHTTP2_STREAM_IDLE, ==, stream->state);
3804   assert_ptr_equal(dep_stream, stream->dep_prev);
3805 
3806   nghttp2_frame_priority_free(&frame.priority);
3807   nghttp2_session_del(session);
3808 
3809   /* Check dep_stream_id == stream_id case */
3810   nghttp2_session_server_new(&session, &callbacks, &user_data);
3811   open_recv_stream(session, 1);
3812 
3813   nghttp2_priority_spec_init(&pri_spec, 1, 0, 0);
3814 
3815   nghttp2_frame_priority_init(&frame.priority, 1, &pri_spec);
3816 
3817   assert_int(0, ==, nghttp2_session_on_priority_received(session, &frame));
3818 
3819   item = nghttp2_session_get_next_ob_item(session);
3820 
3821   assert_uint8(NGHTTP2_GOAWAY, ==, item->frame.hd.type);
3822 
3823   nghttp2_frame_priority_free(&frame.priority);
3824   nghttp2_session_del(session);
3825 
3826   /* Check again dep_stream_id == stream_id, and stream_id is idle */
3827   nghttp2_session_server_new(&session, &callbacks, &user_data);
3828 
3829   nghttp2_priority_spec_init(&pri_spec, 1, 16, 0);
3830 
3831   nghttp2_frame_priority_init(&frame.priority, 1, &pri_spec);
3832 
3833   assert_int(0, ==, nghttp2_session_on_priority_received(session, &frame));
3834 
3835   item = nghttp2_session_get_next_ob_item(session);
3836 
3837   assert_uint8(NGHTTP2_GOAWAY, ==, item->frame.hd.type);
3838 
3839   nghttp2_frame_priority_free(&frame.priority);
3840   nghttp2_session_del(session);
3841 }
3842 
test_nghttp2_session_on_rst_stream_received(void)3843 void test_nghttp2_session_on_rst_stream_received(void) {
3844   nghttp2_session *session;
3845   nghttp2_session_callbacks callbacks;
3846   my_user_data user_data;
3847   nghttp2_frame frame;
3848   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
3849   nghttp2_session_server_new(&session, &callbacks, &user_data);
3850   open_recv_stream(session, 1);
3851 
3852   nghttp2_frame_rst_stream_init(&frame.rst_stream, 1, NGHTTP2_PROTOCOL_ERROR);
3853 
3854   assert_int(0, ==, nghttp2_session_on_rst_stream_received(session, &frame));
3855   assert_null(nghttp2_session_get_stream(session, 1));
3856 
3857   nghttp2_frame_rst_stream_free(&frame.rst_stream);
3858   nghttp2_session_del(session);
3859 }
3860 
test_nghttp2_session_on_settings_received(void)3861 void test_nghttp2_session_on_settings_received(void) {
3862   nghttp2_session *session;
3863   nghttp2_session_callbacks callbacks;
3864   my_user_data user_data;
3865   nghttp2_stream *stream1, *stream2;
3866   nghttp2_frame frame;
3867   const size_t niv = 5;
3868   nghttp2_settings_entry iv[255];
3869   nghttp2_outbound_item *item;
3870   nghttp2_nv nv = MAKE_NV(":authority", "example.org");
3871   nghttp2_mem *mem;
3872   nghttp2_option *option;
3873   uint8_t data[2048];
3874   nghttp2_frame_hd hd;
3875   int rv;
3876   nghttp2_ssize nread;
3877   nghttp2_stream *stream;
3878 
3879   mem = nghttp2_mem_default();
3880 
3881   iv[0].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS;
3882   iv[0].value = 50;
3883 
3884   iv[1].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS;
3885   iv[1].value = 1000000009;
3886 
3887   iv[2].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
3888   iv[2].value = 64 * 1024;
3889 
3890   iv[3].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
3891   iv[3].value = 1024;
3892 
3893   iv[4].settings_id = NGHTTP2_SETTINGS_ENABLE_PUSH;
3894   iv[4].value = 0;
3895 
3896   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
3897   callbacks.send_callback2 = null_send_callback;
3898 
3899   nghttp2_session_client_new(&session, &callbacks, &user_data);
3900   session->remote_settings.initial_window_size = 16 * 1024;
3901 
3902   stream1 = open_sent_stream(session, 1);
3903   stream2 = open_recv_stream(session, 2);
3904 
3905   /* Set window size for each streams and will see how settings
3906      updates these values */
3907   stream1->remote_window_size = 16 * 1024;
3908   stream2->remote_window_size = -48 * 1024;
3909 
3910   nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE,
3911                               dup_iv(iv, niv), niv);
3912 
3913   assert_int(0, ==, nghttp2_session_on_settings_received(session, &frame, 0));
3914   assert_uint32(1000000009, ==,
3915                 session->remote_settings.max_concurrent_streams);
3916   assert_uint32(64 * 1024, ==, session->remote_settings.initial_window_size);
3917   assert_uint32(1024, ==, session->remote_settings.header_table_size);
3918   assert_uint32(0, ==, session->remote_settings.enable_push);
3919 
3920   assert_int32(64 * 1024, ==, stream1->remote_window_size);
3921   assert_int32(0, ==, stream2->remote_window_size);
3922 
3923   frame.settings.iv[2].value = 16 * 1024;
3924 
3925   assert_int(0, ==, nghttp2_session_on_settings_received(session, &frame, 0));
3926 
3927   assert_int32(16 * 1024, ==, stream1->remote_window_size);
3928   assert_int32(-48 * 1024, ==, stream2->remote_window_size);
3929 
3930   assert_int32(
3931     16 * 1024, ==,
3932     nghttp2_session_get_stream_remote_window_size(session, stream1->stream_id));
3933   assert_int32(
3934     0, ==,
3935     nghttp2_session_get_stream_remote_window_size(session, stream2->stream_id));
3936 
3937   nghttp2_frame_settings_free(&frame.settings, mem);
3938 
3939   nghttp2_session_del(session);
3940 
3941   /* Check ACK with niv > 0 */
3942   nghttp2_session_server_new(&session, &callbacks, NULL);
3943   nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_ACK, dup_iv(iv, 1),
3944                               1);
3945   assert_int(0, ==, nghttp2_session_on_settings_received(session, &frame, 0));
3946   item = nghttp2_session_get_next_ob_item(session);
3947   assert_not_null(item);
3948   assert_uint8(NGHTTP2_GOAWAY, ==, item->frame.hd.type);
3949 
3950   nghttp2_frame_settings_free(&frame.settings, mem);
3951   nghttp2_session_del(session);
3952 
3953   /* Check ACK against no inflight SETTINGS */
3954   nghttp2_session_server_new(&session, &callbacks, NULL);
3955   nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_ACK, NULL, 0);
3956 
3957   assert_int(0, ==, nghttp2_session_on_settings_received(session, &frame, 0));
3958   item = nghttp2_session_get_next_ob_item(session);
3959   assert_not_null(item);
3960   assert_uint8(NGHTTP2_GOAWAY, ==, item->frame.hd.type);
3961 
3962   nghttp2_frame_settings_free(&frame.settings, mem);
3963   nghttp2_session_del(session);
3964 
3965   /* Check that 2 SETTINGS_HEADER_TABLE_SIZE 0 and 4096 are included
3966      and header table size is once cleared to 0. */
3967   nghttp2_session_client_new(&session, &callbacks, NULL);
3968 
3969   nghttp2_submit_request2(session, NULL, &nv, 1, NULL, NULL);
3970 
3971   nghttp2_session_send(session);
3972 
3973   assert_size(0, <, session->hd_deflater.ctx.hd_table.len);
3974 
3975   iv[0].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
3976   iv[0].value = 0;
3977 
3978   iv[1].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
3979   iv[1].value = 2048;
3980 
3981   nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE, dup_iv(iv, 2),
3982                               2);
3983 
3984   assert_int(0, ==, nghttp2_session_on_settings_received(session, &frame, 0));
3985 
3986   assert_size(0, ==, session->hd_deflater.ctx.hd_table.len);
3987   assert_size(2048, ==, session->hd_deflater.ctx.hd_table_bufsize_max);
3988   assert_uint32(2048, ==, session->remote_settings.header_table_size);
3989 
3990   nghttp2_frame_settings_free(&frame.settings, mem);
3991   nghttp2_session_del(session);
3992 
3993   /* Check that remote SETTINGS_MAX_CONCURRENT_STREAMS is set to a value set by
3994      nghttp2_option_set_peer_max_concurrent_streams() and reset to the default
3995      value (unlimited) after receiving initial SETTINGS frame from the peer. */
3996   nghttp2_option_new(&option);
3997   nghttp2_option_set_peer_max_concurrent_streams(option, 1000);
3998   nghttp2_session_client_new2(&session, &callbacks, NULL, option);
3999   assert_uint32(1000, ==, session->remote_settings.max_concurrent_streams);
4000 
4001   nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE, NULL, 0);
4002   assert_int(0, ==, nghttp2_session_on_settings_received(session, &frame, 0));
4003   assert_uint32(NGHTTP2_DEFAULT_MAX_CONCURRENT_STREAMS, ==,
4004                 session->remote_settings.max_concurrent_streams);
4005 
4006   nghttp2_frame_settings_free(&frame.settings, mem);
4007   nghttp2_session_del(session);
4008   nghttp2_option_del(option);
4009 
4010   /* Check too large SETTINGS_MAX_FRAME_SIZE */
4011   nghttp2_session_server_new(&session, &callbacks, NULL);
4012 
4013   iv[0].settings_id = NGHTTP2_SETTINGS_MAX_FRAME_SIZE;
4014   iv[0].value = NGHTTP2_MAX_FRAME_SIZE_MAX + 1;
4015 
4016   nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE, dup_iv(iv, 1),
4017                               1);
4018 
4019   assert_int(0, ==, nghttp2_session_on_settings_received(session, &frame, 0));
4020 
4021   item = nghttp2_session_get_next_ob_item(session);
4022 
4023   assert_not_null(item);
4024   assert_uint8(NGHTTP2_GOAWAY, ==, item->frame.hd.type);
4025 
4026   nghttp2_frame_settings_free(&frame.settings, mem);
4027   nghttp2_session_del(session);
4028 
4029   /* Check the case where stream window size overflows */
4030   nghttp2_session_server_new(&session, &callbacks, NULL);
4031 
4032   stream1 = open_recv_stream(session, 1);
4033 
4034   /* This will increment window size by 1 */
4035   nghttp2_frame_window_update_init(&frame.window_update, NGHTTP2_FLAG_NONE, 1,
4036                                    1);
4037 
4038   assert_int(0, ==, nghttp2_session_on_window_update_received(session, &frame));
4039 
4040   nghttp2_frame_window_update_free(&frame.window_update);
4041 
4042   iv[0].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
4043   iv[0].value = NGHTTP2_MAX_WINDOW_SIZE;
4044 
4045   nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE, dup_iv(iv, 1),
4046                               1);
4047 
4048   /* Now window size gets NGHTTP2_MAX_WINDOW_SIZE + 1, which is
4049      unacceptable situation in protocol spec. */
4050   assert_int(0, ==, nghttp2_session_on_settings_received(session, &frame, 0));
4051 
4052   nghttp2_frame_settings_free(&frame.settings, mem);
4053 
4054   item = nghttp2_session_get_next_ob_item(session);
4055 
4056   assert_not_null(item);
4057   assert_uint8(NGHTTP2_SETTINGS, ==, item->frame.hd.type);
4058 
4059   item = nghttp2_outbound_queue_top(&session->ob_reg);
4060 
4061   assert_not_null(item);
4062   assert_uint8(NGHTTP2_RST_STREAM, ==, item->frame.hd.type);
4063   assert_enum(nghttp2_stream_state, NGHTTP2_STREAM_CLOSING, ==, stream1->state);
4064 
4065   nghttp2_session_del(session);
4066 
4067   /* It is invalid that peer disables ENABLE_CONNECT_PROTOCOL once it
4068      has been enabled. */
4069   nghttp2_session_client_new(&session, &callbacks, NULL);
4070 
4071   session->remote_settings.enable_connect_protocol = 1;
4072 
4073   iv[0].settings_id = NGHTTP2_SETTINGS_ENABLE_CONNECT_PROTOCOL;
4074   iv[0].value = 0;
4075 
4076   nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE, dup_iv(iv, 1),
4077                               1);
4078 
4079   assert_int(0, ==, nghttp2_session_on_settings_received(session, &frame, 0));
4080 
4081   nghttp2_frame_settings_free(&frame.settings, mem);
4082 
4083   item = nghttp2_session_get_next_ob_item(session);
4084 
4085   assert_not_null(item);
4086   assert_uint8(NGHTTP2_GOAWAY, ==, item->frame.hd.type);
4087 
4088   nghttp2_session_del(session);
4089 
4090   /* Should send WINDOW_UPDATE with no_auto_window_update option on if
4091      the initial window size is decreased and becomes smaller than or
4092      equal to the amount of data that has already received. */
4093   nghttp2_option_new(&option);
4094   nghttp2_option_set_no_auto_window_update(option, 1);
4095 
4096   nghttp2_session_server_new2(&session, &callbacks, NULL, option);
4097 
4098   iv[0].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
4099   iv[0].value = 1024;
4100 
4101   rv = nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, iv, 1);
4102 
4103   assert_int(0, ==, rv);
4104 
4105   rv = nghttp2_session_send(session);
4106 
4107   assert_int(0, ==, rv);
4108 
4109   stream = open_recv_stream(session, 1);
4110 
4111   memset(data, 0, sizeof(data));
4112   hd.length = 1024;
4113   hd.type = NGHTTP2_DATA;
4114   hd.flags = NGHTTP2_FLAG_NONE;
4115   hd.stream_id = 1;
4116   nghttp2_frame_pack_frame_hd(data, &hd);
4117 
4118   nread =
4119     nghttp2_session_mem_recv2(session, data, NGHTTP2_FRAME_HDLEN + hd.length);
4120 
4121   assert_ptrdiff((nghttp2_ssize)(NGHTTP2_FRAME_HDLEN + hd.length), ==, nread);
4122 
4123   rv = nghttp2_session_consume(session, 1, hd.length);
4124 
4125   assert_int(0, ==, rv);
4126   assert_int32((int32_t)hd.length, ==, stream->recv_window_size);
4127   assert_int32((int32_t)hd.length, ==, stream->consumed_size);
4128 
4129   nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_ACK, NULL, 0);
4130 
4131   rv = nghttp2_session_on_settings_received(session, &frame, 0);
4132 
4133   assert_int(0, ==, rv);
4134   assert_int32(1024, ==, stream->local_window_size);
4135   assert_int32(0, ==, stream->recv_window_size);
4136   assert_int32(0, ==, stream->consumed_size);
4137 
4138   item = nghttp2_session_get_next_ob_item(session);
4139 
4140   assert_not_null(item);
4141   assert_uint8(NGHTTP2_WINDOW_UPDATE, ==, item->frame.hd.type);
4142   assert_int32((int32_t)hd.length, ==,
4143                item->frame.window_update.window_size_increment);
4144 
4145   nghttp2_session_del(session);
4146   nghttp2_option_del(option);
4147 
4148   /* It is invalid to change SETTINGS_NO_RFC7540_PRIORITIES in the
4149      following SETTINGS. */
4150   nghttp2_session_client_new(&session, &callbacks, NULL);
4151 
4152   session->remote_settings.no_rfc7540_priorities = 1;
4153 
4154   iv[0].settings_id = NGHTTP2_SETTINGS_NO_RFC7540_PRIORITIES;
4155   iv[0].value = 0;
4156 
4157   nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE, dup_iv(iv, 1),
4158                               1);
4159 
4160   assert_int(0, ==, nghttp2_session_on_settings_received(session, &frame, 0));
4161 
4162   nghttp2_frame_settings_free(&frame.settings, mem);
4163 
4164   item = nghttp2_session_get_next_ob_item(session);
4165 
4166   assert_not_null(item);
4167   assert_uint8(NGHTTP2_GOAWAY, ==, item->frame.hd.type);
4168 
4169   nghttp2_session_del(session);
4170 }
4171 
test_nghttp2_session_on_push_promise_received(void)4172 void test_nghttp2_session_on_push_promise_received(void) {
4173   nghttp2_session *session;
4174   nghttp2_session_callbacks callbacks;
4175   my_user_data user_data;
4176   nghttp2_frame frame;
4177   nghttp2_stream *stream, *promised_stream;
4178   nghttp2_outbound_item *item;
4179   nghttp2_nv malformed_nva[] = {MAKE_NV(":path", "\x01")};
4180   nghttp2_nv *nva;
4181   size_t nvlen;
4182   nghttp2_mem *mem;
4183   nghttp2_settings_entry iv = {NGHTTP2_SETTINGS_ENABLE_PUSH, 0};
4184 
4185   mem = nghttp2_mem_default();
4186   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4187   callbacks.send_callback2 = null_send_callback;
4188   callbacks.on_begin_headers_callback = on_begin_headers_callback;
4189   callbacks.on_invalid_frame_recv_callback = on_invalid_frame_recv_callback;
4190 
4191   nghttp2_session_client_new(&session, &callbacks, &user_data);
4192 
4193   stream = open_sent_stream(session, 1);
4194 
4195   nghttp2_frame_push_promise_init(&frame.push_promise, NGHTTP2_FLAG_END_HEADERS,
4196                                   1, 2, NULL, 0);
4197 
4198   user_data.begin_headers_cb_called = 0;
4199   user_data.invalid_frame_recv_cb_called = 0;
4200 
4201   assert_int(0, ==, nghttp2_session_on_push_promise_received(session, &frame));
4202 
4203   assert_int(1, ==, user_data.begin_headers_cb_called);
4204   assert_size(1, ==, session->num_incoming_reserved_streams);
4205   promised_stream = nghttp2_session_get_stream(session, 2);
4206   assert_enum(nghttp2_stream_state, NGHTTP2_STREAM_RESERVED, ==,
4207               promised_stream->state);
4208   assert_int32(2, ==, session->last_recv_stream_id);
4209 
4210   /* Attempt to PUSH_PROMISE against half close (remote) */
4211   nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_RD);
4212   frame.push_promise.promised_stream_id = 4;
4213 
4214   user_data.begin_headers_cb_called = 0;
4215   user_data.invalid_frame_recv_cb_called = 0;
4216   assert_int(NGHTTP2_ERR_IGN_HEADER_BLOCK, ==,
4217              nghttp2_session_on_push_promise_received(session, &frame));
4218 
4219   assert_int(0, ==, user_data.begin_headers_cb_called);
4220   assert_int(1, ==, user_data.invalid_frame_recv_cb_called);
4221   assert_size(1, ==, session->num_incoming_reserved_streams);
4222   assert_null(nghttp2_session_get_stream(session, 4));
4223   item = nghttp2_session_get_next_ob_item(session);
4224   assert_uint8(NGHTTP2_GOAWAY, ==, item->frame.hd.type);
4225   assert_uint32(NGHTTP2_STREAM_CLOSED, ==, item->frame.goaway.error_code);
4226   assert_int(0, ==, nghttp2_session_send(session));
4227   assert_int32(4, ==, session->last_recv_stream_id);
4228 
4229   nghttp2_session_del(session);
4230 
4231   nghttp2_session_client_new(&session, &callbacks, &user_data);
4232 
4233   stream = open_sent_stream(session, 1);
4234 
4235   /* Attempt to PUSH_PROMISE against stream in closing state */
4236   stream->state = NGHTTP2_STREAM_CLOSING;
4237   frame.push_promise.promised_stream_id = 6;
4238 
4239   user_data.begin_headers_cb_called = 0;
4240   user_data.invalid_frame_recv_cb_called = 0;
4241   assert_int(NGHTTP2_ERR_IGN_HEADER_BLOCK, ==,
4242              nghttp2_session_on_push_promise_received(session, &frame));
4243 
4244   assert_int(0, ==, user_data.begin_headers_cb_called);
4245   assert_size(0, ==, session->num_incoming_reserved_streams);
4246   assert_null(nghttp2_session_get_stream(session, 6));
4247   item = nghttp2_session_get_next_ob_item(session);
4248   assert_uint8(NGHTTP2_RST_STREAM, ==, item->frame.hd.type);
4249   assert_int32(6, ==, item->frame.hd.stream_id);
4250   assert_uint32(NGHTTP2_CANCEL, ==, item->frame.rst_stream.error_code);
4251   assert_int(0, ==, nghttp2_session_send(session));
4252 
4253   /* Attempt to PUSH_PROMISE against idle stream */
4254   frame.hd.stream_id = 3;
4255   frame.push_promise.promised_stream_id = 8;
4256 
4257   user_data.begin_headers_cb_called = 0;
4258   user_data.invalid_frame_recv_cb_called = 0;
4259   assert_int(NGHTTP2_ERR_IGN_HEADER_BLOCK, ==,
4260              nghttp2_session_on_push_promise_received(session, &frame));
4261 
4262   assert_int(0, ==, user_data.begin_headers_cb_called);
4263   assert_size(0, ==, session->num_incoming_reserved_streams);
4264   assert_null(nghttp2_session_get_stream(session, 8));
4265   item = nghttp2_session_get_next_ob_item(session);
4266   assert_uint8(NGHTTP2_GOAWAY, ==, item->frame.hd.type);
4267   assert_int32(0, ==, item->frame.hd.stream_id);
4268   assert_uint32(NGHTTP2_PROTOCOL_ERROR, ==, item->frame.goaway.error_code);
4269   assert_int(0, ==, nghttp2_session_send(session));
4270 
4271   nghttp2_session_del(session);
4272 
4273   nghttp2_session_client_new(&session, &callbacks, &user_data);
4274 
4275   stream = open_sent_stream(session, 1);
4276 
4277   /* Same ID twice */
4278   frame.hd.stream_id = 1;
4279   frame.push_promise.promised_stream_id = 2;
4280 
4281   user_data.begin_headers_cb_called = 0;
4282   user_data.invalid_frame_recv_cb_called = 0;
4283   assert_int(0, ==, nghttp2_session_on_push_promise_received(session, &frame));
4284 
4285   assert_int(1, ==, user_data.begin_headers_cb_called);
4286   assert_size(1, ==, session->num_incoming_reserved_streams);
4287   assert_not_null(nghttp2_session_get_stream(session, 2));
4288 
4289   user_data.begin_headers_cb_called = 0;
4290   user_data.invalid_frame_recv_cb_called = 0;
4291   assert_int(NGHTTP2_ERR_IGN_HEADER_BLOCK, ==,
4292              nghttp2_session_on_push_promise_received(session, &frame));
4293 
4294   assert_int(0, ==, user_data.begin_headers_cb_called);
4295   assert_size(1, ==, session->num_incoming_reserved_streams);
4296   assert_null(nghttp2_session_get_stream(session, 8));
4297   item = nghttp2_session_get_next_ob_item(session);
4298   assert_uint8(NGHTTP2_GOAWAY, ==, item->frame.hd.type);
4299   assert_uint32(NGHTTP2_PROTOCOL_ERROR, ==, item->frame.goaway.error_code);
4300   assert_int(0, ==, nghttp2_session_send(session));
4301 
4302   /* After GOAWAY, PUSH_PROMISE will be discarded */
4303   frame.push_promise.promised_stream_id = 10;
4304 
4305   user_data.begin_headers_cb_called = 0;
4306   user_data.invalid_frame_recv_cb_called = 0;
4307   assert_int(NGHTTP2_ERR_IGN_HEADER_BLOCK, ==,
4308              nghttp2_session_on_push_promise_received(session, &frame));
4309 
4310   assert_int(0, ==, user_data.begin_headers_cb_called);
4311   assert_size(1, ==, session->num_incoming_reserved_streams);
4312   assert_null(nghttp2_session_get_stream(session, 10));
4313   assert_null(nghttp2_session_get_next_ob_item(session));
4314 
4315   nghttp2_frame_push_promise_free(&frame.push_promise, mem);
4316   nghttp2_session_del(session);
4317 
4318   nghttp2_session_client_new(&session, &callbacks, &user_data);
4319 
4320   open_recv_stream2(session, 2, NGHTTP2_STREAM_RESERVED);
4321 
4322   /* Attempt to PUSH_PROMISE against reserved (remote) stream */
4323   nghttp2_frame_push_promise_init(&frame.push_promise, NGHTTP2_FLAG_END_HEADERS,
4324                                   2, 4, NULL, 0);
4325 
4326   user_data.begin_headers_cb_called = 0;
4327   user_data.invalid_frame_recv_cb_called = 0;
4328   assert_int(NGHTTP2_ERR_IGN_HEADER_BLOCK, ==,
4329              nghttp2_session_on_push_promise_received(session, &frame));
4330 
4331   assert_int(0, ==, user_data.begin_headers_cb_called);
4332   assert_int(1, ==, user_data.invalid_frame_recv_cb_called);
4333   assert_size(1, ==, session->num_incoming_reserved_streams);
4334 
4335   nghttp2_frame_push_promise_free(&frame.push_promise, mem);
4336   nghttp2_session_del(session);
4337 
4338   /* Disable PUSH */
4339   nghttp2_session_client_new(&session, &callbacks, &user_data);
4340 
4341   open_sent_stream(session, 1);
4342 
4343   session->local_settings.enable_push = 0;
4344 
4345   nghttp2_frame_push_promise_init(&frame.push_promise, NGHTTP2_FLAG_END_HEADERS,
4346                                   1, 2, NULL, 0);
4347 
4348   user_data.begin_headers_cb_called = 0;
4349   user_data.invalid_frame_recv_cb_called = 0;
4350   assert_int(NGHTTP2_ERR_IGN_HEADER_BLOCK, ==,
4351              nghttp2_session_on_push_promise_received(session, &frame));
4352 
4353   assert_int(0, ==, user_data.begin_headers_cb_called);
4354   assert_int(1, ==, user_data.invalid_frame_recv_cb_called);
4355   assert_size(0, ==, session->num_incoming_reserved_streams);
4356 
4357   nghttp2_frame_push_promise_free(&frame.push_promise, mem);
4358   nghttp2_session_del(session);
4359 
4360   /* Check malformed headers. We accept malformed headers */
4361   nghttp2_session_client_new(&session, &callbacks, &user_data);
4362 
4363   open_sent_stream(session, 1);
4364 
4365   nvlen = ARRLEN(malformed_nva);
4366   nghttp2_nv_array_copy(&nva, malformed_nva, nvlen, mem);
4367   nghttp2_frame_push_promise_init(&frame.push_promise, NGHTTP2_FLAG_END_HEADERS,
4368                                   1, 2, nva, nvlen);
4369   user_data.begin_headers_cb_called = 0;
4370   user_data.invalid_frame_recv_cb_called = 0;
4371   assert_int(0, ==, nghttp2_session_on_push_promise_received(session, &frame));
4372 
4373   assert_int(1, ==, user_data.begin_headers_cb_called);
4374   assert_int(0, ==, user_data.invalid_frame_recv_cb_called);
4375 
4376   nghttp2_frame_push_promise_free(&frame.push_promise, mem);
4377   nghttp2_session_del(session);
4378 
4379   /* If local_settings.enable_push = 0 is pending, but not acked from
4380      peer, incoming PUSH_PROMISE is rejected */
4381   nghttp2_session_client_new(&session, &callbacks, &user_data);
4382 
4383   open_sent_stream(session, 1);
4384 
4385   /* Submit settings with ENABLE_PUSH = 0 (thus disabling push) */
4386   nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, &iv, 1);
4387 
4388   nghttp2_frame_push_promise_init(&frame.push_promise, NGHTTP2_FLAG_END_HEADERS,
4389                                   1, 2, NULL, 0);
4390 
4391   assert_int(NGHTTP2_ERR_IGN_HEADER_BLOCK, ==,
4392              nghttp2_session_on_push_promise_received(session, &frame));
4393 
4394   assert_size(0, ==, session->num_incoming_reserved_streams);
4395 
4396   nghttp2_frame_push_promise_free(&frame.push_promise, mem);
4397   nghttp2_session_del(session);
4398 
4399   /* Check max_incoming_reserved_streams */
4400   nghttp2_session_client_new(&session, &callbacks, &user_data);
4401   session->max_incoming_reserved_streams = 1;
4402 
4403   open_sent_stream(session, 1);
4404   open_recv_stream2(session, 2, NGHTTP2_STREAM_RESERVED);
4405 
4406   assert_size(1, ==, session->num_incoming_reserved_streams);
4407 
4408   nghttp2_frame_push_promise_init(&frame.push_promise, NGHTTP2_FLAG_END_HEADERS,
4409                                   1, 4, NULL, 0);
4410 
4411   assert_int(NGHTTP2_ERR_IGN_HEADER_BLOCK, ==,
4412              nghttp2_session_on_push_promise_received(session, &frame));
4413 
4414   assert_size(1, ==, session->num_incoming_reserved_streams);
4415 
4416   item = nghttp2_session_get_next_ob_item(session);
4417 
4418   assert_uint8(NGHTTP2_RST_STREAM, ==, item->frame.hd.type);
4419   assert_uint32(NGHTTP2_CANCEL, ==, item->frame.rst_stream.error_code);
4420 
4421   nghttp2_frame_push_promise_free(&frame.push_promise, mem);
4422   nghttp2_session_del(session);
4423 }
4424 
test_nghttp2_session_on_ping_received(void)4425 void test_nghttp2_session_on_ping_received(void) {
4426   nghttp2_session *session;
4427   nghttp2_session_callbacks callbacks;
4428   my_user_data user_data;
4429   nghttp2_frame frame;
4430   nghttp2_outbound_item *top;
4431   const uint8_t opaque_data[] = "01234567";
4432   nghttp2_option *option;
4433 
4434   user_data.frame_recv_cb_called = 0;
4435   user_data.invalid_frame_recv_cb_called = 0;
4436 
4437   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4438   callbacks.on_frame_recv_callback = on_frame_recv_callback;
4439   callbacks.on_invalid_frame_recv_callback = on_invalid_frame_recv_callback;
4440 
4441   nghttp2_session_client_new(&session, &callbacks, &user_data);
4442   nghttp2_frame_ping_init(&frame.ping, NGHTTP2_FLAG_ACK, opaque_data);
4443 
4444   assert_int(0, ==, nghttp2_session_on_ping_received(session, &frame));
4445   assert_int(1, ==, user_data.frame_recv_cb_called);
4446 
4447   /* Since this ping frame has ACK flag set, no further action is
4448      performed. */
4449   assert_null(nghttp2_outbound_queue_top(&session->ob_urgent));
4450 
4451   /* Clear the flag, and receive it again */
4452   frame.hd.flags = NGHTTP2_FLAG_NONE;
4453 
4454   assert_int(0, ==, nghttp2_session_on_ping_received(session, &frame));
4455   assert_int(2, ==, user_data.frame_recv_cb_called);
4456   top = nghttp2_outbound_queue_top(&session->ob_urgent);
4457   assert_uint8(NGHTTP2_PING, ==, top->frame.hd.type);
4458   assert_uint8(NGHTTP2_FLAG_ACK, ==, top->frame.hd.flags);
4459   assert_memory_equal(8, opaque_data, top->frame.ping.opaque_data);
4460 
4461   nghttp2_frame_ping_free(&frame.ping);
4462   nghttp2_session_del(session);
4463 
4464   /* Use nghttp2_option_set_no_auto_ping_ack() */
4465   nghttp2_option_new(&option);
4466   nghttp2_option_set_no_auto_ping_ack(option, 1);
4467 
4468   nghttp2_session_server_new2(&session, &callbacks, &user_data, option);
4469   nghttp2_frame_ping_init(&frame.ping, NGHTTP2_FLAG_NONE, NULL);
4470 
4471   user_data.frame_recv_cb_called = 0;
4472 
4473   assert_int(0, ==, nghttp2_session_on_ping_received(session, &frame));
4474   assert_int(1, ==, user_data.frame_recv_cb_called);
4475   assert_null(nghttp2_outbound_queue_top(&session->ob_urgent));
4476 
4477   nghttp2_frame_ping_free(&frame.ping);
4478   nghttp2_session_del(session);
4479   nghttp2_option_del(option);
4480 }
4481 
test_nghttp2_session_on_goaway_received(void)4482 void test_nghttp2_session_on_goaway_received(void) {
4483   nghttp2_session *session;
4484   nghttp2_session_callbacks callbacks;
4485   my_user_data user_data;
4486   nghttp2_frame frame;
4487   int i;
4488   nghttp2_mem *mem;
4489   const uint8_t *data;
4490   nghttp2_ssize datalen;
4491 
4492   mem = nghttp2_mem_default();
4493   user_data.frame_recv_cb_called = 0;
4494   user_data.invalid_frame_recv_cb_called = 0;
4495 
4496   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4497   callbacks.on_frame_recv_callback = on_frame_recv_callback;
4498   callbacks.on_invalid_frame_recv_callback = on_invalid_frame_recv_callback;
4499   callbacks.on_stream_close_callback = on_stream_close_callback;
4500 
4501   nghttp2_session_client_new(&session, &callbacks, &user_data);
4502 
4503   for (i = 1; i <= 7; ++i) {
4504     if (nghttp2_session_is_my_stream_id(session, i)) {
4505       open_sent_stream(session, i);
4506     } else {
4507       open_recv_stream(session, i);
4508     }
4509   }
4510 
4511   nghttp2_frame_goaway_init(&frame.goaway, 3, NGHTTP2_PROTOCOL_ERROR, NULL, 0);
4512 
4513   user_data.stream_close_cb_called = 0;
4514 
4515   assert_int(0, ==, nghttp2_session_on_goaway_received(session, &frame));
4516 
4517   assert_int(1, ==, user_data.frame_recv_cb_called);
4518   assert_int32(3, ==, session->remote_last_stream_id);
4519   /* on_stream_close should be callsed for 2 times (stream 5 and 7) */
4520   assert_int(2, ==, user_data.stream_close_cb_called);
4521 
4522   assert_not_null(nghttp2_session_get_stream(session, 1));
4523   assert_not_null(nghttp2_session_get_stream(session, 2));
4524   assert_not_null(nghttp2_session_get_stream(session, 3));
4525   assert_not_null(nghttp2_session_get_stream(session, 4));
4526   assert_null(nghttp2_session_get_stream(session, 5));
4527   assert_not_null(nghttp2_session_get_stream(session, 6));
4528   assert_null(nghttp2_session_get_stream(session, 7));
4529 
4530   nghttp2_frame_goaway_free(&frame.goaway, mem);
4531   nghttp2_session_del(session);
4532 
4533   /* Make sure that no memory leak when stream_close callback fails
4534      with a fatal error */
4535   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4536   callbacks.on_stream_close_callback = fatal_error_on_stream_close_callback;
4537 
4538   memset(&user_data, 0, sizeof(user_data));
4539 
4540   nghttp2_session_client_new(&session, &callbacks, &user_data);
4541 
4542   nghttp2_frame_goaway_init(&frame.goaway, 0, NGHTTP2_NO_ERROR, NULL, 0);
4543 
4544   assert_int(0, ==, nghttp2_session_on_goaway_received(session, &frame));
4545 
4546   nghttp2_submit_request2(session, NULL, reqnv, ARRLEN(reqnv), NULL, NULL);
4547 
4548   datalen = nghttp2_session_mem_send2(session, &data);
4549 
4550   assert_ptrdiff(NGHTTP2_ERR_CALLBACK_FAILURE, ==, datalen);
4551   assert_int(1, ==, user_data.stream_close_cb_called);
4552 
4553   nghttp2_frame_goaway_free(&frame.goaway, mem);
4554   nghttp2_session_del(session);
4555 }
4556 
test_nghttp2_session_on_window_update_received(void)4557 void test_nghttp2_session_on_window_update_received(void) {
4558   nghttp2_session *session;
4559   nghttp2_session_callbacks callbacks;
4560   my_user_data user_data;
4561   nghttp2_frame frame;
4562   nghttp2_stream *stream;
4563   nghttp2_outbound_item *data_item;
4564   nghttp2_mem *mem;
4565 
4566   mem = nghttp2_mem_default();
4567 
4568   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4569   callbacks.on_frame_recv_callback = on_frame_recv_callback;
4570   callbacks.on_invalid_frame_recv_callback = on_invalid_frame_recv_callback;
4571   user_data.frame_recv_cb_called = 0;
4572   user_data.invalid_frame_recv_cb_called = 0;
4573 
4574   nghttp2_session_client_new(&session, &callbacks, &user_data);
4575 
4576   stream = open_sent_stream(session, 1);
4577 
4578   data_item = create_data_ob_item(mem);
4579 
4580   assert_int(0, ==, nghttp2_stream_attach_item(stream, data_item));
4581 
4582   nghttp2_frame_window_update_init(&frame.window_update, NGHTTP2_FLAG_NONE, 1,
4583                                    16 * 1024);
4584 
4585   assert_int(0, ==, nghttp2_session_on_window_update_received(session, &frame));
4586   assert_int(1, ==, user_data.frame_recv_cb_called);
4587   assert_int32(NGHTTP2_INITIAL_WINDOW_SIZE + 16 * 1024, ==,
4588                stream->remote_window_size);
4589 
4590   nghttp2_stream_defer_item(stream, NGHTTP2_STREAM_FLAG_DEFERRED_FLOW_CONTROL);
4591 
4592   assert_int(0, ==, nghttp2_session_on_window_update_received(session, &frame));
4593   assert_int(2, ==, user_data.frame_recv_cb_called);
4594   assert_int32(NGHTTP2_INITIAL_WINDOW_SIZE + 16 * 1024 * 2, ==,
4595                stream->remote_window_size);
4596   assert_false(stream->flags & NGHTTP2_STREAM_FLAG_DEFERRED_ALL);
4597 
4598   nghttp2_frame_window_update_free(&frame.window_update);
4599 
4600   /* Receiving WINDOW_UPDATE on reserved (remote) stream is a
4601      connection error */
4602   open_recv_stream2(session, 2, NGHTTP2_STREAM_RESERVED);
4603 
4604   nghttp2_frame_window_update_init(&frame.window_update, NGHTTP2_FLAG_NONE, 2,
4605                                    4096);
4606 
4607   assert_false(session->goaway_flags & NGHTTP2_GOAWAY_TERM_ON_SEND);
4608   assert_int(0, ==, nghttp2_session_on_window_update_received(session, &frame));
4609   assert_true(session->goaway_flags & NGHTTP2_GOAWAY_TERM_ON_SEND);
4610 
4611   nghttp2_frame_window_update_free(&frame.window_update);
4612 
4613   nghttp2_session_del(session);
4614 
4615   /* Receiving WINDOW_UPDATE on reserved (local) stream is allowed */
4616   nghttp2_session_server_new(&session, &callbacks, &user_data);
4617 
4618   stream = open_sent_stream2(session, 2, NGHTTP2_STREAM_RESERVED);
4619 
4620   nghttp2_frame_window_update_init(&frame.window_update, NGHTTP2_FLAG_NONE, 2,
4621                                    4096);
4622 
4623   assert_int(0, ==, nghttp2_session_on_window_update_received(session, &frame));
4624   assert_false(session->goaway_flags & NGHTTP2_GOAWAY_TERM_ON_SEND);
4625 
4626   assert_int32(NGHTTP2_INITIAL_WINDOW_SIZE + 4096, ==,
4627                stream->remote_window_size);
4628 
4629   nghttp2_frame_window_update_free(&frame.window_update);
4630 
4631   nghttp2_session_del(session);
4632 }
4633 
test_nghttp2_session_on_data_received(void)4634 void test_nghttp2_session_on_data_received(void) {
4635   nghttp2_session *session;
4636   nghttp2_session_callbacks callbacks;
4637   my_user_data user_data;
4638   nghttp2_outbound_item *top;
4639   nghttp2_stream *stream;
4640   nghttp2_frame frame;
4641 
4642   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4643 
4644   nghttp2_session_client_new(&session, &callbacks, &user_data);
4645   stream = open_recv_stream(session, 2);
4646 
4647   nghttp2_frame_hd_init(&frame.hd, 4096, NGHTTP2_DATA, NGHTTP2_FLAG_NONE, 2);
4648 
4649   assert_int(0, ==, nghttp2_session_on_data_received(session, &frame));
4650   assert_uint8(0, ==, stream->shut_flags);
4651 
4652   frame.hd.flags = NGHTTP2_FLAG_END_STREAM;
4653 
4654   assert_int(0, ==, nghttp2_session_on_data_received(session, &frame));
4655   assert_uint8(NGHTTP2_SHUT_RD, ==, stream->shut_flags);
4656 
4657   /* If NGHTTP2_STREAM_CLOSING state, DATA frame is discarded. */
4658   open_sent_stream2(session, 1, NGHTTP2_STREAM_CLOSING);
4659 
4660   frame.hd.flags = NGHTTP2_FLAG_NONE;
4661   frame.hd.stream_id = 1;
4662 
4663   assert_int(0, ==, nghttp2_session_on_data_received(session, &frame));
4664   assert_null(nghttp2_outbound_queue_top(&session->ob_reg));
4665 
4666   /* Check INVALID_STREAM case: DATA frame with stream ID which does
4667      not exist. */
4668 
4669   frame.hd.stream_id = 3;
4670 
4671   assert_int(0, ==, nghttp2_session_on_data_received(session, &frame));
4672   top = nghttp2_outbound_queue_top(&session->ob_reg);
4673   /* DATA against nonexistent stream is just ignored for now. */
4674   assert_null(top);
4675 
4676   nghttp2_session_del(session);
4677 }
4678 
test_nghttp2_session_on_data_received_fail_fast(void)4679 void test_nghttp2_session_on_data_received_fail_fast(void) {
4680   nghttp2_session *session;
4681   nghttp2_session_callbacks callbacks;
4682   uint8_t buf[9];
4683   nghttp2_stream *stream;
4684   nghttp2_frame_hd hd;
4685   nghttp2_outbound_item *item;
4686 
4687   memset(&callbacks, 0, sizeof(callbacks));
4688 
4689   nghttp2_frame_hd_init(&hd, 0, NGHTTP2_DATA, NGHTTP2_FLAG_NONE, 1);
4690   nghttp2_frame_pack_frame_hd(buf, &hd);
4691 
4692   nghttp2_session_server_new(&session, &callbacks, NULL);
4693 
4694   /* DATA to closed (remote) */
4695   stream = open_recv_stream(session, 1);
4696   nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_RD);
4697 
4698   assert_ptrdiff((nghttp2_ssize)sizeof(buf), ==,
4699                  nghttp2_session_mem_recv2(session, buf, sizeof(buf)));
4700 
4701   item = nghttp2_session_get_next_ob_item(session);
4702 
4703   assert_not_null(item);
4704   assert_uint8(NGHTTP2_GOAWAY, ==, item->frame.hd.type);
4705 
4706   nghttp2_session_del(session);
4707 
4708   nghttp2_session_server_new(&session, &callbacks, NULL);
4709 
4710   /* DATA to closed stream with explicit closed (remote) */
4711   stream = open_recv_stream(session, 1);
4712   nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_RD);
4713   nghttp2_session_close_stream(session, 1, NGHTTP2_NO_ERROR);
4714 
4715   assert_ptrdiff((nghttp2_ssize)sizeof(buf), ==,
4716                  nghttp2_session_mem_recv2(session, buf, sizeof(buf)));
4717 
4718   item = nghttp2_session_get_next_ob_item(session);
4719 
4720   assert_not_null(item);
4721   assert_uint8(NGHTTP2_GOAWAY, ==, item->frame.hd.type);
4722 
4723   nghttp2_session_del(session);
4724 }
4725 
test_nghttp2_session_on_altsvc_received(void)4726 void test_nghttp2_session_on_altsvc_received(void) {
4727   nghttp2_session *session;
4728   nghttp2_session_callbacks callbacks;
4729   my_user_data ud;
4730   nghttp2_frame frame;
4731   nghttp2_option *option;
4732   uint8_t origin[] = "nghttp2.org";
4733   uint8_t field_value[] = "h2=\":443\"";
4734   int rv;
4735 
4736   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4737   callbacks.on_frame_recv_callback = on_frame_recv_callback;
4738 
4739   nghttp2_option_new(&option);
4740   nghttp2_option_set_builtin_recv_extension_type(option, NGHTTP2_ALTSVC);
4741 
4742   nghttp2_session_client_new2(&session, &callbacks, &ud, option);
4743 
4744   frame.ext.payload = &session->iframe.ext_frame_payload;
4745 
4746   /* We just pass the strings without making a copy.  This is OK,
4747      since we never call nghttp2_frame_altsvc_free(). */
4748   nghttp2_frame_altsvc_init(&frame.ext, 0, origin, sizeof(origin) - 1,
4749                             field_value, sizeof(field_value) - 1);
4750 
4751   ud.frame_recv_cb_called = 0;
4752   rv = nghttp2_session_on_altsvc_received(session, &frame);
4753 
4754   assert_int(0, ==, rv);
4755   assert_int(1, ==, ud.frame_recv_cb_called);
4756 
4757   nghttp2_session_del(session);
4758 
4759   /* Receiving empty origin with stream ID == 0 */
4760   nghttp2_session_client_new2(&session, &callbacks, &ud, option);
4761 
4762   frame.ext.payload = &session->iframe.ext_frame_payload;
4763 
4764   nghttp2_frame_altsvc_init(&frame.ext, 0, origin, 0, field_value,
4765                             sizeof(field_value) - 1);
4766 
4767   ud.frame_recv_cb_called = 0;
4768   rv = nghttp2_session_on_altsvc_received(session, &frame);
4769 
4770   assert_int(0, ==, rv);
4771   assert_int(0, ==, ud.frame_recv_cb_called);
4772 
4773   nghttp2_session_del(session);
4774 
4775   /* Receiving non-empty origin with stream ID != 0 */
4776   nghttp2_session_client_new2(&session, &callbacks, &ud, option);
4777 
4778   frame.ext.payload = &session->iframe.ext_frame_payload;
4779 
4780   open_sent_stream(session, 1);
4781 
4782   nghttp2_frame_altsvc_init(&frame.ext, 1, origin, sizeof(origin) - 1,
4783                             field_value, sizeof(field_value) - 1);
4784 
4785   ud.frame_recv_cb_called = 0;
4786   rv = nghttp2_session_on_altsvc_received(session, &frame);
4787 
4788   assert_int(0, ==, rv);
4789   assert_int(0, ==, ud.frame_recv_cb_called);
4790 
4791   nghttp2_session_del(session);
4792 
4793   /* Receiving empty origin with stream ID != 0; this is OK */
4794   nghttp2_session_client_new2(&session, &callbacks, &ud, option);
4795 
4796   frame.ext.payload = &session->iframe.ext_frame_payload;
4797 
4798   open_sent_stream(session, 1);
4799 
4800   nghttp2_frame_altsvc_init(&frame.ext, 1, origin, 0, field_value,
4801                             sizeof(field_value) - 1);
4802 
4803   ud.frame_recv_cb_called = 0;
4804   rv = nghttp2_session_on_altsvc_received(session, &frame);
4805 
4806   assert_int(0, ==, rv);
4807   assert_int(1, ==, ud.frame_recv_cb_called);
4808 
4809   nghttp2_session_del(session);
4810 
4811   /* Stream does not exist; ALTSVC will be ignored. */
4812   nghttp2_session_client_new2(&session, &callbacks, &ud, option);
4813 
4814   frame.ext.payload = &session->iframe.ext_frame_payload;
4815 
4816   nghttp2_frame_altsvc_init(&frame.ext, 1, origin, 0, field_value,
4817                             sizeof(field_value) - 1);
4818 
4819   ud.frame_recv_cb_called = 0;
4820   rv = nghttp2_session_on_altsvc_received(session, &frame);
4821 
4822   assert_int(0, ==, rv);
4823   assert_int(0, ==, ud.frame_recv_cb_called);
4824 
4825   nghttp2_session_del(session);
4826 
4827   nghttp2_option_del(option);
4828 }
4829 
test_nghttp2_session_send_headers_start_stream(void)4830 void test_nghttp2_session_send_headers_start_stream(void) {
4831   nghttp2_session *session;
4832   nghttp2_session_callbacks callbacks;
4833   nghttp2_outbound_item *item;
4834   nghttp2_frame *frame;
4835   nghttp2_stream *stream;
4836   nghttp2_mem *mem;
4837 
4838   mem = nghttp2_mem_default();
4839 
4840   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4841   callbacks.send_callback2 = null_send_callback;
4842 
4843   nghttp2_session_client_new(&session, &callbacks, NULL);
4844 
4845   item = mem->malloc(sizeof(nghttp2_outbound_item), NULL);
4846 
4847   nghttp2_outbound_item_init(item);
4848 
4849   frame = &item->frame;
4850 
4851   nghttp2_frame_headers_init(&frame->headers, NGHTTP2_FLAG_END_HEADERS,
4852                              (int32_t)session->next_stream_id,
4853                              NGHTTP2_HCAT_REQUEST, NULL, NULL, 0);
4854   session->next_stream_id += 2;
4855 
4856   nghttp2_session_add_item(session, item);
4857   assert_int(0, ==, nghttp2_session_send(session));
4858   stream = nghttp2_session_get_stream(session, 1);
4859   assert_enum(nghttp2_stream_state, NGHTTP2_STREAM_OPENING, ==, stream->state);
4860 
4861   nghttp2_session_del(session);
4862 }
4863 
test_nghttp2_session_send_headers_reply(void)4864 void test_nghttp2_session_send_headers_reply(void) {
4865   nghttp2_session *session;
4866   nghttp2_session_callbacks callbacks;
4867   nghttp2_outbound_item *item;
4868   nghttp2_frame *frame;
4869   nghttp2_stream *stream;
4870   nghttp2_mem *mem;
4871 
4872   mem = nghttp2_mem_default();
4873 
4874   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4875   callbacks.send_callback2 = null_send_callback;
4876 
4877   assert_int(0, ==, nghttp2_session_server_new(&session, &callbacks, NULL));
4878   open_recv_stream2(session, 1, NGHTTP2_STREAM_OPENING);
4879 
4880   item = mem->malloc(sizeof(nghttp2_outbound_item), NULL);
4881 
4882   nghttp2_outbound_item_init(item);
4883 
4884   frame = &item->frame;
4885 
4886   nghttp2_frame_headers_init(&frame->headers, NGHTTP2_FLAG_END_HEADERS, 1,
4887                              NGHTTP2_HCAT_HEADERS, NULL, NULL, 0);
4888   nghttp2_session_add_item(session, item);
4889   assert_int(0, ==, nghttp2_session_send(session));
4890   stream = nghttp2_session_get_stream(session, 1);
4891   assert_enum(nghttp2_stream_state, NGHTTP2_STREAM_OPENED, ==, stream->state);
4892 
4893   nghttp2_session_del(session);
4894 }
4895 
test_nghttp2_session_send_headers_frame_size_error(void)4896 void test_nghttp2_session_send_headers_frame_size_error(void) {
4897   nghttp2_session *session;
4898   nghttp2_session_callbacks callbacks;
4899   nghttp2_outbound_item *item;
4900   nghttp2_frame *frame;
4901   nghttp2_nv *nva;
4902   size_t nvlen;
4903   size_t vallen = NGHTTP2_HD_MAX_NV;
4904   nghttp2_nv nv[28];
4905   size_t nnv = ARRLEN(nv);
4906   size_t i;
4907   my_user_data ud;
4908   nghttp2_mem *mem;
4909 
4910   mem = nghttp2_mem_default();
4911 
4912   for (i = 0; i < nnv; ++i) {
4913     nv[i].name = (uint8_t *)"header";
4914     nv[i].namelen = strlen((const char *)nv[i].name);
4915     nv[i].value = mem->malloc(vallen + 1, NULL);
4916     memset(nv[i].value, '0' + (int)i, vallen);
4917     nv[i].value[vallen] = '\0';
4918     nv[i].valuelen = vallen;
4919     nv[i].flags = NGHTTP2_NV_FLAG_NONE;
4920   }
4921 
4922   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4923   callbacks.send_callback2 = null_send_callback;
4924   callbacks.on_frame_not_send_callback = on_frame_not_send_callback;
4925 
4926   nghttp2_session_client_new(&session, &callbacks, &ud);
4927   nvlen = nnv;
4928   nghttp2_nv_array_copy(&nva, nv, nvlen, mem);
4929 
4930   item = mem->malloc(sizeof(nghttp2_outbound_item), NULL);
4931 
4932   nghttp2_outbound_item_init(item);
4933 
4934   frame = &item->frame;
4935 
4936   nghttp2_frame_headers_init(&frame->headers, NGHTTP2_FLAG_END_HEADERS,
4937                              (int32_t)session->next_stream_id,
4938                              NGHTTP2_HCAT_REQUEST, NULL, nva, nvlen);
4939 
4940   session->next_stream_id += 2;
4941 
4942   nghttp2_session_add_item(session, item);
4943 
4944   ud.frame_not_send_cb_called = 0;
4945 
4946   assert_int(0, ==, nghttp2_session_send(session));
4947 
4948   assert_int(1, ==, ud.frame_not_send_cb_called);
4949   assert_uint8(NGHTTP2_HEADERS, ==, ud.not_sent_frame_type);
4950   assert_int(NGHTTP2_ERR_FRAME_SIZE_ERROR, ==, ud.not_sent_error);
4951 
4952   for (i = 0; i < nnv; ++i) {
4953     mem->free(nv[i].value, NULL);
4954   }
4955   nghttp2_session_del(session);
4956 }
4957 
test_nghttp2_session_send_headers_push_reply(void)4958 void test_nghttp2_session_send_headers_push_reply(void) {
4959   nghttp2_session *session;
4960   nghttp2_session_callbacks callbacks;
4961   nghttp2_outbound_item *item;
4962   nghttp2_frame *frame;
4963   nghttp2_stream *stream;
4964   nghttp2_mem *mem;
4965 
4966   mem = nghttp2_mem_default();
4967 
4968   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4969   callbacks.send_callback2 = null_send_callback;
4970 
4971   assert_int(0, ==, nghttp2_session_server_new(&session, &callbacks, NULL));
4972   open_sent_stream2(session, 2, NGHTTP2_STREAM_RESERVED);
4973 
4974   item = mem->malloc(sizeof(nghttp2_outbound_item), NULL);
4975 
4976   nghttp2_outbound_item_init(item);
4977 
4978   frame = &item->frame;
4979 
4980   nghttp2_frame_headers_init(&frame->headers, NGHTTP2_FLAG_END_HEADERS, 2,
4981                              NGHTTP2_HCAT_HEADERS, NULL, NULL, 0);
4982   nghttp2_session_add_item(session, item);
4983   assert_size(0, ==, session->num_outgoing_streams);
4984   assert_int(0, ==, nghttp2_session_send(session));
4985   assert_size(1, ==, session->num_outgoing_streams);
4986   stream = nghttp2_session_get_stream(session, 2);
4987   assert_enum(nghttp2_stream_state, NGHTTP2_STREAM_OPENED, ==, stream->state);
4988   assert_false(stream->flags & NGHTTP2_STREAM_FLAG_PUSH);
4989   nghttp2_session_del(session);
4990 }
4991 
test_nghttp2_session_send_rst_stream(void)4992 void test_nghttp2_session_send_rst_stream(void) {
4993   nghttp2_session *session;
4994   nghttp2_session_callbacks callbacks;
4995   my_user_data user_data;
4996   nghttp2_outbound_item *item;
4997   nghttp2_frame *frame;
4998   nghttp2_mem *mem;
4999 
5000   mem = nghttp2_mem_default();
5001 
5002   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
5003   callbacks.send_callback2 = null_send_callback;
5004   nghttp2_session_client_new(&session, &callbacks, &user_data);
5005   open_sent_stream(session, 1);
5006 
5007   item = mem->malloc(sizeof(nghttp2_outbound_item), NULL);
5008 
5009   nghttp2_outbound_item_init(item);
5010 
5011   frame = &item->frame;
5012 
5013   nghttp2_frame_rst_stream_init(&frame->rst_stream, 1, NGHTTP2_PROTOCOL_ERROR);
5014   nghttp2_session_add_item(session, item);
5015   assert_int(0, ==, nghttp2_session_send(session));
5016 
5017   assert_null(nghttp2_session_get_stream(session, 1));
5018 
5019   nghttp2_session_del(session);
5020 }
5021 
test_nghttp2_session_send_push_promise(void)5022 void test_nghttp2_session_send_push_promise(void) {
5023   nghttp2_session *session;
5024   nghttp2_session_callbacks callbacks;
5025   nghttp2_outbound_item *item;
5026   nghttp2_frame *frame;
5027   nghttp2_stream *stream;
5028   nghttp2_settings_entry iv;
5029   my_user_data ud;
5030   nghttp2_mem *mem;
5031 
5032   mem = nghttp2_mem_default();
5033   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
5034   callbacks.send_callback2 = null_send_callback;
5035   callbacks.on_frame_not_send_callback = on_frame_not_send_callback;
5036 
5037   nghttp2_session_server_new(&session, &callbacks, &ud);
5038   open_recv_stream(session, 1);
5039 
5040   item = mem->malloc(sizeof(nghttp2_outbound_item), NULL);
5041 
5042   nghttp2_outbound_item_init(item);
5043 
5044   frame = &item->frame;
5045 
5046   nghttp2_frame_push_promise_init(&frame->push_promise,
5047                                   NGHTTP2_FLAG_END_HEADERS, 1,
5048                                   (int32_t)session->next_stream_id, NULL, 0);
5049 
5050   session->next_stream_id += 2;
5051 
5052   nghttp2_session_add_item(session, item);
5053 
5054   assert_int(0, ==, nghttp2_session_send(session));
5055   stream = nghttp2_session_get_stream(session, 2);
5056   assert_enum(nghttp2_stream_state, NGHTTP2_STREAM_RESERVED, ==, stream->state);
5057 
5058   /* Received ENABLE_PUSH = 0 */
5059   iv.settings_id = NGHTTP2_SETTINGS_ENABLE_PUSH;
5060   iv.value = 0;
5061   frame = mem->malloc(sizeof(nghttp2_frame), NULL);
5062   nghttp2_frame_settings_init(&frame->settings, NGHTTP2_FLAG_NONE,
5063                               dup_iv(&iv, 1), 1);
5064   nghttp2_session_on_settings_received(session, frame, 1);
5065   nghttp2_frame_settings_free(&frame->settings, mem);
5066   mem->free(frame, NULL);
5067 
5068   item = mem->malloc(sizeof(nghttp2_outbound_item), NULL);
5069 
5070   nghttp2_outbound_item_init(item);
5071 
5072   frame = &item->frame;
5073 
5074   nghttp2_frame_push_promise_init(&frame->push_promise,
5075                                   NGHTTP2_FLAG_END_HEADERS, 1, -1, NULL, 0);
5076   nghttp2_session_add_item(session, item);
5077 
5078   ud.frame_not_send_cb_called = 0;
5079   assert_int(0, ==, nghttp2_session_send(session));
5080 
5081   assert_int(1, ==, ud.frame_not_send_cb_called);
5082   assert_uint8(NGHTTP2_PUSH_PROMISE, ==, ud.not_sent_frame_type);
5083   assert_int(NGHTTP2_ERR_PUSH_DISABLED, ==, ud.not_sent_error);
5084 
5085   nghttp2_session_del(session);
5086 
5087   /* PUSH_PROMISE from client is error */
5088   nghttp2_session_client_new(&session, &callbacks, &ud);
5089   open_sent_stream(session, 1);
5090   item = mem->malloc(sizeof(nghttp2_outbound_item), NULL);
5091 
5092   nghttp2_outbound_item_init(item);
5093 
5094   frame = &item->frame;
5095 
5096   nghttp2_frame_push_promise_init(&frame->push_promise,
5097                                   NGHTTP2_FLAG_END_HEADERS, 1, -1, NULL, 0);
5098   nghttp2_session_add_item(session, item);
5099 
5100   assert_int(0, ==, nghttp2_session_send(session));
5101   assert_null(nghttp2_session_get_stream(session, 3));
5102 
5103   nghttp2_session_del(session);
5104 }
5105 
test_nghttp2_session_is_my_stream_id(void)5106 void test_nghttp2_session_is_my_stream_id(void) {
5107   nghttp2_session *session;
5108   nghttp2_session_callbacks callbacks;
5109   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
5110   nghttp2_session_server_new(&session, &callbacks, NULL);
5111 
5112   assert_false(nghttp2_session_is_my_stream_id(session, 0));
5113   assert_false(nghttp2_session_is_my_stream_id(session, 1));
5114   assert_true(nghttp2_session_is_my_stream_id(session, 2));
5115 
5116   nghttp2_session_del(session);
5117 
5118   nghttp2_session_client_new(&session, &callbacks, NULL);
5119 
5120   assert_false(nghttp2_session_is_my_stream_id(session, 0));
5121   assert_true(nghttp2_session_is_my_stream_id(session, 1));
5122   assert_false(nghttp2_session_is_my_stream_id(session, 2));
5123 
5124   nghttp2_session_del(session);
5125 }
5126 
test_nghttp2_session_upgrade2(void)5127 void test_nghttp2_session_upgrade2(void) {
5128   nghttp2_session *session;
5129   nghttp2_session_callbacks callbacks;
5130   uint8_t settings_payload[128];
5131   size_t settings_payloadlen;
5132   nghttp2_settings_entry iv[16];
5133   nghttp2_stream *stream;
5134   nghttp2_outbound_item *item;
5135   nghttp2_ssize rv;
5136   nghttp2_bufs bufs;
5137   nghttp2_buf *buf;
5138   nghttp2_hd_deflater deflater;
5139   nghttp2_mem *mem;
5140 
5141   mem = nghttp2_mem_default();
5142   frame_pack_bufs_init(&bufs);
5143 
5144   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
5145   callbacks.send_callback2 = null_send_callback;
5146   iv[0].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS;
5147   iv[0].value = 1;
5148   iv[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
5149   iv[1].value = 4095;
5150   settings_payloadlen = (size_t)nghttp2_pack_settings_payload2(
5151     settings_payload, sizeof(settings_payload), iv, 2);
5152 
5153   /* Check client side */
5154   nghttp2_session_client_new(&session, &callbacks, NULL);
5155   assert_int(0, ==,
5156              nghttp2_session_upgrade2(session, settings_payload,
5157                                       settings_payloadlen, 0, &callbacks));
5158   assert_int32(1, ==, session->last_sent_stream_id);
5159   stream = nghttp2_session_get_stream(session, 1);
5160   assert_not_null(stream);
5161   assert_ptr_equal(&callbacks, stream->stream_user_data);
5162   assert_uint8(NGHTTP2_SHUT_WR, ==, stream->shut_flags);
5163   item = nghttp2_session_get_next_ob_item(session);
5164   assert_uint8(NGHTTP2_SETTINGS, ==, item->frame.hd.type);
5165   assert_size(2, ==, item->frame.settings.niv);
5166   assert_int32(NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, ==,
5167                item->frame.settings.iv[0].settings_id);
5168   assert_uint32(1, ==, item->frame.settings.iv[0].value);
5169   assert_int32(NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE, ==,
5170                item->frame.settings.iv[1].settings_id);
5171   assert_uint32(4095, ==, item->frame.settings.iv[1].value);
5172 
5173   /* Call nghttp2_session_upgrade2() again is error */
5174   assert_int(NGHTTP2_ERR_PROTO, ==,
5175              nghttp2_session_upgrade2(session, settings_payload,
5176                                       settings_payloadlen, 0, &callbacks));
5177   nghttp2_session_del(session);
5178 
5179   /* Make sure that response from server can be received */
5180   nghttp2_session_client_new(&session, &callbacks, NULL);
5181 
5182   assert_int(0, ==,
5183              nghttp2_session_upgrade2(session, settings_payload,
5184                                       settings_payloadlen, 0, &callbacks));
5185 
5186   stream = nghttp2_session_get_stream(session, 1);
5187 
5188   assert_enum(nghttp2_stream_state, NGHTTP2_STREAM_OPENING, ==, stream->state);
5189 
5190   nghttp2_hd_deflate_init(&deflater, mem);
5191   rv = pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, resnv,
5192                     ARRLEN(resnv), mem);
5193 
5194   assert_ptrdiff(0, ==, rv);
5195 
5196   buf = &bufs.head->buf;
5197 
5198   rv = nghttp2_session_mem_recv2(session, buf->pos, nghttp2_buf_len(buf));
5199 
5200   assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(buf), ==, rv);
5201   assert_enum(nghttp2_stream_state, NGHTTP2_STREAM_OPENED, ==, stream->state);
5202 
5203   nghttp2_hd_deflate_free(&deflater);
5204   nghttp2_session_del(session);
5205 
5206   nghttp2_bufs_reset(&bufs);
5207 
5208   /* Check server side */
5209   nghttp2_session_server_new(&session, &callbacks, NULL);
5210   assert_int(0, ==,
5211              nghttp2_session_upgrade2(session, settings_payload,
5212                                       settings_payloadlen, 0, &callbacks));
5213   assert_int32(1, ==, session->last_recv_stream_id);
5214   stream = nghttp2_session_get_stream(session, 1);
5215   assert_not_null(stream);
5216   assert_null(stream->stream_user_data);
5217   assert_uint8(NGHTTP2_SHUT_RD, ==, stream->shut_flags);
5218   assert_null(nghttp2_session_get_next_ob_item(session));
5219   assert_uint32(1, ==, session->remote_settings.max_concurrent_streams);
5220   assert_uint32(4095, ==, session->remote_settings.initial_window_size);
5221   /* Call nghttp2_session_upgrade2() again is error */
5222   assert_int(NGHTTP2_ERR_PROTO, ==,
5223              nghttp2_session_upgrade2(session, settings_payload,
5224                                       settings_payloadlen, 0, &callbacks));
5225   nghttp2_session_del(session);
5226 
5227   /* Empty SETTINGS is OK */
5228   settings_payloadlen = (size_t)nghttp2_pack_settings_payload2(
5229     settings_payload, sizeof(settings_payload), NULL, 0);
5230 
5231   nghttp2_session_client_new(&session, &callbacks, NULL);
5232   assert_int(0, ==,
5233              nghttp2_session_upgrade2(session, settings_payload,
5234                                       settings_payloadlen, 0, NULL));
5235   nghttp2_session_del(session);
5236   nghttp2_bufs_free(&bufs);
5237 }
5238 
test_nghttp2_session_reprioritize_stream(void)5239 void test_nghttp2_session_reprioritize_stream(void) {
5240   nghttp2_session *session;
5241   nghttp2_session_callbacks callbacks;
5242   nghttp2_stream *stream;
5243   nghttp2_stream *dep_stream;
5244   nghttp2_priority_spec pri_spec;
5245   int rv;
5246 
5247   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
5248   callbacks.send_callback2 = block_count_send_callback;
5249 
5250   nghttp2_session_server_new(&session, &callbacks, NULL);
5251 
5252   stream = open_recv_stream(session, 1);
5253 
5254   nghttp2_priority_spec_init(&pri_spec, 0, 10, 0);
5255 
5256   rv = nghttp2_session_reprioritize_stream(session, stream, &pri_spec);
5257 
5258   assert_int(0, ==, rv);
5259   assert_int32(10, ==, stream->weight);
5260   assert_ptr_equal(&session->root, stream->dep_prev);
5261 
5262   /* If dependency to idle stream which is not in dependency tree yet */
5263 
5264   nghttp2_priority_spec_init(&pri_spec, 3, 99, 0);
5265 
5266   rv = nghttp2_session_reprioritize_stream(session, stream, &pri_spec);
5267 
5268   assert_int(0, ==, rv);
5269   assert_int32(99, ==, stream->weight);
5270   assert_int32(3, ==, stream->dep_prev->stream_id);
5271 
5272   dep_stream = nghttp2_session_get_stream_raw(session, 3);
5273 
5274   assert_int32(NGHTTP2_DEFAULT_WEIGHT, ==, dep_stream->weight);
5275 
5276   dep_stream = open_recv_stream(session, 3);
5277 
5278   /* Change weight */
5279   pri_spec.weight = 128;
5280 
5281   rv = nghttp2_session_reprioritize_stream(session, stream, &pri_spec);
5282 
5283   assert_int(0, ==, rv);
5284   assert_int32(128, ==, stream->weight);
5285   assert_ptr_equal(dep_stream, stream->dep_prev);
5286 
5287   /* Change weight again to test short-path case */
5288   pri_spec.weight = 100;
5289 
5290   rv = nghttp2_session_reprioritize_stream(session, stream, &pri_spec);
5291 
5292   assert_int(0, ==, rv);
5293   assert_int32(100, ==, stream->weight);
5294   assert_ptr_equal(dep_stream, stream->dep_prev);
5295   assert_int32(100, ==, dep_stream->sum_dep_weight);
5296 
5297   /* Test circular dependency; stream 1 is first removed and becomes
5298      root.  Then stream 3 depends on it. */
5299   nghttp2_priority_spec_init(&pri_spec, 1, 1, 0);
5300 
5301   rv = nghttp2_session_reprioritize_stream(session, dep_stream, &pri_spec);
5302 
5303   assert_int(0, ==, rv);
5304   assert_int32(1, ==, dep_stream->weight);
5305   assert_ptr_equal(stream, dep_stream->dep_prev);
5306 
5307   /* Making priority to closed stream will result in default
5308      priority */
5309   session->last_recv_stream_id = 9;
5310 
5311   nghttp2_priority_spec_init(&pri_spec, 5, 5, 0);
5312 
5313   rv = nghttp2_session_reprioritize_stream(session, stream, &pri_spec);
5314 
5315   assert_int(0, ==, rv);
5316   assert_int32(NGHTTP2_DEFAULT_WEIGHT, ==, stream->weight);
5317 
5318   nghttp2_session_del(session);
5319 
5320   nghttp2_session_server_new(&session, &callbacks, NULL);
5321 
5322   /* circular dependency; in case of stream which is not a direct
5323      descendant of root.  Use exclusive dependency. */
5324   stream = open_recv_stream(session, 1);
5325   stream = open_recv_stream_with_dep(session, 3, stream);
5326   stream = open_recv_stream_with_dep(session, 5, stream);
5327   stream = open_recv_stream_with_dep(session, 7, stream);
5328   open_recv_stream_with_dep(session, 9, stream);
5329 
5330   nghttp2_priority_spec_init(&pri_spec, 7, 1, 1);
5331 
5332   stream = nghttp2_session_get_stream(session, 3);
5333   rv = nghttp2_session_reprioritize_stream(session, stream, &pri_spec);
5334 
5335   assert_int(0, ==, rv);
5336   assert_int32(7, ==, stream->dep_prev->stream_id);
5337 
5338   stream = nghttp2_session_get_stream(session, 7);
5339 
5340   assert_int32(1, ==, stream->dep_prev->stream_id);
5341 
5342   stream = nghttp2_session_get_stream(session, 9);
5343 
5344   assert_int32(3, ==, stream->dep_prev->stream_id);
5345 
5346   stream = nghttp2_session_get_stream(session, 5);
5347 
5348   assert_int32(3, ==, stream->dep_prev->stream_id);
5349 
5350   nghttp2_session_del(session);
5351 
5352   nghttp2_session_server_new(&session, &callbacks, NULL);
5353 
5354   /* circular dependency; in case of stream which is not a direct
5355      descendant of root.  Without exclusive dependency. */
5356   stream = open_recv_stream(session, 1);
5357   stream = open_recv_stream_with_dep(session, 3, stream);
5358   stream = open_recv_stream_with_dep(session, 5, stream);
5359   stream = open_recv_stream_with_dep(session, 7, stream);
5360   open_recv_stream_with_dep(session, 9, stream);
5361 
5362   nghttp2_priority_spec_init(&pri_spec, 7, 1, 0);
5363 
5364   stream = nghttp2_session_get_stream(session, 3);
5365   rv = nghttp2_session_reprioritize_stream(session, stream, &pri_spec);
5366 
5367   assert_int(0, ==, rv);
5368   assert_int32(7, ==, stream->dep_prev->stream_id);
5369 
5370   stream = nghttp2_session_get_stream(session, 7);
5371 
5372   assert_int32(1, ==, stream->dep_prev->stream_id);
5373 
5374   stream = nghttp2_session_get_stream(session, 9);
5375 
5376   assert_int32(7, ==, stream->dep_prev->stream_id);
5377 
5378   stream = nghttp2_session_get_stream(session, 5);
5379 
5380   assert_int32(3, ==, stream->dep_prev->stream_id);
5381 
5382   nghttp2_session_del(session);
5383 }
5384 
test_nghttp2_session_reprioritize_stream_with_idle_stream_dep(void)5385 void test_nghttp2_session_reprioritize_stream_with_idle_stream_dep(void) {
5386   nghttp2_session *session;
5387   nghttp2_session_callbacks callbacks;
5388   nghttp2_stream *stream;
5389   nghttp2_priority_spec pri_spec;
5390 
5391   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
5392   callbacks.send_callback2 = block_count_send_callback;
5393 
5394   nghttp2_session_server_new(&session, &callbacks, NULL);
5395 
5396   stream = open_recv_stream(session, 1);
5397 
5398   session->pending_local_max_concurrent_stream = 1;
5399 
5400   nghttp2_priority_spec_init(&pri_spec, 101, 10, 0);
5401 
5402   nghttp2_session_reprioritize_stream(session, stream, &pri_spec);
5403 
5404   /* idle stream is not counteed to max concurrent streams */
5405 
5406   assert_int32(10, ==, stream->weight);
5407   assert_int32(101, ==, stream->dep_prev->stream_id);
5408 
5409   stream = nghttp2_session_get_stream_raw(session, 101);
5410 
5411   assert_int32(NGHTTP2_DEFAULT_WEIGHT, ==, stream->weight);
5412 
5413   nghttp2_session_del(session);
5414 }
5415 
test_nghttp2_submit_data(void)5416 void test_nghttp2_submit_data(void) {
5417   nghttp2_session *session;
5418   nghttp2_session_callbacks callbacks;
5419   nghttp2_data_provider2 data_prd;
5420   my_user_data ud;
5421   nghttp2_frame *frame;
5422   nghttp2_frame_hd hd;
5423   nghttp2_active_outbound_item *aob;
5424   nghttp2_bufs *framebufs;
5425   nghttp2_buf *buf;
5426 
5427   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
5428   callbacks.send_callback2 = block_count_send_callback;
5429 
5430   data_prd.read_callback = fixed_length_data_source_read_callback;
5431   ud.data_source_length = NGHTTP2_DATA_PAYLOADLEN * 2;
5432   assert_int(0, ==, nghttp2_session_client_new(&session, &callbacks, &ud));
5433   aob = &session->aob;
5434   framebufs = &aob->framebufs;
5435 
5436   open_sent_stream(session, 1);
5437 
5438   assert_int(
5439     0, ==,
5440     nghttp2_submit_data2(session, NGHTTP2_FLAG_END_STREAM, 1, &data_prd));
5441 
5442   ud.block_count = 0;
5443   assert_int(0, ==, nghttp2_session_send(session));
5444   frame = &aob->item->frame;
5445 
5446   buf = &framebufs->head->buf;
5447   nghttp2_frame_unpack_frame_hd(&hd, buf->pos);
5448 
5449   assert_uint8(NGHTTP2_FLAG_NONE, ==, hd.flags);
5450   assert_uint8(NGHTTP2_FLAG_NONE, ==, frame->hd.flags);
5451   /* aux_data.data.flags has these flags */
5452   assert_uint8(NGHTTP2_FLAG_END_STREAM, ==, aob->item->aux_data.data.flags);
5453 
5454   nghttp2_session_del(session);
5455 }
5456 
test_nghttp2_submit_data_read_length_too_large(void)5457 void test_nghttp2_submit_data_read_length_too_large(void) {
5458   nghttp2_session *session;
5459   nghttp2_session_callbacks callbacks;
5460   nghttp2_data_provider2 data_prd;
5461   my_user_data ud;
5462   nghttp2_frame *frame;
5463   nghttp2_frame_hd hd;
5464   nghttp2_active_outbound_item *aob;
5465   nghttp2_bufs *framebufs;
5466   nghttp2_buf *buf;
5467   size_t payloadlen;
5468 
5469   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
5470   callbacks.send_callback2 = block_count_send_callback;
5471   callbacks.read_length_callback2 = too_large_data_source_length_callback;
5472 
5473   data_prd.read_callback = fixed_length_data_source_read_callback;
5474   ud.data_source_length = NGHTTP2_DATA_PAYLOADLEN * 2;
5475   assert_int(0, ==, nghttp2_session_client_new(&session, &callbacks, &ud));
5476   aob = &session->aob;
5477   framebufs = &aob->framebufs;
5478 
5479   open_sent_stream(session, 1);
5480 
5481   assert_int(
5482     0, ==,
5483     nghttp2_submit_data2(session, NGHTTP2_FLAG_END_STREAM, 1, &data_prd));
5484 
5485   ud.block_count = 0;
5486   assert_int(0, ==, nghttp2_session_send(session));
5487   frame = &aob->item->frame;
5488 
5489   buf = &framebufs->head->buf;
5490   nghttp2_frame_unpack_frame_hd(&hd, buf->pos);
5491 
5492   assert_uint8(NGHTTP2_FLAG_NONE, ==, hd.flags);
5493   assert_uint8(NGHTTP2_FLAG_NONE, ==, frame->hd.flags);
5494   assert_size(16384, ==, hd.length);
5495   /* aux_data.data.flags has these flags */
5496   assert_uint8(NGHTTP2_FLAG_END_STREAM, ==, aob->item->aux_data.data.flags);
5497 
5498   nghttp2_session_del(session);
5499 
5500   /* Check that buffers are expanded */
5501   assert_int(0, ==, nghttp2_session_client_new(&session, &callbacks, &ud));
5502 
5503   ud.data_source_length = NGHTTP2_MAX_FRAME_SIZE_MAX;
5504 
5505   session->remote_settings.max_frame_size = NGHTTP2_MAX_FRAME_SIZE_MAX;
5506 
5507   open_sent_stream(session, 1);
5508 
5509   assert_int(
5510     0, ==,
5511     nghttp2_submit_data2(session, NGHTTP2_FLAG_END_STREAM, 1, &data_prd));
5512 
5513   ud.block_count = 0;
5514   assert_int(0, ==, nghttp2_session_send(session));
5515 
5516   aob = &session->aob;
5517 
5518   frame = &aob->item->frame;
5519 
5520   framebufs = &aob->framebufs;
5521 
5522   buf = &framebufs->head->buf;
5523   nghttp2_frame_unpack_frame_hd(&hd, buf->pos);
5524 
5525   payloadlen = nghttp2_min_size(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE,
5526                                 NGHTTP2_INITIAL_WINDOW_SIZE);
5527 
5528   assert_size(NGHTTP2_FRAME_HDLEN + 1 + payloadlen, ==,
5529               (size_t)nghttp2_buf_cap(buf));
5530   assert_uint8(NGHTTP2_FLAG_NONE, ==, hd.flags);
5531   assert_uint8(NGHTTP2_FLAG_NONE, ==, frame->hd.flags);
5532   assert_size(payloadlen, ==, hd.length);
5533   /* aux_data.data.flags has these flags */
5534   assert_uint8(NGHTTP2_FLAG_END_STREAM, ==, aob->item->aux_data.data.flags);
5535 
5536   nghttp2_session_del(session);
5537 }
5538 
test_nghttp2_submit_data_read_length_smallest(void)5539 void test_nghttp2_submit_data_read_length_smallest(void) {
5540   nghttp2_session *session;
5541   nghttp2_session_callbacks callbacks;
5542   nghttp2_data_provider2 data_prd;
5543   my_user_data ud;
5544   nghttp2_frame *frame;
5545   nghttp2_frame_hd hd;
5546   nghttp2_active_outbound_item *aob;
5547   nghttp2_bufs *framebufs;
5548   nghttp2_buf *buf;
5549 
5550   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
5551   callbacks.send_callback2 = block_count_send_callback;
5552   callbacks.read_length_callback2 = smallest_length_data_source_length_callback;
5553 
5554   data_prd.read_callback = fixed_length_data_source_read_callback;
5555   ud.data_source_length = NGHTTP2_DATA_PAYLOADLEN * 2;
5556   assert_int(0, ==, nghttp2_session_client_new(&session, &callbacks, &ud));
5557   aob = &session->aob;
5558   framebufs = &aob->framebufs;
5559 
5560   open_sent_stream(session, 1);
5561 
5562   assert_int(
5563     0, ==,
5564     nghttp2_submit_data2(session, NGHTTP2_FLAG_END_STREAM, 1, &data_prd));
5565 
5566   ud.block_count = 0;
5567   assert_int(0, ==, nghttp2_session_send(session));
5568   frame = &aob->item->frame;
5569 
5570   buf = &framebufs->head->buf;
5571   nghttp2_frame_unpack_frame_hd(&hd, buf->pos);
5572 
5573   assert_uint8(NGHTTP2_FLAG_NONE, ==, hd.flags);
5574   assert_uint8(NGHTTP2_FLAG_NONE, ==, frame->hd.flags);
5575   assert_size(1, ==, hd.length);
5576   /* aux_data.data.flags has these flags */
5577   assert_uint8(NGHTTP2_FLAG_END_STREAM, ==, aob->item->aux_data.data.flags);
5578 
5579   nghttp2_session_del(session);
5580 }
5581 
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)5582 static nghttp2_ssize submit_data_twice_data_source_read_callback(
5583   nghttp2_session *session, int32_t stream_id, uint8_t *buf, size_t len,
5584   uint32_t *data_flags, nghttp2_data_source *source, void *user_data) {
5585   (void)session;
5586   (void)stream_id;
5587   (void)buf;
5588   (void)source;
5589   (void)user_data;
5590 
5591   *data_flags |= NGHTTP2_DATA_FLAG_EOF;
5592   return (nghttp2_ssize)nghttp2_min_size(len, 16);
5593 }
5594 
submit_data_twice_on_frame_send_callback(nghttp2_session * session,const nghttp2_frame * frame,void * user_data)5595 static int submit_data_twice_on_frame_send_callback(nghttp2_session *session,
5596                                                     const nghttp2_frame *frame,
5597                                                     void *user_data) {
5598   static int called = 0;
5599   int rv;
5600   nghttp2_data_provider2 data_prd;
5601   (void)user_data;
5602 
5603   if (called == 0) {
5604     called = 1;
5605 
5606     data_prd.read_callback = submit_data_twice_data_source_read_callback;
5607 
5608     rv = nghttp2_submit_data2(session, NGHTTP2_FLAG_END_STREAM,
5609                               frame->hd.stream_id, &data_prd);
5610     assert_int(0, ==, rv);
5611   }
5612 
5613   return 0;
5614 }
5615 
test_nghttp2_submit_data_twice(void)5616 void test_nghttp2_submit_data_twice(void) {
5617   nghttp2_session *session;
5618   nghttp2_session_callbacks callbacks;
5619   nghttp2_data_provider2 data_prd;
5620   my_user_data ud;
5621   accumulator acc;
5622 
5623   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
5624   callbacks.send_callback2 = accumulator_send_callback;
5625   callbacks.on_frame_send_callback = submit_data_twice_on_frame_send_callback;
5626 
5627   data_prd.read_callback = submit_data_twice_data_source_read_callback;
5628 
5629   acc.length = 0;
5630   ud.acc = &acc;
5631 
5632   assert_int(0, ==, nghttp2_session_client_new(&session, &callbacks, &ud));
5633 
5634   open_sent_stream(session, 1);
5635 
5636   assert_int(0, ==,
5637              nghttp2_submit_data2(session, NGHTTP2_FLAG_NONE, 1, &data_prd));
5638   assert_int(0, ==, nghttp2_session_send(session));
5639 
5640   /* We should have sent 2 DATA frame with 16 bytes payload each */
5641   assert_size(NGHTTP2_FRAME_HDLEN * 2 + 16 * 2, ==, acc.length);
5642 
5643   nghttp2_session_del(session);
5644 }
5645 
test_nghttp2_submit_request_with_data(void)5646 void test_nghttp2_submit_request_with_data(void) {
5647   nghttp2_session *session;
5648   nghttp2_session_callbacks callbacks;
5649   nghttp2_data_provider2 data_prd;
5650   my_user_data ud;
5651   nghttp2_outbound_item *item;
5652   nghttp2_mem *mem;
5653 
5654   mem = nghttp2_mem_default();
5655 
5656   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
5657   callbacks.send_callback2 = null_send_callback;
5658 
5659   data_prd.read_callback = fixed_length_data_source_read_callback;
5660   ud.data_source_length = 64 * 1024 - 1;
5661   assert_int(0, ==, nghttp2_session_client_new(&session, &callbacks, &ud));
5662   assert_int32(1, ==,
5663                nghttp2_submit_request2(session, NULL, reqnv, ARRLEN(reqnv),
5664                                        &data_prd, NULL));
5665   item = nghttp2_session_get_next_ob_item(session);
5666   assert_size(ARRLEN(reqnv), ==, item->frame.headers.nvlen);
5667   assert_nv_equal(reqnv, item->frame.headers.nva, item->frame.headers.nvlen,
5668                   mem);
5669   assert_int(0, ==, nghttp2_session_send(session));
5670   assert_size(0, ==, ud.data_source_length);
5671 
5672   nghttp2_session_del(session);
5673 
5674   /* nghttp2_submit_request2() with server session is error */
5675   nghttp2_session_server_new(&session, &callbacks, NULL);
5676 
5677   assert_int32(
5678     NGHTTP2_ERR_PROTO, ==,
5679     nghttp2_submit_request2(session, NULL, reqnv, ARRLEN(reqnv), NULL, NULL));
5680 
5681   nghttp2_session_del(session);
5682 }
5683 
test_nghttp2_submit_request_without_data(void)5684 void test_nghttp2_submit_request_without_data(void) {
5685   nghttp2_session *session;
5686   nghttp2_session_callbacks callbacks;
5687   accumulator acc;
5688   nghttp2_data_provider2 data_prd = {{-1}, NULL};
5689   nghttp2_outbound_item *item;
5690   my_user_data ud;
5691   nghttp2_frame frame;
5692   nghttp2_hd_inflater inflater;
5693   nva_out out;
5694   nghttp2_bufs bufs;
5695   nghttp2_mem *mem;
5696   nghttp2_priority_spec pri_spec;
5697 
5698   mem = nghttp2_mem_default();
5699   frame_pack_bufs_init(&bufs);
5700 
5701   nva_out_init(&out);
5702   acc.length = 0;
5703   ud.acc = &acc;
5704   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
5705   callbacks.send_callback2 = accumulator_send_callback;
5706   assert_int(0, ==, nghttp2_session_client_new(&session, &callbacks, &ud));
5707 
5708   nghttp2_hd_inflate_init(&inflater, mem);
5709   assert_int32(1, ==,
5710                nghttp2_submit_request2(session, NULL, reqnv, ARRLEN(reqnv),
5711                                        &data_prd, NULL));
5712   item = nghttp2_session_get_next_ob_item(session);
5713   assert_size(ARRLEN(reqnv), ==, item->frame.headers.nvlen);
5714   assert_nv_equal(reqnv, item->frame.headers.nva, item->frame.headers.nvlen,
5715                   mem);
5716   assert_true(item->frame.hd.flags & NGHTTP2_FLAG_END_STREAM);
5717 
5718   assert_int(0, ==, nghttp2_session_send(session));
5719   assert_int(0, ==, unpack_frame(&frame, acc.buf, acc.length));
5720 
5721   nghttp2_bufs_add(&bufs, acc.buf, acc.length);
5722   inflate_hd(&inflater, &out, &bufs, NGHTTP2_FRAME_HDLEN, mem);
5723 
5724   assert_size(ARRLEN(reqnv), ==, out.nvlen);
5725   assert_nv_equal(reqnv, out.nva, out.nvlen, mem);
5726   nghttp2_frame_headers_free(&frame.headers, mem);
5727   nva_out_reset(&out, mem);
5728 
5729   nghttp2_bufs_free(&bufs);
5730   nghttp2_hd_inflate_free(&inflater);
5731 
5732   /* Try to depend on itself is error */
5733   nghttp2_priority_spec_init(&pri_spec, (int32_t)session->next_stream_id, 16,
5734                              0);
5735 
5736   assert_int32(NGHTTP2_ERR_INVALID_ARGUMENT, ==,
5737                nghttp2_submit_request2(session, &pri_spec, reqnv, ARRLEN(reqnv),
5738                                        NULL, NULL));
5739 
5740   nghttp2_session_del(session);
5741 }
5742 
test_nghttp2_submit_response_with_data(void)5743 void test_nghttp2_submit_response_with_data(void) {
5744   nghttp2_session *session;
5745   nghttp2_session_callbacks callbacks;
5746   nghttp2_data_provider2 data_prd;
5747   my_user_data ud;
5748   nghttp2_outbound_item *item;
5749   nghttp2_mem *mem;
5750 
5751   mem = nghttp2_mem_default();
5752 
5753   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
5754   callbacks.send_callback2 = null_send_callback;
5755 
5756   data_prd.read_callback = fixed_length_data_source_read_callback;
5757   ud.data_source_length = 64 * 1024 - 1;
5758   assert_int(0, ==, nghttp2_session_server_new(&session, &callbacks, &ud));
5759   open_recv_stream2(session, 1, NGHTTP2_STREAM_OPENING);
5760   assert_int(
5761     0, ==,
5762     nghttp2_submit_response2(session, 1, resnv, ARRLEN(resnv), &data_prd));
5763   item = nghttp2_session_get_next_ob_item(session);
5764   assert_size(ARRLEN(resnv), ==, item->frame.headers.nvlen);
5765   assert_nv_equal(resnv, item->frame.headers.nva, item->frame.headers.nvlen,
5766                   mem);
5767   assert_int(0, ==, nghttp2_session_send(session));
5768   assert_size(0, ==, ud.data_source_length);
5769 
5770   nghttp2_session_del(session);
5771 
5772   /* Various error cases */
5773   nghttp2_session_client_new(&session, &callbacks, NULL);
5774 
5775   /* Calling nghttp2_submit_response2() with client session is error */
5776   assert_int(NGHTTP2_ERR_PROTO, ==,
5777              nghttp2_submit_response2(session, 1, resnv, ARRLEN(resnv), NULL));
5778 
5779   /* Stream ID <= 0 is error */
5780   assert_int(NGHTTP2_ERR_INVALID_ARGUMENT, ==,
5781              nghttp2_submit_response2(session, 0, resnv, ARRLEN(resnv), NULL));
5782 
5783   nghttp2_session_del(session);
5784 }
5785 
test_nghttp2_submit_response_without_data(void)5786 void test_nghttp2_submit_response_without_data(void) {
5787   nghttp2_session *session;
5788   nghttp2_session_callbacks callbacks;
5789   accumulator acc;
5790   nghttp2_data_provider2 data_prd = {{-1}, NULL};
5791   nghttp2_outbound_item *item;
5792   my_user_data ud;
5793   nghttp2_frame frame;
5794   nghttp2_hd_inflater inflater;
5795   nva_out out;
5796   nghttp2_bufs bufs;
5797   nghttp2_mem *mem;
5798 
5799   mem = nghttp2_mem_default();
5800   frame_pack_bufs_init(&bufs);
5801 
5802   nva_out_init(&out);
5803   acc.length = 0;
5804   ud.acc = &acc;
5805   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
5806   callbacks.send_callback2 = accumulator_send_callback;
5807   assert_int(0, ==, nghttp2_session_server_new(&session, &callbacks, &ud));
5808 
5809   nghttp2_hd_inflate_init(&inflater, mem);
5810   open_recv_stream2(session, 1, NGHTTP2_STREAM_OPENING);
5811   assert_int(
5812     0, ==,
5813     nghttp2_submit_response2(session, 1, resnv, ARRLEN(resnv), &data_prd));
5814   item = nghttp2_session_get_next_ob_item(session);
5815   assert_size(ARRLEN(resnv), ==, item->frame.headers.nvlen);
5816   assert_nv_equal(resnv, item->frame.headers.nva, item->frame.headers.nvlen,
5817                   mem);
5818   assert_true(item->frame.hd.flags & NGHTTP2_FLAG_END_STREAM);
5819 
5820   assert_int(0, ==, nghttp2_session_send(session));
5821   assert_int(0, ==, unpack_frame(&frame, acc.buf, acc.length));
5822 
5823   nghttp2_bufs_add(&bufs, acc.buf, acc.length);
5824   inflate_hd(&inflater, &out, &bufs, NGHTTP2_FRAME_HDLEN, mem);
5825 
5826   assert_size(ARRLEN(resnv), ==, out.nvlen);
5827   assert_nv_equal(resnv, out.nva, out.nvlen, mem);
5828 
5829   nva_out_reset(&out, mem);
5830   nghttp2_bufs_free(&bufs);
5831   nghttp2_frame_headers_free(&frame.headers, mem);
5832   nghttp2_hd_inflate_free(&inflater);
5833   nghttp2_session_del(session);
5834 }
5835 
test_nghttp2_submit_response_push_response(void)5836 void test_nghttp2_submit_response_push_response(void) {
5837   nghttp2_session *session;
5838   nghttp2_session_callbacks callbacks;
5839   my_user_data ud;
5840 
5841   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
5842   callbacks.send_callback2 = null_send_callback;
5843   callbacks.on_frame_not_send_callback = on_frame_not_send_callback;
5844 
5845   nghttp2_session_server_new(&session, &callbacks, &ud);
5846 
5847   open_sent_stream2(session, 2, NGHTTP2_STREAM_RESERVED);
5848 
5849   session->goaway_flags |= NGHTTP2_GOAWAY_RECV;
5850 
5851   assert_int(0, ==,
5852              nghttp2_submit_response2(session, 2, resnv, ARRLEN(resnv), NULL));
5853 
5854   ud.frame_not_send_cb_called = 0;
5855 
5856   assert_int(0, ==, nghttp2_session_send(session));
5857   assert_int(1, ==, ud.frame_not_send_cb_called);
5858 
5859   nghttp2_session_del(session);
5860 }
5861 
test_nghttp2_submit_trailer(void)5862 void test_nghttp2_submit_trailer(void) {
5863   nghttp2_session *session;
5864   nghttp2_session_callbacks callbacks;
5865   accumulator acc;
5866   nghttp2_data_provider2 data_prd;
5867   nghttp2_outbound_item *item;
5868   my_user_data ud;
5869   nghttp2_frame frame;
5870   nghttp2_hd_inflater inflater;
5871   nva_out out;
5872   nghttp2_bufs bufs;
5873   nghttp2_mem *mem;
5874 
5875   mem = nghttp2_mem_default();
5876   frame_pack_bufs_init(&bufs);
5877 
5878   data_prd.read_callback = no_end_stream_data_source_read_callback;
5879   nva_out_init(&out);
5880   acc.length = 0;
5881   ud.acc = &acc;
5882   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
5883   callbacks.send_callback2 = null_send_callback;
5884   assert_int(0, ==, nghttp2_session_server_new(&session, &callbacks, &ud));
5885 
5886   nghttp2_hd_inflate_init(&inflater, mem);
5887   open_recv_stream2(session, 1, NGHTTP2_STREAM_OPENING);
5888   assert_int(
5889     0, ==,
5890     nghttp2_submit_response2(session, 1, resnv, ARRLEN(resnv), &data_prd));
5891   assert_int(0, ==, nghttp2_session_send(session));
5892 
5893   assert_int(0, ==,
5894              nghttp2_submit_trailer(session, 1, trailernv, ARRLEN(trailernv)));
5895 
5896   session->callbacks.send_callback2 = accumulator_send_callback;
5897 
5898   item = nghttp2_session_get_next_ob_item(session);
5899   assert_uint8(NGHTTP2_HEADERS, ==, item->frame.hd.type);
5900   assert_enum(nghttp2_headers_category, NGHTTP2_HCAT_HEADERS, ==,
5901               item->frame.headers.cat);
5902   assert_true(item->frame.hd.flags & NGHTTP2_FLAG_END_STREAM);
5903 
5904   assert_int(0, ==, nghttp2_session_send(session));
5905   assert_int(0, ==, unpack_frame(&frame, acc.buf, acc.length));
5906 
5907   nghttp2_bufs_add(&bufs, acc.buf, acc.length);
5908   inflate_hd(&inflater, &out, &bufs, NGHTTP2_FRAME_HDLEN, mem);
5909 
5910   assert_size(ARRLEN(trailernv), ==, out.nvlen);
5911   assert_nv_equal(trailernv, out.nva, out.nvlen, mem);
5912 
5913   nva_out_reset(&out, mem);
5914   nghttp2_bufs_free(&bufs);
5915   nghttp2_frame_headers_free(&frame.headers, mem);
5916   nghttp2_hd_inflate_free(&inflater);
5917   nghttp2_session_del(session);
5918 
5919   /* Specifying stream ID <= 0 is error */
5920   nghttp2_session_server_new(&session, &callbacks, NULL);
5921   open_recv_stream(session, 1);
5922 
5923   assert_int(NGHTTP2_ERR_INVALID_ARGUMENT, ==,
5924              nghttp2_submit_trailer(session, 0, trailernv, ARRLEN(trailernv)));
5925 
5926   assert_int(NGHTTP2_ERR_INVALID_ARGUMENT, ==,
5927              nghttp2_submit_trailer(session, -1, trailernv, ARRLEN(trailernv)));
5928 
5929   nghttp2_session_del(session);
5930 }
5931 
test_nghttp2_submit_headers_start_stream(void)5932 void test_nghttp2_submit_headers_start_stream(void) {
5933   nghttp2_session *session;
5934   nghttp2_session_callbacks callbacks;
5935   nghttp2_outbound_item *item;
5936   nghttp2_mem *mem;
5937 
5938   mem = nghttp2_mem_default();
5939 
5940   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
5941   assert_int(0, ==, nghttp2_session_client_new(&session, &callbacks, NULL));
5942   assert_int32(1, ==,
5943                nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, -1,
5944                                       NULL, reqnv, ARRLEN(reqnv), NULL));
5945   item = nghttp2_session_get_next_ob_item(session);
5946   assert_size(ARRLEN(reqnv), ==, item->frame.headers.nvlen);
5947   assert_nv_equal(reqnv, item->frame.headers.nva, item->frame.headers.nvlen,
5948                   mem);
5949   assert_uint8((NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM), ==,
5950                item->frame.hd.flags);
5951   assert_false(item->frame.hd.flags & NGHTTP2_FLAG_PRIORITY);
5952 
5953   nghttp2_session_del(session);
5954 }
5955 
test_nghttp2_submit_headers_reply(void)5956 void test_nghttp2_submit_headers_reply(void) {
5957   nghttp2_session *session;
5958   nghttp2_session_callbacks callbacks;
5959   my_user_data ud;
5960   nghttp2_outbound_item *item;
5961   nghttp2_stream *stream;
5962   nghttp2_mem *mem;
5963 
5964   mem = nghttp2_mem_default();
5965 
5966   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
5967   callbacks.send_callback2 = null_send_callback;
5968   callbacks.on_frame_send_callback = on_frame_send_callback;
5969 
5970   assert_int(0, ==, nghttp2_session_server_new(&session, &callbacks, &ud));
5971   assert_int32(0, ==,
5972                nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, 1, NULL,
5973                                       resnv, ARRLEN(resnv), NULL));
5974   item = nghttp2_session_get_next_ob_item(session);
5975   assert_size(ARRLEN(resnv), ==, item->frame.headers.nvlen);
5976   assert_nv_equal(resnv, item->frame.headers.nva, item->frame.headers.nvlen,
5977                   mem);
5978   assert_uint8((NGHTTP2_FLAG_END_STREAM | NGHTTP2_FLAG_END_HEADERS), ==,
5979                item->frame.hd.flags);
5980 
5981   ud.frame_send_cb_called = 0;
5982   ud.sent_frame_type = 0;
5983   /* The transimission will be canceled because the stream 1 is not
5984      open. */
5985   assert_int(0, ==, nghttp2_session_send(session));
5986   assert_int(0, ==, ud.frame_send_cb_called);
5987 
5988   stream = open_recv_stream2(session, 1, NGHTTP2_STREAM_OPENING);
5989 
5990   assert_int32(0, ==,
5991                nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, 1, NULL,
5992                                       resnv, ARRLEN(resnv), NULL));
5993   assert_int(0, ==, nghttp2_session_send(session));
5994   assert_int(1, ==, ud.frame_send_cb_called);
5995   assert_uint8(NGHTTP2_HEADERS, ==, ud.sent_frame_type);
5996   assert_true(stream->shut_flags & NGHTTP2_SHUT_WR);
5997 
5998   nghttp2_session_del(session);
5999 }
6000 
test_nghttp2_submit_headers_push_reply(void)6001 void test_nghttp2_submit_headers_push_reply(void) {
6002   nghttp2_session *session;
6003   nghttp2_session_callbacks callbacks;
6004   my_user_data ud;
6005   nghttp2_stream *stream;
6006   int foo;
6007 
6008   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6009   callbacks.send_callback2 = null_send_callback;
6010   callbacks.on_frame_send_callback = on_frame_send_callback;
6011 
6012   assert_int(0, ==, nghttp2_session_server_new(&session, &callbacks, &ud));
6013   stream = open_sent_stream2(session, 2, NGHTTP2_STREAM_RESERVED);
6014   assert_int32(0, ==,
6015                nghttp2_submit_headers(session, NGHTTP2_FLAG_NONE, 2, NULL,
6016                                       resnv, ARRLEN(resnv), &foo));
6017 
6018   ud.frame_send_cb_called = 0;
6019   ud.sent_frame_type = 0;
6020   assert_int(0, ==, nghttp2_session_send(session));
6021   assert_int(1, ==, ud.frame_send_cb_called);
6022   assert_uint8(NGHTTP2_HEADERS, ==, ud.sent_frame_type);
6023   assert_enum(nghttp2_stream_state, NGHTTP2_STREAM_OPENED, ==, stream->state);
6024   assert_ptr_equal(&foo, stream->stream_user_data);
6025 
6026   nghttp2_session_del(session);
6027 
6028   /* Sending HEADERS from client against stream in reserved state is
6029      error */
6030   assert_int(0, ==, nghttp2_session_client_new(&session, &callbacks, &ud));
6031   open_recv_stream2(session, 2, NGHTTP2_STREAM_RESERVED);
6032   assert_int32(0, ==,
6033                nghttp2_submit_headers(session, NGHTTP2_FLAG_NONE, 2, NULL,
6034                                       reqnv, ARRLEN(reqnv), NULL));
6035 
6036   ud.frame_send_cb_called = 0;
6037   ud.sent_frame_type = 0;
6038   assert_int(0, ==, nghttp2_session_send(session));
6039   assert_int(0, ==, ud.frame_send_cb_called);
6040 
6041   nghttp2_session_del(session);
6042 }
6043 
test_nghttp2_submit_headers(void)6044 void test_nghttp2_submit_headers(void) {
6045   nghttp2_session *session;
6046   nghttp2_session_callbacks callbacks;
6047   my_user_data ud;
6048   nghttp2_outbound_item *item;
6049   nghttp2_stream *stream;
6050   accumulator acc;
6051   nghttp2_frame frame;
6052   nghttp2_hd_inflater inflater;
6053   nva_out out;
6054   nghttp2_bufs bufs;
6055   nghttp2_mem *mem;
6056   nghttp2_priority_spec pri_spec;
6057 
6058   mem = nghttp2_mem_default();
6059   frame_pack_bufs_init(&bufs);
6060 
6061   nva_out_init(&out);
6062   acc.length = 0;
6063   ud.acc = &acc;
6064   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6065   callbacks.send_callback2 = accumulator_send_callback;
6066   callbacks.on_frame_send_callback = on_frame_send_callback;
6067 
6068   assert_int(0, ==, nghttp2_session_client_new(&session, &callbacks, &ud));
6069 
6070   nghttp2_hd_inflate_init(&inflater, mem);
6071   assert_int32(0, ==,
6072                nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, 1, NULL,
6073                                       reqnv, ARRLEN(reqnv), NULL));
6074   item = nghttp2_session_get_next_ob_item(session);
6075   assert_size(ARRLEN(reqnv), ==, item->frame.headers.nvlen);
6076   assert_nv_equal(reqnv, item->frame.headers.nva, item->frame.headers.nvlen,
6077                   mem);
6078   assert_uint8((NGHTTP2_FLAG_END_STREAM | NGHTTP2_FLAG_END_HEADERS), ==,
6079                item->frame.hd.flags);
6080 
6081   ud.frame_send_cb_called = 0;
6082   ud.sent_frame_type = 0;
6083   /* The transimission will be canceled because the stream 1 is not
6084      open. */
6085   assert_int(0, ==, nghttp2_session_send(session));
6086   assert_int(0, ==, ud.frame_send_cb_called);
6087 
6088   stream = open_sent_stream(session, 1);
6089 
6090   assert_int32(0, ==,
6091                nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, 1, NULL,
6092                                       reqnv, ARRLEN(reqnv), NULL));
6093   assert_int(0, ==, nghttp2_session_send(session));
6094   assert_int(1, ==, ud.frame_send_cb_called);
6095   assert_uint8(NGHTTP2_HEADERS, ==, ud.sent_frame_type);
6096   assert_true(stream->shut_flags & NGHTTP2_SHUT_WR);
6097 
6098   assert_int(0, ==, unpack_frame(&frame, acc.buf, acc.length));
6099 
6100   nghttp2_bufs_add(&bufs, acc.buf, acc.length);
6101   inflate_hd(&inflater, &out, &bufs, NGHTTP2_FRAME_HDLEN, mem);
6102 
6103   assert_size(ARRLEN(reqnv), ==, out.nvlen);
6104   assert_nv_equal(reqnv, out.nva, out.nvlen, mem);
6105 
6106   nva_out_reset(&out, mem);
6107   nghttp2_bufs_free(&bufs);
6108   nghttp2_frame_headers_free(&frame.headers, mem);
6109 
6110   nghttp2_hd_inflate_free(&inflater);
6111 
6112   /* Try to depend on itself */
6113   nghttp2_priority_spec_init(&pri_spec, 3, 16, 0);
6114 
6115   assert_int32(NGHTTP2_ERR_INVALID_ARGUMENT, ==,
6116                nghttp2_submit_headers(session, NGHTTP2_FLAG_NONE, 3, &pri_spec,
6117                                       reqnv, ARRLEN(reqnv), NULL));
6118 
6119   session->next_stream_id = 5;
6120   nghttp2_priority_spec_init(&pri_spec, 5, 16, 0);
6121 
6122   assert_int32(NGHTTP2_ERR_INVALID_ARGUMENT, ==,
6123                nghttp2_submit_headers(session, NGHTTP2_FLAG_NONE, -1, &pri_spec,
6124                                       reqnv, ARRLEN(reqnv), NULL));
6125 
6126   nghttp2_session_del(session);
6127 
6128   /* Error cases with invalid stream ID */
6129   nghttp2_session_server_new(&session, &callbacks, NULL);
6130 
6131   /* Sending nghttp2_submit_headers() with stream_id == 1 and server
6132      session is error */
6133   assert_int32(NGHTTP2_ERR_PROTO, ==,
6134                nghttp2_submit_headers(session, NGHTTP2_FLAG_NONE, -1, NULL,
6135                                       reqnv, ARRLEN(reqnv), NULL));
6136 
6137   /* Sending stream ID <= 0 is error */
6138   assert_int32(NGHTTP2_ERR_INVALID_ARGUMENT, ==,
6139                nghttp2_submit_headers(session, NGHTTP2_FLAG_NONE, 0, NULL,
6140                                       resnv, ARRLEN(resnv), NULL));
6141 
6142   nghttp2_session_del(session);
6143 }
6144 
test_nghttp2_submit_headers_continuation(void)6145 void test_nghttp2_submit_headers_continuation(void) {
6146   nghttp2_session *session;
6147   nghttp2_session_callbacks callbacks;
6148   nghttp2_nv nv[] = {
6149     MAKE_NV("h1", ""), MAKE_NV("h1", ""), MAKE_NV("h1", ""), MAKE_NV("h1", ""),
6150     MAKE_NV("h1", ""), MAKE_NV("h1", ""), MAKE_NV("h1", ""),
6151   };
6152   nghttp2_outbound_item *item;
6153   uint8_t data[4096];
6154   size_t i;
6155   my_user_data ud;
6156 
6157   memset(data, '0', sizeof(data));
6158   for (i = 0; i < ARRLEN(nv); ++i) {
6159     nv[i].valuelen = sizeof(data);
6160     nv[i].value = data;
6161   }
6162 
6163   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6164   callbacks.send_callback2 = null_send_callback;
6165   callbacks.on_frame_send_callback = on_frame_send_callback;
6166 
6167   assert_int(0, ==, nghttp2_session_client_new(&session, &callbacks, &ud));
6168   assert_int32(1, ==,
6169                nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, -1,
6170                                       NULL, nv, ARRLEN(nv), NULL));
6171   item = nghttp2_session_get_next_ob_item(session);
6172   assert_uint8(NGHTTP2_HEADERS, ==, item->frame.hd.type);
6173   assert_uint8((NGHTTP2_FLAG_END_STREAM | NGHTTP2_FLAG_END_HEADERS), ==,
6174                item->frame.hd.flags);
6175   assert_false(item->frame.hd.flags & NGHTTP2_FLAG_PRIORITY);
6176 
6177   ud.frame_send_cb_called = 0;
6178   assert_int(0, ==, nghttp2_session_send(session));
6179   assert_int(1, ==, ud.frame_send_cb_called);
6180 
6181   nghttp2_session_del(session);
6182 }
6183 
test_nghttp2_submit_headers_continuation_extra_large(void)6184 void test_nghttp2_submit_headers_continuation_extra_large(void) {
6185   nghttp2_session *session;
6186   nghttp2_session_callbacks callbacks;
6187   nghttp2_nv nv[] = {
6188     MAKE_NV("h1", ""), MAKE_NV("h1", ""), MAKE_NV("h1", ""),
6189     MAKE_NV("h1", ""), MAKE_NV("h1", ""), MAKE_NV("h1", ""),
6190   };
6191   nghttp2_outbound_item *item;
6192   uint8_t data[16384];
6193   size_t i;
6194   my_user_data ud;
6195   nghttp2_option *opt;
6196 
6197   memset(data, '0', sizeof(data));
6198   for (i = 0; i < ARRLEN(nv); ++i) {
6199     nv[i].valuelen = sizeof(data);
6200     nv[i].value = data;
6201   }
6202 
6203   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6204   callbacks.send_callback2 = null_send_callback;
6205   callbacks.on_frame_send_callback = on_frame_send_callback;
6206 
6207   /* The default size of max send header block length is too small to
6208      send these header fields.  Expand it. */
6209   nghttp2_option_new(&opt);
6210   nghttp2_option_set_max_send_header_block_length(opt, 102400);
6211 
6212   assert_int(0, ==,
6213              nghttp2_session_client_new2(&session, &callbacks, &ud, opt));
6214   assert_int32(1, ==,
6215                nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, -1,
6216                                       NULL, nv, ARRLEN(nv), NULL));
6217   item = nghttp2_session_get_next_ob_item(session);
6218   assert_uint8(NGHTTP2_HEADERS, ==, item->frame.hd.type);
6219   assert_uint8((NGHTTP2_FLAG_END_STREAM | NGHTTP2_FLAG_END_HEADERS), ==,
6220                item->frame.hd.flags);
6221   assert_false(item->frame.hd.flags & NGHTTP2_FLAG_PRIORITY);
6222 
6223   ud.frame_send_cb_called = 0;
6224   assert_int(0, ==, nghttp2_session_send(session));
6225   assert_int(1, ==, ud.frame_send_cb_called);
6226 
6227   nghttp2_session_del(session);
6228   nghttp2_option_del(opt);
6229 }
6230 
test_nghttp2_submit_priority(void)6231 void test_nghttp2_submit_priority(void) {
6232   nghttp2_session *session;
6233   nghttp2_session_callbacks callbacks;
6234   nghttp2_stream *stream;
6235   my_user_data ud;
6236   nghttp2_priority_spec pri_spec;
6237 
6238   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6239   callbacks.send_callback2 = null_send_callback;
6240   callbacks.on_frame_send_callback = on_frame_send_callback;
6241 
6242   nghttp2_session_client_new(&session, &callbacks, &ud);
6243   stream = open_sent_stream(session, 1);
6244 
6245   nghttp2_priority_spec_init(&pri_spec, 0, 3, 0);
6246 
6247   /* depends on stream 0 */
6248   assert_int(0, ==,
6249              nghttp2_submit_priority(session, NGHTTP2_FLAG_NONE, 1, &pri_spec));
6250   assert_int(0, ==, nghttp2_session_send(session));
6251   assert_int32(3, ==, stream->weight);
6252 
6253   /* submit against idle stream */
6254   assert_int(0, ==,
6255              nghttp2_submit_priority(session, NGHTTP2_FLAG_NONE, 3, &pri_spec));
6256 
6257   ud.frame_send_cb_called = 0;
6258   assert_int(0, ==, nghttp2_session_send(session));
6259   assert_int(1, ==, ud.frame_send_cb_called);
6260 
6261   nghttp2_session_del(session);
6262 }
6263 
test_nghttp2_submit_settings(void)6264 void test_nghttp2_submit_settings(void) {
6265   nghttp2_session *session;
6266   nghttp2_session_callbacks callbacks;
6267   my_user_data ud;
6268   nghttp2_outbound_item *item;
6269   nghttp2_frame *frame;
6270   nghttp2_settings_entry iv[7];
6271   nghttp2_frame ack_frame;
6272   const int32_t UNKNOWN_ID = 1000000007;
6273   nghttp2_mem *mem;
6274 
6275   mem = nghttp2_mem_default();
6276 
6277   iv[0].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS;
6278   iv[0].value = 5;
6279 
6280   iv[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
6281   iv[1].value = 16 * 1024;
6282 
6283   iv[2].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS;
6284   iv[2].value = 50;
6285 
6286   iv[3].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
6287   iv[3].value = 111;
6288 
6289   iv[4].settings_id = UNKNOWN_ID;
6290   iv[4].value = 999;
6291 
6292   iv[5].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
6293   iv[5].value = 1023;
6294 
6295   iv[6].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
6296   iv[6].value = (uint32_t)NGHTTP2_MAX_WINDOW_SIZE + 1;
6297 
6298   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6299   callbacks.send_callback2 = null_send_callback;
6300   callbacks.on_frame_send_callback = on_frame_send_callback;
6301   nghttp2_session_server_new(&session, &callbacks, &ud);
6302 
6303   assert_int(NGHTTP2_ERR_INVALID_ARGUMENT, ==,
6304              nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, iv, 7));
6305 
6306   /* Make sure that local settings are not changed */
6307   assert_uint32(NGHTTP2_DEFAULT_MAX_CONCURRENT_STREAMS, ==,
6308                 session->local_settings.max_concurrent_streams);
6309   assert_uint32(NGHTTP2_INITIAL_WINDOW_SIZE, ==,
6310                 session->local_settings.initial_window_size);
6311 
6312   /* Now sends without 6th one */
6313   assert_int(0, ==, nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, iv, 6));
6314 
6315   item = nghttp2_session_get_next_ob_item(session);
6316 
6317   assert_uint8(NGHTTP2_SETTINGS, ==, item->frame.hd.type);
6318 
6319   frame = &item->frame;
6320   assert_size(6, ==, frame->settings.niv);
6321   assert_uint32(5, ==, frame->settings.iv[0].value);
6322   assert_int32(NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, ==,
6323                frame->settings.iv[0].settings_id);
6324 
6325   assert_uint32(16 * 1024, ==, frame->settings.iv[1].value);
6326   assert_int32(NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE, ==,
6327                frame->settings.iv[1].settings_id);
6328 
6329   assert_int32(UNKNOWN_ID, ==, frame->settings.iv[4].settings_id);
6330   assert_uint32(999, ==, frame->settings.iv[4].value);
6331 
6332   ud.frame_send_cb_called = 0;
6333   assert_int(0, ==, nghttp2_session_send(session));
6334   assert_int(1, ==, ud.frame_send_cb_called);
6335 
6336   assert_uint32(50, ==, session->pending_local_max_concurrent_stream);
6337 
6338   /* before receiving SETTINGS ACK, local settings have still default
6339      values */
6340   assert_uint32(NGHTTP2_DEFAULT_MAX_CONCURRENT_STREAMS, ==,
6341                 nghttp2_session_get_local_settings(
6342                   session, NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS));
6343   assert_uint32(NGHTTP2_INITIAL_WINDOW_SIZE, ==,
6344                 nghttp2_session_get_local_settings(
6345                   session, NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE));
6346 
6347   nghttp2_frame_settings_init(&ack_frame.settings, NGHTTP2_FLAG_ACK, NULL, 0);
6348   assert_int(0, ==,
6349              nghttp2_session_on_settings_received(session, &ack_frame, 0));
6350   nghttp2_frame_settings_free(&ack_frame.settings, mem);
6351 
6352   assert_uint32(16 * 1024, ==, session->local_settings.initial_window_size);
6353   assert_size(111, ==, session->hd_inflater.ctx.hd_table_bufsize_max);
6354   assert_size(111, ==, session->hd_inflater.min_hd_table_bufsize_max);
6355   assert_uint32(50, ==, session->local_settings.max_concurrent_streams);
6356 
6357   assert_uint32(50, ==,
6358                 nghttp2_session_get_local_settings(
6359                   session, NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS));
6360   assert_uint32(16 * 1024, ==,
6361                 nghttp2_session_get_local_settings(
6362                   session, NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE));
6363 
6364   /* We just keep the last seen value */
6365   assert_uint32(50, ==, session->pending_local_max_concurrent_stream);
6366 
6367   nghttp2_session_del(session);
6368 
6369   /* Bail out if there are contradicting
6370      SETTINGS_NO_RFC7540_PRIORITIES in one SETTINGS. */
6371   nghttp2_session_server_new(&session, &callbacks, &ud);
6372 
6373   iv[0].settings_id = NGHTTP2_SETTINGS_NO_RFC7540_PRIORITIES;
6374   iv[0].value = 1;
6375   iv[1].settings_id = NGHTTP2_SETTINGS_NO_RFC7540_PRIORITIES;
6376   iv[1].value = 0;
6377 
6378   assert_int(NGHTTP2_ERR_INVALID_ARGUMENT, ==,
6379              nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, iv, 2));
6380 
6381   nghttp2_session_del(session);
6382 
6383   /* Attempt to change SETTINGS_NO_RFC7540_PRIORITIES in the 2nd
6384      SETTINGS. */
6385   nghttp2_session_server_new(&session, &callbacks, &ud);
6386 
6387   iv[0].settings_id = NGHTTP2_SETTINGS_NO_RFC7540_PRIORITIES;
6388   iv[0].value = 1;
6389 
6390   assert_int(0, ==, nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, iv, 1));
6391 
6392   iv[0].settings_id = NGHTTP2_SETTINGS_NO_RFC7540_PRIORITIES;
6393   iv[0].value = 0;
6394 
6395   assert_int(NGHTTP2_ERR_INVALID_ARGUMENT, ==,
6396              nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, iv, 1));
6397 
6398   nghttp2_session_del(session);
6399 }
6400 
test_nghttp2_submit_settings_update_local_window_size(void)6401 void test_nghttp2_submit_settings_update_local_window_size(void) {
6402   nghttp2_session *session;
6403   nghttp2_session_callbacks callbacks;
6404   nghttp2_outbound_item *item;
6405   nghttp2_settings_entry iv[4];
6406   nghttp2_stream *stream;
6407   nghttp2_frame ack_frame;
6408   nghttp2_mem *mem;
6409   nghttp2_option *option;
6410 
6411   mem = nghttp2_mem_default();
6412   nghttp2_frame_settings_init(&ack_frame.settings, NGHTTP2_FLAG_ACK, NULL, 0);
6413 
6414   iv[0].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
6415   iv[0].value = 16 * 1024;
6416 
6417   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6418   callbacks.send_callback2 = null_send_callback;
6419 
6420   nghttp2_session_server_new(&session, &callbacks, NULL);
6421 
6422   stream = open_recv_stream(session, 1);
6423   stream->local_window_size = NGHTTP2_INITIAL_WINDOW_SIZE + 100;
6424   stream->recv_window_size = 32768;
6425 
6426   open_recv_stream(session, 3);
6427 
6428   assert_int(0, ==, nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, iv, 1));
6429   assert_int(0, ==, nghttp2_session_send(session));
6430   assert_int(0, ==,
6431              nghttp2_session_on_settings_received(session, &ack_frame, 0));
6432 
6433   stream = nghttp2_session_get_stream(session, 1);
6434   assert_int32(0, ==, stream->recv_window_size);
6435   assert_int32(16 * 1024 + 100, ==, stream->local_window_size);
6436 
6437   stream = nghttp2_session_get_stream(session, 3);
6438   assert_int32(16 * 1024, ==, stream->local_window_size);
6439 
6440   item = nghttp2_session_get_next_ob_item(session);
6441   assert_uint8(NGHTTP2_WINDOW_UPDATE, ==, item->frame.hd.type);
6442   assert_int32(32768, ==, item->frame.window_update.window_size_increment);
6443 
6444   nghttp2_session_del(session);
6445 
6446   /* Without auto-window update */
6447   nghttp2_option_new(&option);
6448   nghttp2_option_set_no_auto_window_update(option, 1);
6449 
6450   nghttp2_session_server_new2(&session, &callbacks, NULL, option);
6451 
6452   nghttp2_option_del(option);
6453 
6454   stream = open_recv_stream(session, 1);
6455   stream->local_window_size = NGHTTP2_INITIAL_WINDOW_SIZE + 100;
6456   stream->recv_window_size = 32768;
6457 
6458   assert_int(0, ==, nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, iv, 1));
6459   assert_int(0, ==, nghttp2_session_send(session));
6460   assert_int(0, ==,
6461              nghttp2_session_on_settings_received(session, &ack_frame, 0));
6462 
6463   stream = nghttp2_session_get_stream(session, 1);
6464 
6465   assert_int32(32768, ==, stream->recv_window_size);
6466   assert_int32(16 * 1024 + 100, ==, stream->local_window_size);
6467   /* Check that we can handle the case where local_window_size <
6468      recv_window_size */
6469   assert_int32(0, ==, nghttp2_session_get_stream_local_window_size(session, 1));
6470 
6471   nghttp2_session_del(session);
6472 
6473   /* Check overflow case */
6474   iv[0].value = 128 * 1024;
6475   nghttp2_session_server_new(&session, &callbacks, NULL);
6476   stream = open_recv_stream(session, 1);
6477   stream->local_window_size = NGHTTP2_MAX_WINDOW_SIZE;
6478 
6479   assert_int(0, ==, nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, iv, 1));
6480   assert_int(0, ==, nghttp2_session_send(session));
6481   assert_int(0, ==,
6482              nghttp2_session_on_settings_received(session, &ack_frame, 0));
6483 
6484   item = nghttp2_session_get_next_ob_item(session);
6485   assert_uint8(NGHTTP2_RST_STREAM, ==, item->frame.hd.type);
6486   assert_uint32(NGHTTP2_FLOW_CONTROL_ERROR, ==,
6487                 item->frame.rst_stream.error_code);
6488 
6489   nghttp2_session_del(session);
6490   nghttp2_frame_settings_free(&ack_frame.settings, mem);
6491 }
6492 
test_nghttp2_submit_settings_multiple_times(void)6493 void test_nghttp2_submit_settings_multiple_times(void) {
6494   nghttp2_session *session;
6495   nghttp2_session_callbacks callbacks;
6496   nghttp2_settings_entry iv[4];
6497   nghttp2_frame frame;
6498   nghttp2_inflight_settings *inflight_settings;
6499 
6500   memset(&callbacks, 0, sizeof(callbacks));
6501   callbacks.send_callback2 = null_send_callback;
6502 
6503   nghttp2_session_client_new(&session, &callbacks, NULL);
6504 
6505   /* first SETTINGS */
6506   iv[0].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS;
6507   iv[0].value = 100;
6508 
6509   iv[1].settings_id = NGHTTP2_SETTINGS_ENABLE_PUSH;
6510   iv[1].value = 0;
6511 
6512   assert_int(0, ==, nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, iv, 2));
6513 
6514   inflight_settings = session->inflight_settings_head;
6515 
6516   assert_not_null(inflight_settings);
6517   assert_int32(NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, ==,
6518                inflight_settings->iv[0].settings_id);
6519   assert_uint32(100, ==, inflight_settings->iv[0].value);
6520   assert_size(2, ==, inflight_settings->niv);
6521   assert_null(inflight_settings->next);
6522 
6523   assert_uint32(100, ==, session->pending_local_max_concurrent_stream);
6524   assert_uint8(0, ==, session->pending_enable_push);
6525 
6526   /* second SETTINGS */
6527   iv[0].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS;
6528   iv[0].value = 99;
6529 
6530   assert_int(0, ==, nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, iv, 1));
6531 
6532   inflight_settings = session->inflight_settings_head->next;
6533 
6534   assert_not_null(inflight_settings);
6535   assert_int32(NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, ==,
6536                inflight_settings->iv[0].settings_id);
6537   assert_uint32(99, ==, inflight_settings->iv[0].value);
6538   assert_size(1, ==, inflight_settings->niv);
6539   assert_null(inflight_settings->next);
6540 
6541   assert_uint32(99, ==, session->pending_local_max_concurrent_stream);
6542   assert_uint8(0, ==, session->pending_enable_push);
6543 
6544   nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_ACK, NULL, 0);
6545 
6546   /* receive SETTINGS ACK */
6547   assert_int(0, ==, nghttp2_session_on_settings_received(session, &frame, 0));
6548 
6549   inflight_settings = session->inflight_settings_head;
6550 
6551   /* first inflight SETTINGS was removed */
6552   assert_not_null(inflight_settings);
6553   assert_int32(NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, ==,
6554                inflight_settings->iv[0].settings_id);
6555   assert_uint32(99, ==, inflight_settings->iv[0].value);
6556   assert_size(1, ==, inflight_settings->niv);
6557   assert_null(inflight_settings->next);
6558 
6559   assert_uint32(100, ==, session->local_settings.max_concurrent_streams);
6560 
6561   /* receive SETTINGS ACK again */
6562   assert_int(0, ==, nghttp2_session_on_settings_received(session, &frame, 0));
6563 
6564   assert_null(session->inflight_settings_head);
6565   assert_uint32(99, ==, session->local_settings.max_concurrent_streams);
6566 
6567   nghttp2_session_del(session);
6568 }
6569 
test_nghttp2_submit_push_promise(void)6570 void test_nghttp2_submit_push_promise(void) {
6571   nghttp2_session *session;
6572   nghttp2_session_callbacks callbacks;
6573   my_user_data ud;
6574   nghttp2_stream *stream;
6575 
6576   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6577   callbacks.send_callback2 = null_send_callback;
6578   callbacks.on_frame_send_callback = on_frame_send_callback;
6579   callbacks.on_frame_not_send_callback = on_frame_not_send_callback;
6580 
6581   assert_int(0, ==, nghttp2_session_server_new(&session, &callbacks, &ud));
6582   open_recv_stream(session, 1);
6583   assert_int32(2, ==,
6584                nghttp2_submit_push_promise(session, NGHTTP2_FLAG_NONE, 1, reqnv,
6585                                            ARRLEN(reqnv), &ud));
6586 
6587   stream = nghttp2_session_get_stream(session, 2);
6588 
6589   assert_not_null(stream);
6590   assert_enum(nghttp2_stream_state, NGHTTP2_STREAM_RESERVED, ==, stream->state);
6591   assert_ptr_equal(&ud, nghttp2_session_get_stream_user_data(session, 2));
6592 
6593   ud.frame_send_cb_called = 0;
6594   ud.sent_frame_type = 0;
6595 
6596   assert_int(0, ==, nghttp2_session_send(session));
6597   assert_int(1, ==, ud.frame_send_cb_called);
6598   assert_uint8(NGHTTP2_PUSH_PROMISE, ==, ud.sent_frame_type);
6599 
6600   stream = nghttp2_session_get_stream(session, 2);
6601 
6602   assert_enum(nghttp2_stream_state, NGHTTP2_STREAM_RESERVED, ==, stream->state);
6603   assert_ptr_equal(&ud, nghttp2_session_get_stream_user_data(session, 2));
6604 
6605   /* submit PUSH_PROMISE while associated stream is not opened */
6606   assert_int32(NGHTTP2_ERR_STREAM_CLOSED, ==,
6607                nghttp2_submit_push_promise(session, NGHTTP2_FLAG_NONE, 3, reqnv,
6608                                            ARRLEN(reqnv), NULL));
6609 
6610   /* Stream ID <= 0 is error */
6611   assert_int32(NGHTTP2_ERR_INVALID_ARGUMENT, ==,
6612                nghttp2_submit_push_promise(session, NGHTTP2_FLAG_NONE, 0, reqnv,
6613                                            ARRLEN(reqnv), NULL));
6614 
6615   nghttp2_session_del(session);
6616 }
6617 
test_nghttp2_submit_window_update(void)6618 void test_nghttp2_submit_window_update(void) {
6619   nghttp2_session *session;
6620   nghttp2_session_callbacks callbacks;
6621   my_user_data ud;
6622   nghttp2_outbound_item *item;
6623   nghttp2_stream *stream;
6624 
6625   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6626   callbacks.send_callback2 = null_send_callback;
6627 
6628   nghttp2_session_client_new(&session, &callbacks, &ud);
6629   stream = open_recv_stream(session, 2);
6630   stream->recv_window_size = 4096;
6631 
6632   assert_int(0, ==,
6633              nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 2, 1024));
6634   item = nghttp2_session_get_next_ob_item(session);
6635   assert_uint8(NGHTTP2_WINDOW_UPDATE, ==, item->frame.hd.type);
6636   assert_int32(1024, ==, item->frame.window_update.window_size_increment);
6637   assert_int(0, ==, nghttp2_session_send(session));
6638   assert_int32(3072, ==, stream->recv_window_size);
6639 
6640   assert_int(0, ==,
6641              nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 2, 4096));
6642   item = nghttp2_session_get_next_ob_item(session);
6643   assert_uint8(NGHTTP2_WINDOW_UPDATE, ==, item->frame.hd.type);
6644   assert_int32(4096, ==, item->frame.window_update.window_size_increment);
6645   assert_int(0, ==, nghttp2_session_send(session));
6646   assert_int32(0, ==, stream->recv_window_size);
6647 
6648   assert_int(0, ==,
6649              nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 2, 4096));
6650   item = nghttp2_session_get_next_ob_item(session);
6651   assert_uint8(NGHTTP2_WINDOW_UPDATE, ==, item->frame.hd.type);
6652   assert_int32(4096, ==, item->frame.window_update.window_size_increment);
6653   assert_int(0, ==, nghttp2_session_send(session));
6654   assert_int32(0, ==, stream->recv_window_size);
6655 
6656   assert_int(0, ==,
6657              nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 2, 0));
6658   /* It is ok if stream is closed or does not exist at the call
6659      time */
6660   assert_int(0, ==,
6661              nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 4, 4096));
6662 
6663   nghttp2_session_del(session);
6664 }
6665 
test_nghttp2_submit_window_update_local_window_size(void)6666 void test_nghttp2_submit_window_update_local_window_size(void) {
6667   nghttp2_session *session;
6668   nghttp2_session_callbacks callbacks;
6669   nghttp2_outbound_item *item;
6670   nghttp2_stream *stream;
6671 
6672   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6673   callbacks.send_callback2 = null_send_callback;
6674 
6675   nghttp2_session_client_new(&session, &callbacks, NULL);
6676   stream = open_recv_stream(session, 2);
6677   stream->recv_window_size = 4096;
6678 
6679   assert_int(0, ==,
6680              nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 2,
6681                                           stream->recv_window_size + 1));
6682   assert_int32(NGHTTP2_INITIAL_WINDOW_SIZE + 1, ==, stream->local_window_size);
6683   assert_int32(0, ==, stream->recv_window_size);
6684   item = nghttp2_session_get_next_ob_item(session);
6685   assert_uint8(NGHTTP2_WINDOW_UPDATE, ==, item->frame.hd.type);
6686   assert_int32(4097, ==, item->frame.window_update.window_size_increment);
6687 
6688   assert_int(0, ==, nghttp2_session_send(session));
6689 
6690   /* Let's decrement local window size */
6691   stream->recv_window_size = 4096;
6692   assert_int(0, ==,
6693              nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 2,
6694                                           -stream->local_window_size / 2));
6695   assert_int32(32768, ==, stream->local_window_size);
6696   assert_int32(-28672, ==, stream->recv_window_size);
6697   assert_int32(32768, ==, stream->recv_reduction);
6698 
6699   item = nghttp2_session_get_next_ob_item(session);
6700   assert_null(item);
6701 
6702   /* Increase local window size */
6703   assert_int(
6704     0, ==, nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 2, 16384));
6705   assert_int32(49152, ==, stream->local_window_size);
6706   assert_int32(-12288, ==, stream->recv_window_size);
6707   assert_int32(16384, ==, stream->recv_reduction);
6708   assert_null(nghttp2_session_get_next_ob_item(session));
6709 
6710   assert_int(NGHTTP2_ERR_FLOW_CONTROL, ==,
6711              nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 2,
6712                                           NGHTTP2_MAX_WINDOW_SIZE));
6713 
6714   assert_int(0, ==, nghttp2_session_send(session));
6715 
6716   /* Check connection-level flow control */
6717   session->recv_window_size = 4096;
6718   assert_int(0, ==,
6719              nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 0,
6720                                           session->recv_window_size + 1));
6721   assert_int32(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE + 1, ==,
6722                session->local_window_size);
6723   assert_int32(0, ==, session->recv_window_size);
6724   item = nghttp2_session_get_next_ob_item(session);
6725   assert_uint8(NGHTTP2_WINDOW_UPDATE, ==, item->frame.hd.type);
6726   assert_int32(4097, ==, item->frame.window_update.window_size_increment);
6727 
6728   assert_int(0, ==, nghttp2_session_send(session));
6729 
6730   /* Go decrement part */
6731   session->recv_window_size = 4096;
6732   assert_int(0, ==,
6733              nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 0,
6734                                           -session->local_window_size / 2));
6735   assert_int32(32768, ==, session->local_window_size);
6736   assert_int32(-28672, ==, session->recv_window_size);
6737   assert_int32(32768, ==, session->recv_reduction);
6738   item = nghttp2_session_get_next_ob_item(session);
6739   assert_null(item);
6740 
6741   /* Increase local window size */
6742   assert_int(
6743     0, ==, nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 0, 16384));
6744   assert_int32(49152, ==, session->local_window_size);
6745   assert_int32(-12288, ==, session->recv_window_size);
6746   assert_int32(16384, ==, session->recv_reduction);
6747   assert_null(nghttp2_session_get_next_ob_item(session));
6748 
6749   assert_int(NGHTTP2_ERR_FLOW_CONTROL, ==,
6750              nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 0,
6751                                           NGHTTP2_MAX_WINDOW_SIZE));
6752 
6753   nghttp2_session_del(session);
6754 }
6755 
test_nghttp2_submit_shutdown_notice(void)6756 void test_nghttp2_submit_shutdown_notice(void) {
6757   nghttp2_session *session;
6758   nghttp2_session_callbacks callbacks;
6759   my_user_data ud;
6760 
6761   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6762   callbacks.send_callback2 = null_send_callback;
6763   callbacks.on_frame_send_callback = on_frame_send_callback;
6764   callbacks.on_frame_not_send_callback = on_frame_not_send_callback;
6765 
6766   nghttp2_session_server_new(&session, &callbacks, &ud);
6767 
6768   assert_int(0, ==, nghttp2_submit_shutdown_notice(session));
6769 
6770   ud.frame_send_cb_called = 0;
6771 
6772   nghttp2_session_send(session);
6773 
6774   assert_int(1, ==, ud.frame_send_cb_called);
6775   assert_uint8(NGHTTP2_GOAWAY, ==, ud.sent_frame_type);
6776   assert_int32((1u << 31) - 1, ==, session->local_last_stream_id);
6777 
6778   /* After another GOAWAY, nghttp2_submit_shutdown_notice() is
6779      noop. */
6780   assert_int(0, ==,
6781              nghttp2_session_terminate_session(session, NGHTTP2_NO_ERROR));
6782 
6783   ud.frame_send_cb_called = 0;
6784 
6785   nghttp2_session_send(session);
6786 
6787   assert_int(1, ==, ud.frame_send_cb_called);
6788   assert_uint8(NGHTTP2_GOAWAY, ==, ud.sent_frame_type);
6789   assert_int32(0, ==, session->local_last_stream_id);
6790 
6791   assert_int(0, ==, nghttp2_submit_shutdown_notice(session));
6792 
6793   ud.frame_send_cb_called = 0;
6794   ud.frame_not_send_cb_called = 0;
6795 
6796   nghttp2_session_send(session);
6797 
6798   assert_int(0, ==, ud.frame_send_cb_called);
6799   assert_int(0, ==, ud.frame_not_send_cb_called);
6800 
6801   nghttp2_session_del(session);
6802 
6803   /* Using nghttp2_submit_shutdown_notice() with client side session
6804      is error */
6805   nghttp2_session_client_new(&session, &callbacks, NULL);
6806 
6807   assert_int(NGHTTP2_ERR_INVALID_STATE, ==,
6808              nghttp2_submit_shutdown_notice(session));
6809 
6810   nghttp2_session_del(session);
6811 }
6812 
test_nghttp2_submit_invalid_nv(void)6813 void test_nghttp2_submit_invalid_nv(void) {
6814   nghttp2_session *session;
6815   nghttp2_session_callbacks callbacks;
6816   nghttp2_nv empty_name_nv[] = {MAKE_NV("Version", "HTTP/1.1"),
6817                                 MAKE_NV("", "empty name")};
6818 
6819   /* Now invalid header name/value pair in HTTP/1.1 is accepted in
6820      nghttp2 */
6821 
6822   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6823 
6824   assert_int(0, ==, nghttp2_session_server_new(&session, &callbacks, NULL));
6825 
6826   /* nghttp2_submit_response */
6827   assert_int(0, ==,
6828              nghttp2_submit_response2(session, 2, empty_name_nv,
6829                                       ARRLEN(empty_name_nv), NULL));
6830 
6831   /* nghttp2_submit_push_promise */
6832   open_recv_stream(session, 1);
6833 
6834   assert_int32(0, <,
6835                nghttp2_submit_push_promise(session, NGHTTP2_FLAG_NONE, 1,
6836                                            empty_name_nv, ARRLEN(empty_name_nv),
6837                                            NULL));
6838 
6839   nghttp2_session_del(session);
6840 
6841   assert_int(0, ==, nghttp2_session_client_new(&session, &callbacks, NULL));
6842 
6843   /* nghttp2_submit_request */
6844   assert_int32(0, <,
6845                nghttp2_submit_request2(session, NULL, empty_name_nv,
6846                                        ARRLEN(empty_name_nv), NULL, NULL));
6847 
6848   /* nghttp2_submit_headers */
6849   assert_int32(0, <,
6850                nghttp2_submit_headers(session, NGHTTP2_FLAG_NONE, -1, NULL,
6851                                       empty_name_nv, ARRLEN(empty_name_nv),
6852                                       NULL));
6853 
6854   nghttp2_session_del(session);
6855 }
6856 
test_nghttp2_submit_extension(void)6857 void test_nghttp2_submit_extension(void) {
6858   nghttp2_session *session;
6859   nghttp2_session_callbacks callbacks;
6860   my_user_data ud;
6861   accumulator acc;
6862   nghttp2_mem *mem;
6863   const char data[] = "Hello World!";
6864   size_t len;
6865   int32_t stream_id;
6866   int rv;
6867 
6868   mem = nghttp2_mem_default();
6869 
6870   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6871 
6872   callbacks.pack_extension_callback2 = pack_extension_callback;
6873   callbacks.send_callback2 = accumulator_send_callback;
6874 
6875   nghttp2_buf_init2(&ud.scratchbuf, 4096, mem);
6876 
6877   nghttp2_session_client_new(&session, &callbacks, &ud);
6878 
6879   ud.scratchbuf.last = nghttp2_cpymem(ud.scratchbuf.last, data, sizeof(data));
6880   ud.acc = &acc;
6881 
6882   rv = nghttp2_submit_extension(session, 211, 0x01, 3, &ud.scratchbuf);
6883 
6884   assert_int(0, ==, rv);
6885 
6886   acc.length = 0;
6887 
6888   rv = nghttp2_session_send(session);
6889 
6890   assert_int(0, ==, rv);
6891   assert_size(NGHTTP2_FRAME_HDLEN + sizeof(data), ==, acc.length);
6892 
6893   len = nghttp2_get_uint32(acc.buf) >> 8;
6894 
6895   assert_size(sizeof(data), ==, len);
6896   assert_uint8(211, ==, acc.buf[3]);
6897   assert_uint8(0x01, ==, acc.buf[4]);
6898 
6899   stream_id = (int32_t)nghttp2_get_uint32(acc.buf + 5);
6900 
6901   assert_int32(3, ==, stream_id);
6902   assert_memory_equal(sizeof(data), data, &acc.buf[NGHTTP2_FRAME_HDLEN]);
6903 
6904   nghttp2_session_del(session);
6905 
6906   /* submitting standard HTTP/2 frame is error */
6907   nghttp2_session_server_new(&session, &callbacks, &ud);
6908 
6909   rv = nghttp2_submit_extension(session, NGHTTP2_GOAWAY, NGHTTP2_FLAG_NONE, 0,
6910                                 NULL);
6911 
6912   assert_int(NGHTTP2_ERR_INVALID_ARGUMENT, ==, rv);
6913 
6914   nghttp2_session_del(session);
6915   nghttp2_buf_free(&ud.scratchbuf, mem);
6916 }
6917 
test_nghttp2_submit_altsvc(void)6918 void test_nghttp2_submit_altsvc(void) {
6919   nghttp2_session *session;
6920   nghttp2_session_callbacks callbacks;
6921   my_user_data ud;
6922   int rv;
6923   nghttp2_ssize len;
6924   const uint8_t *data;
6925   nghttp2_frame_hd hd;
6926   size_t origin_len;
6927   const uint8_t origin[] = "nghttp2.org";
6928   const uint8_t field_value[] = "h2=\":443\"";
6929 
6930   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6931 
6932   nghttp2_session_server_new(&session, &callbacks, &ud);
6933 
6934   rv = nghttp2_submit_altsvc(session, NGHTTP2_FLAG_NONE, 0, origin,
6935                              sizeof(origin) - 1, field_value,
6936                              sizeof(field_value) - 1);
6937 
6938   assert_int(0, ==, rv);
6939 
6940   ud.frame_send_cb_called = 0;
6941 
6942   len = nghttp2_session_mem_send2(session, &data);
6943 
6944   assert_ptrdiff(NGHTTP2_FRAME_HDLEN + 2 + sizeof(origin) - 1 +
6945                    sizeof(field_value) - 1,
6946                  ==, len);
6947 
6948   nghttp2_frame_unpack_frame_hd(&hd, data);
6949 
6950   assert_size(2 + sizeof(origin) - 1 + sizeof(field_value) - 1, ==, hd.length);
6951   assert_uint8(NGHTTP2_ALTSVC, ==, hd.type);
6952   assert_uint8(NGHTTP2_FLAG_NONE, ==, hd.flags);
6953 
6954   origin_len = nghttp2_get_uint16(data + NGHTTP2_FRAME_HDLEN);
6955 
6956   assert_size(sizeof(origin) - 1, ==, origin_len);
6957   assert_memory_equal(sizeof(origin) - 1, origin,
6958                       data + NGHTTP2_FRAME_HDLEN + 2);
6959   assert_memory_equal(hd.length - (sizeof(origin) - 1) - 2, field_value,
6960                       data + NGHTTP2_FRAME_HDLEN + 2 + sizeof(origin) - 1);
6961 
6962   /* submitting empty origin with stream_id == 0 is error */
6963   rv = nghttp2_submit_altsvc(session, NGHTTP2_FLAG_NONE, 0, NULL, 0,
6964                              field_value, sizeof(field_value) - 1);
6965 
6966   assert_int(NGHTTP2_ERR_INVALID_ARGUMENT, ==, rv);
6967 
6968   /* submitting non-empty origin with stream_id != 0 is error */
6969   rv = nghttp2_submit_altsvc(session, NGHTTP2_FLAG_NONE, 1, origin,
6970                              sizeof(origin) - 1, field_value,
6971                              sizeof(field_value) - 1);
6972 
6973   assert_int(NGHTTP2_ERR_INVALID_ARGUMENT, ==, rv);
6974 
6975   nghttp2_session_del(session);
6976 
6977   /* submitting from client side session is error */
6978   nghttp2_session_client_new(&session, &callbacks, NULL);
6979 
6980   rv = nghttp2_submit_altsvc(session, NGHTTP2_FLAG_NONE, 0, origin,
6981                              sizeof(origin) - 1, field_value,
6982                              sizeof(field_value) - 1);
6983 
6984   assert_int(NGHTTP2_ERR_INVALID_STATE, ==, rv);
6985 
6986   nghttp2_session_del(session);
6987 }
6988 
test_nghttp2_submit_origin(void)6989 void test_nghttp2_submit_origin(void) {
6990   nghttp2_session *session;
6991   nghttp2_session_callbacks callbacks;
6992   my_user_data ud;
6993   int rv;
6994   nghttp2_ssize len;
6995   const uint8_t *data;
6996   static const uint8_t nghttp2[] = "https://nghttp2.org";
6997   static const uint8_t examples[] = "https://examples.com";
6998   static const nghttp2_origin_entry ov[] = {
6999     {
7000       (uint8_t *)nghttp2,
7001       sizeof(nghttp2) - 1,
7002     },
7003     {
7004       (uint8_t *)examples,
7005       sizeof(examples) - 1,
7006     },
7007   };
7008   nghttp2_frame frame;
7009   nghttp2_ext_origin origin;
7010   nghttp2_mem *mem;
7011 
7012   mem = nghttp2_mem_default();
7013 
7014   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7015   callbacks.on_frame_send_callback = on_frame_send_callback;
7016 
7017   frame.ext.payload = &origin;
7018 
7019   nghttp2_session_server_new(&session, &callbacks, &ud);
7020 
7021   rv = nghttp2_submit_origin(session, NGHTTP2_FLAG_NONE, ov, 2);
7022 
7023   assert_int(0, ==, rv);
7024 
7025   ud.frame_send_cb_called = 0;
7026   len = nghttp2_session_mem_send2(session, &data);
7027 
7028   assert_ptrdiff(0, <, len);
7029   assert_int(1, ==, ud.frame_send_cb_called);
7030 
7031   nghttp2_frame_unpack_frame_hd(&frame.hd, data);
7032   rv =
7033     nghttp2_frame_unpack_origin_payload(&frame.ext, data + NGHTTP2_FRAME_HDLEN,
7034                                         (size_t)len - NGHTTP2_FRAME_HDLEN, mem);
7035 
7036   assert_int(0, ==, rv);
7037   assert_int32(0, ==, frame.hd.stream_id);
7038   assert_uint8(NGHTTP2_ORIGIN, ==, frame.hd.type);
7039   assert_size(2, ==, origin.nov);
7040   assert_memory_equal(sizeof(nghttp2) - 1, nghttp2, origin.ov[0].origin);
7041   assert_size(sizeof(nghttp2) - 1, ==, origin.ov[0].origin_len);
7042   assert_memory_equal(sizeof(examples) - 1, examples, origin.ov[1].origin);
7043   assert_size(sizeof(examples) - 1, ==, origin.ov[1].origin_len);
7044 
7045   nghttp2_frame_origin_free(&frame.ext, mem);
7046 
7047   nghttp2_session_del(session);
7048 
7049   /* Submitting ORIGIN frame from client session is error */
7050   nghttp2_session_client_new(&session, &callbacks, NULL);
7051 
7052   rv = nghttp2_submit_origin(session, NGHTTP2_FLAG_NONE, ov, 1);
7053 
7054   assert_int(NGHTTP2_ERR_INVALID_STATE, ==, rv);
7055 
7056   nghttp2_session_del(session);
7057 
7058   /* Submitting empty ORIGIN frame */
7059   nghttp2_session_server_new(&session, &callbacks, &ud);
7060 
7061   rv = nghttp2_submit_origin(session, NGHTTP2_FLAG_NONE, NULL, 0);
7062 
7063   assert_int(0, ==, rv);
7064 
7065   ud.frame_send_cb_called = 0;
7066   len = nghttp2_session_mem_send2(session, &data);
7067 
7068   assert_ptrdiff(NGHTTP2_FRAME_HDLEN, ==, len);
7069   assert_int(1, ==, ud.frame_send_cb_called);
7070 
7071   nghttp2_frame_unpack_frame_hd(&frame.hd, data);
7072 
7073   assert_uint8(NGHTTP2_ORIGIN, ==, frame.hd.type);
7074 
7075   nghttp2_session_del(session);
7076 }
7077 
test_nghttp2_submit_priority_update(void)7078 void test_nghttp2_submit_priority_update(void) {
7079   nghttp2_session *session;
7080   nghttp2_session_callbacks callbacks;
7081   const uint8_t field_value[] = "i";
7082   my_user_data ud;
7083   const uint8_t *data;
7084   int rv;
7085   nghttp2_frame frame;
7086   nghttp2_ext_priority_update priority_update;
7087   nghttp2_ssize len;
7088   int32_t stream_id;
7089 
7090   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7091   callbacks.on_frame_send_callback = on_frame_send_callback;
7092 
7093   nghttp2_session_client_new(&session, &callbacks, &ud);
7094 
7095   session->pending_no_rfc7540_priorities = 1;
7096 
7097   stream_id =
7098     nghttp2_submit_request2(session, NULL, reqnv, ARRLEN(reqnv), NULL, NULL);
7099 
7100   assert_int32(1, ==, stream_id);
7101 
7102   len = nghttp2_session_mem_send2(session, &data);
7103 
7104   assert_ptrdiff(0, <, len);
7105 
7106   rv = nghttp2_submit_priority_update(session, NGHTTP2_FLAG_NONE, stream_id,
7107                                       field_value, sizeof(field_value) - 1);
7108 
7109   assert_int(0, ==, rv);
7110 
7111   frame.ext.payload = &priority_update;
7112 
7113   ud.frame_send_cb_called = 0;
7114   len = nghttp2_session_mem_send2(session, &data);
7115 
7116   assert_ptrdiff(0, <, len);
7117   assert_int(1, ==, ud.frame_send_cb_called);
7118 
7119   nghttp2_frame_unpack_frame_hd(&frame.hd, data);
7120   nghttp2_frame_unpack_priority_update_payload(
7121     &frame.ext, (uint8_t *)(data + NGHTTP2_FRAME_HDLEN),
7122     (size_t)len - NGHTTP2_FRAME_HDLEN);
7123 
7124   assert_int32(0, ==, frame.hd.stream_id);
7125   assert_uint8(NGHTTP2_PRIORITY_UPDATE, ==, frame.hd.type);
7126   assert_int32(stream_id, ==, priority_update.stream_id);
7127   assert_size(sizeof(field_value) - 1, ==, priority_update.field_value_len);
7128   assert_memory_equal(sizeof(field_value) - 1, field_value,
7129                       priority_update.field_value);
7130 
7131   nghttp2_session_del(session);
7132 
7133   /* Submitting PRIORITY_UPDATE frame from server session is error */
7134   nghttp2_session_server_new(&session, &callbacks, &ud);
7135 
7136   open_recv_stream(session, 1);
7137 
7138   rv = nghttp2_submit_priority_update(session, NGHTTP2_FLAG_NONE, 1,
7139                                       field_value, sizeof(field_value) - 1);
7140 
7141   assert_int(NGHTTP2_ERR_INVALID_STATE, ==, rv);
7142 
7143   nghttp2_session_del(session);
7144 
7145   /* Submitting PRIORITY_UPDATE with empty field_value */
7146   nghttp2_session_client_new(&session, &callbacks, &ud);
7147 
7148   stream_id =
7149     nghttp2_submit_request2(session, NULL, reqnv, ARRLEN(reqnv), NULL, NULL);
7150 
7151   assert_int32(1, ==, stream_id);
7152 
7153   len = nghttp2_session_mem_send2(session, &data);
7154 
7155   assert_ptrdiff(0, <, len);
7156 
7157   rv = nghttp2_submit_priority_update(session, NGHTTP2_FLAG_NONE, stream_id,
7158                                       NULL, 0);
7159 
7160   assert_int(0, ==, rv);
7161 
7162   frame.ext.payload = &priority_update;
7163 
7164   len = nghttp2_session_mem_send2(session, &data);
7165 
7166   assert_ptrdiff(0, <, len);
7167 
7168   nghttp2_frame_unpack_frame_hd(&frame.hd, data);
7169   nghttp2_frame_unpack_priority_update_payload(
7170     &frame.ext, (uint8_t *)(data + NGHTTP2_FRAME_HDLEN),
7171     (size_t)len - NGHTTP2_FRAME_HDLEN);
7172 
7173   assert_int32(0, ==, frame.hd.stream_id);
7174   assert_uint8(NGHTTP2_PRIORITY_UPDATE, ==, frame.hd.type);
7175   assert_int32(stream_id, ==, priority_update.stream_id);
7176   assert_size(0, ==, priority_update.field_value_len);
7177   assert_null(priority_update.field_value);
7178 
7179   nghttp2_session_del(session);
7180 }
7181 
test_nghttp2_submit_rst_stream(void)7182 void test_nghttp2_submit_rst_stream(void) {
7183   nghttp2_session *session;
7184   nghttp2_session_callbacks callbacks;
7185   nghttp2_outbound_item *item;
7186   int rv;
7187   int32_t stream_id;
7188 
7189   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7190 
7191   /* Sending RST_STREAM to idle stream (local) is ignored */
7192   nghttp2_session_client_new(&session, &callbacks, NULL);
7193 
7194   rv =
7195     nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, 1, NGHTTP2_NO_ERROR);
7196 
7197   assert_int(0, ==, rv);
7198 
7199   item = nghttp2_outbound_queue_top(&session->ob_reg);
7200 
7201   assert_null(item);
7202 
7203   nghttp2_session_del(session);
7204 
7205   /* Sending RST_STREAM to idle stream (remote) is ignored */
7206   nghttp2_session_client_new(&session, &callbacks, NULL);
7207 
7208   rv =
7209     nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, 2, NGHTTP2_NO_ERROR);
7210 
7211   assert_int(0, ==, rv);
7212 
7213   item = nghttp2_outbound_queue_top(&session->ob_reg);
7214 
7215   assert_null(item);
7216 
7217   nghttp2_session_del(session);
7218 
7219   /* Sending RST_STREAM to non-idle stream (local) */
7220   nghttp2_session_client_new(&session, &callbacks, NULL);
7221 
7222   open_sent_stream(session, 1);
7223 
7224   rv =
7225     nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, 1, NGHTTP2_NO_ERROR);
7226 
7227   assert_int(0, ==, rv);
7228 
7229   item = nghttp2_outbound_queue_top(&session->ob_reg);
7230 
7231   assert_not_null(item);
7232   assert_uint8(NGHTTP2_RST_STREAM, ==, item->frame.hd.type);
7233   assert_int32(1, ==, item->frame.hd.stream_id);
7234 
7235   nghttp2_session_del(session);
7236 
7237   /* Sending RST_STREAM to non-idle stream (remote) */
7238   nghttp2_session_client_new(&session, &callbacks, NULL);
7239 
7240   open_recv_stream(session, 2);
7241 
7242   rv =
7243     nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, 2, NGHTTP2_NO_ERROR);
7244 
7245   assert_int(0, ==, rv);
7246 
7247   item = nghttp2_outbound_queue_top(&session->ob_reg);
7248 
7249   assert_not_null(item);
7250   assert_uint8(NGHTTP2_RST_STREAM, ==, item->frame.hd.type);
7251   assert_int32(2, ==, item->frame.hd.stream_id);
7252 
7253   nghttp2_session_del(session);
7254 
7255   /* Sending RST_STREAM to pending stream */
7256   nghttp2_session_client_new(&session, &callbacks, NULL);
7257 
7258   stream_id =
7259     nghttp2_submit_request2(session, NULL, reqnv, ARRLEN(reqnv), NULL, NULL);
7260 
7261   assert_int32(0, <, stream_id);
7262 
7263   item = nghttp2_outbound_queue_top(&session->ob_syn);
7264 
7265   assert_not_null(item);
7266   assert_uint8(NGHTTP2_HEADERS, ==, item->frame.hd.type);
7267   assert_false(item->aux_data.headers.canceled);
7268 
7269   rv = nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, stream_id,
7270                                  NGHTTP2_NO_ERROR);
7271 
7272   assert_int(0, ==, rv);
7273 
7274   item = nghttp2_outbound_queue_top(&session->ob_syn);
7275 
7276   assert_not_null(item);
7277   assert_uint8(NGHTTP2_HEADERS, ==, item->frame.hd.type);
7278   assert_true(item->aux_data.headers.canceled);
7279 
7280   nghttp2_session_del(session);
7281 }
7282 
test_nghttp2_session_open_stream(void)7283 void test_nghttp2_session_open_stream(void) {
7284   nghttp2_session *session;
7285   nghttp2_session_callbacks callbacks;
7286   nghttp2_stream *stream;
7287   nghttp2_priority_spec pri_spec;
7288 
7289   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7290   nghttp2_session_server_new(&session, &callbacks, NULL);
7291 
7292   nghttp2_priority_spec_init(&pri_spec, 0, 245, 0);
7293 
7294   stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
7295                                        &pri_spec, NGHTTP2_STREAM_OPENED, NULL);
7296   assert_size(1, ==, session->num_incoming_streams);
7297   assert_size(0, ==, session->num_outgoing_streams);
7298   assert_enum(nghttp2_stream_state, NGHTTP2_STREAM_OPENED, ==, stream->state);
7299   assert_int32(245, ==, stream->weight);
7300   assert_ptr_equal(&session->root, stream->dep_prev);
7301   assert_uint8(NGHTTP2_SHUT_NONE, ==, stream->shut_flags);
7302 
7303   stream = nghttp2_session_open_stream(session, 2, NGHTTP2_STREAM_FLAG_NONE,
7304                                        &pri_spec_default,
7305                                        NGHTTP2_STREAM_OPENING, NULL);
7306   assert_size(1, ==, session->num_incoming_streams);
7307   assert_size(1, ==, session->num_outgoing_streams);
7308   assert_ptr_equal(&session->root, stream->dep_prev);
7309   assert_int32(NGHTTP2_DEFAULT_WEIGHT, ==, stream->weight);
7310   assert_uint8(NGHTTP2_SHUT_NONE, ==, stream->shut_flags);
7311 
7312   stream = nghttp2_session_open_stream(session, 4, NGHTTP2_STREAM_FLAG_NONE,
7313                                        &pri_spec_default,
7314                                        NGHTTP2_STREAM_RESERVED, NULL);
7315   assert_size(1, ==, session->num_incoming_streams);
7316   assert_size(1, ==, session->num_outgoing_streams);
7317   assert_ptr_equal(&session->root, stream->dep_prev);
7318   assert_int32(NGHTTP2_DEFAULT_WEIGHT, ==, stream->weight);
7319   assert_uint8(NGHTTP2_SHUT_RD, ==, stream->shut_flags);
7320 
7321   nghttp2_priority_spec_init(&pri_spec, 1, 17, 1);
7322 
7323   stream = nghttp2_session_open_stream(session, 3, NGHTTP2_STREAM_FLAG_NONE,
7324                                        &pri_spec, NGHTTP2_STREAM_OPENED, NULL);
7325   assert_int32(17, ==, stream->weight);
7326   assert_int32(1, ==, stream->dep_prev->stream_id);
7327 
7328   /* Dependency to idle stream */
7329   nghttp2_priority_spec_init(&pri_spec, 1000000007, 240, 1);
7330 
7331   stream = nghttp2_session_open_stream(session, 5, NGHTTP2_STREAM_FLAG_NONE,
7332                                        &pri_spec, NGHTTP2_STREAM_OPENED, NULL);
7333   assert_int32(240, ==, stream->weight);
7334   assert_int32(1000000007, ==, stream->dep_prev->stream_id);
7335 
7336   stream = nghttp2_session_get_stream_raw(session, 1000000007);
7337 
7338   assert_int32(NGHTTP2_DEFAULT_WEIGHT, ==, stream->weight);
7339   assert_ptr_equal(&session->root, stream->dep_prev);
7340 
7341   /* Dependency to closed stream which is not in dependency tree */
7342   session->last_recv_stream_id = 7;
7343 
7344   nghttp2_priority_spec_init(&pri_spec, 7, 10, 0);
7345 
7346   stream = nghttp2_session_open_stream(session, 9, NGHTTP2_FLAG_NONE, &pri_spec,
7347                                        NGHTTP2_STREAM_OPENED, NULL);
7348 
7349   assert_int32(NGHTTP2_DEFAULT_WEIGHT, ==, stream->weight);
7350   assert_ptr_equal(&session->root, stream->dep_prev);
7351 
7352   nghttp2_session_del(session);
7353 
7354   nghttp2_session_client_new(&session, &callbacks, NULL);
7355   stream = nghttp2_session_open_stream(session, 4, NGHTTP2_STREAM_FLAG_NONE,
7356                                        &pri_spec_default,
7357                                        NGHTTP2_STREAM_RESERVED, NULL);
7358   assert_size(0, ==, session->num_incoming_streams);
7359   assert_size(0, ==, session->num_outgoing_streams);
7360   assert_ptr_equal(&session->root, stream->dep_prev);
7361   assert_int32(NGHTTP2_DEFAULT_WEIGHT, ==, stream->weight);
7362   assert_uint8(NGHTTP2_SHUT_WR, ==, stream->shut_flags);
7363 
7364   nghttp2_session_del(session);
7365 }
7366 
test_nghttp2_session_open_stream_with_idle_stream_dep(void)7367 void test_nghttp2_session_open_stream_with_idle_stream_dep(void) {
7368   nghttp2_session *session;
7369   nghttp2_session_callbacks callbacks;
7370   nghttp2_stream *stream;
7371   nghttp2_priority_spec pri_spec;
7372 
7373   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7374   nghttp2_session_server_new(&session, &callbacks, NULL);
7375 
7376   /* Dependency to idle stream */
7377   nghttp2_priority_spec_init(&pri_spec, 101, 245, 0);
7378 
7379   stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
7380                                        &pri_spec, NGHTTP2_STREAM_OPENED, NULL);
7381 
7382   assert_int32(245, ==, stream->weight);
7383   assert_int32(101, ==, stream->dep_prev->stream_id);
7384 
7385   stream = nghttp2_session_get_stream_raw(session, 101);
7386 
7387   assert_enum(nghttp2_stream_state, NGHTTP2_STREAM_IDLE, ==, stream->state);
7388   assert_int32(NGHTTP2_DEFAULT_WEIGHT, ==, stream->weight);
7389 
7390   nghttp2_priority_spec_init(&pri_spec, 211, 1, 0);
7391 
7392   /* stream 101 was already created as idle. */
7393   stream = nghttp2_session_open_stream(session, 101, NGHTTP2_STREAM_FLAG_NONE,
7394                                        &pri_spec, NGHTTP2_STREAM_OPENED, NULL);
7395 
7396   assert_int32(1, ==, stream->weight);
7397   assert_int32(211, ==, stream->dep_prev->stream_id);
7398 
7399   stream = nghttp2_session_get_stream_raw(session, 211);
7400 
7401   assert_enum(nghttp2_stream_state, NGHTTP2_STREAM_IDLE, ==, stream->state);
7402   assert_int32(NGHTTP2_DEFAULT_WEIGHT, ==, stream->weight);
7403 
7404   nghttp2_session_del(session);
7405 }
7406 
test_nghttp2_session_get_next_ob_item(void)7407 void test_nghttp2_session_get_next_ob_item(void) {
7408   nghttp2_session *session;
7409   nghttp2_session_callbacks callbacks;
7410   nghttp2_priority_spec pri_spec;
7411 
7412   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7413   callbacks.send_callback2 = null_send_callback;
7414 
7415   nghttp2_session_client_new(&session, &callbacks, NULL);
7416   session->remote_settings.max_concurrent_streams = 2;
7417 
7418   assert_null(nghttp2_session_get_next_ob_item(session));
7419   nghttp2_submit_ping(session, NGHTTP2_FLAG_NONE, NULL);
7420   assert_uint8(NGHTTP2_PING, ==,
7421                nghttp2_session_get_next_ob_item(session)->frame.hd.type);
7422 
7423   assert_int32(1, ==,
7424                nghttp2_submit_request2(session, NULL, NULL, 0, NULL, NULL));
7425   assert_uint8(NGHTTP2_PING, ==,
7426                nghttp2_session_get_next_ob_item(session)->frame.hd.type);
7427 
7428   assert_int(0, ==, nghttp2_session_send(session));
7429   assert_null(nghttp2_session_get_next_ob_item(session));
7430 
7431   /* Incoming stream does not affect the number of outgoing max
7432      concurrent streams. */
7433   open_recv_stream(session, 2);
7434 
7435   nghttp2_priority_spec_init(&pri_spec, 0, NGHTTP2_MAX_WEIGHT, 0);
7436 
7437   assert_int(3, ==,
7438              nghttp2_submit_request2(session, &pri_spec, NULL, 0, NULL, NULL));
7439   assert_uint8(NGHTTP2_HEADERS, ==,
7440                nghttp2_session_get_next_ob_item(session)->frame.hd.type);
7441   assert_int(0, ==, nghttp2_session_send(session));
7442 
7443   assert_int(5, ==,
7444              nghttp2_submit_request2(session, &pri_spec, NULL, 0, NULL, NULL));
7445   assert_null(nghttp2_session_get_next_ob_item(session));
7446 
7447   session->remote_settings.max_concurrent_streams = 3;
7448 
7449   assert_uint8(NGHTTP2_HEADERS, ==,
7450                nghttp2_session_get_next_ob_item(session)->frame.hd.type);
7451 
7452   nghttp2_session_del(session);
7453 
7454   /* Check that push reply HEADERS are queued into ob_ss_pq */
7455   nghttp2_session_server_new(&session, &callbacks, NULL);
7456   session->remote_settings.max_concurrent_streams = 0;
7457   open_sent_stream2(session, 2, NGHTTP2_STREAM_RESERVED);
7458   assert_int32(0, ==,
7459                nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, 2, NULL,
7460                                       NULL, 0, NULL));
7461   assert_null(nghttp2_session_get_next_ob_item(session));
7462   assert_size(1, ==, nghttp2_outbound_queue_size(&session->ob_syn));
7463   nghttp2_session_del(session);
7464 }
7465 
test_nghttp2_session_pop_next_ob_item(void)7466 void test_nghttp2_session_pop_next_ob_item(void) {
7467   nghttp2_session *session;
7468   nghttp2_session_callbacks callbacks;
7469   nghttp2_outbound_item *item;
7470   nghttp2_priority_spec pri_spec;
7471   nghttp2_mem *mem;
7472 
7473   mem = nghttp2_mem_default();
7474   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7475   callbacks.send_callback2 = null_send_callback;
7476 
7477   nghttp2_session_client_new(&session, &callbacks, NULL);
7478   session->remote_settings.max_concurrent_streams = 1;
7479 
7480   assert_null(nghttp2_session_pop_next_ob_item(session));
7481 
7482   nghttp2_submit_ping(session, NGHTTP2_FLAG_NONE, NULL);
7483 
7484   nghttp2_priority_spec_init(&pri_spec, 0, 254, 0);
7485 
7486   nghttp2_submit_request2(session, &pri_spec, NULL, 0, NULL, NULL);
7487 
7488   item = nghttp2_session_pop_next_ob_item(session);
7489   assert_uint8(NGHTTP2_PING, ==, item->frame.hd.type);
7490   nghttp2_outbound_item_free(item, mem);
7491   mem->free(item, NULL);
7492 
7493   item = nghttp2_session_pop_next_ob_item(session);
7494   assert_uint8(NGHTTP2_HEADERS, ==, item->frame.hd.type);
7495   nghttp2_outbound_item_free(item, mem);
7496   mem->free(item, NULL);
7497 
7498   assert_null(nghttp2_session_pop_next_ob_item(session));
7499 
7500   /* Incoming stream does not affect the number of outgoing max
7501      concurrent streams. */
7502   open_recv_stream(session, 4);
7503   /* In-flight outgoing stream */
7504   open_sent_stream(session, 1);
7505 
7506   nghttp2_priority_spec_init(&pri_spec, 0, NGHTTP2_MAX_WEIGHT, 0);
7507 
7508   nghttp2_submit_request2(session, &pri_spec, NULL, 0, NULL, NULL);
7509 
7510   assert_null(nghttp2_session_pop_next_ob_item(session));
7511 
7512   session->remote_settings.max_concurrent_streams = 2;
7513 
7514   item = nghttp2_session_pop_next_ob_item(session);
7515   assert_uint8(NGHTTP2_HEADERS, ==, item->frame.hd.type);
7516   nghttp2_outbound_item_free(item, mem);
7517   mem->free(item, NULL);
7518 
7519   nghttp2_session_del(session);
7520 
7521   /* Check that push reply HEADERS are queued into ob_ss_pq */
7522   nghttp2_session_server_new(&session, &callbacks, NULL);
7523   session->remote_settings.max_concurrent_streams = 0;
7524   open_sent_stream2(session, 2, NGHTTP2_STREAM_RESERVED);
7525   assert_int32(0, ==,
7526                nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, 2, NULL,
7527                                       NULL, 0, NULL));
7528   assert_null(nghttp2_session_pop_next_ob_item(session));
7529   assert_size(1, ==, nghttp2_outbound_queue_size(&session->ob_syn));
7530   nghttp2_session_del(session);
7531 }
7532 
test_nghttp2_session_reply_fail(void)7533 void test_nghttp2_session_reply_fail(void) {
7534   nghttp2_session *session;
7535   nghttp2_session_callbacks callbacks;
7536   nghttp2_data_provider2 data_prd;
7537   my_user_data ud;
7538 
7539   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7540   callbacks.send_callback2 = fail_send_callback;
7541 
7542   data_prd.read_callback = fixed_length_data_source_read_callback;
7543   ud.data_source_length = 4 * 1024;
7544   assert_int(0, ==, nghttp2_session_server_new(&session, &callbacks, &ud));
7545   open_recv_stream2(session, 1, NGHTTP2_STREAM_OPENING);
7546   assert_int(0, ==, nghttp2_submit_response2(session, 1, NULL, 0, &data_prd));
7547   assert_int(NGHTTP2_ERR_CALLBACK_FAILURE, ==, nghttp2_session_send(session));
7548   nghttp2_session_del(session);
7549 }
7550 
test_nghttp2_session_max_concurrent_streams(void)7551 void test_nghttp2_session_max_concurrent_streams(void) {
7552   nghttp2_session *session;
7553   nghttp2_session_callbacks callbacks;
7554   nghttp2_frame frame;
7555   nghttp2_outbound_item *item;
7556   nghttp2_mem *mem;
7557 
7558   mem = nghttp2_mem_default();
7559   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7560   callbacks.send_callback2 = null_send_callback;
7561 
7562   nghttp2_session_server_new(&session, &callbacks, NULL);
7563   open_recv_stream(session, 1);
7564 
7565   /* Check un-ACKed SETTINGS_MAX_CONCURRENT_STREAMS */
7566   nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 3,
7567                              NGHTTP2_HCAT_HEADERS, NULL, NULL, 0);
7568   session->pending_local_max_concurrent_stream = 1;
7569 
7570   assert_int(NGHTTP2_ERR_IGN_HEADER_BLOCK, ==,
7571              nghttp2_session_on_request_headers_received(session, &frame));
7572 
7573   item = nghttp2_outbound_queue_top(&session->ob_reg);
7574   assert_uint8(NGHTTP2_RST_STREAM, ==, item->frame.hd.type);
7575   assert_uint32(NGHTTP2_REFUSED_STREAM, ==, item->frame.rst_stream.error_code);
7576 
7577   assert_int(0, ==, nghttp2_session_send(session));
7578 
7579   /* Check ACKed SETTINGS_MAX_CONCURRENT_STREAMS */
7580   session->local_settings.max_concurrent_streams = 1;
7581   frame.hd.stream_id = 5;
7582 
7583   assert_int(NGHTTP2_ERR_IGN_HEADER_BLOCK, ==,
7584              nghttp2_session_on_request_headers_received(session, &frame));
7585 
7586   item = nghttp2_outbound_queue_top(&session->ob_reg);
7587   assert_uint8(NGHTTP2_GOAWAY, ==, item->frame.hd.type);
7588   assert_uint32(NGHTTP2_PROTOCOL_ERROR, ==, item->frame.goaway.error_code);
7589 
7590   nghttp2_frame_headers_free(&frame.headers, mem);
7591   nghttp2_session_del(session);
7592 }
7593 
test_nghttp2_session_stop_data_with_rst_stream(void)7594 void test_nghttp2_session_stop_data_with_rst_stream(void) {
7595   nghttp2_session *session;
7596   nghttp2_session_callbacks callbacks;
7597   my_user_data ud;
7598   nghttp2_data_provider2 data_prd;
7599   nghttp2_frame frame;
7600 
7601   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7602   callbacks.on_frame_send_callback = on_frame_send_callback;
7603   callbacks.send_callback2 = block_count_send_callback;
7604   data_prd.read_callback = fixed_length_data_source_read_callback;
7605 
7606   ud.frame_send_cb_called = 0;
7607   ud.data_source_length = NGHTTP2_DATA_PAYLOADLEN * 4;
7608 
7609   nghttp2_session_server_new(&session, &callbacks, &ud);
7610   open_recv_stream2(session, 1, NGHTTP2_STREAM_OPENING);
7611   nghttp2_submit_response2(session, 1, NULL, 0, &data_prd);
7612 
7613   ud.block_count = 2;
7614   /* Sends response HEADERS + DATA[0] */
7615   assert_int(0, ==, nghttp2_session_send(session));
7616   assert_uint8(NGHTTP2_DATA, ==, ud.sent_frame_type);
7617   /* data for DATA[1] is read from data_prd but it is not sent */
7618   assert_size(ud.data_source_length, ==, NGHTTP2_DATA_PAYLOADLEN * 2);
7619 
7620   nghttp2_frame_rst_stream_init(&frame.rst_stream, 1, NGHTTP2_CANCEL);
7621   assert_int(0, ==, nghttp2_session_on_rst_stream_received(session, &frame));
7622   nghttp2_frame_rst_stream_free(&frame.rst_stream);
7623 
7624   /* Big enough number to send all DATA frames potentially. */
7625   ud.block_count = 100;
7626   /* Nothing will be sent in the following call. */
7627   assert_int(0, ==, nghttp2_session_send(session));
7628   /* With RST_STREAM, stream is canceled and further DATA on that
7629      stream are not sent. */
7630   assert_size(ud.data_source_length, ==, NGHTTP2_DATA_PAYLOADLEN * 2);
7631 
7632   assert_null(nghttp2_session_get_stream(session, 1));
7633 
7634   nghttp2_session_del(session);
7635 }
7636 
test_nghttp2_session_defer_data(void)7637 void test_nghttp2_session_defer_data(void) {
7638   nghttp2_session *session;
7639   nghttp2_session_callbacks callbacks;
7640   my_user_data ud;
7641   nghttp2_data_provider2 data_prd;
7642   nghttp2_outbound_item *item;
7643   nghttp2_stream *stream;
7644 
7645   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7646   callbacks.on_frame_send_callback = on_frame_send_callback;
7647   callbacks.send_callback2 = block_count_send_callback;
7648   data_prd.read_callback = defer_data_source_read_callback;
7649 
7650   ud.frame_send_cb_called = 0;
7651   ud.data_source_length = NGHTTP2_DATA_PAYLOADLEN * 4;
7652 
7653   nghttp2_session_server_new(&session, &callbacks, &ud);
7654   stream = open_recv_stream2(session, 1, NGHTTP2_STREAM_OPENING);
7655 
7656   session->remote_window_size = 1 << 20;
7657   stream->remote_window_size = 1 << 20;
7658 
7659   nghttp2_submit_response2(session, 1, NULL, 0, &data_prd);
7660 
7661   ud.block_count = 1;
7662   /* Sends HEADERS reply */
7663   assert_int(0, ==, nghttp2_session_send(session));
7664   assert_uint8(NGHTTP2_HEADERS, ==, ud.sent_frame_type);
7665   /* No data is read */
7666   assert_size(ud.data_source_length, ==, NGHTTP2_DATA_PAYLOADLEN * 4);
7667 
7668   ud.block_count = 1;
7669   nghttp2_submit_ping(session, NGHTTP2_FLAG_NONE, NULL);
7670   /* Sends PING */
7671   assert_int(0, ==, nghttp2_session_send(session));
7672   assert_uint8(NGHTTP2_PING, ==, ud.sent_frame_type);
7673 
7674   /* Resume deferred DATA */
7675   assert_int(0, ==, nghttp2_session_resume_data(session, 1));
7676   item = stream->item;
7677   item->aux_data.data.dpw.data_prd.v1.read_callback =
7678     fixed_length_data_source_read_callback;
7679   ud.block_count = 1;
7680   /* Reads 2 DATA chunks */
7681   assert_int(0, ==, nghttp2_session_send(session));
7682   assert_size(ud.data_source_length, ==, NGHTTP2_DATA_PAYLOADLEN * 2);
7683 
7684   /* Deferred again */
7685   item->aux_data.data.dpw.data_prd.v1.read_callback =
7686     defer_data_source_read_callback;
7687   /* This is needed since 16KiB block is already read and waiting to be
7688      sent. No read_callback invocation. */
7689   ud.block_count = 1;
7690   assert_int(0, ==, nghttp2_session_send(session));
7691   assert_size(ud.data_source_length, ==, NGHTTP2_DATA_PAYLOADLEN * 2);
7692 
7693   /* Resume deferred DATA */
7694   assert_int(0, ==, nghttp2_session_resume_data(session, 1));
7695   item->aux_data.data.dpw.data_prd.v1.read_callback =
7696     fixed_length_data_source_read_callback;
7697   ud.block_count = 1;
7698   /* Reads 2 16KiB blocks */
7699   assert_int(0, ==, nghttp2_session_send(session));
7700   assert_size(ud.data_source_length, ==, 0);
7701 
7702   nghttp2_session_del(session);
7703 }
7704 
test_nghttp2_session_flow_control(void)7705 void test_nghttp2_session_flow_control(void) {
7706   nghttp2_session *session;
7707   nghttp2_session_callbacks callbacks;
7708   my_user_data ud;
7709   nghttp2_data_provider2 data_prd;
7710   nghttp2_frame frame;
7711   nghttp2_stream *stream;
7712   int32_t new_initial_window_size;
7713   nghttp2_settings_entry iv[1];
7714   nghttp2_frame settings_frame;
7715   nghttp2_mem *mem;
7716 
7717   mem = nghttp2_mem_default();
7718   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7719   callbacks.send_callback2 = fixed_bytes_send_callback;
7720   callbacks.on_frame_send_callback = on_frame_send_callback;
7721   data_prd.read_callback = fixed_length_data_source_read_callback;
7722 
7723   ud.frame_send_cb_called = 0;
7724   ud.data_source_length = 128 * 1024;
7725   /* Use smaller emission count so that we can check outbound flow
7726      control window calculation is correct. */
7727   ud.fixed_sendlen = 2 * 1024;
7728 
7729   /* Initial window size to 64KiB - 1*/
7730   nghttp2_session_client_new(&session, &callbacks, &ud);
7731   /* Change it to 64KiB for easy calculation */
7732   session->remote_window_size = 64 * 1024;
7733   session->remote_settings.initial_window_size = 64 * 1024;
7734 
7735   nghttp2_submit_request2(session, NULL, NULL, 0, &data_prd, NULL);
7736 
7737   /* Sends 64KiB - 1 data */
7738   assert_int(0, ==, nghttp2_session_send(session));
7739   assert_size(64 * 1024, ==, ud.data_source_length);
7740 
7741   /* Back 32KiB in stream window */
7742   nghttp2_frame_window_update_init(&frame.window_update, NGHTTP2_FLAG_NONE, 1,
7743                                    32 * 1024);
7744   nghttp2_session_on_window_update_received(session, &frame);
7745 
7746   /* Send nothing because of connection-level window */
7747   assert_int(0, ==, nghttp2_session_send(session));
7748   assert_size(64 * 1024, ==, ud.data_source_length);
7749 
7750   /* Back 32KiB in connection-level window */
7751   frame.hd.stream_id = 0;
7752   nghttp2_session_on_window_update_received(session, &frame);
7753 
7754   /* Sends another 32KiB data */
7755   assert_int(0, ==, nghttp2_session_send(session));
7756   assert_size(32 * 1024, ==, ud.data_source_length);
7757 
7758   stream = nghttp2_session_get_stream(session, 1);
7759   /* Change initial window size to 16KiB. The window_size becomes
7760      negative. */
7761   new_initial_window_size = 16 * 1024;
7762   stream->remote_window_size =
7763     new_initial_window_size -
7764     ((int32_t)session->remote_settings.initial_window_size -
7765      stream->remote_window_size);
7766   session->remote_settings.initial_window_size =
7767     (uint32_t)new_initial_window_size;
7768   assert_int32(-48 * 1024, ==, stream->remote_window_size);
7769 
7770   /* Back 48KiB to stream window */
7771   frame.hd.stream_id = 1;
7772   frame.window_update.window_size_increment = 48 * 1024;
7773   nghttp2_session_on_window_update_received(session, &frame);
7774 
7775   /* Nothing is sent because window_size is 0 */
7776   assert_int(0, ==, nghttp2_session_send(session));
7777   assert_size(32 * 1024, ==, ud.data_source_length);
7778 
7779   /* Back 16KiB in stream window */
7780   frame.hd.stream_id = 1;
7781   frame.window_update.window_size_increment = 16 * 1024;
7782   nghttp2_session_on_window_update_received(session, &frame);
7783 
7784   /* Back 24KiB in connection-level window */
7785   frame.hd.stream_id = 0;
7786   frame.window_update.window_size_increment = 24 * 1024;
7787   nghttp2_session_on_window_update_received(session, &frame);
7788 
7789   /* Sends another 16KiB data */
7790   assert_int(0, ==, nghttp2_session_send(session));
7791   assert_size(16 * 1024, ==, ud.data_source_length);
7792 
7793   /* Increase initial window size to 32KiB */
7794   iv[0].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
7795   iv[0].value = 32 * 1024;
7796 
7797   nghttp2_frame_settings_init(&settings_frame.settings, NGHTTP2_FLAG_NONE,
7798                               dup_iv(iv, 1), 1);
7799   nghttp2_session_on_settings_received(session, &settings_frame, 1);
7800   nghttp2_frame_settings_free(&settings_frame.settings, mem);
7801 
7802   /* Sends another 8KiB data */
7803   assert_int(0, ==, nghttp2_session_send(session));
7804   assert_size(8 * 1024, ==, ud.data_source_length);
7805 
7806   /* Back 8KiB in connection-level window */
7807   frame.hd.stream_id = 0;
7808   frame.window_update.window_size_increment = 8 * 1024;
7809   nghttp2_session_on_window_update_received(session, &frame);
7810 
7811   /* Sends last 8KiB data */
7812   assert_int(0, ==, nghttp2_session_send(session));
7813   assert_size(0, ==, ud.data_source_length);
7814   assert_true(nghttp2_session_get_stream(session, 1)->shut_flags &
7815               NGHTTP2_SHUT_WR);
7816 
7817   nghttp2_frame_window_update_free(&frame.window_update);
7818   nghttp2_session_del(session);
7819 }
7820 
test_nghttp2_session_flow_control_data_recv(void)7821 void test_nghttp2_session_flow_control_data_recv(void) {
7822   nghttp2_session *session;
7823   nghttp2_session_callbacks callbacks;
7824   uint8_t data[64 * 1024 + 16];
7825   nghttp2_frame_hd hd;
7826   nghttp2_outbound_item *item;
7827   nghttp2_stream *stream;
7828 
7829   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7830   callbacks.send_callback2 = null_send_callback;
7831 
7832   /* Initial window size to 64KiB - 1*/
7833   nghttp2_session_client_new(&session, &callbacks, NULL);
7834 
7835   stream = open_sent_stream(session, 1);
7836 
7837   nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_WR);
7838 
7839   session->local_window_size = NGHTTP2_MAX_PAYLOADLEN;
7840   stream->local_window_size = NGHTTP2_MAX_PAYLOADLEN;
7841 
7842   /* Create DATA frame */
7843   memset(data, 0, sizeof(data));
7844   nghttp2_frame_hd_init(&hd, NGHTTP2_MAX_PAYLOADLEN, NGHTTP2_DATA,
7845                         NGHTTP2_FLAG_END_STREAM, 1);
7846 
7847   nghttp2_frame_pack_frame_hd(data, &hd);
7848   assert_ptrdiff(
7849     NGHTTP2_MAX_PAYLOADLEN + NGHTTP2_FRAME_HDLEN, ==,
7850     nghttp2_session_mem_recv2(session, data,
7851                               NGHTTP2_MAX_PAYLOADLEN + NGHTTP2_FRAME_HDLEN));
7852 
7853   item = nghttp2_session_get_next_ob_item(session);
7854   /* Since this is the last frame, stream-level WINDOW_UPDATE is not
7855      issued, but connection-level is. */
7856   assert_uint8(NGHTTP2_WINDOW_UPDATE, ==, item->frame.hd.type);
7857   assert_int32(0, ==, item->frame.hd.stream_id);
7858   assert_int32(NGHTTP2_MAX_PAYLOADLEN, ==,
7859                item->frame.window_update.window_size_increment);
7860 
7861   assert_int(0, ==, nghttp2_session_send(session));
7862 
7863   /* Receive DATA for closed stream. They are still subject to under
7864      connection-level flow control, since this situation arises when
7865      RST_STREAM is issued by the remote, but the local side keeps
7866      sending DATA frames. Without calculating connection-level window,
7867      the subsequent flow control gets confused. */
7868   assert_ptrdiff(
7869     NGHTTP2_MAX_PAYLOADLEN + NGHTTP2_FRAME_HDLEN, ==,
7870     nghttp2_session_mem_recv2(session, data,
7871                               NGHTTP2_MAX_PAYLOADLEN + NGHTTP2_FRAME_HDLEN));
7872 
7873   item = nghttp2_session_get_next_ob_item(session);
7874   assert_uint8(NGHTTP2_WINDOW_UPDATE, ==, item->frame.hd.type);
7875   assert_int32(0, ==, item->frame.hd.stream_id);
7876   assert_int32(NGHTTP2_MAX_PAYLOADLEN, ==,
7877                item->frame.window_update.window_size_increment);
7878 
7879   nghttp2_session_del(session);
7880 }
7881 
test_nghttp2_session_flow_control_data_with_padding_recv(void)7882 void test_nghttp2_session_flow_control_data_with_padding_recv(void) {
7883   nghttp2_session *session;
7884   nghttp2_session_callbacks callbacks;
7885   uint8_t data[1024];
7886   nghttp2_frame_hd hd;
7887   nghttp2_stream *stream;
7888   nghttp2_option *option;
7889 
7890   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7891   callbacks.send_callback2 = null_send_callback;
7892 
7893   nghttp2_option_new(&option);
7894   /* Disable auto window update so that we can check padding is
7895      consumed automatically */
7896   nghttp2_option_set_no_auto_window_update(option, 1);
7897 
7898   /* Initial window size to 64KiB - 1*/
7899   nghttp2_session_client_new2(&session, &callbacks, NULL, option);
7900 
7901   nghttp2_option_del(option);
7902 
7903   stream = open_sent_stream(session, 1);
7904 
7905   /* Create DATA frame */
7906   memset(data, 0, sizeof(data));
7907   nghttp2_frame_hd_init(&hd, 357, NGHTTP2_DATA, NGHTTP2_FLAG_PADDED, 1);
7908 
7909   nghttp2_frame_pack_frame_hd(data, &hd);
7910   /* Set Pad Length field, which itself is padding */
7911   data[NGHTTP2_FRAME_HDLEN] = 255;
7912 
7913   assert_ptrdiff(
7914     (nghttp2_ssize)(NGHTTP2_FRAME_HDLEN + hd.length), ==,
7915     nghttp2_session_mem_recv2(session, data, NGHTTP2_FRAME_HDLEN + hd.length));
7916 
7917   assert_int32((int32_t)hd.length, ==, session->recv_window_size);
7918   assert_int32((int32_t)hd.length, ==, stream->recv_window_size);
7919   assert_int32(256, ==, session->consumed_size);
7920   assert_int32(256, ==, stream->consumed_size);
7921   assert_int32(357, ==, session->recv_window_size);
7922   assert_int32(357, ==, stream->recv_window_size);
7923 
7924   /* Receive the same DATA frame, but in 2 parts: first 9 + 1 + 102
7925      bytes which includes 1st padding byte, and remainder */
7926   assert_ptrdiff(
7927     (nghttp2_ssize)(NGHTTP2_FRAME_HDLEN + 103), ==,
7928     nghttp2_session_mem_recv2(session, data, NGHTTP2_FRAME_HDLEN + 103));
7929   assert_int32(258, ==, session->consumed_size);
7930   assert_int32(258, ==, stream->consumed_size);
7931   assert_int32(460, ==, session->recv_window_size);
7932   assert_int32(460, ==, stream->recv_window_size);
7933 
7934   /* 357 - 103 = 254 bytes left */
7935   assert_ptrdiff(254, ==, nghttp2_session_mem_recv2(session, data, 254));
7936   assert_int32(512, ==, session->consumed_size);
7937   assert_int32(512, ==, stream->consumed_size);
7938   assert_int32(714, ==, session->recv_window_size);
7939   assert_int32(714, ==, stream->recv_window_size);
7940 
7941   /* Receive the same DATA frame, but in 2 parts: first 9 = 1 + 101
7942      bytes which only includes data without padding, 2nd part is
7943      padding only */
7944   assert_ptrdiff(
7945     (nghttp2_ssize)(NGHTTP2_FRAME_HDLEN + 102), ==,
7946     nghttp2_session_mem_recv2(session, data, NGHTTP2_FRAME_HDLEN + 102));
7947   assert_int32(513, ==, session->consumed_size);
7948   assert_int32(513, ==, stream->consumed_size);
7949   assert_int32(816, ==, session->recv_window_size);
7950   assert_int32(816, ==, stream->recv_window_size);
7951 
7952   /* 357 - 102 = 255 bytes left */
7953   assert_ptrdiff(255, ==, nghttp2_session_mem_recv2(session, data, 255));
7954   assert_int32(768, ==, session->consumed_size);
7955   assert_int32(768, ==, stream->consumed_size);
7956   assert_int32(1071, ==, session->recv_window_size);
7957   assert_int32(1071, ==, stream->recv_window_size);
7958 
7959   /* Receive the same DATA frame, but in 2 parts: first 9 = 1 + 50
7960      bytes which includes byte up to middle of data, 2nd part is the
7961      remainder */
7962   assert_ptrdiff(
7963     (nghttp2_ssize)(NGHTTP2_FRAME_HDLEN + 51), ==,
7964     nghttp2_session_mem_recv2(session, data, NGHTTP2_FRAME_HDLEN + 51));
7965   assert_int32(769, ==, session->consumed_size);
7966   assert_int32(769, ==, stream->consumed_size);
7967   assert_int32(1122, ==, session->recv_window_size);
7968   assert_int32(1122, ==, stream->recv_window_size);
7969 
7970   /* 357 - 51 = 306 bytes left */
7971   assert_ptrdiff(306, ==, nghttp2_session_mem_recv2(session, data, 306));
7972   assert_int32(1024, ==, session->consumed_size);
7973   assert_int32(1024, ==, stream->consumed_size);
7974   assert_int32(1428, ==, session->recv_window_size);
7975   assert_int32(1428, ==, stream->recv_window_size);
7976 
7977   nghttp2_session_del(session);
7978 }
7979 
test_nghttp2_session_data_read_temporal_failure(void)7980 void test_nghttp2_session_data_read_temporal_failure(void) {
7981   nghttp2_session *session;
7982   nghttp2_session_callbacks callbacks;
7983   my_user_data ud;
7984   nghttp2_data_provider2 data_prd;
7985   nghttp2_frame frame;
7986   nghttp2_stream *stream;
7987   size_t data_size = 128 * 1024;
7988 
7989   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7990   callbacks.send_callback2 = null_send_callback;
7991   callbacks.on_frame_send_callback = on_frame_send_callback;
7992   data_prd.read_callback = fixed_length_data_source_read_callback;
7993 
7994   ud.data_source_length = data_size;
7995 
7996   /* Initial window size is 64KiB - 1 */
7997   nghttp2_session_client_new(&session, &callbacks, &ud);
7998   nghttp2_submit_request2(session, NULL, NULL, 0, &data_prd, NULL);
7999 
8000   /* Sends NGHTTP2_INITIAL_WINDOW_SIZE data, assuming, it is equal to
8001      or smaller than NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE */
8002   assert_int(0, ==, nghttp2_session_send(session));
8003   assert_size(data_size - NGHTTP2_INITIAL_WINDOW_SIZE, ==,
8004               ud.data_source_length);
8005 
8006   stream = nghttp2_session_get_stream(session, 1);
8007   assert_uint8(NGHTTP2_DATA, ==, stream->item->frame.hd.type);
8008 
8009   stream->item->aux_data.data.dpw.data_prd.v1.read_callback =
8010     temporal_failure_data_source_read_callback;
8011 
8012   /* Back NGHTTP2_INITIAL_WINDOW_SIZE to both connection-level and
8013      stream-wise window */
8014   nghttp2_frame_window_update_init(&frame.window_update, NGHTTP2_FLAG_NONE, 1,
8015                                    NGHTTP2_INITIAL_WINDOW_SIZE);
8016   nghttp2_session_on_window_update_received(session, &frame);
8017   frame.hd.stream_id = 0;
8018   nghttp2_session_on_window_update_received(session, &frame);
8019   nghttp2_frame_window_update_free(&frame.window_update);
8020 
8021   /* Sending data will fail (soft fail) and treated as stream error */
8022   ud.frame_send_cb_called = 0;
8023   assert_int(0, ==, nghttp2_session_send(session));
8024   assert_size(data_size - NGHTTP2_INITIAL_WINDOW_SIZE, ==,
8025               ud.data_source_length);
8026 
8027   assert_int(1, ==, ud.frame_send_cb_called);
8028   assert_uint8(NGHTTP2_RST_STREAM, ==, ud.sent_frame_type);
8029 
8030   data_prd.read_callback = fail_data_source_read_callback;
8031   nghttp2_submit_request2(session, NULL, NULL, 0, &data_prd, NULL);
8032   /* Sending data will fail (hard fail) and session tear down */
8033   assert_int(NGHTTP2_ERR_CALLBACK_FAILURE, ==, nghttp2_session_send(session));
8034 
8035   nghttp2_session_del(session);
8036 }
8037 
test_nghttp2_session_on_stream_close(void)8038 void test_nghttp2_session_on_stream_close(void) {
8039   nghttp2_session *session;
8040   nghttp2_session_callbacks callbacks;
8041   my_user_data user_data;
8042   nghttp2_stream *stream;
8043 
8044   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
8045   callbacks.on_stream_close_callback = on_stream_close_callback;
8046   user_data.stream_close_cb_called = 0;
8047 
8048   nghttp2_session_client_new(&session, &callbacks, &user_data);
8049   stream =
8050     open_sent_stream3(session, 1, NGHTTP2_STREAM_FLAG_NONE, &pri_spec_default,
8051                       NGHTTP2_STREAM_OPENED, &user_data);
8052   assert_not_null(stream);
8053   assert_int(0, ==, nghttp2_session_close_stream(session, 1, NGHTTP2_NO_ERROR));
8054   assert_int(1, ==, user_data.stream_close_cb_called);
8055   nghttp2_session_del(session);
8056 }
8057 
test_nghttp2_session_on_ctrl_not_send(void)8058 void test_nghttp2_session_on_ctrl_not_send(void) {
8059   nghttp2_session *session;
8060   nghttp2_session_callbacks callbacks;
8061   my_user_data user_data;
8062   nghttp2_stream *stream;
8063 
8064   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
8065   callbacks.on_frame_not_send_callback = on_frame_not_send_callback;
8066   callbacks.send_callback2 = null_send_callback;
8067   user_data.frame_not_send_cb_called = 0;
8068   user_data.not_sent_frame_type = 0;
8069   user_data.not_sent_error = 0;
8070 
8071   nghttp2_session_server_new(&session, &callbacks, &user_data);
8072   stream =
8073     open_recv_stream3(session, 1, NGHTTP2_STREAM_FLAG_NONE, &pri_spec_default,
8074                       NGHTTP2_STREAM_OPENING, &user_data);
8075 
8076   /* Check response HEADERS */
8077   /* Send bogus stream ID */
8078   assert_int32(0, ==,
8079                nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, 3, NULL,
8080                                       NULL, 0, NULL));
8081   assert_int(0, ==, nghttp2_session_send(session));
8082   assert_int(1, ==, user_data.frame_not_send_cb_called);
8083   assert_uint8(NGHTTP2_HEADERS, ==, user_data.not_sent_frame_type);
8084   assert_int(NGHTTP2_ERR_STREAM_CLOSED, ==, user_data.not_sent_error);
8085 
8086   user_data.frame_not_send_cb_called = 0;
8087   /* Shutdown transmission */
8088   stream->shut_flags |= NGHTTP2_SHUT_WR;
8089   assert_int32(0, ==,
8090                nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, 1, NULL,
8091                                       NULL, 0, NULL));
8092   assert_int(0, ==, nghttp2_session_send(session));
8093   assert_int(1, ==, user_data.frame_not_send_cb_called);
8094   assert_uint8(NGHTTP2_HEADERS, ==, user_data.not_sent_frame_type);
8095   assert_int(NGHTTP2_ERR_STREAM_SHUT_WR, ==, user_data.not_sent_error);
8096 
8097   stream->shut_flags = NGHTTP2_SHUT_NONE;
8098   user_data.frame_not_send_cb_called = 0;
8099   /* Queue RST_STREAM */
8100   assert_int32(0, ==,
8101                nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, 1, NULL,
8102                                       NULL, 0, NULL));
8103   assert_int(0, ==,
8104              nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, 1,
8105                                        NGHTTP2_INTERNAL_ERROR));
8106   assert_int(0, ==, nghttp2_session_send(session));
8107   assert_int(1, ==, user_data.frame_not_send_cb_called);
8108   assert_uint8(NGHTTP2_HEADERS, ==, user_data.not_sent_frame_type);
8109   assert_int(NGHTTP2_ERR_STREAM_CLOSING, ==, user_data.not_sent_error);
8110 
8111   nghttp2_session_del(session);
8112 
8113   /* Check request HEADERS */
8114   user_data.frame_not_send_cb_called = 0;
8115   assert_int(0, ==,
8116              nghttp2_session_client_new(&session, &callbacks, &user_data));
8117   /* Maximum Stream ID is reached */
8118   session->next_stream_id = (1u << 31) + 1;
8119   assert_int32(NGHTTP2_ERR_STREAM_ID_NOT_AVAILABLE, ==,
8120                nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, -1,
8121                                       NULL, NULL, 0, NULL));
8122 
8123   user_data.frame_not_send_cb_called = 0;
8124   /* GOAWAY received */
8125   session->goaway_flags |= NGHTTP2_GOAWAY_RECV;
8126   session->next_stream_id = 9;
8127 
8128   assert_int32(0, <,
8129                nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, -1,
8130                                       NULL, NULL, 0, NULL));
8131   assert_int(0, ==, nghttp2_session_send(session));
8132   assert_int(1, ==, user_data.frame_not_send_cb_called);
8133   assert_uint8(NGHTTP2_HEADERS, ==, user_data.not_sent_frame_type);
8134   assert_int(NGHTTP2_ERR_START_STREAM_NOT_ALLOWED, ==,
8135              user_data.not_sent_error);
8136 
8137   nghttp2_session_del(session);
8138 }
8139 
test_nghttp2_session_get_outbound_queue_size(void)8140 void test_nghttp2_session_get_outbound_queue_size(void) {
8141   nghttp2_session *session;
8142   nghttp2_session_callbacks callbacks;
8143 
8144   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
8145   assert_int(0, ==, nghttp2_session_client_new(&session, &callbacks, NULL));
8146   assert_size(0, ==, nghttp2_session_get_outbound_queue_size(session));
8147 
8148   assert_int(0, ==, nghttp2_submit_ping(session, NGHTTP2_FLAG_NONE, NULL));
8149   assert_size(1, ==, nghttp2_session_get_outbound_queue_size(session));
8150 
8151   assert_int(0, ==,
8152              nghttp2_submit_goaway(session, NGHTTP2_FLAG_NONE, 2,
8153                                    NGHTTP2_NO_ERROR, NULL, 0));
8154   assert_size(2, ==, nghttp2_session_get_outbound_queue_size(session));
8155 
8156   nghttp2_session_del(session);
8157 }
8158 
test_nghttp2_session_get_effective_local_window_size(void)8159 void test_nghttp2_session_get_effective_local_window_size(void) {
8160   nghttp2_session *session;
8161   nghttp2_session_callbacks callbacks;
8162   nghttp2_stream *stream;
8163 
8164   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
8165   assert_int(0, ==, nghttp2_session_client_new(&session, &callbacks, NULL));
8166 
8167   stream = open_sent_stream(session, 1);
8168 
8169   assert_int32(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE, ==,
8170                nghttp2_session_get_effective_local_window_size(session));
8171   assert_int32(0, ==, nghttp2_session_get_effective_recv_data_length(session));
8172 
8173   assert_int32(
8174     NGHTTP2_INITIAL_WINDOW_SIZE, ==,
8175     nghttp2_session_get_stream_effective_local_window_size(session, 1));
8176   assert_int32(
8177     0, ==, nghttp2_session_get_stream_effective_recv_data_length(session, 1));
8178 
8179   /* Check connection flow control */
8180   session->recv_window_size = 100;
8181   nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 0, 1100);
8182 
8183   assert_int32(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE + 1000, ==,
8184                nghttp2_session_get_effective_local_window_size(session));
8185   assert_int32(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE + 1000, ==,
8186                nghttp2_session_get_local_window_size(session));
8187   assert_int32(0, ==, nghttp2_session_get_effective_recv_data_length(session));
8188 
8189   nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 0, -50);
8190   /* Now session->recv_window_size = -50 */
8191   assert_int32(-50, ==, session->recv_window_size);
8192   assert_int32(50, ==, session->recv_reduction);
8193   assert_int32(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE + 950, ==,
8194                nghttp2_session_get_effective_local_window_size(session));
8195   assert_int32(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE + 1000, ==,
8196                nghttp2_session_get_local_window_size(session));
8197   assert_int32(0, ==, nghttp2_session_get_effective_recv_data_length(session));
8198 
8199   session->recv_window_size += 50;
8200 
8201   /* Now session->recv_window_size = 0 */
8202 
8203   assert_int32(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE + 950, ==,
8204                nghttp2_session_get_local_window_size(session));
8205 
8206   nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 0, 100);
8207   assert_int32(50, ==, session->recv_window_size);
8208   assert_int32(0, ==, session->recv_reduction);
8209   assert_int32(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE + 1050, ==,
8210                nghttp2_session_get_effective_local_window_size(session));
8211   assert_int32(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE + 1000, ==,
8212                nghttp2_session_get_local_window_size(session));
8213   assert_int32(50, ==, nghttp2_session_get_effective_recv_data_length(session));
8214 
8215   /* Check stream flow control */
8216   stream->recv_window_size = 100;
8217   nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 1, 1100);
8218 
8219   assert_int32(
8220     NGHTTP2_INITIAL_WINDOW_SIZE + 1000, ==,
8221     nghttp2_session_get_stream_effective_local_window_size(session, 1));
8222   assert_int32(NGHTTP2_INITIAL_WINDOW_SIZE + 1000, ==,
8223                nghttp2_session_get_stream_local_window_size(session, 1));
8224   assert_int32(
8225     0, ==, nghttp2_session_get_stream_effective_recv_data_length(session, 1));
8226 
8227   nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 1, -50);
8228   /* Now stream->recv_window_size = -50 */
8229   assert_int32(
8230     NGHTTP2_INITIAL_WINDOW_SIZE + 950, ==,
8231     nghttp2_session_get_stream_effective_local_window_size(session, 1));
8232   assert_int32(NGHTTP2_INITIAL_WINDOW_SIZE + 1000, ==,
8233                nghttp2_session_get_stream_local_window_size(session, 1));
8234   assert_int32(
8235     0, ==, nghttp2_session_get_stream_effective_recv_data_length(session, 1));
8236 
8237   stream->recv_window_size += 50;
8238   /* Now stream->recv_window_size = 0 */
8239   nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 1, 100);
8240   assert_int32(
8241     NGHTTP2_INITIAL_WINDOW_SIZE + 1050, ==,
8242     nghttp2_session_get_stream_effective_local_window_size(session, 1));
8243   assert_int32(NGHTTP2_INITIAL_WINDOW_SIZE + 1000, ==,
8244                nghttp2_session_get_stream_local_window_size(session, 1));
8245   assert_int32(
8246     50, ==, nghttp2_session_get_stream_effective_recv_data_length(session, 1));
8247 
8248   nghttp2_session_del(session);
8249 }
8250 
test_nghttp2_session_set_option(void)8251 void test_nghttp2_session_set_option(void) {
8252   nghttp2_session *session;
8253   nghttp2_session_callbacks callbacks;
8254   nghttp2_option *option;
8255   nghttp2_hd_deflater *deflater;
8256   int rv;
8257 
8258   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
8259   callbacks.send_callback2 = null_send_callback;
8260 
8261   /* Test for nghttp2_option_set_no_auto_window_update */
8262   nghttp2_option_new(&option);
8263   nghttp2_option_set_no_auto_window_update(option, 1);
8264 
8265   nghttp2_session_client_new2(&session, &callbacks, NULL, option);
8266 
8267   assert_true(session->opt_flags & NGHTTP2_OPTMASK_NO_AUTO_WINDOW_UPDATE);
8268 
8269   nghttp2_session_del(session);
8270   nghttp2_option_del(option);
8271 
8272   /* Test for nghttp2_option_set_peer_max_concurrent_streams */
8273   nghttp2_option_new(&option);
8274   nghttp2_option_set_peer_max_concurrent_streams(option, 100);
8275 
8276   nghttp2_session_client_new2(&session, &callbacks, NULL, option);
8277 
8278   assert_uint32(100, ==, session->remote_settings.max_concurrent_streams);
8279   nghttp2_session_del(session);
8280   nghttp2_option_del(option);
8281 
8282   /* Test for nghttp2_option_set_max_reserved_remote_streams */
8283   nghttp2_option_new(&option);
8284   nghttp2_option_set_max_reserved_remote_streams(option, 99);
8285 
8286   nghttp2_session_client_new2(&session, &callbacks, NULL, option);
8287 
8288   assert_size(99, ==, session->max_incoming_reserved_streams);
8289   nghttp2_session_del(session);
8290   nghttp2_option_del(option);
8291 
8292   /* Test for nghttp2_option_set_no_auto_ping_ack */
8293   nghttp2_option_new(&option);
8294   nghttp2_option_set_no_auto_ping_ack(option, 1);
8295 
8296   nghttp2_session_client_new2(&session, &callbacks, NULL, option);
8297 
8298   assert_true(session->opt_flags & NGHTTP2_OPTMASK_NO_AUTO_PING_ACK);
8299 
8300   nghttp2_session_del(session);
8301   nghttp2_option_del(option);
8302 
8303   /* Test for nghttp2_option_set_max_deflate_dynamic_table_size */
8304   nghttp2_option_new(&option);
8305   nghttp2_option_set_max_deflate_dynamic_table_size(option, 0);
8306 
8307   nghttp2_session_client_new2(&session, &callbacks, NULL, option);
8308 
8309   deflater = &session->hd_deflater;
8310 
8311   rv = nghttp2_submit_request2(session, NULL, reqnv, ARRLEN(reqnv), NULL, NULL);
8312 
8313   assert_int(1, ==, rv);
8314 
8315   rv = nghttp2_session_send(session);
8316 
8317   assert_int(0, ==, rv);
8318   assert_size(0, ==, deflater->deflate_hd_table_bufsize_max);
8319   assert_size(0, ==, deflater->ctx.hd_table_bufsize);
8320 
8321   nghttp2_session_del(session);
8322   nghttp2_option_del(option);
8323 }
8324 
test_nghttp2_session_data_backoff_by_high_pri_frame(void)8325 void test_nghttp2_session_data_backoff_by_high_pri_frame(void) {
8326   nghttp2_session *session;
8327   nghttp2_session_callbacks callbacks;
8328   my_user_data ud;
8329   nghttp2_data_provider2 data_prd;
8330   nghttp2_stream *stream;
8331 
8332   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
8333   callbacks.send_callback2 = block_count_send_callback;
8334   callbacks.on_frame_send_callback = on_frame_send_callback;
8335   data_prd.read_callback = fixed_length_data_source_read_callback;
8336 
8337   ud.frame_send_cb_called = 0;
8338   ud.data_source_length = NGHTTP2_DATA_PAYLOADLEN * 4;
8339 
8340   nghttp2_session_client_new(&session, &callbacks, &ud);
8341   nghttp2_submit_request2(session, NULL, NULL, 0, &data_prd, NULL);
8342 
8343   session->remote_window_size = 1 << 20;
8344 
8345   ud.block_count = 2;
8346   /* Sends request HEADERS + DATA[0] */
8347   assert_int(0, ==, nghttp2_session_send(session));
8348 
8349   stream = nghttp2_session_get_stream(session, 1);
8350   stream->remote_window_size = 1 << 20;
8351 
8352   assert_uint8(NGHTTP2_DATA, ==, ud.sent_frame_type);
8353   /* data for DATA[1] is read from data_prd but it is not sent */
8354   assert_size(ud.data_source_length, ==, NGHTTP2_DATA_PAYLOADLEN * 2);
8355 
8356   nghttp2_submit_ping(session, NGHTTP2_FLAG_NONE, NULL);
8357   ud.block_count = 2;
8358   /* Sends DATA[1] + PING, PING is interleaved in DATA sequence */
8359   assert_int(0, ==, nghttp2_session_send(session));
8360   assert_uint8(NGHTTP2_PING, ==, ud.sent_frame_type);
8361   /* data for DATA[2] is read from data_prd but it is not sent */
8362   assert_size(ud.data_source_length, ==, NGHTTP2_DATA_PAYLOADLEN);
8363 
8364   ud.block_count = 2;
8365   /* Sends DATA[2..3] */
8366   assert_int(0, ==, nghttp2_session_send(session));
8367 
8368   assert_true(stream->shut_flags & NGHTTP2_SHUT_WR);
8369 
8370   nghttp2_session_del(session);
8371 }
8372 
check_session_recv_data_with_padding(nghttp2_bufs * bufs,size_t datalen,nghttp2_mem * mem)8373 static void check_session_recv_data_with_padding(nghttp2_bufs *bufs,
8374                                                  size_t datalen,
8375                                                  nghttp2_mem *mem) {
8376   nghttp2_session *session;
8377   my_user_data ud;
8378   nghttp2_session_callbacks callbacks;
8379   uint8_t *in;
8380   size_t inlen;
8381 
8382   memset(&callbacks, 0, sizeof(callbacks));
8383   callbacks.on_frame_recv_callback = on_frame_recv_callback;
8384   callbacks.on_data_chunk_recv_callback = on_data_chunk_recv_callback;
8385   nghttp2_session_server_new(&session, &callbacks, &ud);
8386 
8387   open_recv_stream(session, 1);
8388 
8389   inlen = (size_t)nghttp2_bufs_remove(bufs, &in);
8390 
8391   ud.frame_recv_cb_called = 0;
8392   ud.data_chunk_len = 0;
8393 
8394   assert_ptrdiff((nghttp2_ssize)inlen, ==,
8395                  nghttp2_session_mem_recv2(session, in, inlen));
8396 
8397   assert_int(1, ==, ud.frame_recv_cb_called);
8398   assert_size(datalen, ==, ud.data_chunk_len);
8399 
8400   mem->free(in, NULL);
8401   nghttp2_session_del(session);
8402 }
8403 
test_nghttp2_session_pack_data_with_padding(void)8404 void test_nghttp2_session_pack_data_with_padding(void) {
8405   nghttp2_session *session;
8406   my_user_data ud;
8407   nghttp2_session_callbacks callbacks;
8408   nghttp2_data_provider2 data_prd;
8409   nghttp2_frame *frame;
8410   size_t datalen = 55;
8411   nghttp2_mem *mem;
8412 
8413   mem = nghttp2_mem_default();
8414 
8415   memset(&callbacks, 0, sizeof(callbacks));
8416   callbacks.send_callback2 = block_count_send_callback;
8417   callbacks.on_frame_send_callback = on_frame_send_callback;
8418   callbacks.select_padding_callback2 = select_padding_callback;
8419 
8420   data_prd.read_callback = fixed_length_data_source_read_callback;
8421 
8422   nghttp2_session_client_new(&session, &callbacks, &ud);
8423 
8424   ud.padlen = 63;
8425 
8426   nghttp2_submit_request2(session, NULL, NULL, 0, &data_prd, NULL);
8427   ud.block_count = 1;
8428   ud.data_source_length = datalen;
8429   /* Sends HEADERS */
8430   assert_int(0, ==, nghttp2_session_send(session));
8431   assert_uint8(NGHTTP2_HEADERS, ==, ud.sent_frame_type);
8432 
8433   frame = &session->aob.item->frame;
8434 
8435   assert_size(ud.padlen, ==, frame->data.padlen);
8436   assert_true(frame->hd.flags & NGHTTP2_FLAG_PADDED);
8437 
8438   /* Check reception of this DATA frame */
8439   check_session_recv_data_with_padding(&session->aob.framebufs, datalen, mem);
8440 
8441   nghttp2_session_del(session);
8442 }
8443 
test_nghttp2_session_pack_headers_with_padding(void)8444 void test_nghttp2_session_pack_headers_with_padding(void) {
8445   nghttp2_session *session, *sv_session;
8446   accumulator acc;
8447   my_user_data ud;
8448   nghttp2_session_callbacks callbacks;
8449 
8450   memset(&callbacks, 0, sizeof(callbacks));
8451   callbacks.send_callback2 = accumulator_send_callback;
8452   callbacks.on_frame_send_callback = on_frame_send_callback;
8453   callbacks.select_padding_callback2 = select_padding_callback;
8454   callbacks.on_frame_recv_callback = on_frame_recv_callback;
8455 
8456   acc.length = 0;
8457   ud.acc = &acc;
8458 
8459   nghttp2_session_client_new(&session, &callbacks, &ud);
8460   nghttp2_session_server_new(&sv_session, &callbacks, &ud);
8461 
8462   ud.padlen = 163;
8463 
8464   assert_int32(
8465     1, ==,
8466     nghttp2_submit_request2(session, NULL, reqnv, ARRLEN(reqnv), NULL, NULL));
8467   assert_int(0, ==, nghttp2_session_send(session));
8468 
8469   assert_size(NGHTTP2_MAX_PAYLOADLEN, >, acc.length);
8470   ud.frame_recv_cb_called = 0;
8471   assert_ptrdiff((nghttp2_ssize)acc.length, ==,
8472                  nghttp2_session_mem_recv2(sv_session, acc.buf, acc.length));
8473   assert_int(1, ==, ud.frame_recv_cb_called);
8474   assert_null(nghttp2_session_get_next_ob_item(sv_session));
8475 
8476   nghttp2_session_del(sv_session);
8477   nghttp2_session_del(session);
8478 }
8479 
test_nghttp2_pack_settings_payload(void)8480 void test_nghttp2_pack_settings_payload(void) {
8481   nghttp2_settings_entry iv[2];
8482   uint8_t buf[64];
8483   nghttp2_ssize len;
8484   nghttp2_settings_entry *resiv;
8485   size_t resniv;
8486   nghttp2_mem *mem;
8487 
8488   mem = nghttp2_mem_default();
8489 
8490   iv[0].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
8491   iv[0].value = 1023;
8492   iv[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
8493   iv[1].value = 4095;
8494 
8495   len = nghttp2_pack_settings_payload2(buf, sizeof(buf), iv, 2);
8496   assert_ptrdiff(2 * NGHTTP2_FRAME_SETTINGS_ENTRY_LENGTH, ==, len);
8497   assert_int(0, ==,
8498              nghttp2_frame_unpack_settings_payload2(&resiv, &resniv, buf,
8499                                                     (size_t)len, mem));
8500   assert_size(2, ==, resniv);
8501   assert_int32(NGHTTP2_SETTINGS_HEADER_TABLE_SIZE, ==, resiv[0].settings_id);
8502   assert_uint32(1023, ==, resiv[0].value);
8503   assert_int32(NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE, ==, resiv[1].settings_id);
8504   assert_uint32(4095, ==, resiv[1].value);
8505 
8506   mem->free(resiv, NULL);
8507 
8508   len = nghttp2_pack_settings_payload2(buf, 9 /* too small */, iv, 2);
8509   assert_ptrdiff(NGHTTP2_ERR_INSUFF_BUFSIZE, ==, len);
8510 }
8511 
8512 #define check_stream_dep_sib(STREAM, DEP_PREV, DEP_NEXT, SIB_PREV, SIB_NEXT)   \
8513   do {                                                                         \
8514     assert_ptr_equal(DEP_PREV, STREAM->dep_prev);                              \
8515     assert_ptr_equal(DEP_NEXT, STREAM->dep_next);                              \
8516     assert_ptr_equal(SIB_PREV, STREAM->sib_prev);                              \
8517     assert_ptr_equal(SIB_NEXT, STREAM->sib_next);                              \
8518   } while (0)
8519 
8520 /* nghttp2_stream_dep_add() and its families functions should be
8521    tested in nghttp2_stream_test.c, but it is easier to use
8522    nghttp2_session_open_stream().  Therefore, we test them here. */
test_nghttp2_session_stream_dep_add(void)8523 void test_nghttp2_session_stream_dep_add(void) {
8524   nghttp2_session *session;
8525   nghttp2_session_callbacks callbacks;
8526   nghttp2_stream *a, *b, *c, *d, *e, *root;
8527 
8528   memset(&callbacks, 0, sizeof(callbacks));
8529 
8530   nghttp2_session_server_new(&session, &callbacks, NULL);
8531 
8532   root = &session->root;
8533 
8534   a = open_stream(session, 1);
8535 
8536   c = open_stream_with_dep(session, 5, a);
8537   b = open_stream_with_dep(session, 3, a);
8538   d = open_stream_with_dep(session, 7, c);
8539 
8540   /* a
8541    * |
8542    * b--c
8543    *    |
8544    *    d
8545    */
8546 
8547   assert_int32(NGHTTP2_DEFAULT_WEIGHT * 2, ==, a->sum_dep_weight);
8548   assert_int32(0, ==, b->sum_dep_weight);
8549   assert_int32(NGHTTP2_DEFAULT_WEIGHT, ==, c->sum_dep_weight);
8550   assert_int32(0, ==, d->sum_dep_weight);
8551 
8552   check_stream_dep_sib(a, root, b, NULL, NULL);
8553   check_stream_dep_sib(b, a, NULL, NULL, c);
8554   check_stream_dep_sib(c, a, d, b, NULL);
8555   check_stream_dep_sib(d, c, NULL, NULL, NULL);
8556 
8557   assert_ptr_equal(a, session->root.dep_next);
8558 
8559   e = open_stream_with_dep_excl(session, 9, a);
8560 
8561   /* a
8562    * |
8563    * e
8564    * |
8565    * b--c
8566    *    |
8567    *    d
8568    */
8569 
8570   assert_int32(NGHTTP2_DEFAULT_WEIGHT, ==, a->sum_dep_weight);
8571   assert_int32(NGHTTP2_DEFAULT_WEIGHT * 2, ==, e->sum_dep_weight);
8572   assert_int32(0, ==, b->sum_dep_weight);
8573   assert_int32(NGHTTP2_DEFAULT_WEIGHT, ==, c->sum_dep_weight);
8574   assert_int32(0, ==, d->sum_dep_weight);
8575 
8576   check_stream_dep_sib(a, root, e, NULL, NULL);
8577   check_stream_dep_sib(e, a, b, NULL, NULL);
8578   check_stream_dep_sib(b, e, NULL, NULL, c);
8579   check_stream_dep_sib(c, e, d, b, NULL);
8580   check_stream_dep_sib(d, c, NULL, NULL, NULL);
8581 
8582   assert_ptr_equal(a, session->root.dep_next);
8583 
8584   nghttp2_session_del(session);
8585 }
8586 
test_nghttp2_session_stream_dep_remove(void)8587 void test_nghttp2_session_stream_dep_remove(void) {
8588   nghttp2_session *session;
8589   nghttp2_session_callbacks callbacks;
8590   nghttp2_stream *a, *b, *c, *d, *e, *f, *root;
8591 
8592   memset(&callbacks, 0, sizeof(callbacks));
8593 
8594   /* Remove root */
8595   nghttp2_session_server_new(&session, &callbacks, NULL);
8596 
8597   root = &session->root;
8598 
8599   a = open_stream(session, 1);
8600   b = open_stream_with_dep(session, 3, a);
8601   c = open_stream_with_dep(session, 5, a);
8602   d = open_stream_with_dep(session, 7, c);
8603 
8604   /* a
8605    * |
8606    * c--b
8607    * |
8608    * d
8609    */
8610 
8611   nghttp2_stream_dep_remove(a);
8612 
8613   /* becomes:
8614    * c    b
8615    * |
8616    * d
8617    */
8618 
8619   assert_int32(0, ==, a->sum_dep_weight);
8620   assert_int32(0, ==, b->sum_dep_weight);
8621   assert_int32(NGHTTP2_DEFAULT_WEIGHT, ==, c->sum_dep_weight);
8622   assert_int32(0, ==, d->sum_dep_weight);
8623 
8624   check_stream_dep_sib(a, NULL, NULL, NULL, NULL);
8625   check_stream_dep_sib(b, root, NULL, c, NULL);
8626   check_stream_dep_sib(c, root, d, NULL, b);
8627   check_stream_dep_sib(d, c, NULL, NULL, NULL);
8628 
8629   assert_ptr_equal(c, session->root.dep_next);
8630 
8631   nghttp2_session_del(session);
8632 
8633   /* Remove right most stream */
8634   nghttp2_session_server_new(&session, &callbacks, NULL);
8635 
8636   root = &session->root;
8637 
8638   a = open_stream(session, 1);
8639   b = open_stream_with_dep(session, 3, a);
8640   c = open_stream_with_dep(session, 5, a);
8641   d = open_stream_with_dep(session, 7, c);
8642 
8643   /* a
8644    * |
8645    * c--b
8646    * |
8647    * d
8648    */
8649 
8650   nghttp2_stream_dep_remove(b);
8651 
8652   /* becomes:
8653    * a
8654    * |
8655    * c
8656    * |
8657    * d
8658    */
8659 
8660   assert_int32(NGHTTP2_DEFAULT_WEIGHT, ==, a->sum_dep_weight);
8661   assert_int32(NGHTTP2_DEFAULT_WEIGHT, ==, c->sum_dep_weight);
8662   assert_int32(0, ==, d->sum_dep_weight);
8663   assert_int32(0, ==, b->sum_dep_weight);
8664 
8665   check_stream_dep_sib(a, root, c, NULL, NULL);
8666   check_stream_dep_sib(b, NULL, NULL, NULL, NULL);
8667   check_stream_dep_sib(c, a, d, NULL, NULL);
8668   check_stream_dep_sib(d, c, NULL, NULL, NULL);
8669 
8670   assert_ptr_equal(a, session->root.dep_next);
8671 
8672   nghttp2_session_del(session);
8673 
8674   /* Remove left most stream */
8675   nghttp2_session_server_new(&session, &callbacks, NULL);
8676 
8677   root = &session->root;
8678 
8679   a = open_stream(session, 1);
8680   b = open_stream_with_dep(session, 3, a);
8681   c = open_stream_with_dep(session, 5, a);
8682   d = open_stream_with_dep(session, 7, c);
8683   e = open_stream_with_dep(session, 9, c);
8684 
8685   /* a
8686    * |
8687    * c--b
8688    * |
8689    * e--d
8690    */
8691 
8692   nghttp2_stream_dep_remove(c);
8693 
8694   /* becomes:
8695    * a
8696    * |
8697    * e--d--b
8698    */
8699 
8700   assert_int32(NGHTTP2_DEFAULT_WEIGHT * 2, ==, a->sum_dep_weight);
8701   assert_int32(0, ==, b->sum_dep_weight);
8702   assert_int32(0, ==, d->sum_dep_weight);
8703   assert_int32(0, ==, c->sum_dep_weight);
8704   assert_int32(0, ==, e->sum_dep_weight);
8705 
8706   check_stream_dep_sib(a, root, e, NULL, NULL);
8707   check_stream_dep_sib(b, a, NULL, d, NULL);
8708   check_stream_dep_sib(c, NULL, NULL, NULL, NULL);
8709   check_stream_dep_sib(d, a, NULL, e, b);
8710   check_stream_dep_sib(e, a, NULL, NULL, d);
8711 
8712   nghttp2_session_del(session);
8713 
8714   /* Remove middle stream */
8715   nghttp2_session_server_new(&session, &callbacks, NULL);
8716 
8717   root = &session->root;
8718 
8719   a = open_stream(session, 1);
8720   b = open_stream_with_dep(session, 3, a);
8721   c = open_stream_with_dep(session, 5, a);
8722   d = open_stream_with_dep(session, 7, a);
8723   e = open_stream_with_dep(session, 9, c);
8724   f = open_stream_with_dep(session, 11, c);
8725 
8726   /* a
8727    * |
8728    * d--c--b
8729    *    |
8730    *    f--e
8731    */
8732 
8733   assert_int32(NGHTTP2_DEFAULT_WEIGHT * 3, ==, a->sum_dep_weight);
8734   assert_int32(0, ==, b->sum_dep_weight);
8735   assert_int32(NGHTTP2_DEFAULT_WEIGHT * 2, ==, c->sum_dep_weight);
8736   assert_int32(0, ==, d->sum_dep_weight);
8737   assert_int32(0, ==, e->sum_dep_weight);
8738   assert_int32(0, ==, f->sum_dep_weight);
8739 
8740   nghttp2_stream_dep_remove(c);
8741 
8742   /* becomes:
8743    * a
8744    * |
8745    * d--f--e--b
8746    */
8747 
8748   /* c's weight 16 is distributed evenly to e and f.  Each weight of e
8749      and f becomes 8. */
8750   assert_int32(NGHTTP2_DEFAULT_WEIGHT * 2 + 8 * 2, ==, a->sum_dep_weight);
8751   assert_int32(0, ==, b->sum_dep_weight);
8752   assert_int32(0, ==, c->sum_dep_weight);
8753   assert_int32(0, ==, d->sum_dep_weight);
8754   assert_int32(0, ==, e->sum_dep_weight);
8755   assert_int32(0, ==, f->sum_dep_weight);
8756 
8757   check_stream_dep_sib(a, root, d, NULL, NULL);
8758   check_stream_dep_sib(b, a, NULL, e, NULL);
8759   check_stream_dep_sib(c, NULL, NULL, NULL, NULL);
8760   check_stream_dep_sib(e, a, NULL, f, b);
8761   check_stream_dep_sib(f, a, NULL, d, e);
8762   check_stream_dep_sib(d, a, NULL, NULL, f);
8763 
8764   nghttp2_session_del(session);
8765 }
8766 
test_nghttp2_session_stream_dep_add_subtree(void)8767 void test_nghttp2_session_stream_dep_add_subtree(void) {
8768   nghttp2_session *session;
8769   nghttp2_session_callbacks callbacks;
8770   nghttp2_stream *a, *b, *c, *d, *e, *f, *root;
8771 
8772   memset(&callbacks, 0, sizeof(callbacks));
8773 
8774   /* dep_stream has dep_next */
8775   nghttp2_session_server_new(&session, &callbacks, NULL);
8776 
8777   root = &session->root;
8778 
8779   a = open_stream(session, 1);
8780   b = open_stream_with_dep(session, 3, a);
8781   c = open_stream_with_dep(session, 5, a);
8782   d = open_stream_with_dep(session, 7, c);
8783 
8784   e = open_stream(session, 9);
8785   f = open_stream_with_dep(session, 11, e);
8786 
8787   /* a         e
8788    * |         |
8789    * c--b      f
8790    * |
8791    * d
8792    */
8793 
8794   nghttp2_stream_dep_remove_subtree(e);
8795   nghttp2_stream_dep_add_subtree(a, e);
8796 
8797   /* becomes
8798    * a
8799    * |
8800    * e--c--b
8801    * |  |
8802    * f  d
8803    */
8804 
8805   assert_int32(NGHTTP2_DEFAULT_WEIGHT * 3, ==, a->sum_dep_weight);
8806   assert_int32(0, ==, b->sum_dep_weight);
8807   assert_int32(NGHTTP2_DEFAULT_WEIGHT, ==, c->sum_dep_weight);
8808   assert_int32(0, ==, d->sum_dep_weight);
8809   assert_int32(NGHTTP2_DEFAULT_WEIGHT, ==, e->sum_dep_weight);
8810   assert_int32(0, ==, f->sum_dep_weight);
8811 
8812   check_stream_dep_sib(a, root, e, NULL, NULL);
8813   check_stream_dep_sib(b, a, NULL, c, NULL);
8814   check_stream_dep_sib(c, a, d, e, b);
8815   check_stream_dep_sib(d, c, NULL, NULL, NULL);
8816   check_stream_dep_sib(e, a, f, NULL, c);
8817   check_stream_dep_sib(f, e, NULL, NULL, NULL);
8818 
8819   nghttp2_session_del(session);
8820 
8821   /* dep_stream has dep_next and now we insert subtree */
8822   nghttp2_session_server_new(&session, &callbacks, NULL);
8823 
8824   root = &session->root;
8825 
8826   a = open_stream(session, 1);
8827   b = open_stream_with_dep(session, 3, a);
8828   c = open_stream_with_dep(session, 5, a);
8829   d = open_stream_with_dep(session, 7, c);
8830 
8831   e = open_stream(session, 9);
8832   f = open_stream_with_dep(session, 11, e);
8833 
8834   /* a         e
8835    * |         |
8836    * c--b      f
8837    * |
8838    * d
8839    */
8840 
8841   nghttp2_stream_dep_remove_subtree(e);
8842   nghttp2_stream_dep_insert_subtree(a, e);
8843 
8844   /* becomes
8845    * a
8846    * |
8847    * e
8848    * |
8849    * f--c--b
8850    *    |
8851    *    d
8852    */
8853 
8854   assert_int32(NGHTTP2_DEFAULT_WEIGHT, ==, a->sum_dep_weight);
8855   assert_int32(0, ==, b->sum_dep_weight);
8856   assert_int32(NGHTTP2_DEFAULT_WEIGHT, ==, c->sum_dep_weight);
8857   assert_int32(0, ==, d->sum_dep_weight);
8858   assert_int32(NGHTTP2_DEFAULT_WEIGHT * 3, ==, e->sum_dep_weight);
8859   assert_int32(0, ==, f->sum_dep_weight);
8860 
8861   check_stream_dep_sib(a, root, e, NULL, NULL);
8862   check_stream_dep_sib(e, a, f, NULL, NULL);
8863   check_stream_dep_sib(f, e, NULL, NULL, c);
8864   check_stream_dep_sib(b, e, NULL, c, NULL);
8865   check_stream_dep_sib(c, e, d, f, b);
8866   check_stream_dep_sib(d, c, NULL, NULL, NULL);
8867 
8868   nghttp2_session_del(session);
8869 }
8870 
test_nghttp2_session_stream_dep_remove_subtree(void)8871 void test_nghttp2_session_stream_dep_remove_subtree(void) {
8872   nghttp2_session *session;
8873   nghttp2_session_callbacks callbacks;
8874   nghttp2_stream *a, *b, *c, *d, *e, *root;
8875 
8876   memset(&callbacks, 0, sizeof(callbacks));
8877 
8878   /* Remove left most stream */
8879   nghttp2_session_server_new(&session, &callbacks, NULL);
8880 
8881   root = &session->root;
8882 
8883   a = open_stream(session, 1);
8884   b = open_stream_with_dep(session, 3, a);
8885   c = open_stream_with_dep(session, 5, a);
8886   d = open_stream_with_dep(session, 7, c);
8887 
8888   /* a
8889    * |
8890    * c--b
8891    * |
8892    * d
8893    */
8894 
8895   nghttp2_stream_dep_remove_subtree(c);
8896 
8897   /* becomes
8898    * a  c
8899    * |  |
8900    * b  d
8901    */
8902 
8903   assert_int32(NGHTTP2_DEFAULT_WEIGHT, ==, a->sum_dep_weight);
8904   assert_int32(0, ==, b->sum_dep_weight);
8905   assert_int32(NGHTTP2_DEFAULT_WEIGHT, ==, c->sum_dep_weight);
8906   assert_int32(0, ==, d->sum_dep_weight);
8907 
8908   check_stream_dep_sib(a, root, b, NULL, NULL);
8909   check_stream_dep_sib(b, a, NULL, NULL, NULL);
8910   check_stream_dep_sib(c, NULL, d, NULL, NULL);
8911   check_stream_dep_sib(d, c, NULL, NULL, NULL);
8912 
8913   nghttp2_session_del(session);
8914 
8915   /* Remove right most stream */
8916   nghttp2_session_server_new(&session, &callbacks, NULL);
8917 
8918   root = &session->root;
8919 
8920   a = open_stream(session, 1);
8921   b = open_stream_with_dep(session, 3, a);
8922   c = open_stream_with_dep(session, 5, a);
8923   d = open_stream_with_dep(session, 7, c);
8924 
8925   /* a
8926    * |
8927    * c--b
8928    * |
8929    * d
8930    */
8931 
8932   nghttp2_stream_dep_remove_subtree(b);
8933 
8934   /* becomes
8935    * a  b
8936    * |
8937    * c
8938    * |
8939    * d
8940    */
8941 
8942   assert_int32(NGHTTP2_DEFAULT_WEIGHT, ==, a->sum_dep_weight);
8943   assert_int32(0, ==, b->sum_dep_weight);
8944   assert_int32(NGHTTP2_DEFAULT_WEIGHT, ==, c->sum_dep_weight);
8945   assert_int32(0, ==, d->sum_dep_weight);
8946 
8947   check_stream_dep_sib(a, root, c, NULL, NULL);
8948   check_stream_dep_sib(c, a, d, NULL, NULL);
8949   check_stream_dep_sib(d, c, NULL, NULL, NULL);
8950   check_stream_dep_sib(b, NULL, NULL, NULL, NULL);
8951 
8952   nghttp2_session_del(session);
8953 
8954   /* Remove middle stream */
8955   nghttp2_session_server_new(&session, &callbacks, NULL);
8956 
8957   root = &session->root;
8958 
8959   a = open_stream(session, 1);
8960   e = open_stream_with_dep(session, 9, a);
8961   c = open_stream_with_dep(session, 5, a);
8962   b = open_stream_with_dep(session, 3, a);
8963   d = open_stream_with_dep(session, 7, c);
8964 
8965   /* a
8966    * |
8967    * b--c--e
8968    *    |
8969    *    d
8970    */
8971 
8972   nghttp2_stream_dep_remove_subtree(c);
8973 
8974   /* becomes
8975    * a     c
8976    * |     |
8977    * b--e  d
8978    */
8979 
8980   assert_int32(NGHTTP2_DEFAULT_WEIGHT * 2, ==, a->sum_dep_weight);
8981   assert_int32(0, ==, b->sum_dep_weight);
8982   assert_int32(NGHTTP2_DEFAULT_WEIGHT, ==, c->sum_dep_weight);
8983   assert_int32(0, ==, d->sum_dep_weight);
8984   assert_int32(0, ==, e->sum_dep_weight);
8985 
8986   check_stream_dep_sib(a, root, b, NULL, NULL);
8987   check_stream_dep_sib(b, a, NULL, NULL, e);
8988   check_stream_dep_sib(e, a, NULL, b, NULL);
8989   check_stream_dep_sib(c, NULL, d, NULL, NULL);
8990   check_stream_dep_sib(d, c, NULL, NULL, NULL);
8991 
8992   nghttp2_session_del(session);
8993 }
8994 
test_nghttp2_session_stream_dep_all_your_stream_are_belong_to_us(void)8995 void test_nghttp2_session_stream_dep_all_your_stream_are_belong_to_us(void) {
8996   nghttp2_session *session;
8997   nghttp2_session_callbacks callbacks;
8998   nghttp2_stream *a, *b, *c, *d, *root;
8999   nghttp2_outbound_item *db, *dc;
9000   nghttp2_mem *mem;
9001 
9002   mem = nghttp2_mem_default();
9003 
9004   memset(&callbacks, 0, sizeof(callbacks));
9005 
9006   nghttp2_session_server_new(&session, &callbacks, NULL);
9007 
9008   root = &session->root;
9009 
9010   a = open_stream(session, 1);
9011   b = open_stream_with_dep(session, 3, a);
9012 
9013   c = open_stream(session, 5);
9014 
9015   /* a     c
9016    * |
9017    * b
9018    */
9019 
9020   nghttp2_stream_dep_remove_subtree(c);
9021   assert_int(0, ==, nghttp2_stream_dep_insert_subtree(&session->root, c));
9022 
9023   /*
9024    * c
9025    * |
9026    * a
9027    * |
9028    * b
9029    */
9030 
9031   assert_int32(NGHTTP2_DEFAULT_WEIGHT, ==, c->sum_dep_weight);
9032   assert_int32(NGHTTP2_DEFAULT_WEIGHT, ==, a->sum_dep_weight);
9033   assert_int32(0, ==, b->sum_dep_weight);
9034 
9035   assert_true(nghttp2_pq_empty(&a->obq));
9036   assert_true(nghttp2_pq_empty(&b->obq));
9037   assert_true(nghttp2_pq_empty(&c->obq));
9038 
9039   check_stream_dep_sib(c, root, a, NULL, NULL);
9040   check_stream_dep_sib(a, c, b, NULL, NULL);
9041   check_stream_dep_sib(b, a, NULL, NULL, NULL);
9042 
9043   nghttp2_session_del(session);
9044 
9045   nghttp2_session_server_new(&session, &callbacks, NULL);
9046 
9047   root = &session->root;
9048 
9049   a = open_stream(session, 1);
9050   b = open_stream(session, 3);
9051   c = open_stream(session, 5);
9052 
9053   /*
9054    * a  b   c
9055    */
9056 
9057   nghttp2_stream_dep_remove_subtree(c);
9058   assert_int(0, ==, nghttp2_stream_dep_insert_subtree(&session->root, c));
9059 
9060   /*
9061    * c
9062    * |
9063    * b--a
9064    */
9065 
9066   assert_int32(NGHTTP2_DEFAULT_WEIGHT * 2, ==, c->sum_dep_weight);
9067   assert_int32(0, ==, b->sum_dep_weight);
9068   assert_int32(0, ==, a->sum_dep_weight);
9069 
9070   assert_true(nghttp2_pq_empty(&a->obq));
9071   assert_true(nghttp2_pq_empty(&b->obq));
9072   assert_true(nghttp2_pq_empty(&c->obq));
9073 
9074   check_stream_dep_sib(c, root, b, NULL, NULL);
9075   check_stream_dep_sib(b, c, NULL, NULL, a);
9076   check_stream_dep_sib(a, c, NULL, b, NULL);
9077 
9078   nghttp2_session_del(session);
9079 
9080   nghttp2_session_server_new(&session, &callbacks, NULL);
9081 
9082   root = &session->root;
9083 
9084   a = open_stream(session, 1);
9085   b = open_stream_with_dep(session, 3, a);
9086 
9087   c = open_stream(session, 5);
9088   d = open_stream_with_dep(session, 7, c);
9089 
9090   /* a     c
9091    * |     |
9092    * b     d
9093    */
9094 
9095   nghttp2_stream_dep_remove_subtree(c);
9096   assert_int(0, ==, nghttp2_stream_dep_insert_subtree(&session->root, c));
9097 
9098   /*
9099    * c
9100    * |
9101    * d--a
9102    *    |
9103    *    b
9104    */
9105 
9106   assert_int32(NGHTTP2_DEFAULT_WEIGHT * 2, ==, c->sum_dep_weight);
9107   assert_int32(0, ==, d->sum_dep_weight);
9108   assert_int32(NGHTTP2_DEFAULT_WEIGHT, ==, a->sum_dep_weight);
9109   assert_int32(0, ==, b->sum_dep_weight);
9110 
9111   assert_true(nghttp2_pq_empty(&a->obq));
9112   assert_true(nghttp2_pq_empty(&b->obq));
9113   assert_true(nghttp2_pq_empty(&c->obq));
9114   assert_true(nghttp2_pq_empty(&d->obq));
9115 
9116   check_stream_dep_sib(c, root, d, NULL, NULL);
9117   check_stream_dep_sib(d, c, NULL, NULL, a);
9118   check_stream_dep_sib(a, c, b, d, NULL);
9119   check_stream_dep_sib(b, a, NULL, NULL, NULL);
9120 
9121   nghttp2_session_del(session);
9122 
9123   nghttp2_session_server_new(&session, &callbacks, NULL);
9124 
9125   root = &session->root;
9126 
9127   a = open_stream(session, 1);
9128   b = open_stream_with_dep(session, 3, a);
9129 
9130   c = open_stream(session, 5);
9131   d = open_stream_with_dep(session, 7, c);
9132 
9133   /* a     c
9134    * |     |
9135    * b     d
9136    */
9137 
9138   db = create_data_ob_item(mem);
9139 
9140   nghttp2_stream_attach_item(b, db);
9141 
9142   nghttp2_stream_dep_remove_subtree(c);
9143   assert_int(0, ==, nghttp2_stream_dep_insert_subtree(&session->root, c));
9144 
9145   /*
9146    * c
9147    * |
9148    * d--a
9149    *    |
9150    *    b
9151    */
9152 
9153   assert_true(c->queued);
9154   assert_true(a->queued);
9155   assert_true(b->queued);
9156   assert_true(!d->queued);
9157 
9158   assert_size(1, ==, nghttp2_pq_size(&a->obq));
9159   assert_size(1, ==, nghttp2_pq_size(&c->obq));
9160   assert_true(nghttp2_pq_empty(&d->obq));
9161 
9162   check_stream_dep_sib(c, root, d, NULL, NULL);
9163   check_stream_dep_sib(d, c, NULL, NULL, a);
9164   check_stream_dep_sib(a, c, b, d, NULL);
9165   check_stream_dep_sib(b, a, NULL, NULL, NULL);
9166 
9167   nghttp2_session_del(session);
9168 
9169   nghttp2_session_server_new(&session, &callbacks, NULL);
9170 
9171   root = &session->root;
9172 
9173   a = open_stream(session, 1);
9174   b = open_stream_with_dep(session, 3, a);
9175 
9176   c = open_stream(session, 5);
9177   d = open_stream_with_dep(session, 7, c);
9178 
9179   /* a     c
9180    * |     |
9181    * b     d
9182    */
9183 
9184   db = create_data_ob_item(mem);
9185   dc = create_data_ob_item(mem);
9186 
9187   nghttp2_stream_attach_item(b, db);
9188   nghttp2_stream_attach_item(c, dc);
9189 
9190   nghttp2_stream_dep_remove_subtree(c);
9191   assert_int(0, ==, nghttp2_stream_dep_insert_subtree(&session->root, c));
9192 
9193   /*
9194    * c
9195    * |
9196    * d--a
9197    *    |
9198    *    b
9199    */
9200 
9201   assert_true(c->queued);
9202   assert_true(a->queued);
9203   assert_true(b->queued);
9204   assert_true(!d->queued);
9205 
9206   check_stream_dep_sib(c, root, d, NULL, NULL);
9207   check_stream_dep_sib(d, c, NULL, NULL, a);
9208   check_stream_dep_sib(a, c, b, d, NULL);
9209   check_stream_dep_sib(b, a, NULL, NULL, NULL);
9210 
9211   nghttp2_session_del(session);
9212 }
9213 
test_nghttp2_session_stream_attach_item(void)9214 void test_nghttp2_session_stream_attach_item(void) {
9215   nghttp2_session *session;
9216   nghttp2_session_callbacks callbacks;
9217   nghttp2_stream *a, *b, *c, *d, *e;
9218   nghttp2_outbound_item *da, *db, *dc, *dd;
9219   nghttp2_mem *mem;
9220 
9221   mem = nghttp2_mem_default();
9222 
9223   memset(&callbacks, 0, sizeof(callbacks));
9224 
9225   nghttp2_session_server_new(&session, &callbacks, NULL);
9226 
9227   a = open_stream(session, 1);
9228   b = open_stream_with_dep(session, 3, a);
9229   c = open_stream_with_dep(session, 5, a);
9230   d = open_stream_with_dep(session, 7, c);
9231 
9232   /* a
9233    * |
9234    * c--b
9235    * |
9236    * d
9237    */
9238 
9239   db = create_data_ob_item(mem);
9240 
9241   nghttp2_stream_attach_item(b, db);
9242 
9243   assert_true(a->queued);
9244   assert_true(b->queued);
9245   assert_true(!c->queued);
9246   assert_true(!d->queued);
9247 
9248   assert_size(1, ==, nghttp2_pq_size(&a->obq));
9249 
9250   /* Attach item to c */
9251   dc = create_data_ob_item(mem);
9252 
9253   nghttp2_stream_attach_item(c, dc);
9254 
9255   assert_true(a->queued);
9256   assert_true(b->queued);
9257   assert_true(c->queued);
9258   assert_true(!d->queued);
9259 
9260   assert_size(2, ==, nghttp2_pq_size(&a->obq));
9261 
9262   /* Attach item to a */
9263   da = create_data_ob_item(mem);
9264 
9265   nghttp2_stream_attach_item(a, da);
9266 
9267   assert_true(a->queued);
9268   assert_true(b->queued);
9269   assert_true(c->queued);
9270   assert_true(!d->queued);
9271 
9272   assert_size(2, ==, nghttp2_pq_size(&a->obq));
9273 
9274   /* Detach item from a */
9275   nghttp2_stream_detach_item(a);
9276 
9277   assert_true(a->queued);
9278   assert_true(b->queued);
9279   assert_true(c->queued);
9280   assert_true(!d->queued);
9281 
9282   assert_size(2, ==, nghttp2_pq_size(&a->obq));
9283 
9284   /* Attach item to d */
9285   dd = create_data_ob_item(mem);
9286 
9287   nghttp2_stream_attach_item(d, dd);
9288 
9289   assert_true(a->queued);
9290   assert_true(b->queued);
9291   assert_true(c->queued);
9292   assert_true(d->queued);
9293 
9294   assert_size(2, ==, nghttp2_pq_size(&a->obq));
9295   assert_size(1, ==, nghttp2_pq_size(&c->obq));
9296 
9297   /* Detach item from c */
9298   nghttp2_stream_detach_item(c);
9299 
9300   assert_true(a->queued);
9301   assert_true(b->queued);
9302   assert_true(c->queued);
9303   assert_true(d->queued);
9304 
9305   assert_size(2, ==, nghttp2_pq_size(&a->obq));
9306   assert_size(1, ==, nghttp2_pq_size(&c->obq));
9307 
9308   /* Detach item from b */
9309   nghttp2_stream_detach_item(b);
9310 
9311   assert_true(a->queued);
9312   assert_true(!b->queued);
9313   assert_true(c->queued);
9314   assert_true(d->queued);
9315 
9316   assert_size(1, ==, nghttp2_pq_size(&a->obq));
9317 
9318   /* exercises insertion */
9319   e = open_stream_with_dep_excl(session, 9, a);
9320 
9321   /* a
9322    * |
9323    * e
9324    * |
9325    * c--b
9326    * |
9327    * d
9328    */
9329 
9330   assert_true(a->queued);
9331   assert_true(e->queued);
9332   assert_true(!b->queued);
9333   assert_true(c->queued);
9334   assert_true(d->queued);
9335 
9336   assert_size(1, ==, nghttp2_pq_size(&a->obq));
9337   assert_size(1, ==, nghttp2_pq_size(&e->obq));
9338   assert_true(nghttp2_pq_empty(&b->obq));
9339   assert_size(1, ==, nghttp2_pq_size(&c->obq));
9340   assert_true(nghttp2_pq_empty(&d->obq));
9341 
9342   /* exercises deletion */
9343   nghttp2_stream_dep_remove(e);
9344 
9345   /* a
9346    * |
9347    * c--b
9348    * |
9349    * d
9350    */
9351 
9352   assert_true(a->queued);
9353   assert_true(!b->queued);
9354   assert_true(c->queued);
9355   assert_true(d->queued);
9356 
9357   assert_size(1, ==, nghttp2_pq_size(&a->obq));
9358   assert_true(nghttp2_pq_empty(&b->obq));
9359   assert_size(1, ==, nghttp2_pq_size(&c->obq));
9360   assert_true(nghttp2_pq_empty(&d->obq));
9361 
9362   /* e's weight 16 is distributed equally among c and b, both now have
9363      weight 8 each. */
9364   assert_int32(8, ==, b->weight);
9365   assert_int32(8, ==, c->weight);
9366 
9367   /* da, db, dc have been detached */
9368   nghttp2_outbound_item_free(da, mem);
9369   nghttp2_outbound_item_free(db, mem);
9370   nghttp2_outbound_item_free(dc, mem);
9371   free(da);
9372   free(db);
9373   free(dc);
9374 
9375   nghttp2_session_del(session);
9376 
9377   nghttp2_session_server_new(&session, &callbacks, NULL);
9378 
9379   a = open_stream(session, 1);
9380   b = open_stream_with_dep(session, 3, a);
9381   c = open_stream_with_dep(session, 5, a);
9382   d = open_stream_with_dep(session, 7, c);
9383 
9384   /* a
9385    * |
9386    * c--b
9387    * |
9388    * d
9389    */
9390 
9391   da = create_data_ob_item(mem);
9392   db = create_data_ob_item(mem);
9393   dc = create_data_ob_item(mem);
9394 
9395   nghttp2_stream_attach_item(a, da);
9396   nghttp2_stream_attach_item(b, db);
9397   nghttp2_stream_attach_item(c, dc);
9398 
9399   assert_true(a->queued);
9400   assert_true(b->queued);
9401   assert_true(c->queued);
9402   assert_true(!d->queued);
9403 
9404   assert_size(2, ==, nghttp2_pq_size(&a->obq));
9405   assert_true(nghttp2_pq_empty(&b->obq));
9406   assert_true(nghttp2_pq_empty(&c->obq));
9407   assert_true(nghttp2_pq_empty(&d->obq));
9408 
9409   /* Detach item from a */
9410   nghttp2_stream_detach_item(a);
9411 
9412   assert_true(a->queued);
9413   assert_true(b->queued);
9414   assert_true(c->queued);
9415   assert_true(!d->queued);
9416 
9417   assert_size(2, ==, nghttp2_pq_size(&a->obq));
9418   assert_true(nghttp2_pq_empty(&b->obq));
9419   assert_true(nghttp2_pq_empty(&c->obq));
9420   assert_true(nghttp2_pq_empty(&d->obq));
9421 
9422   /* da has been detached */
9423   nghttp2_outbound_item_free(da, mem);
9424   free(da);
9425 
9426   nghttp2_session_del(session);
9427 }
9428 
test_nghttp2_session_stream_attach_item_subtree(void)9429 void test_nghttp2_session_stream_attach_item_subtree(void) {
9430   nghttp2_session *session;
9431   nghttp2_session_callbacks callbacks;
9432   nghttp2_stream *a, *b, *c, *d, *e, *f;
9433   nghttp2_outbound_item *da, *db, *dd, *de;
9434   nghttp2_mem *mem;
9435 
9436   mem = nghttp2_mem_default();
9437 
9438   memset(&callbacks, 0, sizeof(callbacks));
9439 
9440   nghttp2_session_server_new(&session, &callbacks, NULL);
9441 
9442   a = open_stream(session, 1);
9443   b = open_stream_with_dep(session, 3, a);
9444   c = open_stream_with_dep(session, 5, a);
9445   d = open_stream_with_dep(session, 7, c);
9446 
9447   e = open_stream_with_dep_weight(session, 9, 32, &session->root);
9448   f = open_stream_with_dep(session, 11, e);
9449 
9450   /*
9451    * a        e
9452    * |        |
9453    * c--b     f
9454    * |
9455    * d
9456    */
9457 
9458   de = create_data_ob_item(mem);
9459 
9460   nghttp2_stream_attach_item(e, de);
9461 
9462   db = create_data_ob_item(mem);
9463 
9464   nghttp2_stream_attach_item(b, db);
9465 
9466   assert_true(a->queued);
9467   assert_true(b->queued);
9468   assert_true(!c->queued);
9469   assert_true(!d->queued);
9470   assert_true(e->queued);
9471   assert_true(!f->queued);
9472 
9473   assert_size(1, ==, nghttp2_pq_size(&a->obq));
9474   assert_true(nghttp2_pq_empty(&b->obq));
9475   assert_true(nghttp2_pq_empty(&c->obq));
9476   assert_true(nghttp2_pq_empty(&d->obq));
9477   assert_true(nghttp2_pq_empty(&e->obq));
9478   assert_true(nghttp2_pq_empty(&f->obq));
9479 
9480   /* Insert subtree e under a */
9481 
9482   nghttp2_stream_dep_remove_subtree(e);
9483   nghttp2_stream_dep_insert_subtree(a, e);
9484 
9485   /*
9486    * a
9487    * |
9488    * e
9489    * |
9490    * f--c--b
9491    *    |
9492    *    d
9493    */
9494 
9495   assert_true(a->queued);
9496   assert_true(b->queued);
9497   assert_true(!c->queued);
9498   assert_true(!d->queued);
9499   assert_true(e->queued);
9500   assert_true(!f->queued);
9501 
9502   assert_size(1, ==, nghttp2_pq_size(&a->obq));
9503   assert_true(nghttp2_pq_empty(&b->obq));
9504   assert_true(nghttp2_pq_empty(&c->obq));
9505   assert_true(nghttp2_pq_empty(&d->obq));
9506   assert_size(1, ==, nghttp2_pq_size(&e->obq));
9507   assert_true(nghttp2_pq_empty(&f->obq));
9508 
9509   /* Remove subtree b */
9510 
9511   nghttp2_stream_dep_remove_subtree(b);
9512 
9513   assert_int(0, ==, nghttp2_stream_dep_add_subtree(&session->root, b));
9514 
9515   /*
9516    * a       b
9517    * |
9518    * e
9519    * |
9520    * f--c
9521    *    |
9522    *    d
9523    */
9524 
9525   assert_true(a->queued);
9526   assert_true(b->queued);
9527   assert_true(!c->queued);
9528   assert_true(!d->queued);
9529   assert_true(e->queued);
9530   assert_true(!f->queued);
9531 
9532   assert_size(1, ==, nghttp2_pq_size(&a->obq));
9533   assert_true(nghttp2_pq_empty(&b->obq));
9534   assert_true(nghttp2_pq_empty(&c->obq));
9535   assert_true(nghttp2_pq_empty(&d->obq));
9536   assert_true(nghttp2_pq_empty(&e->obq));
9537   assert_true(nghttp2_pq_empty(&f->obq));
9538 
9539   /* Remove subtree a, and add it to root again */
9540 
9541   nghttp2_stream_dep_remove_subtree(a);
9542 
9543   assert_int(0, ==, nghttp2_stream_dep_add_subtree(&session->root, a));
9544 
9545   assert_true(a->queued);
9546   assert_true(b->queued);
9547   assert_true(!c->queued);
9548   assert_true(!d->queued);
9549   assert_true(e->queued);
9550   assert_true(!f->queued);
9551 
9552   assert_size(1, ==, nghttp2_pq_size(&a->obq));
9553   assert_true(nghttp2_pq_empty(&b->obq));
9554   assert_true(nghttp2_pq_empty(&c->obq));
9555   assert_true(nghttp2_pq_empty(&d->obq));
9556   assert_true(nghttp2_pq_empty(&e->obq));
9557   assert_true(nghttp2_pq_empty(&f->obq));
9558 
9559   /* Remove subtree c */
9560 
9561   nghttp2_stream_dep_remove_subtree(c);
9562 
9563   assert_int(0, ==, nghttp2_stream_dep_add_subtree(&session->root, c));
9564 
9565   /*
9566    * a       b     c
9567    * |             |
9568    * e             d
9569    * |
9570    * f
9571    */
9572 
9573   assert_true(a->queued);
9574   assert_true(b->queued);
9575   assert_true(!c->queued);
9576   assert_true(!d->queued);
9577   assert_true(e->queued);
9578   assert_true(!f->queued);
9579 
9580   assert_size(1, ==, nghttp2_pq_size(&a->obq));
9581   assert_true(nghttp2_pq_empty(&b->obq));
9582   assert_true(nghttp2_pq_empty(&c->obq));
9583   assert_true(nghttp2_pq_empty(&d->obq));
9584   assert_true(nghttp2_pq_empty(&e->obq));
9585   assert_true(nghttp2_pq_empty(&f->obq));
9586 
9587   dd = create_data_ob_item(mem);
9588 
9589   nghttp2_stream_attach_item(d, dd);
9590 
9591   /* Add subtree c to a */
9592 
9593   nghttp2_stream_dep_remove_subtree(c);
9594   nghttp2_stream_dep_add_subtree(a, c);
9595 
9596   /*
9597    * a       b
9598    * |
9599    * c--e
9600    * |  |
9601    * d  f
9602    */
9603 
9604   assert_true(a->queued);
9605   assert_true(b->queued);
9606   assert_true(c->queued);
9607   assert_true(d->queued);
9608   assert_true(e->queued);
9609   assert_true(!f->queued);
9610 
9611   assert_size(2, ==, nghttp2_pq_size(&a->obq));
9612   assert_true(nghttp2_pq_empty(&b->obq));
9613   assert_size(1, ==, nghttp2_pq_size(&c->obq));
9614   assert_true(nghttp2_pq_empty(&d->obq));
9615   assert_true(nghttp2_pq_empty(&e->obq));
9616   assert_true(nghttp2_pq_empty(&f->obq));
9617 
9618   /* Insert b under a */
9619 
9620   nghttp2_stream_dep_remove_subtree(b);
9621   nghttp2_stream_dep_insert_subtree(a, b);
9622 
9623   /*
9624    * a
9625    * |
9626    * b
9627    * |
9628    * c--e
9629    * |  |
9630    * d  f
9631    */
9632 
9633   assert_true(a->queued);
9634   assert_true(b->queued);
9635   assert_true(c->queued);
9636   assert_true(d->queued);
9637   assert_true(e->queued);
9638   assert_true(!f->queued);
9639 
9640   assert_size(1, ==, nghttp2_pq_size(&a->obq));
9641   assert_size(2, ==, nghttp2_pq_size(&b->obq));
9642   assert_size(1, ==, nghttp2_pq_size(&c->obq));
9643   assert_true(nghttp2_pq_empty(&d->obq));
9644   assert_true(nghttp2_pq_empty(&e->obq));
9645   assert_true(nghttp2_pq_empty(&f->obq));
9646 
9647   /* Remove subtree b */
9648 
9649   nghttp2_stream_dep_remove_subtree(b);
9650   assert_int(0, ==, nghttp2_stream_dep_add_subtree(&session->root, b));
9651 
9652   /*
9653    * b       a
9654    * |
9655    * e--c
9656    * |  |
9657    * f  d
9658    */
9659 
9660   assert_true(!a->queued);
9661   assert_true(b->queued);
9662   assert_true(c->queued);
9663   assert_true(d->queued);
9664   assert_true(e->queued);
9665   assert_true(!f->queued);
9666 
9667   assert_true(nghttp2_pq_empty(&a->obq));
9668   assert_size(2, ==, nghttp2_pq_size(&b->obq));
9669   assert_size(1, ==, nghttp2_pq_size(&c->obq));
9670   assert_true(nghttp2_pq_empty(&d->obq));
9671   assert_true(nghttp2_pq_empty(&e->obq));
9672   assert_true(nghttp2_pq_empty(&f->obq));
9673 
9674   /* Remove subtree c, and detach item from b, and then re-add
9675      subtree c under b */
9676 
9677   nghttp2_stream_dep_remove_subtree(c);
9678   nghttp2_stream_detach_item(b);
9679   nghttp2_stream_dep_add_subtree(b, c);
9680 
9681   /*
9682    * b       a
9683    * |
9684    * e--c
9685    * |  |
9686    * f  d
9687    */
9688 
9689   assert_true(!a->queued);
9690   assert_true(b->queued);
9691   assert_true(c->queued);
9692   assert_true(d->queued);
9693   assert_true(e->queued);
9694   assert_true(!f->queued);
9695 
9696   assert_true(nghttp2_pq_empty(&a->obq));
9697   assert_size(2, ==, nghttp2_pq_size(&b->obq));
9698   assert_size(1, ==, nghttp2_pq_size(&c->obq));
9699   assert_true(nghttp2_pq_empty(&d->obq));
9700   assert_true(nghttp2_pq_empty(&e->obq));
9701   assert_true(nghttp2_pq_empty(&f->obq));
9702 
9703   /* Attach data to a, and add subtree a under b */
9704 
9705   da = create_data_ob_item(mem);
9706   nghttp2_stream_attach_item(a, da);
9707   nghttp2_stream_dep_remove_subtree(a);
9708   nghttp2_stream_dep_add_subtree(b, a);
9709 
9710   /*
9711    * b
9712    * |
9713    * a--e--c
9714    *    |  |
9715    *    f  d
9716    */
9717 
9718   assert_true(a->queued);
9719   assert_true(b->queued);
9720   assert_true(c->queued);
9721   assert_true(d->queued);
9722   assert_true(e->queued);
9723   assert_true(!f->queued);
9724 
9725   assert_true(nghttp2_pq_empty(&a->obq));
9726   assert_size(3, ==, nghttp2_pq_size(&b->obq));
9727   assert_size(1, ==, nghttp2_pq_size(&c->obq));
9728   assert_true(nghttp2_pq_empty(&d->obq));
9729   assert_true(nghttp2_pq_empty(&e->obq));
9730   assert_true(nghttp2_pq_empty(&f->obq));
9731 
9732   /* Remove subtree c, and add under f */
9733   nghttp2_stream_dep_remove_subtree(c);
9734   nghttp2_stream_dep_insert_subtree(f, c);
9735 
9736   /*
9737    * b
9738    * |
9739    * a--e
9740    *    |
9741    *    f
9742    *    |
9743    *    c
9744    *    |
9745    *    d
9746    */
9747 
9748   assert_true(a->queued);
9749   assert_true(b->queued);
9750   assert_true(c->queued);
9751   assert_true(d->queued);
9752   assert_true(e->queued);
9753   assert_true(f->queued);
9754 
9755   assert_true(nghttp2_pq_empty(&a->obq));
9756   assert_size(2, ==, nghttp2_pq_size(&b->obq));
9757   assert_size(1, ==, nghttp2_pq_size(&c->obq));
9758   assert_true(nghttp2_pq_empty(&d->obq));
9759   assert_size(1, ==, nghttp2_pq_size(&e->obq));
9760   assert_size(1, ==, nghttp2_pq_size(&f->obq));
9761 
9762   /* db has been detached */
9763   nghttp2_outbound_item_free(db, mem);
9764   free(db);
9765 
9766   nghttp2_session_del(session);
9767 }
9768 
test_nghttp2_session_stream_get_state(void)9769 void test_nghttp2_session_stream_get_state(void) {
9770   nghttp2_session *session;
9771   nghttp2_session_callbacks callbacks;
9772   nghttp2_mem *mem;
9773   nghttp2_hd_deflater deflater;
9774   nghttp2_bufs bufs;
9775   nghttp2_buf *buf;
9776   nghttp2_stream *stream;
9777   nghttp2_ssize rv;
9778   nghttp2_data_provider2 data_prd;
9779   nghttp2_frame frame;
9780 
9781   mem = nghttp2_mem_default();
9782   frame_pack_bufs_init(&bufs);
9783   memset(&data_prd, 0, sizeof(data_prd));
9784 
9785   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
9786   callbacks.send_callback2 = null_send_callback;
9787 
9788   nghttp2_session_server_new(&session, &callbacks, NULL);
9789   nghttp2_hd_deflate_init(&deflater, mem);
9790 
9791   assert_enum(
9792     nghttp2_stream_proto_state, NGHTTP2_STREAM_STATE_IDLE, ==,
9793     nghttp2_stream_get_state(nghttp2_session_get_root_stream(session)));
9794 
9795   /* stream 1 HEADERS; without END_STREAM flag set */
9796   pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, reqnv,
9797                ARRLEN(reqnv), mem);
9798 
9799   buf = &bufs.head->buf;
9800   rv = nghttp2_session_mem_recv2(session, buf->pos, nghttp2_buf_len(buf));
9801 
9802   assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(buf), ==, rv);
9803 
9804   stream = nghttp2_session_find_stream(session, 1);
9805 
9806   assert_not_null(stream);
9807   assert_int32(1, ==, stream->stream_id);
9808   assert_enum(nghttp2_stream_proto_state, NGHTTP2_STREAM_STATE_OPEN, ==,
9809               nghttp2_stream_get_state(stream));
9810 
9811   nghttp2_bufs_reset(&bufs);
9812 
9813   /* stream 3 HEADERS; with END_STREAM flag set */
9814   pack_headers(&bufs, &deflater, 3,
9815                NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM, reqnv,
9816                ARRLEN(reqnv), mem);
9817 
9818   buf = &bufs.head->buf;
9819   rv = nghttp2_session_mem_recv2(session, buf->pos, nghttp2_buf_len(buf));
9820 
9821   assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(buf), ==, rv);
9822 
9823   stream = nghttp2_session_find_stream(session, 3);
9824 
9825   assert_not_null(stream);
9826   assert_int32(3, ==, stream->stream_id);
9827   assert_enum(nghttp2_stream_proto_state,
9828               NGHTTP2_STREAM_STATE_HALF_CLOSED_REMOTE, ==,
9829               nghttp2_stream_get_state(stream));
9830 
9831   nghttp2_bufs_reset(&bufs);
9832 
9833   /* Respond to stream 1 */
9834   nghttp2_submit_response2(session, 1, resnv, ARRLEN(resnv), NULL);
9835 
9836   rv = nghttp2_session_send(session);
9837 
9838   assert_ptrdiff(0, ==, rv);
9839 
9840   stream = nghttp2_session_find_stream(session, 1);
9841 
9842   assert_enum(nghttp2_stream_proto_state,
9843               NGHTTP2_STREAM_STATE_HALF_CLOSED_LOCAL, ==,
9844               nghttp2_stream_get_state(stream));
9845 
9846   /* Respond to stream 3 */
9847   nghttp2_submit_response2(session, 3, resnv, ARRLEN(resnv), NULL);
9848 
9849   rv = nghttp2_session_send(session);
9850 
9851   assert_ptrdiff(0, ==, rv);
9852 
9853   stream = nghttp2_session_find_stream(session, 3);
9854 
9855   assert_enum(nghttp2_stream_proto_state, NGHTTP2_STREAM_STATE_CLOSED, ==,
9856               nghttp2_stream_get_state(stream));
9857 
9858   /* stream 5 HEADERS; with END_STREAM flag set */
9859   pack_headers(&bufs, &deflater, 5,
9860                NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM, reqnv,
9861                ARRLEN(reqnv), mem);
9862 
9863   buf = &bufs.head->buf;
9864   rv = nghttp2_session_mem_recv2(session, buf->pos, nghttp2_buf_len(buf));
9865 
9866   assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(buf), ==, rv);
9867 
9868   nghttp2_bufs_reset(&bufs);
9869 
9870   /* Push stream 2 associated to stream 5 */
9871   rv = nghttp2_submit_push_promise(session, NGHTTP2_FLAG_NONE, 5, reqnv,
9872                                    ARRLEN(reqnv), NULL);
9873 
9874   assert_ptrdiff(2, ==, rv);
9875 
9876   rv = nghttp2_session_send(session);
9877 
9878   assert_ptrdiff(0, ==, rv);
9879 
9880   stream = nghttp2_session_find_stream(session, 2);
9881 
9882   assert_enum(nghttp2_stream_proto_state, NGHTTP2_STREAM_STATE_RESERVED_LOCAL,
9883               ==, nghttp2_stream_get_state(stream));
9884 
9885   /* Send response to push stream 2 with END_STREAM set */
9886   nghttp2_submit_response2(session, 2, resnv, ARRLEN(resnv), NULL);
9887 
9888   rv = nghttp2_session_send(session);
9889 
9890   assert_ptrdiff(0, ==, rv);
9891 
9892   stream = nghttp2_session_find_stream(session, 2);
9893 
9894   /* At server, pushed stream object is not retained after closed */
9895   assert_null(stream);
9896 
9897   /* Push stream 4 associated to stream 5 */
9898   rv = nghttp2_submit_push_promise(session, NGHTTP2_FLAG_NONE, 5, reqnv,
9899                                    ARRLEN(reqnv), NULL);
9900 
9901   assert_ptrdiff(4, ==, rv);
9902 
9903   rv = nghttp2_session_send(session);
9904 
9905   assert_ptrdiff(0, ==, rv);
9906 
9907   stream = nghttp2_session_find_stream(session, 4);
9908 
9909   assert_enum(nghttp2_stream_proto_state, NGHTTP2_STREAM_STATE_RESERVED_LOCAL,
9910               ==, nghttp2_stream_get_state(stream));
9911 
9912   /* Send response to push stream 4 without closing */
9913   data_prd.read_callback = defer_data_source_read_callback;
9914 
9915   nghttp2_submit_response2(session, 4, resnv, ARRLEN(resnv), &data_prd);
9916 
9917   rv = nghttp2_session_send(session);
9918 
9919   assert_ptrdiff(0, ==, rv);
9920 
9921   stream = nghttp2_session_find_stream(session, 4);
9922 
9923   assert_enum(nghttp2_stream_proto_state,
9924               NGHTTP2_STREAM_STATE_HALF_CLOSED_REMOTE, ==,
9925               nghttp2_stream_get_state(stream));
9926 
9927   /* Create idle stream by PRIORITY frame */
9928   nghttp2_frame_priority_init(&frame.priority, 7, &pri_spec_default);
9929 
9930   nghttp2_frame_pack_priority(&bufs, &frame.priority);
9931 
9932   nghttp2_frame_priority_free(&frame.priority);
9933 
9934   buf = &bufs.head->buf;
9935   rv = nghttp2_session_mem_recv2(session, buf->pos, nghttp2_buf_len(buf));
9936 
9937   assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(buf), ==, rv);
9938 
9939   stream = nghttp2_session_find_stream(session, 7);
9940 
9941   assert_enum(nghttp2_stream_proto_state, NGHTTP2_STREAM_STATE_IDLE, ==,
9942               nghttp2_stream_get_state(stream));
9943 
9944   nghttp2_bufs_reset(&bufs);
9945 
9946   nghttp2_hd_deflate_free(&deflater);
9947   nghttp2_session_del(session);
9948 
9949   /* Test for client side */
9950 
9951   nghttp2_session_client_new(&session, &callbacks, NULL);
9952   nghttp2_hd_deflate_init(&deflater, mem);
9953 
9954   nghttp2_submit_request2(session, NULL, reqnv, ARRLEN(reqnv), NULL, NULL);
9955 
9956   rv = nghttp2_session_send(session);
9957 
9958   assert_ptrdiff(0, ==, rv);
9959 
9960   /* Receive PUSH_PROMISE 2 associated to stream 1 */
9961   pack_push_promise(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, 2, reqnv,
9962                     ARRLEN(reqnv), mem);
9963 
9964   buf = &bufs.head->buf;
9965   rv = nghttp2_session_mem_recv2(session, buf->pos, nghttp2_buf_len(buf));
9966 
9967   assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(buf), ==, rv);
9968 
9969   stream = nghttp2_session_find_stream(session, 2);
9970 
9971   assert_enum(nghttp2_stream_proto_state, NGHTTP2_STREAM_STATE_RESERVED_REMOTE,
9972               ==, nghttp2_stream_get_state(stream));
9973 
9974   nghttp2_bufs_reset(&bufs);
9975 
9976   /* Receive push response for stream 2 without END_STREAM set */
9977   pack_headers(&bufs, &deflater, 2, NGHTTP2_FLAG_END_HEADERS, resnv,
9978                ARRLEN(resnv), mem);
9979 
9980   buf = &bufs.head->buf;
9981   rv = nghttp2_session_mem_recv2(session, buf->pos, nghttp2_buf_len(buf));
9982 
9983   assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(buf), ==, rv);
9984 
9985   stream = nghttp2_session_find_stream(session, 2);
9986 
9987   assert_enum(nghttp2_stream_proto_state,
9988               NGHTTP2_STREAM_STATE_HALF_CLOSED_LOCAL, ==,
9989               nghttp2_stream_get_state(stream));
9990 
9991   nghttp2_bufs_reset(&bufs);
9992 
9993   nghttp2_hd_deflate_free(&deflater);
9994   nghttp2_session_del(session);
9995 
9996   nghttp2_bufs_free(&bufs);
9997 }
9998 
test_nghttp2_session_stream_get_something(void)9999 void test_nghttp2_session_stream_get_something(void) {
10000   nghttp2_session *session;
10001   nghttp2_session_callbacks callbacks;
10002   nghttp2_stream *a, *b, *c;
10003 
10004   memset(&callbacks, 0, sizeof(callbacks));
10005 
10006   nghttp2_session_server_new(&session, &callbacks, NULL);
10007 
10008   a = open_stream(session, 1);
10009 
10010   assert_ptr_equal(nghttp2_session_get_root_stream(session),
10011                    nghttp2_stream_get_parent(a));
10012   assert_null(nghttp2_stream_get_previous_sibling(a));
10013   assert_null(nghttp2_stream_get_next_sibling(a));
10014   assert_null(nghttp2_stream_get_first_child(a));
10015 
10016   b = open_stream_with_dep(session, 3, a);
10017   c = open_stream_with_dep_weight(session, 5, 11, a);
10018 
10019   assert_ptr_equal(a, nghttp2_stream_get_parent(c));
10020   assert_ptr_equal(a, nghttp2_stream_get_parent(b));
10021 
10022   assert_ptr_equal(c, nghttp2_stream_get_first_child(a));
10023 
10024   assert_ptr_equal(b, nghttp2_stream_get_next_sibling(c));
10025   assert_ptr_equal(c, nghttp2_stream_get_previous_sibling(b));
10026 
10027   assert_int32(27, ==, nghttp2_stream_get_sum_dependency_weight(a));
10028 
10029   assert_int32(11, ==, nghttp2_stream_get_weight(c));
10030   assert_int32(5, ==, nghttp2_stream_get_stream_id(c));
10031   assert_int32(0, ==, nghttp2_stream_get_stream_id(&session->root));
10032 
10033   nghttp2_session_del(session);
10034 }
10035 
test_nghttp2_session_find_stream(void)10036 void test_nghttp2_session_find_stream(void) {
10037   nghttp2_session *session;
10038   nghttp2_session_callbacks callbacks;
10039   nghttp2_stream *stream;
10040 
10041   memset(&callbacks, 0, sizeof(callbacks));
10042 
10043   nghttp2_session_server_new(&session, &callbacks, NULL);
10044 
10045   open_recv_stream(session, 1);
10046 
10047   stream = nghttp2_session_find_stream(session, 1);
10048 
10049   assert_not_null(stream);
10050   assert_int32(1, ==, stream->stream_id);
10051 
10052   stream = nghttp2_session_find_stream(session, 0);
10053 
10054   assert_ptr_equal(&session->root, stream);
10055   assert_int32(0, ==, stream->stream_id);
10056 
10057   stream = nghttp2_session_find_stream(session, 2);
10058 
10059   assert_null(stream);
10060 
10061   nghttp2_session_del(session);
10062 }
10063 
test_nghttp2_session_keep_closed_stream(void)10064 void test_nghttp2_session_keep_closed_stream(void) {
10065   nghttp2_session *session;
10066   nghttp2_session_callbacks callbacks;
10067   const size_t max_concurrent_streams = 5;
10068   nghttp2_settings_entry iv = {NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS,
10069                                (uint32_t)max_concurrent_streams};
10070   size_t i;
10071 
10072   memset(&callbacks, 0, sizeof(callbacks));
10073   callbacks.send_callback2 = null_send_callback;
10074 
10075   nghttp2_session_server_new(&session, &callbacks, NULL);
10076 
10077   nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, &iv, 1);
10078 
10079   for (i = 0; i < max_concurrent_streams; ++i) {
10080     open_recv_stream(session, (int32_t)i * 2 + 1);
10081   }
10082 
10083   assert_size(0, ==, session->num_closed_streams);
10084 
10085   nghttp2_session_close_stream(session, 1, NGHTTP2_NO_ERROR);
10086 
10087   assert_size(1, ==, session->num_closed_streams);
10088   assert_int32(1, ==, session->closed_stream_tail->stream_id);
10089   assert_ptr_equal(session->closed_stream_tail, session->closed_stream_head);
10090 
10091   nghttp2_session_close_stream(session, 5, NGHTTP2_NO_ERROR);
10092 
10093   assert_size(2, ==, session->num_closed_streams);
10094   assert_int32(5, ==, session->closed_stream_tail->stream_id);
10095   assert_int32(1, ==, session->closed_stream_head->stream_id);
10096   assert_ptr_equal(session->closed_stream_head,
10097                    session->closed_stream_tail->closed_prev);
10098   assert_null(session->closed_stream_tail->closed_next);
10099   assert_ptr_equal(session->closed_stream_tail,
10100                    session->closed_stream_head->closed_next);
10101   assert_null(session->closed_stream_head->closed_prev);
10102 
10103   open_recv_stream(session, 11);
10104   nghttp2_session_adjust_closed_stream(session);
10105 
10106   assert_size(1, ==, session->num_closed_streams);
10107   assert_int32(5, ==, session->closed_stream_tail->stream_id);
10108   assert_ptr_equal(session->closed_stream_tail, session->closed_stream_head);
10109   assert_null(session->closed_stream_head->closed_prev);
10110   assert_null(session->closed_stream_head->closed_next);
10111 
10112   open_recv_stream(session, 13);
10113   nghttp2_session_adjust_closed_stream(session);
10114 
10115   assert_size(0, ==, session->num_closed_streams);
10116   assert_null(session->closed_stream_tail);
10117   assert_null(session->closed_stream_head);
10118 
10119   nghttp2_session_close_stream(session, 3, NGHTTP2_NO_ERROR);
10120 
10121   assert_size(1, ==, session->num_closed_streams);
10122   assert_int32(3, ==, session->closed_stream_head->stream_id);
10123 
10124   /* server initiated stream is not counted to max concurrent limit */
10125   open_sent_stream(session, 2);
10126   nghttp2_session_adjust_closed_stream(session);
10127 
10128   assert_size(1, ==, session->num_closed_streams);
10129   assert_int32(3, ==, session->closed_stream_head->stream_id);
10130 
10131   nghttp2_session_close_stream(session, 2, NGHTTP2_NO_ERROR);
10132 
10133   assert_size(1, ==, session->num_closed_streams);
10134   assert_int32(3, ==, session->closed_stream_head->stream_id);
10135 
10136   nghttp2_session_del(session);
10137 }
10138 
test_nghttp2_session_keep_idle_stream(void)10139 void test_nghttp2_session_keep_idle_stream(void) {
10140   nghttp2_session *session;
10141   nghttp2_session_callbacks callbacks;
10142   const size_t max_concurrent_streams = 1;
10143   nghttp2_settings_entry iv = {NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS,
10144                                (uint32_t)max_concurrent_streams};
10145   int i;
10146   int32_t stream_id;
10147 
10148   memset(&callbacks, 0, sizeof(callbacks));
10149   callbacks.send_callback2 = null_send_callback;
10150 
10151   nghttp2_session_server_new(&session, &callbacks, NULL);
10152 
10153   nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, &iv, 1);
10154 
10155   /* We at least allow NGHTTP2_MIN_IDLE_STREAM idle streams even if
10156      max concurrent streams is very low. */
10157   for (i = 0; i < NGHTTP2_MIN_IDLE_STREAMS; ++i) {
10158     open_recv_stream2(session, i * 2 + 1, NGHTTP2_STREAM_IDLE);
10159     nghttp2_session_adjust_idle_stream(session);
10160   }
10161 
10162   assert_size(NGHTTP2_MIN_IDLE_STREAMS, ==, session->num_idle_streams);
10163 
10164   stream_id = (NGHTTP2_MIN_IDLE_STREAMS - 1) * 2 + 1;
10165   assert_int32(1, ==, session->idle_stream_head->stream_id);
10166   assert_int32(stream_id, ==, session->idle_stream_tail->stream_id);
10167 
10168   stream_id += 2;
10169 
10170   open_recv_stream2(session, stream_id, NGHTTP2_STREAM_IDLE);
10171   nghttp2_session_adjust_idle_stream(session);
10172 
10173   assert_size(NGHTTP2_MIN_IDLE_STREAMS, ==, session->num_idle_streams);
10174   assert_int32(3, ==, session->idle_stream_head->stream_id);
10175   assert_int32(stream_id, ==, session->idle_stream_tail->stream_id);
10176 
10177   nghttp2_session_del(session);
10178 }
10179 
test_nghttp2_session_detach_idle_stream(void)10180 void test_nghttp2_session_detach_idle_stream(void) {
10181   nghttp2_session *session;
10182   nghttp2_session_callbacks callbacks;
10183   int i;
10184   nghttp2_stream *stream;
10185 
10186   memset(&callbacks, 0, sizeof(callbacks));
10187   callbacks.send_callback2 = null_send_callback;
10188 
10189   nghttp2_session_server_new(&session, &callbacks, NULL);
10190 
10191   for (i = 1; i <= 3; ++i) {
10192     nghttp2_session_open_stream(session, i, NGHTTP2_STREAM_FLAG_NONE,
10193                                 &pri_spec_default, NGHTTP2_STREAM_IDLE, NULL);
10194   }
10195 
10196   assert_size(3, ==, session->num_idle_streams);
10197 
10198   /* Detach middle stream */
10199   stream = nghttp2_session_get_stream_raw(session, 2);
10200 
10201   assert_ptr_equal(session->idle_stream_head, stream->closed_prev);
10202   assert_ptr_equal(session->idle_stream_tail, stream->closed_next);
10203   assert_ptr_equal(stream, session->idle_stream_head->closed_next);
10204   assert_ptr_equal(stream, session->idle_stream_tail->closed_prev);
10205 
10206   nghttp2_session_detach_idle_stream(session, stream);
10207 
10208   assert_size(2, ==, session->num_idle_streams);
10209 
10210   assert_null(stream->closed_prev);
10211   assert_null(stream->closed_next);
10212 
10213   assert_ptr_equal(session->idle_stream_head,
10214                    session->idle_stream_tail->closed_prev);
10215   assert_ptr_equal(session->idle_stream_tail,
10216                    session->idle_stream_head->closed_next);
10217 
10218   /* Detach head stream */
10219   stream = session->idle_stream_head;
10220 
10221   nghttp2_session_detach_idle_stream(session, stream);
10222 
10223   assert_size(1, ==, session->num_idle_streams);
10224 
10225   assert_ptr_equal(session->idle_stream_head, session->idle_stream_tail);
10226   assert_null(session->idle_stream_head->closed_prev);
10227   assert_null(session->idle_stream_head->closed_next);
10228 
10229   /* Detach last stream */
10230 
10231   stream = session->idle_stream_head;
10232 
10233   nghttp2_session_detach_idle_stream(session, stream);
10234 
10235   assert_size(0, ==, session->num_idle_streams);
10236 
10237   assert_null(session->idle_stream_head);
10238   assert_null(session->idle_stream_tail);
10239 
10240   for (i = 4; i <= 5; ++i) {
10241     nghttp2_session_open_stream(session, i, NGHTTP2_STREAM_FLAG_NONE,
10242                                 &pri_spec_default, NGHTTP2_STREAM_IDLE, NULL);
10243   }
10244 
10245   assert_size(2, ==, session->num_idle_streams);
10246 
10247   /* Detach tail stream */
10248 
10249   stream = session->idle_stream_tail;
10250 
10251   nghttp2_session_detach_idle_stream(session, stream);
10252 
10253   assert_size(1, ==, session->num_idle_streams);
10254 
10255   assert_ptr_equal(session->idle_stream_head, session->idle_stream_tail);
10256   assert_null(session->idle_stream_head->closed_prev);
10257   assert_null(session->idle_stream_head->closed_next);
10258 
10259   nghttp2_session_del(session);
10260 }
10261 
test_nghttp2_session_large_dep_tree(void)10262 void test_nghttp2_session_large_dep_tree(void) {
10263   nghttp2_session *session;
10264   nghttp2_session_callbacks callbacks;
10265   size_t i;
10266   nghttp2_stream *dep_stream = NULL;
10267   nghttp2_stream *stream;
10268   int32_t stream_id;
10269 
10270   memset(&callbacks, 0, sizeof(callbacks));
10271   callbacks.send_callback2 = null_send_callback;
10272 
10273   nghttp2_session_server_new(&session, &callbacks, NULL);
10274 
10275   stream_id = 1;
10276   for (i = 0; i < 250; ++i, stream_id += 2) {
10277     dep_stream = open_stream_with_dep(session, stream_id, dep_stream);
10278   }
10279 
10280   stream_id = 1;
10281   for (i = 0; i < 250; ++i, stream_id += 2) {
10282     stream = nghttp2_session_get_stream(session, stream_id);
10283     assert_true(nghttp2_stream_dep_find_ancestor(stream, &session->root));
10284     assert_true(nghttp2_stream_in_dep_tree(stream));
10285   }
10286 
10287   nghttp2_session_del(session);
10288 }
10289 
test_nghttp2_session_graceful_shutdown(void)10290 void test_nghttp2_session_graceful_shutdown(void) {
10291   nghttp2_session *session;
10292   nghttp2_session_callbacks callbacks;
10293   my_user_data ud;
10294 
10295   memset(&callbacks, 0, sizeof(callbacks));
10296   callbacks.send_callback2 = null_send_callback;
10297   callbacks.on_frame_send_callback = on_frame_send_callback;
10298   callbacks.on_stream_close_callback = on_stream_close_callback;
10299 
10300   nghttp2_session_server_new(&session, &callbacks, &ud);
10301 
10302   open_recv_stream(session, 301);
10303   open_sent_stream(session, 302);
10304   open_recv_stream(session, 309);
10305   open_recv_stream(session, 311);
10306   open_recv_stream(session, 319);
10307 
10308   assert_int(0, ==, nghttp2_submit_shutdown_notice(session));
10309 
10310   ud.frame_send_cb_called = 0;
10311 
10312   assert_int(0, ==, nghttp2_session_send(session));
10313 
10314   assert_int(1, ==, ud.frame_send_cb_called);
10315   assert_int32((1u << 31) - 1, ==, session->local_last_stream_id);
10316 
10317   assert_int(0, ==,
10318              nghttp2_submit_goaway(session, NGHTTP2_FLAG_NONE, 311,
10319                                    NGHTTP2_NO_ERROR, NULL, 0));
10320 
10321   ud.frame_send_cb_called = 0;
10322   ud.stream_close_cb_called = 0;
10323 
10324   assert_int(0, ==, nghttp2_session_send(session));
10325 
10326   assert_int(1, ==, ud.frame_send_cb_called);
10327   assert_int32(311, ==, session->local_last_stream_id);
10328   assert_int(1, ==, ud.stream_close_cb_called);
10329 
10330   assert_int(
10331     0, ==, nghttp2_session_terminate_session2(session, 301, NGHTTP2_NO_ERROR));
10332 
10333   ud.frame_send_cb_called = 0;
10334   ud.stream_close_cb_called = 0;
10335 
10336   assert_int(0, ==, nghttp2_session_send(session));
10337 
10338   assert_int(1, ==, ud.frame_send_cb_called);
10339   assert_int32(301, ==, session->local_last_stream_id);
10340   assert_int(2, ==, ud.stream_close_cb_called);
10341 
10342   assert_not_null(nghttp2_session_get_stream(session, 301));
10343   assert_not_null(nghttp2_session_get_stream(session, 302));
10344   assert_null(nghttp2_session_get_stream(session, 309));
10345   assert_null(nghttp2_session_get_stream(session, 311));
10346   assert_null(nghttp2_session_get_stream(session, 319));
10347 
10348   nghttp2_session_del(session);
10349 }
10350 
test_nghttp2_session_on_header_temporal_failure(void)10351 void test_nghttp2_session_on_header_temporal_failure(void) {
10352   nghttp2_session *session;
10353   nghttp2_session_callbacks callbacks;
10354   my_user_data ud;
10355   nghttp2_bufs bufs;
10356   nghttp2_buf *buf;
10357   nghttp2_hd_deflater deflater;
10358   nghttp2_nv nv[] = {MAKE_NV("alpha", "bravo"), MAKE_NV("charlie", "delta")};
10359   nghttp2_nv *nva;
10360   size_t hdpos;
10361   nghttp2_ssize rv;
10362   nghttp2_frame frame;
10363   nghttp2_frame_hd hd;
10364   nghttp2_outbound_item *item;
10365   nghttp2_mem *mem;
10366 
10367   mem = nghttp2_mem_default();
10368   memset(&callbacks, 0, sizeof(callbacks));
10369   callbacks.on_header_callback = temporal_failure_on_header_callback;
10370 
10371   nghttp2_session_server_new(&session, &callbacks, &ud);
10372 
10373   frame_pack_bufs_init(&bufs);
10374 
10375   nghttp2_hd_deflate_init(&deflater, mem);
10376 
10377   nghttp2_nv_array_copy(&nva, reqnv, ARRLEN(reqnv), mem);
10378 
10379   nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_STREAM, 1,
10380                              NGHTTP2_HCAT_REQUEST, NULL, nva, ARRLEN(reqnv));
10381   nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
10382   nghttp2_frame_headers_free(&frame.headers, mem);
10383 
10384   /* We are going to create CONTINUATION.  First serialize header
10385      block, and then frame header. */
10386   hdpos = nghttp2_bufs_len(&bufs);
10387 
10388   buf = &bufs.head->buf;
10389   buf->last += NGHTTP2_FRAME_HDLEN;
10390 
10391   nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, &nv[1], 1);
10392 
10393   nghttp2_frame_hd_init(&hd,
10394                         nghttp2_bufs_len(&bufs) - hdpos - NGHTTP2_FRAME_HDLEN,
10395                         NGHTTP2_CONTINUATION, NGHTTP2_FLAG_END_HEADERS, 1);
10396 
10397   nghttp2_frame_pack_frame_hd(&buf->pos[hdpos], &hd);
10398 
10399   ud.header_cb_called = 0;
10400   rv = nghttp2_session_mem_recv2(session, buf->pos, nghttp2_bufs_len(&bufs));
10401 
10402   assert_ptrdiff((nghttp2_ssize)nghttp2_bufs_len(&bufs), ==, rv);
10403   assert_int(1, ==, ud.header_cb_called);
10404 
10405   item = nghttp2_session_get_next_ob_item(session);
10406 
10407   assert_uint8(NGHTTP2_RST_STREAM, ==, item->frame.hd.type);
10408   assert_int32(1, ==, item->frame.hd.stream_id);
10409 
10410   /* Make sure no header decompression error occurred */
10411   assert_uint8(NGHTTP2_GOAWAY_NONE, ==, session->goaway_flags);
10412 
10413   nghttp2_hd_deflate_free(&deflater);
10414   nghttp2_session_del(session);
10415 
10416   nghttp2_bufs_reset(&bufs);
10417 
10418   /* Check for PUSH_PROMISE */
10419   nghttp2_hd_deflate_init(&deflater, mem);
10420   nghttp2_session_client_new(&session, &callbacks, &ud);
10421 
10422   open_sent_stream(session, 1);
10423 
10424   rv = pack_push_promise(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, 2,
10425                          reqnv, ARRLEN(reqnv), mem);
10426   assert_ptrdiff(0, ==, rv);
10427 
10428   ud.header_cb_called = 0;
10429   rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
10430                                  nghttp2_bufs_len(&bufs));
10431   assert_ptrdiff((nghttp2_ssize)nghttp2_bufs_len(&bufs), ==, rv);
10432   assert_int(1, ==, ud.header_cb_called);
10433 
10434   item = nghttp2_session_get_next_ob_item(session);
10435   assert_uint8(NGHTTP2_RST_STREAM, ==, item->frame.hd.type);
10436   assert_int32(2, ==, item->frame.hd.stream_id);
10437   assert_uint32(NGHTTP2_INTERNAL_ERROR, ==, item->frame.rst_stream.error_code);
10438 
10439   nghttp2_session_del(session);
10440   nghttp2_hd_deflate_free(&deflater);
10441   nghttp2_bufs_free(&bufs);
10442 }
10443 
test_nghttp2_session_recv_client_magic(void)10444 void test_nghttp2_session_recv_client_magic(void) {
10445   nghttp2_session *session;
10446   nghttp2_session_callbacks callbacks;
10447   nghttp2_ssize rv;
10448   nghttp2_frame ping_frame;
10449   uint8_t buf[16];
10450 
10451   /* enable global nghttp2_enable_strict_preface here */
10452   nghttp2_enable_strict_preface = 1;
10453 
10454   memset(&callbacks, 0, sizeof(callbacks));
10455 
10456   /* Check success case */
10457   nghttp2_session_server_new(&session, &callbacks, NULL);
10458 
10459   rv = nghttp2_session_mem_recv2(session, (const uint8_t *)NGHTTP2_CLIENT_MAGIC,
10460                                  NGHTTP2_CLIENT_MAGIC_LEN);
10461 
10462   assert_ptrdiff(NGHTTP2_CLIENT_MAGIC_LEN, ==, rv);
10463   assert_enum(nghttp2_inbound_state, NGHTTP2_IB_READ_FIRST_SETTINGS, ==,
10464               session->iframe.state);
10465 
10466   /* Receiving PING is error because we want SETTINGS. */
10467   nghttp2_frame_ping_init(&ping_frame.ping, NGHTTP2_FLAG_NONE, NULL);
10468 
10469   nghttp2_frame_pack_frame_hd(buf, &ping_frame.ping.hd);
10470 
10471   rv = nghttp2_session_mem_recv2(session, buf, NGHTTP2_FRAME_HDLEN);
10472   assert_ptrdiff(NGHTTP2_FRAME_HDLEN, ==, rv);
10473   assert_enum(nghttp2_inbound_state, NGHTTP2_IB_IGN_ALL, ==,
10474               session->iframe.state);
10475   assert_size(0, ==, session->iframe.payloadleft);
10476 
10477   nghttp2_frame_ping_free(&ping_frame.ping);
10478 
10479   nghttp2_session_del(session);
10480 
10481   /* Check bad case */
10482   nghttp2_session_server_new(&session, &callbacks, NULL);
10483 
10484   /* Feed magic with one byte less */
10485   rv = nghttp2_session_mem_recv2(session, (const uint8_t *)NGHTTP2_CLIENT_MAGIC,
10486                                  NGHTTP2_CLIENT_MAGIC_LEN - 1);
10487 
10488   assert_ptrdiff(NGHTTP2_CLIENT_MAGIC_LEN - 1, ==, rv);
10489   assert_enum(nghttp2_inbound_state, NGHTTP2_IB_READ_CLIENT_MAGIC, ==,
10490               session->iframe.state);
10491   assert_size(1, ==, session->iframe.payloadleft);
10492 
10493   rv = nghttp2_session_mem_recv2(session, (const uint8_t *)"\0", 1);
10494 
10495   assert_ptrdiff(NGHTTP2_ERR_BAD_CLIENT_MAGIC, ==, rv);
10496 
10497   nghttp2_session_del(session);
10498 
10499   /* disable global nghttp2_enable_strict_preface here */
10500   nghttp2_enable_strict_preface = 0;
10501 }
10502 
test_nghttp2_session_delete_data_item(void)10503 void test_nghttp2_session_delete_data_item(void) {
10504   nghttp2_session *session;
10505   nghttp2_session_callbacks callbacks;
10506   nghttp2_stream *a;
10507   nghttp2_data_provider2 prd;
10508 
10509   memset(&callbacks, 0, sizeof(callbacks));
10510 
10511   nghttp2_session_server_new(&session, &callbacks, NULL);
10512 
10513   a = open_recv_stream(session, 1);
10514   open_recv_stream_with_dep(session, 3, a);
10515 
10516   /* We don't care about these members, since we won't send data */
10517   prd.source.ptr = NULL;
10518   prd.read_callback = fail_data_source_read_callback;
10519 
10520   assert_int(0, ==, nghttp2_submit_data2(session, NGHTTP2_FLAG_NONE, 1, &prd));
10521   assert_int(0, ==, nghttp2_submit_data2(session, NGHTTP2_FLAG_NONE, 3, &prd));
10522 
10523   nghttp2_session_del(session);
10524 }
10525 
test_nghttp2_session_open_idle_stream(void)10526 void test_nghttp2_session_open_idle_stream(void) {
10527   nghttp2_session *session;
10528   nghttp2_session_callbacks callbacks;
10529   nghttp2_stream *stream;
10530   nghttp2_stream *opened_stream;
10531   nghttp2_priority_spec pri_spec;
10532   nghttp2_frame frame;
10533   nghttp2_ext_priority_update priority_update;
10534 
10535   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
10536 
10537   nghttp2_session_server_new(&session, &callbacks, NULL);
10538 
10539   nghttp2_priority_spec_init(&pri_spec, 0, 3, 0);
10540 
10541   nghttp2_frame_priority_init(&frame.priority, 1, &pri_spec);
10542 
10543   assert_int(0, ==, nghttp2_session_on_priority_received(session, &frame));
10544 
10545   stream = nghttp2_session_get_stream_raw(session, 1);
10546 
10547   assert_enum(nghttp2_stream_state, NGHTTP2_STREAM_IDLE, ==, stream->state);
10548   assert_null(stream->closed_prev);
10549   assert_null(stream->closed_next);
10550   assert_size(1, ==, session->num_idle_streams);
10551   assert_ptr_equal(session->idle_stream_head, stream);
10552   assert_ptr_equal(session->idle_stream_tail, stream);
10553 
10554   opened_stream = open_recv_stream2(session, 1, NGHTTP2_STREAM_OPENING);
10555 
10556   assert_ptr_equal(stream, opened_stream);
10557   assert_enum(nghttp2_stream_state, NGHTTP2_STREAM_OPENING, ==, stream->state);
10558   assert_size(0, ==, session->num_idle_streams);
10559   assert_null(session->idle_stream_head);
10560   assert_null(session->idle_stream_tail);
10561 
10562   nghttp2_frame_priority_free(&frame.priority);
10563 
10564   nghttp2_session_del(session);
10565 
10566   /* No RFC 7540 priorities */
10567   nghttp2_session_server_new(&session, &callbacks, NULL);
10568 
10569   session->pending_no_rfc7540_priorities = 1;
10570 
10571   frame.ext.payload = &priority_update;
10572 
10573   nghttp2_frame_priority_update_init(&frame.ext, 1, (uint8_t *)"u=3",
10574                                      strlen("u=3"));
10575 
10576   assert_int(0, ==,
10577              nghttp2_session_on_priority_update_received(session, &frame));
10578 
10579   stream = nghttp2_session_get_stream_raw(session, 1);
10580 
10581   assert_enum(nghttp2_stream_state, NGHTTP2_STREAM_IDLE, ==, stream->state);
10582   assert_null(stream->closed_next);
10583   assert_size(1, ==, session->num_idle_streams);
10584 
10585   opened_stream = open_recv_stream2(session, 1, NGHTTP2_STREAM_OPENING);
10586 
10587   assert_ptr_equal(stream, opened_stream);
10588   assert_enum(nghttp2_stream_state, NGHTTP2_STREAM_OPENING, ==, stream->state);
10589   assert_size(0, ==, session->num_idle_streams);
10590 
10591   nghttp2_frame_priority_free(&frame.priority);
10592 
10593   nghttp2_session_del(session);
10594 }
10595 
test_nghttp2_session_cancel_reserved_remote(void)10596 void test_nghttp2_session_cancel_reserved_remote(void) {
10597   nghttp2_session *session;
10598   nghttp2_session_callbacks callbacks;
10599   nghttp2_stream *stream;
10600   nghttp2_frame frame;
10601   nghttp2_nv *nva;
10602   size_t nvlen;
10603   nghttp2_hd_deflater deflater;
10604   nghttp2_mem *mem;
10605   nghttp2_bufs bufs;
10606   nghttp2_ssize rv;
10607 
10608   mem = nghttp2_mem_default();
10609   frame_pack_bufs_init(&bufs);
10610 
10611   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
10612   callbacks.send_callback2 = null_send_callback;
10613 
10614   nghttp2_session_client_new(&session, &callbacks, NULL);
10615 
10616   nghttp2_hd_deflate_init(&deflater, mem);
10617 
10618   stream = open_recv_stream2(session, 2, NGHTTP2_STREAM_RESERVED);
10619 
10620   nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, 2, NGHTTP2_CANCEL);
10621 
10622   assert_enum(nghttp2_stream_state, NGHTTP2_STREAM_CLOSING, ==, stream->state);
10623 
10624   assert_int(0, ==, nghttp2_session_send(session));
10625 
10626   nvlen = ARRLEN(resnv);
10627   nghttp2_nv_array_copy(&nva, resnv, nvlen, mem);
10628 
10629   nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 2,
10630                              NGHTTP2_HCAT_PUSH_RESPONSE, NULL, nva, nvlen);
10631   rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
10632 
10633   assert_ptrdiff(0, ==, rv);
10634 
10635   rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
10636                                  nghttp2_buf_len(&bufs.head->buf));
10637 
10638   assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(&bufs.head->buf), ==, rv);
10639 
10640   /* stream is not dangling, so assign NULL */
10641   stream = NULL;
10642 
10643   /* No RST_STREAM or GOAWAY is generated since stream should be in
10644      NGHTTP2_STREAM_CLOSING and push response should be ignored. */
10645   assert_size(0, ==, nghttp2_outbound_queue_size(&session->ob_reg));
10646 
10647   /* Check that we can receive push response HEADERS while RST_STREAM
10648      is just queued. */
10649   open_recv_stream2(session, 4, NGHTTP2_STREAM_RESERVED);
10650 
10651   nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, 2, NGHTTP2_CANCEL);
10652 
10653   nghttp2_bufs_reset(&bufs);
10654 
10655   frame.hd.stream_id = 4;
10656   rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
10657 
10658   assert_ptrdiff(0, ==, rv);
10659 
10660   rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
10661                                  nghttp2_buf_len(&bufs.head->buf));
10662 
10663   assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(&bufs.head->buf), ==, rv);
10664 
10665   assert_size(1, ==, nghttp2_outbound_queue_size(&session->ob_reg));
10666 
10667   nghttp2_frame_headers_free(&frame.headers, mem);
10668 
10669   nghttp2_hd_deflate_free(&deflater);
10670 
10671   nghttp2_session_del(session);
10672 
10673   nghttp2_bufs_free(&bufs);
10674 }
10675 
test_nghttp2_session_reset_pending_headers(void)10676 void test_nghttp2_session_reset_pending_headers(void) {
10677   nghttp2_session *session;
10678   nghttp2_session_callbacks callbacks;
10679   nghttp2_stream *stream;
10680   int32_t stream_id;
10681   my_user_data ud;
10682 
10683   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
10684   callbacks.send_callback2 = null_send_callback;
10685   callbacks.on_frame_send_callback = on_frame_send_callback;
10686   callbacks.on_frame_not_send_callback = on_frame_not_send_callback;
10687   callbacks.on_stream_close_callback = on_stream_close_callback;
10688 
10689   nghttp2_session_client_new(&session, &callbacks, &ud);
10690 
10691   stream_id = nghttp2_submit_request2(session, NULL, NULL, 0, NULL, NULL);
10692   assert_int32(1, <=, stream_id);
10693 
10694   nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, stream_id,
10695                             NGHTTP2_CANCEL);
10696 
10697   session->remote_settings.max_concurrent_streams = 0;
10698 
10699   /* RST_STREAM cancels pending HEADERS and is not actually sent. */
10700   ud.frame_send_cb_called = 0;
10701   assert_int(0, ==, nghttp2_session_send(session));
10702 
10703   assert_int(0, ==, ud.frame_send_cb_called);
10704 
10705   stream = nghttp2_session_get_stream(session, stream_id);
10706 
10707   assert_null(stream);
10708 
10709   /* See HEADERS is not sent.  on_stream_close is called just like
10710      transmission failure. */
10711   session->remote_settings.max_concurrent_streams = 1;
10712 
10713   ud.frame_not_send_cb_called = 0;
10714   ud.stream_close_error_code = 0;
10715   assert_int(0, ==, nghttp2_session_send(session));
10716 
10717   assert_int(1, ==, ud.frame_not_send_cb_called);
10718   assert_uint8(NGHTTP2_HEADERS, ==, ud.not_sent_frame_type);
10719   assert_uint32(NGHTTP2_CANCEL, ==, ud.stream_close_error_code);
10720 
10721   stream = nghttp2_session_get_stream(session, stream_id);
10722 
10723   assert_null(stream);
10724 
10725   nghttp2_session_del(session);
10726 }
10727 
test_nghttp2_session_send_data_callback(void)10728 void test_nghttp2_session_send_data_callback(void) {
10729   nghttp2_session *session;
10730   nghttp2_session_callbacks callbacks;
10731   nghttp2_data_provider2 data_prd;
10732   my_user_data ud;
10733   accumulator acc;
10734   nghttp2_frame_hd hd;
10735 
10736   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
10737   callbacks.send_callback2 = accumulator_send_callback;
10738   callbacks.send_data_callback = send_data_callback;
10739 
10740   data_prd.read_callback = no_copy_data_source_read_callback;
10741 
10742   acc.length = 0;
10743   ud.acc = &acc;
10744 
10745   ud.data_source_length = NGHTTP2_DATA_PAYLOADLEN * 2;
10746 
10747   nghttp2_session_client_new(&session, &callbacks, &ud);
10748 
10749   open_sent_stream(session, 1);
10750 
10751   nghttp2_submit_data2(session, NGHTTP2_FLAG_END_STREAM, 1, &data_prd);
10752 
10753   assert_int(0, ==, nghttp2_session_send(session));
10754 
10755   assert_size((NGHTTP2_FRAME_HDLEN + NGHTTP2_DATA_PAYLOADLEN) * 2, ==,
10756               acc.length);
10757 
10758   nghttp2_frame_unpack_frame_hd(&hd, acc.buf);
10759 
10760   assert_size(16384, ==, hd.length);
10761   assert_uint8(NGHTTP2_DATA, ==, hd.type);
10762   assert_uint8(NGHTTP2_FLAG_NONE, ==, hd.flags);
10763 
10764   nghttp2_frame_unpack_frame_hd(&hd, acc.buf + NGHTTP2_FRAME_HDLEN + hd.length);
10765 
10766   assert_size(16384, ==, hd.length);
10767   assert_uint8(NGHTTP2_DATA, ==, hd.type);
10768   assert_uint8(NGHTTP2_FLAG_END_STREAM, ==, hd.flags);
10769 
10770   nghttp2_session_del(session);
10771 }
10772 
test_nghttp2_session_on_begin_headers_temporal_failure(void)10773 void test_nghttp2_session_on_begin_headers_temporal_failure(void) {
10774   nghttp2_session *session;
10775   nghttp2_session_callbacks callbacks;
10776   my_user_data ud;
10777   nghttp2_bufs bufs;
10778   nghttp2_mem *mem;
10779   nghttp2_ssize rv;
10780   nghttp2_hd_deflater deflater;
10781   nghttp2_outbound_item *item;
10782 
10783   mem = nghttp2_mem_default();
10784   frame_pack_bufs_init(&bufs);
10785   nghttp2_hd_deflate_init(&deflater, mem);
10786 
10787   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
10788   callbacks.on_begin_headers_callback =
10789     temporal_failure_on_begin_headers_callback;
10790   callbacks.on_header_callback = on_header_callback;
10791   callbacks.on_frame_recv_callback = on_frame_recv_callback;
10792   callbacks.send_callback2 = null_send_callback;
10793   nghttp2_session_server_new(&session, &callbacks, &ud);
10794 
10795   rv = pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, reqnv,
10796                     ARRLEN(reqnv), mem);
10797   assert_ptrdiff(0, ==, rv);
10798 
10799   ud.header_cb_called = 0;
10800   ud.frame_recv_cb_called = 0;
10801   rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
10802                                  nghttp2_bufs_len(&bufs));
10803   assert_ptrdiff((nghttp2_ssize)nghttp2_bufs_len(&bufs), ==, rv);
10804   assert_int(0, ==, ud.header_cb_called);
10805   assert_int(0, ==, ud.frame_recv_cb_called);
10806 
10807   item = nghttp2_session_get_next_ob_item(session);
10808   assert_uint8(NGHTTP2_RST_STREAM, ==, item->frame.hd.type);
10809   assert_int32(1, ==, item->frame.hd.stream_id);
10810   assert_uint32(NGHTTP2_INTERNAL_ERROR, ==, item->frame.rst_stream.error_code);
10811 
10812   nghttp2_session_del(session);
10813   nghttp2_hd_deflate_free(&deflater);
10814 
10815   nghttp2_bufs_reset(&bufs);
10816   /* check for PUSH_PROMISE */
10817   nghttp2_hd_deflate_init(&deflater, mem);
10818   nghttp2_session_client_new(&session, &callbacks, &ud);
10819 
10820   open_sent_stream(session, 1);
10821 
10822   rv = pack_push_promise(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, 2,
10823                          reqnv, ARRLEN(reqnv), mem);
10824   assert_ptrdiff(0, ==, rv);
10825 
10826   ud.header_cb_called = 0;
10827   ud.frame_recv_cb_called = 0;
10828   rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
10829                                  nghttp2_bufs_len(&bufs));
10830   assert_ptrdiff((nghttp2_ssize)nghttp2_bufs_len(&bufs), ==, rv);
10831   assert_int(0, ==, ud.header_cb_called);
10832   assert_int(0, ==, ud.frame_recv_cb_called);
10833 
10834   item = nghttp2_session_get_next_ob_item(session);
10835   assert_uint8(NGHTTP2_RST_STREAM, ==, item->frame.hd.type);
10836   assert_int32(2, ==, item->frame.hd.stream_id);
10837   assert_uint32(NGHTTP2_INTERNAL_ERROR, ==, item->frame.rst_stream.error_code);
10838 
10839   nghttp2_session_del(session);
10840   nghttp2_hd_deflate_free(&deflater);
10841   nghttp2_bufs_free(&bufs);
10842 }
10843 
test_nghttp2_session_defer_then_close(void)10844 void test_nghttp2_session_defer_then_close(void) {
10845   nghttp2_session *session;
10846   nghttp2_session_callbacks callbacks;
10847   nghttp2_data_provider2 prd;
10848   int rv;
10849   const uint8_t *datap;
10850   nghttp2_ssize datalen;
10851   nghttp2_frame frame;
10852 
10853   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
10854   callbacks.send_callback2 = null_send_callback;
10855 
10856   nghttp2_session_client_new(&session, &callbacks, NULL);
10857 
10858   prd.read_callback = defer_data_source_read_callback;
10859 
10860   rv = nghttp2_submit_request2(session, NULL, reqnv, ARRLEN(reqnv), &prd, NULL);
10861   assert_ptrdiff(0, <, rv);
10862 
10863   /* This sends HEADERS */
10864   datalen = nghttp2_session_mem_send2(session, &datap);
10865 
10866   assert_ptrdiff(0, <, datalen);
10867 
10868   /* This makes DATA item deferred */
10869   datalen = nghttp2_session_mem_send2(session, &datap);
10870 
10871   assert_ptrdiff(0, ==, datalen);
10872 
10873   nghttp2_frame_rst_stream_init(&frame.rst_stream, 1, NGHTTP2_CANCEL);
10874 
10875   /* Assertion failure; GH-264 */
10876   rv = nghttp2_session_on_rst_stream_received(session, &frame);
10877 
10878   assert_int(0, ==, rv);
10879 
10880   nghttp2_session_del(session);
10881 }
10882 
submit_response_on_stream_close(nghttp2_session * session,int32_t stream_id,uint32_t error_code,void * user_data)10883 static int submit_response_on_stream_close(nghttp2_session *session,
10884                                            int32_t stream_id,
10885                                            uint32_t error_code,
10886                                            void *user_data) {
10887   nghttp2_data_provider2 data_prd;
10888   (void)error_code;
10889   (void)user_data;
10890 
10891   data_prd.read_callback = temporal_failure_data_source_read_callback;
10892 
10893   // Attempt to submit response or data to the stream being closed
10894   switch (stream_id) {
10895   case 1:
10896     assert_int(0, ==,
10897                nghttp2_submit_response2(session, stream_id, resnv,
10898                                         ARRLEN(resnv), &data_prd));
10899     break;
10900   case 3:
10901     assert_int(
10902       0, ==,
10903       nghttp2_submit_data2(session, NGHTTP2_FLAG_NONE, stream_id, &data_prd));
10904     break;
10905   }
10906 
10907   return 0;
10908 }
10909 
test_nghttp2_session_detach_item_from_closed_stream(void)10910 void test_nghttp2_session_detach_item_from_closed_stream(void) {
10911   nghttp2_session *session;
10912   nghttp2_session_callbacks callbacks;
10913 
10914   memset(&callbacks, 0, sizeof(callbacks));
10915 
10916   callbacks.send_callback2 = null_send_callback;
10917   callbacks.on_stream_close_callback = submit_response_on_stream_close;
10918 
10919   nghttp2_session_server_new(&session, &callbacks, NULL);
10920 
10921   open_recv_stream(session, 1);
10922   open_recv_stream(session, 3);
10923 
10924   nghttp2_session_close_stream(session, 1, NGHTTP2_NO_ERROR);
10925   nghttp2_session_close_stream(session, 3, NGHTTP2_NO_ERROR);
10926 
10927   assert_int(0, ==, nghttp2_session_send(session));
10928 
10929   nghttp2_session_del(session);
10930 
10931   /* No RFC 7540 priorities */
10932   nghttp2_session_server_new(&session, &callbacks, NULL);
10933 
10934   session->pending_no_rfc7540_priorities = 1;
10935 
10936   open_recv_stream(session, 1);
10937   open_recv_stream(session, 3);
10938 
10939   nghttp2_session_close_stream(session, 1, NGHTTP2_NO_ERROR);
10940   nghttp2_session_close_stream(session, 3, NGHTTP2_NO_ERROR);
10941 
10942   assert_int(0, ==, nghttp2_session_send(session));
10943 
10944   nghttp2_session_del(session);
10945 }
10946 
test_nghttp2_session_flooding(void)10947 void test_nghttp2_session_flooding(void) {
10948   nghttp2_session *session;
10949   nghttp2_session_callbacks callbacks;
10950   nghttp2_bufs bufs;
10951   nghttp2_buf *buf;
10952   nghttp2_frame frame;
10953   nghttp2_mem *mem;
10954   size_t i;
10955 
10956   mem = nghttp2_mem_default();
10957 
10958   frame_pack_bufs_init(&bufs);
10959 
10960   memset(&callbacks, 0, sizeof(callbacks));
10961 
10962   /* PING ACK */
10963   nghttp2_session_server_new(&session, &callbacks, NULL);
10964 
10965   nghttp2_frame_ping_init(&frame.ping, NGHTTP2_FLAG_NONE, NULL);
10966   nghttp2_frame_pack_ping(&bufs, &frame.ping);
10967   nghttp2_frame_ping_free(&frame.ping);
10968 
10969   buf = &bufs.head->buf;
10970 
10971   for (i = 0; i < NGHTTP2_DEFAULT_MAX_OBQ_FLOOD_ITEM; ++i) {
10972     assert_ptrdiff(
10973       (nghttp2_ssize)nghttp2_buf_len(buf), ==,
10974       nghttp2_session_mem_recv2(session, buf->pos, nghttp2_buf_len(buf)));
10975   }
10976 
10977   assert_ptrdiff(
10978     NGHTTP2_ERR_FLOODED, ==,
10979     nghttp2_session_mem_recv2(session, buf->pos, nghttp2_buf_len(buf)));
10980 
10981   nghttp2_session_del(session);
10982 
10983   /* SETTINGS ACK */
10984   nghttp2_bufs_reset(&bufs);
10985 
10986   nghttp2_session_server_new(&session, &callbacks, NULL);
10987 
10988   nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE, NULL, 0);
10989   nghttp2_frame_pack_settings(&bufs, &frame.settings);
10990   nghttp2_frame_settings_free(&frame.settings, mem);
10991 
10992   buf = &bufs.head->buf;
10993 
10994   for (i = 0; i < NGHTTP2_DEFAULT_MAX_OBQ_FLOOD_ITEM; ++i) {
10995     assert_ptrdiff(
10996       (nghttp2_ssize)nghttp2_buf_len(buf), ==,
10997       nghttp2_session_mem_recv2(session, buf->pos, nghttp2_buf_len(buf)));
10998   }
10999 
11000   assert_ptrdiff(
11001     NGHTTP2_ERR_FLOODED, ==,
11002     nghttp2_session_mem_recv2(session, buf->pos, nghttp2_buf_len(buf)));
11003 
11004   nghttp2_session_del(session);
11005   nghttp2_bufs_free(&bufs);
11006 }
11007 
test_nghttp2_session_change_stream_priority(void)11008 void test_nghttp2_session_change_stream_priority(void) {
11009   nghttp2_session *session;
11010   nghttp2_session_callbacks callbacks;
11011   nghttp2_stream *stream1, *stream2, *stream3, *stream5;
11012   nghttp2_priority_spec pri_spec;
11013   int rv;
11014 
11015   memset(&callbacks, 0, sizeof(callbacks));
11016 
11017   nghttp2_session_server_new(&session, &callbacks, NULL);
11018 
11019   stream1 = open_recv_stream(session, 1);
11020   stream3 = open_recv_stream_with_dep_weight(session, 3, 199, stream1);
11021   stream2 = open_sent_stream_with_dep_weight(session, 2, 101, stream3);
11022 
11023   nghttp2_priority_spec_init(&pri_spec, 1, 256, 0);
11024 
11025   rv = nghttp2_session_change_stream_priority(session, 2, &pri_spec);
11026 
11027   assert_int(0, ==, rv);
11028 
11029   assert_ptr_equal(stream1, stream2->dep_prev);
11030   assert_int32(256, ==, stream2->weight);
11031 
11032   /* Cannot change stream which does not exist */
11033   rv = nghttp2_session_change_stream_priority(session, 5, &pri_spec);
11034   assert_int(NGHTTP2_ERR_INVALID_ARGUMENT, ==, rv);
11035 
11036   /* It is an error to depend on itself */
11037   rv = nghttp2_session_change_stream_priority(session, 1, &pri_spec);
11038   assert_int(NGHTTP2_ERR_INVALID_ARGUMENT, ==, rv);
11039 
11040   /* It is an error to change priority of root stream (0) */
11041   rv = nghttp2_session_change_stream_priority(session, 0, &pri_spec);
11042   assert_int(NGHTTP2_ERR_INVALID_ARGUMENT, ==, rv);
11043 
11044   /* Depends on the non-existing idle stream.  This creates that idle
11045      stream. */
11046   nghttp2_priority_spec_init(&pri_spec, 5, 9, 1);
11047 
11048   rv = nghttp2_session_change_stream_priority(session, 2, &pri_spec);
11049 
11050   assert_int(0, ==, rv);
11051 
11052   stream5 = nghttp2_session_get_stream_raw(session, 5);
11053 
11054   assert_not_null(stream5);
11055   assert_ptr_equal(&session->root, stream5->dep_prev);
11056   assert_ptr_equal(stream5, stream2->dep_prev);
11057   assert_int32(9, ==, stream2->weight);
11058 
11059   nghttp2_session_del(session);
11060 
11061   /* Check that this works in client session too */
11062   nghttp2_session_client_new(&session, &callbacks, NULL);
11063 
11064   stream1 = open_sent_stream(session, 1);
11065 
11066   nghttp2_priority_spec_init(&pri_spec, 5, 9, 1);
11067 
11068   rv = nghttp2_session_change_stream_priority(session, 1, &pri_spec);
11069 
11070   assert_int(0, ==, rv);
11071 
11072   stream5 = nghttp2_session_get_stream_raw(session, 5);
11073 
11074   assert_not_null(stream5);
11075   assert_ptr_equal(&session->root, stream5->dep_prev);
11076   assert_ptr_equal(stream5, stream1->dep_prev);
11077   assert_int32(9, ==, stream1->weight);
11078 
11079   nghttp2_session_del(session);
11080 }
11081 
test_nghttp2_session_change_extpri_stream_priority(void)11082 void test_nghttp2_session_change_extpri_stream_priority(void) {
11083   nghttp2_session *session;
11084   nghttp2_session_callbacks callbacks;
11085   nghttp2_bufs bufs;
11086   nghttp2_buf *buf;
11087   nghttp2_ssize rv;
11088   nghttp2_option *option;
11089   nghttp2_extension frame;
11090   nghttp2_ext_priority_update priority_update;
11091   nghttp2_extpri extpri, nextpri;
11092   nghttp2_stream *stream;
11093   static const uint8_t field_value[] = "u=2";
11094 
11095   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
11096 
11097   frame_pack_bufs_init(&bufs);
11098 
11099   nghttp2_option_new(&option);
11100   nghttp2_option_set_builtin_recv_extension_type(option,
11101                                                  NGHTTP2_PRIORITY_UPDATE);
11102 
11103   nghttp2_session_server_new2(&session, &callbacks, NULL, option);
11104 
11105   session->pending_no_rfc7540_priorities = 1;
11106 
11107   open_recv_stream(session, 1);
11108 
11109   extpri.urgency = NGHTTP2_EXTPRI_URGENCY_LOW + 1;
11110   extpri.inc = 1;
11111 
11112   rv = nghttp2_session_change_extpri_stream_priority(
11113     session, 1, &extpri, /* ignore_client_signal = */ 0);
11114 
11115   assert_ptrdiff(0, ==, rv);
11116 
11117   stream = nghttp2_session_get_stream(session, 1);
11118 
11119   assert_uint32(NGHTTP2_EXTPRI_URGENCY_LOW, ==,
11120                 nghttp2_extpri_uint8_urgency(stream->extpri));
11121   assert_true(nghttp2_extpri_uint8_inc(stream->extpri));
11122 
11123   rv = nghttp2_session_get_extpri_stream_priority(session, &nextpri, 1);
11124 
11125   assert_ptrdiff(0, ==, rv);
11126   assert_uint32(NGHTTP2_EXTPRI_URGENCY_LOW, ==, nextpri.urgency);
11127   assert_true(nextpri.inc);
11128 
11129   /* Client can still update stream priority. */
11130   frame.payload = &priority_update;
11131   nghttp2_frame_priority_update_init(&frame, 1, (uint8_t *)field_value,
11132                                      sizeof(field_value) - 1);
11133   nghttp2_frame_pack_priority_update(&bufs, &frame);
11134 
11135   buf = &bufs.head->buf;
11136   rv = nghttp2_session_mem_recv2(session, buf->pos, nghttp2_buf_len(buf));
11137 
11138   assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(buf), ==, rv);
11139   assert_uint8(2, ==, stream->extpri);
11140 
11141   /* Start to ignore client priority signal for this stream. */
11142   rv = nghttp2_session_change_extpri_stream_priority(
11143     session, 1, &extpri, /* ignore_client_signal = */ 1);
11144 
11145   assert_ptrdiff(0, ==, rv);
11146 
11147   stream = nghttp2_session_get_stream(session, 1);
11148 
11149   assert_uint32(NGHTTP2_EXTPRI_URGENCY_LOW, ==,
11150                 nghttp2_extpri_uint8_urgency(stream->extpri));
11151   assert_true(nghttp2_extpri_uint8_inc(stream->extpri));
11152 
11153   buf = &bufs.head->buf;
11154   rv = nghttp2_session_mem_recv2(session, buf->pos, nghttp2_buf_len(buf));
11155 
11156   assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(buf), ==, rv);
11157   assert_uint32(NGHTTP2_EXTPRI_URGENCY_LOW, ==,
11158                 nghttp2_extpri_uint8_urgency(stream->extpri));
11159   assert_true(nghttp2_extpri_uint8_inc(stream->extpri));
11160 
11161   nghttp2_session_del(session);
11162   nghttp2_option_del(option);
11163   nghttp2_bufs_free(&bufs);
11164 }
11165 
test_nghttp2_session_create_idle_stream(void)11166 void test_nghttp2_session_create_idle_stream(void) {
11167   nghttp2_session *session;
11168   nghttp2_session_callbacks callbacks;
11169   nghttp2_stream *stream2, *stream4, *stream8, *stream10;
11170   nghttp2_priority_spec pri_spec;
11171   int rv;
11172   int i;
11173 
11174   memset(&callbacks, 0, sizeof(callbacks));
11175   callbacks.send_callback2 = null_send_callback;
11176 
11177   nghttp2_session_server_new(&session, &callbacks, NULL);
11178 
11179   stream2 = open_sent_stream(session, 2);
11180 
11181   nghttp2_priority_spec_init(&pri_spec, 2, 111, 1);
11182 
11183   rv = nghttp2_session_create_idle_stream(session, 4, &pri_spec);
11184 
11185   assert_int(0, ==, rv);
11186 
11187   stream4 = nghttp2_session_get_stream_raw(session, 4);
11188 
11189   assert_int32(4, ==, stream4->stream_id);
11190   assert_int32(111, ==, stream4->weight);
11191   assert_ptr_equal(stream2, stream4->dep_prev);
11192   assert_ptr_equal(stream4, stream2->dep_next);
11193 
11194   /* If pri_spec->stream_id does not exist, and it is idle stream, it
11195      is created too */
11196   nghttp2_priority_spec_init(&pri_spec, 10, 109, 0);
11197 
11198   rv = nghttp2_session_create_idle_stream(session, 8, &pri_spec);
11199 
11200   assert_int(0, ==, rv);
11201 
11202   stream8 = nghttp2_session_get_stream_raw(session, 8);
11203   stream10 = nghttp2_session_get_stream_raw(session, 10);
11204 
11205   assert_int32(8, ==, stream8->stream_id);
11206   assert_int32(109, ==, stream8->weight);
11207   assert_int32(10, ==, stream10->stream_id);
11208   assert_int32(16, ==, stream10->weight);
11209   assert_ptr_equal(stream10, stream8->dep_prev);
11210   assert_ptr_equal(&session->root, stream10->dep_prev);
11211 
11212   /* It is an error to attempt to create already existing idle
11213      stream */
11214   rv = nghttp2_session_create_idle_stream(session, 4, &pri_spec);
11215 
11216   assert_int(NGHTTP2_ERR_INVALID_ARGUMENT, ==, rv);
11217 
11218   /* It is an error to depend on itself */
11219   pri_spec.stream_id = 6;
11220 
11221   rv = nghttp2_session_create_idle_stream(session, 6, &pri_spec);
11222   assert_int(NGHTTP2_ERR_INVALID_ARGUMENT, ==, rv);
11223 
11224   /* It is an error to create root stream (0) as idle stream */
11225   rv = nghttp2_session_create_idle_stream(session, 0, &pri_spec);
11226   assert_int(NGHTTP2_ERR_INVALID_ARGUMENT, ==, rv);
11227 
11228   /* It is an error to create non-idle stream */
11229   session->last_sent_stream_id = 20;
11230   pri_spec.stream_id = 2;
11231 
11232   rv = nghttp2_session_create_idle_stream(session, 18, &pri_spec);
11233 
11234   assert_int(NGHTTP2_ERR_INVALID_ARGUMENT, ==, rv);
11235 
11236   nghttp2_session_del(session);
11237 
11238   /* Check that this works in client session too */
11239   nghttp2_session_client_new(&session, &callbacks, NULL);
11240 
11241   nghttp2_priority_spec_init(&pri_spec, 4, 99, 1);
11242 
11243   rv = nghttp2_session_create_idle_stream(session, 2, &pri_spec);
11244 
11245   assert_int(0, ==, rv);
11246 
11247   stream4 = nghttp2_session_get_stream_raw(session, 4);
11248   stream2 = nghttp2_session_get_stream_raw(session, 2);
11249 
11250   assert_not_null(stream4);
11251   assert_not_null(stream2);
11252   assert_ptr_equal(&session->root, stream4->dep_prev);
11253   assert_int32(NGHTTP2_DEFAULT_WEIGHT, ==, stream4->weight);
11254   assert_ptr_equal(stream4, stream2->dep_prev);
11255   assert_int32(99, ==, stream2->weight);
11256 
11257   nghttp2_session_del(session);
11258 
11259   /* Check that idle stream is reduced when nghttp2_session_send() is
11260      called. */
11261   nghttp2_session_server_new(&session, &callbacks, NULL);
11262 
11263   session->local_settings.max_concurrent_streams = 30;
11264 
11265   nghttp2_priority_spec_init(&pri_spec, 0, 16, 0);
11266   for (i = 0; i < 100; ++i) {
11267     rv = nghttp2_session_create_idle_stream(session, i * 2 + 1, &pri_spec);
11268 
11269     assert_int(0, ==, rv);
11270 
11271     nghttp2_priority_spec_init(&pri_spec, i * 2 + 1, 16, 0);
11272   }
11273 
11274   assert_size(100, ==, session->num_idle_streams);
11275   assert_int(0, ==, nghttp2_session_send(session));
11276   assert_size(30, ==, session->num_idle_streams);
11277   assert_int32(141, ==, session->idle_stream_head->stream_id);
11278 
11279   nghttp2_session_del(session);
11280 
11281   /* Check that idle stream is reduced when nghttp2_session_mem_recv2() is
11282      called. */
11283   nghttp2_session_client_new(&session, &callbacks, NULL);
11284 
11285   session->local_settings.max_concurrent_streams = 30;
11286 
11287   nghttp2_priority_spec_init(&pri_spec, 0, 16, 0);
11288   for (i = 0; i < 100; ++i) {
11289     rv = nghttp2_session_create_idle_stream(session, i * 2 + 1, &pri_spec);
11290 
11291     assert_int(0, ==, rv);
11292 
11293     nghttp2_priority_spec_init(&pri_spec, i * 2 + 1, 16, 0);
11294   }
11295 
11296   assert_size(100, ==, session->num_idle_streams);
11297   assert_ptrdiff(0, ==, nghttp2_session_mem_recv2(session, NULL, 0));
11298   assert_size(30, ==, session->num_idle_streams);
11299   assert_int32(141, ==, session->idle_stream_head->stream_id);
11300 
11301   nghttp2_session_del(session);
11302 }
11303 
test_nghttp2_session_repeated_priority_change(void)11304 void test_nghttp2_session_repeated_priority_change(void) {
11305   nghttp2_session *session;
11306   nghttp2_session_callbacks callbacks;
11307   nghttp2_frame frame;
11308   nghttp2_priority_spec pri_spec;
11309   int32_t stream_id, last_stream_id;
11310   int32_t max_streams = 20;
11311 
11312   memset(&callbacks, 0, sizeof(callbacks));
11313 
11314   nghttp2_session_server_new(&session, &callbacks, NULL);
11315 
11316   session->local_settings.max_concurrent_streams = (uint32_t)max_streams;
11317 
11318   /* 1 -> 0 */
11319   nghttp2_priority_spec_init(&pri_spec, 0, 16, 0);
11320   nghttp2_frame_priority_init(&frame.priority, 1, &pri_spec);
11321 
11322   assert_int(0, ==, nghttp2_session_on_priority_received(session, &frame));
11323 
11324   nghttp2_frame_priority_free(&frame.priority);
11325 
11326   last_stream_id = max_streams * 2 + 1;
11327 
11328   for (stream_id = 3; stream_id < last_stream_id; stream_id += 2) {
11329     /* 1 -> stream_id */
11330     nghttp2_priority_spec_init(&pri_spec, stream_id, 16, 0);
11331     nghttp2_frame_priority_init(&frame.priority, 1, &pri_spec);
11332 
11333     assert_int(0, ==, nghttp2_session_on_priority_received(session, &frame));
11334 
11335     nghttp2_frame_priority_free(&frame.priority);
11336   }
11337 
11338   assert_size(20, ==, session->num_idle_streams);
11339   assert_int32(1, ==, session->idle_stream_head->stream_id);
11340 
11341   /* 1 -> last_stream_id */
11342   nghttp2_priority_spec_init(&pri_spec, last_stream_id, 16, 0);
11343   nghttp2_frame_priority_init(&frame.priority, 1, &pri_spec);
11344 
11345   assert_int(0, ==, nghttp2_session_on_priority_received(session, &frame));
11346 
11347   nghttp2_frame_priority_free(&frame.priority);
11348 
11349   assert_size(20, ==, session->num_idle_streams);
11350   assert_int32(3, ==, session->idle_stream_head->stream_id);
11351 
11352   nghttp2_session_del(session);
11353 }
11354 
test_nghttp2_session_repeated_priority_submission(void)11355 void test_nghttp2_session_repeated_priority_submission(void) {
11356   nghttp2_session *session;
11357   nghttp2_session_callbacks callbacks;
11358   nghttp2_priority_spec pri_spec;
11359   int32_t stream_id, last_stream_id;
11360   uint32_t max_streams = NGHTTP2_MIN_IDLE_STREAMS;
11361 
11362   memset(&callbacks, 0, sizeof(callbacks));
11363 
11364   callbacks.send_callback2 = null_send_callback;
11365 
11366   nghttp2_session_client_new(&session, &callbacks, NULL);
11367 
11368   session->local_settings.max_concurrent_streams = max_streams;
11369 
11370   /* 1 -> 0 */
11371   nghttp2_priority_spec_init(&pri_spec, 0, 16, 0);
11372 
11373   assert_int(0, ==,
11374              nghttp2_submit_priority(session, NGHTTP2_FLAG_NONE, 1, &pri_spec));
11375 
11376   last_stream_id = (int32_t)(max_streams * 2 + 1);
11377 
11378   for (stream_id = 3; stream_id < last_stream_id; stream_id += 2) {
11379     /* 1 -> stream_id */
11380     nghttp2_priority_spec_init(&pri_spec, stream_id, 16, 0);
11381 
11382     assert_int(
11383       0, ==, nghttp2_submit_priority(session, NGHTTP2_FLAG_NONE, 1, &pri_spec));
11384   }
11385 
11386   assert_int(0, ==, nghttp2_session_send(session));
11387   assert_size(max_streams, ==, session->num_idle_streams);
11388   assert_int32(1, ==, session->idle_stream_head->stream_id);
11389 
11390   /* 1 -> last_stream_id */
11391   nghttp2_priority_spec_init(&pri_spec, last_stream_id, 16, 0);
11392 
11393   assert_int(0, ==,
11394              nghttp2_submit_priority(session, NGHTTP2_FLAG_NONE, 1, &pri_spec));
11395 
11396   assert_int(0, ==, nghttp2_session_send(session));
11397   assert_size(max_streams, ==, session->num_idle_streams);
11398   assert_int32(3, ==, session->idle_stream_head->stream_id);
11399 
11400   nghttp2_session_del(session);
11401 }
11402 
test_nghttp2_session_set_local_window_size(void)11403 void test_nghttp2_session_set_local_window_size(void) {
11404   nghttp2_session *session;
11405   nghttp2_session_callbacks callbacks;
11406   nghttp2_outbound_item *item;
11407   nghttp2_stream *stream;
11408 
11409   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
11410   callbacks.send_callback2 = null_send_callback;
11411 
11412   nghttp2_session_client_new(&session, &callbacks, NULL);
11413   stream = open_sent_stream(session, 1);
11414   stream->recv_window_size = 4096;
11415 
11416   assert_int(0, ==,
11417              nghttp2_session_set_local_window_size(session, NGHTTP2_FLAG_NONE,
11418                                                    1, 65536));
11419   assert_int32(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE + 1, ==,
11420                stream->local_window_size);
11421   assert_int32(4096, ==, stream->recv_window_size);
11422   assert_int32(65536 - 4096, ==,
11423                nghttp2_session_get_stream_local_window_size(session, 1));
11424 
11425   item = nghttp2_session_get_next_ob_item(session);
11426 
11427   assert_uint8(NGHTTP2_WINDOW_UPDATE, ==, item->frame.hd.type);
11428   assert_int32(1, ==, item->frame.window_update.hd.stream_id);
11429   assert_int32(1, ==, item->frame.window_update.window_size_increment);
11430 
11431   assert_int(0, ==, nghttp2_session_send(session));
11432 
11433   /* Go decrement part */
11434   assert_int(0, ==,
11435              nghttp2_session_set_local_window_size(session, NGHTTP2_FLAG_NONE,
11436                                                    1, 32768));
11437   assert_int32(32768, ==, stream->local_window_size);
11438   assert_int32(-28672, ==, stream->recv_window_size);
11439   assert_int32(32768, ==, stream->recv_reduction);
11440   assert_int32(65536 - 4096, ==,
11441                nghttp2_session_get_stream_local_window_size(session, 1));
11442 
11443   item = nghttp2_session_get_next_ob_item(session);
11444 
11445   assert_null(item);
11446 
11447   /* Increase local window size */
11448   assert_int(0, ==,
11449              nghttp2_session_set_local_window_size(session, NGHTTP2_FLAG_NONE,
11450                                                    1, 49152));
11451   assert_int32(49152, ==, stream->local_window_size);
11452   assert_int32(-12288, ==, stream->recv_window_size);
11453   assert_int32(16384, ==, stream->recv_reduction);
11454   assert_int32(65536 - 4096, ==,
11455                nghttp2_session_get_stream_local_window_size(session, 1));
11456   assert_null(nghttp2_session_get_next_ob_item(session));
11457 
11458   /* Increase local window again */
11459   assert_int(0, ==,
11460              nghttp2_session_set_local_window_size(session, NGHTTP2_FLAG_NONE,
11461                                                    1, 65537));
11462   assert_int32(65537, ==, stream->local_window_size);
11463   assert_int32(4096, ==, stream->recv_window_size);
11464   assert_int32(0, ==, stream->recv_reduction);
11465   assert_int32(65537 - 4096, ==,
11466                nghttp2_session_get_stream_local_window_size(session, 1));
11467 
11468   item = nghttp2_session_get_next_ob_item(session);
11469 
11470   assert_int32(1, ==, item->frame.window_update.window_size_increment);
11471 
11472   assert_int(0, ==, nghttp2_session_send(session));
11473 
11474   /* Check connection-level flow control */
11475   session->recv_window_size = 4096;
11476   assert_int(0, ==,
11477              nghttp2_session_set_local_window_size(session, NGHTTP2_FLAG_NONE,
11478                                                    0, 65536));
11479   assert_int32(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE + 1, ==,
11480                session->local_window_size);
11481   assert_int32(4096, ==, session->recv_window_size);
11482   assert_int32(65536 - 4096, ==,
11483                nghttp2_session_get_local_window_size(session));
11484 
11485   item = nghttp2_session_get_next_ob_item(session);
11486 
11487   assert_uint8(NGHTTP2_WINDOW_UPDATE, ==, item->frame.hd.type);
11488   assert_int32(0, ==, item->frame.window_update.hd.stream_id);
11489   assert_int32(1, ==, item->frame.window_update.window_size_increment);
11490 
11491   assert_int(0, ==, nghttp2_session_send(session));
11492 
11493   /* Go decrement part */
11494   assert_int(0, ==,
11495              nghttp2_session_set_local_window_size(session, NGHTTP2_FLAG_NONE,
11496                                                    0, 32768));
11497   assert_int32(32768, ==, session->local_window_size);
11498   assert_int32(-28672, ==, session->recv_window_size);
11499   assert_int32(32768, ==, session->recv_reduction);
11500   assert_int32(65536 - 4096, ==,
11501                nghttp2_session_get_local_window_size(session));
11502 
11503   item = nghttp2_session_get_next_ob_item(session);
11504 
11505   assert_null(item);
11506 
11507   /* Increase local window size */
11508   assert_int(0, ==,
11509              nghttp2_session_set_local_window_size(session, NGHTTP2_FLAG_NONE,
11510                                                    0, 49152));
11511   assert_int32(49152, ==, session->local_window_size);
11512   assert_int32(-12288, ==, session->recv_window_size);
11513   assert_int32(16384, ==, session->recv_reduction);
11514   assert_int32(65536 - 4096, ==,
11515                nghttp2_session_get_local_window_size(session));
11516   assert_null(nghttp2_session_get_next_ob_item(session));
11517 
11518   /* Increase local window again */
11519   assert_int(0, ==,
11520              nghttp2_session_set_local_window_size(session, NGHTTP2_FLAG_NONE,
11521                                                    0, 65537));
11522   assert_int32(65537, ==, session->local_window_size);
11523   assert_int32(4096, ==, session->recv_window_size);
11524   assert_int32(0, ==, session->recv_reduction);
11525   assert_int32(65537 - 4096, ==,
11526                nghttp2_session_get_local_window_size(session));
11527 
11528   item = nghttp2_session_get_next_ob_item(session);
11529 
11530   assert_int32(1, ==, item->frame.window_update.window_size_increment);
11531 
11532   assert_int(0, ==, nghttp2_session_send(session));
11533 
11534   nghttp2_session_del(session);
11535 
11536   /* Make sure that nghttp2_session_set_local_window_size submits
11537      WINDOW_UPDATE if necessary to increase stream-level window. */
11538   nghttp2_session_client_new(&session, &callbacks, NULL);
11539   stream = open_sent_stream(session, 1);
11540   stream->recv_window_size = NGHTTP2_INITIAL_WINDOW_SIZE;
11541 
11542   assert_int(
11543     0, ==,
11544     nghttp2_session_set_local_window_size(session, NGHTTP2_FLAG_NONE, 1, 0));
11545   assert_int32(0, ==, stream->recv_window_size);
11546   assert_int32(0, ==, nghttp2_session_get_stream_local_window_size(session, 1));
11547   /* This should submit WINDOW_UPDATE frame because stream-level
11548      receiving window is now full. */
11549   assert_int(0, ==,
11550              nghttp2_session_set_local_window_size(
11551                session, NGHTTP2_FLAG_NONE, 1, NGHTTP2_INITIAL_WINDOW_SIZE));
11552   assert_int32(0, ==, stream->recv_window_size);
11553   assert_int32(NGHTTP2_INITIAL_WINDOW_SIZE, ==,
11554                nghttp2_session_get_stream_local_window_size(session, 1));
11555 
11556   item = nghttp2_session_get_next_ob_item(session);
11557 
11558   assert_uint8(NGHTTP2_WINDOW_UPDATE, ==, item->frame.hd.type);
11559   assert_int32(1, ==, item->frame.hd.stream_id);
11560   assert_int32(NGHTTP2_INITIAL_WINDOW_SIZE, ==,
11561                item->frame.window_update.window_size_increment);
11562 
11563   nghttp2_session_del(session);
11564 
11565   /* Make sure that nghttp2_session_set_local_window_size submits
11566      WINDOW_UPDATE if necessary to increase connection-level
11567      window. */
11568   nghttp2_session_client_new(&session, &callbacks, NULL);
11569   session->recv_window_size = NGHTTP2_INITIAL_WINDOW_SIZE;
11570 
11571   assert_int(
11572     0, ==,
11573     nghttp2_session_set_local_window_size(session, NGHTTP2_FLAG_NONE, 0, 0));
11574   assert_int32(0, ==, session->recv_window_size);
11575   assert_int32(0, ==, nghttp2_session_get_local_window_size(session));
11576   /* This should submit WINDOW_UPDATE frame because connection-level
11577      receiving window is now full. */
11578   assert_int(0, ==,
11579              nghttp2_session_set_local_window_size(
11580                session, NGHTTP2_FLAG_NONE, 0, NGHTTP2_INITIAL_WINDOW_SIZE));
11581   assert_int32(0, ==, session->recv_window_size);
11582   assert_int32(NGHTTP2_INITIAL_WINDOW_SIZE, ==,
11583                nghttp2_session_get_local_window_size(session));
11584 
11585   item = nghttp2_session_get_next_ob_item(session);
11586 
11587   assert_uint8(NGHTTP2_WINDOW_UPDATE, ==, item->frame.hd.type);
11588   assert_int32(0, ==, item->frame.hd.stream_id);
11589   assert_int32(NGHTTP2_INITIAL_WINDOW_SIZE, ==,
11590                item->frame.window_update.window_size_increment);
11591 
11592   nghttp2_session_del(session);
11593 }
11594 
test_nghttp2_session_cancel_from_before_frame_send(void)11595 void test_nghttp2_session_cancel_from_before_frame_send(void) {
11596   int rv;
11597   nghttp2_session *session;
11598   nghttp2_session_callbacks callbacks;
11599   my_user_data ud;
11600   nghttp2_settings_entry iv;
11601   nghttp2_data_provider2 data_prd;
11602   int32_t stream_id;
11603   nghttp2_stream *stream;
11604 
11605   memset(&callbacks, 0, sizeof(callbacks));
11606 
11607   callbacks.before_frame_send_callback = cancel_before_frame_send_callback;
11608   callbacks.on_frame_not_send_callback = on_frame_not_send_callback;
11609   callbacks.send_callback2 = null_send_callback;
11610 
11611   nghttp2_session_client_new(&session, &callbacks, &ud);
11612 
11613   iv.settings_id = 0;
11614   iv.value = 1000000009;
11615 
11616   rv = nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, &iv, 1);
11617 
11618   assert_int(0, ==, rv);
11619 
11620   ud.frame_send_cb_called = 0;
11621   ud.before_frame_send_cb_called = 0;
11622   ud.frame_not_send_cb_called = 0;
11623 
11624   rv = nghttp2_session_send(session);
11625 
11626   assert_int(0, ==, rv);
11627   assert_int(0, ==, ud.frame_send_cb_called);
11628   assert_int(1, ==, ud.before_frame_send_cb_called);
11629   assert_int(1, ==, ud.frame_not_send_cb_called);
11630 
11631   data_prd.source.ptr = NULL;
11632   data_prd.read_callback = temporal_failure_data_source_read_callback;
11633 
11634   stream_id = nghttp2_submit_request2(session, NULL, reqnv, ARRLEN(reqnv),
11635                                       &data_prd, NULL);
11636 
11637   assert_int32(0, <, stream_id);
11638 
11639   ud.frame_send_cb_called = 0;
11640   ud.before_frame_send_cb_called = 0;
11641   ud.frame_not_send_cb_called = 0;
11642 
11643   rv = nghttp2_session_send(session);
11644 
11645   assert_int(0, ==, rv);
11646   assert_int(0, ==, ud.frame_send_cb_called);
11647   assert_int(1, ==, ud.before_frame_send_cb_called);
11648   assert_int(1, ==, ud.frame_not_send_cb_called);
11649 
11650   stream = nghttp2_session_get_stream_raw(session, stream_id);
11651 
11652   assert_null(stream);
11653 
11654   nghttp2_session_del(session);
11655 
11656   nghttp2_session_server_new(&session, &callbacks, &ud);
11657 
11658   open_recv_stream(session, 1);
11659 
11660   stream_id = nghttp2_submit_push_promise(session, NGHTTP2_FLAG_NONE, 1, reqnv,
11661                                           ARRLEN(reqnv), NULL);
11662 
11663   assert_int32(0, <, stream_id);
11664 
11665   ud.frame_send_cb_called = 0;
11666   ud.before_frame_send_cb_called = 0;
11667   ud.frame_not_send_cb_called = 0;
11668 
11669   rv = nghttp2_session_send(session);
11670 
11671   assert_int(0, ==, rv);
11672   assert_int(0, ==, ud.frame_send_cb_called);
11673   assert_int(1, ==, ud.before_frame_send_cb_called);
11674   assert_int(1, ==, ud.frame_not_send_cb_called);
11675 
11676   stream = nghttp2_session_get_stream_raw(session, stream_id);
11677 
11678   assert_null(stream);
11679 
11680   nghttp2_session_del(session);
11681 }
11682 
test_nghttp2_session_too_many_settings(void)11683 void test_nghttp2_session_too_many_settings(void) {
11684   nghttp2_session *session;
11685   nghttp2_option *option;
11686   nghttp2_session_callbacks callbacks;
11687   nghttp2_frame frame;
11688   nghttp2_bufs bufs;
11689   nghttp2_buf *buf;
11690   nghttp2_ssize rv;
11691   my_user_data ud;
11692   nghttp2_settings_entry iv[3];
11693   nghttp2_mem *mem;
11694   nghttp2_outbound_item *item;
11695 
11696   mem = nghttp2_mem_default();
11697   frame_pack_bufs_init(&bufs);
11698 
11699   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
11700   callbacks.on_frame_recv_callback = on_frame_recv_callback;
11701   callbacks.send_callback2 = null_send_callback;
11702 
11703   nghttp2_option_new(&option);
11704   nghttp2_option_set_max_settings(option, 1);
11705 
11706   nghttp2_session_client_new2(&session, &callbacks, &ud, option);
11707 
11708   assert_size(1, ==, session->max_settings);
11709 
11710   nghttp2_option_del(option);
11711 
11712   iv[0].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
11713   iv[0].value = 3000;
11714 
11715   iv[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
11716   iv[1].value = 16384;
11717 
11718   nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE, dup_iv(iv, 2),
11719                               2);
11720 
11721   rv = nghttp2_frame_pack_settings(&bufs, &frame.settings);
11722 
11723   assert_ptrdiff(0, ==, rv);
11724   assert_size(0, <, nghttp2_bufs_len(&bufs));
11725 
11726   nghttp2_frame_settings_free(&frame.settings, mem);
11727 
11728   buf = &bufs.head->buf;
11729   assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
11730 
11731   ud.frame_recv_cb_called = 0;
11732 
11733   rv = nghttp2_session_mem_recv2(session, buf->pos, nghttp2_buf_len(buf));
11734   assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(buf), ==, rv);
11735 
11736   item = nghttp2_session_get_next_ob_item(session);
11737   assert_uint8(NGHTTP2_GOAWAY, ==, item->frame.hd.type);
11738 
11739   nghttp2_bufs_reset(&bufs);
11740   nghttp2_bufs_free(&bufs);
11741   nghttp2_session_del(session);
11742 }
11743 
11744 static void
prepare_session_removed_closed_stream(nghttp2_session * session,nghttp2_hd_deflater * deflater)11745 prepare_session_removed_closed_stream(nghttp2_session *session,
11746                                       nghttp2_hd_deflater *deflater) {
11747   int rv;
11748   nghttp2_settings_entry iv;
11749   nghttp2_bufs bufs;
11750   nghttp2_mem *mem;
11751   nghttp2_ssize nread;
11752   int i;
11753   nghttp2_stream *stream;
11754   nghttp2_frame_hd hd;
11755 
11756   mem = nghttp2_mem_default();
11757 
11758   frame_pack_bufs_init(&bufs);
11759 
11760   iv.settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS;
11761   iv.value = 2;
11762 
11763   rv = nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, &iv, 1);
11764 
11765   assert_int(0, ==, rv);
11766 
11767   rv = nghttp2_session_send(session);
11768 
11769   assert_int(0, ==, rv);
11770 
11771   for (i = 1; i <= 3; i += 2) {
11772     rv = pack_headers(&bufs, deflater, i,
11773                       NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM, reqnv,
11774                       ARRLEN(reqnv), mem);
11775 
11776     assert_int(0, ==, rv);
11777 
11778     nread = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
11779                                       nghttp2_bufs_len(&bufs));
11780 
11781     assert_ptrdiff((nghttp2_ssize)nghttp2_bufs_len(&bufs), ==, nread);
11782 
11783     nghttp2_bufs_reset(&bufs);
11784   }
11785 
11786   nghttp2_session_close_stream(session, 3, NGHTTP2_NO_ERROR);
11787 
11788   rv = pack_headers(&bufs, deflater, 5,
11789                     NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM, reqnv,
11790                     ARRLEN(reqnv), mem);
11791 
11792   assert_int(0, ==, rv);
11793 
11794   /* Receiving stream 5 will erase stream 3 from closed stream list */
11795   nread = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
11796                                     nghttp2_bufs_len(&bufs));
11797 
11798   assert_ptrdiff((nghttp2_ssize)nghttp2_bufs_len(&bufs), ==, nread);
11799 
11800   stream = nghttp2_session_get_stream_raw(session, 3);
11801 
11802   assert_null(stream);
11803 
11804   /* Since the current max concurrent streams is
11805      NGHTTP2_DEFAULT_MAX_CONCURRENT_STREAMS, receiving frame on stream
11806      3 is ignored. */
11807   nghttp2_bufs_reset(&bufs);
11808   rv = pack_headers(&bufs, deflater, 3,
11809                     NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM,
11810                     trailernv, ARRLEN(trailernv), mem);
11811 
11812   assert_int(0, ==, rv);
11813 
11814   nread = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
11815                                     nghttp2_bufs_len(&bufs));
11816 
11817   assert_ptrdiff((nghttp2_ssize)nghttp2_bufs_len(&bufs), ==, nread);
11818   assert_null(nghttp2_session_get_next_ob_item(session));
11819 
11820   nghttp2_frame_hd_init(&hd, 0, NGHTTP2_DATA, NGHTTP2_FLAG_NONE, 3);
11821   nghttp2_bufs_reset(&bufs);
11822   nghttp2_frame_pack_frame_hd(bufs.head->buf.last, &hd);
11823   bufs.head->buf.last += NGHTTP2_FRAME_HDLEN;
11824 
11825   nread = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
11826                                     nghttp2_bufs_len(&bufs));
11827 
11828   assert_ptrdiff((nghttp2_ssize)nghttp2_bufs_len(&bufs), ==, nread);
11829   assert_null(nghttp2_session_get_next_ob_item(session));
11830 
11831   /* Now server receives SETTINGS ACK */
11832   nghttp2_frame_hd_init(&hd, 0, NGHTTP2_SETTINGS, NGHTTP2_FLAG_ACK, 0);
11833   nghttp2_bufs_reset(&bufs);
11834   nghttp2_frame_pack_frame_hd(bufs.head->buf.last, &hd);
11835   bufs.head->buf.last += NGHTTP2_FRAME_HDLEN;
11836 
11837   nread = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
11838                                     nghttp2_bufs_len(&bufs));
11839 
11840   assert_ptrdiff((nghttp2_ssize)nghttp2_bufs_len(&bufs), ==, nread);
11841 
11842   nghttp2_bufs_free(&bufs);
11843 }
11844 
test_nghttp2_session_removed_closed_stream(void)11845 void test_nghttp2_session_removed_closed_stream(void) {
11846   nghttp2_session *session;
11847   nghttp2_session_callbacks callbacks;
11848   int rv;
11849   nghttp2_hd_deflater deflater;
11850   nghttp2_bufs bufs;
11851   nghttp2_mem *mem;
11852   nghttp2_ssize nread;
11853   nghttp2_frame_hd hd;
11854   nghttp2_outbound_item *item;
11855 
11856   mem = nghttp2_mem_default();
11857 
11858   frame_pack_bufs_init(&bufs);
11859 
11860   memset(&callbacks, 0, sizeof(callbacks));
11861 
11862   callbacks.send_callback2 = null_send_callback;
11863 
11864   nghttp2_session_server_new(&session, &callbacks, NULL);
11865 
11866   /* Now local max concurrent streams is still unlimited, pending max
11867      concurrent streams is now 2. */
11868 
11869   nghttp2_hd_deflate_init(&deflater, mem);
11870 
11871   prepare_session_removed_closed_stream(session, &deflater);
11872 
11873   /* Now current max concurrent streams is 2.  Receiving frame on
11874      stream 3 is ignored because we have no stream object for stream
11875      3. */
11876   nghttp2_bufs_reset(&bufs);
11877   rv = pack_headers(&bufs, &deflater, 3,
11878                     NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM,
11879                     trailernv, ARRLEN(trailernv), mem);
11880 
11881   assert_int(0, ==, rv);
11882 
11883   nread = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
11884                                     nghttp2_bufs_len(&bufs));
11885 
11886   assert_ptrdiff((nghttp2_ssize)nghttp2_bufs_len(&bufs), ==, nread);
11887 
11888   item = nghttp2_session_get_next_ob_item(session);
11889 
11890   assert_null(item);
11891 
11892   nghttp2_hd_deflate_free(&deflater);
11893   nghttp2_session_del(session);
11894 
11895   nghttp2_session_server_new(&session, &callbacks, NULL);
11896   nghttp2_hd_deflate_init(&deflater, mem);
11897   /* Same setup, and then receive DATA instead of HEADERS */
11898 
11899   prepare_session_removed_closed_stream(session, &deflater);
11900 
11901   nghttp2_frame_hd_init(&hd, 0, NGHTTP2_DATA, NGHTTP2_FLAG_NONE, 3);
11902   nghttp2_bufs_reset(&bufs);
11903   nghttp2_frame_pack_frame_hd(bufs.head->buf.last, &hd);
11904   bufs.head->buf.last += NGHTTP2_FRAME_HDLEN;
11905 
11906   nread = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
11907                                     nghttp2_bufs_len(&bufs));
11908 
11909   assert_ptrdiff((nghttp2_ssize)nghttp2_bufs_len(&bufs), ==, nread);
11910 
11911   item = nghttp2_session_get_next_ob_item(session);
11912 
11913   assert_null(item);
11914 
11915   nghttp2_hd_deflate_free(&deflater);
11916   nghttp2_session_del(session);
11917 
11918   nghttp2_bufs_free(&bufs);
11919 }
11920 
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)11921 static nghttp2_ssize pause_once_data_source_read_callback(
11922   nghttp2_session *session, int32_t stream_id, uint8_t *buf, size_t len,
11923   uint32_t *data_flags, nghttp2_data_source *source, void *user_data) {
11924   my_user_data *ud = user_data;
11925   if (ud->data_source_read_cb_paused == 0) {
11926     ++ud->data_source_read_cb_paused;
11927     return NGHTTP2_ERR_PAUSE;
11928   }
11929 
11930   return fixed_length_data_source_read_callback(session, stream_id, buf, len,
11931                                                 data_flags, source, user_data);
11932 }
11933 
test_nghttp2_session_pause_data(void)11934 void test_nghttp2_session_pause_data(void) {
11935   nghttp2_session *session;
11936   nghttp2_session_callbacks callbacks;
11937   nghttp2_data_provider2 data_prd;
11938   my_user_data ud;
11939 
11940   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
11941   callbacks.send_callback2 = null_send_callback;
11942   callbacks.on_frame_send_callback = on_frame_send_callback;
11943 
11944   data_prd.read_callback = pause_once_data_source_read_callback;
11945   ud.data_source_length = NGHTTP2_DATA_PAYLOADLEN;
11946 
11947   nghttp2_session_server_new(&session, &callbacks, &ud);
11948 
11949   open_recv_stream(session, 1);
11950 
11951   assert_int(
11952     0, ==,
11953     nghttp2_submit_data2(session, NGHTTP2_FLAG_END_STREAM, 1, &data_prd));
11954 
11955   ud.frame_send_cb_called = 0;
11956   ud.data_source_read_cb_paused = 0;
11957 
11958   assert_int(0, ==, nghttp2_session_send(session));
11959   assert_int(0, ==, ud.frame_send_cb_called);
11960   assert_null(session->aob.item);
11961   assert_int(0, ==, nghttp2_session_send(session));
11962   assert_int(1, ==, ud.frame_send_cb_called);
11963   assert_uint8(NGHTTP2_DATA, ==, ud.sent_frame_type);
11964   assert_null(nghttp2_session_get_next_ob_item(session));
11965 
11966   nghttp2_session_del(session);
11967 }
11968 
test_nghttp2_session_no_closed_streams(void)11969 void test_nghttp2_session_no_closed_streams(void) {
11970   nghttp2_session *session;
11971   nghttp2_session_callbacks callbacks;
11972   nghttp2_option *option;
11973 
11974   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
11975 
11976   nghttp2_option_new(&option);
11977   nghttp2_option_set_no_closed_streams(option, 1);
11978 
11979   nghttp2_session_server_new2(&session, &callbacks, NULL, option);
11980 
11981   open_recv_stream(session, 1);
11982 
11983   nghttp2_session_close_stream(session, 1, NGHTTP2_NO_ERROR);
11984 
11985   assert_size(0, ==, session->num_closed_streams);
11986 
11987   nghttp2_session_del(session);
11988   nghttp2_option_del(option);
11989 }
11990 
test_nghttp2_session_set_stream_user_data(void)11991 void test_nghttp2_session_set_stream_user_data(void) {
11992   nghttp2_session *session;
11993   nghttp2_session_callbacks callbacks;
11994   int32_t stream_id;
11995   int user_data1, user_data2;
11996   int rv;
11997   const uint8_t *datap;
11998   nghttp2_ssize datalen;
11999 
12000   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
12001 
12002   nghttp2_session_client_new(&session, &callbacks, NULL);
12003 
12004   stream_id = nghttp2_submit_request2(session, NULL, reqnv, ARRLEN(reqnv), NULL,
12005                                       &user_data1);
12006 
12007   rv = nghttp2_session_set_stream_user_data(session, stream_id, &user_data2);
12008 
12009   assert_int(0, ==, rv);
12010 
12011   datalen = nghttp2_session_mem_send2(session, &datap);
12012 
12013   assert_ptrdiff(0, <, datalen);
12014 
12015   assert_ptr_equal(&user_data2,
12016                    nghttp2_session_get_stream_user_data(session, stream_id));
12017 
12018   assert_int(NGHTTP2_ERR_INVALID_ARGUMENT, ==,
12019              nghttp2_session_set_stream_user_data(session, 2, NULL));
12020 
12021   nghttp2_session_del(session);
12022 }
12023 
test_nghttp2_session_no_rfc7540_priorities(void)12024 void test_nghttp2_session_no_rfc7540_priorities(void) {
12025   nghttp2_session *session;
12026   nghttp2_session_callbacks callbacks;
12027   nghttp2_data_provider2 data_prd;
12028   my_user_data ud;
12029   nghttp2_outbound_item *item;
12030   nghttp2_mem *mem;
12031   nghttp2_settings_entry iv;
12032   nghttp2_priority_spec pri_spec;
12033 
12034   mem = nghttp2_mem_default();
12035 
12036   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
12037   callbacks.send_callback2 = null_send_callback;
12038 
12039   /* Do not use a dependency tree if SETTINGS_NO_RFC7540_PRIORITIES =
12040      1. */
12041   data_prd.read_callback = fixed_length_data_source_read_callback;
12042 
12043   ud.data_source_length = 128 * 1024;
12044   assert_int(0, ==, nghttp2_session_server_new(&session, &callbacks, &ud));
12045 
12046   iv.settings_id = NGHTTP2_SETTINGS_NO_RFC7540_PRIORITIES;
12047   iv.value = 1;
12048 
12049   assert_int(0, ==,
12050              nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, &iv, 1));
12051   assert_int(0, ==, nghttp2_session_send(session));
12052 
12053   open_recv_stream2(session, 1, NGHTTP2_STREAM_OPENING);
12054   assert_int(
12055     0, ==,
12056     nghttp2_submit_response2(session, 1, resnv, ARRLEN(resnv), &data_prd));
12057   item = nghttp2_session_get_next_ob_item(session);
12058   assert_size(ARRLEN(resnv), ==, item->frame.headers.nvlen);
12059   assert_nv_equal(resnv, item->frame.headers.nva, item->frame.headers.nvlen,
12060                   mem);
12061 
12062   assert_int(0, ==, nghttp2_session_send(session));
12063   assert_size(
12064     1, ==,
12065     nghttp2_pq_size(&session->sched[NGHTTP2_EXTPRI_DEFAULT_URGENCY].ob_data));
12066   assert_true(nghttp2_pq_empty(&session->root.obq));
12067 
12068   nghttp2_session_del(session);
12069 
12070   /* Priorities are sent as is before client receives
12071      SETTINGS_NO_RFC7540_PRIORITIES = 1 from server. */
12072   assert_int(0, ==, nghttp2_session_client_new(&session, &callbacks, NULL));
12073 
12074   iv.settings_id = NGHTTP2_SETTINGS_NO_RFC7540_PRIORITIES;
12075   iv.value = 1;
12076 
12077   assert_int(0, ==,
12078              nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, &iv, 1));
12079 
12080   pri_spec.stream_id = 5;
12081   pri_spec.weight = 111;
12082   pri_spec.exclusive = 1;
12083 
12084   assert_int32(1, ==,
12085                nghttp2_submit_request2(session, &pri_spec, reqnv, ARRLEN(reqnv),
12086                                        NULL, NULL));
12087 
12088   item = nghttp2_outbound_queue_top(&session->ob_syn);
12089 
12090   assert_not_null(item);
12091   assert_uint8(NGHTTP2_HEADERS, ==, item->frame.hd.type);
12092   assert_int32(pri_spec.stream_id, ==, item->frame.headers.pri_spec.stream_id);
12093   assert_int32(pri_spec.weight, ==, item->frame.headers.pri_spec.weight);
12094   assert_uint8(pri_spec.exclusive, ==, item->frame.headers.pri_spec.exclusive);
12095 
12096   nghttp2_session_del(session);
12097 
12098   /* Priorities are defaulted if client received
12099      SETTINGS_NO_RFC7540_PRIORITIES = 1 from server. */
12100   assert_int(0, ==, nghttp2_session_client_new(&session, &callbacks, NULL));
12101 
12102   iv.settings_id = NGHTTP2_SETTINGS_NO_RFC7540_PRIORITIES;
12103   iv.value = 1;
12104 
12105   assert_int(0, ==,
12106              nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, &iv, 1));
12107 
12108   session->remote_settings.no_rfc7540_priorities = 1;
12109 
12110   pri_spec.stream_id = 5;
12111   pri_spec.weight = 111;
12112   pri_spec.exclusive = 1;
12113 
12114   assert_int32(1, ==,
12115                nghttp2_submit_request2(session, &pri_spec, reqnv, ARRLEN(reqnv),
12116                                        NULL, NULL));
12117 
12118   item = nghttp2_outbound_queue_top(&session->ob_syn);
12119 
12120   assert_not_null(item);
12121   assert_uint8(NGHTTP2_HEADERS, ==, item->frame.hd.type);
12122   assert_true(
12123     nghttp2_priority_spec_check_default(&item->frame.headers.pri_spec));
12124 
12125   nghttp2_session_del(session);
12126 }
12127 
test_nghttp2_session_server_fallback_rfc7540_priorities(void)12128 void test_nghttp2_session_server_fallback_rfc7540_priorities(void) {
12129   nghttp2_session *session;
12130   nghttp2_option *option;
12131   nghttp2_session_callbacks callbacks;
12132   nghttp2_frame frame;
12133   nghttp2_bufs bufs;
12134   nghttp2_buf *buf;
12135   nghttp2_ssize rv;
12136   nghttp2_settings_entry iv;
12137   nghttp2_mem *mem;
12138   nghttp2_hd_deflater deflater;
12139   nghttp2_nv *nva;
12140   size_t nvlen;
12141   nghttp2_priority_spec pri_spec;
12142   nghttp2_stream *anchor_stream, *stream;
12143   my_user_data ud;
12144   nghttp2_ext_priority_update priority_update;
12145   static const uint8_t field_value[] = "u=0";
12146 
12147   mem = nghttp2_mem_default();
12148   frame_pack_bufs_init(&bufs);
12149 
12150   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
12151   callbacks.send_callback2 = null_send_callback;
12152   callbacks.on_frame_recv_callback = on_frame_recv_callback;
12153 
12154   nghttp2_option_new(&option);
12155   nghttp2_option_set_server_fallback_rfc7540_priorities(option, 1);
12156 
12157   iv.settings_id = NGHTTP2_SETTINGS_NO_RFC7540_PRIORITIES;
12158   iv.value = 1;
12159 
12160   /* Server falls back to RFC 7540 priorities. */
12161   nghttp2_session_server_new2(&session, &callbacks, &ud, option);
12162 
12163   rv = nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, &iv, 1);
12164 
12165   assert_ptrdiff(0, ==, rv);
12166 
12167   rv = nghttp2_session_send(session);
12168 
12169   assert_ptrdiff(0, ==, rv);
12170 
12171   nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE, NULL, 0);
12172   rv = nghttp2_frame_pack_settings(&bufs, &frame.settings);
12173 
12174   assert_ptrdiff(0, ==, rv);
12175 
12176   nghttp2_frame_settings_free(&frame.settings, mem);
12177 
12178   buf = &bufs.head->buf;
12179   rv = nghttp2_session_mem_recv2(session, buf->pos, nghttp2_buf_len(buf));
12180 
12181   assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(buf), ==, rv);
12182   assert_true(session->fallback_rfc7540_priorities);
12183 
12184   nghttp2_hd_deflate_init(&deflater, mem);
12185 
12186   nvlen = ARRLEN(reqnv);
12187   nghttp2_nv_array_copy(&nva, reqnv, nvlen, mem);
12188   nghttp2_priority_spec_init(&pri_spec, 3, 111, 1);
12189   nghttp2_frame_headers_init(&frame.headers,
12190                              NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PRIORITY,
12191                              1, NGHTTP2_HCAT_HEADERS, &pri_spec, nva, nvlen);
12192   nghttp2_bufs_reset(&bufs);
12193   rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
12194 
12195   assert_ptrdiff(0, ==, rv);
12196 
12197   nghttp2_frame_headers_free(&frame.headers, mem);
12198 
12199   buf = &bufs.head->buf;
12200   rv = nghttp2_session_mem_recv2(session, buf->pos, nghttp2_buf_len(buf));
12201 
12202   assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(buf), ==, rv);
12203 
12204   anchor_stream = nghttp2_session_get_stream_raw(session, 3);
12205 
12206   assert_enum(nghttp2_stream_state, NGHTTP2_STREAM_IDLE, ==,
12207               anchor_stream->state);
12208   assert_false(anchor_stream->flags &
12209                NGHTTP2_STREAM_FLAG_NO_RFC7540_PRIORITIES);
12210   assert_ptr_equal(&session->root, anchor_stream->dep_prev);
12211 
12212   stream = nghttp2_session_get_stream(session, 1);
12213 
12214   assert_enum(nghttp2_stream_state, NGHTTP2_STREAM_OPENING, ==, stream->state);
12215   assert_false(stream->flags & NGHTTP2_STREAM_FLAG_NO_RFC7540_PRIORITIES);
12216   assert_ptr_equal(anchor_stream, stream->dep_prev);
12217 
12218   /* Make sure that PRIORITY frame updates stream priority. */
12219   nghttp2_priority_spec_init(&pri_spec, 5, 1, 0);
12220   nghttp2_frame_priority_init(&frame.priority, 1, &pri_spec);
12221   nghttp2_bufs_reset(&bufs);
12222   nghttp2_frame_pack_priority(&bufs, &frame.priority);
12223 
12224   nghttp2_frame_priority_free(&frame.priority);
12225 
12226   buf = &bufs.head->buf;
12227   rv = nghttp2_session_mem_recv2(session, buf->pos, nghttp2_buf_len(buf));
12228 
12229   assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(buf), ==, rv);
12230 
12231   anchor_stream = nghttp2_session_get_stream_raw(session, 5);
12232 
12233   assert_enum(nghttp2_stream_state, NGHTTP2_STREAM_IDLE, ==,
12234               anchor_stream->state);
12235   assert_ptr_equal(&session->root, anchor_stream->dep_prev);
12236   assert_ptr_equal(anchor_stream, stream->dep_prev);
12237 
12238   /* Make sure that PRIORITY_UPDATE frame is ignored. */
12239   frame.ext.payload = &priority_update;
12240   nghttp2_frame_priority_update_init(&frame.ext, 1, (uint8_t *)field_value,
12241                                      sizeof(field_value) - 1);
12242   nghttp2_bufs_reset(&bufs);
12243   nghttp2_frame_pack_priority_update(&bufs, &frame.ext);
12244 
12245   ud.frame_recv_cb_called = 0;
12246   buf = &bufs.head->buf;
12247   rv = nghttp2_session_mem_recv2(session, buf->pos, nghttp2_buf_len(buf));
12248 
12249   assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(buf), ==, rv);
12250   assert_int(0, ==, ud.frame_recv_cb_called);
12251   assert_uint32(NGHTTP2_EXTPRI_DEFAULT_URGENCY, ==, stream->extpri);
12252 
12253   nghttp2_hd_deflate_free(&deflater);
12254   nghttp2_session_del(session);
12255 
12256   /* Server does not fallback to RFC 7540 priorities. */
12257   nghttp2_session_server_new2(&session, &callbacks, &ud, option);
12258 
12259   rv = nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, &iv, 1);
12260 
12261   assert_ptrdiff(0, ==, rv);
12262 
12263   rv = nghttp2_session_send(session);
12264 
12265   assert_ptrdiff(0, ==, rv);
12266 
12267   iv.settings_id = NGHTTP2_SETTINGS_NO_RFC7540_PRIORITIES;
12268   iv.value = 0;
12269 
12270   nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE,
12271                               dup_iv(&iv, 1), 1);
12272   nghttp2_bufs_reset(&bufs);
12273   rv = nghttp2_frame_pack_settings(&bufs, &frame.settings);
12274 
12275   assert_ptrdiff(0, ==, rv);
12276 
12277   nghttp2_frame_settings_free(&frame.settings, mem);
12278 
12279   buf = &bufs.head->buf;
12280   rv = nghttp2_session_mem_recv2(session, buf->pos, nghttp2_buf_len(buf));
12281 
12282   assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(buf), ==, rv);
12283   assert_false(session->fallback_rfc7540_priorities);
12284 
12285   nghttp2_hd_deflate_init(&deflater, mem);
12286 
12287   nvlen = ARRLEN(reqnv);
12288   nghttp2_nv_array_copy(&nva, reqnv, nvlen, mem);
12289   nghttp2_priority_spec_init(&pri_spec, 3, 111, 1);
12290   nghttp2_frame_headers_init(&frame.headers,
12291                              NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PRIORITY,
12292                              1, NGHTTP2_HCAT_HEADERS, &pri_spec, nva, nvlen);
12293   nghttp2_bufs_reset(&bufs);
12294   rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
12295 
12296   assert_ptrdiff(0, ==, rv);
12297 
12298   nghttp2_frame_headers_free(&frame.headers, mem);
12299 
12300   buf = &bufs.head->buf;
12301   rv = nghttp2_session_mem_recv2(session, buf->pos, nghttp2_buf_len(buf));
12302 
12303   assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(buf), ==, rv);
12304   assert_null(nghttp2_session_get_stream_raw(session, 3));
12305 
12306   stream = nghttp2_session_get_stream(session, 1);
12307 
12308   assert_enum(nghttp2_stream_state, NGHTTP2_STREAM_OPENING, ==, stream->state);
12309   assert_true(stream->flags & NGHTTP2_STREAM_FLAG_NO_RFC7540_PRIORITIES);
12310 
12311   nghttp2_hd_deflate_free(&deflater);
12312   nghttp2_session_del(session);
12313 
12314   nghttp2_option_del(option);
12315   nghttp2_bufs_free(&bufs);
12316 }
12317 
test_nghttp2_session_stream_reset_ratelim(void)12318 void test_nghttp2_session_stream_reset_ratelim(void) {
12319   nghttp2_session *session;
12320   nghttp2_session_callbacks callbacks;
12321   nghttp2_frame frame;
12322   nghttp2_ssize rv;
12323   nghttp2_bufs bufs;
12324   nghttp2_buf *buf;
12325   nghttp2_mem *mem;
12326   size_t i;
12327   nghttp2_hd_deflater deflater;
12328   size_t nvlen;
12329   nghttp2_nv *nva;
12330   int32_t stream_id;
12331   nghttp2_outbound_item *item;
12332   nghttp2_option *option;
12333 
12334   mem = nghttp2_mem_default();
12335   frame_pack_bufs_init(&bufs);
12336 
12337   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
12338   callbacks.send_callback2 = null_send_callback;
12339 
12340   nghttp2_option_new(&option);
12341   nghttp2_option_set_stream_reset_rate_limit(
12342     option, NGHTTP2_DEFAULT_STREAM_RESET_BURST, 0);
12343 
12344   nghttp2_session_server_new2(&session, &callbacks, NULL, option);
12345 
12346   nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE, NULL, 0);
12347   rv = nghttp2_frame_pack_settings(&bufs, &frame.settings);
12348 
12349   assert_ptrdiff(0, ==, rv);
12350 
12351   nghttp2_frame_settings_free(&frame.settings, mem);
12352 
12353   buf = &bufs.head->buf;
12354   rv = nghttp2_session_mem_recv2(session, buf->pos, nghttp2_buf_len(buf));
12355 
12356   assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(buf), ==, rv);
12357 
12358   /* Send SETTINGS ACK */
12359   rv = nghttp2_session_send(session);
12360 
12361   assert_ptrdiff(0, ==, rv);
12362 
12363   nghttp2_hd_deflate_init(&deflater, mem);
12364 
12365   for (i = 0; i < NGHTTP2_DEFAULT_STREAM_RESET_BURST + 2; ++i) {
12366     stream_id = (int32_t)(i * 2 + 1);
12367 
12368     nghttp2_bufs_reset(&bufs);
12369 
12370     /* HEADERS */
12371     nvlen = ARRLEN(reqnv);
12372     nghttp2_nv_array_copy(&nva, reqnv, nvlen, mem);
12373     nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS,
12374                                stream_id, NGHTTP2_HCAT_HEADERS, NULL, nva,
12375                                nvlen);
12376     rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
12377 
12378     assert_ptrdiff(0, ==, rv);
12379 
12380     nghttp2_frame_headers_free(&frame.headers, mem);
12381 
12382     buf = &bufs.head->buf;
12383     rv = nghttp2_session_mem_recv2(session, buf->pos, nghttp2_buf_len(buf));
12384 
12385     assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(buf), ==, rv);
12386 
12387     nghttp2_bufs_reset(&bufs);
12388 
12389     /* RST_STREAM */
12390     nghttp2_frame_rst_stream_init(&frame.rst_stream, stream_id,
12391                                   NGHTTP2_NO_ERROR);
12392     nghttp2_frame_pack_rst_stream(&bufs, &frame.rst_stream);
12393     nghttp2_frame_rst_stream_free(&frame.rst_stream);
12394 
12395     buf = &bufs.head->buf;
12396     rv = nghttp2_session_mem_recv2(session, buf->pos, nghttp2_buf_len(buf));
12397 
12398     assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(buf), ==, rv);
12399 
12400     if (i < NGHTTP2_DEFAULT_STREAM_RESET_BURST) {
12401       assert_size(0, ==, nghttp2_outbound_queue_size(&session->ob_reg));
12402 
12403       continue;
12404     }
12405 
12406     assert_size(1, ==, nghttp2_outbound_queue_size(&session->ob_reg));
12407 
12408     item = nghttp2_session_get_next_ob_item(session);
12409 
12410     assert_uint8(NGHTTP2_GOAWAY, ==, item->frame.hd.type);
12411     assert_int32(NGHTTP2_DEFAULT_STREAM_RESET_BURST * 2 + 1, ==,
12412                  item->frame.goaway.last_stream_id);
12413   }
12414 
12415   nghttp2_hd_deflate_free(&deflater);
12416   nghttp2_session_del(session);
12417   nghttp2_bufs_free(&bufs);
12418   nghttp2_option_del(option);
12419 }
12420 
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)12421 static void check_nghttp2_http_recv_headers_fail(
12422   nghttp2_session *session, nghttp2_hd_deflater *deflater, int32_t stream_id,
12423   int stream_state, const nghttp2_nv *nva, size_t nvlen) {
12424   nghttp2_mem *mem;
12425   nghttp2_ssize rv;
12426   nghttp2_outbound_item *item;
12427   nghttp2_bufs bufs;
12428   my_user_data *ud;
12429 
12430   mem = nghttp2_mem_default();
12431   frame_pack_bufs_init(&bufs);
12432 
12433   ud = session->user_data;
12434 
12435   if (stream_state != -1) {
12436     if (nghttp2_session_is_my_stream_id(session, stream_id)) {
12437       open_sent_stream2(session, stream_id, (nghttp2_stream_state)stream_state);
12438     } else {
12439       open_recv_stream2(session, stream_id, (nghttp2_stream_state)stream_state);
12440     }
12441   }
12442 
12443   rv = pack_headers(&bufs, deflater, stream_id, NGHTTP2_FLAG_END_HEADERS, nva,
12444                     nvlen, mem);
12445   assert_ptrdiff(0, ==, rv);
12446 
12447   ud->invalid_frame_recv_cb_called = 0;
12448 
12449   rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
12450                                  nghttp2_buf_len(&bufs.head->buf));
12451 
12452   assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(&bufs.head->buf), ==, rv);
12453 
12454   item = nghttp2_session_get_next_ob_item(session);
12455 
12456   assert_uint8(NGHTTP2_RST_STREAM, ==, item->frame.hd.type);
12457   assert_ptrdiff(1, ==, ud->invalid_frame_recv_cb_called);
12458 
12459   assert_int(0, ==, nghttp2_session_send(session));
12460 
12461   nghttp2_bufs_free(&bufs);
12462 }
12463 
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)12464 static void check_nghttp2_http_recv_headers_ok(
12465   nghttp2_session *session, nghttp2_hd_deflater *deflater, int32_t stream_id,
12466   int stream_state, const nghttp2_nv *nva, size_t nvlen) {
12467   nghttp2_mem *mem;
12468   nghttp2_ssize rv;
12469   nghttp2_bufs bufs;
12470   my_user_data *ud;
12471 
12472   mem = nghttp2_mem_default();
12473   frame_pack_bufs_init(&bufs);
12474 
12475   ud = session->user_data;
12476 
12477   if (stream_state != -1) {
12478     if (nghttp2_session_is_my_stream_id(session, stream_id)) {
12479       open_sent_stream2(session, stream_id, (nghttp2_stream_state)stream_state);
12480     } else {
12481       open_recv_stream2(session, stream_id, (nghttp2_stream_state)stream_state);
12482     }
12483   }
12484 
12485   rv = pack_headers(&bufs, deflater, stream_id, NGHTTP2_FLAG_END_HEADERS, nva,
12486                     nvlen, mem);
12487   assert_ptrdiff(0, ==, rv);
12488 
12489   ud->frame_recv_cb_called = 0;
12490 
12491   rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
12492                                  nghttp2_buf_len(&bufs.head->buf));
12493 
12494   assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(&bufs.head->buf), ==, rv);
12495   assert_null(nghttp2_session_get_next_ob_item(session));
12496   assert_int(1, ==, ud->frame_recv_cb_called);
12497 
12498   nghttp2_bufs_free(&bufs);
12499 }
12500 
test_nghttp2_http_mandatory_headers(void)12501 void test_nghttp2_http_mandatory_headers(void) {
12502   nghttp2_session *session;
12503   nghttp2_session_callbacks callbacks;
12504   nghttp2_hd_deflater deflater;
12505   nghttp2_mem *mem;
12506   my_user_data ud;
12507   /* test case for response */
12508   const nghttp2_nv nostatus_resnv[] = {MAKE_NV("server", "foo")};
12509   const nghttp2_nv dupstatus_resnv[] = {MAKE_NV(":status", "200"),
12510                                         MAKE_NV(":status", "200")};
12511   const nghttp2_nv badpseudo_resnv[] = {MAKE_NV(":status", "200"),
12512                                         MAKE_NV(":scheme", "https")};
12513   const nghttp2_nv latepseudo_resnv[] = {MAKE_NV("server", "foo"),
12514                                          MAKE_NV(":status", "200")};
12515   const nghttp2_nv badstatus_resnv[] = {MAKE_NV(":status", "2000")};
12516   const nghttp2_nv badcl_resnv[] = {MAKE_NV(":status", "200"),
12517                                     MAKE_NV("content-length", "-1")};
12518   const nghttp2_nv dupcl_resnv[] = {MAKE_NV(":status", "200"),
12519                                     MAKE_NV("content-length", "0"),
12520                                     MAKE_NV("content-length", "0")};
12521   const nghttp2_nv badhd_resnv[] = {MAKE_NV(":status", "200"),
12522                                     MAKE_NV("connection", "close")};
12523   const nghttp2_nv cl1xx_resnv[] = {MAKE_NV(":status", "100"),
12524                                     MAKE_NV("content-length", "0")};
12525   const nghttp2_nv cl204_resnv[] = {MAKE_NV(":status", "204"),
12526                                     MAKE_NV("content-length", "0")};
12527   const nghttp2_nv clnonzero204_resnv[] = {MAKE_NV(":status", "204"),
12528                                            MAKE_NV("content-length", "100")};
12529   const nghttp2_nv status101_resnv[] = {MAKE_NV(":status", "101")};
12530   const nghttp2_nv unexpectedhost_resnv[] = {MAKE_NV(":status", "200"),
12531                                              MAKE_NV("host", "/localhost")};
12532 
12533   /* test case for request */
12534   const nghttp2_nv nopath_reqnv[] = {MAKE_NV(":scheme", "https"),
12535                                      MAKE_NV(":method", "GET"),
12536                                      MAKE_NV(":authority", "localhost")};
12537   const nghttp2_nv earlyconnect_reqnv[] = {
12538     MAKE_NV(":method", "CONNECT"), MAKE_NV(":scheme", "https"),
12539     MAKE_NV(":path", "/"), MAKE_NV(":authority", "localhost")};
12540   const nghttp2_nv lateconnect_reqnv[] = {
12541     MAKE_NV(":scheme", "https"), MAKE_NV(":path", "/"),
12542     MAKE_NV(":method", "CONNECT"), MAKE_NV(":authority", "localhost")};
12543   const nghttp2_nv duppath_reqnv[] = {
12544     MAKE_NV(":scheme", "https"), MAKE_NV(":method", "GET"),
12545     MAKE_NV(":authority", "localhost"), MAKE_NV(":path", "/"),
12546     MAKE_NV(":path", "/")};
12547   const nghttp2_nv badcl_reqnv[] = {
12548     MAKE_NV(":scheme", "https"), MAKE_NV(":method", "POST"),
12549     MAKE_NV(":authority", "localhost"), MAKE_NV(":path", "/"),
12550     MAKE_NV("content-length", "-1")};
12551   const nghttp2_nv dupcl_reqnv[] = {
12552     MAKE_NV(":scheme", "https"),        MAKE_NV(":method", "POST"),
12553     MAKE_NV(":authority", "localhost"), MAKE_NV(":path", "/"),
12554     MAKE_NV("content-length", "0"),     MAKE_NV("content-length", "0")};
12555   const nghttp2_nv badhd_reqnv[] = {
12556     MAKE_NV(":scheme", "https"), MAKE_NV(":method", "GET"),
12557     MAKE_NV(":authority", "localhost"), MAKE_NV(":path", "/"),
12558     MAKE_NV("connection", "close")};
12559   const nghttp2_nv badauthority_reqnv[] = {
12560     MAKE_NV(":scheme", "https"), MAKE_NV(":method", "GET"),
12561     MAKE_NV(":authority", "\x0d\x0alocalhost"), MAKE_NV(":path", "/")};
12562   const nghttp2_nv badhdbtw_reqnv[] = {
12563     MAKE_NV(":scheme", "https"), MAKE_NV(":method", "GET"),
12564     MAKE_NV("foo", "\x0d\x0a"), MAKE_NV(":authority", "localhost"),
12565     MAKE_NV(":path", "/")};
12566   const nghttp2_nv asteriskget1_reqnv[] = {
12567     MAKE_NV(":path", "*"), MAKE_NV(":scheme", "https"),
12568     MAKE_NV(":authority", "localhost"), MAKE_NV(":method", "GET")};
12569   const nghttp2_nv asteriskget2_reqnv[] = {
12570     MAKE_NV(":scheme", "https"), MAKE_NV(":authority", "localhost"),
12571     MAKE_NV(":method", "GET"), MAKE_NV(":path", "*")};
12572   const nghttp2_nv asteriskoptions1_reqnv[] = {
12573     MAKE_NV(":path", "*"), MAKE_NV(":scheme", "https"),
12574     MAKE_NV(":authority", "localhost"), MAKE_NV(":method", "OPTIONS")};
12575   const nghttp2_nv asteriskoptions2_reqnv[] = {
12576     MAKE_NV(":scheme", "https"), MAKE_NV(":authority", "localhost"),
12577     MAKE_NV(":method", "OPTIONS"), MAKE_NV(":path", "*")};
12578   const nghttp2_nv connectproto_reqnv[] = {
12579     MAKE_NV(":scheme", "https"), MAKE_NV(":path", "/"),
12580     MAKE_NV(":method", "CONNECT"), MAKE_NV(":authority", "localhost"),
12581     MAKE_NV(":protocol", "websocket")};
12582   const nghttp2_nv connectprotoget_reqnv[] = {
12583     MAKE_NV(":scheme", "https"), MAKE_NV(":path", "/"),
12584     MAKE_NV(":method", "GET"), MAKE_NV(":authority", "localhost"),
12585     MAKE_NV(":protocol", "websocket")};
12586   const nghttp2_nv connectprotonopath_reqnv[] = {
12587     MAKE_NV(":scheme", "https"), MAKE_NV(":method", "CONNECT"),
12588     MAKE_NV(":authority", "localhost"), MAKE_NV(":protocol", "websocket")};
12589   const nghttp2_nv connectprotonoauth_reqnv[] = {
12590     MAKE_NV(":scheme", "http"), MAKE_NV(":path", "/"),
12591     MAKE_NV(":method", "CONNECT"), MAKE_NV("host", "localhost"),
12592     MAKE_NV(":protocol", "websocket")};
12593   const nghttp2_nv regularconnect_reqnv[] = {
12594     MAKE_NV(":method", "CONNECT"), MAKE_NV(":authority", "localhost")};
12595 
12596   mem = nghttp2_mem_default();
12597 
12598   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
12599   callbacks.send_callback2 = null_send_callback;
12600   callbacks.on_frame_recv_callback = on_frame_recv_callback;
12601   callbacks.on_invalid_frame_recv_callback = on_invalid_frame_recv_callback;
12602 
12603   nghttp2_session_client_new(&session, &callbacks, &ud);
12604 
12605   nghttp2_hd_deflate_init(&deflater, mem);
12606 
12607   /* response header lacks :status */
12608   check_nghttp2_http_recv_headers_fail(session, &deflater, 1,
12609                                        NGHTTP2_STREAM_OPENING, nostatus_resnv,
12610                                        ARRLEN(nostatus_resnv));
12611 
12612   /* response header has 2 :status */
12613   check_nghttp2_http_recv_headers_fail(session, &deflater, 3,
12614                                        NGHTTP2_STREAM_OPENING, dupstatus_resnv,
12615                                        ARRLEN(dupstatus_resnv));
12616 
12617   /* response header has bad pseudo header :scheme */
12618   check_nghttp2_http_recv_headers_fail(session, &deflater, 5,
12619                                        NGHTTP2_STREAM_OPENING, badpseudo_resnv,
12620                                        ARRLEN(badpseudo_resnv));
12621 
12622   /* response header has :status after regular header field */
12623   check_nghttp2_http_recv_headers_fail(session, &deflater, 7,
12624                                        NGHTTP2_STREAM_OPENING, latepseudo_resnv,
12625                                        ARRLEN(latepseudo_resnv));
12626 
12627   /* response header has bad status code */
12628   check_nghttp2_http_recv_headers_fail(session, &deflater, 9,
12629                                        NGHTTP2_STREAM_OPENING, badstatus_resnv,
12630                                        ARRLEN(badstatus_resnv));
12631 
12632   /* response header has bad content-length */
12633   check_nghttp2_http_recv_headers_fail(session, &deflater, 11,
12634                                        NGHTTP2_STREAM_OPENING, badcl_resnv,
12635                                        ARRLEN(badcl_resnv));
12636 
12637   /* response header has multiple content-length */
12638   check_nghttp2_http_recv_headers_fail(session, &deflater, 13,
12639                                        NGHTTP2_STREAM_OPENING, dupcl_resnv,
12640                                        ARRLEN(dupcl_resnv));
12641 
12642   /* response header has disallowed header field */
12643   check_nghttp2_http_recv_headers_fail(session, &deflater, 15,
12644                                        NGHTTP2_STREAM_OPENING, badhd_resnv,
12645                                        ARRLEN(badhd_resnv));
12646 
12647   /* response header has content-length with 100 status code */
12648   check_nghttp2_http_recv_headers_fail(session, &deflater, 17,
12649                                        NGHTTP2_STREAM_OPENING, cl1xx_resnv,
12650                                        ARRLEN(cl1xx_resnv));
12651 
12652   /* response header has 0 content-length with 204 status code */
12653   check_nghttp2_http_recv_headers_ok(session, &deflater, 19,
12654                                      NGHTTP2_STREAM_OPENING, cl204_resnv,
12655                                      ARRLEN(cl204_resnv));
12656 
12657   /* response header has nonzero content-length with 204 status
12658      code */
12659   check_nghttp2_http_recv_headers_fail(
12660     session, &deflater, 21, NGHTTP2_STREAM_OPENING, clnonzero204_resnv,
12661     ARRLEN(clnonzero204_resnv));
12662 
12663   /* status code 101 should not be used in HTTP/2 because it is used
12664      for HTTP Upgrade which HTTP/2 removes. */
12665   check_nghttp2_http_recv_headers_fail(session, &deflater, 23,
12666                                        NGHTTP2_STREAM_OPENING, status101_resnv,
12667                                        ARRLEN(status101_resnv));
12668 
12669   /* Specific characters check for host field in response header
12670      should not be done as its use is undefined. */
12671   check_nghttp2_http_recv_headers_ok(
12672     session, &deflater, 25, NGHTTP2_STREAM_OPENING, unexpectedhost_resnv,
12673     ARRLEN(unexpectedhost_resnv));
12674 
12675   nghttp2_hd_deflate_free(&deflater);
12676 
12677   nghttp2_session_del(session);
12678 
12679   /* check server side */
12680   nghttp2_session_server_new(&session, &callbacks, &ud);
12681 
12682   nghttp2_hd_deflate_init(&deflater, mem);
12683 
12684   /* request header has no :path */
12685   check_nghttp2_http_recv_headers_fail(session, &deflater, 1, -1, nopath_reqnv,
12686                                        ARRLEN(nopath_reqnv));
12687 
12688   /* request header has CONNECT method, but followed by :path */
12689   check_nghttp2_http_recv_headers_fail(
12690     session, &deflater, 3, -1, earlyconnect_reqnv, ARRLEN(earlyconnect_reqnv));
12691 
12692   /* request header has CONNECT method following :path */
12693   check_nghttp2_http_recv_headers_fail(
12694     session, &deflater, 5, -1, lateconnect_reqnv, ARRLEN(lateconnect_reqnv));
12695 
12696   /* request header has multiple :path */
12697   check_nghttp2_http_recv_headers_fail(session, &deflater, 7, -1, duppath_reqnv,
12698                                        ARRLEN(duppath_reqnv));
12699 
12700   /* request header has bad content-length */
12701   check_nghttp2_http_recv_headers_fail(session, &deflater, 9, -1, badcl_reqnv,
12702                                        ARRLEN(badcl_reqnv));
12703 
12704   /* request header has multiple content-length */
12705   check_nghttp2_http_recv_headers_fail(session, &deflater, 11, -1, dupcl_reqnv,
12706                                        ARRLEN(dupcl_reqnv));
12707 
12708   /* request header has disallowed header field */
12709   check_nghttp2_http_recv_headers_fail(session, &deflater, 13, -1, badhd_reqnv,
12710                                        ARRLEN(badhd_reqnv));
12711 
12712   /* request header has :authority header field containing illegal
12713      characters */
12714   check_nghttp2_http_recv_headers_fail(
12715     session, &deflater, 15, -1, badauthority_reqnv, ARRLEN(badauthority_reqnv));
12716 
12717   /* request header has regular header field containing illegal
12718      character before all mandatory header fields are seen. */
12719   check_nghttp2_http_recv_headers_fail(session, &deflater, 17, -1,
12720                                        badhdbtw_reqnv, ARRLEN(badhdbtw_reqnv));
12721 
12722   /* request header has "*" in :path header field while method is GET.
12723      :path is received before :method */
12724   check_nghttp2_http_recv_headers_fail(
12725     session, &deflater, 19, -1, asteriskget1_reqnv, ARRLEN(asteriskget1_reqnv));
12726 
12727   /* request header has "*" in :path header field while method is GET.
12728      :method is received before :path */
12729   check_nghttp2_http_recv_headers_fail(
12730     session, &deflater, 21, -1, asteriskget2_reqnv, ARRLEN(asteriskget2_reqnv));
12731 
12732   /* OPTIONS method can include "*" in :path header field.  :path is
12733      received before :method. */
12734   check_nghttp2_http_recv_headers_ok(session, &deflater, 23, -1,
12735                                      asteriskoptions1_reqnv,
12736                                      ARRLEN(asteriskoptions1_reqnv));
12737 
12738   /* OPTIONS method can include "*" in :path header field.  :method is
12739      received before :path. */
12740   check_nghttp2_http_recv_headers_ok(session, &deflater, 25, -1,
12741                                      asteriskoptions2_reqnv,
12742                                      ARRLEN(asteriskoptions2_reqnv));
12743 
12744   /* :protocol is not allowed unless it is enabled by the local
12745      endpoint. */
12746   check_nghttp2_http_recv_headers_fail(
12747     session, &deflater, 27, -1, connectproto_reqnv, ARRLEN(connectproto_reqnv));
12748 
12749   nghttp2_hd_deflate_free(&deflater);
12750 
12751   nghttp2_session_del(session);
12752 
12753   /* enable SETTINGS_CONNECT_PROTOCOL */
12754   nghttp2_session_server_new(&session, &callbacks, &ud);
12755 
12756   session->pending_enable_connect_protocol = 1;
12757 
12758   nghttp2_hd_deflate_init(&deflater, mem);
12759 
12760   /* :protocol is allowed if SETTINGS_CONNECT_PROTOCOL is enabled by
12761      the local endpoint. */
12762   check_nghttp2_http_recv_headers_ok(
12763     session, &deflater, 1, -1, connectproto_reqnv, ARRLEN(connectproto_reqnv));
12764 
12765   /* :protocol is only allowed with CONNECT method. */
12766   check_nghttp2_http_recv_headers_fail(session, &deflater, 3, -1,
12767                                        connectprotoget_reqnv,
12768                                        ARRLEN(connectprotoget_reqnv));
12769 
12770   /* CONNECT method with :protocol requires :path. */
12771   check_nghttp2_http_recv_headers_fail(session, &deflater, 5, -1,
12772                                        connectprotonopath_reqnv,
12773                                        ARRLEN(connectprotonopath_reqnv));
12774 
12775   /* CONNECT method with :protocol requires :authority. */
12776   check_nghttp2_http_recv_headers_fail(session, &deflater, 7, -1,
12777                                        connectprotonoauth_reqnv,
12778                                        ARRLEN(connectprotonoauth_reqnv));
12779 
12780   /* regular CONNECT method should succeed with
12781      SETTINGS_CONNECT_PROTOCOL */
12782   check_nghttp2_http_recv_headers_ok(session, &deflater, 9, -1,
12783                                      regularconnect_reqnv,
12784                                      ARRLEN(regularconnect_reqnv));
12785 
12786   nghttp2_hd_deflate_free(&deflater);
12787 
12788   nghttp2_session_del(session);
12789 }
12790 
test_nghttp2_http_content_length(void)12791 void test_nghttp2_http_content_length(void) {
12792   nghttp2_session *session;
12793   nghttp2_session_callbacks callbacks;
12794   nghttp2_hd_deflater deflater;
12795   nghttp2_mem *mem;
12796   nghttp2_bufs bufs;
12797   nghttp2_ssize rv;
12798   nghttp2_stream *stream;
12799   const nghttp2_nv cl_resnv[] = {MAKE_NV(":status", "200"),
12800                                  MAKE_NV("te", "trailers"),
12801                                  MAKE_NV("content-length", "9000000000")};
12802   const nghttp2_nv cl_reqnv[] = {
12803     MAKE_NV(":path", "/"),        MAKE_NV(":method", "PUT"),
12804     MAKE_NV(":scheme", "https"),  MAKE_NV("te", "trailers"),
12805     MAKE_NV("host", "localhost"), MAKE_NV("content-length", "9000000000")};
12806 
12807   mem = nghttp2_mem_default();
12808   frame_pack_bufs_init(&bufs);
12809 
12810   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
12811   callbacks.send_callback2 = null_send_callback;
12812 
12813   nghttp2_session_client_new(&session, &callbacks, NULL);
12814 
12815   nghttp2_hd_deflate_init(&deflater, mem);
12816 
12817   stream = open_sent_stream2(session, 1, NGHTTP2_STREAM_OPENING);
12818 
12819   rv = pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, cl_resnv,
12820                     ARRLEN(cl_resnv), mem);
12821   assert_ptrdiff(0, ==, rv);
12822 
12823   rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
12824                                  nghttp2_buf_len(&bufs.head->buf));
12825 
12826   assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(&bufs.head->buf), ==, rv);
12827   assert_null(nghttp2_session_get_next_ob_item(session));
12828   assert_int64(9000000000LL, ==, stream->content_length);
12829   assert_int16(200, ==, stream->status_code);
12830 
12831   nghttp2_hd_deflate_free(&deflater);
12832 
12833   nghttp2_session_del(session);
12834 
12835   nghttp2_bufs_reset(&bufs);
12836 
12837   /* check server side */
12838   nghttp2_session_server_new(&session, &callbacks, NULL);
12839 
12840   nghttp2_hd_deflate_init(&deflater, mem);
12841 
12842   rv = pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, cl_reqnv,
12843                     ARRLEN(cl_reqnv), mem);
12844   assert_ptrdiff(0, ==, rv);
12845 
12846   rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
12847                                  nghttp2_buf_len(&bufs.head->buf));
12848 
12849   assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(&bufs.head->buf), ==, rv);
12850 
12851   stream = nghttp2_session_get_stream(session, 1);
12852 
12853   assert_null(nghttp2_session_get_next_ob_item(session));
12854   assert_int64(9000000000LL, ==, stream->content_length);
12855 
12856   nghttp2_hd_deflate_free(&deflater);
12857 
12858   nghttp2_session_del(session);
12859 
12860   nghttp2_bufs_free(&bufs);
12861 }
12862 
test_nghttp2_http_content_length_mismatch(void)12863 void test_nghttp2_http_content_length_mismatch(void) {
12864   nghttp2_session *session;
12865   nghttp2_session_callbacks callbacks;
12866   nghttp2_hd_deflater deflater;
12867   nghttp2_mem *mem;
12868   nghttp2_bufs bufs;
12869   nghttp2_ssize rv;
12870   const nghttp2_nv cl_reqnv[] = {
12871     MAKE_NV(":path", "/"), MAKE_NV(":method", "PUT"),
12872     MAKE_NV(":authority", "localhost"), MAKE_NV(":scheme", "https"),
12873     MAKE_NV("content-length", "20")};
12874   const nghttp2_nv cl_resnv[] = {MAKE_NV(":status", "200"),
12875                                  MAKE_NV("content-length", "20")};
12876   nghttp2_outbound_item *item;
12877   nghttp2_frame_hd hd;
12878 
12879   mem = nghttp2_mem_default();
12880   frame_pack_bufs_init(&bufs);
12881 
12882   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
12883   callbacks.send_callback2 = null_send_callback;
12884 
12885   nghttp2_session_server_new(&session, &callbacks, NULL);
12886 
12887   nghttp2_hd_deflate_init(&deflater, mem);
12888 
12889   /* header says content-length: 20, but HEADERS has END_STREAM flag set */
12890   rv = pack_headers(&bufs, &deflater, 1,
12891                     NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM,
12892                     cl_reqnv, ARRLEN(cl_reqnv), mem);
12893   assert_ptrdiff(0, ==, rv);
12894 
12895   rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
12896                                  nghttp2_buf_len(&bufs.head->buf));
12897 
12898   assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(&bufs.head->buf), ==, rv);
12899 
12900   item = nghttp2_session_get_next_ob_item(session);
12901   assert_uint8(NGHTTP2_RST_STREAM, ==, item->frame.hd.type);
12902 
12903   assert_int(0, ==, nghttp2_session_send(session));
12904 
12905   nghttp2_bufs_reset(&bufs);
12906 
12907   /* header says content-length: 20, but DATA has 0 byte */
12908   rv = pack_headers(&bufs, &deflater, 3, NGHTTP2_FLAG_END_HEADERS, cl_reqnv,
12909                     ARRLEN(cl_reqnv), mem);
12910   assert_ptrdiff(0, ==, rv);
12911 
12912   nghttp2_frame_hd_init(&hd, 0, NGHTTP2_DATA, NGHTTP2_FLAG_END_STREAM, 3);
12913   nghttp2_frame_pack_frame_hd(bufs.head->buf.last, &hd);
12914   bufs.head->buf.last += NGHTTP2_FRAME_HDLEN;
12915 
12916   rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
12917                                  nghttp2_buf_len(&bufs.head->buf));
12918 
12919   assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(&bufs.head->buf), ==, rv);
12920 
12921   item = nghttp2_session_get_next_ob_item(session);
12922   assert_uint8(NGHTTP2_RST_STREAM, ==, item->frame.hd.type);
12923 
12924   assert_int(0, ==, nghttp2_session_send(session));
12925 
12926   nghttp2_bufs_reset(&bufs);
12927 
12928   /* header says content-length: 20, but DATA has 21 bytes */
12929   rv = pack_headers(&bufs, &deflater, 5, NGHTTP2_FLAG_END_HEADERS, cl_reqnv,
12930                     ARRLEN(cl_reqnv), mem);
12931   assert_ptrdiff(0, ==, rv);
12932 
12933   nghttp2_frame_hd_init(&hd, 21, NGHTTP2_DATA, NGHTTP2_FLAG_END_STREAM, 5);
12934   nghttp2_frame_pack_frame_hd(bufs.head->buf.last, &hd);
12935   bufs.head->buf.last += NGHTTP2_FRAME_HDLEN + 21;
12936 
12937   rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
12938                                  nghttp2_buf_len(&bufs.head->buf));
12939 
12940   assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(&bufs.head->buf), ==, rv);
12941 
12942   item = nghttp2_session_get_next_ob_item(session);
12943   assert_uint8(NGHTTP2_RST_STREAM, ==, item->frame.hd.type);
12944 
12945   assert_int(0, ==, nghttp2_session_send(session));
12946 
12947   nghttp2_bufs_reset(&bufs);
12948 
12949   nghttp2_hd_deflate_free(&deflater);
12950 
12951   nghttp2_session_del(session);
12952 
12953   /* Check for client */
12954   nghttp2_session_client_new(&session, &callbacks, NULL);
12955 
12956   nghttp2_hd_deflate_init(&deflater, mem);
12957 
12958   /* header says content-length: 20, but HEADERS has END_STREAM flag set */
12959   nghttp2_submit_request2(session, NULL, reqnv, ARRLEN(reqnv), NULL, NULL);
12960 
12961   assert_int(0, ==, nghttp2_session_send(session));
12962 
12963   rv = pack_headers(&bufs, &deflater, 1,
12964                     NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM,
12965                     cl_resnv, ARRLEN(cl_resnv), mem);
12966   assert_ptrdiff(0, ==, rv);
12967 
12968   rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
12969                                  nghttp2_buf_len(&bufs.head->buf));
12970 
12971   assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(&bufs.head->buf), ==, rv);
12972 
12973   item = nghttp2_session_get_next_ob_item(session);
12974   assert_uint8(NGHTTP2_RST_STREAM, ==, item->frame.hd.type);
12975 
12976   assert_not_null(nghttp2_session_get_stream(session, 1));
12977   assert_int(0, ==, nghttp2_session_send(session));
12978   /* After sending RST_STREAM, stream must be closed */
12979   assert_null(nghttp2_session_get_stream(session, 1));
12980 
12981   nghttp2_bufs_reset(&bufs);
12982 
12983   /* header says content-length: 20, but DATA has 0 byte */
12984   nghttp2_submit_request2(session, NULL, reqnv, ARRLEN(reqnv), NULL, NULL);
12985 
12986   assert_int(0, ==, nghttp2_session_send(session));
12987 
12988   rv = pack_headers(&bufs, &deflater, 3, NGHTTP2_FLAG_END_HEADERS, cl_resnv,
12989                     ARRLEN(cl_resnv), mem);
12990   assert_ptrdiff(0, ==, rv);
12991 
12992   nghttp2_frame_hd_init(&hd, 0, NGHTTP2_DATA, NGHTTP2_FLAG_END_STREAM, 3);
12993   nghttp2_frame_pack_frame_hd(bufs.head->buf.last, &hd);
12994   bufs.head->buf.last += NGHTTP2_FRAME_HDLEN;
12995 
12996   rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
12997                                  nghttp2_buf_len(&bufs.head->buf));
12998 
12999   assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(&bufs.head->buf), ==, rv);
13000 
13001   item = nghttp2_session_get_next_ob_item(session);
13002   assert_uint8(NGHTTP2_RST_STREAM, ==, item->frame.hd.type);
13003 
13004   assert_not_null(nghttp2_session_get_stream(session, 3));
13005   assert_int(0, ==, nghttp2_session_send(session));
13006   /* After sending RST_STREAM, stream must be closed */
13007   assert_null(nghttp2_session_get_stream(session, 3));
13008 
13009   nghttp2_bufs_reset(&bufs);
13010 
13011   /* header says content-length: 20, but DATA has 21 bytes */
13012   nghttp2_submit_request2(session, NULL, reqnv, ARRLEN(reqnv), NULL, NULL);
13013 
13014   assert_int(0, ==, nghttp2_session_send(session));
13015 
13016   rv = pack_headers(&bufs, &deflater, 5, NGHTTP2_FLAG_END_HEADERS, cl_resnv,
13017                     ARRLEN(cl_resnv), mem);
13018   assert_ptrdiff(0, ==, rv);
13019 
13020   nghttp2_frame_hd_init(&hd, 21, NGHTTP2_DATA, NGHTTP2_FLAG_END_STREAM, 5);
13021   nghttp2_frame_pack_frame_hd(bufs.head->buf.last, &hd);
13022   bufs.head->buf.last += NGHTTP2_FRAME_HDLEN + 21;
13023 
13024   rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
13025                                  nghttp2_buf_len(&bufs.head->buf));
13026 
13027   assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(&bufs.head->buf), ==, rv);
13028 
13029   item = nghttp2_session_get_next_ob_item(session);
13030   assert_uint8(NGHTTP2_RST_STREAM, ==, item->frame.hd.type);
13031 
13032   assert_not_null(nghttp2_session_get_stream(session, 5));
13033   assert_int(0, ==, nghttp2_session_send(session));
13034   /* After sending RST_STREAM, stream must be closed */
13035   assert_null(nghttp2_session_get_stream(session, 5));
13036 
13037   nghttp2_bufs_reset(&bufs);
13038 
13039   nghttp2_bufs_free(&bufs);
13040 
13041   nghttp2_hd_deflate_free(&deflater);
13042 
13043   nghttp2_session_del(session);
13044 }
13045 
test_nghttp2_http_non_final_response(void)13046 void test_nghttp2_http_non_final_response(void) {
13047   nghttp2_session *session;
13048   nghttp2_session_callbacks callbacks;
13049   nghttp2_hd_deflater deflater;
13050   nghttp2_mem *mem;
13051   nghttp2_bufs bufs;
13052   nghttp2_ssize rv;
13053   const nghttp2_nv nonfinal_resnv[] = {
13054     MAKE_NV(":status", "100"),
13055   };
13056   nghttp2_outbound_item *item;
13057   nghttp2_frame_hd hd;
13058 
13059   mem = nghttp2_mem_default();
13060   frame_pack_bufs_init(&bufs);
13061 
13062   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
13063   callbacks.send_callback2 = null_send_callback;
13064 
13065   nghttp2_session_client_new(&session, &callbacks, NULL);
13066 
13067   nghttp2_hd_deflate_init(&deflater, mem);
13068 
13069   /* non-final HEADERS with END_STREAM is illegal */
13070   open_sent_stream2(session, 1, NGHTTP2_STREAM_OPENING);
13071 
13072   rv = pack_headers(&bufs, &deflater, 1,
13073                     NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM,
13074                     nonfinal_resnv, ARRLEN(nonfinal_resnv), mem);
13075   assert_ptrdiff(0, ==, rv);
13076 
13077   rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
13078                                  nghttp2_buf_len(&bufs.head->buf));
13079 
13080   assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(&bufs.head->buf), ==, rv);
13081 
13082   item = nghttp2_session_get_next_ob_item(session);
13083   assert_uint8(NGHTTP2_RST_STREAM, ==, item->frame.hd.type);
13084 
13085   assert_int(0, ==, nghttp2_session_send(session));
13086 
13087   nghttp2_bufs_reset(&bufs);
13088 
13089   /* non-final HEADERS followed by non-empty DATA is illegal */
13090   open_sent_stream2(session, 3, NGHTTP2_STREAM_OPENING);
13091 
13092   rv = pack_headers(&bufs, &deflater, 3, NGHTTP2_FLAG_END_HEADERS,
13093                     nonfinal_resnv, ARRLEN(nonfinal_resnv), mem);
13094   assert_ptrdiff(0, ==, rv);
13095 
13096   nghttp2_frame_hd_init(&hd, 10, NGHTTP2_DATA, NGHTTP2_FLAG_END_STREAM, 3);
13097   nghttp2_frame_pack_frame_hd(bufs.head->buf.last, &hd);
13098   bufs.head->buf.last += NGHTTP2_FRAME_HDLEN + 10;
13099 
13100   rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
13101                                  nghttp2_buf_len(&bufs.head->buf));
13102 
13103   assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(&bufs.head->buf), ==, rv);
13104 
13105   item = nghttp2_session_get_next_ob_item(session);
13106   assert_uint8(NGHTTP2_RST_STREAM, ==, item->frame.hd.type);
13107 
13108   assert_int(0, ==, nghttp2_session_send(session));
13109 
13110   nghttp2_bufs_reset(&bufs);
13111 
13112   /* non-final HEADERS followed by empty DATA (without END_STREAM) is
13113      ok */
13114   open_sent_stream2(session, 5, NGHTTP2_STREAM_OPENING);
13115 
13116   rv = pack_headers(&bufs, &deflater, 5, NGHTTP2_FLAG_END_HEADERS,
13117                     nonfinal_resnv, ARRLEN(nonfinal_resnv), mem);
13118   assert_ptrdiff(0, ==, rv);
13119 
13120   nghttp2_frame_hd_init(&hd, 0, NGHTTP2_DATA, NGHTTP2_FLAG_NONE, 5);
13121   nghttp2_frame_pack_frame_hd(bufs.head->buf.last, &hd);
13122   bufs.head->buf.last += NGHTTP2_FRAME_HDLEN;
13123 
13124   rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
13125                                  nghttp2_buf_len(&bufs.head->buf));
13126 
13127   assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(&bufs.head->buf), ==, rv);
13128 
13129   assert_null(nghttp2_session_get_next_ob_item(session));
13130 
13131   nghttp2_bufs_reset(&bufs);
13132 
13133   /* non-final HEADERS followed by empty DATA (with END_STREAM) is
13134      illegal */
13135   open_sent_stream2(session, 7, NGHTTP2_STREAM_OPENING);
13136 
13137   rv = pack_headers(&bufs, &deflater, 7, NGHTTP2_FLAG_END_HEADERS,
13138                     nonfinal_resnv, ARRLEN(nonfinal_resnv), mem);
13139   assert_ptrdiff(0, ==, rv);
13140 
13141   nghttp2_frame_hd_init(&hd, 0, NGHTTP2_DATA, NGHTTP2_FLAG_END_STREAM, 7);
13142   nghttp2_frame_pack_frame_hd(bufs.head->buf.last, &hd);
13143   bufs.head->buf.last += NGHTTP2_FRAME_HDLEN;
13144 
13145   rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
13146                                  nghttp2_buf_len(&bufs.head->buf));
13147 
13148   assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(&bufs.head->buf), ==, rv);
13149 
13150   item = nghttp2_session_get_next_ob_item(session);
13151 
13152   assert_uint8(NGHTTP2_RST_STREAM, ==, item->frame.hd.type);
13153 
13154   assert_int(0, ==, nghttp2_session_send(session));
13155 
13156   nghttp2_bufs_reset(&bufs);
13157 
13158   /* non-final HEADERS followed by final HEADERS is OK */
13159   open_sent_stream2(session, 9, NGHTTP2_STREAM_OPENING);
13160 
13161   rv = pack_headers(&bufs, &deflater, 9, NGHTTP2_FLAG_END_HEADERS,
13162                     nonfinal_resnv, ARRLEN(nonfinal_resnv), mem);
13163   assert_ptrdiff(0, ==, rv);
13164 
13165   rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
13166                                  nghttp2_buf_len(&bufs.head->buf));
13167 
13168   assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(&bufs.head->buf), ==, rv);
13169 
13170   nghttp2_bufs_reset(&bufs);
13171 
13172   rv = pack_headers(&bufs, &deflater, 9, NGHTTP2_FLAG_END_HEADERS, resnv,
13173                     ARRLEN(resnv), mem);
13174   assert_ptrdiff(0, ==, rv);
13175 
13176   rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
13177                                  nghttp2_buf_len(&bufs.head->buf));
13178 
13179   assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(&bufs.head->buf), ==, rv);
13180 
13181   assert_null(nghttp2_session_get_next_ob_item(session));
13182 
13183   nghttp2_bufs_reset(&bufs);
13184 
13185   nghttp2_hd_deflate_free(&deflater);
13186 
13187   nghttp2_session_del(session);
13188 
13189   nghttp2_bufs_free(&bufs);
13190 }
13191 
test_nghttp2_http_trailer_headers(void)13192 void test_nghttp2_http_trailer_headers(void) {
13193   nghttp2_session *session;
13194   nghttp2_session_callbacks callbacks;
13195   nghttp2_hd_deflater deflater;
13196   nghttp2_mem *mem;
13197   nghttp2_bufs bufs;
13198   nghttp2_ssize rv;
13199   const nghttp2_nv trailer_reqnv[] = {
13200     MAKE_NV("foo", "bar"),
13201   };
13202   nghttp2_outbound_item *item;
13203 
13204   mem = nghttp2_mem_default();
13205   frame_pack_bufs_init(&bufs);
13206 
13207   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
13208   callbacks.send_callback2 = null_send_callback;
13209 
13210   nghttp2_session_server_new(&session, &callbacks, NULL);
13211 
13212   nghttp2_hd_deflate_init(&deflater, mem);
13213 
13214   /* good trailer header */
13215   rv = pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, reqnv,
13216                     ARRLEN(reqnv), mem);
13217   assert_ptrdiff(0, ==, rv);
13218 
13219   rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
13220                                  nghttp2_buf_len(&bufs.head->buf));
13221 
13222   assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(&bufs.head->buf), ==, rv);
13223 
13224   nghttp2_bufs_reset(&bufs);
13225 
13226   rv = pack_headers(&bufs, &deflater, 1,
13227                     NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM,
13228                     trailer_reqnv, ARRLEN(trailer_reqnv), mem);
13229   assert_ptrdiff(0, ==, rv);
13230 
13231   rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
13232                                  nghttp2_buf_len(&bufs.head->buf));
13233 
13234   assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(&bufs.head->buf), ==, rv);
13235 
13236   assert_null(nghttp2_session_get_next_ob_item(session));
13237 
13238   nghttp2_bufs_reset(&bufs);
13239 
13240   /* trailer header without END_STREAM is illegal */
13241   rv = pack_headers(&bufs, &deflater, 3, NGHTTP2_FLAG_END_HEADERS, reqnv,
13242                     ARRLEN(reqnv), mem);
13243   assert_ptrdiff(0, ==, rv);
13244 
13245   rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
13246                                  nghttp2_buf_len(&bufs.head->buf));
13247 
13248   assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(&bufs.head->buf), ==, rv);
13249 
13250   nghttp2_bufs_reset(&bufs);
13251 
13252   rv = pack_headers(&bufs, &deflater, 3, NGHTTP2_FLAG_END_HEADERS,
13253                     trailer_reqnv, ARRLEN(trailer_reqnv), mem);
13254   assert_ptrdiff(0, ==, rv);
13255 
13256   rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
13257                                  nghttp2_buf_len(&bufs.head->buf));
13258 
13259   assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(&bufs.head->buf), ==, rv);
13260 
13261   item = nghttp2_session_get_next_ob_item(session);
13262 
13263   assert_uint8(NGHTTP2_RST_STREAM, ==, item->frame.hd.type);
13264 
13265   assert_int(0, ==, nghttp2_session_send(session));
13266 
13267   nghttp2_bufs_reset(&bufs);
13268 
13269   /* trailer header including pseudo header field is illegal */
13270   rv = pack_headers(&bufs, &deflater, 5, NGHTTP2_FLAG_END_HEADERS, reqnv,
13271                     ARRLEN(reqnv), mem);
13272   assert_ptrdiff(0, ==, rv);
13273 
13274   rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
13275                                  nghttp2_buf_len(&bufs.head->buf));
13276 
13277   assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(&bufs.head->buf), ==, rv);
13278 
13279   nghttp2_bufs_reset(&bufs);
13280 
13281   rv = pack_headers(&bufs, &deflater, 5, NGHTTP2_FLAG_END_HEADERS, reqnv,
13282                     ARRLEN(reqnv), mem);
13283   assert_ptrdiff(0, ==, rv);
13284 
13285   rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
13286                                  nghttp2_buf_len(&bufs.head->buf));
13287 
13288   assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(&bufs.head->buf), ==, rv);
13289 
13290   item = nghttp2_session_get_next_ob_item(session);
13291 
13292   assert_uint8(NGHTTP2_RST_STREAM, ==, item->frame.hd.type);
13293 
13294   assert_int(0, ==, nghttp2_session_send(session));
13295 
13296   nghttp2_bufs_reset(&bufs);
13297 
13298   nghttp2_hd_deflate_free(&deflater);
13299 
13300   nghttp2_session_del(session);
13301 
13302   nghttp2_bufs_free(&bufs);
13303 }
13304 
test_nghttp2_http_ignore_regular_header(void)13305 void test_nghttp2_http_ignore_regular_header(void) {
13306   nghttp2_session *session;
13307   nghttp2_session_callbacks callbacks;
13308   nghttp2_hd_deflater deflater;
13309   nghttp2_mem *mem;
13310   nghttp2_bufs bufs;
13311   nghttp2_ssize rv;
13312   my_user_data ud;
13313   const nghttp2_nv bad_reqnv[] = {
13314     MAKE_NV(":authority", "localhost"),
13315     MAKE_NV(":scheme", "https"),
13316     MAKE_NV(":path", "/"),
13317     MAKE_NV(":method", "GET"),
13318     MAKE_NV("foo", "\x0zzz"),
13319     MAKE_NV("bar", "buzz"),
13320   };
13321   const nghttp2_nv bad_ansnv[] = {
13322     MAKE_NV(":authority", "localhost"), MAKE_NV(":scheme", "https"),
13323     MAKE_NV(":path", "/"), MAKE_NV(":method", "GET"), MAKE_NV("bar", "buzz")};
13324   size_t proclen;
13325   size_t i;
13326   nghttp2_outbound_item *item;
13327 
13328   mem = nghttp2_mem_default();
13329   frame_pack_bufs_init(&bufs);
13330 
13331   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
13332   callbacks.send_callback2 = null_send_callback;
13333   callbacks.on_header_callback = pause_on_header_callback;
13334 
13335   nghttp2_session_server_new(&session, &callbacks, &ud);
13336   nghttp2_hd_deflate_init(&deflater, mem);
13337 
13338   rv = pack_headers(&bufs, &deflater, 1,
13339                     NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM,
13340                     bad_reqnv, ARRLEN(bad_reqnv), mem);
13341 
13342   assert_ptrdiff(0, ==, rv);
13343 
13344   nghttp2_hd_deflate_free(&deflater);
13345 
13346   proclen = 0;
13347 
13348   for (i = 0; i < 4; ++i) {
13349     rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos + proclen,
13350                                    nghttp2_buf_len(&bufs.head->buf) - proclen);
13351     assert_ptrdiff(0, <, rv);
13352     proclen += (size_t)rv;
13353     assert_true(nghttp2_nv_equal(&bad_ansnv[i], &ud.nv));
13354   }
13355 
13356   rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos + proclen,
13357                                  nghttp2_buf_len(&bufs.head->buf) - proclen);
13358   assert_ptrdiff(0, <, rv);
13359   /* Without on_invalid_frame_recv_callback, bad header causes stream
13360      reset */
13361   item = nghttp2_session_get_next_ob_item(session);
13362 
13363   assert_uint8(NGHTTP2_RST_STREAM, ==, item->frame.hd.type);
13364 
13365   proclen += (size_t)rv;
13366 
13367   assert_size(nghttp2_buf_len(&bufs.head->buf), ==, proclen);
13368 
13369   nghttp2_session_del(session);
13370 
13371   /* use on_invalid_header_callback */
13372   callbacks.on_invalid_header_callback = pause_on_invalid_header_callback;
13373 
13374   nghttp2_session_server_new(&session, &callbacks, &ud);
13375 
13376   proclen = 0;
13377 
13378   ud.invalid_header_cb_called = 0;
13379 
13380   for (i = 0; i < 4; ++i) {
13381     rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos + proclen,
13382                                    nghttp2_buf_len(&bufs.head->buf) - proclen);
13383     assert_ptrdiff(0, <, rv);
13384     proclen += (size_t)rv;
13385     assert_true(nghttp2_nv_equal(&bad_ansnv[i], &ud.nv));
13386   }
13387 
13388   assert_int(0, ==, ud.invalid_header_cb_called);
13389 
13390   rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos + proclen,
13391                                  nghttp2_buf_len(&bufs.head->buf) - proclen);
13392 
13393   assert_ptrdiff(0, <, rv);
13394   assert_int(1, ==, ud.invalid_header_cb_called);
13395   assert_true(nghttp2_nv_equal(&bad_reqnv[4], &ud.nv));
13396 
13397   proclen += (size_t)rv;
13398 
13399   rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos + proclen,
13400                                  nghttp2_buf_len(&bufs.head->buf) - proclen);
13401 
13402   assert_ptrdiff(0, <, rv);
13403   assert_true(nghttp2_nv_equal(&bad_ansnv[4], &ud.nv));
13404 
13405   nghttp2_session_del(session);
13406 
13407   /* make sure that we can reset stream from
13408      on_invalid_header_callback */
13409   callbacks.on_header_callback = on_header_callback;
13410   callbacks.on_invalid_header_callback = reset_on_invalid_header_callback;
13411 
13412   nghttp2_session_server_new(&session, &callbacks, &ud);
13413 
13414   rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
13415                                  nghttp2_buf_len(&bufs.head->buf));
13416 
13417   assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(&bufs.head->buf), ==, rv);
13418 
13419   item = nghttp2_session_get_next_ob_item(session);
13420 
13421   assert_uint8(NGHTTP2_RST_STREAM, ==, item->frame.hd.type);
13422   assert_int32(1, ==, item->frame.hd.stream_id);
13423 
13424   nghttp2_session_del(session);
13425   nghttp2_bufs_free(&bufs);
13426 }
13427 
test_nghttp2_http_ignore_content_length(void)13428 void test_nghttp2_http_ignore_content_length(void) {
13429   nghttp2_session *session;
13430   nghttp2_session_callbacks callbacks;
13431   nghttp2_hd_deflater deflater;
13432   nghttp2_mem *mem;
13433   nghttp2_bufs bufs;
13434   nghttp2_ssize rv;
13435   const nghttp2_nv cl_resnv[] = {MAKE_NV(":status", "304"),
13436                                  MAKE_NV("content-length", "20")};
13437   const nghttp2_nv conn_reqnv[] = {MAKE_NV(":authority", "localhost"),
13438                                    MAKE_NV(":method", "CONNECT"),
13439                                    MAKE_NV("content-length", "999999")};
13440   const nghttp2_nv conn_cl_resnv[] = {MAKE_NV(":status", "200"),
13441                                       MAKE_NV("content-length", "0")};
13442   nghttp2_stream *stream;
13443 
13444   mem = nghttp2_mem_default();
13445   frame_pack_bufs_init(&bufs);
13446 
13447   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
13448   callbacks.send_callback2 = null_send_callback;
13449 
13450   nghttp2_session_client_new(&session, &callbacks, NULL);
13451 
13452   nghttp2_hd_deflate_init(&deflater, mem);
13453 
13454   /* If status 304, content-length must be ignored */
13455   open_sent_stream2(session, 1, NGHTTP2_STREAM_OPENING);
13456 
13457   rv = pack_headers(&bufs, &deflater, 1,
13458                     NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM,
13459                     cl_resnv, ARRLEN(cl_resnv), mem);
13460   assert_ptrdiff(0, ==, rv);
13461 
13462   rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
13463                                  nghttp2_buf_len(&bufs.head->buf));
13464 
13465   assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(&bufs.head->buf), ==, rv);
13466 
13467   assert_null(nghttp2_session_get_next_ob_item(session));
13468 
13469   nghttp2_bufs_reset(&bufs);
13470 
13471   /* Content-Length in 200 response to CONNECT is ignored */
13472   stream = open_sent_stream2(session, 3, NGHTTP2_STREAM_OPENING);
13473   stream->http_flags |= NGHTTP2_HTTP_FLAG_METH_CONNECT;
13474 
13475   rv = pack_headers(&bufs, &deflater, 3, NGHTTP2_FLAG_END_HEADERS,
13476                     conn_cl_resnv, ARRLEN(conn_cl_resnv), mem);
13477   assert_ptrdiff(0, ==, rv);
13478 
13479   rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
13480                                  nghttp2_buf_len(&bufs.head->buf));
13481 
13482   assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(&bufs.head->buf), ==, rv);
13483 
13484   assert_null(nghttp2_session_get_next_ob_item(session));
13485   assert_int64(-1, ==, stream->content_length);
13486 
13487   nghttp2_bufs_reset(&bufs);
13488 
13489   nghttp2_hd_deflate_free(&deflater);
13490   nghttp2_session_del(session);
13491 
13492   /* If request method is CONNECT, content-length must be ignored */
13493   nghttp2_session_server_new(&session, &callbacks, NULL);
13494 
13495   nghttp2_hd_deflate_init(&deflater, mem);
13496 
13497   rv = pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, conn_reqnv,
13498                     ARRLEN(conn_reqnv), mem);
13499 
13500   assert_ptrdiff(0, ==, rv);
13501 
13502   rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
13503                                  nghttp2_buf_len(&bufs.head->buf));
13504 
13505   assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(&bufs.head->buf), ==, rv);
13506 
13507   assert_null(nghttp2_session_get_next_ob_item(session));
13508 
13509   stream = nghttp2_session_get_stream(session, 1);
13510 
13511   assert_int64(-1, ==, stream->content_length);
13512   assert_true(stream->http_flags & NGHTTP2_HTTP_FLAG_METH_CONNECT);
13513 
13514   nghttp2_hd_deflate_free(&deflater);
13515   nghttp2_session_del(session);
13516   nghttp2_bufs_free(&bufs);
13517 }
13518 
test_nghttp2_http_record_request_method(void)13519 void test_nghttp2_http_record_request_method(void) {
13520   nghttp2_session *session;
13521   nghttp2_session_callbacks callbacks;
13522   const nghttp2_nv conn_reqnv[] = {MAKE_NV(":method", "CONNECT"),
13523                                    MAKE_NV(":authority", "localhost")};
13524   const nghttp2_nv conn_resnv[] = {MAKE_NV(":status", "200"),
13525                                    MAKE_NV("content-length", "9999")};
13526   nghttp2_stream *stream;
13527   nghttp2_ssize rv;
13528   nghttp2_bufs bufs;
13529   nghttp2_hd_deflater deflater;
13530   nghttp2_mem *mem;
13531   nghttp2_outbound_item *item;
13532 
13533   mem = nghttp2_mem_default();
13534   frame_pack_bufs_init(&bufs);
13535 
13536   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
13537   callbacks.send_callback2 = null_send_callback;
13538 
13539   nghttp2_session_client_new(&session, &callbacks, NULL);
13540 
13541   nghttp2_hd_deflate_init(&deflater, mem);
13542 
13543   assert_int32(1, ==,
13544                nghttp2_submit_request2(session, NULL, conn_reqnv,
13545                                        ARRLEN(conn_reqnv), NULL, NULL));
13546 
13547   assert_int(0, ==, nghttp2_session_send(session));
13548 
13549   stream = nghttp2_session_get_stream(session, 1);
13550 
13551   assert_uint32(NGHTTP2_HTTP_FLAG_METH_CONNECT, ==, stream->http_flags);
13552 
13553   rv = pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, conn_resnv,
13554                     ARRLEN(conn_resnv), mem);
13555   assert_ptrdiff(0, ==, rv);
13556 
13557   rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
13558                                  nghttp2_buf_len(&bufs.head->buf));
13559 
13560   assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(&bufs.head->buf), ==, rv);
13561 
13562   assert_true(NGHTTP2_HTTP_FLAG_METH_CONNECT & stream->http_flags);
13563   assert_int64(-1, ==, stream->content_length);
13564 
13565   /* content-length is ignored in 200 response to a CONNECT request */
13566   item = nghttp2_session_get_next_ob_item(session);
13567 
13568   assert_null(item);
13569 
13570   nghttp2_hd_deflate_free(&deflater);
13571   nghttp2_session_del(session);
13572   nghttp2_bufs_free(&bufs);
13573 }
13574 
test_nghttp2_http_push_promise(void)13575 void test_nghttp2_http_push_promise(void) {
13576   nghttp2_session *session;
13577   nghttp2_session_callbacks callbacks;
13578   nghttp2_hd_deflater deflater;
13579   nghttp2_mem *mem;
13580   nghttp2_bufs bufs;
13581   nghttp2_ssize rv;
13582   nghttp2_stream *stream;
13583   const nghttp2_nv bad_reqnv[] = {MAKE_NV(":method", "GET")};
13584   nghttp2_outbound_item *item;
13585 
13586   mem = nghttp2_mem_default();
13587   frame_pack_bufs_init(&bufs);
13588 
13589   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
13590   callbacks.send_callback2 = null_send_callback;
13591 
13592   /* good PUSH_PROMISE case */
13593   nghttp2_session_client_new(&session, &callbacks, NULL);
13594 
13595   nghttp2_hd_deflate_init(&deflater, mem);
13596 
13597   open_sent_stream2(session, 1, NGHTTP2_STREAM_OPENING);
13598 
13599   rv = pack_push_promise(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, 2,
13600                          reqnv, ARRLEN(reqnv), mem);
13601   assert_ptrdiff(0, ==, rv);
13602 
13603   rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
13604                                  nghttp2_buf_len(&bufs.head->buf));
13605 
13606   assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(&bufs.head->buf), ==, rv);
13607 
13608   assert_null(nghttp2_session_get_next_ob_item(session));
13609 
13610   stream = nghttp2_session_get_stream(session, 2);
13611   assert_not_null(stream);
13612 
13613   nghttp2_bufs_reset(&bufs);
13614 
13615   rv = pack_headers(&bufs, &deflater, 2, NGHTTP2_FLAG_END_HEADERS, resnv,
13616                     ARRLEN(resnv), mem);
13617 
13618   assert_ptrdiff(0, ==, rv);
13619 
13620   rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
13621                                  nghttp2_buf_len(&bufs.head->buf));
13622 
13623   assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(&bufs.head->buf), ==, rv);
13624 
13625   assert_null(nghttp2_session_get_next_ob_item(session));
13626 
13627   assert_int16(200, ==, stream->status_code);
13628 
13629   nghttp2_bufs_reset(&bufs);
13630 
13631   /* PUSH_PROMISE lacks mandatory header */
13632   rv = pack_push_promise(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, 4,
13633                          bad_reqnv, ARRLEN(bad_reqnv), mem);
13634 
13635   assert_ptrdiff(0, ==, rv);
13636 
13637   rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
13638                                  nghttp2_buf_len(&bufs.head->buf));
13639 
13640   assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(&bufs.head->buf), ==, rv);
13641 
13642   item = nghttp2_session_get_next_ob_item(session);
13643 
13644   assert_uint8(NGHTTP2_RST_STREAM, ==, item->frame.hd.type);
13645   assert_int32(4, ==, item->frame.hd.stream_id);
13646 
13647   nghttp2_bufs_reset(&bufs);
13648 
13649   nghttp2_hd_deflate_free(&deflater);
13650   nghttp2_session_del(session);
13651   nghttp2_bufs_free(&bufs);
13652 }
13653 
test_nghttp2_http_head_method_upgrade_workaround(void)13654 void test_nghttp2_http_head_method_upgrade_workaround(void) {
13655   nghttp2_session *session;
13656   nghttp2_session_callbacks callbacks;
13657   const nghttp2_nv cl_resnv[] = {MAKE_NV(":status", "200"),
13658                                  MAKE_NV("content-length", "1000000007")};
13659   nghttp2_bufs bufs;
13660   nghttp2_hd_deflater deflater;
13661   nghttp2_mem *mem;
13662   nghttp2_ssize rv;
13663   nghttp2_stream *stream;
13664 
13665   mem = nghttp2_mem_default();
13666   frame_pack_bufs_init(&bufs);
13667 
13668   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
13669   callbacks.send_callback2 = null_send_callback;
13670 
13671   nghttp2_session_client_new(&session, &callbacks, NULL);
13672 
13673   nghttp2_hd_deflate_init(&deflater, mem);
13674 
13675   nghttp2_session_upgrade(session, NULL, 0, NULL);
13676 
13677   rv = pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, cl_resnv,
13678                     ARRLEN(cl_resnv), mem);
13679 
13680   assert_ptrdiff(0, ==, rv);
13681 
13682   rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
13683                                  nghttp2_buf_len(&bufs.head->buf));
13684 
13685   assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(&bufs.head->buf), ==, rv);
13686 
13687   stream = nghttp2_session_get_stream(session, 1);
13688 
13689   assert_int64(-1, ==, stream->content_length);
13690 
13691   nghttp2_hd_deflate_free(&deflater);
13692   nghttp2_session_del(session);
13693   nghttp2_bufs_free(&bufs);
13694 }
13695 
test_nghttp2_http_no_rfc9113_leading_and_trailing_ws_validation(void)13696 void test_nghttp2_http_no_rfc9113_leading_and_trailing_ws_validation(void) {
13697   nghttp2_session *session;
13698   nghttp2_session_callbacks callbacks;
13699   nghttp2_hd_deflater deflater;
13700   nghttp2_mem *mem;
13701   nghttp2_bufs bufs;
13702   nghttp2_ssize rv;
13703   const nghttp2_nv ws_reqnv[] = {
13704     MAKE_NV(":path", "/"),
13705     MAKE_NV(":method", "GET"),
13706     MAKE_NV(":authority", "localhost"),
13707     MAKE_NV(":scheme", "https"),
13708     MAKE_NV("foo", "bar "),
13709   };
13710   nghttp2_outbound_item *item;
13711   nghttp2_option *option;
13712 
13713   mem = nghttp2_mem_default();
13714   frame_pack_bufs_init(&bufs);
13715 
13716   memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
13717   callbacks.send_callback2 = null_send_callback;
13718 
13719   /* By default, the leading and trailing white spaces validation is
13720      enabled as per RFC 9113. */
13721   nghttp2_session_server_new(&session, &callbacks, NULL);
13722 
13723   nghttp2_hd_deflate_init(&deflater, mem);
13724 
13725   rv = pack_headers(&bufs, &deflater, 1,
13726                     NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM,
13727                     ws_reqnv, ARRLEN(ws_reqnv), mem);
13728 
13729   assert_ptrdiff(0, ==, rv);
13730 
13731   rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
13732                                  nghttp2_buf_len(&bufs.head->buf));
13733 
13734   assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(&bufs.head->buf), ==, rv);
13735 
13736   item = nghttp2_session_get_next_ob_item(session);
13737 
13738   assert_uint8(NGHTTP2_RST_STREAM, ==, item->frame.hd.type);
13739   assert_int(0, ==, nghttp2_session_send(session));
13740 
13741   nghttp2_bufs_reset(&bufs);
13742   nghttp2_hd_deflate_free(&deflater);
13743   nghttp2_session_del(session);
13744 
13745   /* Turn off the validation */
13746   nghttp2_option_new(&option);
13747   nghttp2_option_set_no_rfc9113_leading_and_trailing_ws_validation(option, 1);
13748 
13749   nghttp2_session_server_new2(&session, &callbacks, NULL, option);
13750 
13751   nghttp2_hd_deflate_init(&deflater, mem);
13752 
13753   rv = pack_headers(&bufs, &deflater, 1,
13754                     NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM,
13755                     ws_reqnv, ARRLEN(ws_reqnv), mem);
13756 
13757   assert_ptrdiff(0, ==, rv);
13758 
13759   rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
13760                                  nghttp2_buf_len(&bufs.head->buf));
13761 
13762   assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(&bufs.head->buf), ==, rv);
13763 
13764   item = nghttp2_session_get_next_ob_item(session);
13765 
13766   assert_null(item);
13767 
13768   nghttp2_bufs_reset(&bufs);
13769   nghttp2_hd_deflate_free(&deflater);
13770   nghttp2_session_del(session);
13771   nghttp2_option_del(option);
13772 
13773   nghttp2_bufs_free(&bufs);
13774 }
13775