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