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