1 /*
2 * nghttp2 - HTTP/2 C Library
3 *
4 * Copyright (c) 2013 Tatsuhiro Tsujikawa
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining
7 * a copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sublicense, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be
15 * included in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 */
25 #include "nghttp2_session_test.h"
26
27 #include <stdio.h>
28 #include <assert.h>
29
30 #include "munit.h"
31
32 #include "nghttp2_session.h"
33 #include "nghttp2_stream.h"
34 #include "nghttp2_net.h"
35 #include "nghttp2_helper.h"
36 #include "nghttp2_test_helper.h"
37 #include "nghttp2_assertion.h"
38 #include "nghttp2_priority_spec.h"
39 #include "nghttp2_extpri.h"
40
41 static const MunitTest tests[] = {
42 munit_void_test(test_nghttp2_session_recv),
43 munit_void_test(test_nghttp2_session_recv_invalid_stream_id),
44 munit_void_test(test_nghttp2_session_recv_invalid_frame),
45 munit_void_test(test_nghttp2_session_recv_eof),
46 munit_void_test(test_nghttp2_session_recv_data),
47 munit_void_test(test_nghttp2_session_recv_data_no_auto_flow_control),
48 munit_void_test(test_nghttp2_session_recv_continuation),
49 munit_void_test(test_nghttp2_session_recv_headers_with_priority),
50 munit_void_test(test_nghttp2_session_recv_headers_with_padding),
51 munit_void_test(test_nghttp2_session_recv_headers_early_response),
52 munit_void_test(test_nghttp2_session_recv_headers_for_closed_stream),
53 munit_void_test(test_nghttp2_session_recv_headers_with_extpri),
54 munit_void_test(test_nghttp2_session_server_recv_push_response),
55 munit_void_test(test_nghttp2_session_recv_premature_headers),
56 munit_void_test(test_nghttp2_session_recv_unknown_frame),
57 munit_void_test(test_nghttp2_session_recv_unexpected_continuation),
58 munit_void_test(test_nghttp2_session_recv_settings_header_table_size),
59 munit_void_test(test_nghttp2_session_recv_too_large_frame_length),
60 munit_void_test(test_nghttp2_session_recv_extension),
61 munit_void_test(test_nghttp2_session_recv_altsvc),
62 munit_void_test(test_nghttp2_session_recv_origin),
63 munit_void_test(test_nghttp2_session_recv_priority_update),
64 munit_void_test(test_nghttp2_session_continue),
65 munit_void_test(test_nghttp2_session_add_frame),
66 munit_void_test(test_nghttp2_session_on_request_headers_received),
67 munit_void_test(test_nghttp2_session_on_response_headers_received),
68 munit_void_test(test_nghttp2_session_on_headers_received),
69 munit_void_test(test_nghttp2_session_on_push_response_headers_received),
70 munit_void_test(test_nghttp2_session_on_priority_received),
71 munit_void_test(test_nghttp2_session_on_rst_stream_received),
72 munit_void_test(test_nghttp2_session_on_settings_received),
73 munit_void_test(test_nghttp2_session_on_push_promise_received),
74 munit_void_test(test_nghttp2_session_on_ping_received),
75 munit_void_test(test_nghttp2_session_on_goaway_received),
76 munit_void_test(test_nghttp2_session_on_window_update_received),
77 munit_void_test(test_nghttp2_session_on_data_received),
78 munit_void_test(test_nghttp2_session_on_data_received_fail_fast),
79 munit_void_test(test_nghttp2_session_on_altsvc_received),
80 munit_void_test(test_nghttp2_session_send_headers_start_stream),
81 munit_void_test(test_nghttp2_session_send_headers_reply),
82 munit_void_test(test_nghttp2_session_send_headers_frame_size_error),
83 munit_void_test(test_nghttp2_session_send_headers_push_reply),
84 munit_void_test(test_nghttp2_session_send_rst_stream),
85 munit_void_test(test_nghttp2_session_send_push_promise),
86 munit_void_test(test_nghttp2_session_is_my_stream_id),
87 munit_void_test(test_nghttp2_session_upgrade2),
88 munit_void_test(test_nghttp2_session_reprioritize_stream),
89 munit_void_test(
90 test_nghttp2_session_reprioritize_stream_with_idle_stream_dep),
91 munit_void_test(test_nghttp2_submit_data),
92 munit_void_test(test_nghttp2_submit_data_read_length_too_large),
93 munit_void_test(test_nghttp2_submit_data_read_length_smallest),
94 munit_void_test(test_nghttp2_submit_data_twice),
95 munit_void_test(test_nghttp2_submit_request_with_data),
96 munit_void_test(test_nghttp2_submit_request_without_data),
97 munit_void_test(test_nghttp2_submit_response_with_data),
98 munit_void_test(test_nghttp2_submit_response_without_data),
99 munit_void_test(test_nghttp2_submit_response_push_response),
100 munit_void_test(test_nghttp2_submit_trailer),
101 munit_void_test(test_nghttp2_submit_headers_start_stream),
102 munit_void_test(test_nghttp2_submit_headers_reply),
103 munit_void_test(test_nghttp2_submit_headers_push_reply),
104 munit_void_test(test_nghttp2_submit_headers),
105 munit_void_test(test_nghttp2_submit_headers_continuation),
106 munit_void_test(test_nghttp2_submit_headers_continuation_extra_large),
107 munit_void_test(test_nghttp2_submit_priority),
108 munit_void_test(test_nghttp2_submit_settings),
109 munit_void_test(test_nghttp2_submit_settings_update_local_window_size),
110 munit_void_test(test_nghttp2_submit_settings_multiple_times),
111 munit_void_test(test_nghttp2_submit_push_promise),
112 munit_void_test(test_nghttp2_submit_window_update),
113 munit_void_test(test_nghttp2_submit_window_update_local_window_size),
114 munit_void_test(test_nghttp2_submit_shutdown_notice),
115 munit_void_test(test_nghttp2_submit_invalid_nv),
116 munit_void_test(test_nghttp2_submit_extension),
117 munit_void_test(test_nghttp2_submit_altsvc),
118 munit_void_test(test_nghttp2_submit_origin),
119 munit_void_test(test_nghttp2_submit_priority_update),
120 munit_void_test(test_nghttp2_submit_rst_stream),
121 munit_void_test(test_nghttp2_session_open_stream),
122 munit_void_test(test_nghttp2_session_open_stream_with_idle_stream_dep),
123 munit_void_test(test_nghttp2_session_get_next_ob_item),
124 munit_void_test(test_nghttp2_session_pop_next_ob_item),
125 munit_void_test(test_nghttp2_session_reply_fail),
126 munit_void_test(test_nghttp2_session_max_concurrent_streams),
127 munit_void_test(test_nghttp2_session_stop_data_with_rst_stream),
128 munit_void_test(test_nghttp2_session_defer_data),
129 munit_void_test(test_nghttp2_session_flow_control),
130 munit_void_test(test_nghttp2_session_flow_control_data_recv),
131 munit_void_test(test_nghttp2_session_flow_control_data_with_padding_recv),
132 munit_void_test(test_nghttp2_session_data_read_temporal_failure),
133 munit_void_test(test_nghttp2_session_on_stream_close),
134 munit_void_test(test_nghttp2_session_on_ctrl_not_send),
135 munit_void_test(test_nghttp2_session_get_outbound_queue_size),
136 munit_void_test(test_nghttp2_session_get_effective_local_window_size),
137 munit_void_test(test_nghttp2_session_set_option),
138 munit_void_test(test_nghttp2_session_data_backoff_by_high_pri_frame),
139 munit_void_test(test_nghttp2_session_pack_data_with_padding),
140 munit_void_test(test_nghttp2_session_pack_headers_with_padding),
141 munit_void_test(test_nghttp2_pack_settings_payload),
142 munit_void_test(test_nghttp2_session_stream_dep_add),
143 munit_void_test(test_nghttp2_session_stream_dep_remove),
144 munit_void_test(test_nghttp2_session_stream_dep_add_subtree),
145 munit_void_test(test_nghttp2_session_stream_dep_remove_subtree),
146 munit_void_test(
147 test_nghttp2_session_stream_dep_all_your_stream_are_belong_to_us),
148 munit_void_test(test_nghttp2_session_stream_attach_item),
149 munit_void_test(test_nghttp2_session_stream_attach_item_subtree),
150 munit_void_test(test_nghttp2_session_stream_get_state),
151 munit_void_test(test_nghttp2_session_stream_get_something),
152 munit_void_test(test_nghttp2_session_find_stream),
153 munit_void_test(test_nghttp2_session_keep_closed_stream),
154 munit_void_test(test_nghttp2_session_keep_idle_stream),
155 munit_void_test(test_nghttp2_session_detach_idle_stream),
156 munit_void_test(test_nghttp2_session_large_dep_tree),
157 munit_void_test(test_nghttp2_session_graceful_shutdown),
158 munit_void_test(test_nghttp2_session_on_header_temporal_failure),
159 munit_void_test(test_nghttp2_session_recv_client_magic),
160 munit_void_test(test_nghttp2_session_delete_data_item),
161 munit_void_test(test_nghttp2_session_open_idle_stream),
162 munit_void_test(test_nghttp2_session_cancel_reserved_remote),
163 munit_void_test(test_nghttp2_session_reset_pending_headers),
164 munit_void_test(test_nghttp2_session_send_data_callback),
165 munit_void_test(test_nghttp2_session_on_begin_headers_temporal_failure),
166 munit_void_test(test_nghttp2_session_defer_then_close),
167 munit_void_test(test_nghttp2_session_detach_item_from_closed_stream),
168 munit_void_test(test_nghttp2_session_flooding),
169 munit_void_test(test_nghttp2_session_change_stream_priority),
170 munit_void_test(test_nghttp2_session_change_extpri_stream_priority),
171 munit_void_test(test_nghttp2_session_create_idle_stream),
172 munit_void_test(test_nghttp2_session_repeated_priority_change),
173 munit_void_test(test_nghttp2_session_repeated_priority_submission),
174 munit_void_test(test_nghttp2_session_set_local_window_size),
175 munit_void_test(test_nghttp2_session_cancel_from_before_frame_send),
176 munit_void_test(test_nghttp2_session_too_many_settings),
177 munit_void_test(test_nghttp2_session_removed_closed_stream),
178 munit_void_test(test_nghttp2_session_pause_data),
179 munit_void_test(test_nghttp2_session_no_closed_streams),
180 munit_void_test(test_nghttp2_session_set_stream_user_data),
181 munit_void_test(test_nghttp2_session_no_rfc7540_priorities),
182 munit_void_test(test_nghttp2_session_server_fallback_rfc7540_priorities),
183 munit_void_test(test_nghttp2_session_stream_reset_ratelim),
184 munit_void_test(test_nghttp2_http_mandatory_headers),
185 munit_void_test(test_nghttp2_http_content_length),
186 munit_void_test(test_nghttp2_http_content_length_mismatch),
187 munit_void_test(test_nghttp2_http_non_final_response),
188 munit_void_test(test_nghttp2_http_trailer_headers),
189 munit_void_test(test_nghttp2_http_ignore_regular_header),
190 munit_void_test(test_nghttp2_http_ignore_content_length),
191 munit_void_test(test_nghttp2_http_record_request_method),
192 munit_void_test(test_nghttp2_http_push_promise),
193 munit_void_test(test_nghttp2_http_head_method_upgrade_workaround),
194 munit_void_test(
195 test_nghttp2_http_no_rfc9113_leading_and_trailing_ws_validation),
196 munit_test_end(),
197 };
198
199 const MunitSuite session_suite = {
200 "/session", tests, NULL, 1, MUNIT_SUITE_OPTION_NONE,
201 };
202
203 typedef struct {
204 uint8_t buf[65535];
205 size_t length;
206 } accumulator;
207
208 typedef struct {
209 uint8_t data[8192];
210 uint8_t *datamark;
211 uint8_t *datalimit;
212 size_t feedseq[8192];
213 size_t seqidx;
214 } scripted_data_feed;
215
216 typedef struct {
217 accumulator *acc;
218 scripted_data_feed *df;
219 int frame_recv_cb_called, invalid_frame_recv_cb_called;
220 uint8_t recv_frame_type;
221 nghttp2_frame_hd recv_frame_hd;
222 int frame_send_cb_called;
223 uint8_t sent_frame_type;
224 int before_frame_send_cb_called;
225 int frame_not_send_cb_called;
226 uint8_t not_sent_frame_type;
227 int not_sent_error;
228 int stream_close_cb_called;
229 uint32_t stream_close_error_code;
230 size_t data_source_length;
231 int32_t stream_id;
232 size_t block_count;
233 int data_chunk_recv_cb_called;
234 const nghttp2_frame *frame;
235 size_t fixed_sendlen;
236 int header_cb_called;
237 int invalid_header_cb_called;
238 int begin_headers_cb_called;
239 nghttp2_nv nv;
240 size_t data_chunk_len;
241 size_t padlen;
242 int begin_frame_cb_called;
243 nghttp2_buf scratchbuf;
244 size_t data_source_read_cb_paused;
245 } my_user_data;
246
247 static const nghttp2_nv reqnv[] = {
248 MAKE_NV(":method", "GET"),
249 MAKE_NV(":path", "/"),
250 MAKE_NV(":scheme", "https"),
251 MAKE_NV(":authority", "localhost"),
252 };
253
254 static const nghttp2_nv resnv[] = {
255 MAKE_NV(":status", "200"),
256 };
257
258 static const nghttp2_nv trailernv[] = {
259 // from http://tools.ietf.org/html/rfc6249#section-7
260 MAKE_NV("digest", "SHA-256="
261 "MWVkMWQxYTRiMzk5MDQ0MzI3NGU5NDEyZTk5OWY1ZGFmNzgyZTJlODYz"
262 "YjRjYzFhOTlmNTQwYzI2M2QwM2U2MQ=="),
263 };
264
scripted_data_feed_init2(scripted_data_feed * df,nghttp2_bufs * bufs)265 static void scripted_data_feed_init2(scripted_data_feed *df,
266 nghttp2_bufs *bufs) {
267 nghttp2_buf_chain *ci;
268 nghttp2_buf *buf;
269 uint8_t *ptr;
270 size_t len;
271
272 memset(df, 0, sizeof(scripted_data_feed));
273 ptr = df->data;
274 len = 0;
275
276 for (ci = bufs->head; ci; ci = ci->next) {
277 buf = &ci->buf;
278 ptr = nghttp2_cpymem(ptr, buf->pos, nghttp2_buf_len(buf));
279 len += nghttp2_buf_len(buf);
280 }
281
282 df->datamark = df->data;
283 df->datalimit = df->data + len;
284 df->feedseq[0] = len;
285 }
286
null_send_callback(nghttp2_session * session,const uint8_t * data,size_t len,int flags,void * user_data)287 static nghttp2_ssize null_send_callback(nghttp2_session *session,
288 const uint8_t *data, size_t len,
289 int flags, void *user_data) {
290 (void)session;
291 (void)data;
292 (void)flags;
293 (void)user_data;
294
295 return (nghttp2_ssize)len;
296 }
297
fail_send_callback(nghttp2_session * session,const uint8_t * data,size_t len,int flags,void * user_data)298 static nghttp2_ssize fail_send_callback(nghttp2_session *session,
299 const uint8_t *data, size_t len,
300 int flags, void *user_data) {
301 (void)session;
302 (void)data;
303 (void)len;
304 (void)flags;
305 (void)user_data;
306
307 return NGHTTP2_ERR_CALLBACK_FAILURE;
308 }
309
fixed_bytes_send_callback(nghttp2_session * session,const uint8_t * data,size_t len,int flags,void * user_data)310 static nghttp2_ssize fixed_bytes_send_callback(nghttp2_session *session,
311 const uint8_t *data, size_t len,
312 int flags, void *user_data) {
313 size_t fixed_sendlen = ((my_user_data *)user_data)->fixed_sendlen;
314 (void)session;
315 (void)data;
316 (void)flags;
317
318 return (nghttp2_ssize)(fixed_sendlen < len ? fixed_sendlen : len);
319 }
320
scripted_recv_callback(nghttp2_session * session,uint8_t * data,size_t len,int flags,void * user_data)321 static nghttp2_ssize scripted_recv_callback(nghttp2_session *session,
322 uint8_t *data, size_t len,
323 int flags, void *user_data) {
324 scripted_data_feed *df = ((my_user_data *)user_data)->df;
325 size_t wlen = df->feedseq[df->seqidx] > len ? len : df->feedseq[df->seqidx];
326 (void)session;
327 (void)flags;
328
329 memcpy(data, df->datamark, wlen);
330 df->datamark += wlen;
331 df->feedseq[df->seqidx] -= wlen;
332 if (df->feedseq[df->seqidx] == 0) {
333 ++df->seqidx;
334 }
335 return (nghttp2_ssize)wlen;
336 }
337
eof_recv_callback(nghttp2_session * session,uint8_t * data,size_t len,int flags,void * user_data)338 static nghttp2_ssize eof_recv_callback(nghttp2_session *session, uint8_t *data,
339 size_t len, int flags, void *user_data) {
340 (void)session;
341 (void)data;
342 (void)len;
343 (void)flags;
344 (void)user_data;
345
346 return NGHTTP2_ERR_EOF;
347 }
348
accumulator_send_callback(nghttp2_session * session,const uint8_t * buf,size_t len,int flags,void * user_data)349 static nghttp2_ssize accumulator_send_callback(nghttp2_session *session,
350 const uint8_t *buf, size_t len,
351 int flags, void *user_data) {
352 accumulator *acc = ((my_user_data *)user_data)->acc;
353 (void)session;
354 (void)flags;
355
356 assert(acc->length + len < sizeof(acc->buf));
357 memcpy(acc->buf + acc->length, buf, len);
358 acc->length += len;
359 return (nghttp2_ssize)len;
360 }
361
on_begin_frame_callback(nghttp2_session * session,const nghttp2_frame_hd * hd,void * user_data)362 static int on_begin_frame_callback(nghttp2_session *session,
363 const nghttp2_frame_hd *hd,
364 void *user_data) {
365 my_user_data *ud = (my_user_data *)user_data;
366 (void)session;
367 (void)hd;
368
369 ++ud->begin_frame_cb_called;
370 return 0;
371 }
372
on_frame_recv_callback(nghttp2_session * session,const nghttp2_frame * frame,void * user_data)373 static int on_frame_recv_callback(nghttp2_session *session,
374 const nghttp2_frame *frame, void *user_data) {
375 my_user_data *ud = (my_user_data *)user_data;
376 (void)session;
377
378 ++ud->frame_recv_cb_called;
379 ud->recv_frame_type = frame->hd.type;
380 ud->recv_frame_hd = frame->hd;
381
382 return 0;
383 }
384
on_invalid_frame_recv_callback(nghttp2_session * session,const nghttp2_frame * frame,int lib_error_code,void * user_data)385 static int on_invalid_frame_recv_callback(nghttp2_session *session,
386 const nghttp2_frame *frame,
387 int lib_error_code, void *user_data) {
388 my_user_data *ud = (my_user_data *)user_data;
389 (void)session;
390 (void)frame;
391 (void)lib_error_code;
392
393 ++ud->invalid_frame_recv_cb_called;
394 return 0;
395 }
396
on_frame_send_callback(nghttp2_session * session,const nghttp2_frame * frame,void * user_data)397 static int on_frame_send_callback(nghttp2_session *session,
398 const nghttp2_frame *frame, void *user_data) {
399 my_user_data *ud = (my_user_data *)user_data;
400 (void)session;
401
402 ++ud->frame_send_cb_called;
403 ud->sent_frame_type = frame->hd.type;
404 return 0;
405 }
406
on_frame_not_send_callback(nghttp2_session * session,const nghttp2_frame * frame,int lib_error,void * user_data)407 static int on_frame_not_send_callback(nghttp2_session *session,
408 const nghttp2_frame *frame, int lib_error,
409 void *user_data) {
410 my_user_data *ud = (my_user_data *)user_data;
411 (void)session;
412
413 ++ud->frame_not_send_cb_called;
414 ud->not_sent_frame_type = frame->hd.type;
415 ud->not_sent_error = lib_error;
416 return 0;
417 }
418
cancel_before_frame_send_callback(nghttp2_session * session,const nghttp2_frame * frame,void * user_data)419 static int cancel_before_frame_send_callback(nghttp2_session *session,
420 const nghttp2_frame *frame,
421 void *user_data) {
422 my_user_data *ud = (my_user_data *)user_data;
423 (void)session;
424 (void)frame;
425
426 ++ud->before_frame_send_cb_called;
427 return NGHTTP2_ERR_CANCEL;
428 }
429
on_data_chunk_recv_callback(nghttp2_session * session,uint8_t flags,int32_t stream_id,const uint8_t * data,size_t len,void * user_data)430 static int on_data_chunk_recv_callback(nghttp2_session *session, uint8_t flags,
431 int32_t stream_id, const uint8_t *data,
432 size_t len, void *user_data) {
433 my_user_data *ud = (my_user_data *)user_data;
434 (void)session;
435 (void)flags;
436 (void)stream_id;
437 (void)data;
438
439 ++ud->data_chunk_recv_cb_called;
440 ud->data_chunk_len = len;
441 return 0;
442 }
443
pause_on_data_chunk_recv_callback(nghttp2_session * session,uint8_t flags,int32_t stream_id,const uint8_t * data,size_t len,void * user_data)444 static int pause_on_data_chunk_recv_callback(nghttp2_session *session,
445 uint8_t flags, int32_t stream_id,
446 const uint8_t *data, size_t len,
447 void *user_data) {
448 my_user_data *ud = (my_user_data *)user_data;
449 (void)session;
450 (void)flags;
451 (void)stream_id;
452 (void)data;
453 (void)len;
454
455 ++ud->data_chunk_recv_cb_called;
456 return NGHTTP2_ERR_PAUSE;
457 }
458
select_padding_callback(nghttp2_session * session,const nghttp2_frame * frame,size_t max_payloadlen,void * user_data)459 static nghttp2_ssize select_padding_callback(nghttp2_session *session,
460 const nghttp2_frame *frame,
461 size_t max_payloadlen,
462 void *user_data) {
463 my_user_data *ud = (my_user_data *)user_data;
464 (void)session;
465
466 return (nghttp2_ssize)nghttp2_min_size(max_payloadlen,
467 frame->hd.length + ud->padlen);
468 }
469
too_large_data_source_length_callback(nghttp2_session * session,uint8_t frame_type,int32_t stream_id,int32_t session_remote_window_size,int32_t stream_remote_window_size,uint32_t remote_max_frame_size,void * user_data)470 static nghttp2_ssize too_large_data_source_length_callback(
471 nghttp2_session *session, uint8_t frame_type, int32_t stream_id,
472 int32_t session_remote_window_size, int32_t stream_remote_window_size,
473 uint32_t remote_max_frame_size, void *user_data) {
474 (void)session;
475 (void)frame_type;
476 (void)stream_id;
477 (void)session_remote_window_size;
478 (void)stream_remote_window_size;
479 (void)remote_max_frame_size;
480 (void)user_data;
481
482 return NGHTTP2_MAX_FRAME_SIZE_MAX + 1;
483 }
484
smallest_length_data_source_length_callback(nghttp2_session * session,uint8_t frame_type,int32_t stream_id,int32_t session_remote_window_size,int32_t stream_remote_window_size,uint32_t remote_max_frame_size,void * user_data)485 static nghttp2_ssize smallest_length_data_source_length_callback(
486 nghttp2_session *session, uint8_t frame_type, int32_t stream_id,
487 int32_t session_remote_window_size, int32_t stream_remote_window_size,
488 uint32_t remote_max_frame_size, void *user_data) {
489 (void)session;
490 (void)frame_type;
491 (void)stream_id;
492 (void)session_remote_window_size;
493 (void)stream_remote_window_size;
494 (void)remote_max_frame_size;
495 (void)user_data;
496
497 return 1;
498 }
499
fixed_length_data_source_read_callback(nghttp2_session * session,int32_t stream_id,uint8_t * buf,size_t len,uint32_t * data_flags,nghttp2_data_source * source,void * user_data)500 static nghttp2_ssize fixed_length_data_source_read_callback(
501 nghttp2_session *session, int32_t stream_id, uint8_t *buf, size_t len,
502 uint32_t *data_flags, nghttp2_data_source *source, void *user_data) {
503 my_user_data *ud = (my_user_data *)user_data;
504 size_t wlen;
505 (void)session;
506 (void)stream_id;
507 (void)buf;
508 (void)source;
509
510 if (len < ud->data_source_length) {
511 wlen = len;
512 } else {
513 wlen = ud->data_source_length;
514 }
515 ud->data_source_length -= wlen;
516 if (ud->data_source_length == 0) {
517 *data_flags |= NGHTTP2_DATA_FLAG_EOF;
518 }
519 return (nghttp2_ssize)wlen;
520 }
521
temporal_failure_data_source_read_callback(nghttp2_session * session,int32_t stream_id,uint8_t * buf,size_t len,uint32_t * data_flags,nghttp2_data_source * source,void * user_data)522 static nghttp2_ssize temporal_failure_data_source_read_callback(
523 nghttp2_session *session, int32_t stream_id, uint8_t *buf, size_t len,
524 uint32_t *data_flags, nghttp2_data_source *source, void *user_data) {
525 (void)session;
526 (void)stream_id;
527 (void)buf;
528 (void)len;
529 (void)data_flags;
530 (void)source;
531 (void)user_data;
532
533 return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
534 }
535
536 static nghttp2_ssize
fail_data_source_read_callback(nghttp2_session * session,int32_t stream_id,uint8_t * buf,size_t len,uint32_t * data_flags,nghttp2_data_source * source,void * user_data)537 fail_data_source_read_callback(nghttp2_session *session, int32_t stream_id,
538 uint8_t *buf, size_t len, uint32_t *data_flags,
539 nghttp2_data_source *source, void *user_data) {
540 (void)session;
541 (void)stream_id;
542 (void)buf;
543 (void)len;
544 (void)data_flags;
545 (void)source;
546 (void)user_data;
547
548 return NGHTTP2_ERR_CALLBACK_FAILURE;
549 }
550
no_end_stream_data_source_read_callback(nghttp2_session * session,int32_t stream_id,uint8_t * buf,size_t len,uint32_t * data_flags,nghttp2_data_source * source,void * user_data)551 static nghttp2_ssize no_end_stream_data_source_read_callback(
552 nghttp2_session *session, int32_t stream_id, uint8_t *buf, size_t len,
553 uint32_t *data_flags, nghttp2_data_source *source, void *user_data) {
554 (void)session;
555 (void)stream_id;
556 (void)buf;
557 (void)len;
558 (void)source;
559 (void)user_data;
560
561 *data_flags |= NGHTTP2_DATA_FLAG_EOF | NGHTTP2_DATA_FLAG_NO_END_STREAM;
562 return 0;
563 }
564
no_copy_data_source_read_callback(nghttp2_session * session,int32_t stream_id,uint8_t * buf,size_t len,uint32_t * data_flags,nghttp2_data_source * source,void * user_data)565 static nghttp2_ssize no_copy_data_source_read_callback(
566 nghttp2_session *session, int32_t stream_id, uint8_t *buf, size_t len,
567 uint32_t *data_flags, nghttp2_data_source *source, void *user_data) {
568 my_user_data *ud = (my_user_data *)user_data;
569 size_t wlen;
570 (void)session;
571 (void)stream_id;
572 (void)buf;
573 (void)source;
574
575 if (len < ud->data_source_length) {
576 wlen = len;
577 } else {
578 wlen = ud->data_source_length;
579 }
580
581 ud->data_source_length -= wlen;
582
583 *data_flags |= NGHTTP2_DATA_FLAG_NO_COPY;
584
585 if (ud->data_source_length == 0) {
586 *data_flags |= NGHTTP2_DATA_FLAG_EOF;
587 }
588 return (nghttp2_ssize)wlen;
589 }
590
send_data_callback(nghttp2_session * session,nghttp2_frame * frame,const uint8_t * framehd,size_t length,nghttp2_data_source * source,void * user_data)591 static int send_data_callback(nghttp2_session *session, nghttp2_frame *frame,
592 const uint8_t *framehd, size_t length,
593 nghttp2_data_source *source, void *user_data) {
594 accumulator *acc = ((my_user_data *)user_data)->acc;
595 (void)session;
596 (void)source;
597
598 memcpy(acc->buf + acc->length, framehd, NGHTTP2_FRAME_HDLEN);
599 acc->length += NGHTTP2_FRAME_HDLEN;
600
601 if (frame->data.padlen) {
602 *(acc->buf + acc->length++) = (uint8_t)(frame->data.padlen - 1);
603 }
604
605 acc->length += length;
606
607 if (frame->data.padlen) {
608 acc->length += frame->data.padlen - 1;
609 }
610
611 return 0;
612 }
613
block_count_send_callback(nghttp2_session * session,const uint8_t * data,size_t len,int flags,void * user_data)614 static nghttp2_ssize block_count_send_callback(nghttp2_session *session,
615 const uint8_t *data, size_t len,
616 int flags, void *user_data) {
617 my_user_data *ud = (my_user_data *)user_data;
618 (void)session;
619 (void)data;
620 (void)flags;
621
622 if (ud->block_count == 0) {
623 return NGHTTP2_ERR_WOULDBLOCK;
624 }
625
626 --ud->block_count;
627 return (nghttp2_ssize)len;
628 }
629
on_header_callback(nghttp2_session * session,const nghttp2_frame * frame,const uint8_t * name,size_t namelen,const uint8_t * value,size_t valuelen,uint8_t flags,void * user_data)630 static int on_header_callback(nghttp2_session *session,
631 const nghttp2_frame *frame, const uint8_t *name,
632 size_t namelen, const uint8_t *value,
633 size_t valuelen, uint8_t flags, void *user_data) {
634 my_user_data *ud = (my_user_data *)user_data;
635 (void)session;
636 (void)flags;
637
638 ++ud->header_cb_called;
639 ud->nv.name = (uint8_t *)name;
640 ud->nv.namelen = namelen;
641 ud->nv.value = (uint8_t *)value;
642 ud->nv.valuelen = valuelen;
643
644 ud->frame = frame;
645 return 0;
646 }
647
pause_on_header_callback(nghttp2_session * session,const nghttp2_frame * frame,const uint8_t * name,size_t namelen,const uint8_t * value,size_t valuelen,uint8_t flags,void * user_data)648 static int pause_on_header_callback(nghttp2_session *session,
649 const nghttp2_frame *frame,
650 const uint8_t *name, size_t namelen,
651 const uint8_t *value, size_t valuelen,
652 uint8_t flags, void *user_data) {
653 on_header_callback(session, frame, name, namelen, value, valuelen, flags,
654 user_data);
655 return NGHTTP2_ERR_PAUSE;
656 }
657
temporal_failure_on_header_callback(nghttp2_session * session,const nghttp2_frame * frame,const uint8_t * name,size_t namelen,const uint8_t * value,size_t valuelen,uint8_t flags,void * user_data)658 static int temporal_failure_on_header_callback(
659 nghttp2_session *session, const nghttp2_frame *frame, const uint8_t *name,
660 size_t namelen, const uint8_t *value, size_t valuelen, uint8_t flags,
661 void *user_data) {
662 on_header_callback(session, frame, name, namelen, value, valuelen, flags,
663 user_data);
664 return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
665 }
666
on_invalid_header_callback(nghttp2_session * session,const nghttp2_frame * frame,const uint8_t * name,size_t namelen,const uint8_t * value,size_t valuelen,uint8_t flags,void * user_data)667 static int on_invalid_header_callback(nghttp2_session *session,
668 const nghttp2_frame *frame,
669 const uint8_t *name, size_t namelen,
670 const uint8_t *value, size_t valuelen,
671 uint8_t flags, void *user_data) {
672 my_user_data *ud = (my_user_data *)user_data;
673 (void)session;
674 (void)flags;
675
676 ++ud->invalid_header_cb_called;
677 ud->nv.name = (uint8_t *)name;
678 ud->nv.namelen = namelen;
679 ud->nv.value = (uint8_t *)value;
680 ud->nv.valuelen = valuelen;
681
682 ud->frame = frame;
683 return 0;
684 }
685
pause_on_invalid_header_callback(nghttp2_session * session,const nghttp2_frame * frame,const uint8_t * name,size_t namelen,const uint8_t * value,size_t valuelen,uint8_t flags,void * user_data)686 static int pause_on_invalid_header_callback(nghttp2_session *session,
687 const nghttp2_frame *frame,
688 const uint8_t *name, size_t namelen,
689 const uint8_t *value,
690 size_t valuelen, uint8_t flags,
691 void *user_data) {
692 on_invalid_header_callback(session, frame, name, namelen, value, valuelen,
693 flags, user_data);
694 return NGHTTP2_ERR_PAUSE;
695 }
696
reset_on_invalid_header_callback(nghttp2_session * session,const nghttp2_frame * frame,const uint8_t * name,size_t namelen,const uint8_t * value,size_t valuelen,uint8_t flags,void * user_data)697 static int reset_on_invalid_header_callback(nghttp2_session *session,
698 const nghttp2_frame *frame,
699 const uint8_t *name, size_t namelen,
700 const uint8_t *value,
701 size_t valuelen, uint8_t flags,
702 void *user_data) {
703 on_invalid_header_callback(session, frame, name, namelen, value, valuelen,
704 flags, user_data);
705 return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
706 }
707
on_begin_headers_callback(nghttp2_session * session,const nghttp2_frame * frame,void * user_data)708 static int on_begin_headers_callback(nghttp2_session *session,
709 const nghttp2_frame *frame,
710 void *user_data) {
711 my_user_data *ud = (my_user_data *)user_data;
712 (void)session;
713 (void)frame;
714
715 ++ud->begin_headers_cb_called;
716 return 0;
717 }
718
temporal_failure_on_begin_headers_callback(nghttp2_session * session,const nghttp2_frame * frame,void * user_data)719 static int temporal_failure_on_begin_headers_callback(
720 nghttp2_session *session, const nghttp2_frame *frame, void *user_data) {
721 on_begin_headers_callback(session, frame, user_data);
722 return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
723 }
724
725 static nghttp2_ssize
defer_data_source_read_callback(nghttp2_session * session,int32_t stream_id,uint8_t * buf,size_t len,uint32_t * data_flags,nghttp2_data_source * source,void * user_data)726 defer_data_source_read_callback(nghttp2_session *session, int32_t stream_id,
727 uint8_t *buf, size_t len, uint32_t *data_flags,
728 nghttp2_data_source *source, void *user_data) {
729 (void)session;
730 (void)stream_id;
731 (void)buf;
732 (void)len;
733 (void)data_flags;
734 (void)source;
735 (void)user_data;
736
737 return NGHTTP2_ERR_DEFERRED;
738 }
739
on_stream_close_callback(nghttp2_session * session,int32_t stream_id,uint32_t error_code,void * user_data)740 static int on_stream_close_callback(nghttp2_session *session, int32_t stream_id,
741 uint32_t error_code, void *user_data) {
742 my_user_data *my_data = (my_user_data *)user_data;
743 (void)session;
744 (void)stream_id;
745 (void)error_code;
746
747 ++my_data->stream_close_cb_called;
748 my_data->stream_close_error_code = error_code;
749
750 return 0;
751 }
752
fatal_error_on_stream_close_callback(nghttp2_session * session,int32_t stream_id,uint32_t error_code,void * user_data)753 static int fatal_error_on_stream_close_callback(nghttp2_session *session,
754 int32_t stream_id,
755 uint32_t error_code,
756 void *user_data) {
757 on_stream_close_callback(session, stream_id, error_code, user_data);
758
759 return NGHTTP2_ERR_CALLBACK_FAILURE;
760 }
761
pack_extension_callback(nghttp2_session * session,uint8_t * buf,size_t len,const nghttp2_frame * frame,void * user_data)762 static nghttp2_ssize pack_extension_callback(nghttp2_session *session,
763 uint8_t *buf, size_t len,
764 const nghttp2_frame *frame,
765 void *user_data) {
766 nghttp2_buf *p = frame->ext.payload;
767 (void)session;
768 (void)len;
769 (void)user_data;
770
771 memcpy(buf, p->pos, nghttp2_buf_len(p));
772
773 return (nghttp2_ssize)nghttp2_buf_len(p);
774 }
775
on_extension_chunk_recv_callback(nghttp2_session * session,const nghttp2_frame_hd * hd,const uint8_t * data,size_t len,void * user_data)776 static int on_extension_chunk_recv_callback(nghttp2_session *session,
777 const nghttp2_frame_hd *hd,
778 const uint8_t *data, size_t len,
779 void *user_data) {
780 my_user_data *my_data = (my_user_data *)user_data;
781 nghttp2_buf *buf = &my_data->scratchbuf;
782 (void)session;
783 (void)hd;
784
785 buf->last = nghttp2_cpymem(buf->last, data, len);
786
787 return 0;
788 }
789
cancel_on_extension_chunk_recv_callback(nghttp2_session * session,const nghttp2_frame_hd * hd,const uint8_t * data,size_t len,void * user_data)790 static int cancel_on_extension_chunk_recv_callback(nghttp2_session *session,
791 const nghttp2_frame_hd *hd,
792 const uint8_t *data,
793 size_t len,
794 void *user_data) {
795 (void)session;
796 (void)hd;
797 (void)data;
798 (void)len;
799 (void)user_data;
800
801 return NGHTTP2_ERR_CANCEL;
802 }
803
unpack_extension_callback(nghttp2_session * session,void ** payload,const nghttp2_frame_hd * hd,void * user_data)804 static int unpack_extension_callback(nghttp2_session *session, void **payload,
805 const nghttp2_frame_hd *hd,
806 void *user_data) {
807 my_user_data *my_data = (my_user_data *)user_data;
808 nghttp2_buf *buf = &my_data->scratchbuf;
809 (void)session;
810 (void)hd;
811
812 *payload = buf;
813
814 return 0;
815 }
816
cancel_unpack_extension_callback(nghttp2_session * session,void ** payload,const nghttp2_frame_hd * hd,void * user_data)817 static int cancel_unpack_extension_callback(nghttp2_session *session,
818 void **payload,
819 const nghttp2_frame_hd *hd,
820 void *user_data) {
821 (void)session;
822 (void)payload;
823 (void)hd;
824 (void)user_data;
825
826 return NGHTTP2_ERR_CANCEL;
827 }
828
dup_iv(const nghttp2_settings_entry * iv,size_t niv)829 static nghttp2_settings_entry *dup_iv(const nghttp2_settings_entry *iv,
830 size_t niv) {
831 return nghttp2_frame_iv_copy(iv, niv, nghttp2_mem_default());
832 }
833
834 static nghttp2_priority_spec pri_spec_default = {0, NGHTTP2_DEFAULT_WEIGHT, 0};
835
test_nghttp2_session_recv(void)836 void test_nghttp2_session_recv(void) {
837 nghttp2_session *session;
838 nghttp2_session_callbacks callbacks;
839 scripted_data_feed df;
840 my_user_data user_data;
841 nghttp2_bufs bufs;
842 size_t framelen;
843 nghttp2_frame frame;
844 size_t i;
845 nghttp2_outbound_item *item;
846 nghttp2_nv *nva;
847 size_t nvlen;
848 nghttp2_hd_deflater deflater;
849 int rv;
850 nghttp2_mem *mem;
851
852 mem = nghttp2_mem_default();
853 frame_pack_bufs_init(&bufs);
854
855 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
856 callbacks.send_callback2 = null_send_callback;
857 callbacks.recv_callback2 = scripted_recv_callback;
858 callbacks.on_frame_recv_callback = on_frame_recv_callback;
859 callbacks.on_begin_frame_callback = on_begin_frame_callback;
860
861 user_data.df = &df;
862
863 nghttp2_session_server_new(&session, &callbacks, &user_data);
864 nghttp2_hd_deflate_init(&deflater, mem);
865
866 nvlen = ARRLEN(reqnv);
867 nghttp2_nv_array_copy(&nva, reqnv, nvlen, mem);
868 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 1,
869 NGHTTP2_HCAT_HEADERS, NULL, nva, nvlen);
870 rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
871
872 assert_int(0, ==, rv);
873
874 scripted_data_feed_init2(&df, &bufs);
875
876 framelen = nghttp2_bufs_len(&bufs);
877
878 /* Send 1 byte per each read */
879 for (i = 0; i < framelen; ++i) {
880 df.feedseq[i] = 1;
881 }
882
883 nghttp2_frame_headers_free(&frame.headers, mem);
884
885 user_data.frame_recv_cb_called = 0;
886 user_data.begin_frame_cb_called = 0;
887
888 while (df.seqidx < framelen) {
889 assert_int(0, ==, nghttp2_session_recv(session));
890 }
891 assert_int(1, ==, user_data.frame_recv_cb_called);
892 assert_int(1, ==, user_data.begin_frame_cb_called);
893
894 nghttp2_bufs_reset(&bufs);
895
896 /* Receive PRIORITY */
897 nghttp2_frame_priority_init(&frame.priority, 5, &pri_spec_default);
898
899 nghttp2_frame_pack_priority(&bufs, &frame.priority);
900
901 nghttp2_frame_priority_free(&frame.priority);
902
903 scripted_data_feed_init2(&df, &bufs);
904
905 user_data.frame_recv_cb_called = 0;
906 user_data.begin_frame_cb_called = 0;
907
908 assert_int(0, ==, nghttp2_session_recv(session));
909 assert_int(1, ==, user_data.frame_recv_cb_called);
910 assert_int(1, ==, user_data.begin_frame_cb_called);
911
912 nghttp2_bufs_reset(&bufs);
913
914 nghttp2_hd_deflate_free(&deflater);
915 nghttp2_session_del(session);
916
917 /* Some tests for frame too large */
918 nghttp2_session_server_new(&session, &callbacks, &user_data);
919
920 /* Receive PING with too large payload */
921 nghttp2_frame_ping_init(&frame.ping, NGHTTP2_FLAG_NONE, NULL);
922
923 nghttp2_frame_pack_ping(&bufs, &frame.ping);
924
925 /* Add extra 16 bytes */
926 nghttp2_bufs_seek_last_present(&bufs);
927 assert(nghttp2_buf_len(&bufs.cur->buf) >= 16);
928
929 bufs.cur->buf.last += 16;
930 nghttp2_put_uint32be(
931 bufs.cur->buf.pos,
932 (uint32_t)(((frame.hd.length + 16) << 8) + bufs.cur->buf.pos[3]));
933
934 nghttp2_frame_ping_free(&frame.ping);
935
936 scripted_data_feed_init2(&df, &bufs);
937 user_data.frame_recv_cb_called = 0;
938 user_data.begin_frame_cb_called = 0;
939
940 assert_int(0, ==, nghttp2_session_recv(session));
941 assert_int(0, ==, user_data.frame_recv_cb_called);
942 assert_int(0, ==, user_data.begin_frame_cb_called);
943
944 item = nghttp2_session_get_next_ob_item(session);
945 assert_uint8(NGHTTP2_GOAWAY, ==, item->frame.hd.type);
946 assert_uint32(NGHTTP2_FRAME_SIZE_ERROR, ==, item->frame.goaway.error_code);
947 assert_int(0, ==, nghttp2_session_send(session));
948
949 nghttp2_bufs_free(&bufs);
950 nghttp2_session_del(session);
951 }
952
test_nghttp2_session_recv_invalid_stream_id(void)953 void test_nghttp2_session_recv_invalid_stream_id(void) {
954 nghttp2_session *session;
955 nghttp2_session_callbacks callbacks;
956 scripted_data_feed df;
957 my_user_data user_data;
958 nghttp2_bufs bufs;
959 nghttp2_frame frame;
960 nghttp2_hd_deflater deflater;
961 int rv;
962 nghttp2_mem *mem;
963 nghttp2_nv *nva;
964 size_t nvlen;
965
966 mem = nghttp2_mem_default();
967 frame_pack_bufs_init(&bufs);
968
969 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
970 callbacks.recv_callback2 = scripted_recv_callback;
971 callbacks.on_invalid_frame_recv_callback = on_invalid_frame_recv_callback;
972
973 user_data.df = &df;
974 user_data.invalid_frame_recv_cb_called = 0;
975 nghttp2_session_server_new(&session, &callbacks, &user_data);
976 nghttp2_hd_deflate_init(&deflater, mem);
977
978 nvlen = ARRLEN(reqnv);
979 nghttp2_nv_array_copy(&nva, reqnv, nvlen, mem);
980 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 2,
981 NGHTTP2_HCAT_HEADERS, NULL, nva, nvlen);
982 rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
983
984 assert_int(0, ==, rv);
985 assert_size(0, <, nghttp2_bufs_len(&bufs));
986
987 scripted_data_feed_init2(&df, &bufs);
988 nghttp2_frame_headers_free(&frame.headers, mem);
989
990 assert_int(0, ==, nghttp2_session_recv(session));
991 assert_int(1, ==, user_data.invalid_frame_recv_cb_called);
992
993 nghttp2_bufs_free(&bufs);
994 nghttp2_hd_deflate_free(&deflater);
995 nghttp2_session_del(session);
996 }
997
test_nghttp2_session_recv_invalid_frame(void)998 void test_nghttp2_session_recv_invalid_frame(void) {
999 nghttp2_session *session;
1000 nghttp2_session_callbacks callbacks;
1001 scripted_data_feed df;
1002 my_user_data user_data;
1003 nghttp2_bufs bufs;
1004 nghttp2_frame frame;
1005 nghttp2_nv *nva;
1006 size_t nvlen;
1007 nghttp2_hd_deflater deflater;
1008 int rv;
1009 nghttp2_mem *mem;
1010
1011 mem = nghttp2_mem_default();
1012 frame_pack_bufs_init(&bufs);
1013
1014 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
1015 callbacks.recv_callback2 = scripted_recv_callback;
1016 callbacks.send_callback2 = null_send_callback;
1017 callbacks.on_frame_send_callback = on_frame_send_callback;
1018
1019 user_data.df = &df;
1020 user_data.frame_send_cb_called = 0;
1021 nghttp2_session_server_new(&session, &callbacks, &user_data);
1022 nghttp2_hd_deflate_init(&deflater, mem);
1023 nvlen = ARRLEN(reqnv);
1024 nghttp2_nv_array_copy(&nva, reqnv, nvlen, mem);
1025 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 1,
1026 NGHTTP2_HCAT_HEADERS, NULL, nva, nvlen);
1027 rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
1028
1029 assert_int(0, ==, rv);
1030 assert_size(0, <, nghttp2_bufs_len(&bufs));
1031
1032 scripted_data_feed_init2(&df, &bufs);
1033
1034 assert_int(0, ==, nghttp2_session_recv(session));
1035 assert_int(0, ==, nghttp2_session_send(session));
1036 assert_int(0, ==, user_data.frame_send_cb_called);
1037
1038 /* Receive exactly same bytes of HEADERS is treated as error, because it has
1039 * pseudo headers and without END_STREAM flag set */
1040 scripted_data_feed_init2(&df, &bufs);
1041
1042 assert_int(0, ==, nghttp2_session_recv(session));
1043 assert_int(0, ==, nghttp2_session_send(session));
1044 assert_int(1, ==, user_data.frame_send_cb_called);
1045 assert_uint8(NGHTTP2_RST_STREAM, ==, user_data.sent_frame_type);
1046
1047 nghttp2_bufs_free(&bufs);
1048 nghttp2_frame_headers_free(&frame.headers, mem);
1049
1050 nghttp2_hd_deflate_free(&deflater);
1051 nghttp2_session_del(session);
1052 }
1053
test_nghttp2_session_recv_eof(void)1054 void test_nghttp2_session_recv_eof(void) {
1055 nghttp2_session *session;
1056 nghttp2_session_callbacks callbacks;
1057
1058 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
1059 callbacks.send_callback2 = null_send_callback;
1060 callbacks.recv_callback2 = eof_recv_callback;
1061
1062 nghttp2_session_client_new(&session, &callbacks, NULL);
1063 assert_int(NGHTTP2_ERR_EOF, ==, nghttp2_session_recv(session));
1064
1065 nghttp2_session_del(session);
1066 }
1067
test_nghttp2_session_recv_data(void)1068 void test_nghttp2_session_recv_data(void) {
1069 nghttp2_session *session;
1070 nghttp2_session_callbacks callbacks;
1071 my_user_data ud;
1072 uint8_t data[8092];
1073 nghttp2_ssize rv;
1074 nghttp2_outbound_item *item;
1075 nghttp2_stream *stream;
1076 nghttp2_frame_hd hd;
1077 int i;
1078
1079 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
1080 callbacks.send_callback2 = null_send_callback;
1081 callbacks.on_data_chunk_recv_callback = on_data_chunk_recv_callback;
1082 callbacks.on_frame_recv_callback = on_frame_recv_callback;
1083 callbacks.on_frame_send_callback = on_frame_send_callback;
1084
1085 nghttp2_session_client_new(&session, &callbacks, &ud);
1086
1087 /* Create DATA frame with length 4KiB */
1088 memset(data, 0, sizeof(data));
1089 hd.length = 4096;
1090 hd.type = NGHTTP2_DATA;
1091 hd.flags = NGHTTP2_FLAG_NONE;
1092 hd.stream_id = 1;
1093 nghttp2_frame_pack_frame_hd(data, &hd);
1094
1095 /* stream 1 is not opened, so it must be responded with connection
1096 error. This is not mandated by the spec */
1097 ud.data_chunk_recv_cb_called = 0;
1098 ud.frame_recv_cb_called = 0;
1099 rv = nghttp2_session_mem_recv2(session, data, NGHTTP2_FRAME_HDLEN + 4096);
1100 assert_ptrdiff(NGHTTP2_FRAME_HDLEN + 4096, ==, rv);
1101
1102 assert_int(0, ==, ud.data_chunk_recv_cb_called);
1103 assert_int(0, ==, ud.frame_recv_cb_called);
1104 item = nghttp2_session_get_next_ob_item(session);
1105 assert_uint8(NGHTTP2_GOAWAY, ==, item->frame.hd.type);
1106
1107 nghttp2_session_del(session);
1108
1109 nghttp2_session_client_new(&session, &callbacks, &ud);
1110
1111 /* Create stream 1 with CLOSING state. DATA is ignored. */
1112 stream = open_sent_stream2(session, 1, NGHTTP2_STREAM_CLOSING);
1113
1114 /* Set initial window size 16383 to check stream flow control,
1115 isolating it from the connection flow control */
1116 stream->local_window_size = 16383;
1117
1118 ud.data_chunk_recv_cb_called = 0;
1119 ud.frame_recv_cb_called = 0;
1120 rv = nghttp2_session_mem_recv2(session, data, NGHTTP2_FRAME_HDLEN + 4096);
1121 assert_ptrdiff(NGHTTP2_FRAME_HDLEN + 4096, ==, rv);
1122
1123 assert_int(0, ==, ud.data_chunk_recv_cb_called);
1124 assert_int(0, ==, ud.frame_recv_cb_called);
1125 item = nghttp2_session_get_next_ob_item(session);
1126 assert_null(item);
1127
1128 /* This is normal case. DATA is acceptable. */
1129 stream->state = NGHTTP2_STREAM_OPENED;
1130
1131 ud.data_chunk_recv_cb_called = 0;
1132 ud.frame_recv_cb_called = 0;
1133 rv = nghttp2_session_mem_recv2(session, data, NGHTTP2_FRAME_HDLEN + 4096);
1134 assert_ptrdiff(NGHTTP2_FRAME_HDLEN + 4096, ==, rv);
1135
1136 assert_int(1, ==, ud.data_chunk_recv_cb_called);
1137 assert_int(1, ==, ud.frame_recv_cb_called);
1138
1139 assert_null(nghttp2_session_get_next_ob_item(session));
1140
1141 ud.data_chunk_recv_cb_called = 0;
1142 ud.frame_recv_cb_called = 0;
1143 rv = nghttp2_session_mem_recv2(session, data, NGHTTP2_FRAME_HDLEN + 4096);
1144 assert_ptrdiff(NGHTTP2_FRAME_HDLEN + 4096, ==, rv);
1145
1146 /* Now we got data more than initial-window-size / 2, WINDOW_UPDATE
1147 must be queued */
1148 assert_int(1, ==, ud.data_chunk_recv_cb_called);
1149 assert_int(1, ==, ud.frame_recv_cb_called);
1150 item = nghttp2_session_get_next_ob_item(session);
1151 assert_uint8(NGHTTP2_WINDOW_UPDATE, ==, item->frame.hd.type);
1152 assert_int32(1, ==, item->frame.window_update.hd.stream_id);
1153 assert_int(0, ==, nghttp2_session_send(session));
1154
1155 /* Set initial window size to 1MiB, so that we can check connection
1156 flow control individually */
1157 stream->local_window_size = 1 << 20;
1158 /* Connection flow control takes into account DATA which is received
1159 in the error condition. We have received 4096 * 4 bytes of
1160 DATA. Additional 4 DATA frames, connection flow control will kick
1161 in. */
1162 for (i = 0; i < 5; ++i) {
1163 rv = nghttp2_session_mem_recv2(session, data, NGHTTP2_FRAME_HDLEN + 4096);
1164 assert_ptrdiff(NGHTTP2_FRAME_HDLEN + 4096, ==, rv);
1165 }
1166 item = nghttp2_session_get_next_ob_item(session);
1167 assert_uint8(NGHTTP2_WINDOW_UPDATE, ==, item->frame.hd.type);
1168 assert_int32(0, ==, item->frame.window_update.hd.stream_id);
1169 assert_int(0, ==, nghttp2_session_send(session));
1170
1171 /* Reception of DATA with stream ID = 0 causes connection error */
1172 hd.length = 4096;
1173 hd.type = NGHTTP2_DATA;
1174 hd.flags = NGHTTP2_FLAG_NONE;
1175 hd.stream_id = 0;
1176 nghttp2_frame_pack_frame_hd(data, &hd);
1177
1178 ud.data_chunk_recv_cb_called = 0;
1179 ud.frame_recv_cb_called = 0;
1180 rv = nghttp2_session_mem_recv2(session, data, NGHTTP2_FRAME_HDLEN + 4096);
1181 assert_ptrdiff(NGHTTP2_FRAME_HDLEN + 4096, ==, rv);
1182
1183 assert_int(0, ==, ud.data_chunk_recv_cb_called);
1184 assert_int(0, ==, ud.frame_recv_cb_called);
1185 item = nghttp2_session_get_next_ob_item(session);
1186 assert_uint8(NGHTTP2_GOAWAY, ==, item->frame.hd.type);
1187 assert_uint32(NGHTTP2_PROTOCOL_ERROR, ==, item->frame.goaway.error_code);
1188
1189 nghttp2_session_del(session);
1190
1191 /* Check window_update_queued flag in both session and stream */
1192 nghttp2_session_server_new(&session, &callbacks, &ud);
1193
1194 hd.length = 4096;
1195 hd.type = NGHTTP2_DATA;
1196 hd.flags = NGHTTP2_FLAG_NONE;
1197 hd.stream_id = 1;
1198 nghttp2_frame_pack_frame_hd(data, &hd);
1199
1200 stream = open_recv_stream(session, 1);
1201
1202 /* Send 32767 bytes of DATA. In our current flow control algorithm,
1203 it triggers first WINDOW_UPDATE of window_size_increment
1204 32767. */
1205 for (i = 0; i < 7; ++i) {
1206 rv = nghttp2_session_mem_recv2(session, data, NGHTTP2_FRAME_HDLEN + 4096);
1207 assert_ptrdiff(NGHTTP2_FRAME_HDLEN + 4096, ==, rv);
1208 }
1209
1210 hd.length = 4095;
1211 nghttp2_frame_pack_frame_hd(data, &hd);
1212 rv = nghttp2_session_mem_recv2(session, data, NGHTTP2_FRAME_HDLEN + 4095);
1213 assert_ptrdiff(NGHTTP2_FRAME_HDLEN + 4095, ==, rv);
1214
1215 /* Now 2 WINDOW_UPDATEs for session and stream should be queued. */
1216 assert_int32(0, ==, stream->recv_window_size);
1217 assert_int32(0, ==, session->recv_window_size);
1218 assert_true(stream->window_update_queued);
1219 assert_true(session->window_update_queued);
1220
1221 /* Then send 32768 bytes of DATA. Since we have not sent queued
1222 WINDOW_UDPATE frame, recv_window_size should not be decreased */
1223 hd.length = 4096;
1224 nghttp2_frame_pack_frame_hd(data, &hd);
1225
1226 for (i = 0; i < 8; ++i) {
1227 rv = nghttp2_session_mem_recv2(session, data, NGHTTP2_FRAME_HDLEN + 4096);
1228 assert_ptrdiff(NGHTTP2_FRAME_HDLEN + 4096, ==, rv);
1229 }
1230
1231 /* WINDOW_UPDATE is blocked for session and stream, so
1232 recv_window_size must not be decreased. */
1233 assert_int32(32768, ==, stream->recv_window_size);
1234 assert_int32(32768, ==, session->recv_window_size);
1235 assert_true(stream->window_update_queued);
1236 assert_true(session->window_update_queued);
1237
1238 ud.frame_send_cb_called = 0;
1239
1240 /* This sends queued WINDOW_UPDATES. And then check
1241 recv_window_size, and queue WINDOW_UPDATEs for both session and
1242 stream, and send them at once. */
1243 assert_int(0, ==, nghttp2_session_send(session));
1244
1245 assert_int(4, ==, ud.frame_send_cb_called);
1246 assert_int32(0, ==, stream->recv_window_size);
1247 assert_int32(0, ==, session->recv_window_size);
1248 assert_false(stream->window_update_queued);
1249 assert_false(session->window_update_queued);
1250
1251 nghttp2_session_del(session);
1252 }
1253
test_nghttp2_session_recv_data_no_auto_flow_control(void)1254 void test_nghttp2_session_recv_data_no_auto_flow_control(void) {
1255 nghttp2_session *session;
1256 nghttp2_session_callbacks callbacks;
1257 my_user_data ud;
1258 nghttp2_option *option;
1259 nghttp2_frame_hd hd;
1260 size_t padlen;
1261 uint8_t data[8192];
1262 nghttp2_ssize rv;
1263 size_t sendlen;
1264 nghttp2_stream *stream;
1265 size_t i;
1266
1267 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
1268 callbacks.send_callback2 = null_send_callback;
1269 callbacks.on_frame_send_callback = on_frame_send_callback;
1270
1271 nghttp2_option_new(&option);
1272 nghttp2_option_set_no_auto_window_update(option, 1);
1273
1274 nghttp2_session_server_new2(&session, &callbacks, &ud, option);
1275
1276 /* Create DATA frame with length 4KiB + 11 bytes padding*/
1277 padlen = 11;
1278 memset(data, 0, sizeof(data));
1279 hd.length = 4096 + 1 + padlen;
1280 hd.type = NGHTTP2_DATA;
1281 hd.flags = NGHTTP2_FLAG_PADDED;
1282 hd.stream_id = 1;
1283 nghttp2_frame_pack_frame_hd(data, &hd);
1284 data[NGHTTP2_FRAME_HDLEN] = (uint8_t)padlen;
1285
1286 /* First create stream 1, then close it. Check that data is
1287 consumed for connection in this situation */
1288 open_recv_stream(session, 1);
1289
1290 /* Receive first 100 bytes */
1291 sendlen = 100;
1292 rv = nghttp2_session_mem_recv2(session, data, sendlen);
1293 assert_ptrdiff((nghttp2_ssize)sendlen, ==, rv);
1294
1295 /* We consumed pad length field (1 byte) */
1296 assert_int32(1, ==, session->consumed_size);
1297
1298 /* close stream here */
1299 nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, 1, NGHTTP2_NO_ERROR);
1300 nghttp2_session_send(session);
1301
1302 /* stream 1 has been closed, and we disabled auto flow-control, so
1303 data must be immediately consumed for connection. */
1304 rv = nghttp2_session_mem_recv2(session, data + sendlen,
1305 NGHTTP2_FRAME_HDLEN + hd.length - sendlen);
1306 assert_ptrdiff((nghttp2_ssize)(NGHTTP2_FRAME_HDLEN + hd.length - sendlen), ==,
1307 rv);
1308
1309 /* We already consumed pad length field (1 byte), so do +1 here */
1310 assert_int32((int32_t)(NGHTTP2_FRAME_HDLEN + hd.length - sendlen + 1), ==,
1311 session->consumed_size);
1312
1313 nghttp2_session_del(session);
1314
1315 /* Reuse DATA created previously. */
1316
1317 nghttp2_session_server_new2(&session, &callbacks, &ud, option);
1318
1319 /* Now we are expecting final response header, which means receiving
1320 DATA for that stream is illegal. */
1321 stream = open_recv_stream(session, 1);
1322 stream->http_flags |= NGHTTP2_HTTP_FLAG_EXPECT_FINAL_RESPONSE;
1323
1324 rv =
1325 nghttp2_session_mem_recv2(session, data, NGHTTP2_FRAME_HDLEN + hd.length);
1326 assert_ptrdiff((nghttp2_ssize)(NGHTTP2_FRAME_HDLEN + hd.length), ==, rv);
1327
1328 /* Whole payload must be consumed now because HTTP messaging rule
1329 was not honored. */
1330 assert_int32((int32_t)hd.length, ==, session->consumed_size);
1331
1332 nghttp2_session_del(session);
1333
1334 /* Check window_update_queued flag in both session and stream */
1335 nghttp2_session_server_new2(&session, &callbacks, &ud, option);
1336
1337 stream = open_recv_stream(session, 1);
1338
1339 hd.length = 4096;
1340 hd.type = NGHTTP2_DATA;
1341 hd.flags = NGHTTP2_FLAG_NONE;
1342 hd.stream_id = 1;
1343 nghttp2_frame_pack_frame_hd(data, &hd);
1344
1345 /* Receive up to 65535 bytes of DATA */
1346 for (i = 0; i < 15; ++i) {
1347 rv = nghttp2_session_mem_recv2(session, data, NGHTTP2_FRAME_HDLEN + 4096);
1348 assert_ptrdiff(NGHTTP2_FRAME_HDLEN + 4096, ==, rv);
1349 }
1350
1351 hd.length = 4095;
1352 nghttp2_frame_pack_frame_hd(data, &hd);
1353
1354 rv = nghttp2_session_mem_recv2(session, data, NGHTTP2_FRAME_HDLEN + 4095);
1355 assert_ptrdiff(NGHTTP2_FRAME_HDLEN + 4095, ==, rv);
1356
1357 assert_int32(65535, ==, session->recv_window_size);
1358 assert_int32(65535, ==, stream->recv_window_size);
1359
1360 /* The first call of nghttp2_session_consume_connection() will queue
1361 WINDOW_UPDATE. Next call does not. */
1362 nghttp2_session_consume_connection(session, 32767);
1363 nghttp2_session_consume_connection(session, 32768);
1364
1365 assert_int32(32768, ==, session->recv_window_size);
1366 assert_int32(65535, ==, stream->recv_window_size);
1367 assert_true(session->window_update_queued);
1368 assert_false(stream->window_update_queued);
1369
1370 ud.frame_send_cb_called = 0;
1371
1372 /* This will send WINDOW_UPDATE, and check whether we should send
1373 WINDOW_UPDATE, and queue and send it at once. */
1374 assert_int(0, ==, nghttp2_session_send(session));
1375 assert_int32(0, ==, session->recv_window_size);
1376 assert_int32(65535, ==, stream->recv_window_size);
1377 assert_false(session->window_update_queued);
1378 assert_false(stream->window_update_queued);
1379 assert_int(2, ==, ud.frame_send_cb_called);
1380
1381 /* Do the same for stream */
1382 nghttp2_session_consume_stream(session, 1, 32767);
1383 nghttp2_session_consume_stream(session, 1, 32768);
1384
1385 assert_int32(0, ==, session->recv_window_size);
1386 assert_int32(32768, ==, stream->recv_window_size);
1387 assert_false(session->window_update_queued);
1388 assert_true(stream->window_update_queued);
1389
1390 ud.frame_send_cb_called = 0;
1391
1392 assert_int(0, ==, nghttp2_session_send(session));
1393 assert_int32(0, ==, session->recv_window_size);
1394 assert_int32(0, ==, stream->recv_window_size);
1395 assert_false(session->window_update_queued);
1396 assert_false(stream->window_update_queued);
1397 assert_int(2, ==, ud.frame_send_cb_called);
1398
1399 nghttp2_session_del(session);
1400 nghttp2_option_del(option);
1401 }
1402
test_nghttp2_session_recv_continuation(void)1403 void test_nghttp2_session_recv_continuation(void) {
1404 nghttp2_session *session;
1405 nghttp2_session_callbacks callbacks;
1406 nghttp2_nv *nva;
1407 size_t nvlen;
1408 nghttp2_frame frame;
1409 nghttp2_bufs bufs;
1410 nghttp2_buf *buf;
1411 nghttp2_ssize rv;
1412 my_user_data ud;
1413 nghttp2_hd_deflater deflater;
1414 uint8_t data[1024];
1415 size_t datalen;
1416 nghttp2_frame_hd cont_hd;
1417 nghttp2_priority_spec pri_spec;
1418 nghttp2_mem *mem;
1419
1420 mem = nghttp2_mem_default();
1421 frame_pack_bufs_init(&bufs);
1422
1423 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
1424 callbacks.on_header_callback = on_header_callback;
1425 callbacks.on_begin_headers_callback = on_begin_headers_callback;
1426 callbacks.on_begin_frame_callback = on_begin_frame_callback;
1427
1428 nghttp2_session_server_new(&session, &callbacks, &ud);
1429
1430 nghttp2_hd_deflate_init(&deflater, mem);
1431
1432 /* Make 1 HEADERS and insert CONTINUATION header */
1433 nvlen = ARRLEN(reqnv);
1434 nghttp2_nv_array_copy(&nva, reqnv, nvlen, mem);
1435 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_NONE, 1,
1436 NGHTTP2_HCAT_HEADERS, NULL, nva, nvlen);
1437 rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
1438
1439 assert_ptrdiff(0, ==, rv);
1440 assert_size(0, <, nghttp2_bufs_len(&bufs));
1441
1442 /* make sure that all data is in the first buf */
1443 buf = &bufs.head->buf;
1444 assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
1445
1446 nghttp2_frame_headers_free(&frame.headers, mem);
1447
1448 /* HEADERS's payload is 1 byte */
1449 memcpy(data, buf->pos, NGHTTP2_FRAME_HDLEN + 1);
1450 datalen = NGHTTP2_FRAME_HDLEN + 1;
1451 buf->pos += NGHTTP2_FRAME_HDLEN + 1;
1452
1453 nghttp2_put_uint32be(data, (uint32_t)((1 << 8) + data[3]));
1454
1455 /* First CONTINUATION, 2 bytes */
1456 nghttp2_frame_hd_init(&cont_hd, 2, NGHTTP2_CONTINUATION, NGHTTP2_FLAG_NONE,
1457 1);
1458
1459 nghttp2_frame_pack_frame_hd(data + datalen, &cont_hd);
1460 datalen += NGHTTP2_FRAME_HDLEN;
1461
1462 memcpy(data + datalen, buf->pos, cont_hd.length);
1463 datalen += cont_hd.length;
1464 buf->pos += cont_hd.length;
1465
1466 /* Second CONTINUATION, rest of the bytes */
1467 nghttp2_frame_hd_init(&cont_hd, nghttp2_buf_len(buf), NGHTTP2_CONTINUATION,
1468 NGHTTP2_FLAG_END_HEADERS, 1);
1469
1470 nghttp2_frame_pack_frame_hd(data + datalen, &cont_hd);
1471 datalen += NGHTTP2_FRAME_HDLEN;
1472
1473 memcpy(data + datalen, buf->pos, cont_hd.length);
1474 datalen += cont_hd.length;
1475 buf->pos += cont_hd.length;
1476
1477 assert_size(0, ==, nghttp2_buf_len(buf));
1478
1479 ud.header_cb_called = 0;
1480 ud.begin_frame_cb_called = 0;
1481
1482 rv = nghttp2_session_mem_recv2(session, data, datalen);
1483 assert_ptrdiff((nghttp2_ssize)datalen, ==, rv);
1484 assert_int(4, ==, ud.header_cb_called);
1485 assert_int(3, ==, ud.begin_frame_cb_called);
1486
1487 nghttp2_hd_deflate_free(&deflater);
1488 nghttp2_session_del(session);
1489
1490 /* HEADERS with padding followed by CONTINUATION */
1491 nghttp2_session_server_new(&session, &callbacks, &ud);
1492
1493 nghttp2_hd_deflate_init(&deflater, mem);
1494
1495 nvlen = ARRLEN(reqnv);
1496 nghttp2_nv_array_copy(&nva, reqnv, nvlen, mem);
1497 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_NONE, 1,
1498 NGHTTP2_HCAT_HEADERS, NULL, nva, nvlen);
1499
1500 nghttp2_bufs_reset(&bufs);
1501 rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
1502
1503 assert_ptrdiff(0, ==, rv);
1504
1505 nghttp2_frame_headers_free(&frame.headers, mem);
1506
1507 /* make sure that all data is in the first buf */
1508 buf = &bufs.head->buf;
1509 assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
1510
1511 /* HEADERS payload is 3 byte (1 for padding field, 1 for padding) */
1512 memcpy(data, buf->pos, NGHTTP2_FRAME_HDLEN);
1513 nghttp2_put_uint32be(data, (uint32_t)((3 << 8) + data[3]));
1514 data[4] |= NGHTTP2_FLAG_PADDED;
1515 /* padding field */
1516 data[NGHTTP2_FRAME_HDLEN] = 1;
1517 data[NGHTTP2_FRAME_HDLEN + 1] = buf->pos[NGHTTP2_FRAME_HDLEN];
1518 /* padding */
1519 data[NGHTTP2_FRAME_HDLEN + 2] = 0;
1520 datalen = NGHTTP2_FRAME_HDLEN + 3;
1521 buf->pos += NGHTTP2_FRAME_HDLEN + 1;
1522
1523 /* CONTINUATION, rest of the bytes */
1524 nghttp2_frame_hd_init(&cont_hd, nghttp2_buf_len(buf), NGHTTP2_CONTINUATION,
1525 NGHTTP2_FLAG_END_HEADERS, 1);
1526 nghttp2_frame_pack_frame_hd(data + datalen, &cont_hd);
1527 datalen += NGHTTP2_FRAME_HDLEN;
1528
1529 memcpy(data + datalen, buf->pos, cont_hd.length);
1530 datalen += cont_hd.length;
1531 buf->pos += cont_hd.length;
1532
1533 assert_size(0, ==, nghttp2_buf_len(buf));
1534
1535 ud.header_cb_called = 0;
1536 ud.begin_frame_cb_called = 0;
1537
1538 rv = nghttp2_session_mem_recv2(session, data, datalen);
1539
1540 assert_ptrdiff((nghttp2_ssize)datalen, ==, rv);
1541 assert_int(4, ==, ud.header_cb_called);
1542 assert_int(2, ==, ud.begin_frame_cb_called);
1543
1544 nghttp2_hd_deflate_free(&deflater);
1545 nghttp2_session_del(session);
1546
1547 /* Expecting CONTINUATION, but get the other frame */
1548 nghttp2_session_server_new(&session, &callbacks, &ud);
1549
1550 nghttp2_hd_deflate_init(&deflater, mem);
1551
1552 /* HEADERS without END_HEADERS flag */
1553 nvlen = ARRLEN(reqnv);
1554 nghttp2_nv_array_copy(&nva, reqnv, nvlen, mem);
1555 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_NONE, 1,
1556 NGHTTP2_HCAT_HEADERS, NULL, nva, nvlen);
1557 nghttp2_bufs_reset(&bufs);
1558 rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
1559
1560 assert_ptrdiff(0, ==, rv);
1561 assert_size(0, <, nghttp2_bufs_len(&bufs));
1562
1563 nghttp2_frame_headers_free(&frame.headers, mem);
1564
1565 /* make sure that all data is in the first buf */
1566 buf = &bufs.head->buf;
1567 assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
1568
1569 memcpy(data, buf->pos, nghttp2_buf_len(buf));
1570 datalen = nghttp2_buf_len(buf);
1571
1572 /* Followed by PRIORITY */
1573 nghttp2_priority_spec_default_init(&pri_spec);
1574
1575 nghttp2_frame_priority_init(&frame.priority, 1, &pri_spec);
1576 nghttp2_bufs_reset(&bufs);
1577
1578 nghttp2_frame_pack_priority(&bufs, &frame.priority);
1579
1580 assert_size(0, <, nghttp2_bufs_len(&bufs));
1581
1582 memcpy(data + datalen, buf->pos, nghttp2_buf_len(buf));
1583 datalen += nghttp2_buf_len(buf);
1584
1585 ud.begin_headers_cb_called = 0;
1586 rv = nghttp2_session_mem_recv2(session, data, datalen);
1587 assert_ptrdiff((nghttp2_ssize)datalen, ==, rv);
1588
1589 assert_int(1, ==, ud.begin_headers_cb_called);
1590 assert_uint8(NGHTTP2_GOAWAY, ==,
1591 nghttp2_session_get_next_ob_item(session)->frame.hd.type);
1592
1593 nghttp2_bufs_free(&bufs);
1594 nghttp2_hd_deflate_free(&deflater);
1595 nghttp2_session_del(session);
1596 }
1597
test_nghttp2_session_recv_headers_with_priority(void)1598 void test_nghttp2_session_recv_headers_with_priority(void) {
1599 nghttp2_session *session;
1600 nghttp2_session_callbacks callbacks;
1601 nghttp2_nv *nva;
1602 size_t nvlen;
1603 nghttp2_frame frame;
1604 nghttp2_bufs bufs;
1605 nghttp2_buf *buf;
1606 nghttp2_ssize rv;
1607 my_user_data ud;
1608 nghttp2_hd_deflater deflater;
1609 nghttp2_outbound_item *item;
1610 nghttp2_priority_spec pri_spec;
1611 nghttp2_stream *stream;
1612 nghttp2_mem *mem;
1613
1614 mem = nghttp2_mem_default();
1615 frame_pack_bufs_init(&bufs);
1616
1617 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
1618 callbacks.on_frame_recv_callback = on_frame_recv_callback;
1619
1620 nghttp2_session_server_new(&session, &callbacks, &ud);
1621
1622 nghttp2_hd_deflate_init(&deflater, mem);
1623
1624 open_recv_stream(session, 1);
1625
1626 /* With NGHTTP2_FLAG_PRIORITY without exclusive flag set */
1627 nvlen = ARRLEN(reqnv);
1628 nghttp2_nv_array_copy(&nva, reqnv, nvlen, mem);
1629
1630 nghttp2_priority_spec_init(&pri_spec, 1, 99, 0);
1631
1632 nghttp2_frame_headers_init(&frame.headers,
1633 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PRIORITY,
1634 3, NGHTTP2_HCAT_HEADERS, &pri_spec, nva, nvlen);
1635
1636 rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
1637
1638 assert_ptrdiff(0, ==, rv);
1639 assert_size(0, <, nghttp2_bufs_len(&bufs));
1640
1641 nghttp2_frame_headers_free(&frame.headers, mem);
1642
1643 buf = &bufs.head->buf;
1644 assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
1645
1646 ud.frame_recv_cb_called = 0;
1647
1648 rv = nghttp2_session_mem_recv2(session, buf->pos, nghttp2_buf_len(buf));
1649
1650 assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(buf), ==, rv);
1651 assert_int(1, ==, ud.frame_recv_cb_called);
1652
1653 stream = nghttp2_session_get_stream(session, 3);
1654
1655 assert_int32(99, ==, stream->weight);
1656 assert_int32(1, ==, stream->dep_prev->stream_id);
1657
1658 nghttp2_bufs_reset(&bufs);
1659
1660 /* With NGHTTP2_FLAG_PRIORITY, but cut last 1 byte to make it
1661 invalid. */
1662 nvlen = ARRLEN(reqnv);
1663 nghttp2_nv_array_copy(&nva, reqnv, nvlen, mem);
1664
1665 nghttp2_priority_spec_init(&pri_spec, 0, 99, 0);
1666
1667 nghttp2_frame_headers_init(&frame.headers,
1668 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PRIORITY,
1669 5, NGHTTP2_HCAT_HEADERS, &pri_spec, nva, nvlen);
1670
1671 rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
1672
1673 assert_ptrdiff(0, ==, rv);
1674 assert_size(NGHTTP2_FRAME_HDLEN + 5, <, nghttp2_bufs_len(&bufs));
1675
1676 nghttp2_frame_headers_free(&frame.headers, mem);
1677
1678 buf = &bufs.head->buf;
1679 /* Make payload shorter than required length to store priority
1680 group */
1681 nghttp2_put_uint32be(buf->pos, (uint32_t)((4 << 8) + buf->pos[3]));
1682
1683 ud.frame_recv_cb_called = 0;
1684
1685 rv = nghttp2_session_mem_recv2(session, buf->pos, nghttp2_buf_len(buf));
1686
1687 assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(buf), ==, rv);
1688 assert_int(0, ==, ud.frame_recv_cb_called);
1689
1690 stream = nghttp2_session_get_stream(session, 5);
1691
1692 assert_null(stream);
1693
1694 item = nghttp2_session_get_next_ob_item(session);
1695 assert_not_null(item);
1696 assert_uint8(NGHTTP2_GOAWAY, ==, item->frame.hd.type);
1697 assert_uint32(NGHTTP2_FRAME_SIZE_ERROR, ==, item->frame.goaway.error_code);
1698
1699 nghttp2_bufs_reset(&bufs);
1700
1701 nghttp2_hd_deflate_free(&deflater);
1702 nghttp2_session_del(session);
1703
1704 /* Check dep_stream_id == stream_id */
1705 nghttp2_session_server_new(&session, &callbacks, &ud);
1706
1707 nghttp2_hd_deflate_init(&deflater, mem);
1708
1709 nvlen = ARRLEN(reqnv);
1710 nghttp2_nv_array_copy(&nva, reqnv, nvlen, mem);
1711
1712 nghttp2_priority_spec_init(&pri_spec, 1, 0, 0);
1713
1714 nghttp2_frame_headers_init(&frame.headers,
1715 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PRIORITY,
1716 1, NGHTTP2_HCAT_HEADERS, &pri_spec, nva, nvlen);
1717
1718 rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
1719
1720 assert_ptrdiff(0, ==, rv);
1721 assert_size(0, <, nghttp2_bufs_len(&bufs));
1722
1723 nghttp2_frame_headers_free(&frame.headers, mem);
1724
1725 buf = &bufs.head->buf;
1726 assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
1727
1728 ud.frame_recv_cb_called = 0;
1729
1730 rv = nghttp2_session_mem_recv2(session, buf->pos, nghttp2_buf_len(buf));
1731
1732 assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(buf), ==, rv);
1733 assert_int(0, ==, ud.frame_recv_cb_called);
1734
1735 stream = nghttp2_session_get_stream(session, 1);
1736
1737 assert_null(stream);
1738
1739 item = nghttp2_session_get_next_ob_item(session);
1740 assert_not_null(item);
1741 assert_uint8(NGHTTP2_GOAWAY, ==, item->frame.hd.type);
1742 assert_uint32(NGHTTP2_PROTOCOL_ERROR, ==, item->frame.goaway.error_code);
1743
1744 nghttp2_bufs_reset(&bufs);
1745
1746 nghttp2_bufs_free(&bufs);
1747 nghttp2_hd_deflate_free(&deflater);
1748 nghttp2_session_del(session);
1749 }
1750
test_nghttp2_session_recv_headers_with_padding(void)1751 void test_nghttp2_session_recv_headers_with_padding(void) {
1752 nghttp2_session *session;
1753 nghttp2_session_callbacks callbacks;
1754 nghttp2_bufs bufs;
1755 nghttp2_buf *buf;
1756 nghttp2_frame_hd hd;
1757 nghttp2_outbound_item *item;
1758 my_user_data ud;
1759 nghttp2_ssize rv;
1760
1761 frame_pack_bufs_init(&bufs);
1762
1763 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
1764 callbacks.on_frame_recv_callback = on_frame_recv_callback;
1765 callbacks.send_callback2 = null_send_callback;
1766
1767 /* HEADERS: Wrong padding length */
1768 nghttp2_session_server_new(&session, &callbacks, &ud);
1769 nghttp2_session_send(session);
1770
1771 nghttp2_frame_hd_init(
1772 &hd, 10, NGHTTP2_HEADERS,
1773 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PRIORITY | NGHTTP2_FLAG_PADDED, 1);
1774 buf = &bufs.head->buf;
1775 nghttp2_frame_pack_frame_hd(buf->last, &hd);
1776 buf->last += NGHTTP2_FRAME_HDLEN;
1777 /* padding is 6 bytes */
1778 *buf->last++ = 5;
1779 /* priority field */
1780 nghttp2_put_uint32be(buf->last, 3);
1781 buf->last += sizeof(uint32_t);
1782 *buf->last++ = 1;
1783 /* rest is garbage */
1784 memset(buf->last, 0, 4);
1785 buf->last += 4;
1786
1787 ud.frame_recv_cb_called = 0;
1788
1789 rv = nghttp2_session_mem_recv2(session, buf->pos, nghttp2_buf_len(buf));
1790
1791 assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(buf), ==, rv);
1792 assert_int(0, ==, ud.frame_recv_cb_called);
1793
1794 item = nghttp2_session_get_next_ob_item(session);
1795
1796 assert_not_null(item);
1797 assert_uint8(NGHTTP2_GOAWAY, ==, item->frame.hd.type);
1798
1799 nghttp2_bufs_reset(&bufs);
1800 nghttp2_session_del(session);
1801
1802 /* PUSH_PROMISE: Wrong padding length */
1803 nghttp2_session_client_new(&session, &callbacks, &ud);
1804 nghttp2_session_send(session);
1805
1806 open_sent_stream(session, 1);
1807
1808 nghttp2_frame_hd_init(&hd, 9, NGHTTP2_PUSH_PROMISE,
1809 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PADDED, 1);
1810 buf = &bufs.head->buf;
1811 nghttp2_frame_pack_frame_hd(buf->last, &hd);
1812 buf->last += NGHTTP2_FRAME_HDLEN;
1813 /* padding is 6 bytes */
1814 *buf->last++ = 5;
1815 /* promised stream ID field */
1816 nghttp2_put_uint32be(buf->last, 2);
1817 buf->last += sizeof(uint32_t);
1818 /* rest is garbage */
1819 memset(buf->last, 0, 4);
1820 buf->last += 4;
1821
1822 ud.frame_recv_cb_called = 0;
1823
1824 rv = nghttp2_session_mem_recv2(session, buf->pos, nghttp2_buf_len(buf));
1825
1826 assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(buf), ==, rv);
1827 assert_int(0, ==, ud.frame_recv_cb_called);
1828
1829 item = nghttp2_session_get_next_ob_item(session);
1830
1831 assert_not_null(item);
1832 assert_uint8(NGHTTP2_GOAWAY, ==, item->frame.hd.type);
1833
1834 nghttp2_bufs_free(&bufs);
1835 nghttp2_session_del(session);
1836 }
1837
response_on_begin_frame_callback(nghttp2_session * session,const nghttp2_frame_hd * hd,void * user_data)1838 static int response_on_begin_frame_callback(nghttp2_session *session,
1839 const nghttp2_frame_hd *hd,
1840 void *user_data) {
1841 int rv;
1842 (void)user_data;
1843
1844 if (hd->type != NGHTTP2_HEADERS) {
1845 return 0;
1846 }
1847
1848 rv = nghttp2_submit_response2(session, hd->stream_id, resnv, ARRLEN(resnv),
1849 NULL);
1850
1851 assert_int(0, ==, rv);
1852
1853 return 0;
1854 }
1855
test_nghttp2_session_recv_headers_early_response(void)1856 void test_nghttp2_session_recv_headers_early_response(void) {
1857 nghttp2_session *session;
1858 nghttp2_session_callbacks callbacks;
1859 nghttp2_bufs bufs;
1860 nghttp2_buf *buf;
1861 nghttp2_hd_deflater deflater;
1862 nghttp2_mem *mem;
1863 nghttp2_nv *nva;
1864 size_t nvlen;
1865 nghttp2_frame frame;
1866 nghttp2_ssize rv;
1867 nghttp2_stream *stream;
1868
1869 mem = nghttp2_mem_default();
1870 frame_pack_bufs_init(&bufs);
1871
1872 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
1873 callbacks.send_callback2 = null_send_callback;
1874 callbacks.on_begin_frame_callback = response_on_begin_frame_callback;
1875
1876 nghttp2_session_server_new(&session, &callbacks, NULL);
1877
1878 nghttp2_hd_deflate_init(&deflater, mem);
1879
1880 nvlen = ARRLEN(reqnv);
1881 nghttp2_nv_array_copy(&nva, reqnv, nvlen, mem);
1882 nghttp2_frame_headers_init(&frame.headers,
1883 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM,
1884 1, NGHTTP2_HCAT_REQUEST, NULL, nva, nvlen);
1885
1886 rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
1887
1888 assert_ptrdiff(0, ==, rv);
1889
1890 nghttp2_frame_headers_free(&frame.headers, mem);
1891
1892 buf = &bufs.head->buf;
1893
1894 /* Only receive 9 bytes headers, and invoke
1895 on_begin_frame_callback */
1896 rv = nghttp2_session_mem_recv2(session, buf->pos, 9);
1897
1898 assert_ptrdiff(9, ==, rv);
1899
1900 rv = nghttp2_session_send(session);
1901
1902 assert_ptrdiff(0, ==, rv);
1903
1904 rv =
1905 nghttp2_session_mem_recv2(session, buf->pos + 9, nghttp2_buf_len(buf) - 9);
1906
1907 assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(buf) - 9, ==, rv);
1908
1909 stream = nghttp2_session_get_stream_raw(session, 1);
1910
1911 assert_true(stream->flags & NGHTTP2_STREAM_FLAG_CLOSED);
1912
1913 nghttp2_hd_deflate_free(&deflater);
1914 nghttp2_session_del(session);
1915 nghttp2_bufs_free(&bufs);
1916 }
1917
test_nghttp2_session_recv_headers_for_closed_stream(void)1918 void test_nghttp2_session_recv_headers_for_closed_stream(void) {
1919 nghttp2_session *session;
1920 nghttp2_session_callbacks callbacks;
1921 nghttp2_nv *nva;
1922 size_t nvlen;
1923 nghttp2_frame frame;
1924 nghttp2_bufs bufs;
1925 nghttp2_buf *buf;
1926 nghttp2_ssize rv;
1927 my_user_data ud;
1928 nghttp2_hd_deflater deflater;
1929 nghttp2_stream *stream;
1930 nghttp2_mem *mem;
1931 const uint8_t *data;
1932
1933 mem = nghttp2_mem_default();
1934 frame_pack_bufs_init(&bufs);
1935
1936 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
1937 callbacks.on_frame_recv_callback = on_frame_recv_callback;
1938 callbacks.on_header_callback = on_header_callback;
1939
1940 nghttp2_session_server_new(&session, &callbacks, &ud);
1941
1942 nghttp2_hd_deflate_init(&deflater, mem);
1943
1944 /* Make sure that on_header callback never be invoked for closed
1945 stream */
1946 nvlen = ARRLEN(reqnv);
1947 nghttp2_nv_array_copy(&nva, reqnv, nvlen, mem);
1948
1949 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 1,
1950 NGHTTP2_HCAT_HEADERS, NULL, nva, nvlen);
1951
1952 rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
1953
1954 assert_ptrdiff(0, ==, rv);
1955 assert_size(0, <, nghttp2_bufs_len(&bufs));
1956
1957 nghttp2_frame_headers_free(&frame.headers, mem);
1958
1959 buf = &bufs.head->buf;
1960 assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
1961
1962 ud.header_cb_called = 0;
1963 ud.frame_recv_cb_called = 0;
1964
1965 rv = nghttp2_session_mem_recv2(session, buf->pos, NGHTTP2_FRAME_HDLEN);
1966
1967 assert_ptrdiff(NGHTTP2_FRAME_HDLEN, ==, rv);
1968 assert_int(0, ==, ud.header_cb_called);
1969 assert_int(0, ==, ud.frame_recv_cb_called);
1970
1971 stream = nghttp2_session_get_stream(session, 1);
1972
1973 assert_not_null(stream);
1974
1975 rv =
1976 nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, 1, NGHTTP2_NO_ERROR);
1977
1978 assert_ptrdiff(0, ==, rv);
1979
1980 rv = nghttp2_session_mem_send2(session, &data);
1981
1982 assert_ptrdiff(0, <, rv);
1983
1984 stream = nghttp2_session_get_stream(session, 1);
1985
1986 assert_null(stream);
1987
1988 ud.header_cb_called = 0;
1989 ud.frame_recv_cb_called = 0;
1990
1991 rv = nghttp2_session_mem_recv2(session, buf->pos + NGHTTP2_FRAME_HDLEN,
1992 nghttp2_buf_len(buf) - NGHTTP2_FRAME_HDLEN);
1993
1994 assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(buf) - NGHTTP2_FRAME_HDLEN, ==,
1995 rv);
1996 assert_int(0, ==, ud.header_cb_called);
1997 assert_int(0, ==, ud.frame_recv_cb_called);
1998
1999 nghttp2_bufs_free(&bufs);
2000 nghttp2_hd_deflate_free(&deflater);
2001 nghttp2_session_del(session);
2002 }
2003
test_nghttp2_session_recv_headers_with_extpri(void)2004 void test_nghttp2_session_recv_headers_with_extpri(void) {
2005 nghttp2_session *session;
2006 nghttp2_session_callbacks callbacks;
2007 nghttp2_nv *nva;
2008 size_t nvlen;
2009 nghttp2_frame frame;
2010 nghttp2_bufs bufs;
2011 nghttp2_buf *buf;
2012 nghttp2_ssize rv;
2013 nghttp2_hd_deflater deflater;
2014 nghttp2_stream *stream;
2015 nghttp2_mem *mem;
2016 const nghttp2_nv extpri_reqnv[] = {
2017 MAKE_NV(":method", "GET"), MAKE_NV(":path", "/"),
2018 MAKE_NV(":scheme", "https"), MAKE_NV(":authority", "localhost"),
2019 MAKE_NV("priority", "i,u=2"),
2020 };
2021 nghttp2_settings_entry iv;
2022
2023 mem = nghttp2_mem_default();
2024 frame_pack_bufs_init(&bufs);
2025
2026 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
2027
2028 nghttp2_session_server_new(&session, &callbacks, NULL);
2029
2030 iv.settings_id = NGHTTP2_SETTINGS_NO_RFC7540_PRIORITIES;
2031 iv.value = 1;
2032
2033 nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, &iv, 1);
2034
2035 nghttp2_hd_deflate_init(&deflater, mem);
2036
2037 nvlen = ARRLEN(extpri_reqnv);
2038 nghttp2_nv_array_copy(&nva, extpri_reqnv, nvlen, mem);
2039
2040 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 1,
2041 NGHTTP2_HCAT_HEADERS, NULL, nva, nvlen);
2042
2043 rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
2044
2045 assert_ptrdiff(0, ==, rv);
2046 assert_size(0, <, nghttp2_bufs_len(&bufs));
2047
2048 nghttp2_frame_headers_free(&frame.headers, mem);
2049
2050 buf = &bufs.head->buf;
2051 assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
2052
2053 rv = nghttp2_session_mem_recv2(session, buf->pos, nghttp2_buf_len(buf));
2054
2055 stream = nghttp2_session_get_stream(session, 1);
2056
2057 assert_uint32(2, ==, nghttp2_extpri_uint8_urgency(stream->extpri));
2058 assert_true(nghttp2_extpri_uint8_inc(stream->extpri));
2059
2060 nghttp2_hd_deflate_free(&deflater);
2061 nghttp2_session_del(session);
2062
2063 nghttp2_bufs_reset(&bufs);
2064
2065 /* Client should ignore priority header field included in
2066 PUSH_PROMISE. */
2067 nghttp2_session_client_new(&session, &callbacks, NULL);
2068
2069 nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, &iv, 1);
2070
2071 open_sent_stream(session, 1);
2072
2073 nghttp2_hd_deflate_init(&deflater, mem);
2074
2075 nvlen = ARRLEN(extpri_reqnv);
2076 nghttp2_nv_array_copy(&nva, extpri_reqnv, nvlen, mem);
2077
2078 nghttp2_frame_push_promise_init(&frame.push_promise, NGHTTP2_FLAG_END_HEADERS,
2079 1, 2, nva, nvlen);
2080
2081 rv = nghttp2_frame_pack_push_promise(&bufs, &frame.push_promise, &deflater);
2082
2083 assert_ptrdiff(0, ==, rv);
2084 assert_size(0, <, nghttp2_bufs_len(&bufs));
2085
2086 nghttp2_frame_push_promise_free(&frame.push_promise, mem);
2087
2088 buf = &bufs.head->buf;
2089 assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
2090
2091 rv = nghttp2_session_mem_recv2(session, buf->pos, nghttp2_buf_len(buf));
2092
2093 stream = nghttp2_session_get_stream(session, 2);
2094
2095 assert_uint32(NGHTTP2_EXTPRI_DEFAULT_URGENCY, ==,
2096 nghttp2_extpri_uint8_urgency(stream->http_extpri));
2097 assert_uint32(NGHTTP2_EXTPRI_DEFAULT_URGENCY, ==,
2098 nghttp2_extpri_uint8_urgency(stream->extpri));
2099
2100 nghttp2_hd_deflate_free(&deflater);
2101 nghttp2_session_del(session);
2102 nghttp2_bufs_free(&bufs);
2103 }
2104
test_nghttp2_session_server_recv_push_response(void)2105 void test_nghttp2_session_server_recv_push_response(void) {
2106 nghttp2_session *session;
2107 nghttp2_session_callbacks callbacks;
2108 nghttp2_bufs bufs;
2109 nghttp2_buf *buf;
2110 nghttp2_ssize rv;
2111 my_user_data ud;
2112 nghttp2_mem *mem;
2113 nghttp2_frame frame;
2114 nghttp2_hd_deflater deflater;
2115 nghttp2_nv *nva;
2116 size_t nvlen;
2117
2118 mem = nghttp2_mem_default();
2119 frame_pack_bufs_init(&bufs);
2120
2121 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
2122 callbacks.on_invalid_frame_recv_callback = on_invalid_frame_recv_callback;
2123
2124 nghttp2_session_server_new(&session, &callbacks, &ud);
2125
2126 nghttp2_hd_deflate_init(&deflater, mem);
2127
2128 open_sent_stream2(session, 2, NGHTTP2_STREAM_RESERVED);
2129
2130 nvlen = ARRLEN(resnv);
2131 nghttp2_nv_array_copy(&nva, resnv, nvlen, mem);
2132 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 2,
2133 NGHTTP2_HCAT_HEADERS, &pri_spec_default, nva,
2134 nvlen);
2135 rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
2136
2137 assert_ptrdiff(0, ==, rv);
2138 assert_size(0, <, nghttp2_bufs_len(&bufs));
2139
2140 nghttp2_frame_headers_free(&frame.headers, mem);
2141
2142 buf = &bufs.head->buf;
2143
2144 ud.invalid_frame_recv_cb_called = 0;
2145
2146 rv = nghttp2_session_mem_recv2(session, buf->pos, nghttp2_buf_len(buf));
2147
2148 assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(buf), ==, rv);
2149 assert_int(1, ==, ud.invalid_frame_recv_cb_called);
2150
2151 nghttp2_bufs_free(&bufs);
2152 nghttp2_hd_deflate_free(&deflater);
2153 nghttp2_session_del(session);
2154 }
2155
test_nghttp2_session_recv_premature_headers(void)2156 void test_nghttp2_session_recv_premature_headers(void) {
2157 nghttp2_session *session;
2158 nghttp2_session_callbacks callbacks;
2159 nghttp2_bufs bufs;
2160 nghttp2_buf *buf;
2161 nghttp2_ssize rv;
2162 my_user_data ud;
2163 nghttp2_hd_deflater deflater;
2164 nghttp2_outbound_item *item;
2165 nghttp2_mem *mem;
2166 uint32_t payloadlen;
2167
2168 mem = nghttp2_mem_default();
2169 frame_pack_bufs_init(&bufs);
2170
2171 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
2172 callbacks.send_callback2 = null_send_callback;
2173
2174 nghttp2_session_server_new(&session, &callbacks, &ud);
2175
2176 nghttp2_hd_deflate_init(&deflater, mem);
2177
2178 pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, reqnv,
2179 ARRLEN(reqnv), mem);
2180
2181 buf = &bufs.head->buf;
2182 /* Intentionally feed payload cutting last 1 byte off */
2183 payloadlen = nghttp2_get_uint32(buf->pos) >> 8;
2184 nghttp2_put_uint32be(buf->pos, ((payloadlen - 1) << 8) + buf->pos[3]);
2185 rv = nghttp2_session_mem_recv2(session, buf->pos, nghttp2_buf_len(buf) - 1);
2186
2187 assert_ptrdiff((nghttp2_ssize)(nghttp2_buf_len(buf) - 1), ==, rv);
2188
2189 item = nghttp2_session_get_next_ob_item(session);
2190
2191 assert_not_null(item);
2192 assert_uint8(NGHTTP2_RST_STREAM, ==, item->frame.hd.type);
2193 assert_uint32(NGHTTP2_COMPRESSION_ERROR, ==,
2194 item->frame.rst_stream.error_code);
2195 assert_int32(1, ==, item->frame.hd.stream_id);
2196 assert_int(0, ==, nghttp2_session_send(session));
2197
2198 nghttp2_bufs_reset(&bufs);
2199 nghttp2_hd_deflate_free(&deflater);
2200 nghttp2_session_del(session);
2201
2202 /* Test for PUSH_PROMISE */
2203 nghttp2_session_client_new(&session, &callbacks, &ud);
2204 nghttp2_hd_deflate_init(&deflater, mem);
2205
2206 open_sent_stream3(session, 1, NGHTTP2_STREAM_FLAG_NONE, &pri_spec_default,
2207 NGHTTP2_STREAM_OPENING, NULL);
2208
2209 rv = pack_push_promise(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, 2,
2210 reqnv, ARRLEN(reqnv), mem);
2211
2212 assert_ptrdiff(0, ==, rv);
2213
2214 buf = &bufs.head->buf;
2215 payloadlen = nghttp2_get_uint32(buf->pos) >> 8;
2216 /* Intentionally feed payload cutting last 1 byte off */
2217 nghttp2_put_uint32be(buf->pos, ((payloadlen - 1) << 8) + buf->pos[3]);
2218 rv = nghttp2_session_mem_recv2(session, buf->pos, nghttp2_buf_len(buf) - 1);
2219
2220 assert_ptrdiff((nghttp2_ssize)(nghttp2_buf_len(buf) - 1), ==, rv);
2221
2222 item = nghttp2_session_get_next_ob_item(session);
2223
2224 assert_not_null(item);
2225 assert_uint8(NGHTTP2_RST_STREAM, ==, item->frame.hd.type);
2226 assert_uint32(NGHTTP2_COMPRESSION_ERROR, ==,
2227 item->frame.rst_stream.error_code);
2228 assert_int32(2, ==, item->frame.hd.stream_id);
2229 assert_int(0, ==, nghttp2_session_send(session));
2230
2231 nghttp2_hd_deflate_free(&deflater);
2232 nghttp2_session_del(session);
2233 nghttp2_bufs_free(&bufs);
2234 }
2235
test_nghttp2_session_recv_unknown_frame(void)2236 void test_nghttp2_session_recv_unknown_frame(void) {
2237 nghttp2_session *session;
2238 nghttp2_session_callbacks callbacks;
2239 my_user_data ud;
2240 uint8_t data[16384];
2241 size_t datalen;
2242 nghttp2_frame_hd hd;
2243 nghttp2_ssize rv;
2244
2245 nghttp2_frame_hd_init(&hd, 16000, 99, NGHTTP2_FLAG_NONE, 0);
2246
2247 nghttp2_frame_pack_frame_hd(data, &hd);
2248 datalen = NGHTTP2_FRAME_HDLEN + hd.length;
2249
2250 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
2251 callbacks.on_frame_recv_callback = on_frame_recv_callback;
2252
2253 nghttp2_session_server_new(&session, &callbacks, &ud);
2254
2255 ud.frame_recv_cb_called = 0;
2256
2257 /* Unknown frame must be ignored */
2258 rv = nghttp2_session_mem_recv2(session, data, datalen);
2259
2260 assert_ptrdiff(rv, ==, (nghttp2_ssize)datalen);
2261 assert_int(0, ==, ud.frame_recv_cb_called);
2262 assert_null(nghttp2_session_get_next_ob_item(session));
2263
2264 nghttp2_session_del(session);
2265 }
2266
test_nghttp2_session_recv_unexpected_continuation(void)2267 void test_nghttp2_session_recv_unexpected_continuation(void) {
2268 nghttp2_session *session;
2269 nghttp2_session_callbacks callbacks;
2270 my_user_data ud;
2271 uint8_t data[16384];
2272 size_t datalen;
2273 nghttp2_frame_hd hd;
2274 nghttp2_ssize rv;
2275 nghttp2_outbound_item *item;
2276
2277 nghttp2_frame_hd_init(&hd, 16000, NGHTTP2_CONTINUATION,
2278 NGHTTP2_FLAG_END_HEADERS, 1);
2279
2280 nghttp2_frame_pack_frame_hd(data, &hd);
2281 datalen = NGHTTP2_FRAME_HDLEN + hd.length;
2282
2283 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
2284 callbacks.on_frame_recv_callback = on_frame_recv_callback;
2285
2286 nghttp2_session_server_new(&session, &callbacks, &ud);
2287
2288 open_recv_stream(session, 1);
2289
2290 ud.frame_recv_cb_called = 0;
2291
2292 /* unexpected CONTINUATION must be treated as connection error */
2293 rv = nghttp2_session_mem_recv2(session, data, datalen);
2294
2295 assert_ptrdiff(rv, ==, (nghttp2_ssize)datalen);
2296 assert_int(0, ==, ud.frame_recv_cb_called);
2297
2298 item = nghttp2_session_get_next_ob_item(session);
2299
2300 assert_uint8(NGHTTP2_GOAWAY, ==, item->frame.hd.type);
2301
2302 nghttp2_session_del(session);
2303 }
2304
test_nghttp2_session_recv_settings_header_table_size(void)2305 void test_nghttp2_session_recv_settings_header_table_size(void) {
2306 nghttp2_session *session;
2307 nghttp2_session_callbacks callbacks;
2308 nghttp2_frame frame;
2309 nghttp2_bufs bufs;
2310 nghttp2_buf *buf;
2311 nghttp2_ssize rv;
2312 my_user_data ud;
2313 nghttp2_settings_entry iv[3];
2314 nghttp2_nv nv = MAKE_NV(":authority", "example.org");
2315 nghttp2_mem *mem;
2316
2317 mem = nghttp2_mem_default();
2318 frame_pack_bufs_init(&bufs);
2319
2320 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
2321 callbacks.on_frame_recv_callback = on_frame_recv_callback;
2322 callbacks.send_callback2 = null_send_callback;
2323
2324 nghttp2_session_client_new(&session, &callbacks, &ud);
2325
2326 iv[0].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
2327 iv[0].value = 3000;
2328
2329 iv[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
2330 iv[1].value = 16384;
2331
2332 nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE, dup_iv(iv, 2),
2333 2);
2334
2335 rv = nghttp2_frame_pack_settings(&bufs, &frame.settings);
2336
2337 assert_ptrdiff(0, ==, rv);
2338 assert_size(0, <, nghttp2_bufs_len(&bufs));
2339
2340 nghttp2_frame_settings_free(&frame.settings, mem);
2341
2342 buf = &bufs.head->buf;
2343 assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
2344
2345 ud.frame_recv_cb_called = 0;
2346
2347 rv = nghttp2_session_mem_recv2(session, buf->pos, nghttp2_buf_len(buf));
2348
2349 assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(buf), ==, rv);
2350 assert_int(1, ==, ud.frame_recv_cb_called);
2351
2352 assert_uint32(3000, ==, session->remote_settings.header_table_size);
2353 assert_uint32(16384, ==, session->remote_settings.initial_window_size);
2354
2355 nghttp2_bufs_reset(&bufs);
2356
2357 /* 2 SETTINGS_HEADER_TABLE_SIZE */
2358 iv[0].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
2359 iv[0].value = 3001;
2360
2361 iv[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
2362 iv[1].value = 16383;
2363
2364 iv[2].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
2365 iv[2].value = 3001;
2366
2367 nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE, dup_iv(iv, 3),
2368 3);
2369
2370 rv = nghttp2_frame_pack_settings(&bufs, &frame.settings);
2371
2372 assert_ptrdiff(0, ==, rv);
2373 assert_size(0, <, nghttp2_bufs_len(&bufs));
2374
2375 nghttp2_frame_settings_free(&frame.settings, mem);
2376
2377 buf = &bufs.head->buf;
2378 assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
2379
2380 ud.frame_recv_cb_called = 0;
2381
2382 rv = nghttp2_session_mem_recv2(session, buf->pos, nghttp2_buf_len(buf));
2383
2384 assert_ptrdiff((nghttp2_ssize)(nghttp2_buf_len(buf)), ==, rv);
2385 assert_int(1, ==, ud.frame_recv_cb_called);
2386
2387 assert_uint32(3001, ==, session->remote_settings.header_table_size);
2388 assert_uint32(16383, ==, session->remote_settings.initial_window_size);
2389
2390 nghttp2_bufs_reset(&bufs);
2391
2392 /* 2 SETTINGS_HEADER_TABLE_SIZE; first entry clears dynamic header
2393 table. */
2394
2395 nghttp2_submit_request2(session, NULL, &nv, 1, NULL, NULL);
2396 nghttp2_session_send(session);
2397
2398 assert_size(0, <, session->hd_deflater.ctx.hd_table.len);
2399
2400 iv[0].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
2401 iv[0].value = 0;
2402
2403 iv[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
2404 iv[1].value = 16382;
2405
2406 iv[2].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
2407 iv[2].value = 4096;
2408
2409 nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE, dup_iv(iv, 3),
2410 3);
2411
2412 rv = nghttp2_frame_pack_settings(&bufs, &frame.settings);
2413
2414 assert_ptrdiff(0, ==, rv);
2415 assert_size(0, <, nghttp2_bufs_len(&bufs));
2416
2417 nghttp2_frame_settings_free(&frame.settings, mem);
2418
2419 buf = &bufs.head->buf;
2420 assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
2421
2422 ud.frame_recv_cb_called = 0;
2423
2424 rv = nghttp2_session_mem_recv2(session, buf->pos, nghttp2_buf_len(buf));
2425
2426 assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(buf), ==, rv);
2427 assert_int(1, ==, ud.frame_recv_cb_called);
2428
2429 assert_uint32(4096, ==, session->remote_settings.header_table_size);
2430 assert_uint32(16382, ==, session->remote_settings.initial_window_size);
2431 assert_size(0, ==, session->hd_deflater.ctx.hd_table.len);
2432
2433 nghttp2_bufs_reset(&bufs);
2434
2435 /* 2 SETTINGS_HEADER_TABLE_SIZE; second entry clears dynamic header
2436 table. */
2437
2438 nghttp2_submit_request2(session, NULL, &nv, 1, NULL, NULL);
2439 nghttp2_session_send(session);
2440
2441 assert_size(0, <, session->hd_deflater.ctx.hd_table.len);
2442
2443 iv[0].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
2444 iv[0].value = 3000;
2445
2446 iv[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
2447 iv[1].value = 16381;
2448
2449 iv[2].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
2450 iv[2].value = 0;
2451
2452 nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE, dup_iv(iv, 3),
2453 3);
2454
2455 rv = nghttp2_frame_pack_settings(&bufs, &frame.settings);
2456
2457 assert_ptrdiff(0, ==, rv);
2458 assert_size(0, <, nghttp2_bufs_len(&bufs));
2459
2460 nghttp2_frame_settings_free(&frame.settings, mem);
2461
2462 buf = &bufs.head->buf;
2463 assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
2464
2465 ud.frame_recv_cb_called = 0;
2466
2467 rv = nghttp2_session_mem_recv2(session, buf->pos, nghttp2_buf_len(buf));
2468
2469 assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(buf), ==, rv);
2470 assert_int(1, ==, ud.frame_recv_cb_called);
2471
2472 assert_uint32(0, ==, session->remote_settings.header_table_size);
2473 assert_uint32(16381, ==, session->remote_settings.initial_window_size);
2474 assert_size(0, ==, session->hd_deflater.ctx.hd_table.len);
2475
2476 nghttp2_bufs_reset(&bufs);
2477
2478 nghttp2_bufs_free(&bufs);
2479 nghttp2_session_del(session);
2480 }
2481
test_nghttp2_session_recv_too_large_frame_length(void)2482 void test_nghttp2_session_recv_too_large_frame_length(void) {
2483 nghttp2_session *session;
2484 nghttp2_session_callbacks callbacks;
2485 uint8_t buf[NGHTTP2_FRAME_HDLEN];
2486 nghttp2_outbound_item *item;
2487 nghttp2_frame_hd hd;
2488
2489 /* Initial max frame size is NGHTTP2_MAX_FRAME_SIZE_MIN */
2490 nghttp2_frame_hd_init(&hd, NGHTTP2_MAX_FRAME_SIZE_MIN + 1, NGHTTP2_HEADERS,
2491 NGHTTP2_FLAG_NONE, 1);
2492
2493 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
2494
2495 nghttp2_session_server_new(&session, &callbacks, NULL);
2496
2497 nghttp2_frame_pack_frame_hd(buf, &hd);
2498
2499 assert_ptrdiff(sizeof(buf), ==,
2500 nghttp2_session_mem_recv2(session, buf, sizeof(buf)));
2501
2502 item = nghttp2_session_get_next_ob_item(session);
2503
2504 assert_not_null(item);
2505 assert_uint8(NGHTTP2_GOAWAY, ==, item->frame.hd.type);
2506
2507 nghttp2_session_del(session);
2508 }
2509
test_nghttp2_session_recv_extension(void)2510 void test_nghttp2_session_recv_extension(void) {
2511 nghttp2_session *session;
2512 nghttp2_session_callbacks callbacks;
2513 my_user_data ud;
2514 nghttp2_buf buf;
2515 nghttp2_frame_hd hd;
2516 nghttp2_mem *mem;
2517 const char data[] = "Hello World!";
2518 nghttp2_ssize rv;
2519 nghttp2_option *option;
2520
2521 mem = nghttp2_mem_default();
2522
2523 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
2524
2525 callbacks.on_extension_chunk_recv_callback = on_extension_chunk_recv_callback;
2526 callbacks.unpack_extension_callback = unpack_extension_callback;
2527 callbacks.on_frame_recv_callback = on_frame_recv_callback;
2528
2529 nghttp2_option_new(&option);
2530 nghttp2_option_set_user_recv_extension_type(option, 111);
2531
2532 nghttp2_buf_init2(&ud.scratchbuf, 4096, mem);
2533 nghttp2_buf_init2(&buf, 4096, mem);
2534
2535 nghttp2_frame_hd_init(&hd, sizeof(data), 111, 0xab, 1000000007);
2536 nghttp2_frame_pack_frame_hd(buf.last, &hd);
2537 buf.last += NGHTTP2_FRAME_HDLEN;
2538 buf.last = nghttp2_cpymem(buf.last, data, sizeof(data));
2539
2540 nghttp2_session_client_new2(&session, &callbacks, &ud, option);
2541
2542 nghttp2_frame_hd_init(&ud.recv_frame_hd, 0, 0, 0, 0);
2543 rv = nghttp2_session_mem_recv2(session, buf.pos, nghttp2_buf_len(&buf));
2544
2545 assert_size(NGHTTP2_FRAME_HDLEN + hd.length, ==, (size_t)rv);
2546 assert_uint8(111, ==, ud.recv_frame_hd.type);
2547 assert_uint8(0xab, ==, ud.recv_frame_hd.flags);
2548 assert_int32(1000000007, ==, ud.recv_frame_hd.stream_id);
2549 assert_memory_equal(sizeof(data), data, ud.scratchbuf.pos);
2550
2551 nghttp2_session_del(session);
2552
2553 /* cancel in on_extension_chunk_recv_callback */
2554 nghttp2_buf_reset(&ud.scratchbuf);
2555
2556 callbacks.on_extension_chunk_recv_callback =
2557 cancel_on_extension_chunk_recv_callback;
2558
2559 nghttp2_session_server_new2(&session, &callbacks, &ud, option);
2560
2561 ud.frame_recv_cb_called = 0;
2562 rv = nghttp2_session_mem_recv2(session, buf.pos, nghttp2_buf_len(&buf));
2563
2564 assert_size(NGHTTP2_FRAME_HDLEN + hd.length, ==, (size_t)rv);
2565 assert_int(0, ==, ud.frame_recv_cb_called);
2566
2567 nghttp2_session_del(session);
2568
2569 /* cancel in unpack_extension_callback */
2570 nghttp2_buf_reset(&ud.scratchbuf);
2571
2572 callbacks.on_extension_chunk_recv_callback = on_extension_chunk_recv_callback;
2573 callbacks.unpack_extension_callback = cancel_unpack_extension_callback;
2574
2575 nghttp2_session_server_new2(&session, &callbacks, &ud, option);
2576
2577 ud.frame_recv_cb_called = 0;
2578 rv = nghttp2_session_mem_recv2(session, buf.pos, nghttp2_buf_len(&buf));
2579
2580 assert_size(NGHTTP2_FRAME_HDLEN + hd.length, ==, (size_t)rv);
2581 assert_int(0, ==, ud.frame_recv_cb_called);
2582
2583 nghttp2_session_del(session);
2584
2585 nghttp2_buf_free(&buf, mem);
2586 nghttp2_buf_free(&ud.scratchbuf, mem);
2587
2588 nghttp2_option_del(option);
2589 }
2590
test_nghttp2_session_recv_altsvc(void)2591 void test_nghttp2_session_recv_altsvc(void) {
2592 nghttp2_session *session;
2593 nghttp2_session_callbacks callbacks;
2594 my_user_data ud;
2595 nghttp2_buf buf;
2596 nghttp2_frame_hd hd;
2597 nghttp2_mem *mem;
2598 nghttp2_ssize rv;
2599 nghttp2_option *option;
2600 static const uint8_t origin[] = "nghttp2.org";
2601 static const uint8_t field_value[] = "h2=\":443\"";
2602
2603 mem = nghttp2_mem_default();
2604
2605 nghttp2_buf_init2(&buf, NGHTTP2_FRAME_HDLEN + NGHTTP2_MAX_FRAME_SIZE_MIN,
2606 mem);
2607
2608 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
2609
2610 callbacks.on_frame_recv_callback = on_frame_recv_callback;
2611 callbacks.on_invalid_frame_recv_callback = on_invalid_frame_recv_callback;
2612
2613 nghttp2_option_new(&option);
2614 nghttp2_option_set_builtin_recv_extension_type(option, NGHTTP2_ALTSVC);
2615
2616 nghttp2_session_client_new2(&session, &callbacks, &ud, option);
2617
2618 nghttp2_frame_hd_init(&hd, 2 + sizeof(origin) - 1 + sizeof(field_value) - 1,
2619 NGHTTP2_ALTSVC, NGHTTP2_FLAG_NONE, 0);
2620 nghttp2_frame_pack_frame_hd(buf.last, &hd);
2621 buf.last += NGHTTP2_FRAME_HDLEN;
2622 nghttp2_put_uint16be(buf.last, sizeof(origin) - 1);
2623 buf.last += 2;
2624 buf.last = nghttp2_cpymem(buf.last, origin, sizeof(origin) - 1);
2625 buf.last = nghttp2_cpymem(buf.last, field_value, sizeof(field_value) - 1);
2626
2627 ud.frame_recv_cb_called = 0;
2628 rv = nghttp2_session_mem_recv2(session, buf.pos, nghttp2_buf_len(&buf));
2629
2630 assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(&buf), ==, rv);
2631 assert_int(1, ==, ud.frame_recv_cb_called);
2632 assert_uint8(NGHTTP2_ALTSVC, ==, ud.recv_frame_hd.type);
2633 assert_uint8(NGHTTP2_FLAG_NONE, ==, ud.recv_frame_hd.flags);
2634 assert_int32(0, ==, ud.recv_frame_hd.stream_id);
2635
2636 nghttp2_session_del(session);
2637
2638 /* size of origin is larger than frame length */
2639 nghttp2_buf_reset(&buf);
2640
2641 nghttp2_session_client_new2(&session, &callbacks, &ud, option);
2642
2643 nghttp2_frame_hd_init(&hd, 2 + sizeof(origin) - 1 - 1, NGHTTP2_ALTSVC,
2644 NGHTTP2_FLAG_NONE, 0);
2645 nghttp2_frame_pack_frame_hd(buf.last, &hd);
2646 buf.last += NGHTTP2_FRAME_HDLEN;
2647 nghttp2_put_uint16be(buf.last, sizeof(origin) - 1);
2648 buf.last += 2;
2649 buf.last = nghttp2_cpymem(buf.last, origin, sizeof(origin) - 1 - 1);
2650
2651 ud.frame_recv_cb_called = 0;
2652 rv = nghttp2_session_mem_recv2(session, buf.pos, nghttp2_buf_len(&buf));
2653
2654 assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(&buf), ==, rv);
2655 assert_int(0, ==, ud.frame_recv_cb_called);
2656
2657 nghttp2_session_del(session);
2658
2659 /* zero-length value */
2660 nghttp2_buf_reset(&buf);
2661
2662 nghttp2_session_client_new2(&session, &callbacks, &ud, option);
2663
2664 nghttp2_frame_hd_init(&hd, 2 + sizeof(origin) - 1, NGHTTP2_ALTSVC,
2665 NGHTTP2_FLAG_NONE, 0);
2666 nghttp2_frame_pack_frame_hd(buf.last, &hd);
2667 buf.last += NGHTTP2_FRAME_HDLEN;
2668 nghttp2_put_uint16be(buf.last, sizeof(origin) - 1);
2669 buf.last += 2;
2670 buf.last = nghttp2_cpymem(buf.last, origin, sizeof(origin) - 1);
2671
2672 ud.invalid_frame_recv_cb_called = 0;
2673 rv = nghttp2_session_mem_recv2(session, buf.pos, nghttp2_buf_len(&buf));
2674
2675 assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(&buf), ==, rv);
2676 assert_int(1, ==, ud.invalid_frame_recv_cb_called);
2677
2678 nghttp2_session_del(session);
2679
2680 /* non-empty origin to a stream other than 0 */
2681 nghttp2_buf_reset(&buf);
2682
2683 nghttp2_session_client_new2(&session, &callbacks, &ud, option);
2684
2685 open_sent_stream(session, 1);
2686
2687 nghttp2_frame_hd_init(&hd, 2 + sizeof(origin) - 1 + sizeof(field_value) - 1,
2688 NGHTTP2_ALTSVC, NGHTTP2_FLAG_NONE, 1);
2689 nghttp2_frame_pack_frame_hd(buf.last, &hd);
2690 buf.last += NGHTTP2_FRAME_HDLEN;
2691 nghttp2_put_uint16be(buf.last, sizeof(origin) - 1);
2692 buf.last += 2;
2693 buf.last = nghttp2_cpymem(buf.last, origin, sizeof(origin) - 1);
2694 buf.last = nghttp2_cpymem(buf.last, field_value, sizeof(field_value) - 1);
2695
2696 ud.invalid_frame_recv_cb_called = 0;
2697 rv = nghttp2_session_mem_recv2(session, buf.pos, nghttp2_buf_len(&buf));
2698
2699 assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(&buf), ==, rv);
2700 assert_int(1, ==, ud.invalid_frame_recv_cb_called);
2701
2702 nghttp2_session_del(session);
2703
2704 /* empty origin to stream 0 */
2705 nghttp2_buf_reset(&buf);
2706
2707 nghttp2_session_client_new2(&session, &callbacks, &ud, option);
2708
2709 nghttp2_frame_hd_init(&hd, 2 + sizeof(field_value) - 1, NGHTTP2_ALTSVC,
2710 NGHTTP2_FLAG_NONE, 0);
2711 nghttp2_frame_pack_frame_hd(buf.last, &hd);
2712 buf.last += NGHTTP2_FRAME_HDLEN;
2713 nghttp2_put_uint16be(buf.last, 0);
2714 buf.last += 2;
2715 buf.last = nghttp2_cpymem(buf.last, field_value, sizeof(field_value) - 1);
2716
2717 ud.invalid_frame_recv_cb_called = 0;
2718 rv = nghttp2_session_mem_recv2(session, buf.pos, nghttp2_buf_len(&buf));
2719
2720 assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(&buf), ==, rv);
2721 assert_int(1, ==, ud.invalid_frame_recv_cb_called);
2722
2723 nghttp2_session_del(session);
2724
2725 /* send large frame (16KiB) */
2726 nghttp2_buf_reset(&buf);
2727
2728 nghttp2_session_client_new2(&session, &callbacks, &ud, option);
2729
2730 nghttp2_frame_hd_init(&hd, NGHTTP2_MAX_FRAME_SIZE_MIN, NGHTTP2_ALTSVC,
2731 NGHTTP2_FLAG_NONE, 0);
2732 nghttp2_frame_pack_frame_hd(buf.last, &hd);
2733 buf.last += NGHTTP2_FRAME_HDLEN;
2734 nghttp2_put_uint16be(buf.last, sizeof(origin) - 1);
2735 buf.last += 2;
2736 buf.last = nghttp2_cpymem(buf.last, origin, sizeof(origin) - 1);
2737 memset(buf.last, 0, nghttp2_buf_avail(&buf));
2738 buf.last += nghttp2_buf_avail(&buf);
2739
2740 ud.frame_recv_cb_called = 0;
2741 rv = nghttp2_session_mem_recv2(session, buf.pos, nghttp2_buf_len(&buf));
2742
2743 assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(&buf), ==, rv);
2744 assert_int(1, ==, ud.frame_recv_cb_called);
2745 assert_uint8(NGHTTP2_ALTSVC, ==, ud.recv_frame_hd.type);
2746 assert_size(NGHTTP2_MAX_FRAME_SIZE_MIN, ==, ud.recv_frame_hd.length);
2747
2748 nghttp2_session_del(session);
2749
2750 /* send too large frame */
2751 nghttp2_buf_reset(&buf);
2752
2753 nghttp2_session_client_new2(&session, &callbacks, &ud, option);
2754
2755 session->local_settings.max_frame_size = NGHTTP2_MAX_FRAME_SIZE_MIN - 1;
2756
2757 nghttp2_frame_hd_init(&hd, NGHTTP2_MAX_FRAME_SIZE_MIN + 1, NGHTTP2_ALTSVC,
2758 NGHTTP2_FLAG_NONE, 0);
2759 nghttp2_frame_pack_frame_hd(buf.last, &hd);
2760 buf.last += NGHTTP2_FRAME_HDLEN;
2761 nghttp2_put_uint16be(buf.last, sizeof(origin) - 1);
2762 buf.last += 2;
2763 buf.last = nghttp2_cpymem(buf.last, origin, sizeof(origin) - 1);
2764 memset(buf.last, 0, nghttp2_buf_avail(&buf));
2765 buf.last += nghttp2_buf_avail(&buf);
2766
2767 ud.frame_recv_cb_called = 0;
2768 rv = nghttp2_session_mem_recv2(session, buf.pos, nghttp2_buf_len(&buf));
2769
2770 assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(&buf), ==, rv);
2771 assert_int(0, ==, ud.frame_recv_cb_called);
2772
2773 nghttp2_session_del(session);
2774
2775 /* received by server */
2776 nghttp2_buf_reset(&buf);
2777
2778 nghttp2_session_server_new2(&session, &callbacks, &ud, option);
2779
2780 nghttp2_frame_hd_init(&hd, 2 + sizeof(origin) - 1 + sizeof(field_value) - 1,
2781 NGHTTP2_ALTSVC, NGHTTP2_FLAG_NONE, 0);
2782 nghttp2_frame_pack_frame_hd(buf.last, &hd);
2783 buf.last += NGHTTP2_FRAME_HDLEN;
2784 nghttp2_put_uint16be(buf.last, sizeof(origin) - 1);
2785 buf.last += 2;
2786 buf.last = nghttp2_cpymem(buf.last, origin, sizeof(origin) - 1);
2787 buf.last = nghttp2_cpymem(buf.last, field_value, sizeof(field_value) - 1);
2788
2789 ud.frame_recv_cb_called = 0;
2790 rv = nghttp2_session_mem_recv2(session, buf.pos, nghttp2_buf_len(&buf));
2791
2792 assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(&buf), ==, rv);
2793 assert_int(0, ==, ud.frame_recv_cb_called);
2794
2795 nghttp2_session_del(session);
2796
2797 nghttp2_buf_free(&buf, mem);
2798 nghttp2_option_del(option);
2799 }
2800
test_nghttp2_session_recv_origin(void)2801 void test_nghttp2_session_recv_origin(void) {
2802 nghttp2_session *session;
2803 nghttp2_session_callbacks callbacks;
2804 my_user_data ud;
2805 nghttp2_bufs bufs;
2806 nghttp2_ssize rv;
2807 nghttp2_option *option;
2808 nghttp2_extension frame;
2809 nghttp2_ext_origin origin;
2810 nghttp2_origin_entry ov;
2811 static const uint8_t nghttp2[] = "https://nghttp2.org";
2812
2813 frame_pack_bufs_init(&bufs);
2814
2815 frame.payload = &origin;
2816
2817 ov.origin = (uint8_t *)nghttp2;
2818 ov.origin_len = sizeof(nghttp2) - 1;
2819
2820 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
2821
2822 callbacks.on_frame_recv_callback = on_frame_recv_callback;
2823
2824 nghttp2_option_new(&option);
2825 nghttp2_option_set_builtin_recv_extension_type(option, NGHTTP2_ORIGIN);
2826
2827 nghttp2_session_client_new2(&session, &callbacks, &ud, option);
2828
2829 nghttp2_frame_origin_init(&frame, &ov, 1);
2830
2831 rv = nghttp2_frame_pack_origin(&bufs, &frame);
2832
2833 assert_ptrdiff(0, ==, rv);
2834
2835 ud.frame_recv_cb_called = 0;
2836 rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
2837 nghttp2_bufs_len(&bufs));
2838
2839 assert_ptrdiff((nghttp2_ssize)nghttp2_bufs_len(&bufs), ==, rv);
2840 assert_int(1, ==, ud.frame_recv_cb_called);
2841 assert_uint8(NGHTTP2_ORIGIN, ==, ud.recv_frame_hd.type);
2842 assert_uint8(NGHTTP2_FLAG_NONE, ==, ud.recv_frame_hd.flags);
2843 assert_int32(0, ==, ud.recv_frame_hd.stream_id);
2844
2845 nghttp2_session_del(session);
2846 nghttp2_bufs_reset(&bufs);
2847
2848 /* The length of origin is larger than payload length. */
2849 nghttp2_session_client_new2(&session, &callbacks, &ud, option);
2850
2851 nghttp2_frame_origin_init(&frame, &ov, 1);
2852 rv = nghttp2_frame_pack_origin(&bufs, &frame);
2853
2854 assert_ptrdiff(0, ==, rv);
2855
2856 nghttp2_put_uint16be(bufs.head->buf.pos + NGHTTP2_FRAME_HDLEN,
2857 (uint16_t)sizeof(nghttp2));
2858
2859 ud.frame_recv_cb_called = 0;
2860 rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
2861 nghttp2_bufs_len(&bufs));
2862
2863 assert_ptrdiff((nghttp2_ssize)nghttp2_bufs_len(&bufs), ==, rv);
2864 assert_int(0, ==, ud.frame_recv_cb_called);
2865
2866 nghttp2_session_del(session);
2867 nghttp2_bufs_reset(&bufs);
2868
2869 /* A frame should be ignored if it is sent to a stream other than
2870 stream 0. */
2871 nghttp2_session_client_new2(&session, &callbacks, &ud, option);
2872
2873 nghttp2_frame_origin_init(&frame, &ov, 1);
2874 frame.hd.stream_id = 1;
2875 rv = nghttp2_frame_pack_origin(&bufs, &frame);
2876
2877 assert_ptrdiff(0, ==, rv);
2878
2879 ud.frame_recv_cb_called = 0;
2880 rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
2881 nghttp2_bufs_len(&bufs));
2882
2883 assert_ptrdiff((nghttp2_ssize)nghttp2_bufs_len(&bufs), ==, rv);
2884 assert_int(0, ==, ud.frame_recv_cb_called);
2885
2886 nghttp2_session_del(session);
2887 nghttp2_bufs_reset(&bufs);
2888
2889 /* A frame should be ignored if the reserved flag is set */
2890 nghttp2_session_client_new2(&session, &callbacks, &ud, option);
2891
2892 nghttp2_frame_origin_init(&frame, &ov, 1);
2893 frame.hd.flags = 0xf0;
2894 rv = nghttp2_frame_pack_origin(&bufs, &frame);
2895
2896 assert_ptrdiff(0, ==, rv);
2897
2898 ud.frame_recv_cb_called = 0;
2899 rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
2900 nghttp2_bufs_len(&bufs));
2901
2902 assert_ptrdiff((nghttp2_ssize)nghttp2_bufs_len(&bufs), ==, rv);
2903 assert_int(0, ==, ud.frame_recv_cb_called);
2904
2905 nghttp2_session_del(session);
2906 nghttp2_bufs_reset(&bufs);
2907
2908 /* A frame should be ignored if it is received by a server. */
2909 nghttp2_session_server_new2(&session, &callbacks, &ud, option);
2910
2911 nghttp2_frame_origin_init(&frame, &ov, 1);
2912 rv = nghttp2_frame_pack_origin(&bufs, &frame);
2913
2914 assert_ptrdiff(0, ==, rv);
2915
2916 ud.frame_recv_cb_called = 0;
2917 rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
2918 nghttp2_bufs_len(&bufs));
2919
2920 assert_ptrdiff((nghttp2_ssize)nghttp2_bufs_len(&bufs), ==, rv);
2921 assert_int(0, ==, ud.frame_recv_cb_called);
2922
2923 nghttp2_session_del(session);
2924 nghttp2_bufs_reset(&bufs);
2925
2926 /* Receiving empty ORIGIN frame */
2927 nghttp2_session_client_new2(&session, &callbacks, &ud, option);
2928
2929 nghttp2_frame_origin_init(&frame, NULL, 0);
2930 rv = nghttp2_frame_pack_origin(&bufs, &frame);
2931
2932 assert_ptrdiff(0, ==, rv);
2933
2934 ud.frame_recv_cb_called = 0;
2935 rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
2936 nghttp2_bufs_len(&bufs));
2937
2938 assert_ptrdiff((nghttp2_ssize)nghttp2_bufs_len(&bufs), ==, rv);
2939 assert_int(1, ==, ud.frame_recv_cb_called);
2940 assert_uint8(NGHTTP2_ORIGIN, ==, ud.recv_frame_hd.type);
2941
2942 nghttp2_session_del(session);
2943
2944 nghttp2_option_del(option);
2945 nghttp2_bufs_free(&bufs);
2946 }
2947
test_nghttp2_session_recv_priority_update(void)2948 void test_nghttp2_session_recv_priority_update(void) {
2949 nghttp2_session *session;
2950 nghttp2_session_callbacks callbacks;
2951 my_user_data ud;
2952 nghttp2_bufs bufs;
2953 nghttp2_ssize rv;
2954 nghttp2_option *option;
2955 nghttp2_extension frame;
2956 nghttp2_ext_priority_update priority_update;
2957 nghttp2_stream *stream;
2958 nghttp2_hd_deflater deflater;
2959 nghttp2_mem *mem;
2960 uint8_t large_field_value[sizeof(session->iframe.raw_sbuf) + 1];
2961 nghttp2_outbound_item *item;
2962 size_t i;
2963 int32_t stream_id;
2964 static const uint8_t field_value[] = "u=2,i";
2965
2966 mem = nghttp2_mem_default();
2967
2968 memset(large_field_value, ' ', sizeof(large_field_value));
2969 memcpy(large_field_value, field_value, sizeof(field_value) - 1);
2970
2971 frame_pack_bufs_init(&bufs);
2972
2973 frame.payload = &priority_update;
2974
2975 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
2976
2977 callbacks.on_frame_recv_callback = on_frame_recv_callback;
2978
2979 nghttp2_option_new(&option);
2980 nghttp2_option_set_builtin_recv_extension_type(option,
2981 NGHTTP2_PRIORITY_UPDATE);
2982
2983 nghttp2_session_server_new2(&session, &callbacks, &ud, option);
2984
2985 session->pending_no_rfc7540_priorities = 1;
2986
2987 nghttp2_frame_priority_update_init(&frame, 1, (uint8_t *)field_value,
2988 sizeof(field_value) - 1);
2989
2990 nghttp2_frame_pack_priority_update(&bufs, &frame);
2991
2992 open_recv_stream(session, 1);
2993
2994 ud.frame_recv_cb_called = 0;
2995 rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
2996 nghttp2_bufs_len(&bufs));
2997
2998 assert_ptrdiff((nghttp2_ssize)nghttp2_bufs_len(&bufs), ==, rv);
2999 assert_int(1, ==, ud.frame_recv_cb_called);
3000 assert_uint8(NGHTTP2_PRIORITY_UPDATE, ==, ud.recv_frame_hd.type);
3001 assert_uint8(NGHTTP2_FLAG_NONE, ==, ud.recv_frame_hd.flags);
3002 assert_int32(0, ==, ud.recv_frame_hd.stream_id);
3003
3004 stream = nghttp2_session_get_stream_raw(session, 1);
3005
3006 assert_uint32(2, ==, nghttp2_extpri_uint8_urgency(stream->extpri));
3007 assert_true(nghttp2_extpri_uint8_inc(stream->extpri));
3008
3009 nghttp2_session_del(session);
3010 nghttp2_bufs_reset(&bufs);
3011
3012 /* Check that priority which is received in idle state is
3013 retained. */
3014 nghttp2_session_server_new2(&session, &callbacks, &ud, option);
3015
3016 session->pending_no_rfc7540_priorities = 1;
3017
3018 nghttp2_frame_priority_update_init(&frame, 1, (uint8_t *)field_value,
3019 sizeof(field_value) - 1);
3020
3021 nghttp2_frame_pack_priority_update(&bufs, &frame);
3022
3023 ud.frame_recv_cb_called = 0;
3024 rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
3025 nghttp2_bufs_len(&bufs));
3026
3027 assert_ptrdiff((nghttp2_ssize)nghttp2_bufs_len(&bufs), ==, rv);
3028 assert_int(1, ==, ud.frame_recv_cb_called);
3029 assert_uint8(NGHTTP2_PRIORITY_UPDATE, ==, ud.recv_frame_hd.type);
3030 assert_uint8(NGHTTP2_FLAG_NONE, ==, ud.recv_frame_hd.flags);
3031 assert_int32(0, ==, ud.recv_frame_hd.stream_id);
3032
3033 stream = nghttp2_session_get_stream_raw(session, 1);
3034
3035 assert_enum(nghttp2_stream_state, NGHTTP2_STREAM_IDLE, ==, stream->state);
3036 assert_uint32(2, ==, nghttp2_extpri_uint8_urgency(stream->extpri));
3037 assert_true(nghttp2_extpri_uint8_inc(stream->extpri));
3038
3039 nghttp2_hd_deflate_init(&deflater, mem);
3040 nghttp2_bufs_reset(&bufs);
3041 rv = pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, reqnv,
3042 ARRLEN(reqnv), mem);
3043
3044 assert_ptrdiff(0, ==, rv);
3045
3046 ud.frame_recv_cb_called = 0;
3047 rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
3048 nghttp2_bufs_len(&bufs));
3049
3050 assert_ptrdiff((nghttp2_ssize)nghttp2_bufs_len(&bufs), ==, rv);
3051 assert_int(1, ==, ud.frame_recv_cb_called);
3052 assert_uint8(NGHTTP2_HEADERS, ==, ud.recv_frame_hd.type);
3053 assert_enum(nghttp2_stream_state, NGHTTP2_STREAM_OPENING, ==, stream->state);
3054 assert_uint32(2, ==, nghttp2_extpri_uint8_urgency(stream->extpri));
3055 assert_true(nghttp2_extpri_uint8_inc(stream->extpri));
3056
3057 nghttp2_hd_deflate_free(&deflater);
3058
3059 nghttp2_session_del(session);
3060 nghttp2_bufs_reset(&bufs);
3061
3062 /* PRIORITY_UPDATE with too large field_value is discarded */
3063 nghttp2_session_server_new2(&session, &callbacks, &ud, option);
3064
3065 session->pending_no_rfc7540_priorities = 1;
3066
3067 nghttp2_frame_priority_update_init(&frame, 1, large_field_value,
3068 sizeof(large_field_value));
3069
3070 nghttp2_frame_pack_priority_update(&bufs, &frame);
3071
3072 open_recv_stream(session, 1);
3073
3074 ud.frame_recv_cb_called = 0;
3075 rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
3076 nghttp2_bufs_len(&bufs));
3077
3078 assert_ptrdiff((nghttp2_ssize)nghttp2_bufs_len(&bufs), ==, rv);
3079 assert_int(0, ==, ud.frame_recv_cb_called);
3080
3081 stream = nghttp2_session_get_stream_raw(session, 1);
3082
3083 assert_uint32(NGHTTP2_EXTPRI_DEFAULT_URGENCY, ==, stream->extpri);
3084
3085 nghttp2_session_del(session);
3086 nghttp2_bufs_reset(&bufs);
3087
3088 /* Connection error if client receives PRIORITY_UPDATE. */
3089 nghttp2_session_client_new2(&session, &callbacks, &ud, option);
3090
3091 session->pending_no_rfc7540_priorities = 1;
3092
3093 nghttp2_frame_priority_update_init(&frame, 1, (uint8_t *)field_value,
3094 sizeof(field_value) - 1);
3095
3096 nghttp2_frame_pack_priority_update(&bufs, &frame);
3097
3098 open_sent_stream(session, 1);
3099
3100 ud.frame_recv_cb_called = 0;
3101 rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
3102 nghttp2_bufs_len(&bufs));
3103
3104 assert_ptrdiff((nghttp2_ssize)nghttp2_bufs_len(&bufs), ==, rv);
3105 assert_int(0, ==, ud.frame_recv_cb_called);
3106
3107 item = nghttp2_session_get_next_ob_item(session);
3108 assert_uint8(NGHTTP2_GOAWAY, ==, item->frame.hd.type);
3109 assert_uint32(NGHTTP2_PROTOCOL_ERROR, ==, item->frame.goaway.error_code);
3110
3111 nghttp2_session_del(session);
3112 nghttp2_bufs_reset(&bufs);
3113
3114 /* The number of idle streams exceeds the maximum. */
3115 nghttp2_session_server_new2(&session, &callbacks, &ud, option);
3116
3117 session->pending_no_rfc7540_priorities = 1;
3118 session->local_settings.max_concurrent_streams = 100;
3119
3120 for (i = 0; i < 101; ++i) {
3121 stream_id = (int32_t)(i * 2 + 1);
3122 nghttp2_frame_priority_update_init(
3123 &frame, stream_id, (uint8_t *)field_value, sizeof(field_value) - 1);
3124
3125 nghttp2_frame_pack_priority_update(&bufs, &frame);
3126
3127 ud.frame_recv_cb_called = 0;
3128 rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
3129 nghttp2_bufs_len(&bufs));
3130
3131 if (i < 100) {
3132 assert_ptrdiff((nghttp2_ssize)nghttp2_bufs_len(&bufs), ==, rv);
3133 assert_int(1, ==, ud.frame_recv_cb_called);
3134 assert_uint8(NGHTTP2_PRIORITY_UPDATE, ==, ud.recv_frame_hd.type);
3135 } else {
3136 assert_int(0, ==, ud.frame_recv_cb_called);
3137 }
3138
3139 nghttp2_bufs_reset(&bufs);
3140 }
3141
3142 item = nghttp2_session_get_next_ob_item(session);
3143 assert_uint8(NGHTTP2_GOAWAY, ==, item->frame.hd.type);
3144 assert_uint32(NGHTTP2_PROTOCOL_ERROR, ==, item->frame.goaway.error_code);
3145
3146 nghttp2_session_del(session);
3147 nghttp2_option_del(option);
3148 nghttp2_bufs_free(&bufs);
3149 }
3150
test_nghttp2_session_continue(void)3151 void test_nghttp2_session_continue(void) {
3152 nghttp2_session *session;
3153 nghttp2_session_callbacks callbacks;
3154 my_user_data user_data;
3155 const nghttp2_nv nv1[] = {MAKE_NV(":method", "GET"), MAKE_NV(":path", "/")};
3156 const nghttp2_nv nv2[] = {MAKE_NV("user-agent", "nghttp2/1.0.0"),
3157 MAKE_NV("alpha", "bravo")};
3158 nghttp2_bufs bufs;
3159 nghttp2_buf *buf;
3160 size_t framelen1, framelen2;
3161 nghttp2_ssize rv;
3162 uint8_t buffer[4096];
3163 nghttp2_buf databuf;
3164 nghttp2_frame frame;
3165 nghttp2_nv *nva;
3166 size_t nvlen;
3167 const nghttp2_frame *recv_frame;
3168 nghttp2_frame_hd data_hd;
3169 nghttp2_hd_deflater deflater;
3170 nghttp2_mem *mem;
3171
3172 mem = nghttp2_mem_default();
3173 frame_pack_bufs_init(&bufs);
3174 nghttp2_buf_wrap_init(&databuf, buffer, sizeof(buffer));
3175
3176 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
3177 callbacks.send_callback2 = null_send_callback;
3178 callbacks.on_frame_recv_callback = on_frame_recv_callback;
3179 callbacks.on_data_chunk_recv_callback = pause_on_data_chunk_recv_callback;
3180 callbacks.on_header_callback = pause_on_header_callback;
3181 callbacks.on_begin_headers_callback = on_begin_headers_callback;
3182
3183 nghttp2_session_server_new(&session, &callbacks, &user_data);
3184 /* disable strict HTTP layering checks */
3185 session->opt_flags |= NGHTTP2_OPTMASK_NO_HTTP_MESSAGING;
3186
3187 nghttp2_hd_deflate_init(&deflater, mem);
3188
3189 /* Make 2 HEADERS frames */
3190 nvlen = ARRLEN(nv1);
3191 nghttp2_nv_array_copy(&nva, nv1, nvlen, mem);
3192 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 1,
3193 NGHTTP2_HCAT_HEADERS, NULL, nva, nvlen);
3194 rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
3195
3196 assert_ptrdiff(0, ==, rv);
3197 assert_size(0, <, nghttp2_bufs_len(&bufs));
3198
3199 nghttp2_frame_headers_free(&frame.headers, mem);
3200
3201 buf = &bufs.head->buf;
3202 assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
3203
3204 framelen1 = nghttp2_buf_len(buf);
3205 databuf.last = nghttp2_cpymem(databuf.last, buf->pos, nghttp2_buf_len(buf));
3206
3207 nvlen = ARRLEN(nv2);
3208 nghttp2_nv_array_copy(&nva, nv2, nvlen, mem);
3209 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 3,
3210 NGHTTP2_HCAT_HEADERS, NULL, nva, nvlen);
3211 nghttp2_bufs_reset(&bufs);
3212 rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
3213
3214 assert_ptrdiff(0, ==, rv);
3215 assert_size(0, <, nghttp2_bufs_len(&bufs));
3216
3217 nghttp2_frame_headers_free(&frame.headers, mem);
3218
3219 assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
3220
3221 framelen2 = nghttp2_buf_len(buf);
3222 databuf.last = nghttp2_cpymem(databuf.last, buf->pos, nghttp2_buf_len(buf));
3223
3224 /* Receive 1st HEADERS and pause */
3225 user_data.begin_headers_cb_called = 0;
3226 user_data.header_cb_called = 0;
3227 rv =
3228 nghttp2_session_mem_recv2(session, databuf.pos, nghttp2_buf_len(&databuf));
3229
3230 assert_ptrdiff(0, <=, rv);
3231 databuf.pos += rv;
3232
3233 recv_frame = user_data.frame;
3234 assert_uint8(NGHTTP2_HEADERS, ==, recv_frame->hd.type);
3235 assert_size(framelen1 - NGHTTP2_FRAME_HDLEN, ==, recv_frame->hd.length);
3236
3237 assert_int(1, ==, user_data.begin_headers_cb_called);
3238 assert_int(1, ==, user_data.header_cb_called);
3239
3240 assert_true(nghttp2_nv_equal(&nv1[0], &user_data.nv));
3241
3242 /* get 2nd header field */
3243 user_data.begin_headers_cb_called = 0;
3244 user_data.header_cb_called = 0;
3245 rv =
3246 nghttp2_session_mem_recv2(session, databuf.pos, nghttp2_buf_len(&databuf));
3247
3248 assert_ptrdiff(0, <=, rv);
3249 databuf.pos += rv;
3250
3251 assert_int(0, ==, user_data.begin_headers_cb_called);
3252 assert_int(1, ==, user_data.header_cb_called);
3253
3254 assert_true(nghttp2_nv_equal(&nv1[1], &user_data.nv));
3255
3256 /* will call end_headers_callback and receive 2nd HEADERS and pause */
3257 user_data.begin_headers_cb_called = 0;
3258 user_data.header_cb_called = 0;
3259 rv =
3260 nghttp2_session_mem_recv2(session, databuf.pos, nghttp2_buf_len(&databuf));
3261
3262 assert_ptrdiff(0, <=, rv);
3263 databuf.pos += rv;
3264
3265 recv_frame = user_data.frame;
3266 assert_uint8(NGHTTP2_HEADERS, ==, recv_frame->hd.type);
3267 assert_size(framelen2 - NGHTTP2_FRAME_HDLEN, ==, recv_frame->hd.length);
3268
3269 assert_int(1, ==, user_data.begin_headers_cb_called);
3270 assert_int(1, ==, user_data.header_cb_called);
3271
3272 assert_true(nghttp2_nv_equal(&nv2[0], &user_data.nv));
3273
3274 /* get 2nd header field */
3275 user_data.begin_headers_cb_called = 0;
3276 user_data.header_cb_called = 0;
3277 rv =
3278 nghttp2_session_mem_recv2(session, databuf.pos, nghttp2_buf_len(&databuf));
3279
3280 assert_ptrdiff(0, <=, rv);
3281 databuf.pos += rv;
3282
3283 assert_int(0, ==, user_data.begin_headers_cb_called);
3284 assert_int(1, ==, user_data.header_cb_called);
3285
3286 assert_true(nghttp2_nv_equal(&nv2[1], &user_data.nv));
3287
3288 /* No input data, frame_recv_callback is called */
3289 user_data.begin_headers_cb_called = 0;
3290 user_data.header_cb_called = 0;
3291 user_data.frame_recv_cb_called = 0;
3292 rv =
3293 nghttp2_session_mem_recv2(session, databuf.pos, nghttp2_buf_len(&databuf));
3294
3295 assert_ptrdiff(0, <=, rv);
3296 databuf.pos += rv;
3297
3298 assert_int(0, ==, user_data.begin_headers_cb_called);
3299 assert_int(0, ==, user_data.header_cb_called);
3300 assert_int(1, ==, user_data.frame_recv_cb_called);
3301
3302 /* Receive DATA */
3303 nghttp2_frame_hd_init(&data_hd, 16, NGHTTP2_DATA, NGHTTP2_FLAG_NONE, 1);
3304
3305 nghttp2_buf_reset(&databuf);
3306 nghttp2_frame_pack_frame_hd(databuf.pos, &data_hd);
3307
3308 /* Intentionally specify larger buffer size to see pause is kicked
3309 in. */
3310 databuf.last = databuf.end;
3311
3312 user_data.frame_recv_cb_called = 0;
3313 rv =
3314 nghttp2_session_mem_recv2(session, databuf.pos, nghttp2_buf_len(&databuf));
3315
3316 assert_ptrdiff(16 + NGHTTP2_FRAME_HDLEN, ==, rv);
3317 assert_int(0, ==, user_data.frame_recv_cb_called);
3318
3319 /* Next nghttp2_session_mem_recv2 invokes on_frame_recv_callback and
3320 pause again in on_data_chunk_recv_callback since we pass same
3321 DATA frame. */
3322 user_data.frame_recv_cb_called = 0;
3323 rv =
3324 nghttp2_session_mem_recv2(session, databuf.pos, nghttp2_buf_len(&databuf));
3325 assert_ptrdiff(16 + NGHTTP2_FRAME_HDLEN, ==, rv);
3326 assert_int(1, ==, user_data.frame_recv_cb_called);
3327
3328 /* And finally call on_frame_recv_callback with 0 size input */
3329 user_data.frame_recv_cb_called = 0;
3330 rv = nghttp2_session_mem_recv2(session, NULL, 0);
3331 assert_ptrdiff(0, ==, rv);
3332 assert_int(1, ==, user_data.frame_recv_cb_called);
3333
3334 nghttp2_bufs_free(&bufs);
3335 nghttp2_hd_deflate_free(&deflater);
3336 nghttp2_session_del(session);
3337 }
3338
test_nghttp2_session_add_frame(void)3339 void test_nghttp2_session_add_frame(void) {
3340 nghttp2_session *session;
3341 nghttp2_session_callbacks callbacks;
3342 accumulator acc;
3343 my_user_data user_data;
3344 nghttp2_outbound_item *item;
3345 nghttp2_frame *frame;
3346 nghttp2_nv *nva;
3347 size_t nvlen;
3348 nghttp2_mem *mem;
3349
3350 mem = nghttp2_mem_default();
3351 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
3352 callbacks.send_callback2 = accumulator_send_callback;
3353
3354 acc.length = 0;
3355 user_data.acc = &acc;
3356
3357 assert_int(0, ==,
3358 nghttp2_session_client_new(&session, &callbacks, &user_data));
3359
3360 item = mem->malloc(sizeof(nghttp2_outbound_item), NULL);
3361
3362 nghttp2_outbound_item_init(item);
3363
3364 frame = &item->frame;
3365
3366 nvlen = ARRLEN(reqnv);
3367 nghttp2_nv_array_copy(&nva, reqnv, nvlen, mem);
3368
3369 nghttp2_frame_headers_init(
3370 &frame->headers, NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PRIORITY,
3371 (int32_t)session->next_stream_id, NGHTTP2_HCAT_REQUEST, NULL, nva, nvlen);
3372
3373 session->next_stream_id += 2;
3374
3375 assert_int(0, ==, nghttp2_session_add_item(session, item));
3376 assert_not_null(nghttp2_outbound_queue_top(&session->ob_syn));
3377 assert_int(0, ==, nghttp2_session_send(session));
3378 assert_uint8(NGHTTP2_HEADERS, ==, acc.buf[3]);
3379 assert_uint8((NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PRIORITY), ==,
3380 acc.buf[4]);
3381 /* check stream id */
3382 assert_uint32(1, ==, nghttp2_get_uint32(&acc.buf[5]));
3383
3384 nghttp2_session_del(session);
3385 }
3386
test_nghttp2_session_on_request_headers_received(void)3387 void test_nghttp2_session_on_request_headers_received(void) {
3388 nghttp2_session *session;
3389 nghttp2_session_callbacks callbacks;
3390 my_user_data user_data;
3391 nghttp2_frame frame;
3392 nghttp2_stream *stream;
3393 int32_t stream_id = 1;
3394 nghttp2_nv malformed_nva[] = {MAKE_NV(":path", "\x01")};
3395 nghttp2_nv *nva;
3396 size_t nvlen;
3397 nghttp2_priority_spec pri_spec;
3398 nghttp2_mem *mem;
3399
3400 mem = nghttp2_mem_default();
3401 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
3402 callbacks.on_begin_headers_callback = on_begin_headers_callback;
3403 callbacks.on_invalid_frame_recv_callback = on_invalid_frame_recv_callback;
3404
3405 nghttp2_session_server_new(&session, &callbacks, &user_data);
3406
3407 nghttp2_priority_spec_init(&pri_spec, 0, 255, 0);
3408
3409 nghttp2_frame_headers_init(
3410 &frame.headers, NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PRIORITY, stream_id,
3411 NGHTTP2_HCAT_REQUEST, &pri_spec, NULL, 0);
3412
3413 user_data.begin_headers_cb_called = 0;
3414 user_data.invalid_frame_recv_cb_called = 0;
3415
3416 assert_int(0, ==,
3417 nghttp2_session_on_request_headers_received(session, &frame));
3418 assert_int(1, ==, user_data.begin_headers_cb_called);
3419 stream = nghttp2_session_get_stream(session, stream_id);
3420 assert_enum(nghttp2_stream_state, NGHTTP2_STREAM_OPENING, ==, stream->state);
3421 assert_int32(255, ==, stream->weight);
3422
3423 nghttp2_frame_headers_free(&frame.headers, mem);
3424
3425 /* More than un-ACKed max concurrent streams leads REFUSED_STREAM */
3426 session->pending_local_max_concurrent_stream = 1;
3427 nghttp2_frame_headers_init(&frame.headers,
3428 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PRIORITY,
3429 3, NGHTTP2_HCAT_HEADERS, NULL, NULL, 0);
3430 user_data.invalid_frame_recv_cb_called = 0;
3431 assert_int(NGHTTP2_ERR_IGN_HEADER_BLOCK, ==,
3432 nghttp2_session_on_request_headers_received(session, &frame));
3433 assert_int(1, ==, user_data.invalid_frame_recv_cb_called);
3434 assert_false(session->goaway_flags & NGHTTP2_GOAWAY_TERM_ON_SEND);
3435
3436 nghttp2_frame_headers_free(&frame.headers, mem);
3437 session->local_settings.max_concurrent_streams =
3438 NGHTTP2_DEFAULT_MAX_CONCURRENT_STREAMS;
3439
3440 /* Stream ID less than or equal to the previously received request
3441 HEADERS is just ignored due to race condition */
3442 nghttp2_frame_headers_init(&frame.headers,
3443 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PRIORITY,
3444 3, NGHTTP2_HCAT_HEADERS, NULL, NULL, 0);
3445 user_data.invalid_frame_recv_cb_called = 0;
3446 assert_int(NGHTTP2_ERR_IGN_HEADER_BLOCK, ==,
3447 nghttp2_session_on_request_headers_received(session, &frame));
3448 assert_int(0, ==, user_data.invalid_frame_recv_cb_called);
3449 assert_false(session->goaway_flags & NGHTTP2_GOAWAY_TERM_ON_SEND);
3450
3451 nghttp2_frame_headers_free(&frame.headers, mem);
3452
3453 /* Stream ID is our side and it is idle stream ID, then treat it as
3454 connection error */
3455 nghttp2_frame_headers_init(&frame.headers,
3456 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PRIORITY,
3457 2, NGHTTP2_HCAT_HEADERS, NULL, NULL, 0);
3458 user_data.invalid_frame_recv_cb_called = 0;
3459 assert_int(NGHTTP2_ERR_IGN_HEADER_BLOCK, ==,
3460 nghttp2_session_on_request_headers_received(session, &frame));
3461 assert_int(1, ==, user_data.invalid_frame_recv_cb_called);
3462 assert_true(session->goaway_flags & NGHTTP2_GOAWAY_TERM_ON_SEND);
3463
3464 nghttp2_frame_headers_free(&frame.headers, mem);
3465
3466 nghttp2_session_del(session);
3467
3468 /* Check malformed headers. The library accept it. */
3469 nghttp2_session_server_new(&session, &callbacks, &user_data);
3470
3471 nvlen = ARRLEN(malformed_nva);
3472 nghttp2_nv_array_copy(&nva, malformed_nva, nvlen, mem);
3473 nghttp2_frame_headers_init(&frame.headers,
3474 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PRIORITY,
3475 1, NGHTTP2_HCAT_HEADERS, NULL, nva, nvlen);
3476 user_data.begin_headers_cb_called = 0;
3477 user_data.invalid_frame_recv_cb_called = 0;
3478 assert_int(0, ==,
3479 nghttp2_session_on_request_headers_received(session, &frame));
3480 assert_int(1, ==, user_data.begin_headers_cb_called);
3481 assert_int(0, ==, user_data.invalid_frame_recv_cb_called);
3482
3483 nghttp2_frame_headers_free(&frame.headers, mem);
3484
3485 nghttp2_session_del(session);
3486
3487 /* Check client side */
3488 nghttp2_session_client_new(&session, &callbacks, &user_data);
3489
3490 /* Receiving peer's idle stream ID is subject to connection error */
3491 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 2,
3492 NGHTTP2_HCAT_REQUEST, NULL, NULL, 0);
3493
3494 user_data.invalid_frame_recv_cb_called = 0;
3495 assert_int(NGHTTP2_ERR_IGN_HEADER_BLOCK, ==,
3496 nghttp2_session_on_request_headers_received(session, &frame));
3497 assert_int(1, ==, user_data.invalid_frame_recv_cb_called);
3498 assert_true(session->goaway_flags & NGHTTP2_GOAWAY_TERM_ON_SEND);
3499
3500 nghttp2_frame_headers_free(&frame.headers, mem);
3501
3502 nghttp2_session_del(session);
3503
3504 nghttp2_session_client_new(&session, &callbacks, &user_data);
3505
3506 /* Receiving our's idle stream ID is subject to connection error */
3507 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 1,
3508 NGHTTP2_HCAT_REQUEST, NULL, NULL, 0);
3509
3510 user_data.invalid_frame_recv_cb_called = 0;
3511 assert_int(NGHTTP2_ERR_IGN_HEADER_BLOCK, ==,
3512 nghttp2_session_on_request_headers_received(session, &frame));
3513 assert_int(1, ==, user_data.invalid_frame_recv_cb_called);
3514 assert_true(session->goaway_flags & NGHTTP2_GOAWAY_TERM_ON_SEND);
3515
3516 nghttp2_frame_headers_free(&frame.headers, mem);
3517
3518 nghttp2_session_del(session);
3519
3520 nghttp2_session_client_new(&session, &callbacks, &user_data);
3521
3522 session->next_stream_id = 5;
3523 session->last_sent_stream_id = 3;
3524
3525 /* Stream ID which is not idle and not in stream map is just
3526 ignored */
3527 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 3,
3528 NGHTTP2_HCAT_REQUEST, NULL, NULL, 0);
3529
3530 user_data.invalid_frame_recv_cb_called = 0;
3531 assert_int(NGHTTP2_ERR_IGN_HEADER_BLOCK, ==,
3532 nghttp2_session_on_request_headers_received(session, &frame));
3533 assert_int(0, ==, user_data.invalid_frame_recv_cb_called);
3534 assert_false(session->goaway_flags & NGHTTP2_GOAWAY_TERM_ON_SEND);
3535
3536 nghttp2_frame_headers_free(&frame.headers, mem);
3537
3538 nghttp2_session_del(session);
3539
3540 nghttp2_session_server_new(&session, &callbacks, &user_data);
3541
3542 /* Stream ID which is equal to local_last_stream_id is ok. */
3543 session->local_last_stream_id = 3;
3544
3545 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 3,
3546 NGHTTP2_HCAT_REQUEST, NULL, NULL, 0);
3547
3548 assert_int(0, ==,
3549 nghttp2_session_on_request_headers_received(session, &frame));
3550
3551 nghttp2_frame_headers_free(&frame.headers, mem);
3552
3553 /* If GOAWAY has been sent, new stream is ignored */
3554 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 5,
3555 NGHTTP2_HCAT_REQUEST, NULL, NULL, 0);
3556
3557 session->goaway_flags |= NGHTTP2_GOAWAY_SENT;
3558 user_data.invalid_frame_recv_cb_called = 0;
3559 assert_int(NGHTTP2_ERR_IGN_HEADER_BLOCK, ==,
3560 nghttp2_session_on_request_headers_received(session, &frame));
3561 assert_int(0, ==, user_data.invalid_frame_recv_cb_called);
3562 assert_false(session->goaway_flags & NGHTTP2_GOAWAY_TERM_ON_SEND);
3563
3564 nghttp2_frame_headers_free(&frame.headers, mem);
3565
3566 nghttp2_session_del(session);
3567
3568 nghttp2_session_server_new(&session, &callbacks, &user_data);
3569
3570 /* HEADERS to closed stream */
3571 stream = open_recv_stream(session, 1);
3572 nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_RD);
3573 nghttp2_session_close_stream(session, 1, NGHTTP2_NO_ERROR);
3574
3575 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 1,
3576 NGHTTP2_HCAT_REQUEST, NULL, NULL, 0);
3577
3578 assert_int(NGHTTP2_ERR_IGN_HEADER_BLOCK, ==,
3579 nghttp2_session_on_request_headers_received(session, &frame));
3580 assert_true(session->goaway_flags & NGHTTP2_GOAWAY_TERM_ON_SEND);
3581
3582 nghttp2_frame_headers_free(&frame.headers, mem);
3583
3584 nghttp2_session_del(session);
3585 }
3586
test_nghttp2_session_on_response_headers_received(void)3587 void test_nghttp2_session_on_response_headers_received(void) {
3588 nghttp2_session *session;
3589 nghttp2_session_callbacks callbacks;
3590 my_user_data user_data;
3591 nghttp2_frame frame;
3592 nghttp2_stream *stream;
3593 nghttp2_mem *mem;
3594
3595 mem = nghttp2_mem_default();
3596 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
3597 callbacks.on_begin_headers_callback = on_begin_headers_callback;
3598 callbacks.on_invalid_frame_recv_callback = on_invalid_frame_recv_callback;
3599
3600 nghttp2_session_client_new(&session, &callbacks, &user_data);
3601 stream = open_sent_stream2(session, 1, NGHTTP2_STREAM_OPENING);
3602 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 1,
3603 NGHTTP2_HCAT_HEADERS, NULL, NULL, 0);
3604
3605 user_data.begin_headers_cb_called = 0;
3606 user_data.invalid_frame_recv_cb_called = 0;
3607
3608 assert_int(
3609 0, ==,
3610 nghttp2_session_on_response_headers_received(session, &frame, stream));
3611 assert_int(1, ==, user_data.begin_headers_cb_called);
3612 assert_enum(nghttp2_stream_state, NGHTTP2_STREAM_OPENED, ==, stream->state);
3613
3614 nghttp2_frame_headers_free(&frame.headers, mem);
3615 nghttp2_session_del(session);
3616 }
3617
test_nghttp2_session_on_headers_received(void)3618 void test_nghttp2_session_on_headers_received(void) {
3619 nghttp2_session *session;
3620 nghttp2_session_callbacks callbacks;
3621 my_user_data user_data;
3622 nghttp2_frame frame;
3623 nghttp2_stream *stream;
3624 nghttp2_mem *mem;
3625
3626 mem = nghttp2_mem_default();
3627 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
3628 callbacks.on_begin_headers_callback = on_begin_headers_callback;
3629 callbacks.on_invalid_frame_recv_callback = on_invalid_frame_recv_callback;
3630
3631 nghttp2_session_client_new(&session, &callbacks, &user_data);
3632 stream = open_sent_stream2(session, 1, NGHTTP2_STREAM_OPENED);
3633 nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_WR);
3634 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 1,
3635 NGHTTP2_HCAT_HEADERS, NULL, NULL, 0);
3636
3637 user_data.begin_headers_cb_called = 0;
3638 user_data.invalid_frame_recv_cb_called = 0;
3639
3640 assert_int(0, ==,
3641 nghttp2_session_on_headers_received(session, &frame, stream));
3642 assert_int(1, ==, user_data.begin_headers_cb_called);
3643 assert_enum(nghttp2_stream_state, NGHTTP2_STREAM_OPENED, ==, stream->state);
3644
3645 /* stream closed */
3646 frame.hd.flags |= NGHTTP2_FLAG_END_STREAM;
3647
3648 assert_int(0, ==,
3649 nghttp2_session_on_headers_received(session, &frame, stream));
3650 assert_int(2, ==, user_data.begin_headers_cb_called);
3651
3652 /* Check to see when NGHTTP2_STREAM_CLOSING, incoming HEADERS is
3653 discarded. */
3654 stream = open_sent_stream2(session, 3, NGHTTP2_STREAM_CLOSING);
3655 frame.hd.stream_id = 3;
3656 frame.hd.flags = NGHTTP2_FLAG_END_HEADERS;
3657 assert_int(NGHTTP2_ERR_IGN_HEADER_BLOCK, ==,
3658 nghttp2_session_on_headers_received(session, &frame, stream));
3659 /* See no counters are updated */
3660 assert_int(2, ==, user_data.begin_headers_cb_called);
3661 assert_int(0, ==, user_data.invalid_frame_recv_cb_called);
3662
3663 /* Server initiated stream */
3664 stream = open_recv_stream(session, 2);
3665
3666 frame.hd.flags = NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM;
3667 frame.hd.stream_id = 2;
3668
3669 assert_int(0, ==,
3670 nghttp2_session_on_headers_received(session, &frame, stream));
3671 assert_int(3, ==, user_data.begin_headers_cb_called);
3672 assert_enum(nghttp2_stream_state, NGHTTP2_STREAM_OPENED, ==, stream->state);
3673
3674 nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_RD);
3675
3676 /* Further reception of HEADERS is subject to stream error */
3677 assert_int(NGHTTP2_ERR_IGN_HEADER_BLOCK, ==,
3678 nghttp2_session_on_headers_received(session, &frame, stream));
3679 assert_int(1, ==, user_data.invalid_frame_recv_cb_called);
3680
3681 nghttp2_frame_headers_free(&frame.headers, mem);
3682
3683 nghttp2_session_del(session);
3684 }
3685
test_nghttp2_session_on_push_response_headers_received(void)3686 void test_nghttp2_session_on_push_response_headers_received(void) {
3687 nghttp2_session *session;
3688 nghttp2_session_callbacks callbacks;
3689 my_user_data user_data;
3690 nghttp2_frame frame;
3691 nghttp2_stream *stream;
3692 nghttp2_outbound_item *item;
3693 nghttp2_mem *mem;
3694
3695 mem = nghttp2_mem_default();
3696 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
3697 callbacks.send_callback2 = null_send_callback;
3698 callbacks.on_begin_headers_callback = on_begin_headers_callback;
3699 callbacks.on_invalid_frame_recv_callback = on_invalid_frame_recv_callback;
3700
3701 nghttp2_session_client_new(&session, &callbacks, &user_data);
3702 stream = open_recv_stream2(session, 2, NGHTTP2_STREAM_RESERVED);
3703 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 2,
3704 NGHTTP2_HCAT_HEADERS, NULL, NULL, 0);
3705 /* nghttp2_session_on_push_response_headers_received assumes
3706 stream's state is NGHTTP2_STREAM_RESERVED and session->server is
3707 0. */
3708
3709 user_data.begin_headers_cb_called = 0;
3710 user_data.invalid_frame_recv_cb_called = 0;
3711
3712 assert_size(1, ==, session->num_incoming_reserved_streams);
3713 assert_int(
3714 0, ==,
3715 nghttp2_session_on_push_response_headers_received(session, &frame, stream));
3716 assert_int(1, ==, user_data.begin_headers_cb_called);
3717 assert_size(0, ==, session->num_incoming_reserved_streams);
3718 assert_enum(nghttp2_stream_state, NGHTTP2_STREAM_OPENED, ==, stream->state);
3719 assert_size(1, ==, session->num_incoming_streams);
3720 assert_false(stream->flags & NGHTTP2_STREAM_FLAG_PUSH);
3721
3722 /* If un-ACKed max concurrent streams limit is exceeded,
3723 RST_STREAMed */
3724 session->pending_local_max_concurrent_stream = 1;
3725 stream = open_recv_stream2(session, 4, NGHTTP2_STREAM_RESERVED);
3726 frame.hd.stream_id = 4;
3727 assert_int(
3728 NGHTTP2_ERR_IGN_HEADER_BLOCK, ==,
3729 nghttp2_session_on_push_response_headers_received(session, &frame, stream));
3730 item = nghttp2_session_get_next_ob_item(session);
3731 assert_uint8(NGHTTP2_RST_STREAM, ==, item->frame.hd.type);
3732 assert_uint32(NGHTTP2_REFUSED_STREAM, ==, item->frame.rst_stream.error_code);
3733 assert_size(1, ==, session->num_incoming_streams);
3734 assert_size(1, ==, session->num_incoming_reserved_streams);
3735
3736 assert_int(0, ==, nghttp2_session_send(session));
3737 assert_size(1, ==, session->num_incoming_streams);
3738
3739 /* If ACKed max concurrent streams limit is exceeded, GOAWAY is
3740 issued */
3741 session->local_settings.max_concurrent_streams = 1;
3742
3743 stream = open_recv_stream2(session, 6, NGHTTP2_STREAM_RESERVED);
3744 frame.hd.stream_id = 6;
3745
3746 assert_int(
3747 NGHTTP2_ERR_IGN_HEADER_BLOCK, ==,
3748 nghttp2_session_on_push_response_headers_received(session, &frame, stream));
3749 item = nghttp2_session_get_next_ob_item(session);
3750 assert_uint8(NGHTTP2_GOAWAY, ==, item->frame.hd.type);
3751 assert_uint32(NGHTTP2_PROTOCOL_ERROR, ==, item->frame.goaway.error_code);
3752 assert_size(1, ==, session->num_incoming_streams);
3753 assert_size(1, ==, session->num_incoming_reserved_streams);
3754
3755 nghttp2_frame_headers_free(&frame.headers, mem);
3756 nghttp2_session_del(session);
3757 }
3758
test_nghttp2_session_on_priority_received(void)3759 void test_nghttp2_session_on_priority_received(void) {
3760 nghttp2_session *session;
3761 nghttp2_session_callbacks callbacks;
3762 my_user_data user_data;
3763 nghttp2_frame frame;
3764 nghttp2_stream *stream, *dep_stream;
3765 nghttp2_priority_spec pri_spec;
3766 nghttp2_outbound_item *item;
3767
3768 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
3769 callbacks.on_frame_recv_callback = on_frame_recv_callback;
3770 callbacks.on_invalid_frame_recv_callback = on_invalid_frame_recv_callback;
3771
3772 nghttp2_session_server_new(&session, &callbacks, &user_data);
3773 stream = open_recv_stream(session, 1);
3774
3775 nghttp2_priority_spec_init(&pri_spec, 0, 2, 0);
3776
3777 nghttp2_frame_priority_init(&frame.priority, 1, &pri_spec);
3778
3779 /* depend on stream 0 */
3780 assert_int(0, ==, nghttp2_session_on_priority_received(session, &frame));
3781
3782 assert_int32(2, ==, stream->weight);
3783
3784 stream = open_sent_stream(session, 2);
3785 dep_stream = open_recv_stream(session, 3);
3786
3787 frame.hd.stream_id = 2;
3788
3789 /* using dependency stream */
3790 nghttp2_priority_spec_init(&frame.priority.pri_spec, 3, 1, 0);
3791
3792 assert_int(0, ==, nghttp2_session_on_priority_received(session, &frame));
3793 assert_ptr_equal(dep_stream, stream->dep_prev);
3794
3795 /* PRIORITY against idle stream */
3796
3797 frame.hd.stream_id = 100;
3798
3799 assert_int(0, ==, nghttp2_session_on_priority_received(session, &frame));
3800
3801 stream = nghttp2_session_get_stream_raw(session, frame.hd.stream_id);
3802
3803 assert_enum(nghttp2_stream_state, NGHTTP2_STREAM_IDLE, ==, stream->state);
3804 assert_ptr_equal(dep_stream, stream->dep_prev);
3805
3806 nghttp2_frame_priority_free(&frame.priority);
3807 nghttp2_session_del(session);
3808
3809 /* Check dep_stream_id == stream_id case */
3810 nghttp2_session_server_new(&session, &callbacks, &user_data);
3811 open_recv_stream(session, 1);
3812
3813 nghttp2_priority_spec_init(&pri_spec, 1, 0, 0);
3814
3815 nghttp2_frame_priority_init(&frame.priority, 1, &pri_spec);
3816
3817 assert_int(0, ==, nghttp2_session_on_priority_received(session, &frame));
3818
3819 item = nghttp2_session_get_next_ob_item(session);
3820
3821 assert_uint8(NGHTTP2_GOAWAY, ==, item->frame.hd.type);
3822
3823 nghttp2_frame_priority_free(&frame.priority);
3824 nghttp2_session_del(session);
3825
3826 /* Check again dep_stream_id == stream_id, and stream_id is idle */
3827 nghttp2_session_server_new(&session, &callbacks, &user_data);
3828
3829 nghttp2_priority_spec_init(&pri_spec, 1, 16, 0);
3830
3831 nghttp2_frame_priority_init(&frame.priority, 1, &pri_spec);
3832
3833 assert_int(0, ==, nghttp2_session_on_priority_received(session, &frame));
3834
3835 item = nghttp2_session_get_next_ob_item(session);
3836
3837 assert_uint8(NGHTTP2_GOAWAY, ==, item->frame.hd.type);
3838
3839 nghttp2_frame_priority_free(&frame.priority);
3840 nghttp2_session_del(session);
3841 }
3842
test_nghttp2_session_on_rst_stream_received(void)3843 void test_nghttp2_session_on_rst_stream_received(void) {
3844 nghttp2_session *session;
3845 nghttp2_session_callbacks callbacks;
3846 my_user_data user_data;
3847 nghttp2_frame frame;
3848 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
3849 nghttp2_session_server_new(&session, &callbacks, &user_data);
3850 open_recv_stream(session, 1);
3851
3852 nghttp2_frame_rst_stream_init(&frame.rst_stream, 1, NGHTTP2_PROTOCOL_ERROR);
3853
3854 assert_int(0, ==, nghttp2_session_on_rst_stream_received(session, &frame));
3855 assert_null(nghttp2_session_get_stream(session, 1));
3856
3857 nghttp2_frame_rst_stream_free(&frame.rst_stream);
3858 nghttp2_session_del(session);
3859 }
3860
test_nghttp2_session_on_settings_received(void)3861 void test_nghttp2_session_on_settings_received(void) {
3862 nghttp2_session *session;
3863 nghttp2_session_callbacks callbacks;
3864 my_user_data user_data;
3865 nghttp2_stream *stream1, *stream2;
3866 nghttp2_frame frame;
3867 const size_t niv = 5;
3868 nghttp2_settings_entry iv[255];
3869 nghttp2_outbound_item *item;
3870 nghttp2_nv nv = MAKE_NV(":authority", "example.org");
3871 nghttp2_mem *mem;
3872 nghttp2_option *option;
3873 uint8_t data[2048];
3874 nghttp2_frame_hd hd;
3875 int rv;
3876 nghttp2_ssize nread;
3877 nghttp2_stream *stream;
3878
3879 mem = nghttp2_mem_default();
3880
3881 iv[0].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS;
3882 iv[0].value = 50;
3883
3884 iv[1].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS;
3885 iv[1].value = 1000000009;
3886
3887 iv[2].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
3888 iv[2].value = 64 * 1024;
3889
3890 iv[3].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
3891 iv[3].value = 1024;
3892
3893 iv[4].settings_id = NGHTTP2_SETTINGS_ENABLE_PUSH;
3894 iv[4].value = 0;
3895
3896 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
3897 callbacks.send_callback2 = null_send_callback;
3898
3899 nghttp2_session_client_new(&session, &callbacks, &user_data);
3900 session->remote_settings.initial_window_size = 16 * 1024;
3901
3902 stream1 = open_sent_stream(session, 1);
3903 stream2 = open_recv_stream(session, 2);
3904
3905 /* Set window size for each streams and will see how settings
3906 updates these values */
3907 stream1->remote_window_size = 16 * 1024;
3908 stream2->remote_window_size = -48 * 1024;
3909
3910 nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE,
3911 dup_iv(iv, niv), niv);
3912
3913 assert_int(0, ==, nghttp2_session_on_settings_received(session, &frame, 0));
3914 assert_uint32(1000000009, ==,
3915 session->remote_settings.max_concurrent_streams);
3916 assert_uint32(64 * 1024, ==, session->remote_settings.initial_window_size);
3917 assert_uint32(1024, ==, session->remote_settings.header_table_size);
3918 assert_uint32(0, ==, session->remote_settings.enable_push);
3919
3920 assert_int32(64 * 1024, ==, stream1->remote_window_size);
3921 assert_int32(0, ==, stream2->remote_window_size);
3922
3923 frame.settings.iv[2].value = 16 * 1024;
3924
3925 assert_int(0, ==, nghttp2_session_on_settings_received(session, &frame, 0));
3926
3927 assert_int32(16 * 1024, ==, stream1->remote_window_size);
3928 assert_int32(-48 * 1024, ==, stream2->remote_window_size);
3929
3930 assert_int32(
3931 16 * 1024, ==,
3932 nghttp2_session_get_stream_remote_window_size(session, stream1->stream_id));
3933 assert_int32(
3934 0, ==,
3935 nghttp2_session_get_stream_remote_window_size(session, stream2->stream_id));
3936
3937 nghttp2_frame_settings_free(&frame.settings, mem);
3938
3939 nghttp2_session_del(session);
3940
3941 /* Check ACK with niv > 0 */
3942 nghttp2_session_server_new(&session, &callbacks, NULL);
3943 nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_ACK, dup_iv(iv, 1),
3944 1);
3945 assert_int(0, ==, nghttp2_session_on_settings_received(session, &frame, 0));
3946 item = nghttp2_session_get_next_ob_item(session);
3947 assert_not_null(item);
3948 assert_uint8(NGHTTP2_GOAWAY, ==, item->frame.hd.type);
3949
3950 nghttp2_frame_settings_free(&frame.settings, mem);
3951 nghttp2_session_del(session);
3952
3953 /* Check ACK against no inflight SETTINGS */
3954 nghttp2_session_server_new(&session, &callbacks, NULL);
3955 nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_ACK, NULL, 0);
3956
3957 assert_int(0, ==, nghttp2_session_on_settings_received(session, &frame, 0));
3958 item = nghttp2_session_get_next_ob_item(session);
3959 assert_not_null(item);
3960 assert_uint8(NGHTTP2_GOAWAY, ==, item->frame.hd.type);
3961
3962 nghttp2_frame_settings_free(&frame.settings, mem);
3963 nghttp2_session_del(session);
3964
3965 /* Check that 2 SETTINGS_HEADER_TABLE_SIZE 0 and 4096 are included
3966 and header table size is once cleared to 0. */
3967 nghttp2_session_client_new(&session, &callbacks, NULL);
3968
3969 nghttp2_submit_request2(session, NULL, &nv, 1, NULL, NULL);
3970
3971 nghttp2_session_send(session);
3972
3973 assert_size(0, <, session->hd_deflater.ctx.hd_table.len);
3974
3975 iv[0].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
3976 iv[0].value = 0;
3977
3978 iv[1].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
3979 iv[1].value = 2048;
3980
3981 nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE, dup_iv(iv, 2),
3982 2);
3983
3984 assert_int(0, ==, nghttp2_session_on_settings_received(session, &frame, 0));
3985
3986 assert_size(0, ==, session->hd_deflater.ctx.hd_table.len);
3987 assert_size(2048, ==, session->hd_deflater.ctx.hd_table_bufsize_max);
3988 assert_uint32(2048, ==, session->remote_settings.header_table_size);
3989
3990 nghttp2_frame_settings_free(&frame.settings, mem);
3991 nghttp2_session_del(session);
3992
3993 /* Check that remote SETTINGS_MAX_CONCURRENT_STREAMS is set to a value set by
3994 nghttp2_option_set_peer_max_concurrent_streams() and reset to the default
3995 value (unlimited) after receiving initial SETTINGS frame from the peer. */
3996 nghttp2_option_new(&option);
3997 nghttp2_option_set_peer_max_concurrent_streams(option, 1000);
3998 nghttp2_session_client_new2(&session, &callbacks, NULL, option);
3999 assert_uint32(1000, ==, session->remote_settings.max_concurrent_streams);
4000
4001 nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE, NULL, 0);
4002 assert_int(0, ==, nghttp2_session_on_settings_received(session, &frame, 0));
4003 assert_uint32(NGHTTP2_DEFAULT_MAX_CONCURRENT_STREAMS, ==,
4004 session->remote_settings.max_concurrent_streams);
4005
4006 nghttp2_frame_settings_free(&frame.settings, mem);
4007 nghttp2_session_del(session);
4008 nghttp2_option_del(option);
4009
4010 /* Check too large SETTINGS_MAX_FRAME_SIZE */
4011 nghttp2_session_server_new(&session, &callbacks, NULL);
4012
4013 iv[0].settings_id = NGHTTP2_SETTINGS_MAX_FRAME_SIZE;
4014 iv[0].value = NGHTTP2_MAX_FRAME_SIZE_MAX + 1;
4015
4016 nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE, dup_iv(iv, 1),
4017 1);
4018
4019 assert_int(0, ==, nghttp2_session_on_settings_received(session, &frame, 0));
4020
4021 item = nghttp2_session_get_next_ob_item(session);
4022
4023 assert_not_null(item);
4024 assert_uint8(NGHTTP2_GOAWAY, ==, item->frame.hd.type);
4025
4026 nghttp2_frame_settings_free(&frame.settings, mem);
4027 nghttp2_session_del(session);
4028
4029 /* Check the case where stream window size overflows */
4030 nghttp2_session_server_new(&session, &callbacks, NULL);
4031
4032 stream1 = open_recv_stream(session, 1);
4033
4034 /* This will increment window size by 1 */
4035 nghttp2_frame_window_update_init(&frame.window_update, NGHTTP2_FLAG_NONE, 1,
4036 1);
4037
4038 assert_int(0, ==, nghttp2_session_on_window_update_received(session, &frame));
4039
4040 nghttp2_frame_window_update_free(&frame.window_update);
4041
4042 iv[0].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
4043 iv[0].value = NGHTTP2_MAX_WINDOW_SIZE;
4044
4045 nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE, dup_iv(iv, 1),
4046 1);
4047
4048 /* Now window size gets NGHTTP2_MAX_WINDOW_SIZE + 1, which is
4049 unacceptable situation in protocol spec. */
4050 assert_int(0, ==, nghttp2_session_on_settings_received(session, &frame, 0));
4051
4052 nghttp2_frame_settings_free(&frame.settings, mem);
4053
4054 item = nghttp2_session_get_next_ob_item(session);
4055
4056 assert_not_null(item);
4057 assert_uint8(NGHTTP2_SETTINGS, ==, item->frame.hd.type);
4058
4059 item = nghttp2_outbound_queue_top(&session->ob_reg);
4060
4061 assert_not_null(item);
4062 assert_uint8(NGHTTP2_RST_STREAM, ==, item->frame.hd.type);
4063 assert_enum(nghttp2_stream_state, NGHTTP2_STREAM_CLOSING, ==, stream1->state);
4064
4065 nghttp2_session_del(session);
4066
4067 /* It is invalid that peer disables ENABLE_CONNECT_PROTOCOL once it
4068 has been enabled. */
4069 nghttp2_session_client_new(&session, &callbacks, NULL);
4070
4071 session->remote_settings.enable_connect_protocol = 1;
4072
4073 iv[0].settings_id = NGHTTP2_SETTINGS_ENABLE_CONNECT_PROTOCOL;
4074 iv[0].value = 0;
4075
4076 nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE, dup_iv(iv, 1),
4077 1);
4078
4079 assert_int(0, ==, nghttp2_session_on_settings_received(session, &frame, 0));
4080
4081 nghttp2_frame_settings_free(&frame.settings, mem);
4082
4083 item = nghttp2_session_get_next_ob_item(session);
4084
4085 assert_not_null(item);
4086 assert_uint8(NGHTTP2_GOAWAY, ==, item->frame.hd.type);
4087
4088 nghttp2_session_del(session);
4089
4090 /* Should send WINDOW_UPDATE with no_auto_window_update option on if
4091 the initial window size is decreased and becomes smaller than or
4092 equal to the amount of data that has already received. */
4093 nghttp2_option_new(&option);
4094 nghttp2_option_set_no_auto_window_update(option, 1);
4095
4096 nghttp2_session_server_new2(&session, &callbacks, NULL, option);
4097
4098 iv[0].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
4099 iv[0].value = 1024;
4100
4101 rv = nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, iv, 1);
4102
4103 assert_int(0, ==, rv);
4104
4105 rv = nghttp2_session_send(session);
4106
4107 assert_int(0, ==, rv);
4108
4109 stream = open_recv_stream(session, 1);
4110
4111 memset(data, 0, sizeof(data));
4112 hd.length = 1024;
4113 hd.type = NGHTTP2_DATA;
4114 hd.flags = NGHTTP2_FLAG_NONE;
4115 hd.stream_id = 1;
4116 nghttp2_frame_pack_frame_hd(data, &hd);
4117
4118 nread =
4119 nghttp2_session_mem_recv2(session, data, NGHTTP2_FRAME_HDLEN + hd.length);
4120
4121 assert_ptrdiff((nghttp2_ssize)(NGHTTP2_FRAME_HDLEN + hd.length), ==, nread);
4122
4123 rv = nghttp2_session_consume(session, 1, hd.length);
4124
4125 assert_int(0, ==, rv);
4126 assert_int32((int32_t)hd.length, ==, stream->recv_window_size);
4127 assert_int32((int32_t)hd.length, ==, stream->consumed_size);
4128
4129 nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_ACK, NULL, 0);
4130
4131 rv = nghttp2_session_on_settings_received(session, &frame, 0);
4132
4133 assert_int(0, ==, rv);
4134 assert_int32(1024, ==, stream->local_window_size);
4135 assert_int32(0, ==, stream->recv_window_size);
4136 assert_int32(0, ==, stream->consumed_size);
4137
4138 item = nghttp2_session_get_next_ob_item(session);
4139
4140 assert_not_null(item);
4141 assert_uint8(NGHTTP2_WINDOW_UPDATE, ==, item->frame.hd.type);
4142 assert_int32((int32_t)hd.length, ==,
4143 item->frame.window_update.window_size_increment);
4144
4145 nghttp2_session_del(session);
4146 nghttp2_option_del(option);
4147
4148 /* It is invalid to change SETTINGS_NO_RFC7540_PRIORITIES in the
4149 following SETTINGS. */
4150 nghttp2_session_client_new(&session, &callbacks, NULL);
4151
4152 session->remote_settings.no_rfc7540_priorities = 1;
4153
4154 iv[0].settings_id = NGHTTP2_SETTINGS_NO_RFC7540_PRIORITIES;
4155 iv[0].value = 0;
4156
4157 nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE, dup_iv(iv, 1),
4158 1);
4159
4160 assert_int(0, ==, nghttp2_session_on_settings_received(session, &frame, 0));
4161
4162 nghttp2_frame_settings_free(&frame.settings, mem);
4163
4164 item = nghttp2_session_get_next_ob_item(session);
4165
4166 assert_not_null(item);
4167 assert_uint8(NGHTTP2_GOAWAY, ==, item->frame.hd.type);
4168
4169 nghttp2_session_del(session);
4170 }
4171
test_nghttp2_session_on_push_promise_received(void)4172 void test_nghttp2_session_on_push_promise_received(void) {
4173 nghttp2_session *session;
4174 nghttp2_session_callbacks callbacks;
4175 my_user_data user_data;
4176 nghttp2_frame frame;
4177 nghttp2_stream *stream, *promised_stream;
4178 nghttp2_outbound_item *item;
4179 nghttp2_nv malformed_nva[] = {MAKE_NV(":path", "\x01")};
4180 nghttp2_nv *nva;
4181 size_t nvlen;
4182 nghttp2_mem *mem;
4183 nghttp2_settings_entry iv = {NGHTTP2_SETTINGS_ENABLE_PUSH, 0};
4184
4185 mem = nghttp2_mem_default();
4186 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4187 callbacks.send_callback2 = null_send_callback;
4188 callbacks.on_begin_headers_callback = on_begin_headers_callback;
4189 callbacks.on_invalid_frame_recv_callback = on_invalid_frame_recv_callback;
4190
4191 nghttp2_session_client_new(&session, &callbacks, &user_data);
4192
4193 stream = open_sent_stream(session, 1);
4194
4195 nghttp2_frame_push_promise_init(&frame.push_promise, NGHTTP2_FLAG_END_HEADERS,
4196 1, 2, NULL, 0);
4197
4198 user_data.begin_headers_cb_called = 0;
4199 user_data.invalid_frame_recv_cb_called = 0;
4200
4201 assert_int(0, ==, nghttp2_session_on_push_promise_received(session, &frame));
4202
4203 assert_int(1, ==, user_data.begin_headers_cb_called);
4204 assert_size(1, ==, session->num_incoming_reserved_streams);
4205 promised_stream = nghttp2_session_get_stream(session, 2);
4206 assert_enum(nghttp2_stream_state, NGHTTP2_STREAM_RESERVED, ==,
4207 promised_stream->state);
4208 assert_int32(2, ==, session->last_recv_stream_id);
4209
4210 /* Attempt to PUSH_PROMISE against half close (remote) */
4211 nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_RD);
4212 frame.push_promise.promised_stream_id = 4;
4213
4214 user_data.begin_headers_cb_called = 0;
4215 user_data.invalid_frame_recv_cb_called = 0;
4216 assert_int(NGHTTP2_ERR_IGN_HEADER_BLOCK, ==,
4217 nghttp2_session_on_push_promise_received(session, &frame));
4218
4219 assert_int(0, ==, user_data.begin_headers_cb_called);
4220 assert_int(1, ==, user_data.invalid_frame_recv_cb_called);
4221 assert_size(1, ==, session->num_incoming_reserved_streams);
4222 assert_null(nghttp2_session_get_stream(session, 4));
4223 item = nghttp2_session_get_next_ob_item(session);
4224 assert_uint8(NGHTTP2_GOAWAY, ==, item->frame.hd.type);
4225 assert_uint32(NGHTTP2_STREAM_CLOSED, ==, item->frame.goaway.error_code);
4226 assert_int(0, ==, nghttp2_session_send(session));
4227 assert_int32(4, ==, session->last_recv_stream_id);
4228
4229 nghttp2_session_del(session);
4230
4231 nghttp2_session_client_new(&session, &callbacks, &user_data);
4232
4233 stream = open_sent_stream(session, 1);
4234
4235 /* Attempt to PUSH_PROMISE against stream in closing state */
4236 stream->state = NGHTTP2_STREAM_CLOSING;
4237 frame.push_promise.promised_stream_id = 6;
4238
4239 user_data.begin_headers_cb_called = 0;
4240 user_data.invalid_frame_recv_cb_called = 0;
4241 assert_int(NGHTTP2_ERR_IGN_HEADER_BLOCK, ==,
4242 nghttp2_session_on_push_promise_received(session, &frame));
4243
4244 assert_int(0, ==, user_data.begin_headers_cb_called);
4245 assert_size(0, ==, session->num_incoming_reserved_streams);
4246 assert_null(nghttp2_session_get_stream(session, 6));
4247 item = nghttp2_session_get_next_ob_item(session);
4248 assert_uint8(NGHTTP2_RST_STREAM, ==, item->frame.hd.type);
4249 assert_int32(6, ==, item->frame.hd.stream_id);
4250 assert_uint32(NGHTTP2_CANCEL, ==, item->frame.rst_stream.error_code);
4251 assert_int(0, ==, nghttp2_session_send(session));
4252
4253 /* Attempt to PUSH_PROMISE against idle stream */
4254 frame.hd.stream_id = 3;
4255 frame.push_promise.promised_stream_id = 8;
4256
4257 user_data.begin_headers_cb_called = 0;
4258 user_data.invalid_frame_recv_cb_called = 0;
4259 assert_int(NGHTTP2_ERR_IGN_HEADER_BLOCK, ==,
4260 nghttp2_session_on_push_promise_received(session, &frame));
4261
4262 assert_int(0, ==, user_data.begin_headers_cb_called);
4263 assert_size(0, ==, session->num_incoming_reserved_streams);
4264 assert_null(nghttp2_session_get_stream(session, 8));
4265 item = nghttp2_session_get_next_ob_item(session);
4266 assert_uint8(NGHTTP2_GOAWAY, ==, item->frame.hd.type);
4267 assert_int32(0, ==, item->frame.hd.stream_id);
4268 assert_uint32(NGHTTP2_PROTOCOL_ERROR, ==, item->frame.goaway.error_code);
4269 assert_int(0, ==, nghttp2_session_send(session));
4270
4271 nghttp2_session_del(session);
4272
4273 nghttp2_session_client_new(&session, &callbacks, &user_data);
4274
4275 stream = open_sent_stream(session, 1);
4276
4277 /* Same ID twice */
4278 frame.hd.stream_id = 1;
4279 frame.push_promise.promised_stream_id = 2;
4280
4281 user_data.begin_headers_cb_called = 0;
4282 user_data.invalid_frame_recv_cb_called = 0;
4283 assert_int(0, ==, nghttp2_session_on_push_promise_received(session, &frame));
4284
4285 assert_int(1, ==, user_data.begin_headers_cb_called);
4286 assert_size(1, ==, session->num_incoming_reserved_streams);
4287 assert_not_null(nghttp2_session_get_stream(session, 2));
4288
4289 user_data.begin_headers_cb_called = 0;
4290 user_data.invalid_frame_recv_cb_called = 0;
4291 assert_int(NGHTTP2_ERR_IGN_HEADER_BLOCK, ==,
4292 nghttp2_session_on_push_promise_received(session, &frame));
4293
4294 assert_int(0, ==, user_data.begin_headers_cb_called);
4295 assert_size(1, ==, session->num_incoming_reserved_streams);
4296 assert_null(nghttp2_session_get_stream(session, 8));
4297 item = nghttp2_session_get_next_ob_item(session);
4298 assert_uint8(NGHTTP2_GOAWAY, ==, item->frame.hd.type);
4299 assert_uint32(NGHTTP2_PROTOCOL_ERROR, ==, item->frame.goaway.error_code);
4300 assert_int(0, ==, nghttp2_session_send(session));
4301
4302 /* After GOAWAY, PUSH_PROMISE will be discarded */
4303 frame.push_promise.promised_stream_id = 10;
4304
4305 user_data.begin_headers_cb_called = 0;
4306 user_data.invalid_frame_recv_cb_called = 0;
4307 assert_int(NGHTTP2_ERR_IGN_HEADER_BLOCK, ==,
4308 nghttp2_session_on_push_promise_received(session, &frame));
4309
4310 assert_int(0, ==, user_data.begin_headers_cb_called);
4311 assert_size(1, ==, session->num_incoming_reserved_streams);
4312 assert_null(nghttp2_session_get_stream(session, 10));
4313 assert_null(nghttp2_session_get_next_ob_item(session));
4314
4315 nghttp2_frame_push_promise_free(&frame.push_promise, mem);
4316 nghttp2_session_del(session);
4317
4318 nghttp2_session_client_new(&session, &callbacks, &user_data);
4319
4320 open_recv_stream2(session, 2, NGHTTP2_STREAM_RESERVED);
4321
4322 /* Attempt to PUSH_PROMISE against reserved (remote) stream */
4323 nghttp2_frame_push_promise_init(&frame.push_promise, NGHTTP2_FLAG_END_HEADERS,
4324 2, 4, NULL, 0);
4325
4326 user_data.begin_headers_cb_called = 0;
4327 user_data.invalid_frame_recv_cb_called = 0;
4328 assert_int(NGHTTP2_ERR_IGN_HEADER_BLOCK, ==,
4329 nghttp2_session_on_push_promise_received(session, &frame));
4330
4331 assert_int(0, ==, user_data.begin_headers_cb_called);
4332 assert_int(1, ==, user_data.invalid_frame_recv_cb_called);
4333 assert_size(1, ==, session->num_incoming_reserved_streams);
4334
4335 nghttp2_frame_push_promise_free(&frame.push_promise, mem);
4336 nghttp2_session_del(session);
4337
4338 /* Disable PUSH */
4339 nghttp2_session_client_new(&session, &callbacks, &user_data);
4340
4341 open_sent_stream(session, 1);
4342
4343 session->local_settings.enable_push = 0;
4344
4345 nghttp2_frame_push_promise_init(&frame.push_promise, NGHTTP2_FLAG_END_HEADERS,
4346 1, 2, NULL, 0);
4347
4348 user_data.begin_headers_cb_called = 0;
4349 user_data.invalid_frame_recv_cb_called = 0;
4350 assert_int(NGHTTP2_ERR_IGN_HEADER_BLOCK, ==,
4351 nghttp2_session_on_push_promise_received(session, &frame));
4352
4353 assert_int(0, ==, user_data.begin_headers_cb_called);
4354 assert_int(1, ==, user_data.invalid_frame_recv_cb_called);
4355 assert_size(0, ==, session->num_incoming_reserved_streams);
4356
4357 nghttp2_frame_push_promise_free(&frame.push_promise, mem);
4358 nghttp2_session_del(session);
4359
4360 /* Check malformed headers. We accept malformed headers */
4361 nghttp2_session_client_new(&session, &callbacks, &user_data);
4362
4363 open_sent_stream(session, 1);
4364
4365 nvlen = ARRLEN(malformed_nva);
4366 nghttp2_nv_array_copy(&nva, malformed_nva, nvlen, mem);
4367 nghttp2_frame_push_promise_init(&frame.push_promise, NGHTTP2_FLAG_END_HEADERS,
4368 1, 2, nva, nvlen);
4369 user_data.begin_headers_cb_called = 0;
4370 user_data.invalid_frame_recv_cb_called = 0;
4371 assert_int(0, ==, nghttp2_session_on_push_promise_received(session, &frame));
4372
4373 assert_int(1, ==, user_data.begin_headers_cb_called);
4374 assert_int(0, ==, user_data.invalid_frame_recv_cb_called);
4375
4376 nghttp2_frame_push_promise_free(&frame.push_promise, mem);
4377 nghttp2_session_del(session);
4378
4379 /* If local_settings.enable_push = 0 is pending, but not acked from
4380 peer, incoming PUSH_PROMISE is rejected */
4381 nghttp2_session_client_new(&session, &callbacks, &user_data);
4382
4383 open_sent_stream(session, 1);
4384
4385 /* Submit settings with ENABLE_PUSH = 0 (thus disabling push) */
4386 nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, &iv, 1);
4387
4388 nghttp2_frame_push_promise_init(&frame.push_promise, NGHTTP2_FLAG_END_HEADERS,
4389 1, 2, NULL, 0);
4390
4391 assert_int(NGHTTP2_ERR_IGN_HEADER_BLOCK, ==,
4392 nghttp2_session_on_push_promise_received(session, &frame));
4393
4394 assert_size(0, ==, session->num_incoming_reserved_streams);
4395
4396 nghttp2_frame_push_promise_free(&frame.push_promise, mem);
4397 nghttp2_session_del(session);
4398
4399 /* Check max_incoming_reserved_streams */
4400 nghttp2_session_client_new(&session, &callbacks, &user_data);
4401 session->max_incoming_reserved_streams = 1;
4402
4403 open_sent_stream(session, 1);
4404 open_recv_stream2(session, 2, NGHTTP2_STREAM_RESERVED);
4405
4406 assert_size(1, ==, session->num_incoming_reserved_streams);
4407
4408 nghttp2_frame_push_promise_init(&frame.push_promise, NGHTTP2_FLAG_END_HEADERS,
4409 1, 4, NULL, 0);
4410
4411 assert_int(NGHTTP2_ERR_IGN_HEADER_BLOCK, ==,
4412 nghttp2_session_on_push_promise_received(session, &frame));
4413
4414 assert_size(1, ==, session->num_incoming_reserved_streams);
4415
4416 item = nghttp2_session_get_next_ob_item(session);
4417
4418 assert_uint8(NGHTTP2_RST_STREAM, ==, item->frame.hd.type);
4419 assert_uint32(NGHTTP2_CANCEL, ==, item->frame.rst_stream.error_code);
4420
4421 nghttp2_frame_push_promise_free(&frame.push_promise, mem);
4422 nghttp2_session_del(session);
4423 }
4424
test_nghttp2_session_on_ping_received(void)4425 void test_nghttp2_session_on_ping_received(void) {
4426 nghttp2_session *session;
4427 nghttp2_session_callbacks callbacks;
4428 my_user_data user_data;
4429 nghttp2_frame frame;
4430 nghttp2_outbound_item *top;
4431 const uint8_t opaque_data[] = "01234567";
4432 nghttp2_option *option;
4433
4434 user_data.frame_recv_cb_called = 0;
4435 user_data.invalid_frame_recv_cb_called = 0;
4436
4437 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4438 callbacks.on_frame_recv_callback = on_frame_recv_callback;
4439 callbacks.on_invalid_frame_recv_callback = on_invalid_frame_recv_callback;
4440
4441 nghttp2_session_client_new(&session, &callbacks, &user_data);
4442 nghttp2_frame_ping_init(&frame.ping, NGHTTP2_FLAG_ACK, opaque_data);
4443
4444 assert_int(0, ==, nghttp2_session_on_ping_received(session, &frame));
4445 assert_int(1, ==, user_data.frame_recv_cb_called);
4446
4447 /* Since this ping frame has ACK flag set, no further action is
4448 performed. */
4449 assert_null(nghttp2_outbound_queue_top(&session->ob_urgent));
4450
4451 /* Clear the flag, and receive it again */
4452 frame.hd.flags = NGHTTP2_FLAG_NONE;
4453
4454 assert_int(0, ==, nghttp2_session_on_ping_received(session, &frame));
4455 assert_int(2, ==, user_data.frame_recv_cb_called);
4456 top = nghttp2_outbound_queue_top(&session->ob_urgent);
4457 assert_uint8(NGHTTP2_PING, ==, top->frame.hd.type);
4458 assert_uint8(NGHTTP2_FLAG_ACK, ==, top->frame.hd.flags);
4459 assert_memory_equal(8, opaque_data, top->frame.ping.opaque_data);
4460
4461 nghttp2_frame_ping_free(&frame.ping);
4462 nghttp2_session_del(session);
4463
4464 /* Use nghttp2_option_set_no_auto_ping_ack() */
4465 nghttp2_option_new(&option);
4466 nghttp2_option_set_no_auto_ping_ack(option, 1);
4467
4468 nghttp2_session_server_new2(&session, &callbacks, &user_data, option);
4469 nghttp2_frame_ping_init(&frame.ping, NGHTTP2_FLAG_NONE, NULL);
4470
4471 user_data.frame_recv_cb_called = 0;
4472
4473 assert_int(0, ==, nghttp2_session_on_ping_received(session, &frame));
4474 assert_int(1, ==, user_data.frame_recv_cb_called);
4475 assert_null(nghttp2_outbound_queue_top(&session->ob_urgent));
4476
4477 nghttp2_frame_ping_free(&frame.ping);
4478 nghttp2_session_del(session);
4479 nghttp2_option_del(option);
4480 }
4481
test_nghttp2_session_on_goaway_received(void)4482 void test_nghttp2_session_on_goaway_received(void) {
4483 nghttp2_session *session;
4484 nghttp2_session_callbacks callbacks;
4485 my_user_data user_data;
4486 nghttp2_frame frame;
4487 int i;
4488 nghttp2_mem *mem;
4489 const uint8_t *data;
4490 nghttp2_ssize datalen;
4491
4492 mem = nghttp2_mem_default();
4493 user_data.frame_recv_cb_called = 0;
4494 user_data.invalid_frame_recv_cb_called = 0;
4495
4496 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4497 callbacks.on_frame_recv_callback = on_frame_recv_callback;
4498 callbacks.on_invalid_frame_recv_callback = on_invalid_frame_recv_callback;
4499 callbacks.on_stream_close_callback = on_stream_close_callback;
4500
4501 nghttp2_session_client_new(&session, &callbacks, &user_data);
4502
4503 for (i = 1; i <= 7; ++i) {
4504 if (nghttp2_session_is_my_stream_id(session, i)) {
4505 open_sent_stream(session, i);
4506 } else {
4507 open_recv_stream(session, i);
4508 }
4509 }
4510
4511 nghttp2_frame_goaway_init(&frame.goaway, 3, NGHTTP2_PROTOCOL_ERROR, NULL, 0);
4512
4513 user_data.stream_close_cb_called = 0;
4514
4515 assert_int(0, ==, nghttp2_session_on_goaway_received(session, &frame));
4516
4517 assert_int(1, ==, user_data.frame_recv_cb_called);
4518 assert_int32(3, ==, session->remote_last_stream_id);
4519 /* on_stream_close should be callsed for 2 times (stream 5 and 7) */
4520 assert_int(2, ==, user_data.stream_close_cb_called);
4521
4522 assert_not_null(nghttp2_session_get_stream(session, 1));
4523 assert_not_null(nghttp2_session_get_stream(session, 2));
4524 assert_not_null(nghttp2_session_get_stream(session, 3));
4525 assert_not_null(nghttp2_session_get_stream(session, 4));
4526 assert_null(nghttp2_session_get_stream(session, 5));
4527 assert_not_null(nghttp2_session_get_stream(session, 6));
4528 assert_null(nghttp2_session_get_stream(session, 7));
4529
4530 nghttp2_frame_goaway_free(&frame.goaway, mem);
4531 nghttp2_session_del(session);
4532
4533 /* Make sure that no memory leak when stream_close callback fails
4534 with a fatal error */
4535 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4536 callbacks.on_stream_close_callback = fatal_error_on_stream_close_callback;
4537
4538 memset(&user_data, 0, sizeof(user_data));
4539
4540 nghttp2_session_client_new(&session, &callbacks, &user_data);
4541
4542 nghttp2_frame_goaway_init(&frame.goaway, 0, NGHTTP2_NO_ERROR, NULL, 0);
4543
4544 assert_int(0, ==, nghttp2_session_on_goaway_received(session, &frame));
4545
4546 nghttp2_submit_request2(session, NULL, reqnv, ARRLEN(reqnv), NULL, NULL);
4547
4548 datalen = nghttp2_session_mem_send2(session, &data);
4549
4550 assert_ptrdiff(NGHTTP2_ERR_CALLBACK_FAILURE, ==, datalen);
4551 assert_int(1, ==, user_data.stream_close_cb_called);
4552
4553 nghttp2_frame_goaway_free(&frame.goaway, mem);
4554 nghttp2_session_del(session);
4555 }
4556
test_nghttp2_session_on_window_update_received(void)4557 void test_nghttp2_session_on_window_update_received(void) {
4558 nghttp2_session *session;
4559 nghttp2_session_callbacks callbacks;
4560 my_user_data user_data;
4561 nghttp2_frame frame;
4562 nghttp2_stream *stream;
4563 nghttp2_outbound_item *data_item;
4564 nghttp2_mem *mem;
4565
4566 mem = nghttp2_mem_default();
4567
4568 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4569 callbacks.on_frame_recv_callback = on_frame_recv_callback;
4570 callbacks.on_invalid_frame_recv_callback = on_invalid_frame_recv_callback;
4571 user_data.frame_recv_cb_called = 0;
4572 user_data.invalid_frame_recv_cb_called = 0;
4573
4574 nghttp2_session_client_new(&session, &callbacks, &user_data);
4575
4576 stream = open_sent_stream(session, 1);
4577
4578 data_item = create_data_ob_item(mem);
4579
4580 assert_int(0, ==, nghttp2_stream_attach_item(stream, data_item));
4581
4582 nghttp2_frame_window_update_init(&frame.window_update, NGHTTP2_FLAG_NONE, 1,
4583 16 * 1024);
4584
4585 assert_int(0, ==, nghttp2_session_on_window_update_received(session, &frame));
4586 assert_int(1, ==, user_data.frame_recv_cb_called);
4587 assert_int32(NGHTTP2_INITIAL_WINDOW_SIZE + 16 * 1024, ==,
4588 stream->remote_window_size);
4589
4590 nghttp2_stream_defer_item(stream, NGHTTP2_STREAM_FLAG_DEFERRED_FLOW_CONTROL);
4591
4592 assert_int(0, ==, nghttp2_session_on_window_update_received(session, &frame));
4593 assert_int(2, ==, user_data.frame_recv_cb_called);
4594 assert_int32(NGHTTP2_INITIAL_WINDOW_SIZE + 16 * 1024 * 2, ==,
4595 stream->remote_window_size);
4596 assert_false(stream->flags & NGHTTP2_STREAM_FLAG_DEFERRED_ALL);
4597
4598 nghttp2_frame_window_update_free(&frame.window_update);
4599
4600 /* Receiving WINDOW_UPDATE on reserved (remote) stream is a
4601 connection error */
4602 open_recv_stream2(session, 2, NGHTTP2_STREAM_RESERVED);
4603
4604 nghttp2_frame_window_update_init(&frame.window_update, NGHTTP2_FLAG_NONE, 2,
4605 4096);
4606
4607 assert_false(session->goaway_flags & NGHTTP2_GOAWAY_TERM_ON_SEND);
4608 assert_int(0, ==, nghttp2_session_on_window_update_received(session, &frame));
4609 assert_true(session->goaway_flags & NGHTTP2_GOAWAY_TERM_ON_SEND);
4610
4611 nghttp2_frame_window_update_free(&frame.window_update);
4612
4613 nghttp2_session_del(session);
4614
4615 /* Receiving WINDOW_UPDATE on reserved (local) stream is allowed */
4616 nghttp2_session_server_new(&session, &callbacks, &user_data);
4617
4618 stream = open_sent_stream2(session, 2, NGHTTP2_STREAM_RESERVED);
4619
4620 nghttp2_frame_window_update_init(&frame.window_update, NGHTTP2_FLAG_NONE, 2,
4621 4096);
4622
4623 assert_int(0, ==, nghttp2_session_on_window_update_received(session, &frame));
4624 assert_false(session->goaway_flags & NGHTTP2_GOAWAY_TERM_ON_SEND);
4625
4626 assert_int32(NGHTTP2_INITIAL_WINDOW_SIZE + 4096, ==,
4627 stream->remote_window_size);
4628
4629 nghttp2_frame_window_update_free(&frame.window_update);
4630
4631 nghttp2_session_del(session);
4632 }
4633
test_nghttp2_session_on_data_received(void)4634 void test_nghttp2_session_on_data_received(void) {
4635 nghttp2_session *session;
4636 nghttp2_session_callbacks callbacks;
4637 my_user_data user_data;
4638 nghttp2_outbound_item *top;
4639 nghttp2_stream *stream;
4640 nghttp2_frame frame;
4641
4642 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4643
4644 nghttp2_session_client_new(&session, &callbacks, &user_data);
4645 stream = open_recv_stream(session, 2);
4646
4647 nghttp2_frame_hd_init(&frame.hd, 4096, NGHTTP2_DATA, NGHTTP2_FLAG_NONE, 2);
4648
4649 assert_int(0, ==, nghttp2_session_on_data_received(session, &frame));
4650 assert_uint8(0, ==, stream->shut_flags);
4651
4652 frame.hd.flags = NGHTTP2_FLAG_END_STREAM;
4653
4654 assert_int(0, ==, nghttp2_session_on_data_received(session, &frame));
4655 assert_uint8(NGHTTP2_SHUT_RD, ==, stream->shut_flags);
4656
4657 /* If NGHTTP2_STREAM_CLOSING state, DATA frame is discarded. */
4658 open_sent_stream2(session, 1, NGHTTP2_STREAM_CLOSING);
4659
4660 frame.hd.flags = NGHTTP2_FLAG_NONE;
4661 frame.hd.stream_id = 1;
4662
4663 assert_int(0, ==, nghttp2_session_on_data_received(session, &frame));
4664 assert_null(nghttp2_outbound_queue_top(&session->ob_reg));
4665
4666 /* Check INVALID_STREAM case: DATA frame with stream ID which does
4667 not exist. */
4668
4669 frame.hd.stream_id = 3;
4670
4671 assert_int(0, ==, nghttp2_session_on_data_received(session, &frame));
4672 top = nghttp2_outbound_queue_top(&session->ob_reg);
4673 /* DATA against nonexistent stream is just ignored for now. */
4674 assert_null(top);
4675
4676 nghttp2_session_del(session);
4677 }
4678
test_nghttp2_session_on_data_received_fail_fast(void)4679 void test_nghttp2_session_on_data_received_fail_fast(void) {
4680 nghttp2_session *session;
4681 nghttp2_session_callbacks callbacks;
4682 uint8_t buf[9];
4683 nghttp2_stream *stream;
4684 nghttp2_frame_hd hd;
4685 nghttp2_outbound_item *item;
4686
4687 memset(&callbacks, 0, sizeof(callbacks));
4688
4689 nghttp2_frame_hd_init(&hd, 0, NGHTTP2_DATA, NGHTTP2_FLAG_NONE, 1);
4690 nghttp2_frame_pack_frame_hd(buf, &hd);
4691
4692 nghttp2_session_server_new(&session, &callbacks, NULL);
4693
4694 /* DATA to closed (remote) */
4695 stream = open_recv_stream(session, 1);
4696 nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_RD);
4697
4698 assert_ptrdiff((nghttp2_ssize)sizeof(buf), ==,
4699 nghttp2_session_mem_recv2(session, buf, sizeof(buf)));
4700
4701 item = nghttp2_session_get_next_ob_item(session);
4702
4703 assert_not_null(item);
4704 assert_uint8(NGHTTP2_GOAWAY, ==, item->frame.hd.type);
4705
4706 nghttp2_session_del(session);
4707
4708 nghttp2_session_server_new(&session, &callbacks, NULL);
4709
4710 /* DATA to closed stream with explicit closed (remote) */
4711 stream = open_recv_stream(session, 1);
4712 nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_RD);
4713 nghttp2_session_close_stream(session, 1, NGHTTP2_NO_ERROR);
4714
4715 assert_ptrdiff((nghttp2_ssize)sizeof(buf), ==,
4716 nghttp2_session_mem_recv2(session, buf, sizeof(buf)));
4717
4718 item = nghttp2_session_get_next_ob_item(session);
4719
4720 assert_not_null(item);
4721 assert_uint8(NGHTTP2_GOAWAY, ==, item->frame.hd.type);
4722
4723 nghttp2_session_del(session);
4724 }
4725
test_nghttp2_session_on_altsvc_received(void)4726 void test_nghttp2_session_on_altsvc_received(void) {
4727 nghttp2_session *session;
4728 nghttp2_session_callbacks callbacks;
4729 my_user_data ud;
4730 nghttp2_frame frame;
4731 nghttp2_option *option;
4732 uint8_t origin[] = "nghttp2.org";
4733 uint8_t field_value[] = "h2=\":443\"";
4734 int rv;
4735
4736 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4737 callbacks.on_frame_recv_callback = on_frame_recv_callback;
4738
4739 nghttp2_option_new(&option);
4740 nghttp2_option_set_builtin_recv_extension_type(option, NGHTTP2_ALTSVC);
4741
4742 nghttp2_session_client_new2(&session, &callbacks, &ud, option);
4743
4744 frame.ext.payload = &session->iframe.ext_frame_payload;
4745
4746 /* We just pass the strings without making a copy. This is OK,
4747 since we never call nghttp2_frame_altsvc_free(). */
4748 nghttp2_frame_altsvc_init(&frame.ext, 0, origin, sizeof(origin) - 1,
4749 field_value, sizeof(field_value) - 1);
4750
4751 ud.frame_recv_cb_called = 0;
4752 rv = nghttp2_session_on_altsvc_received(session, &frame);
4753
4754 assert_int(0, ==, rv);
4755 assert_int(1, ==, ud.frame_recv_cb_called);
4756
4757 nghttp2_session_del(session);
4758
4759 /* Receiving empty origin with stream ID == 0 */
4760 nghttp2_session_client_new2(&session, &callbacks, &ud, option);
4761
4762 frame.ext.payload = &session->iframe.ext_frame_payload;
4763
4764 nghttp2_frame_altsvc_init(&frame.ext, 0, origin, 0, field_value,
4765 sizeof(field_value) - 1);
4766
4767 ud.frame_recv_cb_called = 0;
4768 rv = nghttp2_session_on_altsvc_received(session, &frame);
4769
4770 assert_int(0, ==, rv);
4771 assert_int(0, ==, ud.frame_recv_cb_called);
4772
4773 nghttp2_session_del(session);
4774
4775 /* Receiving non-empty origin with stream ID != 0 */
4776 nghttp2_session_client_new2(&session, &callbacks, &ud, option);
4777
4778 frame.ext.payload = &session->iframe.ext_frame_payload;
4779
4780 open_sent_stream(session, 1);
4781
4782 nghttp2_frame_altsvc_init(&frame.ext, 1, origin, sizeof(origin) - 1,
4783 field_value, sizeof(field_value) - 1);
4784
4785 ud.frame_recv_cb_called = 0;
4786 rv = nghttp2_session_on_altsvc_received(session, &frame);
4787
4788 assert_int(0, ==, rv);
4789 assert_int(0, ==, ud.frame_recv_cb_called);
4790
4791 nghttp2_session_del(session);
4792
4793 /* Receiving empty origin with stream ID != 0; this is OK */
4794 nghttp2_session_client_new2(&session, &callbacks, &ud, option);
4795
4796 frame.ext.payload = &session->iframe.ext_frame_payload;
4797
4798 open_sent_stream(session, 1);
4799
4800 nghttp2_frame_altsvc_init(&frame.ext, 1, origin, 0, field_value,
4801 sizeof(field_value) - 1);
4802
4803 ud.frame_recv_cb_called = 0;
4804 rv = nghttp2_session_on_altsvc_received(session, &frame);
4805
4806 assert_int(0, ==, rv);
4807 assert_int(1, ==, ud.frame_recv_cb_called);
4808
4809 nghttp2_session_del(session);
4810
4811 /* Stream does not exist; ALTSVC will be ignored. */
4812 nghttp2_session_client_new2(&session, &callbacks, &ud, option);
4813
4814 frame.ext.payload = &session->iframe.ext_frame_payload;
4815
4816 nghttp2_frame_altsvc_init(&frame.ext, 1, origin, 0, field_value,
4817 sizeof(field_value) - 1);
4818
4819 ud.frame_recv_cb_called = 0;
4820 rv = nghttp2_session_on_altsvc_received(session, &frame);
4821
4822 assert_int(0, ==, rv);
4823 assert_int(0, ==, ud.frame_recv_cb_called);
4824
4825 nghttp2_session_del(session);
4826
4827 nghttp2_option_del(option);
4828 }
4829
test_nghttp2_session_send_headers_start_stream(void)4830 void test_nghttp2_session_send_headers_start_stream(void) {
4831 nghttp2_session *session;
4832 nghttp2_session_callbacks callbacks;
4833 nghttp2_outbound_item *item;
4834 nghttp2_frame *frame;
4835 nghttp2_stream *stream;
4836 nghttp2_mem *mem;
4837
4838 mem = nghttp2_mem_default();
4839
4840 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4841 callbacks.send_callback2 = null_send_callback;
4842
4843 nghttp2_session_client_new(&session, &callbacks, NULL);
4844
4845 item = mem->malloc(sizeof(nghttp2_outbound_item), NULL);
4846
4847 nghttp2_outbound_item_init(item);
4848
4849 frame = &item->frame;
4850
4851 nghttp2_frame_headers_init(&frame->headers, NGHTTP2_FLAG_END_HEADERS,
4852 (int32_t)session->next_stream_id,
4853 NGHTTP2_HCAT_REQUEST, NULL, NULL, 0);
4854 session->next_stream_id += 2;
4855
4856 nghttp2_session_add_item(session, item);
4857 assert_int(0, ==, nghttp2_session_send(session));
4858 stream = nghttp2_session_get_stream(session, 1);
4859 assert_enum(nghttp2_stream_state, NGHTTP2_STREAM_OPENING, ==, stream->state);
4860
4861 nghttp2_session_del(session);
4862 }
4863
test_nghttp2_session_send_headers_reply(void)4864 void test_nghttp2_session_send_headers_reply(void) {
4865 nghttp2_session *session;
4866 nghttp2_session_callbacks callbacks;
4867 nghttp2_outbound_item *item;
4868 nghttp2_frame *frame;
4869 nghttp2_stream *stream;
4870 nghttp2_mem *mem;
4871
4872 mem = nghttp2_mem_default();
4873
4874 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4875 callbacks.send_callback2 = null_send_callback;
4876
4877 assert_int(0, ==, nghttp2_session_server_new(&session, &callbacks, NULL));
4878 open_recv_stream2(session, 1, NGHTTP2_STREAM_OPENING);
4879
4880 item = mem->malloc(sizeof(nghttp2_outbound_item), NULL);
4881
4882 nghttp2_outbound_item_init(item);
4883
4884 frame = &item->frame;
4885
4886 nghttp2_frame_headers_init(&frame->headers, NGHTTP2_FLAG_END_HEADERS, 1,
4887 NGHTTP2_HCAT_HEADERS, NULL, NULL, 0);
4888 nghttp2_session_add_item(session, item);
4889 assert_int(0, ==, nghttp2_session_send(session));
4890 stream = nghttp2_session_get_stream(session, 1);
4891 assert_enum(nghttp2_stream_state, NGHTTP2_STREAM_OPENED, ==, stream->state);
4892
4893 nghttp2_session_del(session);
4894 }
4895
test_nghttp2_session_send_headers_frame_size_error(void)4896 void test_nghttp2_session_send_headers_frame_size_error(void) {
4897 nghttp2_session *session;
4898 nghttp2_session_callbacks callbacks;
4899 nghttp2_outbound_item *item;
4900 nghttp2_frame *frame;
4901 nghttp2_nv *nva;
4902 size_t nvlen;
4903 size_t vallen = NGHTTP2_HD_MAX_NV;
4904 nghttp2_nv nv[28];
4905 size_t nnv = ARRLEN(nv);
4906 size_t i;
4907 my_user_data ud;
4908 nghttp2_mem *mem;
4909
4910 mem = nghttp2_mem_default();
4911
4912 for (i = 0; i < nnv; ++i) {
4913 nv[i].name = (uint8_t *)"header";
4914 nv[i].namelen = strlen((const char *)nv[i].name);
4915 nv[i].value = mem->malloc(vallen + 1, NULL);
4916 memset(nv[i].value, '0' + (int)i, vallen);
4917 nv[i].value[vallen] = '\0';
4918 nv[i].valuelen = vallen;
4919 nv[i].flags = NGHTTP2_NV_FLAG_NONE;
4920 }
4921
4922 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4923 callbacks.send_callback2 = null_send_callback;
4924 callbacks.on_frame_not_send_callback = on_frame_not_send_callback;
4925
4926 nghttp2_session_client_new(&session, &callbacks, &ud);
4927 nvlen = nnv;
4928 nghttp2_nv_array_copy(&nva, nv, nvlen, mem);
4929
4930 item = mem->malloc(sizeof(nghttp2_outbound_item), NULL);
4931
4932 nghttp2_outbound_item_init(item);
4933
4934 frame = &item->frame;
4935
4936 nghttp2_frame_headers_init(&frame->headers, NGHTTP2_FLAG_END_HEADERS,
4937 (int32_t)session->next_stream_id,
4938 NGHTTP2_HCAT_REQUEST, NULL, nva, nvlen);
4939
4940 session->next_stream_id += 2;
4941
4942 nghttp2_session_add_item(session, item);
4943
4944 ud.frame_not_send_cb_called = 0;
4945
4946 assert_int(0, ==, nghttp2_session_send(session));
4947
4948 assert_int(1, ==, ud.frame_not_send_cb_called);
4949 assert_uint8(NGHTTP2_HEADERS, ==, ud.not_sent_frame_type);
4950 assert_int(NGHTTP2_ERR_FRAME_SIZE_ERROR, ==, ud.not_sent_error);
4951
4952 for (i = 0; i < nnv; ++i) {
4953 mem->free(nv[i].value, NULL);
4954 }
4955 nghttp2_session_del(session);
4956 }
4957
test_nghttp2_session_send_headers_push_reply(void)4958 void test_nghttp2_session_send_headers_push_reply(void) {
4959 nghttp2_session *session;
4960 nghttp2_session_callbacks callbacks;
4961 nghttp2_outbound_item *item;
4962 nghttp2_frame *frame;
4963 nghttp2_stream *stream;
4964 nghttp2_mem *mem;
4965
4966 mem = nghttp2_mem_default();
4967
4968 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4969 callbacks.send_callback2 = null_send_callback;
4970
4971 assert_int(0, ==, nghttp2_session_server_new(&session, &callbacks, NULL));
4972 open_sent_stream2(session, 2, NGHTTP2_STREAM_RESERVED);
4973
4974 item = mem->malloc(sizeof(nghttp2_outbound_item), NULL);
4975
4976 nghttp2_outbound_item_init(item);
4977
4978 frame = &item->frame;
4979
4980 nghttp2_frame_headers_init(&frame->headers, NGHTTP2_FLAG_END_HEADERS, 2,
4981 NGHTTP2_HCAT_HEADERS, NULL, NULL, 0);
4982 nghttp2_session_add_item(session, item);
4983 assert_size(0, ==, session->num_outgoing_streams);
4984 assert_int(0, ==, nghttp2_session_send(session));
4985 assert_size(1, ==, session->num_outgoing_streams);
4986 stream = nghttp2_session_get_stream(session, 2);
4987 assert_enum(nghttp2_stream_state, NGHTTP2_STREAM_OPENED, ==, stream->state);
4988 assert_false(stream->flags & NGHTTP2_STREAM_FLAG_PUSH);
4989 nghttp2_session_del(session);
4990 }
4991
test_nghttp2_session_send_rst_stream(void)4992 void test_nghttp2_session_send_rst_stream(void) {
4993 nghttp2_session *session;
4994 nghttp2_session_callbacks callbacks;
4995 my_user_data user_data;
4996 nghttp2_outbound_item *item;
4997 nghttp2_frame *frame;
4998 nghttp2_mem *mem;
4999
5000 mem = nghttp2_mem_default();
5001
5002 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
5003 callbacks.send_callback2 = null_send_callback;
5004 nghttp2_session_client_new(&session, &callbacks, &user_data);
5005 open_sent_stream(session, 1);
5006
5007 item = mem->malloc(sizeof(nghttp2_outbound_item), NULL);
5008
5009 nghttp2_outbound_item_init(item);
5010
5011 frame = &item->frame;
5012
5013 nghttp2_frame_rst_stream_init(&frame->rst_stream, 1, NGHTTP2_PROTOCOL_ERROR);
5014 nghttp2_session_add_item(session, item);
5015 assert_int(0, ==, nghttp2_session_send(session));
5016
5017 assert_null(nghttp2_session_get_stream(session, 1));
5018
5019 nghttp2_session_del(session);
5020 }
5021
test_nghttp2_session_send_push_promise(void)5022 void test_nghttp2_session_send_push_promise(void) {
5023 nghttp2_session *session;
5024 nghttp2_session_callbacks callbacks;
5025 nghttp2_outbound_item *item;
5026 nghttp2_frame *frame;
5027 nghttp2_stream *stream;
5028 nghttp2_settings_entry iv;
5029 my_user_data ud;
5030 nghttp2_mem *mem;
5031
5032 mem = nghttp2_mem_default();
5033 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
5034 callbacks.send_callback2 = null_send_callback;
5035 callbacks.on_frame_not_send_callback = on_frame_not_send_callback;
5036
5037 nghttp2_session_server_new(&session, &callbacks, &ud);
5038 open_recv_stream(session, 1);
5039
5040 item = mem->malloc(sizeof(nghttp2_outbound_item), NULL);
5041
5042 nghttp2_outbound_item_init(item);
5043
5044 frame = &item->frame;
5045
5046 nghttp2_frame_push_promise_init(&frame->push_promise,
5047 NGHTTP2_FLAG_END_HEADERS, 1,
5048 (int32_t)session->next_stream_id, NULL, 0);
5049
5050 session->next_stream_id += 2;
5051
5052 nghttp2_session_add_item(session, item);
5053
5054 assert_int(0, ==, nghttp2_session_send(session));
5055 stream = nghttp2_session_get_stream(session, 2);
5056 assert_enum(nghttp2_stream_state, NGHTTP2_STREAM_RESERVED, ==, stream->state);
5057
5058 /* Received ENABLE_PUSH = 0 */
5059 iv.settings_id = NGHTTP2_SETTINGS_ENABLE_PUSH;
5060 iv.value = 0;
5061 frame = mem->malloc(sizeof(nghttp2_frame), NULL);
5062 nghttp2_frame_settings_init(&frame->settings, NGHTTP2_FLAG_NONE,
5063 dup_iv(&iv, 1), 1);
5064 nghttp2_session_on_settings_received(session, frame, 1);
5065 nghttp2_frame_settings_free(&frame->settings, mem);
5066 mem->free(frame, NULL);
5067
5068 item = mem->malloc(sizeof(nghttp2_outbound_item), NULL);
5069
5070 nghttp2_outbound_item_init(item);
5071
5072 frame = &item->frame;
5073
5074 nghttp2_frame_push_promise_init(&frame->push_promise,
5075 NGHTTP2_FLAG_END_HEADERS, 1, -1, NULL, 0);
5076 nghttp2_session_add_item(session, item);
5077
5078 ud.frame_not_send_cb_called = 0;
5079 assert_int(0, ==, nghttp2_session_send(session));
5080
5081 assert_int(1, ==, ud.frame_not_send_cb_called);
5082 assert_uint8(NGHTTP2_PUSH_PROMISE, ==, ud.not_sent_frame_type);
5083 assert_int(NGHTTP2_ERR_PUSH_DISABLED, ==, ud.not_sent_error);
5084
5085 nghttp2_session_del(session);
5086
5087 /* PUSH_PROMISE from client is error */
5088 nghttp2_session_client_new(&session, &callbacks, &ud);
5089 open_sent_stream(session, 1);
5090 item = mem->malloc(sizeof(nghttp2_outbound_item), NULL);
5091
5092 nghttp2_outbound_item_init(item);
5093
5094 frame = &item->frame;
5095
5096 nghttp2_frame_push_promise_init(&frame->push_promise,
5097 NGHTTP2_FLAG_END_HEADERS, 1, -1, NULL, 0);
5098 nghttp2_session_add_item(session, item);
5099
5100 assert_int(0, ==, nghttp2_session_send(session));
5101 assert_null(nghttp2_session_get_stream(session, 3));
5102
5103 nghttp2_session_del(session);
5104 }
5105
test_nghttp2_session_is_my_stream_id(void)5106 void test_nghttp2_session_is_my_stream_id(void) {
5107 nghttp2_session *session;
5108 nghttp2_session_callbacks callbacks;
5109 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
5110 nghttp2_session_server_new(&session, &callbacks, NULL);
5111
5112 assert_false(nghttp2_session_is_my_stream_id(session, 0));
5113 assert_false(nghttp2_session_is_my_stream_id(session, 1));
5114 assert_true(nghttp2_session_is_my_stream_id(session, 2));
5115
5116 nghttp2_session_del(session);
5117
5118 nghttp2_session_client_new(&session, &callbacks, NULL);
5119
5120 assert_false(nghttp2_session_is_my_stream_id(session, 0));
5121 assert_true(nghttp2_session_is_my_stream_id(session, 1));
5122 assert_false(nghttp2_session_is_my_stream_id(session, 2));
5123
5124 nghttp2_session_del(session);
5125 }
5126
test_nghttp2_session_upgrade2(void)5127 void test_nghttp2_session_upgrade2(void) {
5128 nghttp2_session *session;
5129 nghttp2_session_callbacks callbacks;
5130 uint8_t settings_payload[128];
5131 size_t settings_payloadlen;
5132 nghttp2_settings_entry iv[16];
5133 nghttp2_stream *stream;
5134 nghttp2_outbound_item *item;
5135 nghttp2_ssize rv;
5136 nghttp2_bufs bufs;
5137 nghttp2_buf *buf;
5138 nghttp2_hd_deflater deflater;
5139 nghttp2_mem *mem;
5140
5141 mem = nghttp2_mem_default();
5142 frame_pack_bufs_init(&bufs);
5143
5144 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
5145 callbacks.send_callback2 = null_send_callback;
5146 iv[0].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS;
5147 iv[0].value = 1;
5148 iv[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
5149 iv[1].value = 4095;
5150 settings_payloadlen = (size_t)nghttp2_pack_settings_payload2(
5151 settings_payload, sizeof(settings_payload), iv, 2);
5152
5153 /* Check client side */
5154 nghttp2_session_client_new(&session, &callbacks, NULL);
5155 assert_int(0, ==,
5156 nghttp2_session_upgrade2(session, settings_payload,
5157 settings_payloadlen, 0, &callbacks));
5158 assert_int32(1, ==, session->last_sent_stream_id);
5159 stream = nghttp2_session_get_stream(session, 1);
5160 assert_not_null(stream);
5161 assert_ptr_equal(&callbacks, stream->stream_user_data);
5162 assert_uint8(NGHTTP2_SHUT_WR, ==, stream->shut_flags);
5163 item = nghttp2_session_get_next_ob_item(session);
5164 assert_uint8(NGHTTP2_SETTINGS, ==, item->frame.hd.type);
5165 assert_size(2, ==, item->frame.settings.niv);
5166 assert_int32(NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, ==,
5167 item->frame.settings.iv[0].settings_id);
5168 assert_uint32(1, ==, item->frame.settings.iv[0].value);
5169 assert_int32(NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE, ==,
5170 item->frame.settings.iv[1].settings_id);
5171 assert_uint32(4095, ==, item->frame.settings.iv[1].value);
5172
5173 /* Call nghttp2_session_upgrade2() again is error */
5174 assert_int(NGHTTP2_ERR_PROTO, ==,
5175 nghttp2_session_upgrade2(session, settings_payload,
5176 settings_payloadlen, 0, &callbacks));
5177 nghttp2_session_del(session);
5178
5179 /* Make sure that response from server can be received */
5180 nghttp2_session_client_new(&session, &callbacks, NULL);
5181
5182 assert_int(0, ==,
5183 nghttp2_session_upgrade2(session, settings_payload,
5184 settings_payloadlen, 0, &callbacks));
5185
5186 stream = nghttp2_session_get_stream(session, 1);
5187
5188 assert_enum(nghttp2_stream_state, NGHTTP2_STREAM_OPENING, ==, stream->state);
5189
5190 nghttp2_hd_deflate_init(&deflater, mem);
5191 rv = pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, resnv,
5192 ARRLEN(resnv), mem);
5193
5194 assert_ptrdiff(0, ==, rv);
5195
5196 buf = &bufs.head->buf;
5197
5198 rv = nghttp2_session_mem_recv2(session, buf->pos, nghttp2_buf_len(buf));
5199
5200 assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(buf), ==, rv);
5201 assert_enum(nghttp2_stream_state, NGHTTP2_STREAM_OPENED, ==, stream->state);
5202
5203 nghttp2_hd_deflate_free(&deflater);
5204 nghttp2_session_del(session);
5205
5206 nghttp2_bufs_reset(&bufs);
5207
5208 /* Check server side */
5209 nghttp2_session_server_new(&session, &callbacks, NULL);
5210 assert_int(0, ==,
5211 nghttp2_session_upgrade2(session, settings_payload,
5212 settings_payloadlen, 0, &callbacks));
5213 assert_int32(1, ==, session->last_recv_stream_id);
5214 stream = nghttp2_session_get_stream(session, 1);
5215 assert_not_null(stream);
5216 assert_null(stream->stream_user_data);
5217 assert_uint8(NGHTTP2_SHUT_RD, ==, stream->shut_flags);
5218 assert_null(nghttp2_session_get_next_ob_item(session));
5219 assert_uint32(1, ==, session->remote_settings.max_concurrent_streams);
5220 assert_uint32(4095, ==, session->remote_settings.initial_window_size);
5221 /* Call nghttp2_session_upgrade2() again is error */
5222 assert_int(NGHTTP2_ERR_PROTO, ==,
5223 nghttp2_session_upgrade2(session, settings_payload,
5224 settings_payloadlen, 0, &callbacks));
5225 nghttp2_session_del(session);
5226
5227 /* Empty SETTINGS is OK */
5228 settings_payloadlen = (size_t)nghttp2_pack_settings_payload2(
5229 settings_payload, sizeof(settings_payload), NULL, 0);
5230
5231 nghttp2_session_client_new(&session, &callbacks, NULL);
5232 assert_int(0, ==,
5233 nghttp2_session_upgrade2(session, settings_payload,
5234 settings_payloadlen, 0, NULL));
5235 nghttp2_session_del(session);
5236 nghttp2_bufs_free(&bufs);
5237 }
5238
test_nghttp2_session_reprioritize_stream(void)5239 void test_nghttp2_session_reprioritize_stream(void) {
5240 nghttp2_session *session;
5241 nghttp2_session_callbacks callbacks;
5242 nghttp2_stream *stream;
5243 nghttp2_stream *dep_stream;
5244 nghttp2_priority_spec pri_spec;
5245 int rv;
5246
5247 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
5248 callbacks.send_callback2 = block_count_send_callback;
5249
5250 nghttp2_session_server_new(&session, &callbacks, NULL);
5251
5252 stream = open_recv_stream(session, 1);
5253
5254 nghttp2_priority_spec_init(&pri_spec, 0, 10, 0);
5255
5256 rv = nghttp2_session_reprioritize_stream(session, stream, &pri_spec);
5257
5258 assert_int(0, ==, rv);
5259 assert_int32(10, ==, stream->weight);
5260 assert_ptr_equal(&session->root, stream->dep_prev);
5261
5262 /* If dependency to idle stream which is not in dependency tree yet */
5263
5264 nghttp2_priority_spec_init(&pri_spec, 3, 99, 0);
5265
5266 rv = nghttp2_session_reprioritize_stream(session, stream, &pri_spec);
5267
5268 assert_int(0, ==, rv);
5269 assert_int32(99, ==, stream->weight);
5270 assert_int32(3, ==, stream->dep_prev->stream_id);
5271
5272 dep_stream = nghttp2_session_get_stream_raw(session, 3);
5273
5274 assert_int32(NGHTTP2_DEFAULT_WEIGHT, ==, dep_stream->weight);
5275
5276 dep_stream = open_recv_stream(session, 3);
5277
5278 /* Change weight */
5279 pri_spec.weight = 128;
5280
5281 rv = nghttp2_session_reprioritize_stream(session, stream, &pri_spec);
5282
5283 assert_int(0, ==, rv);
5284 assert_int32(128, ==, stream->weight);
5285 assert_ptr_equal(dep_stream, stream->dep_prev);
5286
5287 /* Change weight again to test short-path case */
5288 pri_spec.weight = 100;
5289
5290 rv = nghttp2_session_reprioritize_stream(session, stream, &pri_spec);
5291
5292 assert_int(0, ==, rv);
5293 assert_int32(100, ==, stream->weight);
5294 assert_ptr_equal(dep_stream, stream->dep_prev);
5295 assert_int32(100, ==, dep_stream->sum_dep_weight);
5296
5297 /* Test circular dependency; stream 1 is first removed and becomes
5298 root. Then stream 3 depends on it. */
5299 nghttp2_priority_spec_init(&pri_spec, 1, 1, 0);
5300
5301 rv = nghttp2_session_reprioritize_stream(session, dep_stream, &pri_spec);
5302
5303 assert_int(0, ==, rv);
5304 assert_int32(1, ==, dep_stream->weight);
5305 assert_ptr_equal(stream, dep_stream->dep_prev);
5306
5307 /* Making priority to closed stream will result in default
5308 priority */
5309 session->last_recv_stream_id = 9;
5310
5311 nghttp2_priority_spec_init(&pri_spec, 5, 5, 0);
5312
5313 rv = nghttp2_session_reprioritize_stream(session, stream, &pri_spec);
5314
5315 assert_int(0, ==, rv);
5316 assert_int32(NGHTTP2_DEFAULT_WEIGHT, ==, stream->weight);
5317
5318 nghttp2_session_del(session);
5319
5320 nghttp2_session_server_new(&session, &callbacks, NULL);
5321
5322 /* circular dependency; in case of stream which is not a direct
5323 descendant of root. Use exclusive dependency. */
5324 stream = open_recv_stream(session, 1);
5325 stream = open_recv_stream_with_dep(session, 3, stream);
5326 stream = open_recv_stream_with_dep(session, 5, stream);
5327 stream = open_recv_stream_with_dep(session, 7, stream);
5328 open_recv_stream_with_dep(session, 9, stream);
5329
5330 nghttp2_priority_spec_init(&pri_spec, 7, 1, 1);
5331
5332 stream = nghttp2_session_get_stream(session, 3);
5333 rv = nghttp2_session_reprioritize_stream(session, stream, &pri_spec);
5334
5335 assert_int(0, ==, rv);
5336 assert_int32(7, ==, stream->dep_prev->stream_id);
5337
5338 stream = nghttp2_session_get_stream(session, 7);
5339
5340 assert_int32(1, ==, stream->dep_prev->stream_id);
5341
5342 stream = nghttp2_session_get_stream(session, 9);
5343
5344 assert_int32(3, ==, stream->dep_prev->stream_id);
5345
5346 stream = nghttp2_session_get_stream(session, 5);
5347
5348 assert_int32(3, ==, stream->dep_prev->stream_id);
5349
5350 nghttp2_session_del(session);
5351
5352 nghttp2_session_server_new(&session, &callbacks, NULL);
5353
5354 /* circular dependency; in case of stream which is not a direct
5355 descendant of root. Without exclusive dependency. */
5356 stream = open_recv_stream(session, 1);
5357 stream = open_recv_stream_with_dep(session, 3, stream);
5358 stream = open_recv_stream_with_dep(session, 5, stream);
5359 stream = open_recv_stream_with_dep(session, 7, stream);
5360 open_recv_stream_with_dep(session, 9, stream);
5361
5362 nghttp2_priority_spec_init(&pri_spec, 7, 1, 0);
5363
5364 stream = nghttp2_session_get_stream(session, 3);
5365 rv = nghttp2_session_reprioritize_stream(session, stream, &pri_spec);
5366
5367 assert_int(0, ==, rv);
5368 assert_int32(7, ==, stream->dep_prev->stream_id);
5369
5370 stream = nghttp2_session_get_stream(session, 7);
5371
5372 assert_int32(1, ==, stream->dep_prev->stream_id);
5373
5374 stream = nghttp2_session_get_stream(session, 9);
5375
5376 assert_int32(7, ==, stream->dep_prev->stream_id);
5377
5378 stream = nghttp2_session_get_stream(session, 5);
5379
5380 assert_int32(3, ==, stream->dep_prev->stream_id);
5381
5382 nghttp2_session_del(session);
5383 }
5384
test_nghttp2_session_reprioritize_stream_with_idle_stream_dep(void)5385 void test_nghttp2_session_reprioritize_stream_with_idle_stream_dep(void) {
5386 nghttp2_session *session;
5387 nghttp2_session_callbacks callbacks;
5388 nghttp2_stream *stream;
5389 nghttp2_priority_spec pri_spec;
5390
5391 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
5392 callbacks.send_callback2 = block_count_send_callback;
5393
5394 nghttp2_session_server_new(&session, &callbacks, NULL);
5395
5396 stream = open_recv_stream(session, 1);
5397
5398 session->pending_local_max_concurrent_stream = 1;
5399
5400 nghttp2_priority_spec_init(&pri_spec, 101, 10, 0);
5401
5402 nghttp2_session_reprioritize_stream(session, stream, &pri_spec);
5403
5404 /* idle stream is not counteed to max concurrent streams */
5405
5406 assert_int32(10, ==, stream->weight);
5407 assert_int32(101, ==, stream->dep_prev->stream_id);
5408
5409 stream = nghttp2_session_get_stream_raw(session, 101);
5410
5411 assert_int32(NGHTTP2_DEFAULT_WEIGHT, ==, stream->weight);
5412
5413 nghttp2_session_del(session);
5414 }
5415
test_nghttp2_submit_data(void)5416 void test_nghttp2_submit_data(void) {
5417 nghttp2_session *session;
5418 nghttp2_session_callbacks callbacks;
5419 nghttp2_data_provider2 data_prd;
5420 my_user_data ud;
5421 nghttp2_frame *frame;
5422 nghttp2_frame_hd hd;
5423 nghttp2_active_outbound_item *aob;
5424 nghttp2_bufs *framebufs;
5425 nghttp2_buf *buf;
5426
5427 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
5428 callbacks.send_callback2 = block_count_send_callback;
5429
5430 data_prd.read_callback = fixed_length_data_source_read_callback;
5431 ud.data_source_length = NGHTTP2_DATA_PAYLOADLEN * 2;
5432 assert_int(0, ==, nghttp2_session_client_new(&session, &callbacks, &ud));
5433 aob = &session->aob;
5434 framebufs = &aob->framebufs;
5435
5436 open_sent_stream(session, 1);
5437
5438 assert_int(
5439 0, ==,
5440 nghttp2_submit_data2(session, NGHTTP2_FLAG_END_STREAM, 1, &data_prd));
5441
5442 ud.block_count = 0;
5443 assert_int(0, ==, nghttp2_session_send(session));
5444 frame = &aob->item->frame;
5445
5446 buf = &framebufs->head->buf;
5447 nghttp2_frame_unpack_frame_hd(&hd, buf->pos);
5448
5449 assert_uint8(NGHTTP2_FLAG_NONE, ==, hd.flags);
5450 assert_uint8(NGHTTP2_FLAG_NONE, ==, frame->hd.flags);
5451 /* aux_data.data.flags has these flags */
5452 assert_uint8(NGHTTP2_FLAG_END_STREAM, ==, aob->item->aux_data.data.flags);
5453
5454 nghttp2_session_del(session);
5455 }
5456
test_nghttp2_submit_data_read_length_too_large(void)5457 void test_nghttp2_submit_data_read_length_too_large(void) {
5458 nghttp2_session *session;
5459 nghttp2_session_callbacks callbacks;
5460 nghttp2_data_provider2 data_prd;
5461 my_user_data ud;
5462 nghttp2_frame *frame;
5463 nghttp2_frame_hd hd;
5464 nghttp2_active_outbound_item *aob;
5465 nghttp2_bufs *framebufs;
5466 nghttp2_buf *buf;
5467 size_t payloadlen;
5468
5469 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
5470 callbacks.send_callback2 = block_count_send_callback;
5471 callbacks.read_length_callback2 = too_large_data_source_length_callback;
5472
5473 data_prd.read_callback = fixed_length_data_source_read_callback;
5474 ud.data_source_length = NGHTTP2_DATA_PAYLOADLEN * 2;
5475 assert_int(0, ==, nghttp2_session_client_new(&session, &callbacks, &ud));
5476 aob = &session->aob;
5477 framebufs = &aob->framebufs;
5478
5479 open_sent_stream(session, 1);
5480
5481 assert_int(
5482 0, ==,
5483 nghttp2_submit_data2(session, NGHTTP2_FLAG_END_STREAM, 1, &data_prd));
5484
5485 ud.block_count = 0;
5486 assert_int(0, ==, nghttp2_session_send(session));
5487 frame = &aob->item->frame;
5488
5489 buf = &framebufs->head->buf;
5490 nghttp2_frame_unpack_frame_hd(&hd, buf->pos);
5491
5492 assert_uint8(NGHTTP2_FLAG_NONE, ==, hd.flags);
5493 assert_uint8(NGHTTP2_FLAG_NONE, ==, frame->hd.flags);
5494 assert_size(16384, ==, hd.length);
5495 /* aux_data.data.flags has these flags */
5496 assert_uint8(NGHTTP2_FLAG_END_STREAM, ==, aob->item->aux_data.data.flags);
5497
5498 nghttp2_session_del(session);
5499
5500 /* Check that buffers are expanded */
5501 assert_int(0, ==, nghttp2_session_client_new(&session, &callbacks, &ud));
5502
5503 ud.data_source_length = NGHTTP2_MAX_FRAME_SIZE_MAX;
5504
5505 session->remote_settings.max_frame_size = NGHTTP2_MAX_FRAME_SIZE_MAX;
5506
5507 open_sent_stream(session, 1);
5508
5509 assert_int(
5510 0, ==,
5511 nghttp2_submit_data2(session, NGHTTP2_FLAG_END_STREAM, 1, &data_prd));
5512
5513 ud.block_count = 0;
5514 assert_int(0, ==, nghttp2_session_send(session));
5515
5516 aob = &session->aob;
5517
5518 frame = &aob->item->frame;
5519
5520 framebufs = &aob->framebufs;
5521
5522 buf = &framebufs->head->buf;
5523 nghttp2_frame_unpack_frame_hd(&hd, buf->pos);
5524
5525 payloadlen = nghttp2_min_size(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE,
5526 NGHTTP2_INITIAL_WINDOW_SIZE);
5527
5528 assert_size(NGHTTP2_FRAME_HDLEN + 1 + payloadlen, ==,
5529 (size_t)nghttp2_buf_cap(buf));
5530 assert_uint8(NGHTTP2_FLAG_NONE, ==, hd.flags);
5531 assert_uint8(NGHTTP2_FLAG_NONE, ==, frame->hd.flags);
5532 assert_size(payloadlen, ==, hd.length);
5533 /* aux_data.data.flags has these flags */
5534 assert_uint8(NGHTTP2_FLAG_END_STREAM, ==, aob->item->aux_data.data.flags);
5535
5536 nghttp2_session_del(session);
5537 }
5538
test_nghttp2_submit_data_read_length_smallest(void)5539 void test_nghttp2_submit_data_read_length_smallest(void) {
5540 nghttp2_session *session;
5541 nghttp2_session_callbacks callbacks;
5542 nghttp2_data_provider2 data_prd;
5543 my_user_data ud;
5544 nghttp2_frame *frame;
5545 nghttp2_frame_hd hd;
5546 nghttp2_active_outbound_item *aob;
5547 nghttp2_bufs *framebufs;
5548 nghttp2_buf *buf;
5549
5550 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
5551 callbacks.send_callback2 = block_count_send_callback;
5552 callbacks.read_length_callback2 = smallest_length_data_source_length_callback;
5553
5554 data_prd.read_callback = fixed_length_data_source_read_callback;
5555 ud.data_source_length = NGHTTP2_DATA_PAYLOADLEN * 2;
5556 assert_int(0, ==, nghttp2_session_client_new(&session, &callbacks, &ud));
5557 aob = &session->aob;
5558 framebufs = &aob->framebufs;
5559
5560 open_sent_stream(session, 1);
5561
5562 assert_int(
5563 0, ==,
5564 nghttp2_submit_data2(session, NGHTTP2_FLAG_END_STREAM, 1, &data_prd));
5565
5566 ud.block_count = 0;
5567 assert_int(0, ==, nghttp2_session_send(session));
5568 frame = &aob->item->frame;
5569
5570 buf = &framebufs->head->buf;
5571 nghttp2_frame_unpack_frame_hd(&hd, buf->pos);
5572
5573 assert_uint8(NGHTTP2_FLAG_NONE, ==, hd.flags);
5574 assert_uint8(NGHTTP2_FLAG_NONE, ==, frame->hd.flags);
5575 assert_size(1, ==, hd.length);
5576 /* aux_data.data.flags has these flags */
5577 assert_uint8(NGHTTP2_FLAG_END_STREAM, ==, aob->item->aux_data.data.flags);
5578
5579 nghttp2_session_del(session);
5580 }
5581
submit_data_twice_data_source_read_callback(nghttp2_session * session,int32_t stream_id,uint8_t * buf,size_t len,uint32_t * data_flags,nghttp2_data_source * source,void * user_data)5582 static nghttp2_ssize submit_data_twice_data_source_read_callback(
5583 nghttp2_session *session, int32_t stream_id, uint8_t *buf, size_t len,
5584 uint32_t *data_flags, nghttp2_data_source *source, void *user_data) {
5585 (void)session;
5586 (void)stream_id;
5587 (void)buf;
5588 (void)source;
5589 (void)user_data;
5590
5591 *data_flags |= NGHTTP2_DATA_FLAG_EOF;
5592 return (nghttp2_ssize)nghttp2_min_size(len, 16);
5593 }
5594
submit_data_twice_on_frame_send_callback(nghttp2_session * session,const nghttp2_frame * frame,void * user_data)5595 static int submit_data_twice_on_frame_send_callback(nghttp2_session *session,
5596 const nghttp2_frame *frame,
5597 void *user_data) {
5598 static int called = 0;
5599 int rv;
5600 nghttp2_data_provider2 data_prd;
5601 (void)user_data;
5602
5603 if (called == 0) {
5604 called = 1;
5605
5606 data_prd.read_callback = submit_data_twice_data_source_read_callback;
5607
5608 rv = nghttp2_submit_data2(session, NGHTTP2_FLAG_END_STREAM,
5609 frame->hd.stream_id, &data_prd);
5610 assert_int(0, ==, rv);
5611 }
5612
5613 return 0;
5614 }
5615
test_nghttp2_submit_data_twice(void)5616 void test_nghttp2_submit_data_twice(void) {
5617 nghttp2_session *session;
5618 nghttp2_session_callbacks callbacks;
5619 nghttp2_data_provider2 data_prd;
5620 my_user_data ud;
5621 accumulator acc;
5622
5623 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
5624 callbacks.send_callback2 = accumulator_send_callback;
5625 callbacks.on_frame_send_callback = submit_data_twice_on_frame_send_callback;
5626
5627 data_prd.read_callback = submit_data_twice_data_source_read_callback;
5628
5629 acc.length = 0;
5630 ud.acc = &acc;
5631
5632 assert_int(0, ==, nghttp2_session_client_new(&session, &callbacks, &ud));
5633
5634 open_sent_stream(session, 1);
5635
5636 assert_int(0, ==,
5637 nghttp2_submit_data2(session, NGHTTP2_FLAG_NONE, 1, &data_prd));
5638 assert_int(0, ==, nghttp2_session_send(session));
5639
5640 /* We should have sent 2 DATA frame with 16 bytes payload each */
5641 assert_size(NGHTTP2_FRAME_HDLEN * 2 + 16 * 2, ==, acc.length);
5642
5643 nghttp2_session_del(session);
5644 }
5645
test_nghttp2_submit_request_with_data(void)5646 void test_nghttp2_submit_request_with_data(void) {
5647 nghttp2_session *session;
5648 nghttp2_session_callbacks callbacks;
5649 nghttp2_data_provider2 data_prd;
5650 my_user_data ud;
5651 nghttp2_outbound_item *item;
5652 nghttp2_mem *mem;
5653
5654 mem = nghttp2_mem_default();
5655
5656 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
5657 callbacks.send_callback2 = null_send_callback;
5658
5659 data_prd.read_callback = fixed_length_data_source_read_callback;
5660 ud.data_source_length = 64 * 1024 - 1;
5661 assert_int(0, ==, nghttp2_session_client_new(&session, &callbacks, &ud));
5662 assert_int32(1, ==,
5663 nghttp2_submit_request2(session, NULL, reqnv, ARRLEN(reqnv),
5664 &data_prd, NULL));
5665 item = nghttp2_session_get_next_ob_item(session);
5666 assert_size(ARRLEN(reqnv), ==, item->frame.headers.nvlen);
5667 assert_nv_equal(reqnv, item->frame.headers.nva, item->frame.headers.nvlen,
5668 mem);
5669 assert_int(0, ==, nghttp2_session_send(session));
5670 assert_size(0, ==, ud.data_source_length);
5671
5672 nghttp2_session_del(session);
5673
5674 /* nghttp2_submit_request2() with server session is error */
5675 nghttp2_session_server_new(&session, &callbacks, NULL);
5676
5677 assert_int32(
5678 NGHTTP2_ERR_PROTO, ==,
5679 nghttp2_submit_request2(session, NULL, reqnv, ARRLEN(reqnv), NULL, NULL));
5680
5681 nghttp2_session_del(session);
5682 }
5683
test_nghttp2_submit_request_without_data(void)5684 void test_nghttp2_submit_request_without_data(void) {
5685 nghttp2_session *session;
5686 nghttp2_session_callbacks callbacks;
5687 accumulator acc;
5688 nghttp2_data_provider2 data_prd = {{-1}, NULL};
5689 nghttp2_outbound_item *item;
5690 my_user_data ud;
5691 nghttp2_frame frame;
5692 nghttp2_hd_inflater inflater;
5693 nva_out out;
5694 nghttp2_bufs bufs;
5695 nghttp2_mem *mem;
5696 nghttp2_priority_spec pri_spec;
5697
5698 mem = nghttp2_mem_default();
5699 frame_pack_bufs_init(&bufs);
5700
5701 nva_out_init(&out);
5702 acc.length = 0;
5703 ud.acc = &acc;
5704 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
5705 callbacks.send_callback2 = accumulator_send_callback;
5706 assert_int(0, ==, nghttp2_session_client_new(&session, &callbacks, &ud));
5707
5708 nghttp2_hd_inflate_init(&inflater, mem);
5709 assert_int32(1, ==,
5710 nghttp2_submit_request2(session, NULL, reqnv, ARRLEN(reqnv),
5711 &data_prd, NULL));
5712 item = nghttp2_session_get_next_ob_item(session);
5713 assert_size(ARRLEN(reqnv), ==, item->frame.headers.nvlen);
5714 assert_nv_equal(reqnv, item->frame.headers.nva, item->frame.headers.nvlen,
5715 mem);
5716 assert_true(item->frame.hd.flags & NGHTTP2_FLAG_END_STREAM);
5717
5718 assert_int(0, ==, nghttp2_session_send(session));
5719 assert_int(0, ==, unpack_frame(&frame, acc.buf, acc.length));
5720
5721 nghttp2_bufs_add(&bufs, acc.buf, acc.length);
5722 inflate_hd(&inflater, &out, &bufs, NGHTTP2_FRAME_HDLEN, mem);
5723
5724 assert_size(ARRLEN(reqnv), ==, out.nvlen);
5725 assert_nv_equal(reqnv, out.nva, out.nvlen, mem);
5726 nghttp2_frame_headers_free(&frame.headers, mem);
5727 nva_out_reset(&out, mem);
5728
5729 nghttp2_bufs_free(&bufs);
5730 nghttp2_hd_inflate_free(&inflater);
5731
5732 /* Try to depend on itself is error */
5733 nghttp2_priority_spec_init(&pri_spec, (int32_t)session->next_stream_id, 16,
5734 0);
5735
5736 assert_int32(NGHTTP2_ERR_INVALID_ARGUMENT, ==,
5737 nghttp2_submit_request2(session, &pri_spec, reqnv, ARRLEN(reqnv),
5738 NULL, NULL));
5739
5740 nghttp2_session_del(session);
5741 }
5742
test_nghttp2_submit_response_with_data(void)5743 void test_nghttp2_submit_response_with_data(void) {
5744 nghttp2_session *session;
5745 nghttp2_session_callbacks callbacks;
5746 nghttp2_data_provider2 data_prd;
5747 my_user_data ud;
5748 nghttp2_outbound_item *item;
5749 nghttp2_mem *mem;
5750
5751 mem = nghttp2_mem_default();
5752
5753 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
5754 callbacks.send_callback2 = null_send_callback;
5755
5756 data_prd.read_callback = fixed_length_data_source_read_callback;
5757 ud.data_source_length = 64 * 1024 - 1;
5758 assert_int(0, ==, nghttp2_session_server_new(&session, &callbacks, &ud));
5759 open_recv_stream2(session, 1, NGHTTP2_STREAM_OPENING);
5760 assert_int(
5761 0, ==,
5762 nghttp2_submit_response2(session, 1, resnv, ARRLEN(resnv), &data_prd));
5763 item = nghttp2_session_get_next_ob_item(session);
5764 assert_size(ARRLEN(resnv), ==, item->frame.headers.nvlen);
5765 assert_nv_equal(resnv, item->frame.headers.nva, item->frame.headers.nvlen,
5766 mem);
5767 assert_int(0, ==, nghttp2_session_send(session));
5768 assert_size(0, ==, ud.data_source_length);
5769
5770 nghttp2_session_del(session);
5771
5772 /* Various error cases */
5773 nghttp2_session_client_new(&session, &callbacks, NULL);
5774
5775 /* Calling nghttp2_submit_response2() with client session is error */
5776 assert_int(NGHTTP2_ERR_PROTO, ==,
5777 nghttp2_submit_response2(session, 1, resnv, ARRLEN(resnv), NULL));
5778
5779 /* Stream ID <= 0 is error */
5780 assert_int(NGHTTP2_ERR_INVALID_ARGUMENT, ==,
5781 nghttp2_submit_response2(session, 0, resnv, ARRLEN(resnv), NULL));
5782
5783 nghttp2_session_del(session);
5784 }
5785
test_nghttp2_submit_response_without_data(void)5786 void test_nghttp2_submit_response_without_data(void) {
5787 nghttp2_session *session;
5788 nghttp2_session_callbacks callbacks;
5789 accumulator acc;
5790 nghttp2_data_provider2 data_prd = {{-1}, NULL};
5791 nghttp2_outbound_item *item;
5792 my_user_data ud;
5793 nghttp2_frame frame;
5794 nghttp2_hd_inflater inflater;
5795 nva_out out;
5796 nghttp2_bufs bufs;
5797 nghttp2_mem *mem;
5798
5799 mem = nghttp2_mem_default();
5800 frame_pack_bufs_init(&bufs);
5801
5802 nva_out_init(&out);
5803 acc.length = 0;
5804 ud.acc = &acc;
5805 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
5806 callbacks.send_callback2 = accumulator_send_callback;
5807 assert_int(0, ==, nghttp2_session_server_new(&session, &callbacks, &ud));
5808
5809 nghttp2_hd_inflate_init(&inflater, mem);
5810 open_recv_stream2(session, 1, NGHTTP2_STREAM_OPENING);
5811 assert_int(
5812 0, ==,
5813 nghttp2_submit_response2(session, 1, resnv, ARRLEN(resnv), &data_prd));
5814 item = nghttp2_session_get_next_ob_item(session);
5815 assert_size(ARRLEN(resnv), ==, item->frame.headers.nvlen);
5816 assert_nv_equal(resnv, item->frame.headers.nva, item->frame.headers.nvlen,
5817 mem);
5818 assert_true(item->frame.hd.flags & NGHTTP2_FLAG_END_STREAM);
5819
5820 assert_int(0, ==, nghttp2_session_send(session));
5821 assert_int(0, ==, unpack_frame(&frame, acc.buf, acc.length));
5822
5823 nghttp2_bufs_add(&bufs, acc.buf, acc.length);
5824 inflate_hd(&inflater, &out, &bufs, NGHTTP2_FRAME_HDLEN, mem);
5825
5826 assert_size(ARRLEN(resnv), ==, out.nvlen);
5827 assert_nv_equal(resnv, out.nva, out.nvlen, mem);
5828
5829 nva_out_reset(&out, mem);
5830 nghttp2_bufs_free(&bufs);
5831 nghttp2_frame_headers_free(&frame.headers, mem);
5832 nghttp2_hd_inflate_free(&inflater);
5833 nghttp2_session_del(session);
5834 }
5835
test_nghttp2_submit_response_push_response(void)5836 void test_nghttp2_submit_response_push_response(void) {
5837 nghttp2_session *session;
5838 nghttp2_session_callbacks callbacks;
5839 my_user_data ud;
5840
5841 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
5842 callbacks.send_callback2 = null_send_callback;
5843 callbacks.on_frame_not_send_callback = on_frame_not_send_callback;
5844
5845 nghttp2_session_server_new(&session, &callbacks, &ud);
5846
5847 open_sent_stream2(session, 2, NGHTTP2_STREAM_RESERVED);
5848
5849 session->goaway_flags |= NGHTTP2_GOAWAY_RECV;
5850
5851 assert_int(0, ==,
5852 nghttp2_submit_response2(session, 2, resnv, ARRLEN(resnv), NULL));
5853
5854 ud.frame_not_send_cb_called = 0;
5855
5856 assert_int(0, ==, nghttp2_session_send(session));
5857 assert_int(1, ==, ud.frame_not_send_cb_called);
5858
5859 nghttp2_session_del(session);
5860 }
5861
test_nghttp2_submit_trailer(void)5862 void test_nghttp2_submit_trailer(void) {
5863 nghttp2_session *session;
5864 nghttp2_session_callbacks callbacks;
5865 accumulator acc;
5866 nghttp2_data_provider2 data_prd;
5867 nghttp2_outbound_item *item;
5868 my_user_data ud;
5869 nghttp2_frame frame;
5870 nghttp2_hd_inflater inflater;
5871 nva_out out;
5872 nghttp2_bufs bufs;
5873 nghttp2_mem *mem;
5874
5875 mem = nghttp2_mem_default();
5876 frame_pack_bufs_init(&bufs);
5877
5878 data_prd.read_callback = no_end_stream_data_source_read_callback;
5879 nva_out_init(&out);
5880 acc.length = 0;
5881 ud.acc = &acc;
5882 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
5883 callbacks.send_callback2 = null_send_callback;
5884 assert_int(0, ==, nghttp2_session_server_new(&session, &callbacks, &ud));
5885
5886 nghttp2_hd_inflate_init(&inflater, mem);
5887 open_recv_stream2(session, 1, NGHTTP2_STREAM_OPENING);
5888 assert_int(
5889 0, ==,
5890 nghttp2_submit_response2(session, 1, resnv, ARRLEN(resnv), &data_prd));
5891 assert_int(0, ==, nghttp2_session_send(session));
5892
5893 assert_int(0, ==,
5894 nghttp2_submit_trailer(session, 1, trailernv, ARRLEN(trailernv)));
5895
5896 session->callbacks.send_callback2 = accumulator_send_callback;
5897
5898 item = nghttp2_session_get_next_ob_item(session);
5899 assert_uint8(NGHTTP2_HEADERS, ==, item->frame.hd.type);
5900 assert_enum(nghttp2_headers_category, NGHTTP2_HCAT_HEADERS, ==,
5901 item->frame.headers.cat);
5902 assert_true(item->frame.hd.flags & NGHTTP2_FLAG_END_STREAM);
5903
5904 assert_int(0, ==, nghttp2_session_send(session));
5905 assert_int(0, ==, unpack_frame(&frame, acc.buf, acc.length));
5906
5907 nghttp2_bufs_add(&bufs, acc.buf, acc.length);
5908 inflate_hd(&inflater, &out, &bufs, NGHTTP2_FRAME_HDLEN, mem);
5909
5910 assert_size(ARRLEN(trailernv), ==, out.nvlen);
5911 assert_nv_equal(trailernv, out.nva, out.nvlen, mem);
5912
5913 nva_out_reset(&out, mem);
5914 nghttp2_bufs_free(&bufs);
5915 nghttp2_frame_headers_free(&frame.headers, mem);
5916 nghttp2_hd_inflate_free(&inflater);
5917 nghttp2_session_del(session);
5918
5919 /* Specifying stream ID <= 0 is error */
5920 nghttp2_session_server_new(&session, &callbacks, NULL);
5921 open_recv_stream(session, 1);
5922
5923 assert_int(NGHTTP2_ERR_INVALID_ARGUMENT, ==,
5924 nghttp2_submit_trailer(session, 0, trailernv, ARRLEN(trailernv)));
5925
5926 assert_int(NGHTTP2_ERR_INVALID_ARGUMENT, ==,
5927 nghttp2_submit_trailer(session, -1, trailernv, ARRLEN(trailernv)));
5928
5929 nghttp2_session_del(session);
5930 }
5931
test_nghttp2_submit_headers_start_stream(void)5932 void test_nghttp2_submit_headers_start_stream(void) {
5933 nghttp2_session *session;
5934 nghttp2_session_callbacks callbacks;
5935 nghttp2_outbound_item *item;
5936 nghttp2_mem *mem;
5937
5938 mem = nghttp2_mem_default();
5939
5940 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
5941 assert_int(0, ==, nghttp2_session_client_new(&session, &callbacks, NULL));
5942 assert_int32(1, ==,
5943 nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, -1,
5944 NULL, reqnv, ARRLEN(reqnv), NULL));
5945 item = nghttp2_session_get_next_ob_item(session);
5946 assert_size(ARRLEN(reqnv), ==, item->frame.headers.nvlen);
5947 assert_nv_equal(reqnv, item->frame.headers.nva, item->frame.headers.nvlen,
5948 mem);
5949 assert_uint8((NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM), ==,
5950 item->frame.hd.flags);
5951 assert_false(item->frame.hd.flags & NGHTTP2_FLAG_PRIORITY);
5952
5953 nghttp2_session_del(session);
5954 }
5955
test_nghttp2_submit_headers_reply(void)5956 void test_nghttp2_submit_headers_reply(void) {
5957 nghttp2_session *session;
5958 nghttp2_session_callbacks callbacks;
5959 my_user_data ud;
5960 nghttp2_outbound_item *item;
5961 nghttp2_stream *stream;
5962 nghttp2_mem *mem;
5963
5964 mem = nghttp2_mem_default();
5965
5966 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
5967 callbacks.send_callback2 = null_send_callback;
5968 callbacks.on_frame_send_callback = on_frame_send_callback;
5969
5970 assert_int(0, ==, nghttp2_session_server_new(&session, &callbacks, &ud));
5971 assert_int32(0, ==,
5972 nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, 1, NULL,
5973 resnv, ARRLEN(resnv), NULL));
5974 item = nghttp2_session_get_next_ob_item(session);
5975 assert_size(ARRLEN(resnv), ==, item->frame.headers.nvlen);
5976 assert_nv_equal(resnv, item->frame.headers.nva, item->frame.headers.nvlen,
5977 mem);
5978 assert_uint8((NGHTTP2_FLAG_END_STREAM | NGHTTP2_FLAG_END_HEADERS), ==,
5979 item->frame.hd.flags);
5980
5981 ud.frame_send_cb_called = 0;
5982 ud.sent_frame_type = 0;
5983 /* The transimission will be canceled because the stream 1 is not
5984 open. */
5985 assert_int(0, ==, nghttp2_session_send(session));
5986 assert_int(0, ==, ud.frame_send_cb_called);
5987
5988 stream = open_recv_stream2(session, 1, NGHTTP2_STREAM_OPENING);
5989
5990 assert_int32(0, ==,
5991 nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, 1, NULL,
5992 resnv, ARRLEN(resnv), NULL));
5993 assert_int(0, ==, nghttp2_session_send(session));
5994 assert_int(1, ==, ud.frame_send_cb_called);
5995 assert_uint8(NGHTTP2_HEADERS, ==, ud.sent_frame_type);
5996 assert_true(stream->shut_flags & NGHTTP2_SHUT_WR);
5997
5998 nghttp2_session_del(session);
5999 }
6000
test_nghttp2_submit_headers_push_reply(void)6001 void test_nghttp2_submit_headers_push_reply(void) {
6002 nghttp2_session *session;
6003 nghttp2_session_callbacks callbacks;
6004 my_user_data ud;
6005 nghttp2_stream *stream;
6006 int foo;
6007
6008 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6009 callbacks.send_callback2 = null_send_callback;
6010 callbacks.on_frame_send_callback = on_frame_send_callback;
6011
6012 assert_int(0, ==, nghttp2_session_server_new(&session, &callbacks, &ud));
6013 stream = open_sent_stream2(session, 2, NGHTTP2_STREAM_RESERVED);
6014 assert_int32(0, ==,
6015 nghttp2_submit_headers(session, NGHTTP2_FLAG_NONE, 2, NULL,
6016 resnv, ARRLEN(resnv), &foo));
6017
6018 ud.frame_send_cb_called = 0;
6019 ud.sent_frame_type = 0;
6020 assert_int(0, ==, nghttp2_session_send(session));
6021 assert_int(1, ==, ud.frame_send_cb_called);
6022 assert_uint8(NGHTTP2_HEADERS, ==, ud.sent_frame_type);
6023 assert_enum(nghttp2_stream_state, NGHTTP2_STREAM_OPENED, ==, stream->state);
6024 assert_ptr_equal(&foo, stream->stream_user_data);
6025
6026 nghttp2_session_del(session);
6027
6028 /* Sending HEADERS from client against stream in reserved state is
6029 error */
6030 assert_int(0, ==, nghttp2_session_client_new(&session, &callbacks, &ud));
6031 open_recv_stream2(session, 2, NGHTTP2_STREAM_RESERVED);
6032 assert_int32(0, ==,
6033 nghttp2_submit_headers(session, NGHTTP2_FLAG_NONE, 2, NULL,
6034 reqnv, ARRLEN(reqnv), NULL));
6035
6036 ud.frame_send_cb_called = 0;
6037 ud.sent_frame_type = 0;
6038 assert_int(0, ==, nghttp2_session_send(session));
6039 assert_int(0, ==, ud.frame_send_cb_called);
6040
6041 nghttp2_session_del(session);
6042 }
6043
test_nghttp2_submit_headers(void)6044 void test_nghttp2_submit_headers(void) {
6045 nghttp2_session *session;
6046 nghttp2_session_callbacks callbacks;
6047 my_user_data ud;
6048 nghttp2_outbound_item *item;
6049 nghttp2_stream *stream;
6050 accumulator acc;
6051 nghttp2_frame frame;
6052 nghttp2_hd_inflater inflater;
6053 nva_out out;
6054 nghttp2_bufs bufs;
6055 nghttp2_mem *mem;
6056 nghttp2_priority_spec pri_spec;
6057
6058 mem = nghttp2_mem_default();
6059 frame_pack_bufs_init(&bufs);
6060
6061 nva_out_init(&out);
6062 acc.length = 0;
6063 ud.acc = &acc;
6064 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6065 callbacks.send_callback2 = accumulator_send_callback;
6066 callbacks.on_frame_send_callback = on_frame_send_callback;
6067
6068 assert_int(0, ==, nghttp2_session_client_new(&session, &callbacks, &ud));
6069
6070 nghttp2_hd_inflate_init(&inflater, mem);
6071 assert_int32(0, ==,
6072 nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, 1, NULL,
6073 reqnv, ARRLEN(reqnv), NULL));
6074 item = nghttp2_session_get_next_ob_item(session);
6075 assert_size(ARRLEN(reqnv), ==, item->frame.headers.nvlen);
6076 assert_nv_equal(reqnv, item->frame.headers.nva, item->frame.headers.nvlen,
6077 mem);
6078 assert_uint8((NGHTTP2_FLAG_END_STREAM | NGHTTP2_FLAG_END_HEADERS), ==,
6079 item->frame.hd.flags);
6080
6081 ud.frame_send_cb_called = 0;
6082 ud.sent_frame_type = 0;
6083 /* The transimission will be canceled because the stream 1 is not
6084 open. */
6085 assert_int(0, ==, nghttp2_session_send(session));
6086 assert_int(0, ==, ud.frame_send_cb_called);
6087
6088 stream = open_sent_stream(session, 1);
6089
6090 assert_int32(0, ==,
6091 nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, 1, NULL,
6092 reqnv, ARRLEN(reqnv), NULL));
6093 assert_int(0, ==, nghttp2_session_send(session));
6094 assert_int(1, ==, ud.frame_send_cb_called);
6095 assert_uint8(NGHTTP2_HEADERS, ==, ud.sent_frame_type);
6096 assert_true(stream->shut_flags & NGHTTP2_SHUT_WR);
6097
6098 assert_int(0, ==, unpack_frame(&frame, acc.buf, acc.length));
6099
6100 nghttp2_bufs_add(&bufs, acc.buf, acc.length);
6101 inflate_hd(&inflater, &out, &bufs, NGHTTP2_FRAME_HDLEN, mem);
6102
6103 assert_size(ARRLEN(reqnv), ==, out.nvlen);
6104 assert_nv_equal(reqnv, out.nva, out.nvlen, mem);
6105
6106 nva_out_reset(&out, mem);
6107 nghttp2_bufs_free(&bufs);
6108 nghttp2_frame_headers_free(&frame.headers, mem);
6109
6110 nghttp2_hd_inflate_free(&inflater);
6111
6112 /* Try to depend on itself */
6113 nghttp2_priority_spec_init(&pri_spec, 3, 16, 0);
6114
6115 assert_int32(NGHTTP2_ERR_INVALID_ARGUMENT, ==,
6116 nghttp2_submit_headers(session, NGHTTP2_FLAG_NONE, 3, &pri_spec,
6117 reqnv, ARRLEN(reqnv), NULL));
6118
6119 session->next_stream_id = 5;
6120 nghttp2_priority_spec_init(&pri_spec, 5, 16, 0);
6121
6122 assert_int32(NGHTTP2_ERR_INVALID_ARGUMENT, ==,
6123 nghttp2_submit_headers(session, NGHTTP2_FLAG_NONE, -1, &pri_spec,
6124 reqnv, ARRLEN(reqnv), NULL));
6125
6126 nghttp2_session_del(session);
6127
6128 /* Error cases with invalid stream ID */
6129 nghttp2_session_server_new(&session, &callbacks, NULL);
6130
6131 /* Sending nghttp2_submit_headers() with stream_id == 1 and server
6132 session is error */
6133 assert_int32(NGHTTP2_ERR_PROTO, ==,
6134 nghttp2_submit_headers(session, NGHTTP2_FLAG_NONE, -1, NULL,
6135 reqnv, ARRLEN(reqnv), NULL));
6136
6137 /* Sending stream ID <= 0 is error */
6138 assert_int32(NGHTTP2_ERR_INVALID_ARGUMENT, ==,
6139 nghttp2_submit_headers(session, NGHTTP2_FLAG_NONE, 0, NULL,
6140 resnv, ARRLEN(resnv), NULL));
6141
6142 nghttp2_session_del(session);
6143 }
6144
test_nghttp2_submit_headers_continuation(void)6145 void test_nghttp2_submit_headers_continuation(void) {
6146 nghttp2_session *session;
6147 nghttp2_session_callbacks callbacks;
6148 nghttp2_nv nv[] = {
6149 MAKE_NV("h1", ""), MAKE_NV("h1", ""), MAKE_NV("h1", ""), MAKE_NV("h1", ""),
6150 MAKE_NV("h1", ""), MAKE_NV("h1", ""), MAKE_NV("h1", ""),
6151 };
6152 nghttp2_outbound_item *item;
6153 uint8_t data[4096];
6154 size_t i;
6155 my_user_data ud;
6156
6157 memset(data, '0', sizeof(data));
6158 for (i = 0; i < ARRLEN(nv); ++i) {
6159 nv[i].valuelen = sizeof(data);
6160 nv[i].value = data;
6161 }
6162
6163 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6164 callbacks.send_callback2 = null_send_callback;
6165 callbacks.on_frame_send_callback = on_frame_send_callback;
6166
6167 assert_int(0, ==, nghttp2_session_client_new(&session, &callbacks, &ud));
6168 assert_int32(1, ==,
6169 nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, -1,
6170 NULL, nv, ARRLEN(nv), NULL));
6171 item = nghttp2_session_get_next_ob_item(session);
6172 assert_uint8(NGHTTP2_HEADERS, ==, item->frame.hd.type);
6173 assert_uint8((NGHTTP2_FLAG_END_STREAM | NGHTTP2_FLAG_END_HEADERS), ==,
6174 item->frame.hd.flags);
6175 assert_false(item->frame.hd.flags & NGHTTP2_FLAG_PRIORITY);
6176
6177 ud.frame_send_cb_called = 0;
6178 assert_int(0, ==, nghttp2_session_send(session));
6179 assert_int(1, ==, ud.frame_send_cb_called);
6180
6181 nghttp2_session_del(session);
6182 }
6183
test_nghttp2_submit_headers_continuation_extra_large(void)6184 void test_nghttp2_submit_headers_continuation_extra_large(void) {
6185 nghttp2_session *session;
6186 nghttp2_session_callbacks callbacks;
6187 nghttp2_nv nv[] = {
6188 MAKE_NV("h1", ""), MAKE_NV("h1", ""), MAKE_NV("h1", ""),
6189 MAKE_NV("h1", ""), MAKE_NV("h1", ""), MAKE_NV("h1", ""),
6190 };
6191 nghttp2_outbound_item *item;
6192 uint8_t data[16384];
6193 size_t i;
6194 my_user_data ud;
6195 nghttp2_option *opt;
6196
6197 memset(data, '0', sizeof(data));
6198 for (i = 0; i < ARRLEN(nv); ++i) {
6199 nv[i].valuelen = sizeof(data);
6200 nv[i].value = data;
6201 }
6202
6203 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6204 callbacks.send_callback2 = null_send_callback;
6205 callbacks.on_frame_send_callback = on_frame_send_callback;
6206
6207 /* The default size of max send header block length is too small to
6208 send these header fields. Expand it. */
6209 nghttp2_option_new(&opt);
6210 nghttp2_option_set_max_send_header_block_length(opt, 102400);
6211
6212 assert_int(0, ==,
6213 nghttp2_session_client_new2(&session, &callbacks, &ud, opt));
6214 assert_int32(1, ==,
6215 nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, -1,
6216 NULL, nv, ARRLEN(nv), NULL));
6217 item = nghttp2_session_get_next_ob_item(session);
6218 assert_uint8(NGHTTP2_HEADERS, ==, item->frame.hd.type);
6219 assert_uint8((NGHTTP2_FLAG_END_STREAM | NGHTTP2_FLAG_END_HEADERS), ==,
6220 item->frame.hd.flags);
6221 assert_false(item->frame.hd.flags & NGHTTP2_FLAG_PRIORITY);
6222
6223 ud.frame_send_cb_called = 0;
6224 assert_int(0, ==, nghttp2_session_send(session));
6225 assert_int(1, ==, ud.frame_send_cb_called);
6226
6227 nghttp2_session_del(session);
6228 nghttp2_option_del(opt);
6229 }
6230
test_nghttp2_submit_priority(void)6231 void test_nghttp2_submit_priority(void) {
6232 nghttp2_session *session;
6233 nghttp2_session_callbacks callbacks;
6234 nghttp2_stream *stream;
6235 my_user_data ud;
6236 nghttp2_priority_spec pri_spec;
6237
6238 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6239 callbacks.send_callback2 = null_send_callback;
6240 callbacks.on_frame_send_callback = on_frame_send_callback;
6241
6242 nghttp2_session_client_new(&session, &callbacks, &ud);
6243 stream = open_sent_stream(session, 1);
6244
6245 nghttp2_priority_spec_init(&pri_spec, 0, 3, 0);
6246
6247 /* depends on stream 0 */
6248 assert_int(0, ==,
6249 nghttp2_submit_priority(session, NGHTTP2_FLAG_NONE, 1, &pri_spec));
6250 assert_int(0, ==, nghttp2_session_send(session));
6251 assert_int32(3, ==, stream->weight);
6252
6253 /* submit against idle stream */
6254 assert_int(0, ==,
6255 nghttp2_submit_priority(session, NGHTTP2_FLAG_NONE, 3, &pri_spec));
6256
6257 ud.frame_send_cb_called = 0;
6258 assert_int(0, ==, nghttp2_session_send(session));
6259 assert_int(1, ==, ud.frame_send_cb_called);
6260
6261 nghttp2_session_del(session);
6262 }
6263
test_nghttp2_submit_settings(void)6264 void test_nghttp2_submit_settings(void) {
6265 nghttp2_session *session;
6266 nghttp2_session_callbacks callbacks;
6267 my_user_data ud;
6268 nghttp2_outbound_item *item;
6269 nghttp2_frame *frame;
6270 nghttp2_settings_entry iv[7];
6271 nghttp2_frame ack_frame;
6272 const int32_t UNKNOWN_ID = 1000000007;
6273 nghttp2_mem *mem;
6274
6275 mem = nghttp2_mem_default();
6276
6277 iv[0].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS;
6278 iv[0].value = 5;
6279
6280 iv[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
6281 iv[1].value = 16 * 1024;
6282
6283 iv[2].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS;
6284 iv[2].value = 50;
6285
6286 iv[3].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
6287 iv[3].value = 111;
6288
6289 iv[4].settings_id = UNKNOWN_ID;
6290 iv[4].value = 999;
6291
6292 iv[5].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
6293 iv[5].value = 1023;
6294
6295 iv[6].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
6296 iv[6].value = (uint32_t)NGHTTP2_MAX_WINDOW_SIZE + 1;
6297
6298 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6299 callbacks.send_callback2 = null_send_callback;
6300 callbacks.on_frame_send_callback = on_frame_send_callback;
6301 nghttp2_session_server_new(&session, &callbacks, &ud);
6302
6303 assert_int(NGHTTP2_ERR_INVALID_ARGUMENT, ==,
6304 nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, iv, 7));
6305
6306 /* Make sure that local settings are not changed */
6307 assert_uint32(NGHTTP2_DEFAULT_MAX_CONCURRENT_STREAMS, ==,
6308 session->local_settings.max_concurrent_streams);
6309 assert_uint32(NGHTTP2_INITIAL_WINDOW_SIZE, ==,
6310 session->local_settings.initial_window_size);
6311
6312 /* Now sends without 6th one */
6313 assert_int(0, ==, nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, iv, 6));
6314
6315 item = nghttp2_session_get_next_ob_item(session);
6316
6317 assert_uint8(NGHTTP2_SETTINGS, ==, item->frame.hd.type);
6318
6319 frame = &item->frame;
6320 assert_size(6, ==, frame->settings.niv);
6321 assert_uint32(5, ==, frame->settings.iv[0].value);
6322 assert_int32(NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, ==,
6323 frame->settings.iv[0].settings_id);
6324
6325 assert_uint32(16 * 1024, ==, frame->settings.iv[1].value);
6326 assert_int32(NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE, ==,
6327 frame->settings.iv[1].settings_id);
6328
6329 assert_int32(UNKNOWN_ID, ==, frame->settings.iv[4].settings_id);
6330 assert_uint32(999, ==, frame->settings.iv[4].value);
6331
6332 ud.frame_send_cb_called = 0;
6333 assert_int(0, ==, nghttp2_session_send(session));
6334 assert_int(1, ==, ud.frame_send_cb_called);
6335
6336 assert_uint32(50, ==, session->pending_local_max_concurrent_stream);
6337
6338 /* before receiving SETTINGS ACK, local settings have still default
6339 values */
6340 assert_uint32(NGHTTP2_DEFAULT_MAX_CONCURRENT_STREAMS, ==,
6341 nghttp2_session_get_local_settings(
6342 session, NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS));
6343 assert_uint32(NGHTTP2_INITIAL_WINDOW_SIZE, ==,
6344 nghttp2_session_get_local_settings(
6345 session, NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE));
6346
6347 nghttp2_frame_settings_init(&ack_frame.settings, NGHTTP2_FLAG_ACK, NULL, 0);
6348 assert_int(0, ==,
6349 nghttp2_session_on_settings_received(session, &ack_frame, 0));
6350 nghttp2_frame_settings_free(&ack_frame.settings, mem);
6351
6352 assert_uint32(16 * 1024, ==, session->local_settings.initial_window_size);
6353 assert_size(111, ==, session->hd_inflater.ctx.hd_table_bufsize_max);
6354 assert_size(111, ==, session->hd_inflater.min_hd_table_bufsize_max);
6355 assert_uint32(50, ==, session->local_settings.max_concurrent_streams);
6356
6357 assert_uint32(50, ==,
6358 nghttp2_session_get_local_settings(
6359 session, NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS));
6360 assert_uint32(16 * 1024, ==,
6361 nghttp2_session_get_local_settings(
6362 session, NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE));
6363
6364 /* We just keep the last seen value */
6365 assert_uint32(50, ==, session->pending_local_max_concurrent_stream);
6366
6367 nghttp2_session_del(session);
6368
6369 /* Bail out if there are contradicting
6370 SETTINGS_NO_RFC7540_PRIORITIES in one SETTINGS. */
6371 nghttp2_session_server_new(&session, &callbacks, &ud);
6372
6373 iv[0].settings_id = NGHTTP2_SETTINGS_NO_RFC7540_PRIORITIES;
6374 iv[0].value = 1;
6375 iv[1].settings_id = NGHTTP2_SETTINGS_NO_RFC7540_PRIORITIES;
6376 iv[1].value = 0;
6377
6378 assert_int(NGHTTP2_ERR_INVALID_ARGUMENT, ==,
6379 nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, iv, 2));
6380
6381 nghttp2_session_del(session);
6382
6383 /* Attempt to change SETTINGS_NO_RFC7540_PRIORITIES in the 2nd
6384 SETTINGS. */
6385 nghttp2_session_server_new(&session, &callbacks, &ud);
6386
6387 iv[0].settings_id = NGHTTP2_SETTINGS_NO_RFC7540_PRIORITIES;
6388 iv[0].value = 1;
6389
6390 assert_int(0, ==, nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, iv, 1));
6391
6392 iv[0].settings_id = NGHTTP2_SETTINGS_NO_RFC7540_PRIORITIES;
6393 iv[0].value = 0;
6394
6395 assert_int(NGHTTP2_ERR_INVALID_ARGUMENT, ==,
6396 nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, iv, 1));
6397
6398 nghttp2_session_del(session);
6399 }
6400
test_nghttp2_submit_settings_update_local_window_size(void)6401 void test_nghttp2_submit_settings_update_local_window_size(void) {
6402 nghttp2_session *session;
6403 nghttp2_session_callbacks callbacks;
6404 nghttp2_outbound_item *item;
6405 nghttp2_settings_entry iv[4];
6406 nghttp2_stream *stream;
6407 nghttp2_frame ack_frame;
6408 nghttp2_mem *mem;
6409 nghttp2_option *option;
6410
6411 mem = nghttp2_mem_default();
6412 nghttp2_frame_settings_init(&ack_frame.settings, NGHTTP2_FLAG_ACK, NULL, 0);
6413
6414 iv[0].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
6415 iv[0].value = 16 * 1024;
6416
6417 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6418 callbacks.send_callback2 = null_send_callback;
6419
6420 nghttp2_session_server_new(&session, &callbacks, NULL);
6421
6422 stream = open_recv_stream(session, 1);
6423 stream->local_window_size = NGHTTP2_INITIAL_WINDOW_SIZE + 100;
6424 stream->recv_window_size = 32768;
6425
6426 open_recv_stream(session, 3);
6427
6428 assert_int(0, ==, nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, iv, 1));
6429 assert_int(0, ==, nghttp2_session_send(session));
6430 assert_int(0, ==,
6431 nghttp2_session_on_settings_received(session, &ack_frame, 0));
6432
6433 stream = nghttp2_session_get_stream(session, 1);
6434 assert_int32(0, ==, stream->recv_window_size);
6435 assert_int32(16 * 1024 + 100, ==, stream->local_window_size);
6436
6437 stream = nghttp2_session_get_stream(session, 3);
6438 assert_int32(16 * 1024, ==, stream->local_window_size);
6439
6440 item = nghttp2_session_get_next_ob_item(session);
6441 assert_uint8(NGHTTP2_WINDOW_UPDATE, ==, item->frame.hd.type);
6442 assert_int32(32768, ==, item->frame.window_update.window_size_increment);
6443
6444 nghttp2_session_del(session);
6445
6446 /* Without auto-window update */
6447 nghttp2_option_new(&option);
6448 nghttp2_option_set_no_auto_window_update(option, 1);
6449
6450 nghttp2_session_server_new2(&session, &callbacks, NULL, option);
6451
6452 nghttp2_option_del(option);
6453
6454 stream = open_recv_stream(session, 1);
6455 stream->local_window_size = NGHTTP2_INITIAL_WINDOW_SIZE + 100;
6456 stream->recv_window_size = 32768;
6457
6458 assert_int(0, ==, nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, iv, 1));
6459 assert_int(0, ==, nghttp2_session_send(session));
6460 assert_int(0, ==,
6461 nghttp2_session_on_settings_received(session, &ack_frame, 0));
6462
6463 stream = nghttp2_session_get_stream(session, 1);
6464
6465 assert_int32(32768, ==, stream->recv_window_size);
6466 assert_int32(16 * 1024 + 100, ==, stream->local_window_size);
6467 /* Check that we can handle the case where local_window_size <
6468 recv_window_size */
6469 assert_int32(0, ==, nghttp2_session_get_stream_local_window_size(session, 1));
6470
6471 nghttp2_session_del(session);
6472
6473 /* Check overflow case */
6474 iv[0].value = 128 * 1024;
6475 nghttp2_session_server_new(&session, &callbacks, NULL);
6476 stream = open_recv_stream(session, 1);
6477 stream->local_window_size = NGHTTP2_MAX_WINDOW_SIZE;
6478
6479 assert_int(0, ==, nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, iv, 1));
6480 assert_int(0, ==, nghttp2_session_send(session));
6481 assert_int(0, ==,
6482 nghttp2_session_on_settings_received(session, &ack_frame, 0));
6483
6484 item = nghttp2_session_get_next_ob_item(session);
6485 assert_uint8(NGHTTP2_RST_STREAM, ==, item->frame.hd.type);
6486 assert_uint32(NGHTTP2_FLOW_CONTROL_ERROR, ==,
6487 item->frame.rst_stream.error_code);
6488
6489 nghttp2_session_del(session);
6490 nghttp2_frame_settings_free(&ack_frame.settings, mem);
6491 }
6492
test_nghttp2_submit_settings_multiple_times(void)6493 void test_nghttp2_submit_settings_multiple_times(void) {
6494 nghttp2_session *session;
6495 nghttp2_session_callbacks callbacks;
6496 nghttp2_settings_entry iv[4];
6497 nghttp2_frame frame;
6498 nghttp2_inflight_settings *inflight_settings;
6499
6500 memset(&callbacks, 0, sizeof(callbacks));
6501 callbacks.send_callback2 = null_send_callback;
6502
6503 nghttp2_session_client_new(&session, &callbacks, NULL);
6504
6505 /* first SETTINGS */
6506 iv[0].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS;
6507 iv[0].value = 100;
6508
6509 iv[1].settings_id = NGHTTP2_SETTINGS_ENABLE_PUSH;
6510 iv[1].value = 0;
6511
6512 assert_int(0, ==, nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, iv, 2));
6513
6514 inflight_settings = session->inflight_settings_head;
6515
6516 assert_not_null(inflight_settings);
6517 assert_int32(NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, ==,
6518 inflight_settings->iv[0].settings_id);
6519 assert_uint32(100, ==, inflight_settings->iv[0].value);
6520 assert_size(2, ==, inflight_settings->niv);
6521 assert_null(inflight_settings->next);
6522
6523 assert_uint32(100, ==, session->pending_local_max_concurrent_stream);
6524 assert_uint8(0, ==, session->pending_enable_push);
6525
6526 /* second SETTINGS */
6527 iv[0].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS;
6528 iv[0].value = 99;
6529
6530 assert_int(0, ==, nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, iv, 1));
6531
6532 inflight_settings = session->inflight_settings_head->next;
6533
6534 assert_not_null(inflight_settings);
6535 assert_int32(NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, ==,
6536 inflight_settings->iv[0].settings_id);
6537 assert_uint32(99, ==, inflight_settings->iv[0].value);
6538 assert_size(1, ==, inflight_settings->niv);
6539 assert_null(inflight_settings->next);
6540
6541 assert_uint32(99, ==, session->pending_local_max_concurrent_stream);
6542 assert_uint8(0, ==, session->pending_enable_push);
6543
6544 nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_ACK, NULL, 0);
6545
6546 /* receive SETTINGS ACK */
6547 assert_int(0, ==, nghttp2_session_on_settings_received(session, &frame, 0));
6548
6549 inflight_settings = session->inflight_settings_head;
6550
6551 /* first inflight SETTINGS was removed */
6552 assert_not_null(inflight_settings);
6553 assert_int32(NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, ==,
6554 inflight_settings->iv[0].settings_id);
6555 assert_uint32(99, ==, inflight_settings->iv[0].value);
6556 assert_size(1, ==, inflight_settings->niv);
6557 assert_null(inflight_settings->next);
6558
6559 assert_uint32(100, ==, session->local_settings.max_concurrent_streams);
6560
6561 /* receive SETTINGS ACK again */
6562 assert_int(0, ==, nghttp2_session_on_settings_received(session, &frame, 0));
6563
6564 assert_null(session->inflight_settings_head);
6565 assert_uint32(99, ==, session->local_settings.max_concurrent_streams);
6566
6567 nghttp2_session_del(session);
6568 }
6569
test_nghttp2_submit_push_promise(void)6570 void test_nghttp2_submit_push_promise(void) {
6571 nghttp2_session *session;
6572 nghttp2_session_callbacks callbacks;
6573 my_user_data ud;
6574 nghttp2_stream *stream;
6575
6576 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6577 callbacks.send_callback2 = null_send_callback;
6578 callbacks.on_frame_send_callback = on_frame_send_callback;
6579 callbacks.on_frame_not_send_callback = on_frame_not_send_callback;
6580
6581 assert_int(0, ==, nghttp2_session_server_new(&session, &callbacks, &ud));
6582 open_recv_stream(session, 1);
6583 assert_int32(2, ==,
6584 nghttp2_submit_push_promise(session, NGHTTP2_FLAG_NONE, 1, reqnv,
6585 ARRLEN(reqnv), &ud));
6586
6587 stream = nghttp2_session_get_stream(session, 2);
6588
6589 assert_not_null(stream);
6590 assert_enum(nghttp2_stream_state, NGHTTP2_STREAM_RESERVED, ==, stream->state);
6591 assert_ptr_equal(&ud, nghttp2_session_get_stream_user_data(session, 2));
6592
6593 ud.frame_send_cb_called = 0;
6594 ud.sent_frame_type = 0;
6595
6596 assert_int(0, ==, nghttp2_session_send(session));
6597 assert_int(1, ==, ud.frame_send_cb_called);
6598 assert_uint8(NGHTTP2_PUSH_PROMISE, ==, ud.sent_frame_type);
6599
6600 stream = nghttp2_session_get_stream(session, 2);
6601
6602 assert_enum(nghttp2_stream_state, NGHTTP2_STREAM_RESERVED, ==, stream->state);
6603 assert_ptr_equal(&ud, nghttp2_session_get_stream_user_data(session, 2));
6604
6605 /* submit PUSH_PROMISE while associated stream is not opened */
6606 assert_int32(NGHTTP2_ERR_STREAM_CLOSED, ==,
6607 nghttp2_submit_push_promise(session, NGHTTP2_FLAG_NONE, 3, reqnv,
6608 ARRLEN(reqnv), NULL));
6609
6610 /* Stream ID <= 0 is error */
6611 assert_int32(NGHTTP2_ERR_INVALID_ARGUMENT, ==,
6612 nghttp2_submit_push_promise(session, NGHTTP2_FLAG_NONE, 0, reqnv,
6613 ARRLEN(reqnv), NULL));
6614
6615 nghttp2_session_del(session);
6616 }
6617
test_nghttp2_submit_window_update(void)6618 void test_nghttp2_submit_window_update(void) {
6619 nghttp2_session *session;
6620 nghttp2_session_callbacks callbacks;
6621 my_user_data ud;
6622 nghttp2_outbound_item *item;
6623 nghttp2_stream *stream;
6624
6625 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6626 callbacks.send_callback2 = null_send_callback;
6627
6628 nghttp2_session_client_new(&session, &callbacks, &ud);
6629 stream = open_recv_stream(session, 2);
6630 stream->recv_window_size = 4096;
6631
6632 assert_int(0, ==,
6633 nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 2, 1024));
6634 item = nghttp2_session_get_next_ob_item(session);
6635 assert_uint8(NGHTTP2_WINDOW_UPDATE, ==, item->frame.hd.type);
6636 assert_int32(1024, ==, item->frame.window_update.window_size_increment);
6637 assert_int(0, ==, nghttp2_session_send(session));
6638 assert_int32(3072, ==, stream->recv_window_size);
6639
6640 assert_int(0, ==,
6641 nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 2, 4096));
6642 item = nghttp2_session_get_next_ob_item(session);
6643 assert_uint8(NGHTTP2_WINDOW_UPDATE, ==, item->frame.hd.type);
6644 assert_int32(4096, ==, item->frame.window_update.window_size_increment);
6645 assert_int(0, ==, nghttp2_session_send(session));
6646 assert_int32(0, ==, stream->recv_window_size);
6647
6648 assert_int(0, ==,
6649 nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 2, 4096));
6650 item = nghttp2_session_get_next_ob_item(session);
6651 assert_uint8(NGHTTP2_WINDOW_UPDATE, ==, item->frame.hd.type);
6652 assert_int32(4096, ==, item->frame.window_update.window_size_increment);
6653 assert_int(0, ==, nghttp2_session_send(session));
6654 assert_int32(0, ==, stream->recv_window_size);
6655
6656 assert_int(0, ==,
6657 nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 2, 0));
6658 /* It is ok if stream is closed or does not exist at the call
6659 time */
6660 assert_int(0, ==,
6661 nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 4, 4096));
6662
6663 nghttp2_session_del(session);
6664 }
6665
test_nghttp2_submit_window_update_local_window_size(void)6666 void test_nghttp2_submit_window_update_local_window_size(void) {
6667 nghttp2_session *session;
6668 nghttp2_session_callbacks callbacks;
6669 nghttp2_outbound_item *item;
6670 nghttp2_stream *stream;
6671
6672 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6673 callbacks.send_callback2 = null_send_callback;
6674
6675 nghttp2_session_client_new(&session, &callbacks, NULL);
6676 stream = open_recv_stream(session, 2);
6677 stream->recv_window_size = 4096;
6678
6679 assert_int(0, ==,
6680 nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 2,
6681 stream->recv_window_size + 1));
6682 assert_int32(NGHTTP2_INITIAL_WINDOW_SIZE + 1, ==, stream->local_window_size);
6683 assert_int32(0, ==, stream->recv_window_size);
6684 item = nghttp2_session_get_next_ob_item(session);
6685 assert_uint8(NGHTTP2_WINDOW_UPDATE, ==, item->frame.hd.type);
6686 assert_int32(4097, ==, item->frame.window_update.window_size_increment);
6687
6688 assert_int(0, ==, nghttp2_session_send(session));
6689
6690 /* Let's decrement local window size */
6691 stream->recv_window_size = 4096;
6692 assert_int(0, ==,
6693 nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 2,
6694 -stream->local_window_size / 2));
6695 assert_int32(32768, ==, stream->local_window_size);
6696 assert_int32(-28672, ==, stream->recv_window_size);
6697 assert_int32(32768, ==, stream->recv_reduction);
6698
6699 item = nghttp2_session_get_next_ob_item(session);
6700 assert_null(item);
6701
6702 /* Increase local window size */
6703 assert_int(
6704 0, ==, nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 2, 16384));
6705 assert_int32(49152, ==, stream->local_window_size);
6706 assert_int32(-12288, ==, stream->recv_window_size);
6707 assert_int32(16384, ==, stream->recv_reduction);
6708 assert_null(nghttp2_session_get_next_ob_item(session));
6709
6710 assert_int(NGHTTP2_ERR_FLOW_CONTROL, ==,
6711 nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 2,
6712 NGHTTP2_MAX_WINDOW_SIZE));
6713
6714 assert_int(0, ==, nghttp2_session_send(session));
6715
6716 /* Check connection-level flow control */
6717 session->recv_window_size = 4096;
6718 assert_int(0, ==,
6719 nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 0,
6720 session->recv_window_size + 1));
6721 assert_int32(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE + 1, ==,
6722 session->local_window_size);
6723 assert_int32(0, ==, session->recv_window_size);
6724 item = nghttp2_session_get_next_ob_item(session);
6725 assert_uint8(NGHTTP2_WINDOW_UPDATE, ==, item->frame.hd.type);
6726 assert_int32(4097, ==, item->frame.window_update.window_size_increment);
6727
6728 assert_int(0, ==, nghttp2_session_send(session));
6729
6730 /* Go decrement part */
6731 session->recv_window_size = 4096;
6732 assert_int(0, ==,
6733 nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 0,
6734 -session->local_window_size / 2));
6735 assert_int32(32768, ==, session->local_window_size);
6736 assert_int32(-28672, ==, session->recv_window_size);
6737 assert_int32(32768, ==, session->recv_reduction);
6738 item = nghttp2_session_get_next_ob_item(session);
6739 assert_null(item);
6740
6741 /* Increase local window size */
6742 assert_int(
6743 0, ==, nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 0, 16384));
6744 assert_int32(49152, ==, session->local_window_size);
6745 assert_int32(-12288, ==, session->recv_window_size);
6746 assert_int32(16384, ==, session->recv_reduction);
6747 assert_null(nghttp2_session_get_next_ob_item(session));
6748
6749 assert_int(NGHTTP2_ERR_FLOW_CONTROL, ==,
6750 nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 0,
6751 NGHTTP2_MAX_WINDOW_SIZE));
6752
6753 nghttp2_session_del(session);
6754 }
6755
test_nghttp2_submit_shutdown_notice(void)6756 void test_nghttp2_submit_shutdown_notice(void) {
6757 nghttp2_session *session;
6758 nghttp2_session_callbacks callbacks;
6759 my_user_data ud;
6760
6761 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6762 callbacks.send_callback2 = null_send_callback;
6763 callbacks.on_frame_send_callback = on_frame_send_callback;
6764 callbacks.on_frame_not_send_callback = on_frame_not_send_callback;
6765
6766 nghttp2_session_server_new(&session, &callbacks, &ud);
6767
6768 assert_int(0, ==, nghttp2_submit_shutdown_notice(session));
6769
6770 ud.frame_send_cb_called = 0;
6771
6772 nghttp2_session_send(session);
6773
6774 assert_int(1, ==, ud.frame_send_cb_called);
6775 assert_uint8(NGHTTP2_GOAWAY, ==, ud.sent_frame_type);
6776 assert_int32((1u << 31) - 1, ==, session->local_last_stream_id);
6777
6778 /* After another GOAWAY, nghttp2_submit_shutdown_notice() is
6779 noop. */
6780 assert_int(0, ==,
6781 nghttp2_session_terminate_session(session, NGHTTP2_NO_ERROR));
6782
6783 ud.frame_send_cb_called = 0;
6784
6785 nghttp2_session_send(session);
6786
6787 assert_int(1, ==, ud.frame_send_cb_called);
6788 assert_uint8(NGHTTP2_GOAWAY, ==, ud.sent_frame_type);
6789 assert_int32(0, ==, session->local_last_stream_id);
6790
6791 assert_int(0, ==, nghttp2_submit_shutdown_notice(session));
6792
6793 ud.frame_send_cb_called = 0;
6794 ud.frame_not_send_cb_called = 0;
6795
6796 nghttp2_session_send(session);
6797
6798 assert_int(0, ==, ud.frame_send_cb_called);
6799 assert_int(0, ==, ud.frame_not_send_cb_called);
6800
6801 nghttp2_session_del(session);
6802
6803 /* Using nghttp2_submit_shutdown_notice() with client side session
6804 is error */
6805 nghttp2_session_client_new(&session, &callbacks, NULL);
6806
6807 assert_int(NGHTTP2_ERR_INVALID_STATE, ==,
6808 nghttp2_submit_shutdown_notice(session));
6809
6810 nghttp2_session_del(session);
6811 }
6812
test_nghttp2_submit_invalid_nv(void)6813 void test_nghttp2_submit_invalid_nv(void) {
6814 nghttp2_session *session;
6815 nghttp2_session_callbacks callbacks;
6816 nghttp2_nv empty_name_nv[] = {MAKE_NV("Version", "HTTP/1.1"),
6817 MAKE_NV("", "empty name")};
6818
6819 /* Now invalid header name/value pair in HTTP/1.1 is accepted in
6820 nghttp2 */
6821
6822 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6823
6824 assert_int(0, ==, nghttp2_session_server_new(&session, &callbacks, NULL));
6825
6826 /* nghttp2_submit_response */
6827 assert_int(0, ==,
6828 nghttp2_submit_response2(session, 2, empty_name_nv,
6829 ARRLEN(empty_name_nv), NULL));
6830
6831 /* nghttp2_submit_push_promise */
6832 open_recv_stream(session, 1);
6833
6834 assert_int32(0, <,
6835 nghttp2_submit_push_promise(session, NGHTTP2_FLAG_NONE, 1,
6836 empty_name_nv, ARRLEN(empty_name_nv),
6837 NULL));
6838
6839 nghttp2_session_del(session);
6840
6841 assert_int(0, ==, nghttp2_session_client_new(&session, &callbacks, NULL));
6842
6843 /* nghttp2_submit_request */
6844 assert_int32(0, <,
6845 nghttp2_submit_request2(session, NULL, empty_name_nv,
6846 ARRLEN(empty_name_nv), NULL, NULL));
6847
6848 /* nghttp2_submit_headers */
6849 assert_int32(0, <,
6850 nghttp2_submit_headers(session, NGHTTP2_FLAG_NONE, -1, NULL,
6851 empty_name_nv, ARRLEN(empty_name_nv),
6852 NULL));
6853
6854 nghttp2_session_del(session);
6855 }
6856
test_nghttp2_submit_extension(void)6857 void test_nghttp2_submit_extension(void) {
6858 nghttp2_session *session;
6859 nghttp2_session_callbacks callbacks;
6860 my_user_data ud;
6861 accumulator acc;
6862 nghttp2_mem *mem;
6863 const char data[] = "Hello World!";
6864 size_t len;
6865 int32_t stream_id;
6866 int rv;
6867
6868 mem = nghttp2_mem_default();
6869
6870 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6871
6872 callbacks.pack_extension_callback2 = pack_extension_callback;
6873 callbacks.send_callback2 = accumulator_send_callback;
6874
6875 nghttp2_buf_init2(&ud.scratchbuf, 4096, mem);
6876
6877 nghttp2_session_client_new(&session, &callbacks, &ud);
6878
6879 ud.scratchbuf.last = nghttp2_cpymem(ud.scratchbuf.last, data, sizeof(data));
6880 ud.acc = &acc;
6881
6882 rv = nghttp2_submit_extension(session, 211, 0x01, 3, &ud.scratchbuf);
6883
6884 assert_int(0, ==, rv);
6885
6886 acc.length = 0;
6887
6888 rv = nghttp2_session_send(session);
6889
6890 assert_int(0, ==, rv);
6891 assert_size(NGHTTP2_FRAME_HDLEN + sizeof(data), ==, acc.length);
6892
6893 len = nghttp2_get_uint32(acc.buf) >> 8;
6894
6895 assert_size(sizeof(data), ==, len);
6896 assert_uint8(211, ==, acc.buf[3]);
6897 assert_uint8(0x01, ==, acc.buf[4]);
6898
6899 stream_id = (int32_t)nghttp2_get_uint32(acc.buf + 5);
6900
6901 assert_int32(3, ==, stream_id);
6902 assert_memory_equal(sizeof(data), data, &acc.buf[NGHTTP2_FRAME_HDLEN]);
6903
6904 nghttp2_session_del(session);
6905
6906 /* submitting standard HTTP/2 frame is error */
6907 nghttp2_session_server_new(&session, &callbacks, &ud);
6908
6909 rv = nghttp2_submit_extension(session, NGHTTP2_GOAWAY, NGHTTP2_FLAG_NONE, 0,
6910 NULL);
6911
6912 assert_int(NGHTTP2_ERR_INVALID_ARGUMENT, ==, rv);
6913
6914 nghttp2_session_del(session);
6915 nghttp2_buf_free(&ud.scratchbuf, mem);
6916 }
6917
test_nghttp2_submit_altsvc(void)6918 void test_nghttp2_submit_altsvc(void) {
6919 nghttp2_session *session;
6920 nghttp2_session_callbacks callbacks;
6921 my_user_data ud;
6922 int rv;
6923 nghttp2_ssize len;
6924 const uint8_t *data;
6925 nghttp2_frame_hd hd;
6926 size_t origin_len;
6927 const uint8_t origin[] = "nghttp2.org";
6928 const uint8_t field_value[] = "h2=\":443\"";
6929
6930 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6931
6932 nghttp2_session_server_new(&session, &callbacks, &ud);
6933
6934 rv = nghttp2_submit_altsvc(session, NGHTTP2_FLAG_NONE, 0, origin,
6935 sizeof(origin) - 1, field_value,
6936 sizeof(field_value) - 1);
6937
6938 assert_int(0, ==, rv);
6939
6940 ud.frame_send_cb_called = 0;
6941
6942 len = nghttp2_session_mem_send2(session, &data);
6943
6944 assert_ptrdiff(NGHTTP2_FRAME_HDLEN + 2 + sizeof(origin) - 1 +
6945 sizeof(field_value) - 1,
6946 ==, len);
6947
6948 nghttp2_frame_unpack_frame_hd(&hd, data);
6949
6950 assert_size(2 + sizeof(origin) - 1 + sizeof(field_value) - 1, ==, hd.length);
6951 assert_uint8(NGHTTP2_ALTSVC, ==, hd.type);
6952 assert_uint8(NGHTTP2_FLAG_NONE, ==, hd.flags);
6953
6954 origin_len = nghttp2_get_uint16(data + NGHTTP2_FRAME_HDLEN);
6955
6956 assert_size(sizeof(origin) - 1, ==, origin_len);
6957 assert_memory_equal(sizeof(origin) - 1, origin,
6958 data + NGHTTP2_FRAME_HDLEN + 2);
6959 assert_memory_equal(hd.length - (sizeof(origin) - 1) - 2, field_value,
6960 data + NGHTTP2_FRAME_HDLEN + 2 + sizeof(origin) - 1);
6961
6962 /* submitting empty origin with stream_id == 0 is error */
6963 rv = nghttp2_submit_altsvc(session, NGHTTP2_FLAG_NONE, 0, NULL, 0,
6964 field_value, sizeof(field_value) - 1);
6965
6966 assert_int(NGHTTP2_ERR_INVALID_ARGUMENT, ==, rv);
6967
6968 /* submitting non-empty origin with stream_id != 0 is error */
6969 rv = nghttp2_submit_altsvc(session, NGHTTP2_FLAG_NONE, 1, origin,
6970 sizeof(origin) - 1, field_value,
6971 sizeof(field_value) - 1);
6972
6973 assert_int(NGHTTP2_ERR_INVALID_ARGUMENT, ==, rv);
6974
6975 nghttp2_session_del(session);
6976
6977 /* submitting from client side session is error */
6978 nghttp2_session_client_new(&session, &callbacks, NULL);
6979
6980 rv = nghttp2_submit_altsvc(session, NGHTTP2_FLAG_NONE, 0, origin,
6981 sizeof(origin) - 1, field_value,
6982 sizeof(field_value) - 1);
6983
6984 assert_int(NGHTTP2_ERR_INVALID_STATE, ==, rv);
6985
6986 nghttp2_session_del(session);
6987 }
6988
test_nghttp2_submit_origin(void)6989 void test_nghttp2_submit_origin(void) {
6990 nghttp2_session *session;
6991 nghttp2_session_callbacks callbacks;
6992 my_user_data ud;
6993 int rv;
6994 nghttp2_ssize len;
6995 const uint8_t *data;
6996 static const uint8_t nghttp2[] = "https://nghttp2.org";
6997 static const uint8_t examples[] = "https://examples.com";
6998 static const nghttp2_origin_entry ov[] = {
6999 {
7000 (uint8_t *)nghttp2,
7001 sizeof(nghttp2) - 1,
7002 },
7003 {
7004 (uint8_t *)examples,
7005 sizeof(examples) - 1,
7006 },
7007 };
7008 nghttp2_frame frame;
7009 nghttp2_ext_origin origin;
7010 nghttp2_mem *mem;
7011
7012 mem = nghttp2_mem_default();
7013
7014 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7015 callbacks.on_frame_send_callback = on_frame_send_callback;
7016
7017 frame.ext.payload = &origin;
7018
7019 nghttp2_session_server_new(&session, &callbacks, &ud);
7020
7021 rv = nghttp2_submit_origin(session, NGHTTP2_FLAG_NONE, ov, 2);
7022
7023 assert_int(0, ==, rv);
7024
7025 ud.frame_send_cb_called = 0;
7026 len = nghttp2_session_mem_send2(session, &data);
7027
7028 assert_ptrdiff(0, <, len);
7029 assert_int(1, ==, ud.frame_send_cb_called);
7030
7031 nghttp2_frame_unpack_frame_hd(&frame.hd, data);
7032 rv =
7033 nghttp2_frame_unpack_origin_payload(&frame.ext, data + NGHTTP2_FRAME_HDLEN,
7034 (size_t)len - NGHTTP2_FRAME_HDLEN, mem);
7035
7036 assert_int(0, ==, rv);
7037 assert_int32(0, ==, frame.hd.stream_id);
7038 assert_uint8(NGHTTP2_ORIGIN, ==, frame.hd.type);
7039 assert_size(2, ==, origin.nov);
7040 assert_memory_equal(sizeof(nghttp2) - 1, nghttp2, origin.ov[0].origin);
7041 assert_size(sizeof(nghttp2) - 1, ==, origin.ov[0].origin_len);
7042 assert_memory_equal(sizeof(examples) - 1, examples, origin.ov[1].origin);
7043 assert_size(sizeof(examples) - 1, ==, origin.ov[1].origin_len);
7044
7045 nghttp2_frame_origin_free(&frame.ext, mem);
7046
7047 nghttp2_session_del(session);
7048
7049 /* Submitting ORIGIN frame from client session is error */
7050 nghttp2_session_client_new(&session, &callbacks, NULL);
7051
7052 rv = nghttp2_submit_origin(session, NGHTTP2_FLAG_NONE, ov, 1);
7053
7054 assert_int(NGHTTP2_ERR_INVALID_STATE, ==, rv);
7055
7056 nghttp2_session_del(session);
7057
7058 /* Submitting empty ORIGIN frame */
7059 nghttp2_session_server_new(&session, &callbacks, &ud);
7060
7061 rv = nghttp2_submit_origin(session, NGHTTP2_FLAG_NONE, NULL, 0);
7062
7063 assert_int(0, ==, rv);
7064
7065 ud.frame_send_cb_called = 0;
7066 len = nghttp2_session_mem_send2(session, &data);
7067
7068 assert_ptrdiff(NGHTTP2_FRAME_HDLEN, ==, len);
7069 assert_int(1, ==, ud.frame_send_cb_called);
7070
7071 nghttp2_frame_unpack_frame_hd(&frame.hd, data);
7072
7073 assert_uint8(NGHTTP2_ORIGIN, ==, frame.hd.type);
7074
7075 nghttp2_session_del(session);
7076 }
7077
test_nghttp2_submit_priority_update(void)7078 void test_nghttp2_submit_priority_update(void) {
7079 nghttp2_session *session;
7080 nghttp2_session_callbacks callbacks;
7081 const uint8_t field_value[] = "i";
7082 my_user_data ud;
7083 const uint8_t *data;
7084 int rv;
7085 nghttp2_frame frame;
7086 nghttp2_ext_priority_update priority_update;
7087 nghttp2_ssize len;
7088 int32_t stream_id;
7089
7090 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7091 callbacks.on_frame_send_callback = on_frame_send_callback;
7092
7093 nghttp2_session_client_new(&session, &callbacks, &ud);
7094
7095 session->pending_no_rfc7540_priorities = 1;
7096
7097 stream_id =
7098 nghttp2_submit_request2(session, NULL, reqnv, ARRLEN(reqnv), NULL, NULL);
7099
7100 assert_int32(1, ==, stream_id);
7101
7102 len = nghttp2_session_mem_send2(session, &data);
7103
7104 assert_ptrdiff(0, <, len);
7105
7106 rv = nghttp2_submit_priority_update(session, NGHTTP2_FLAG_NONE, stream_id,
7107 field_value, sizeof(field_value) - 1);
7108
7109 assert_int(0, ==, rv);
7110
7111 frame.ext.payload = &priority_update;
7112
7113 ud.frame_send_cb_called = 0;
7114 len = nghttp2_session_mem_send2(session, &data);
7115
7116 assert_ptrdiff(0, <, len);
7117 assert_int(1, ==, ud.frame_send_cb_called);
7118
7119 nghttp2_frame_unpack_frame_hd(&frame.hd, data);
7120 nghttp2_frame_unpack_priority_update_payload(
7121 &frame.ext, (uint8_t *)(data + NGHTTP2_FRAME_HDLEN),
7122 (size_t)len - NGHTTP2_FRAME_HDLEN);
7123
7124 assert_int32(0, ==, frame.hd.stream_id);
7125 assert_uint8(NGHTTP2_PRIORITY_UPDATE, ==, frame.hd.type);
7126 assert_int32(stream_id, ==, priority_update.stream_id);
7127 assert_size(sizeof(field_value) - 1, ==, priority_update.field_value_len);
7128 assert_memory_equal(sizeof(field_value) - 1, field_value,
7129 priority_update.field_value);
7130
7131 nghttp2_session_del(session);
7132
7133 /* Submitting PRIORITY_UPDATE frame from server session is error */
7134 nghttp2_session_server_new(&session, &callbacks, &ud);
7135
7136 open_recv_stream(session, 1);
7137
7138 rv = nghttp2_submit_priority_update(session, NGHTTP2_FLAG_NONE, 1,
7139 field_value, sizeof(field_value) - 1);
7140
7141 assert_int(NGHTTP2_ERR_INVALID_STATE, ==, rv);
7142
7143 nghttp2_session_del(session);
7144
7145 /* Submitting PRIORITY_UPDATE with empty field_value */
7146 nghttp2_session_client_new(&session, &callbacks, &ud);
7147
7148 stream_id =
7149 nghttp2_submit_request2(session, NULL, reqnv, ARRLEN(reqnv), NULL, NULL);
7150
7151 assert_int32(1, ==, stream_id);
7152
7153 len = nghttp2_session_mem_send2(session, &data);
7154
7155 assert_ptrdiff(0, <, len);
7156
7157 rv = nghttp2_submit_priority_update(session, NGHTTP2_FLAG_NONE, stream_id,
7158 NULL, 0);
7159
7160 assert_int(0, ==, rv);
7161
7162 frame.ext.payload = &priority_update;
7163
7164 len = nghttp2_session_mem_send2(session, &data);
7165
7166 assert_ptrdiff(0, <, len);
7167
7168 nghttp2_frame_unpack_frame_hd(&frame.hd, data);
7169 nghttp2_frame_unpack_priority_update_payload(
7170 &frame.ext, (uint8_t *)(data + NGHTTP2_FRAME_HDLEN),
7171 (size_t)len - NGHTTP2_FRAME_HDLEN);
7172
7173 assert_int32(0, ==, frame.hd.stream_id);
7174 assert_uint8(NGHTTP2_PRIORITY_UPDATE, ==, frame.hd.type);
7175 assert_int32(stream_id, ==, priority_update.stream_id);
7176 assert_size(0, ==, priority_update.field_value_len);
7177 assert_null(priority_update.field_value);
7178
7179 nghttp2_session_del(session);
7180 }
7181
test_nghttp2_submit_rst_stream(void)7182 void test_nghttp2_submit_rst_stream(void) {
7183 nghttp2_session *session;
7184 nghttp2_session_callbacks callbacks;
7185 nghttp2_outbound_item *item;
7186 int rv;
7187 int32_t stream_id;
7188
7189 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7190
7191 /* Sending RST_STREAM to idle stream (local) is ignored */
7192 nghttp2_session_client_new(&session, &callbacks, NULL);
7193
7194 rv =
7195 nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, 1, NGHTTP2_NO_ERROR);
7196
7197 assert_int(0, ==, rv);
7198
7199 item = nghttp2_outbound_queue_top(&session->ob_reg);
7200
7201 assert_null(item);
7202
7203 nghttp2_session_del(session);
7204
7205 /* Sending RST_STREAM to idle stream (remote) is ignored */
7206 nghttp2_session_client_new(&session, &callbacks, NULL);
7207
7208 rv =
7209 nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, 2, NGHTTP2_NO_ERROR);
7210
7211 assert_int(0, ==, rv);
7212
7213 item = nghttp2_outbound_queue_top(&session->ob_reg);
7214
7215 assert_null(item);
7216
7217 nghttp2_session_del(session);
7218
7219 /* Sending RST_STREAM to non-idle stream (local) */
7220 nghttp2_session_client_new(&session, &callbacks, NULL);
7221
7222 open_sent_stream(session, 1);
7223
7224 rv =
7225 nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, 1, NGHTTP2_NO_ERROR);
7226
7227 assert_int(0, ==, rv);
7228
7229 item = nghttp2_outbound_queue_top(&session->ob_reg);
7230
7231 assert_not_null(item);
7232 assert_uint8(NGHTTP2_RST_STREAM, ==, item->frame.hd.type);
7233 assert_int32(1, ==, item->frame.hd.stream_id);
7234
7235 nghttp2_session_del(session);
7236
7237 /* Sending RST_STREAM to non-idle stream (remote) */
7238 nghttp2_session_client_new(&session, &callbacks, NULL);
7239
7240 open_recv_stream(session, 2);
7241
7242 rv =
7243 nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, 2, NGHTTP2_NO_ERROR);
7244
7245 assert_int(0, ==, rv);
7246
7247 item = nghttp2_outbound_queue_top(&session->ob_reg);
7248
7249 assert_not_null(item);
7250 assert_uint8(NGHTTP2_RST_STREAM, ==, item->frame.hd.type);
7251 assert_int32(2, ==, item->frame.hd.stream_id);
7252
7253 nghttp2_session_del(session);
7254
7255 /* Sending RST_STREAM to pending stream */
7256 nghttp2_session_client_new(&session, &callbacks, NULL);
7257
7258 stream_id =
7259 nghttp2_submit_request2(session, NULL, reqnv, ARRLEN(reqnv), NULL, NULL);
7260
7261 assert_int32(0, <, stream_id);
7262
7263 item = nghttp2_outbound_queue_top(&session->ob_syn);
7264
7265 assert_not_null(item);
7266 assert_uint8(NGHTTP2_HEADERS, ==, item->frame.hd.type);
7267 assert_false(item->aux_data.headers.canceled);
7268
7269 rv = nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, stream_id,
7270 NGHTTP2_NO_ERROR);
7271
7272 assert_int(0, ==, rv);
7273
7274 item = nghttp2_outbound_queue_top(&session->ob_syn);
7275
7276 assert_not_null(item);
7277 assert_uint8(NGHTTP2_HEADERS, ==, item->frame.hd.type);
7278 assert_true(item->aux_data.headers.canceled);
7279
7280 nghttp2_session_del(session);
7281 }
7282
test_nghttp2_session_open_stream(void)7283 void test_nghttp2_session_open_stream(void) {
7284 nghttp2_session *session;
7285 nghttp2_session_callbacks callbacks;
7286 nghttp2_stream *stream;
7287 nghttp2_priority_spec pri_spec;
7288
7289 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7290 nghttp2_session_server_new(&session, &callbacks, NULL);
7291
7292 nghttp2_priority_spec_init(&pri_spec, 0, 245, 0);
7293
7294 stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
7295 &pri_spec, NGHTTP2_STREAM_OPENED, NULL);
7296 assert_size(1, ==, session->num_incoming_streams);
7297 assert_size(0, ==, session->num_outgoing_streams);
7298 assert_enum(nghttp2_stream_state, NGHTTP2_STREAM_OPENED, ==, stream->state);
7299 assert_int32(245, ==, stream->weight);
7300 assert_ptr_equal(&session->root, stream->dep_prev);
7301 assert_uint8(NGHTTP2_SHUT_NONE, ==, stream->shut_flags);
7302
7303 stream = nghttp2_session_open_stream(session, 2, NGHTTP2_STREAM_FLAG_NONE,
7304 &pri_spec_default,
7305 NGHTTP2_STREAM_OPENING, NULL);
7306 assert_size(1, ==, session->num_incoming_streams);
7307 assert_size(1, ==, session->num_outgoing_streams);
7308 assert_ptr_equal(&session->root, stream->dep_prev);
7309 assert_int32(NGHTTP2_DEFAULT_WEIGHT, ==, stream->weight);
7310 assert_uint8(NGHTTP2_SHUT_NONE, ==, stream->shut_flags);
7311
7312 stream = nghttp2_session_open_stream(session, 4, NGHTTP2_STREAM_FLAG_NONE,
7313 &pri_spec_default,
7314 NGHTTP2_STREAM_RESERVED, NULL);
7315 assert_size(1, ==, session->num_incoming_streams);
7316 assert_size(1, ==, session->num_outgoing_streams);
7317 assert_ptr_equal(&session->root, stream->dep_prev);
7318 assert_int32(NGHTTP2_DEFAULT_WEIGHT, ==, stream->weight);
7319 assert_uint8(NGHTTP2_SHUT_RD, ==, stream->shut_flags);
7320
7321 nghttp2_priority_spec_init(&pri_spec, 1, 17, 1);
7322
7323 stream = nghttp2_session_open_stream(session, 3, NGHTTP2_STREAM_FLAG_NONE,
7324 &pri_spec, NGHTTP2_STREAM_OPENED, NULL);
7325 assert_int32(17, ==, stream->weight);
7326 assert_int32(1, ==, stream->dep_prev->stream_id);
7327
7328 /* Dependency to idle stream */
7329 nghttp2_priority_spec_init(&pri_spec, 1000000007, 240, 1);
7330
7331 stream = nghttp2_session_open_stream(session, 5, NGHTTP2_STREAM_FLAG_NONE,
7332 &pri_spec, NGHTTP2_STREAM_OPENED, NULL);
7333 assert_int32(240, ==, stream->weight);
7334 assert_int32(1000000007, ==, stream->dep_prev->stream_id);
7335
7336 stream = nghttp2_session_get_stream_raw(session, 1000000007);
7337
7338 assert_int32(NGHTTP2_DEFAULT_WEIGHT, ==, stream->weight);
7339 assert_ptr_equal(&session->root, stream->dep_prev);
7340
7341 /* Dependency to closed stream which is not in dependency tree */
7342 session->last_recv_stream_id = 7;
7343
7344 nghttp2_priority_spec_init(&pri_spec, 7, 10, 0);
7345
7346 stream = nghttp2_session_open_stream(session, 9, NGHTTP2_FLAG_NONE, &pri_spec,
7347 NGHTTP2_STREAM_OPENED, NULL);
7348
7349 assert_int32(NGHTTP2_DEFAULT_WEIGHT, ==, stream->weight);
7350 assert_ptr_equal(&session->root, stream->dep_prev);
7351
7352 nghttp2_session_del(session);
7353
7354 nghttp2_session_client_new(&session, &callbacks, NULL);
7355 stream = nghttp2_session_open_stream(session, 4, NGHTTP2_STREAM_FLAG_NONE,
7356 &pri_spec_default,
7357 NGHTTP2_STREAM_RESERVED, NULL);
7358 assert_size(0, ==, session->num_incoming_streams);
7359 assert_size(0, ==, session->num_outgoing_streams);
7360 assert_ptr_equal(&session->root, stream->dep_prev);
7361 assert_int32(NGHTTP2_DEFAULT_WEIGHT, ==, stream->weight);
7362 assert_uint8(NGHTTP2_SHUT_WR, ==, stream->shut_flags);
7363
7364 nghttp2_session_del(session);
7365 }
7366
test_nghttp2_session_open_stream_with_idle_stream_dep(void)7367 void test_nghttp2_session_open_stream_with_idle_stream_dep(void) {
7368 nghttp2_session *session;
7369 nghttp2_session_callbacks callbacks;
7370 nghttp2_stream *stream;
7371 nghttp2_priority_spec pri_spec;
7372
7373 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7374 nghttp2_session_server_new(&session, &callbacks, NULL);
7375
7376 /* Dependency to idle stream */
7377 nghttp2_priority_spec_init(&pri_spec, 101, 245, 0);
7378
7379 stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
7380 &pri_spec, NGHTTP2_STREAM_OPENED, NULL);
7381
7382 assert_int32(245, ==, stream->weight);
7383 assert_int32(101, ==, stream->dep_prev->stream_id);
7384
7385 stream = nghttp2_session_get_stream_raw(session, 101);
7386
7387 assert_enum(nghttp2_stream_state, NGHTTP2_STREAM_IDLE, ==, stream->state);
7388 assert_int32(NGHTTP2_DEFAULT_WEIGHT, ==, stream->weight);
7389
7390 nghttp2_priority_spec_init(&pri_spec, 211, 1, 0);
7391
7392 /* stream 101 was already created as idle. */
7393 stream = nghttp2_session_open_stream(session, 101, NGHTTP2_STREAM_FLAG_NONE,
7394 &pri_spec, NGHTTP2_STREAM_OPENED, NULL);
7395
7396 assert_int32(1, ==, stream->weight);
7397 assert_int32(211, ==, stream->dep_prev->stream_id);
7398
7399 stream = nghttp2_session_get_stream_raw(session, 211);
7400
7401 assert_enum(nghttp2_stream_state, NGHTTP2_STREAM_IDLE, ==, stream->state);
7402 assert_int32(NGHTTP2_DEFAULT_WEIGHT, ==, stream->weight);
7403
7404 nghttp2_session_del(session);
7405 }
7406
test_nghttp2_session_get_next_ob_item(void)7407 void test_nghttp2_session_get_next_ob_item(void) {
7408 nghttp2_session *session;
7409 nghttp2_session_callbacks callbacks;
7410 nghttp2_priority_spec pri_spec;
7411
7412 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7413 callbacks.send_callback2 = null_send_callback;
7414
7415 nghttp2_session_client_new(&session, &callbacks, NULL);
7416 session->remote_settings.max_concurrent_streams = 2;
7417
7418 assert_null(nghttp2_session_get_next_ob_item(session));
7419 nghttp2_submit_ping(session, NGHTTP2_FLAG_NONE, NULL);
7420 assert_uint8(NGHTTP2_PING, ==,
7421 nghttp2_session_get_next_ob_item(session)->frame.hd.type);
7422
7423 assert_int32(1, ==,
7424 nghttp2_submit_request2(session, NULL, NULL, 0, NULL, NULL));
7425 assert_uint8(NGHTTP2_PING, ==,
7426 nghttp2_session_get_next_ob_item(session)->frame.hd.type);
7427
7428 assert_int(0, ==, nghttp2_session_send(session));
7429 assert_null(nghttp2_session_get_next_ob_item(session));
7430
7431 /* Incoming stream does not affect the number of outgoing max
7432 concurrent streams. */
7433 open_recv_stream(session, 2);
7434
7435 nghttp2_priority_spec_init(&pri_spec, 0, NGHTTP2_MAX_WEIGHT, 0);
7436
7437 assert_int(3, ==,
7438 nghttp2_submit_request2(session, &pri_spec, NULL, 0, NULL, NULL));
7439 assert_uint8(NGHTTP2_HEADERS, ==,
7440 nghttp2_session_get_next_ob_item(session)->frame.hd.type);
7441 assert_int(0, ==, nghttp2_session_send(session));
7442
7443 assert_int(5, ==,
7444 nghttp2_submit_request2(session, &pri_spec, NULL, 0, NULL, NULL));
7445 assert_null(nghttp2_session_get_next_ob_item(session));
7446
7447 session->remote_settings.max_concurrent_streams = 3;
7448
7449 assert_uint8(NGHTTP2_HEADERS, ==,
7450 nghttp2_session_get_next_ob_item(session)->frame.hd.type);
7451
7452 nghttp2_session_del(session);
7453
7454 /* Check that push reply HEADERS are queued into ob_ss_pq */
7455 nghttp2_session_server_new(&session, &callbacks, NULL);
7456 session->remote_settings.max_concurrent_streams = 0;
7457 open_sent_stream2(session, 2, NGHTTP2_STREAM_RESERVED);
7458 assert_int32(0, ==,
7459 nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, 2, NULL,
7460 NULL, 0, NULL));
7461 assert_null(nghttp2_session_get_next_ob_item(session));
7462 assert_size(1, ==, nghttp2_outbound_queue_size(&session->ob_syn));
7463 nghttp2_session_del(session);
7464 }
7465
test_nghttp2_session_pop_next_ob_item(void)7466 void test_nghttp2_session_pop_next_ob_item(void) {
7467 nghttp2_session *session;
7468 nghttp2_session_callbacks callbacks;
7469 nghttp2_outbound_item *item;
7470 nghttp2_priority_spec pri_spec;
7471 nghttp2_mem *mem;
7472
7473 mem = nghttp2_mem_default();
7474 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7475 callbacks.send_callback2 = null_send_callback;
7476
7477 nghttp2_session_client_new(&session, &callbacks, NULL);
7478 session->remote_settings.max_concurrent_streams = 1;
7479
7480 assert_null(nghttp2_session_pop_next_ob_item(session));
7481
7482 nghttp2_submit_ping(session, NGHTTP2_FLAG_NONE, NULL);
7483
7484 nghttp2_priority_spec_init(&pri_spec, 0, 254, 0);
7485
7486 nghttp2_submit_request2(session, &pri_spec, NULL, 0, NULL, NULL);
7487
7488 item = nghttp2_session_pop_next_ob_item(session);
7489 assert_uint8(NGHTTP2_PING, ==, item->frame.hd.type);
7490 nghttp2_outbound_item_free(item, mem);
7491 mem->free(item, NULL);
7492
7493 item = nghttp2_session_pop_next_ob_item(session);
7494 assert_uint8(NGHTTP2_HEADERS, ==, item->frame.hd.type);
7495 nghttp2_outbound_item_free(item, mem);
7496 mem->free(item, NULL);
7497
7498 assert_null(nghttp2_session_pop_next_ob_item(session));
7499
7500 /* Incoming stream does not affect the number of outgoing max
7501 concurrent streams. */
7502 open_recv_stream(session, 4);
7503 /* In-flight outgoing stream */
7504 open_sent_stream(session, 1);
7505
7506 nghttp2_priority_spec_init(&pri_spec, 0, NGHTTP2_MAX_WEIGHT, 0);
7507
7508 nghttp2_submit_request2(session, &pri_spec, NULL, 0, NULL, NULL);
7509
7510 assert_null(nghttp2_session_pop_next_ob_item(session));
7511
7512 session->remote_settings.max_concurrent_streams = 2;
7513
7514 item = nghttp2_session_pop_next_ob_item(session);
7515 assert_uint8(NGHTTP2_HEADERS, ==, item->frame.hd.type);
7516 nghttp2_outbound_item_free(item, mem);
7517 mem->free(item, NULL);
7518
7519 nghttp2_session_del(session);
7520
7521 /* Check that push reply HEADERS are queued into ob_ss_pq */
7522 nghttp2_session_server_new(&session, &callbacks, NULL);
7523 session->remote_settings.max_concurrent_streams = 0;
7524 open_sent_stream2(session, 2, NGHTTP2_STREAM_RESERVED);
7525 assert_int32(0, ==,
7526 nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, 2, NULL,
7527 NULL, 0, NULL));
7528 assert_null(nghttp2_session_pop_next_ob_item(session));
7529 assert_size(1, ==, nghttp2_outbound_queue_size(&session->ob_syn));
7530 nghttp2_session_del(session);
7531 }
7532
test_nghttp2_session_reply_fail(void)7533 void test_nghttp2_session_reply_fail(void) {
7534 nghttp2_session *session;
7535 nghttp2_session_callbacks callbacks;
7536 nghttp2_data_provider2 data_prd;
7537 my_user_data ud;
7538
7539 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7540 callbacks.send_callback2 = fail_send_callback;
7541
7542 data_prd.read_callback = fixed_length_data_source_read_callback;
7543 ud.data_source_length = 4 * 1024;
7544 assert_int(0, ==, nghttp2_session_server_new(&session, &callbacks, &ud));
7545 open_recv_stream2(session, 1, NGHTTP2_STREAM_OPENING);
7546 assert_int(0, ==, nghttp2_submit_response2(session, 1, NULL, 0, &data_prd));
7547 assert_int(NGHTTP2_ERR_CALLBACK_FAILURE, ==, nghttp2_session_send(session));
7548 nghttp2_session_del(session);
7549 }
7550
test_nghttp2_session_max_concurrent_streams(void)7551 void test_nghttp2_session_max_concurrent_streams(void) {
7552 nghttp2_session *session;
7553 nghttp2_session_callbacks callbacks;
7554 nghttp2_frame frame;
7555 nghttp2_outbound_item *item;
7556 nghttp2_mem *mem;
7557
7558 mem = nghttp2_mem_default();
7559 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7560 callbacks.send_callback2 = null_send_callback;
7561
7562 nghttp2_session_server_new(&session, &callbacks, NULL);
7563 open_recv_stream(session, 1);
7564
7565 /* Check un-ACKed SETTINGS_MAX_CONCURRENT_STREAMS */
7566 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 3,
7567 NGHTTP2_HCAT_HEADERS, NULL, NULL, 0);
7568 session->pending_local_max_concurrent_stream = 1;
7569
7570 assert_int(NGHTTP2_ERR_IGN_HEADER_BLOCK, ==,
7571 nghttp2_session_on_request_headers_received(session, &frame));
7572
7573 item = nghttp2_outbound_queue_top(&session->ob_reg);
7574 assert_uint8(NGHTTP2_RST_STREAM, ==, item->frame.hd.type);
7575 assert_uint32(NGHTTP2_REFUSED_STREAM, ==, item->frame.rst_stream.error_code);
7576
7577 assert_int(0, ==, nghttp2_session_send(session));
7578
7579 /* Check ACKed SETTINGS_MAX_CONCURRENT_STREAMS */
7580 session->local_settings.max_concurrent_streams = 1;
7581 frame.hd.stream_id = 5;
7582
7583 assert_int(NGHTTP2_ERR_IGN_HEADER_BLOCK, ==,
7584 nghttp2_session_on_request_headers_received(session, &frame));
7585
7586 item = nghttp2_outbound_queue_top(&session->ob_reg);
7587 assert_uint8(NGHTTP2_GOAWAY, ==, item->frame.hd.type);
7588 assert_uint32(NGHTTP2_PROTOCOL_ERROR, ==, item->frame.goaway.error_code);
7589
7590 nghttp2_frame_headers_free(&frame.headers, mem);
7591 nghttp2_session_del(session);
7592 }
7593
test_nghttp2_session_stop_data_with_rst_stream(void)7594 void test_nghttp2_session_stop_data_with_rst_stream(void) {
7595 nghttp2_session *session;
7596 nghttp2_session_callbacks callbacks;
7597 my_user_data ud;
7598 nghttp2_data_provider2 data_prd;
7599 nghttp2_frame frame;
7600
7601 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7602 callbacks.on_frame_send_callback = on_frame_send_callback;
7603 callbacks.send_callback2 = block_count_send_callback;
7604 data_prd.read_callback = fixed_length_data_source_read_callback;
7605
7606 ud.frame_send_cb_called = 0;
7607 ud.data_source_length = NGHTTP2_DATA_PAYLOADLEN * 4;
7608
7609 nghttp2_session_server_new(&session, &callbacks, &ud);
7610 open_recv_stream2(session, 1, NGHTTP2_STREAM_OPENING);
7611 nghttp2_submit_response2(session, 1, NULL, 0, &data_prd);
7612
7613 ud.block_count = 2;
7614 /* Sends response HEADERS + DATA[0] */
7615 assert_int(0, ==, nghttp2_session_send(session));
7616 assert_uint8(NGHTTP2_DATA, ==, ud.sent_frame_type);
7617 /* data for DATA[1] is read from data_prd but it is not sent */
7618 assert_size(ud.data_source_length, ==, NGHTTP2_DATA_PAYLOADLEN * 2);
7619
7620 nghttp2_frame_rst_stream_init(&frame.rst_stream, 1, NGHTTP2_CANCEL);
7621 assert_int(0, ==, nghttp2_session_on_rst_stream_received(session, &frame));
7622 nghttp2_frame_rst_stream_free(&frame.rst_stream);
7623
7624 /* Big enough number to send all DATA frames potentially. */
7625 ud.block_count = 100;
7626 /* Nothing will be sent in the following call. */
7627 assert_int(0, ==, nghttp2_session_send(session));
7628 /* With RST_STREAM, stream is canceled and further DATA on that
7629 stream are not sent. */
7630 assert_size(ud.data_source_length, ==, NGHTTP2_DATA_PAYLOADLEN * 2);
7631
7632 assert_null(nghttp2_session_get_stream(session, 1));
7633
7634 nghttp2_session_del(session);
7635 }
7636
test_nghttp2_session_defer_data(void)7637 void test_nghttp2_session_defer_data(void) {
7638 nghttp2_session *session;
7639 nghttp2_session_callbacks callbacks;
7640 my_user_data ud;
7641 nghttp2_data_provider2 data_prd;
7642 nghttp2_outbound_item *item;
7643 nghttp2_stream *stream;
7644
7645 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7646 callbacks.on_frame_send_callback = on_frame_send_callback;
7647 callbacks.send_callback2 = block_count_send_callback;
7648 data_prd.read_callback = defer_data_source_read_callback;
7649
7650 ud.frame_send_cb_called = 0;
7651 ud.data_source_length = NGHTTP2_DATA_PAYLOADLEN * 4;
7652
7653 nghttp2_session_server_new(&session, &callbacks, &ud);
7654 stream = open_recv_stream2(session, 1, NGHTTP2_STREAM_OPENING);
7655
7656 session->remote_window_size = 1 << 20;
7657 stream->remote_window_size = 1 << 20;
7658
7659 nghttp2_submit_response2(session, 1, NULL, 0, &data_prd);
7660
7661 ud.block_count = 1;
7662 /* Sends HEADERS reply */
7663 assert_int(0, ==, nghttp2_session_send(session));
7664 assert_uint8(NGHTTP2_HEADERS, ==, ud.sent_frame_type);
7665 /* No data is read */
7666 assert_size(ud.data_source_length, ==, NGHTTP2_DATA_PAYLOADLEN * 4);
7667
7668 ud.block_count = 1;
7669 nghttp2_submit_ping(session, NGHTTP2_FLAG_NONE, NULL);
7670 /* Sends PING */
7671 assert_int(0, ==, nghttp2_session_send(session));
7672 assert_uint8(NGHTTP2_PING, ==, ud.sent_frame_type);
7673
7674 /* Resume deferred DATA */
7675 assert_int(0, ==, nghttp2_session_resume_data(session, 1));
7676 item = stream->item;
7677 item->aux_data.data.dpw.data_prd.v1.read_callback =
7678 fixed_length_data_source_read_callback;
7679 ud.block_count = 1;
7680 /* Reads 2 DATA chunks */
7681 assert_int(0, ==, nghttp2_session_send(session));
7682 assert_size(ud.data_source_length, ==, NGHTTP2_DATA_PAYLOADLEN * 2);
7683
7684 /* Deferred again */
7685 item->aux_data.data.dpw.data_prd.v1.read_callback =
7686 defer_data_source_read_callback;
7687 /* This is needed since 16KiB block is already read and waiting to be
7688 sent. No read_callback invocation. */
7689 ud.block_count = 1;
7690 assert_int(0, ==, nghttp2_session_send(session));
7691 assert_size(ud.data_source_length, ==, NGHTTP2_DATA_PAYLOADLEN * 2);
7692
7693 /* Resume deferred DATA */
7694 assert_int(0, ==, nghttp2_session_resume_data(session, 1));
7695 item->aux_data.data.dpw.data_prd.v1.read_callback =
7696 fixed_length_data_source_read_callback;
7697 ud.block_count = 1;
7698 /* Reads 2 16KiB blocks */
7699 assert_int(0, ==, nghttp2_session_send(session));
7700 assert_size(ud.data_source_length, ==, 0);
7701
7702 nghttp2_session_del(session);
7703 }
7704
test_nghttp2_session_flow_control(void)7705 void test_nghttp2_session_flow_control(void) {
7706 nghttp2_session *session;
7707 nghttp2_session_callbacks callbacks;
7708 my_user_data ud;
7709 nghttp2_data_provider2 data_prd;
7710 nghttp2_frame frame;
7711 nghttp2_stream *stream;
7712 int32_t new_initial_window_size;
7713 nghttp2_settings_entry iv[1];
7714 nghttp2_frame settings_frame;
7715 nghttp2_mem *mem;
7716
7717 mem = nghttp2_mem_default();
7718 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7719 callbacks.send_callback2 = fixed_bytes_send_callback;
7720 callbacks.on_frame_send_callback = on_frame_send_callback;
7721 data_prd.read_callback = fixed_length_data_source_read_callback;
7722
7723 ud.frame_send_cb_called = 0;
7724 ud.data_source_length = 128 * 1024;
7725 /* Use smaller emission count so that we can check outbound flow
7726 control window calculation is correct. */
7727 ud.fixed_sendlen = 2 * 1024;
7728
7729 /* Initial window size to 64KiB - 1*/
7730 nghttp2_session_client_new(&session, &callbacks, &ud);
7731 /* Change it to 64KiB for easy calculation */
7732 session->remote_window_size = 64 * 1024;
7733 session->remote_settings.initial_window_size = 64 * 1024;
7734
7735 nghttp2_submit_request2(session, NULL, NULL, 0, &data_prd, NULL);
7736
7737 /* Sends 64KiB - 1 data */
7738 assert_int(0, ==, nghttp2_session_send(session));
7739 assert_size(64 * 1024, ==, ud.data_source_length);
7740
7741 /* Back 32KiB in stream window */
7742 nghttp2_frame_window_update_init(&frame.window_update, NGHTTP2_FLAG_NONE, 1,
7743 32 * 1024);
7744 nghttp2_session_on_window_update_received(session, &frame);
7745
7746 /* Send nothing because of connection-level window */
7747 assert_int(0, ==, nghttp2_session_send(session));
7748 assert_size(64 * 1024, ==, ud.data_source_length);
7749
7750 /* Back 32KiB in connection-level window */
7751 frame.hd.stream_id = 0;
7752 nghttp2_session_on_window_update_received(session, &frame);
7753
7754 /* Sends another 32KiB data */
7755 assert_int(0, ==, nghttp2_session_send(session));
7756 assert_size(32 * 1024, ==, ud.data_source_length);
7757
7758 stream = nghttp2_session_get_stream(session, 1);
7759 /* Change initial window size to 16KiB. The window_size becomes
7760 negative. */
7761 new_initial_window_size = 16 * 1024;
7762 stream->remote_window_size =
7763 new_initial_window_size -
7764 ((int32_t)session->remote_settings.initial_window_size -
7765 stream->remote_window_size);
7766 session->remote_settings.initial_window_size =
7767 (uint32_t)new_initial_window_size;
7768 assert_int32(-48 * 1024, ==, stream->remote_window_size);
7769
7770 /* Back 48KiB to stream window */
7771 frame.hd.stream_id = 1;
7772 frame.window_update.window_size_increment = 48 * 1024;
7773 nghttp2_session_on_window_update_received(session, &frame);
7774
7775 /* Nothing is sent because window_size is 0 */
7776 assert_int(0, ==, nghttp2_session_send(session));
7777 assert_size(32 * 1024, ==, ud.data_source_length);
7778
7779 /* Back 16KiB in stream window */
7780 frame.hd.stream_id = 1;
7781 frame.window_update.window_size_increment = 16 * 1024;
7782 nghttp2_session_on_window_update_received(session, &frame);
7783
7784 /* Back 24KiB in connection-level window */
7785 frame.hd.stream_id = 0;
7786 frame.window_update.window_size_increment = 24 * 1024;
7787 nghttp2_session_on_window_update_received(session, &frame);
7788
7789 /* Sends another 16KiB data */
7790 assert_int(0, ==, nghttp2_session_send(session));
7791 assert_size(16 * 1024, ==, ud.data_source_length);
7792
7793 /* Increase initial window size to 32KiB */
7794 iv[0].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
7795 iv[0].value = 32 * 1024;
7796
7797 nghttp2_frame_settings_init(&settings_frame.settings, NGHTTP2_FLAG_NONE,
7798 dup_iv(iv, 1), 1);
7799 nghttp2_session_on_settings_received(session, &settings_frame, 1);
7800 nghttp2_frame_settings_free(&settings_frame.settings, mem);
7801
7802 /* Sends another 8KiB data */
7803 assert_int(0, ==, nghttp2_session_send(session));
7804 assert_size(8 * 1024, ==, ud.data_source_length);
7805
7806 /* Back 8KiB in connection-level window */
7807 frame.hd.stream_id = 0;
7808 frame.window_update.window_size_increment = 8 * 1024;
7809 nghttp2_session_on_window_update_received(session, &frame);
7810
7811 /* Sends last 8KiB data */
7812 assert_int(0, ==, nghttp2_session_send(session));
7813 assert_size(0, ==, ud.data_source_length);
7814 assert_true(nghttp2_session_get_stream(session, 1)->shut_flags &
7815 NGHTTP2_SHUT_WR);
7816
7817 nghttp2_frame_window_update_free(&frame.window_update);
7818 nghttp2_session_del(session);
7819 }
7820
test_nghttp2_session_flow_control_data_recv(void)7821 void test_nghttp2_session_flow_control_data_recv(void) {
7822 nghttp2_session *session;
7823 nghttp2_session_callbacks callbacks;
7824 uint8_t data[64 * 1024 + 16];
7825 nghttp2_frame_hd hd;
7826 nghttp2_outbound_item *item;
7827 nghttp2_stream *stream;
7828
7829 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7830 callbacks.send_callback2 = null_send_callback;
7831
7832 /* Initial window size to 64KiB - 1*/
7833 nghttp2_session_client_new(&session, &callbacks, NULL);
7834
7835 stream = open_sent_stream(session, 1);
7836
7837 nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_WR);
7838
7839 session->local_window_size = NGHTTP2_MAX_PAYLOADLEN;
7840 stream->local_window_size = NGHTTP2_MAX_PAYLOADLEN;
7841
7842 /* Create DATA frame */
7843 memset(data, 0, sizeof(data));
7844 nghttp2_frame_hd_init(&hd, NGHTTP2_MAX_PAYLOADLEN, NGHTTP2_DATA,
7845 NGHTTP2_FLAG_END_STREAM, 1);
7846
7847 nghttp2_frame_pack_frame_hd(data, &hd);
7848 assert_ptrdiff(
7849 NGHTTP2_MAX_PAYLOADLEN + NGHTTP2_FRAME_HDLEN, ==,
7850 nghttp2_session_mem_recv2(session, data,
7851 NGHTTP2_MAX_PAYLOADLEN + NGHTTP2_FRAME_HDLEN));
7852
7853 item = nghttp2_session_get_next_ob_item(session);
7854 /* Since this is the last frame, stream-level WINDOW_UPDATE is not
7855 issued, but connection-level is. */
7856 assert_uint8(NGHTTP2_WINDOW_UPDATE, ==, item->frame.hd.type);
7857 assert_int32(0, ==, item->frame.hd.stream_id);
7858 assert_int32(NGHTTP2_MAX_PAYLOADLEN, ==,
7859 item->frame.window_update.window_size_increment);
7860
7861 assert_int(0, ==, nghttp2_session_send(session));
7862
7863 /* Receive DATA for closed stream. They are still subject to under
7864 connection-level flow control, since this situation arises when
7865 RST_STREAM is issued by the remote, but the local side keeps
7866 sending DATA frames. Without calculating connection-level window,
7867 the subsequent flow control gets confused. */
7868 assert_ptrdiff(
7869 NGHTTP2_MAX_PAYLOADLEN + NGHTTP2_FRAME_HDLEN, ==,
7870 nghttp2_session_mem_recv2(session, data,
7871 NGHTTP2_MAX_PAYLOADLEN + NGHTTP2_FRAME_HDLEN));
7872
7873 item = nghttp2_session_get_next_ob_item(session);
7874 assert_uint8(NGHTTP2_WINDOW_UPDATE, ==, item->frame.hd.type);
7875 assert_int32(0, ==, item->frame.hd.stream_id);
7876 assert_int32(NGHTTP2_MAX_PAYLOADLEN, ==,
7877 item->frame.window_update.window_size_increment);
7878
7879 nghttp2_session_del(session);
7880 }
7881
test_nghttp2_session_flow_control_data_with_padding_recv(void)7882 void test_nghttp2_session_flow_control_data_with_padding_recv(void) {
7883 nghttp2_session *session;
7884 nghttp2_session_callbacks callbacks;
7885 uint8_t data[1024];
7886 nghttp2_frame_hd hd;
7887 nghttp2_stream *stream;
7888 nghttp2_option *option;
7889
7890 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7891 callbacks.send_callback2 = null_send_callback;
7892
7893 nghttp2_option_new(&option);
7894 /* Disable auto window update so that we can check padding is
7895 consumed automatically */
7896 nghttp2_option_set_no_auto_window_update(option, 1);
7897
7898 /* Initial window size to 64KiB - 1*/
7899 nghttp2_session_client_new2(&session, &callbacks, NULL, option);
7900
7901 nghttp2_option_del(option);
7902
7903 stream = open_sent_stream(session, 1);
7904
7905 /* Create DATA frame */
7906 memset(data, 0, sizeof(data));
7907 nghttp2_frame_hd_init(&hd, 357, NGHTTP2_DATA, NGHTTP2_FLAG_PADDED, 1);
7908
7909 nghttp2_frame_pack_frame_hd(data, &hd);
7910 /* Set Pad Length field, which itself is padding */
7911 data[NGHTTP2_FRAME_HDLEN] = 255;
7912
7913 assert_ptrdiff(
7914 (nghttp2_ssize)(NGHTTP2_FRAME_HDLEN + hd.length), ==,
7915 nghttp2_session_mem_recv2(session, data, NGHTTP2_FRAME_HDLEN + hd.length));
7916
7917 assert_int32((int32_t)hd.length, ==, session->recv_window_size);
7918 assert_int32((int32_t)hd.length, ==, stream->recv_window_size);
7919 assert_int32(256, ==, session->consumed_size);
7920 assert_int32(256, ==, stream->consumed_size);
7921 assert_int32(357, ==, session->recv_window_size);
7922 assert_int32(357, ==, stream->recv_window_size);
7923
7924 /* Receive the same DATA frame, but in 2 parts: first 9 + 1 + 102
7925 bytes which includes 1st padding byte, and remainder */
7926 assert_ptrdiff(
7927 (nghttp2_ssize)(NGHTTP2_FRAME_HDLEN + 103), ==,
7928 nghttp2_session_mem_recv2(session, data, NGHTTP2_FRAME_HDLEN + 103));
7929 assert_int32(258, ==, session->consumed_size);
7930 assert_int32(258, ==, stream->consumed_size);
7931 assert_int32(460, ==, session->recv_window_size);
7932 assert_int32(460, ==, stream->recv_window_size);
7933
7934 /* 357 - 103 = 254 bytes left */
7935 assert_ptrdiff(254, ==, nghttp2_session_mem_recv2(session, data, 254));
7936 assert_int32(512, ==, session->consumed_size);
7937 assert_int32(512, ==, stream->consumed_size);
7938 assert_int32(714, ==, session->recv_window_size);
7939 assert_int32(714, ==, stream->recv_window_size);
7940
7941 /* Receive the same DATA frame, but in 2 parts: first 9 = 1 + 101
7942 bytes which only includes data without padding, 2nd part is
7943 padding only */
7944 assert_ptrdiff(
7945 (nghttp2_ssize)(NGHTTP2_FRAME_HDLEN + 102), ==,
7946 nghttp2_session_mem_recv2(session, data, NGHTTP2_FRAME_HDLEN + 102));
7947 assert_int32(513, ==, session->consumed_size);
7948 assert_int32(513, ==, stream->consumed_size);
7949 assert_int32(816, ==, session->recv_window_size);
7950 assert_int32(816, ==, stream->recv_window_size);
7951
7952 /* 357 - 102 = 255 bytes left */
7953 assert_ptrdiff(255, ==, nghttp2_session_mem_recv2(session, data, 255));
7954 assert_int32(768, ==, session->consumed_size);
7955 assert_int32(768, ==, stream->consumed_size);
7956 assert_int32(1071, ==, session->recv_window_size);
7957 assert_int32(1071, ==, stream->recv_window_size);
7958
7959 /* Receive the same DATA frame, but in 2 parts: first 9 = 1 + 50
7960 bytes which includes byte up to middle of data, 2nd part is the
7961 remainder */
7962 assert_ptrdiff(
7963 (nghttp2_ssize)(NGHTTP2_FRAME_HDLEN + 51), ==,
7964 nghttp2_session_mem_recv2(session, data, NGHTTP2_FRAME_HDLEN + 51));
7965 assert_int32(769, ==, session->consumed_size);
7966 assert_int32(769, ==, stream->consumed_size);
7967 assert_int32(1122, ==, session->recv_window_size);
7968 assert_int32(1122, ==, stream->recv_window_size);
7969
7970 /* 357 - 51 = 306 bytes left */
7971 assert_ptrdiff(306, ==, nghttp2_session_mem_recv2(session, data, 306));
7972 assert_int32(1024, ==, session->consumed_size);
7973 assert_int32(1024, ==, stream->consumed_size);
7974 assert_int32(1428, ==, session->recv_window_size);
7975 assert_int32(1428, ==, stream->recv_window_size);
7976
7977 nghttp2_session_del(session);
7978 }
7979
test_nghttp2_session_data_read_temporal_failure(void)7980 void test_nghttp2_session_data_read_temporal_failure(void) {
7981 nghttp2_session *session;
7982 nghttp2_session_callbacks callbacks;
7983 my_user_data ud;
7984 nghttp2_data_provider2 data_prd;
7985 nghttp2_frame frame;
7986 nghttp2_stream *stream;
7987 size_t data_size = 128 * 1024;
7988
7989 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7990 callbacks.send_callback2 = null_send_callback;
7991 callbacks.on_frame_send_callback = on_frame_send_callback;
7992 data_prd.read_callback = fixed_length_data_source_read_callback;
7993
7994 ud.data_source_length = data_size;
7995
7996 /* Initial window size is 64KiB - 1 */
7997 nghttp2_session_client_new(&session, &callbacks, &ud);
7998 nghttp2_submit_request2(session, NULL, NULL, 0, &data_prd, NULL);
7999
8000 /* Sends NGHTTP2_INITIAL_WINDOW_SIZE data, assuming, it is equal to
8001 or smaller than NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE */
8002 assert_int(0, ==, nghttp2_session_send(session));
8003 assert_size(data_size - NGHTTP2_INITIAL_WINDOW_SIZE, ==,
8004 ud.data_source_length);
8005
8006 stream = nghttp2_session_get_stream(session, 1);
8007 assert_uint8(NGHTTP2_DATA, ==, stream->item->frame.hd.type);
8008
8009 stream->item->aux_data.data.dpw.data_prd.v1.read_callback =
8010 temporal_failure_data_source_read_callback;
8011
8012 /* Back NGHTTP2_INITIAL_WINDOW_SIZE to both connection-level and
8013 stream-wise window */
8014 nghttp2_frame_window_update_init(&frame.window_update, NGHTTP2_FLAG_NONE, 1,
8015 NGHTTP2_INITIAL_WINDOW_SIZE);
8016 nghttp2_session_on_window_update_received(session, &frame);
8017 frame.hd.stream_id = 0;
8018 nghttp2_session_on_window_update_received(session, &frame);
8019 nghttp2_frame_window_update_free(&frame.window_update);
8020
8021 /* Sending data will fail (soft fail) and treated as stream error */
8022 ud.frame_send_cb_called = 0;
8023 assert_int(0, ==, nghttp2_session_send(session));
8024 assert_size(data_size - NGHTTP2_INITIAL_WINDOW_SIZE, ==,
8025 ud.data_source_length);
8026
8027 assert_int(1, ==, ud.frame_send_cb_called);
8028 assert_uint8(NGHTTP2_RST_STREAM, ==, ud.sent_frame_type);
8029
8030 data_prd.read_callback = fail_data_source_read_callback;
8031 nghttp2_submit_request2(session, NULL, NULL, 0, &data_prd, NULL);
8032 /* Sending data will fail (hard fail) and session tear down */
8033 assert_int(NGHTTP2_ERR_CALLBACK_FAILURE, ==, nghttp2_session_send(session));
8034
8035 nghttp2_session_del(session);
8036 }
8037
test_nghttp2_session_on_stream_close(void)8038 void test_nghttp2_session_on_stream_close(void) {
8039 nghttp2_session *session;
8040 nghttp2_session_callbacks callbacks;
8041 my_user_data user_data;
8042 nghttp2_stream *stream;
8043
8044 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
8045 callbacks.on_stream_close_callback = on_stream_close_callback;
8046 user_data.stream_close_cb_called = 0;
8047
8048 nghttp2_session_client_new(&session, &callbacks, &user_data);
8049 stream =
8050 open_sent_stream3(session, 1, NGHTTP2_STREAM_FLAG_NONE, &pri_spec_default,
8051 NGHTTP2_STREAM_OPENED, &user_data);
8052 assert_not_null(stream);
8053 assert_int(0, ==, nghttp2_session_close_stream(session, 1, NGHTTP2_NO_ERROR));
8054 assert_int(1, ==, user_data.stream_close_cb_called);
8055 nghttp2_session_del(session);
8056 }
8057
test_nghttp2_session_on_ctrl_not_send(void)8058 void test_nghttp2_session_on_ctrl_not_send(void) {
8059 nghttp2_session *session;
8060 nghttp2_session_callbacks callbacks;
8061 my_user_data user_data;
8062 nghttp2_stream *stream;
8063
8064 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
8065 callbacks.on_frame_not_send_callback = on_frame_not_send_callback;
8066 callbacks.send_callback2 = null_send_callback;
8067 user_data.frame_not_send_cb_called = 0;
8068 user_data.not_sent_frame_type = 0;
8069 user_data.not_sent_error = 0;
8070
8071 nghttp2_session_server_new(&session, &callbacks, &user_data);
8072 stream =
8073 open_recv_stream3(session, 1, NGHTTP2_STREAM_FLAG_NONE, &pri_spec_default,
8074 NGHTTP2_STREAM_OPENING, &user_data);
8075
8076 /* Check response HEADERS */
8077 /* Send bogus stream ID */
8078 assert_int32(0, ==,
8079 nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, 3, NULL,
8080 NULL, 0, NULL));
8081 assert_int(0, ==, nghttp2_session_send(session));
8082 assert_int(1, ==, user_data.frame_not_send_cb_called);
8083 assert_uint8(NGHTTP2_HEADERS, ==, user_data.not_sent_frame_type);
8084 assert_int(NGHTTP2_ERR_STREAM_CLOSED, ==, user_data.not_sent_error);
8085
8086 user_data.frame_not_send_cb_called = 0;
8087 /* Shutdown transmission */
8088 stream->shut_flags |= NGHTTP2_SHUT_WR;
8089 assert_int32(0, ==,
8090 nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, 1, NULL,
8091 NULL, 0, NULL));
8092 assert_int(0, ==, nghttp2_session_send(session));
8093 assert_int(1, ==, user_data.frame_not_send_cb_called);
8094 assert_uint8(NGHTTP2_HEADERS, ==, user_data.not_sent_frame_type);
8095 assert_int(NGHTTP2_ERR_STREAM_SHUT_WR, ==, user_data.not_sent_error);
8096
8097 stream->shut_flags = NGHTTP2_SHUT_NONE;
8098 user_data.frame_not_send_cb_called = 0;
8099 /* Queue RST_STREAM */
8100 assert_int32(0, ==,
8101 nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, 1, NULL,
8102 NULL, 0, NULL));
8103 assert_int(0, ==,
8104 nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, 1,
8105 NGHTTP2_INTERNAL_ERROR));
8106 assert_int(0, ==, nghttp2_session_send(session));
8107 assert_int(1, ==, user_data.frame_not_send_cb_called);
8108 assert_uint8(NGHTTP2_HEADERS, ==, user_data.not_sent_frame_type);
8109 assert_int(NGHTTP2_ERR_STREAM_CLOSING, ==, user_data.not_sent_error);
8110
8111 nghttp2_session_del(session);
8112
8113 /* Check request HEADERS */
8114 user_data.frame_not_send_cb_called = 0;
8115 assert_int(0, ==,
8116 nghttp2_session_client_new(&session, &callbacks, &user_data));
8117 /* Maximum Stream ID is reached */
8118 session->next_stream_id = (1u << 31) + 1;
8119 assert_int32(NGHTTP2_ERR_STREAM_ID_NOT_AVAILABLE, ==,
8120 nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, -1,
8121 NULL, NULL, 0, NULL));
8122
8123 user_data.frame_not_send_cb_called = 0;
8124 /* GOAWAY received */
8125 session->goaway_flags |= NGHTTP2_GOAWAY_RECV;
8126 session->next_stream_id = 9;
8127
8128 assert_int32(0, <,
8129 nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, -1,
8130 NULL, NULL, 0, NULL));
8131 assert_int(0, ==, nghttp2_session_send(session));
8132 assert_int(1, ==, user_data.frame_not_send_cb_called);
8133 assert_uint8(NGHTTP2_HEADERS, ==, user_data.not_sent_frame_type);
8134 assert_int(NGHTTP2_ERR_START_STREAM_NOT_ALLOWED, ==,
8135 user_data.not_sent_error);
8136
8137 nghttp2_session_del(session);
8138 }
8139
test_nghttp2_session_get_outbound_queue_size(void)8140 void test_nghttp2_session_get_outbound_queue_size(void) {
8141 nghttp2_session *session;
8142 nghttp2_session_callbacks callbacks;
8143
8144 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
8145 assert_int(0, ==, nghttp2_session_client_new(&session, &callbacks, NULL));
8146 assert_size(0, ==, nghttp2_session_get_outbound_queue_size(session));
8147
8148 assert_int(0, ==, nghttp2_submit_ping(session, NGHTTP2_FLAG_NONE, NULL));
8149 assert_size(1, ==, nghttp2_session_get_outbound_queue_size(session));
8150
8151 assert_int(0, ==,
8152 nghttp2_submit_goaway(session, NGHTTP2_FLAG_NONE, 2,
8153 NGHTTP2_NO_ERROR, NULL, 0));
8154 assert_size(2, ==, nghttp2_session_get_outbound_queue_size(session));
8155
8156 nghttp2_session_del(session);
8157 }
8158
test_nghttp2_session_get_effective_local_window_size(void)8159 void test_nghttp2_session_get_effective_local_window_size(void) {
8160 nghttp2_session *session;
8161 nghttp2_session_callbacks callbacks;
8162 nghttp2_stream *stream;
8163
8164 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
8165 assert_int(0, ==, nghttp2_session_client_new(&session, &callbacks, NULL));
8166
8167 stream = open_sent_stream(session, 1);
8168
8169 assert_int32(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE, ==,
8170 nghttp2_session_get_effective_local_window_size(session));
8171 assert_int32(0, ==, nghttp2_session_get_effective_recv_data_length(session));
8172
8173 assert_int32(
8174 NGHTTP2_INITIAL_WINDOW_SIZE, ==,
8175 nghttp2_session_get_stream_effective_local_window_size(session, 1));
8176 assert_int32(
8177 0, ==, nghttp2_session_get_stream_effective_recv_data_length(session, 1));
8178
8179 /* Check connection flow control */
8180 session->recv_window_size = 100;
8181 nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 0, 1100);
8182
8183 assert_int32(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE + 1000, ==,
8184 nghttp2_session_get_effective_local_window_size(session));
8185 assert_int32(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE + 1000, ==,
8186 nghttp2_session_get_local_window_size(session));
8187 assert_int32(0, ==, nghttp2_session_get_effective_recv_data_length(session));
8188
8189 nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 0, -50);
8190 /* Now session->recv_window_size = -50 */
8191 assert_int32(-50, ==, session->recv_window_size);
8192 assert_int32(50, ==, session->recv_reduction);
8193 assert_int32(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE + 950, ==,
8194 nghttp2_session_get_effective_local_window_size(session));
8195 assert_int32(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE + 1000, ==,
8196 nghttp2_session_get_local_window_size(session));
8197 assert_int32(0, ==, nghttp2_session_get_effective_recv_data_length(session));
8198
8199 session->recv_window_size += 50;
8200
8201 /* Now session->recv_window_size = 0 */
8202
8203 assert_int32(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE + 950, ==,
8204 nghttp2_session_get_local_window_size(session));
8205
8206 nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 0, 100);
8207 assert_int32(50, ==, session->recv_window_size);
8208 assert_int32(0, ==, session->recv_reduction);
8209 assert_int32(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE + 1050, ==,
8210 nghttp2_session_get_effective_local_window_size(session));
8211 assert_int32(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE + 1000, ==,
8212 nghttp2_session_get_local_window_size(session));
8213 assert_int32(50, ==, nghttp2_session_get_effective_recv_data_length(session));
8214
8215 /* Check stream flow control */
8216 stream->recv_window_size = 100;
8217 nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 1, 1100);
8218
8219 assert_int32(
8220 NGHTTP2_INITIAL_WINDOW_SIZE + 1000, ==,
8221 nghttp2_session_get_stream_effective_local_window_size(session, 1));
8222 assert_int32(NGHTTP2_INITIAL_WINDOW_SIZE + 1000, ==,
8223 nghttp2_session_get_stream_local_window_size(session, 1));
8224 assert_int32(
8225 0, ==, nghttp2_session_get_stream_effective_recv_data_length(session, 1));
8226
8227 nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 1, -50);
8228 /* Now stream->recv_window_size = -50 */
8229 assert_int32(
8230 NGHTTP2_INITIAL_WINDOW_SIZE + 950, ==,
8231 nghttp2_session_get_stream_effective_local_window_size(session, 1));
8232 assert_int32(NGHTTP2_INITIAL_WINDOW_SIZE + 1000, ==,
8233 nghttp2_session_get_stream_local_window_size(session, 1));
8234 assert_int32(
8235 0, ==, nghttp2_session_get_stream_effective_recv_data_length(session, 1));
8236
8237 stream->recv_window_size += 50;
8238 /* Now stream->recv_window_size = 0 */
8239 nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 1, 100);
8240 assert_int32(
8241 NGHTTP2_INITIAL_WINDOW_SIZE + 1050, ==,
8242 nghttp2_session_get_stream_effective_local_window_size(session, 1));
8243 assert_int32(NGHTTP2_INITIAL_WINDOW_SIZE + 1000, ==,
8244 nghttp2_session_get_stream_local_window_size(session, 1));
8245 assert_int32(
8246 50, ==, nghttp2_session_get_stream_effective_recv_data_length(session, 1));
8247
8248 nghttp2_session_del(session);
8249 }
8250
test_nghttp2_session_set_option(void)8251 void test_nghttp2_session_set_option(void) {
8252 nghttp2_session *session;
8253 nghttp2_session_callbacks callbacks;
8254 nghttp2_option *option;
8255 nghttp2_hd_deflater *deflater;
8256 int rv;
8257
8258 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
8259 callbacks.send_callback2 = null_send_callback;
8260
8261 /* Test for nghttp2_option_set_no_auto_window_update */
8262 nghttp2_option_new(&option);
8263 nghttp2_option_set_no_auto_window_update(option, 1);
8264
8265 nghttp2_session_client_new2(&session, &callbacks, NULL, option);
8266
8267 assert_true(session->opt_flags & NGHTTP2_OPTMASK_NO_AUTO_WINDOW_UPDATE);
8268
8269 nghttp2_session_del(session);
8270 nghttp2_option_del(option);
8271
8272 /* Test for nghttp2_option_set_peer_max_concurrent_streams */
8273 nghttp2_option_new(&option);
8274 nghttp2_option_set_peer_max_concurrent_streams(option, 100);
8275
8276 nghttp2_session_client_new2(&session, &callbacks, NULL, option);
8277
8278 assert_uint32(100, ==, session->remote_settings.max_concurrent_streams);
8279 nghttp2_session_del(session);
8280 nghttp2_option_del(option);
8281
8282 /* Test for nghttp2_option_set_max_reserved_remote_streams */
8283 nghttp2_option_new(&option);
8284 nghttp2_option_set_max_reserved_remote_streams(option, 99);
8285
8286 nghttp2_session_client_new2(&session, &callbacks, NULL, option);
8287
8288 assert_size(99, ==, session->max_incoming_reserved_streams);
8289 nghttp2_session_del(session);
8290 nghttp2_option_del(option);
8291
8292 /* Test for nghttp2_option_set_no_auto_ping_ack */
8293 nghttp2_option_new(&option);
8294 nghttp2_option_set_no_auto_ping_ack(option, 1);
8295
8296 nghttp2_session_client_new2(&session, &callbacks, NULL, option);
8297
8298 assert_true(session->opt_flags & NGHTTP2_OPTMASK_NO_AUTO_PING_ACK);
8299
8300 nghttp2_session_del(session);
8301 nghttp2_option_del(option);
8302
8303 /* Test for nghttp2_option_set_max_deflate_dynamic_table_size */
8304 nghttp2_option_new(&option);
8305 nghttp2_option_set_max_deflate_dynamic_table_size(option, 0);
8306
8307 nghttp2_session_client_new2(&session, &callbacks, NULL, option);
8308
8309 deflater = &session->hd_deflater;
8310
8311 rv = nghttp2_submit_request2(session, NULL, reqnv, ARRLEN(reqnv), NULL, NULL);
8312
8313 assert_int(1, ==, rv);
8314
8315 rv = nghttp2_session_send(session);
8316
8317 assert_int(0, ==, rv);
8318 assert_size(0, ==, deflater->deflate_hd_table_bufsize_max);
8319 assert_size(0, ==, deflater->ctx.hd_table_bufsize);
8320
8321 nghttp2_session_del(session);
8322 nghttp2_option_del(option);
8323 }
8324
test_nghttp2_session_data_backoff_by_high_pri_frame(void)8325 void test_nghttp2_session_data_backoff_by_high_pri_frame(void) {
8326 nghttp2_session *session;
8327 nghttp2_session_callbacks callbacks;
8328 my_user_data ud;
8329 nghttp2_data_provider2 data_prd;
8330 nghttp2_stream *stream;
8331
8332 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
8333 callbacks.send_callback2 = block_count_send_callback;
8334 callbacks.on_frame_send_callback = on_frame_send_callback;
8335 data_prd.read_callback = fixed_length_data_source_read_callback;
8336
8337 ud.frame_send_cb_called = 0;
8338 ud.data_source_length = NGHTTP2_DATA_PAYLOADLEN * 4;
8339
8340 nghttp2_session_client_new(&session, &callbacks, &ud);
8341 nghttp2_submit_request2(session, NULL, NULL, 0, &data_prd, NULL);
8342
8343 session->remote_window_size = 1 << 20;
8344
8345 ud.block_count = 2;
8346 /* Sends request HEADERS + DATA[0] */
8347 assert_int(0, ==, nghttp2_session_send(session));
8348
8349 stream = nghttp2_session_get_stream(session, 1);
8350 stream->remote_window_size = 1 << 20;
8351
8352 assert_uint8(NGHTTP2_DATA, ==, ud.sent_frame_type);
8353 /* data for DATA[1] is read from data_prd but it is not sent */
8354 assert_size(ud.data_source_length, ==, NGHTTP2_DATA_PAYLOADLEN * 2);
8355
8356 nghttp2_submit_ping(session, NGHTTP2_FLAG_NONE, NULL);
8357 ud.block_count = 2;
8358 /* Sends DATA[1] + PING, PING is interleaved in DATA sequence */
8359 assert_int(0, ==, nghttp2_session_send(session));
8360 assert_uint8(NGHTTP2_PING, ==, ud.sent_frame_type);
8361 /* data for DATA[2] is read from data_prd but it is not sent */
8362 assert_size(ud.data_source_length, ==, NGHTTP2_DATA_PAYLOADLEN);
8363
8364 ud.block_count = 2;
8365 /* Sends DATA[2..3] */
8366 assert_int(0, ==, nghttp2_session_send(session));
8367
8368 assert_true(stream->shut_flags & NGHTTP2_SHUT_WR);
8369
8370 nghttp2_session_del(session);
8371 }
8372
check_session_recv_data_with_padding(nghttp2_bufs * bufs,size_t datalen,nghttp2_mem * mem)8373 static void check_session_recv_data_with_padding(nghttp2_bufs *bufs,
8374 size_t datalen,
8375 nghttp2_mem *mem) {
8376 nghttp2_session *session;
8377 my_user_data ud;
8378 nghttp2_session_callbacks callbacks;
8379 uint8_t *in;
8380 size_t inlen;
8381
8382 memset(&callbacks, 0, sizeof(callbacks));
8383 callbacks.on_frame_recv_callback = on_frame_recv_callback;
8384 callbacks.on_data_chunk_recv_callback = on_data_chunk_recv_callback;
8385 nghttp2_session_server_new(&session, &callbacks, &ud);
8386
8387 open_recv_stream(session, 1);
8388
8389 inlen = (size_t)nghttp2_bufs_remove(bufs, &in);
8390
8391 ud.frame_recv_cb_called = 0;
8392 ud.data_chunk_len = 0;
8393
8394 assert_ptrdiff((nghttp2_ssize)inlen, ==,
8395 nghttp2_session_mem_recv2(session, in, inlen));
8396
8397 assert_int(1, ==, ud.frame_recv_cb_called);
8398 assert_size(datalen, ==, ud.data_chunk_len);
8399
8400 mem->free(in, NULL);
8401 nghttp2_session_del(session);
8402 }
8403
test_nghttp2_session_pack_data_with_padding(void)8404 void test_nghttp2_session_pack_data_with_padding(void) {
8405 nghttp2_session *session;
8406 my_user_data ud;
8407 nghttp2_session_callbacks callbacks;
8408 nghttp2_data_provider2 data_prd;
8409 nghttp2_frame *frame;
8410 size_t datalen = 55;
8411 nghttp2_mem *mem;
8412
8413 mem = nghttp2_mem_default();
8414
8415 memset(&callbacks, 0, sizeof(callbacks));
8416 callbacks.send_callback2 = block_count_send_callback;
8417 callbacks.on_frame_send_callback = on_frame_send_callback;
8418 callbacks.select_padding_callback2 = select_padding_callback;
8419
8420 data_prd.read_callback = fixed_length_data_source_read_callback;
8421
8422 nghttp2_session_client_new(&session, &callbacks, &ud);
8423
8424 ud.padlen = 63;
8425
8426 nghttp2_submit_request2(session, NULL, NULL, 0, &data_prd, NULL);
8427 ud.block_count = 1;
8428 ud.data_source_length = datalen;
8429 /* Sends HEADERS */
8430 assert_int(0, ==, nghttp2_session_send(session));
8431 assert_uint8(NGHTTP2_HEADERS, ==, ud.sent_frame_type);
8432
8433 frame = &session->aob.item->frame;
8434
8435 assert_size(ud.padlen, ==, frame->data.padlen);
8436 assert_true(frame->hd.flags & NGHTTP2_FLAG_PADDED);
8437
8438 /* Check reception of this DATA frame */
8439 check_session_recv_data_with_padding(&session->aob.framebufs, datalen, mem);
8440
8441 nghttp2_session_del(session);
8442 }
8443
test_nghttp2_session_pack_headers_with_padding(void)8444 void test_nghttp2_session_pack_headers_with_padding(void) {
8445 nghttp2_session *session, *sv_session;
8446 accumulator acc;
8447 my_user_data ud;
8448 nghttp2_session_callbacks callbacks;
8449
8450 memset(&callbacks, 0, sizeof(callbacks));
8451 callbacks.send_callback2 = accumulator_send_callback;
8452 callbacks.on_frame_send_callback = on_frame_send_callback;
8453 callbacks.select_padding_callback2 = select_padding_callback;
8454 callbacks.on_frame_recv_callback = on_frame_recv_callback;
8455
8456 acc.length = 0;
8457 ud.acc = &acc;
8458
8459 nghttp2_session_client_new(&session, &callbacks, &ud);
8460 nghttp2_session_server_new(&sv_session, &callbacks, &ud);
8461
8462 ud.padlen = 163;
8463
8464 assert_int32(
8465 1, ==,
8466 nghttp2_submit_request2(session, NULL, reqnv, ARRLEN(reqnv), NULL, NULL));
8467 assert_int(0, ==, nghttp2_session_send(session));
8468
8469 assert_size(NGHTTP2_MAX_PAYLOADLEN, >, acc.length);
8470 ud.frame_recv_cb_called = 0;
8471 assert_ptrdiff((nghttp2_ssize)acc.length, ==,
8472 nghttp2_session_mem_recv2(sv_session, acc.buf, acc.length));
8473 assert_int(1, ==, ud.frame_recv_cb_called);
8474 assert_null(nghttp2_session_get_next_ob_item(sv_session));
8475
8476 nghttp2_session_del(sv_session);
8477 nghttp2_session_del(session);
8478 }
8479
test_nghttp2_pack_settings_payload(void)8480 void test_nghttp2_pack_settings_payload(void) {
8481 nghttp2_settings_entry iv[2];
8482 uint8_t buf[64];
8483 nghttp2_ssize len;
8484 nghttp2_settings_entry *resiv;
8485 size_t resniv;
8486 nghttp2_mem *mem;
8487
8488 mem = nghttp2_mem_default();
8489
8490 iv[0].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
8491 iv[0].value = 1023;
8492 iv[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
8493 iv[1].value = 4095;
8494
8495 len = nghttp2_pack_settings_payload2(buf, sizeof(buf), iv, 2);
8496 assert_ptrdiff(2 * NGHTTP2_FRAME_SETTINGS_ENTRY_LENGTH, ==, len);
8497 assert_int(0, ==,
8498 nghttp2_frame_unpack_settings_payload2(&resiv, &resniv, buf,
8499 (size_t)len, mem));
8500 assert_size(2, ==, resniv);
8501 assert_int32(NGHTTP2_SETTINGS_HEADER_TABLE_SIZE, ==, resiv[0].settings_id);
8502 assert_uint32(1023, ==, resiv[0].value);
8503 assert_int32(NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE, ==, resiv[1].settings_id);
8504 assert_uint32(4095, ==, resiv[1].value);
8505
8506 mem->free(resiv, NULL);
8507
8508 len = nghttp2_pack_settings_payload2(buf, 9 /* too small */, iv, 2);
8509 assert_ptrdiff(NGHTTP2_ERR_INSUFF_BUFSIZE, ==, len);
8510 }
8511
8512 #define check_stream_dep_sib(STREAM, DEP_PREV, DEP_NEXT, SIB_PREV, SIB_NEXT) \
8513 do { \
8514 assert_ptr_equal(DEP_PREV, STREAM->dep_prev); \
8515 assert_ptr_equal(DEP_NEXT, STREAM->dep_next); \
8516 assert_ptr_equal(SIB_PREV, STREAM->sib_prev); \
8517 assert_ptr_equal(SIB_NEXT, STREAM->sib_next); \
8518 } while (0)
8519
8520 /* nghttp2_stream_dep_add() and its families functions should be
8521 tested in nghttp2_stream_test.c, but it is easier to use
8522 nghttp2_session_open_stream(). Therefore, we test them here. */
test_nghttp2_session_stream_dep_add(void)8523 void test_nghttp2_session_stream_dep_add(void) {
8524 nghttp2_session *session;
8525 nghttp2_session_callbacks callbacks;
8526 nghttp2_stream *a, *b, *c, *d, *e, *root;
8527
8528 memset(&callbacks, 0, sizeof(callbacks));
8529
8530 nghttp2_session_server_new(&session, &callbacks, NULL);
8531
8532 root = &session->root;
8533
8534 a = open_stream(session, 1);
8535
8536 c = open_stream_with_dep(session, 5, a);
8537 b = open_stream_with_dep(session, 3, a);
8538 d = open_stream_with_dep(session, 7, c);
8539
8540 /* a
8541 * |
8542 * b--c
8543 * |
8544 * d
8545 */
8546
8547 assert_int32(NGHTTP2_DEFAULT_WEIGHT * 2, ==, a->sum_dep_weight);
8548 assert_int32(0, ==, b->sum_dep_weight);
8549 assert_int32(NGHTTP2_DEFAULT_WEIGHT, ==, c->sum_dep_weight);
8550 assert_int32(0, ==, d->sum_dep_weight);
8551
8552 check_stream_dep_sib(a, root, b, NULL, NULL);
8553 check_stream_dep_sib(b, a, NULL, NULL, c);
8554 check_stream_dep_sib(c, a, d, b, NULL);
8555 check_stream_dep_sib(d, c, NULL, NULL, NULL);
8556
8557 assert_ptr_equal(a, session->root.dep_next);
8558
8559 e = open_stream_with_dep_excl(session, 9, a);
8560
8561 /* a
8562 * |
8563 * e
8564 * |
8565 * b--c
8566 * |
8567 * d
8568 */
8569
8570 assert_int32(NGHTTP2_DEFAULT_WEIGHT, ==, a->sum_dep_weight);
8571 assert_int32(NGHTTP2_DEFAULT_WEIGHT * 2, ==, e->sum_dep_weight);
8572 assert_int32(0, ==, b->sum_dep_weight);
8573 assert_int32(NGHTTP2_DEFAULT_WEIGHT, ==, c->sum_dep_weight);
8574 assert_int32(0, ==, d->sum_dep_weight);
8575
8576 check_stream_dep_sib(a, root, e, NULL, NULL);
8577 check_stream_dep_sib(e, a, b, NULL, NULL);
8578 check_stream_dep_sib(b, e, NULL, NULL, c);
8579 check_stream_dep_sib(c, e, d, b, NULL);
8580 check_stream_dep_sib(d, c, NULL, NULL, NULL);
8581
8582 assert_ptr_equal(a, session->root.dep_next);
8583
8584 nghttp2_session_del(session);
8585 }
8586
test_nghttp2_session_stream_dep_remove(void)8587 void test_nghttp2_session_stream_dep_remove(void) {
8588 nghttp2_session *session;
8589 nghttp2_session_callbacks callbacks;
8590 nghttp2_stream *a, *b, *c, *d, *e, *f, *root;
8591
8592 memset(&callbacks, 0, sizeof(callbacks));
8593
8594 /* Remove root */
8595 nghttp2_session_server_new(&session, &callbacks, NULL);
8596
8597 root = &session->root;
8598
8599 a = open_stream(session, 1);
8600 b = open_stream_with_dep(session, 3, a);
8601 c = open_stream_with_dep(session, 5, a);
8602 d = open_stream_with_dep(session, 7, c);
8603
8604 /* a
8605 * |
8606 * c--b
8607 * |
8608 * d
8609 */
8610
8611 nghttp2_stream_dep_remove(a);
8612
8613 /* becomes:
8614 * c b
8615 * |
8616 * d
8617 */
8618
8619 assert_int32(0, ==, a->sum_dep_weight);
8620 assert_int32(0, ==, b->sum_dep_weight);
8621 assert_int32(NGHTTP2_DEFAULT_WEIGHT, ==, c->sum_dep_weight);
8622 assert_int32(0, ==, d->sum_dep_weight);
8623
8624 check_stream_dep_sib(a, NULL, NULL, NULL, NULL);
8625 check_stream_dep_sib(b, root, NULL, c, NULL);
8626 check_stream_dep_sib(c, root, d, NULL, b);
8627 check_stream_dep_sib(d, c, NULL, NULL, NULL);
8628
8629 assert_ptr_equal(c, session->root.dep_next);
8630
8631 nghttp2_session_del(session);
8632
8633 /* Remove right most stream */
8634 nghttp2_session_server_new(&session, &callbacks, NULL);
8635
8636 root = &session->root;
8637
8638 a = open_stream(session, 1);
8639 b = open_stream_with_dep(session, 3, a);
8640 c = open_stream_with_dep(session, 5, a);
8641 d = open_stream_with_dep(session, 7, c);
8642
8643 /* a
8644 * |
8645 * c--b
8646 * |
8647 * d
8648 */
8649
8650 nghttp2_stream_dep_remove(b);
8651
8652 /* becomes:
8653 * a
8654 * |
8655 * c
8656 * |
8657 * d
8658 */
8659
8660 assert_int32(NGHTTP2_DEFAULT_WEIGHT, ==, a->sum_dep_weight);
8661 assert_int32(NGHTTP2_DEFAULT_WEIGHT, ==, c->sum_dep_weight);
8662 assert_int32(0, ==, d->sum_dep_weight);
8663 assert_int32(0, ==, b->sum_dep_weight);
8664
8665 check_stream_dep_sib(a, root, c, NULL, NULL);
8666 check_stream_dep_sib(b, NULL, NULL, NULL, NULL);
8667 check_stream_dep_sib(c, a, d, NULL, NULL);
8668 check_stream_dep_sib(d, c, NULL, NULL, NULL);
8669
8670 assert_ptr_equal(a, session->root.dep_next);
8671
8672 nghttp2_session_del(session);
8673
8674 /* Remove left most stream */
8675 nghttp2_session_server_new(&session, &callbacks, NULL);
8676
8677 root = &session->root;
8678
8679 a = open_stream(session, 1);
8680 b = open_stream_with_dep(session, 3, a);
8681 c = open_stream_with_dep(session, 5, a);
8682 d = open_stream_with_dep(session, 7, c);
8683 e = open_stream_with_dep(session, 9, c);
8684
8685 /* a
8686 * |
8687 * c--b
8688 * |
8689 * e--d
8690 */
8691
8692 nghttp2_stream_dep_remove(c);
8693
8694 /* becomes:
8695 * a
8696 * |
8697 * e--d--b
8698 */
8699
8700 assert_int32(NGHTTP2_DEFAULT_WEIGHT * 2, ==, a->sum_dep_weight);
8701 assert_int32(0, ==, b->sum_dep_weight);
8702 assert_int32(0, ==, d->sum_dep_weight);
8703 assert_int32(0, ==, c->sum_dep_weight);
8704 assert_int32(0, ==, e->sum_dep_weight);
8705
8706 check_stream_dep_sib(a, root, e, NULL, NULL);
8707 check_stream_dep_sib(b, a, NULL, d, NULL);
8708 check_stream_dep_sib(c, NULL, NULL, NULL, NULL);
8709 check_stream_dep_sib(d, a, NULL, e, b);
8710 check_stream_dep_sib(e, a, NULL, NULL, d);
8711
8712 nghttp2_session_del(session);
8713
8714 /* Remove middle stream */
8715 nghttp2_session_server_new(&session, &callbacks, NULL);
8716
8717 root = &session->root;
8718
8719 a = open_stream(session, 1);
8720 b = open_stream_with_dep(session, 3, a);
8721 c = open_stream_with_dep(session, 5, a);
8722 d = open_stream_with_dep(session, 7, a);
8723 e = open_stream_with_dep(session, 9, c);
8724 f = open_stream_with_dep(session, 11, c);
8725
8726 /* a
8727 * |
8728 * d--c--b
8729 * |
8730 * f--e
8731 */
8732
8733 assert_int32(NGHTTP2_DEFAULT_WEIGHT * 3, ==, a->sum_dep_weight);
8734 assert_int32(0, ==, b->sum_dep_weight);
8735 assert_int32(NGHTTP2_DEFAULT_WEIGHT * 2, ==, c->sum_dep_weight);
8736 assert_int32(0, ==, d->sum_dep_weight);
8737 assert_int32(0, ==, e->sum_dep_weight);
8738 assert_int32(0, ==, f->sum_dep_weight);
8739
8740 nghttp2_stream_dep_remove(c);
8741
8742 /* becomes:
8743 * a
8744 * |
8745 * d--f--e--b
8746 */
8747
8748 /* c's weight 16 is distributed evenly to e and f. Each weight of e
8749 and f becomes 8. */
8750 assert_int32(NGHTTP2_DEFAULT_WEIGHT * 2 + 8 * 2, ==, a->sum_dep_weight);
8751 assert_int32(0, ==, b->sum_dep_weight);
8752 assert_int32(0, ==, c->sum_dep_weight);
8753 assert_int32(0, ==, d->sum_dep_weight);
8754 assert_int32(0, ==, e->sum_dep_weight);
8755 assert_int32(0, ==, f->sum_dep_weight);
8756
8757 check_stream_dep_sib(a, root, d, NULL, NULL);
8758 check_stream_dep_sib(b, a, NULL, e, NULL);
8759 check_stream_dep_sib(c, NULL, NULL, NULL, NULL);
8760 check_stream_dep_sib(e, a, NULL, f, b);
8761 check_stream_dep_sib(f, a, NULL, d, e);
8762 check_stream_dep_sib(d, a, NULL, NULL, f);
8763
8764 nghttp2_session_del(session);
8765 }
8766
test_nghttp2_session_stream_dep_add_subtree(void)8767 void test_nghttp2_session_stream_dep_add_subtree(void) {
8768 nghttp2_session *session;
8769 nghttp2_session_callbacks callbacks;
8770 nghttp2_stream *a, *b, *c, *d, *e, *f, *root;
8771
8772 memset(&callbacks, 0, sizeof(callbacks));
8773
8774 /* dep_stream has dep_next */
8775 nghttp2_session_server_new(&session, &callbacks, NULL);
8776
8777 root = &session->root;
8778
8779 a = open_stream(session, 1);
8780 b = open_stream_with_dep(session, 3, a);
8781 c = open_stream_with_dep(session, 5, a);
8782 d = open_stream_with_dep(session, 7, c);
8783
8784 e = open_stream(session, 9);
8785 f = open_stream_with_dep(session, 11, e);
8786
8787 /* a e
8788 * | |
8789 * c--b f
8790 * |
8791 * d
8792 */
8793
8794 nghttp2_stream_dep_remove_subtree(e);
8795 nghttp2_stream_dep_add_subtree(a, e);
8796
8797 /* becomes
8798 * a
8799 * |
8800 * e--c--b
8801 * | |
8802 * f d
8803 */
8804
8805 assert_int32(NGHTTP2_DEFAULT_WEIGHT * 3, ==, a->sum_dep_weight);
8806 assert_int32(0, ==, b->sum_dep_weight);
8807 assert_int32(NGHTTP2_DEFAULT_WEIGHT, ==, c->sum_dep_weight);
8808 assert_int32(0, ==, d->sum_dep_weight);
8809 assert_int32(NGHTTP2_DEFAULT_WEIGHT, ==, e->sum_dep_weight);
8810 assert_int32(0, ==, f->sum_dep_weight);
8811
8812 check_stream_dep_sib(a, root, e, NULL, NULL);
8813 check_stream_dep_sib(b, a, NULL, c, NULL);
8814 check_stream_dep_sib(c, a, d, e, b);
8815 check_stream_dep_sib(d, c, NULL, NULL, NULL);
8816 check_stream_dep_sib(e, a, f, NULL, c);
8817 check_stream_dep_sib(f, e, NULL, NULL, NULL);
8818
8819 nghttp2_session_del(session);
8820
8821 /* dep_stream has dep_next and now we insert subtree */
8822 nghttp2_session_server_new(&session, &callbacks, NULL);
8823
8824 root = &session->root;
8825
8826 a = open_stream(session, 1);
8827 b = open_stream_with_dep(session, 3, a);
8828 c = open_stream_with_dep(session, 5, a);
8829 d = open_stream_with_dep(session, 7, c);
8830
8831 e = open_stream(session, 9);
8832 f = open_stream_with_dep(session, 11, e);
8833
8834 /* a e
8835 * | |
8836 * c--b f
8837 * |
8838 * d
8839 */
8840
8841 nghttp2_stream_dep_remove_subtree(e);
8842 nghttp2_stream_dep_insert_subtree(a, e);
8843
8844 /* becomes
8845 * a
8846 * |
8847 * e
8848 * |
8849 * f--c--b
8850 * |
8851 * d
8852 */
8853
8854 assert_int32(NGHTTP2_DEFAULT_WEIGHT, ==, a->sum_dep_weight);
8855 assert_int32(0, ==, b->sum_dep_weight);
8856 assert_int32(NGHTTP2_DEFAULT_WEIGHT, ==, c->sum_dep_weight);
8857 assert_int32(0, ==, d->sum_dep_weight);
8858 assert_int32(NGHTTP2_DEFAULT_WEIGHT * 3, ==, e->sum_dep_weight);
8859 assert_int32(0, ==, f->sum_dep_weight);
8860
8861 check_stream_dep_sib(a, root, e, NULL, NULL);
8862 check_stream_dep_sib(e, a, f, NULL, NULL);
8863 check_stream_dep_sib(f, e, NULL, NULL, c);
8864 check_stream_dep_sib(b, e, NULL, c, NULL);
8865 check_stream_dep_sib(c, e, d, f, b);
8866 check_stream_dep_sib(d, c, NULL, NULL, NULL);
8867
8868 nghttp2_session_del(session);
8869 }
8870
test_nghttp2_session_stream_dep_remove_subtree(void)8871 void test_nghttp2_session_stream_dep_remove_subtree(void) {
8872 nghttp2_session *session;
8873 nghttp2_session_callbacks callbacks;
8874 nghttp2_stream *a, *b, *c, *d, *e, *root;
8875
8876 memset(&callbacks, 0, sizeof(callbacks));
8877
8878 /* Remove left most stream */
8879 nghttp2_session_server_new(&session, &callbacks, NULL);
8880
8881 root = &session->root;
8882
8883 a = open_stream(session, 1);
8884 b = open_stream_with_dep(session, 3, a);
8885 c = open_stream_with_dep(session, 5, a);
8886 d = open_stream_with_dep(session, 7, c);
8887
8888 /* a
8889 * |
8890 * c--b
8891 * |
8892 * d
8893 */
8894
8895 nghttp2_stream_dep_remove_subtree(c);
8896
8897 /* becomes
8898 * a c
8899 * | |
8900 * b d
8901 */
8902
8903 assert_int32(NGHTTP2_DEFAULT_WEIGHT, ==, a->sum_dep_weight);
8904 assert_int32(0, ==, b->sum_dep_weight);
8905 assert_int32(NGHTTP2_DEFAULT_WEIGHT, ==, c->sum_dep_weight);
8906 assert_int32(0, ==, d->sum_dep_weight);
8907
8908 check_stream_dep_sib(a, root, b, NULL, NULL);
8909 check_stream_dep_sib(b, a, NULL, NULL, NULL);
8910 check_stream_dep_sib(c, NULL, d, NULL, NULL);
8911 check_stream_dep_sib(d, c, NULL, NULL, NULL);
8912
8913 nghttp2_session_del(session);
8914
8915 /* Remove right most stream */
8916 nghttp2_session_server_new(&session, &callbacks, NULL);
8917
8918 root = &session->root;
8919
8920 a = open_stream(session, 1);
8921 b = open_stream_with_dep(session, 3, a);
8922 c = open_stream_with_dep(session, 5, a);
8923 d = open_stream_with_dep(session, 7, c);
8924
8925 /* a
8926 * |
8927 * c--b
8928 * |
8929 * d
8930 */
8931
8932 nghttp2_stream_dep_remove_subtree(b);
8933
8934 /* becomes
8935 * a b
8936 * |
8937 * c
8938 * |
8939 * d
8940 */
8941
8942 assert_int32(NGHTTP2_DEFAULT_WEIGHT, ==, a->sum_dep_weight);
8943 assert_int32(0, ==, b->sum_dep_weight);
8944 assert_int32(NGHTTP2_DEFAULT_WEIGHT, ==, c->sum_dep_weight);
8945 assert_int32(0, ==, d->sum_dep_weight);
8946
8947 check_stream_dep_sib(a, root, c, NULL, NULL);
8948 check_stream_dep_sib(c, a, d, NULL, NULL);
8949 check_stream_dep_sib(d, c, NULL, NULL, NULL);
8950 check_stream_dep_sib(b, NULL, NULL, NULL, NULL);
8951
8952 nghttp2_session_del(session);
8953
8954 /* Remove middle stream */
8955 nghttp2_session_server_new(&session, &callbacks, NULL);
8956
8957 root = &session->root;
8958
8959 a = open_stream(session, 1);
8960 e = open_stream_with_dep(session, 9, a);
8961 c = open_stream_with_dep(session, 5, a);
8962 b = open_stream_with_dep(session, 3, a);
8963 d = open_stream_with_dep(session, 7, c);
8964
8965 /* a
8966 * |
8967 * b--c--e
8968 * |
8969 * d
8970 */
8971
8972 nghttp2_stream_dep_remove_subtree(c);
8973
8974 /* becomes
8975 * a c
8976 * | |
8977 * b--e d
8978 */
8979
8980 assert_int32(NGHTTP2_DEFAULT_WEIGHT * 2, ==, a->sum_dep_weight);
8981 assert_int32(0, ==, b->sum_dep_weight);
8982 assert_int32(NGHTTP2_DEFAULT_WEIGHT, ==, c->sum_dep_weight);
8983 assert_int32(0, ==, d->sum_dep_weight);
8984 assert_int32(0, ==, e->sum_dep_weight);
8985
8986 check_stream_dep_sib(a, root, b, NULL, NULL);
8987 check_stream_dep_sib(b, a, NULL, NULL, e);
8988 check_stream_dep_sib(e, a, NULL, b, NULL);
8989 check_stream_dep_sib(c, NULL, d, NULL, NULL);
8990 check_stream_dep_sib(d, c, NULL, NULL, NULL);
8991
8992 nghttp2_session_del(session);
8993 }
8994
test_nghttp2_session_stream_dep_all_your_stream_are_belong_to_us(void)8995 void test_nghttp2_session_stream_dep_all_your_stream_are_belong_to_us(void) {
8996 nghttp2_session *session;
8997 nghttp2_session_callbacks callbacks;
8998 nghttp2_stream *a, *b, *c, *d, *root;
8999 nghttp2_outbound_item *db, *dc;
9000 nghttp2_mem *mem;
9001
9002 mem = nghttp2_mem_default();
9003
9004 memset(&callbacks, 0, sizeof(callbacks));
9005
9006 nghttp2_session_server_new(&session, &callbacks, NULL);
9007
9008 root = &session->root;
9009
9010 a = open_stream(session, 1);
9011 b = open_stream_with_dep(session, 3, a);
9012
9013 c = open_stream(session, 5);
9014
9015 /* a c
9016 * |
9017 * b
9018 */
9019
9020 nghttp2_stream_dep_remove_subtree(c);
9021 assert_int(0, ==, nghttp2_stream_dep_insert_subtree(&session->root, c));
9022
9023 /*
9024 * c
9025 * |
9026 * a
9027 * |
9028 * b
9029 */
9030
9031 assert_int32(NGHTTP2_DEFAULT_WEIGHT, ==, c->sum_dep_weight);
9032 assert_int32(NGHTTP2_DEFAULT_WEIGHT, ==, a->sum_dep_weight);
9033 assert_int32(0, ==, b->sum_dep_weight);
9034
9035 assert_true(nghttp2_pq_empty(&a->obq));
9036 assert_true(nghttp2_pq_empty(&b->obq));
9037 assert_true(nghttp2_pq_empty(&c->obq));
9038
9039 check_stream_dep_sib(c, root, a, NULL, NULL);
9040 check_stream_dep_sib(a, c, b, NULL, NULL);
9041 check_stream_dep_sib(b, a, NULL, NULL, NULL);
9042
9043 nghttp2_session_del(session);
9044
9045 nghttp2_session_server_new(&session, &callbacks, NULL);
9046
9047 root = &session->root;
9048
9049 a = open_stream(session, 1);
9050 b = open_stream(session, 3);
9051 c = open_stream(session, 5);
9052
9053 /*
9054 * a b c
9055 */
9056
9057 nghttp2_stream_dep_remove_subtree(c);
9058 assert_int(0, ==, nghttp2_stream_dep_insert_subtree(&session->root, c));
9059
9060 /*
9061 * c
9062 * |
9063 * b--a
9064 */
9065
9066 assert_int32(NGHTTP2_DEFAULT_WEIGHT * 2, ==, c->sum_dep_weight);
9067 assert_int32(0, ==, b->sum_dep_weight);
9068 assert_int32(0, ==, a->sum_dep_weight);
9069
9070 assert_true(nghttp2_pq_empty(&a->obq));
9071 assert_true(nghttp2_pq_empty(&b->obq));
9072 assert_true(nghttp2_pq_empty(&c->obq));
9073
9074 check_stream_dep_sib(c, root, b, NULL, NULL);
9075 check_stream_dep_sib(b, c, NULL, NULL, a);
9076 check_stream_dep_sib(a, c, NULL, b, NULL);
9077
9078 nghttp2_session_del(session);
9079
9080 nghttp2_session_server_new(&session, &callbacks, NULL);
9081
9082 root = &session->root;
9083
9084 a = open_stream(session, 1);
9085 b = open_stream_with_dep(session, 3, a);
9086
9087 c = open_stream(session, 5);
9088 d = open_stream_with_dep(session, 7, c);
9089
9090 /* a c
9091 * | |
9092 * b d
9093 */
9094
9095 nghttp2_stream_dep_remove_subtree(c);
9096 assert_int(0, ==, nghttp2_stream_dep_insert_subtree(&session->root, c));
9097
9098 /*
9099 * c
9100 * |
9101 * d--a
9102 * |
9103 * b
9104 */
9105
9106 assert_int32(NGHTTP2_DEFAULT_WEIGHT * 2, ==, c->sum_dep_weight);
9107 assert_int32(0, ==, d->sum_dep_weight);
9108 assert_int32(NGHTTP2_DEFAULT_WEIGHT, ==, a->sum_dep_weight);
9109 assert_int32(0, ==, b->sum_dep_weight);
9110
9111 assert_true(nghttp2_pq_empty(&a->obq));
9112 assert_true(nghttp2_pq_empty(&b->obq));
9113 assert_true(nghttp2_pq_empty(&c->obq));
9114 assert_true(nghttp2_pq_empty(&d->obq));
9115
9116 check_stream_dep_sib(c, root, d, NULL, NULL);
9117 check_stream_dep_sib(d, c, NULL, NULL, a);
9118 check_stream_dep_sib(a, c, b, d, NULL);
9119 check_stream_dep_sib(b, a, NULL, NULL, NULL);
9120
9121 nghttp2_session_del(session);
9122
9123 nghttp2_session_server_new(&session, &callbacks, NULL);
9124
9125 root = &session->root;
9126
9127 a = open_stream(session, 1);
9128 b = open_stream_with_dep(session, 3, a);
9129
9130 c = open_stream(session, 5);
9131 d = open_stream_with_dep(session, 7, c);
9132
9133 /* a c
9134 * | |
9135 * b d
9136 */
9137
9138 db = create_data_ob_item(mem);
9139
9140 nghttp2_stream_attach_item(b, db);
9141
9142 nghttp2_stream_dep_remove_subtree(c);
9143 assert_int(0, ==, nghttp2_stream_dep_insert_subtree(&session->root, c));
9144
9145 /*
9146 * c
9147 * |
9148 * d--a
9149 * |
9150 * b
9151 */
9152
9153 assert_true(c->queued);
9154 assert_true(a->queued);
9155 assert_true(b->queued);
9156 assert_true(!d->queued);
9157
9158 assert_size(1, ==, nghttp2_pq_size(&a->obq));
9159 assert_size(1, ==, nghttp2_pq_size(&c->obq));
9160 assert_true(nghttp2_pq_empty(&d->obq));
9161
9162 check_stream_dep_sib(c, root, d, NULL, NULL);
9163 check_stream_dep_sib(d, c, NULL, NULL, a);
9164 check_stream_dep_sib(a, c, b, d, NULL);
9165 check_stream_dep_sib(b, a, NULL, NULL, NULL);
9166
9167 nghttp2_session_del(session);
9168
9169 nghttp2_session_server_new(&session, &callbacks, NULL);
9170
9171 root = &session->root;
9172
9173 a = open_stream(session, 1);
9174 b = open_stream_with_dep(session, 3, a);
9175
9176 c = open_stream(session, 5);
9177 d = open_stream_with_dep(session, 7, c);
9178
9179 /* a c
9180 * | |
9181 * b d
9182 */
9183
9184 db = create_data_ob_item(mem);
9185 dc = create_data_ob_item(mem);
9186
9187 nghttp2_stream_attach_item(b, db);
9188 nghttp2_stream_attach_item(c, dc);
9189
9190 nghttp2_stream_dep_remove_subtree(c);
9191 assert_int(0, ==, nghttp2_stream_dep_insert_subtree(&session->root, c));
9192
9193 /*
9194 * c
9195 * |
9196 * d--a
9197 * |
9198 * b
9199 */
9200
9201 assert_true(c->queued);
9202 assert_true(a->queued);
9203 assert_true(b->queued);
9204 assert_true(!d->queued);
9205
9206 check_stream_dep_sib(c, root, d, NULL, NULL);
9207 check_stream_dep_sib(d, c, NULL, NULL, a);
9208 check_stream_dep_sib(a, c, b, d, NULL);
9209 check_stream_dep_sib(b, a, NULL, NULL, NULL);
9210
9211 nghttp2_session_del(session);
9212 }
9213
test_nghttp2_session_stream_attach_item(void)9214 void test_nghttp2_session_stream_attach_item(void) {
9215 nghttp2_session *session;
9216 nghttp2_session_callbacks callbacks;
9217 nghttp2_stream *a, *b, *c, *d, *e;
9218 nghttp2_outbound_item *da, *db, *dc, *dd;
9219 nghttp2_mem *mem;
9220
9221 mem = nghttp2_mem_default();
9222
9223 memset(&callbacks, 0, sizeof(callbacks));
9224
9225 nghttp2_session_server_new(&session, &callbacks, NULL);
9226
9227 a = open_stream(session, 1);
9228 b = open_stream_with_dep(session, 3, a);
9229 c = open_stream_with_dep(session, 5, a);
9230 d = open_stream_with_dep(session, 7, c);
9231
9232 /* a
9233 * |
9234 * c--b
9235 * |
9236 * d
9237 */
9238
9239 db = create_data_ob_item(mem);
9240
9241 nghttp2_stream_attach_item(b, db);
9242
9243 assert_true(a->queued);
9244 assert_true(b->queued);
9245 assert_true(!c->queued);
9246 assert_true(!d->queued);
9247
9248 assert_size(1, ==, nghttp2_pq_size(&a->obq));
9249
9250 /* Attach item to c */
9251 dc = create_data_ob_item(mem);
9252
9253 nghttp2_stream_attach_item(c, dc);
9254
9255 assert_true(a->queued);
9256 assert_true(b->queued);
9257 assert_true(c->queued);
9258 assert_true(!d->queued);
9259
9260 assert_size(2, ==, nghttp2_pq_size(&a->obq));
9261
9262 /* Attach item to a */
9263 da = create_data_ob_item(mem);
9264
9265 nghttp2_stream_attach_item(a, da);
9266
9267 assert_true(a->queued);
9268 assert_true(b->queued);
9269 assert_true(c->queued);
9270 assert_true(!d->queued);
9271
9272 assert_size(2, ==, nghttp2_pq_size(&a->obq));
9273
9274 /* Detach item from a */
9275 nghttp2_stream_detach_item(a);
9276
9277 assert_true(a->queued);
9278 assert_true(b->queued);
9279 assert_true(c->queued);
9280 assert_true(!d->queued);
9281
9282 assert_size(2, ==, nghttp2_pq_size(&a->obq));
9283
9284 /* Attach item to d */
9285 dd = create_data_ob_item(mem);
9286
9287 nghttp2_stream_attach_item(d, dd);
9288
9289 assert_true(a->queued);
9290 assert_true(b->queued);
9291 assert_true(c->queued);
9292 assert_true(d->queued);
9293
9294 assert_size(2, ==, nghttp2_pq_size(&a->obq));
9295 assert_size(1, ==, nghttp2_pq_size(&c->obq));
9296
9297 /* Detach item from c */
9298 nghttp2_stream_detach_item(c);
9299
9300 assert_true(a->queued);
9301 assert_true(b->queued);
9302 assert_true(c->queued);
9303 assert_true(d->queued);
9304
9305 assert_size(2, ==, nghttp2_pq_size(&a->obq));
9306 assert_size(1, ==, nghttp2_pq_size(&c->obq));
9307
9308 /* Detach item from b */
9309 nghttp2_stream_detach_item(b);
9310
9311 assert_true(a->queued);
9312 assert_true(!b->queued);
9313 assert_true(c->queued);
9314 assert_true(d->queued);
9315
9316 assert_size(1, ==, nghttp2_pq_size(&a->obq));
9317
9318 /* exercises insertion */
9319 e = open_stream_with_dep_excl(session, 9, a);
9320
9321 /* a
9322 * |
9323 * e
9324 * |
9325 * c--b
9326 * |
9327 * d
9328 */
9329
9330 assert_true(a->queued);
9331 assert_true(e->queued);
9332 assert_true(!b->queued);
9333 assert_true(c->queued);
9334 assert_true(d->queued);
9335
9336 assert_size(1, ==, nghttp2_pq_size(&a->obq));
9337 assert_size(1, ==, nghttp2_pq_size(&e->obq));
9338 assert_true(nghttp2_pq_empty(&b->obq));
9339 assert_size(1, ==, nghttp2_pq_size(&c->obq));
9340 assert_true(nghttp2_pq_empty(&d->obq));
9341
9342 /* exercises deletion */
9343 nghttp2_stream_dep_remove(e);
9344
9345 /* a
9346 * |
9347 * c--b
9348 * |
9349 * d
9350 */
9351
9352 assert_true(a->queued);
9353 assert_true(!b->queued);
9354 assert_true(c->queued);
9355 assert_true(d->queued);
9356
9357 assert_size(1, ==, nghttp2_pq_size(&a->obq));
9358 assert_true(nghttp2_pq_empty(&b->obq));
9359 assert_size(1, ==, nghttp2_pq_size(&c->obq));
9360 assert_true(nghttp2_pq_empty(&d->obq));
9361
9362 /* e's weight 16 is distributed equally among c and b, both now have
9363 weight 8 each. */
9364 assert_int32(8, ==, b->weight);
9365 assert_int32(8, ==, c->weight);
9366
9367 /* da, db, dc have been detached */
9368 nghttp2_outbound_item_free(da, mem);
9369 nghttp2_outbound_item_free(db, mem);
9370 nghttp2_outbound_item_free(dc, mem);
9371 free(da);
9372 free(db);
9373 free(dc);
9374
9375 nghttp2_session_del(session);
9376
9377 nghttp2_session_server_new(&session, &callbacks, NULL);
9378
9379 a = open_stream(session, 1);
9380 b = open_stream_with_dep(session, 3, a);
9381 c = open_stream_with_dep(session, 5, a);
9382 d = open_stream_with_dep(session, 7, c);
9383
9384 /* a
9385 * |
9386 * c--b
9387 * |
9388 * d
9389 */
9390
9391 da = create_data_ob_item(mem);
9392 db = create_data_ob_item(mem);
9393 dc = create_data_ob_item(mem);
9394
9395 nghttp2_stream_attach_item(a, da);
9396 nghttp2_stream_attach_item(b, db);
9397 nghttp2_stream_attach_item(c, dc);
9398
9399 assert_true(a->queued);
9400 assert_true(b->queued);
9401 assert_true(c->queued);
9402 assert_true(!d->queued);
9403
9404 assert_size(2, ==, nghttp2_pq_size(&a->obq));
9405 assert_true(nghttp2_pq_empty(&b->obq));
9406 assert_true(nghttp2_pq_empty(&c->obq));
9407 assert_true(nghttp2_pq_empty(&d->obq));
9408
9409 /* Detach item from a */
9410 nghttp2_stream_detach_item(a);
9411
9412 assert_true(a->queued);
9413 assert_true(b->queued);
9414 assert_true(c->queued);
9415 assert_true(!d->queued);
9416
9417 assert_size(2, ==, nghttp2_pq_size(&a->obq));
9418 assert_true(nghttp2_pq_empty(&b->obq));
9419 assert_true(nghttp2_pq_empty(&c->obq));
9420 assert_true(nghttp2_pq_empty(&d->obq));
9421
9422 /* da has been detached */
9423 nghttp2_outbound_item_free(da, mem);
9424 free(da);
9425
9426 nghttp2_session_del(session);
9427 }
9428
test_nghttp2_session_stream_attach_item_subtree(void)9429 void test_nghttp2_session_stream_attach_item_subtree(void) {
9430 nghttp2_session *session;
9431 nghttp2_session_callbacks callbacks;
9432 nghttp2_stream *a, *b, *c, *d, *e, *f;
9433 nghttp2_outbound_item *da, *db, *dd, *de;
9434 nghttp2_mem *mem;
9435
9436 mem = nghttp2_mem_default();
9437
9438 memset(&callbacks, 0, sizeof(callbacks));
9439
9440 nghttp2_session_server_new(&session, &callbacks, NULL);
9441
9442 a = open_stream(session, 1);
9443 b = open_stream_with_dep(session, 3, a);
9444 c = open_stream_with_dep(session, 5, a);
9445 d = open_stream_with_dep(session, 7, c);
9446
9447 e = open_stream_with_dep_weight(session, 9, 32, &session->root);
9448 f = open_stream_with_dep(session, 11, e);
9449
9450 /*
9451 * a e
9452 * | |
9453 * c--b f
9454 * |
9455 * d
9456 */
9457
9458 de = create_data_ob_item(mem);
9459
9460 nghttp2_stream_attach_item(e, de);
9461
9462 db = create_data_ob_item(mem);
9463
9464 nghttp2_stream_attach_item(b, db);
9465
9466 assert_true(a->queued);
9467 assert_true(b->queued);
9468 assert_true(!c->queued);
9469 assert_true(!d->queued);
9470 assert_true(e->queued);
9471 assert_true(!f->queued);
9472
9473 assert_size(1, ==, nghttp2_pq_size(&a->obq));
9474 assert_true(nghttp2_pq_empty(&b->obq));
9475 assert_true(nghttp2_pq_empty(&c->obq));
9476 assert_true(nghttp2_pq_empty(&d->obq));
9477 assert_true(nghttp2_pq_empty(&e->obq));
9478 assert_true(nghttp2_pq_empty(&f->obq));
9479
9480 /* Insert subtree e under a */
9481
9482 nghttp2_stream_dep_remove_subtree(e);
9483 nghttp2_stream_dep_insert_subtree(a, e);
9484
9485 /*
9486 * a
9487 * |
9488 * e
9489 * |
9490 * f--c--b
9491 * |
9492 * d
9493 */
9494
9495 assert_true(a->queued);
9496 assert_true(b->queued);
9497 assert_true(!c->queued);
9498 assert_true(!d->queued);
9499 assert_true(e->queued);
9500 assert_true(!f->queued);
9501
9502 assert_size(1, ==, nghttp2_pq_size(&a->obq));
9503 assert_true(nghttp2_pq_empty(&b->obq));
9504 assert_true(nghttp2_pq_empty(&c->obq));
9505 assert_true(nghttp2_pq_empty(&d->obq));
9506 assert_size(1, ==, nghttp2_pq_size(&e->obq));
9507 assert_true(nghttp2_pq_empty(&f->obq));
9508
9509 /* Remove subtree b */
9510
9511 nghttp2_stream_dep_remove_subtree(b);
9512
9513 assert_int(0, ==, nghttp2_stream_dep_add_subtree(&session->root, b));
9514
9515 /*
9516 * a b
9517 * |
9518 * e
9519 * |
9520 * f--c
9521 * |
9522 * d
9523 */
9524
9525 assert_true(a->queued);
9526 assert_true(b->queued);
9527 assert_true(!c->queued);
9528 assert_true(!d->queued);
9529 assert_true(e->queued);
9530 assert_true(!f->queued);
9531
9532 assert_size(1, ==, nghttp2_pq_size(&a->obq));
9533 assert_true(nghttp2_pq_empty(&b->obq));
9534 assert_true(nghttp2_pq_empty(&c->obq));
9535 assert_true(nghttp2_pq_empty(&d->obq));
9536 assert_true(nghttp2_pq_empty(&e->obq));
9537 assert_true(nghttp2_pq_empty(&f->obq));
9538
9539 /* Remove subtree a, and add it to root again */
9540
9541 nghttp2_stream_dep_remove_subtree(a);
9542
9543 assert_int(0, ==, nghttp2_stream_dep_add_subtree(&session->root, a));
9544
9545 assert_true(a->queued);
9546 assert_true(b->queued);
9547 assert_true(!c->queued);
9548 assert_true(!d->queued);
9549 assert_true(e->queued);
9550 assert_true(!f->queued);
9551
9552 assert_size(1, ==, nghttp2_pq_size(&a->obq));
9553 assert_true(nghttp2_pq_empty(&b->obq));
9554 assert_true(nghttp2_pq_empty(&c->obq));
9555 assert_true(nghttp2_pq_empty(&d->obq));
9556 assert_true(nghttp2_pq_empty(&e->obq));
9557 assert_true(nghttp2_pq_empty(&f->obq));
9558
9559 /* Remove subtree c */
9560
9561 nghttp2_stream_dep_remove_subtree(c);
9562
9563 assert_int(0, ==, nghttp2_stream_dep_add_subtree(&session->root, c));
9564
9565 /*
9566 * a b c
9567 * | |
9568 * e d
9569 * |
9570 * f
9571 */
9572
9573 assert_true(a->queued);
9574 assert_true(b->queued);
9575 assert_true(!c->queued);
9576 assert_true(!d->queued);
9577 assert_true(e->queued);
9578 assert_true(!f->queued);
9579
9580 assert_size(1, ==, nghttp2_pq_size(&a->obq));
9581 assert_true(nghttp2_pq_empty(&b->obq));
9582 assert_true(nghttp2_pq_empty(&c->obq));
9583 assert_true(nghttp2_pq_empty(&d->obq));
9584 assert_true(nghttp2_pq_empty(&e->obq));
9585 assert_true(nghttp2_pq_empty(&f->obq));
9586
9587 dd = create_data_ob_item(mem);
9588
9589 nghttp2_stream_attach_item(d, dd);
9590
9591 /* Add subtree c to a */
9592
9593 nghttp2_stream_dep_remove_subtree(c);
9594 nghttp2_stream_dep_add_subtree(a, c);
9595
9596 /*
9597 * a b
9598 * |
9599 * c--e
9600 * | |
9601 * d f
9602 */
9603
9604 assert_true(a->queued);
9605 assert_true(b->queued);
9606 assert_true(c->queued);
9607 assert_true(d->queued);
9608 assert_true(e->queued);
9609 assert_true(!f->queued);
9610
9611 assert_size(2, ==, nghttp2_pq_size(&a->obq));
9612 assert_true(nghttp2_pq_empty(&b->obq));
9613 assert_size(1, ==, nghttp2_pq_size(&c->obq));
9614 assert_true(nghttp2_pq_empty(&d->obq));
9615 assert_true(nghttp2_pq_empty(&e->obq));
9616 assert_true(nghttp2_pq_empty(&f->obq));
9617
9618 /* Insert b under a */
9619
9620 nghttp2_stream_dep_remove_subtree(b);
9621 nghttp2_stream_dep_insert_subtree(a, b);
9622
9623 /*
9624 * a
9625 * |
9626 * b
9627 * |
9628 * c--e
9629 * | |
9630 * d f
9631 */
9632
9633 assert_true(a->queued);
9634 assert_true(b->queued);
9635 assert_true(c->queued);
9636 assert_true(d->queued);
9637 assert_true(e->queued);
9638 assert_true(!f->queued);
9639
9640 assert_size(1, ==, nghttp2_pq_size(&a->obq));
9641 assert_size(2, ==, nghttp2_pq_size(&b->obq));
9642 assert_size(1, ==, nghttp2_pq_size(&c->obq));
9643 assert_true(nghttp2_pq_empty(&d->obq));
9644 assert_true(nghttp2_pq_empty(&e->obq));
9645 assert_true(nghttp2_pq_empty(&f->obq));
9646
9647 /* Remove subtree b */
9648
9649 nghttp2_stream_dep_remove_subtree(b);
9650 assert_int(0, ==, nghttp2_stream_dep_add_subtree(&session->root, b));
9651
9652 /*
9653 * b a
9654 * |
9655 * e--c
9656 * | |
9657 * f d
9658 */
9659
9660 assert_true(!a->queued);
9661 assert_true(b->queued);
9662 assert_true(c->queued);
9663 assert_true(d->queued);
9664 assert_true(e->queued);
9665 assert_true(!f->queued);
9666
9667 assert_true(nghttp2_pq_empty(&a->obq));
9668 assert_size(2, ==, nghttp2_pq_size(&b->obq));
9669 assert_size(1, ==, nghttp2_pq_size(&c->obq));
9670 assert_true(nghttp2_pq_empty(&d->obq));
9671 assert_true(nghttp2_pq_empty(&e->obq));
9672 assert_true(nghttp2_pq_empty(&f->obq));
9673
9674 /* Remove subtree c, and detach item from b, and then re-add
9675 subtree c under b */
9676
9677 nghttp2_stream_dep_remove_subtree(c);
9678 nghttp2_stream_detach_item(b);
9679 nghttp2_stream_dep_add_subtree(b, c);
9680
9681 /*
9682 * b a
9683 * |
9684 * e--c
9685 * | |
9686 * f d
9687 */
9688
9689 assert_true(!a->queued);
9690 assert_true(b->queued);
9691 assert_true(c->queued);
9692 assert_true(d->queued);
9693 assert_true(e->queued);
9694 assert_true(!f->queued);
9695
9696 assert_true(nghttp2_pq_empty(&a->obq));
9697 assert_size(2, ==, nghttp2_pq_size(&b->obq));
9698 assert_size(1, ==, nghttp2_pq_size(&c->obq));
9699 assert_true(nghttp2_pq_empty(&d->obq));
9700 assert_true(nghttp2_pq_empty(&e->obq));
9701 assert_true(nghttp2_pq_empty(&f->obq));
9702
9703 /* Attach data to a, and add subtree a under b */
9704
9705 da = create_data_ob_item(mem);
9706 nghttp2_stream_attach_item(a, da);
9707 nghttp2_stream_dep_remove_subtree(a);
9708 nghttp2_stream_dep_add_subtree(b, a);
9709
9710 /*
9711 * b
9712 * |
9713 * a--e--c
9714 * | |
9715 * f d
9716 */
9717
9718 assert_true(a->queued);
9719 assert_true(b->queued);
9720 assert_true(c->queued);
9721 assert_true(d->queued);
9722 assert_true(e->queued);
9723 assert_true(!f->queued);
9724
9725 assert_true(nghttp2_pq_empty(&a->obq));
9726 assert_size(3, ==, nghttp2_pq_size(&b->obq));
9727 assert_size(1, ==, nghttp2_pq_size(&c->obq));
9728 assert_true(nghttp2_pq_empty(&d->obq));
9729 assert_true(nghttp2_pq_empty(&e->obq));
9730 assert_true(nghttp2_pq_empty(&f->obq));
9731
9732 /* Remove subtree c, and add under f */
9733 nghttp2_stream_dep_remove_subtree(c);
9734 nghttp2_stream_dep_insert_subtree(f, c);
9735
9736 /*
9737 * b
9738 * |
9739 * a--e
9740 * |
9741 * f
9742 * |
9743 * c
9744 * |
9745 * d
9746 */
9747
9748 assert_true(a->queued);
9749 assert_true(b->queued);
9750 assert_true(c->queued);
9751 assert_true(d->queued);
9752 assert_true(e->queued);
9753 assert_true(f->queued);
9754
9755 assert_true(nghttp2_pq_empty(&a->obq));
9756 assert_size(2, ==, nghttp2_pq_size(&b->obq));
9757 assert_size(1, ==, nghttp2_pq_size(&c->obq));
9758 assert_true(nghttp2_pq_empty(&d->obq));
9759 assert_size(1, ==, nghttp2_pq_size(&e->obq));
9760 assert_size(1, ==, nghttp2_pq_size(&f->obq));
9761
9762 /* db has been detached */
9763 nghttp2_outbound_item_free(db, mem);
9764 free(db);
9765
9766 nghttp2_session_del(session);
9767 }
9768
test_nghttp2_session_stream_get_state(void)9769 void test_nghttp2_session_stream_get_state(void) {
9770 nghttp2_session *session;
9771 nghttp2_session_callbacks callbacks;
9772 nghttp2_mem *mem;
9773 nghttp2_hd_deflater deflater;
9774 nghttp2_bufs bufs;
9775 nghttp2_buf *buf;
9776 nghttp2_stream *stream;
9777 nghttp2_ssize rv;
9778 nghttp2_data_provider2 data_prd;
9779 nghttp2_frame frame;
9780
9781 mem = nghttp2_mem_default();
9782 frame_pack_bufs_init(&bufs);
9783 memset(&data_prd, 0, sizeof(data_prd));
9784
9785 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
9786 callbacks.send_callback2 = null_send_callback;
9787
9788 nghttp2_session_server_new(&session, &callbacks, NULL);
9789 nghttp2_hd_deflate_init(&deflater, mem);
9790
9791 assert_enum(
9792 nghttp2_stream_proto_state, NGHTTP2_STREAM_STATE_IDLE, ==,
9793 nghttp2_stream_get_state(nghttp2_session_get_root_stream(session)));
9794
9795 /* stream 1 HEADERS; without END_STREAM flag set */
9796 pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, reqnv,
9797 ARRLEN(reqnv), mem);
9798
9799 buf = &bufs.head->buf;
9800 rv = nghttp2_session_mem_recv2(session, buf->pos, nghttp2_buf_len(buf));
9801
9802 assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(buf), ==, rv);
9803
9804 stream = nghttp2_session_find_stream(session, 1);
9805
9806 assert_not_null(stream);
9807 assert_int32(1, ==, stream->stream_id);
9808 assert_enum(nghttp2_stream_proto_state, NGHTTP2_STREAM_STATE_OPEN, ==,
9809 nghttp2_stream_get_state(stream));
9810
9811 nghttp2_bufs_reset(&bufs);
9812
9813 /* stream 3 HEADERS; with END_STREAM flag set */
9814 pack_headers(&bufs, &deflater, 3,
9815 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM, reqnv,
9816 ARRLEN(reqnv), mem);
9817
9818 buf = &bufs.head->buf;
9819 rv = nghttp2_session_mem_recv2(session, buf->pos, nghttp2_buf_len(buf));
9820
9821 assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(buf), ==, rv);
9822
9823 stream = nghttp2_session_find_stream(session, 3);
9824
9825 assert_not_null(stream);
9826 assert_int32(3, ==, stream->stream_id);
9827 assert_enum(nghttp2_stream_proto_state,
9828 NGHTTP2_STREAM_STATE_HALF_CLOSED_REMOTE, ==,
9829 nghttp2_stream_get_state(stream));
9830
9831 nghttp2_bufs_reset(&bufs);
9832
9833 /* Respond to stream 1 */
9834 nghttp2_submit_response2(session, 1, resnv, ARRLEN(resnv), NULL);
9835
9836 rv = nghttp2_session_send(session);
9837
9838 assert_ptrdiff(0, ==, rv);
9839
9840 stream = nghttp2_session_find_stream(session, 1);
9841
9842 assert_enum(nghttp2_stream_proto_state,
9843 NGHTTP2_STREAM_STATE_HALF_CLOSED_LOCAL, ==,
9844 nghttp2_stream_get_state(stream));
9845
9846 /* Respond to stream 3 */
9847 nghttp2_submit_response2(session, 3, resnv, ARRLEN(resnv), NULL);
9848
9849 rv = nghttp2_session_send(session);
9850
9851 assert_ptrdiff(0, ==, rv);
9852
9853 stream = nghttp2_session_find_stream(session, 3);
9854
9855 assert_enum(nghttp2_stream_proto_state, NGHTTP2_STREAM_STATE_CLOSED, ==,
9856 nghttp2_stream_get_state(stream));
9857
9858 /* stream 5 HEADERS; with END_STREAM flag set */
9859 pack_headers(&bufs, &deflater, 5,
9860 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM, reqnv,
9861 ARRLEN(reqnv), mem);
9862
9863 buf = &bufs.head->buf;
9864 rv = nghttp2_session_mem_recv2(session, buf->pos, nghttp2_buf_len(buf));
9865
9866 assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(buf), ==, rv);
9867
9868 nghttp2_bufs_reset(&bufs);
9869
9870 /* Push stream 2 associated to stream 5 */
9871 rv = nghttp2_submit_push_promise(session, NGHTTP2_FLAG_NONE, 5, reqnv,
9872 ARRLEN(reqnv), NULL);
9873
9874 assert_ptrdiff(2, ==, rv);
9875
9876 rv = nghttp2_session_send(session);
9877
9878 assert_ptrdiff(0, ==, rv);
9879
9880 stream = nghttp2_session_find_stream(session, 2);
9881
9882 assert_enum(nghttp2_stream_proto_state, NGHTTP2_STREAM_STATE_RESERVED_LOCAL,
9883 ==, nghttp2_stream_get_state(stream));
9884
9885 /* Send response to push stream 2 with END_STREAM set */
9886 nghttp2_submit_response2(session, 2, resnv, ARRLEN(resnv), NULL);
9887
9888 rv = nghttp2_session_send(session);
9889
9890 assert_ptrdiff(0, ==, rv);
9891
9892 stream = nghttp2_session_find_stream(session, 2);
9893
9894 /* At server, pushed stream object is not retained after closed */
9895 assert_null(stream);
9896
9897 /* Push stream 4 associated to stream 5 */
9898 rv = nghttp2_submit_push_promise(session, NGHTTP2_FLAG_NONE, 5, reqnv,
9899 ARRLEN(reqnv), NULL);
9900
9901 assert_ptrdiff(4, ==, rv);
9902
9903 rv = nghttp2_session_send(session);
9904
9905 assert_ptrdiff(0, ==, rv);
9906
9907 stream = nghttp2_session_find_stream(session, 4);
9908
9909 assert_enum(nghttp2_stream_proto_state, NGHTTP2_STREAM_STATE_RESERVED_LOCAL,
9910 ==, nghttp2_stream_get_state(stream));
9911
9912 /* Send response to push stream 4 without closing */
9913 data_prd.read_callback = defer_data_source_read_callback;
9914
9915 nghttp2_submit_response2(session, 4, resnv, ARRLEN(resnv), &data_prd);
9916
9917 rv = nghttp2_session_send(session);
9918
9919 assert_ptrdiff(0, ==, rv);
9920
9921 stream = nghttp2_session_find_stream(session, 4);
9922
9923 assert_enum(nghttp2_stream_proto_state,
9924 NGHTTP2_STREAM_STATE_HALF_CLOSED_REMOTE, ==,
9925 nghttp2_stream_get_state(stream));
9926
9927 /* Create idle stream by PRIORITY frame */
9928 nghttp2_frame_priority_init(&frame.priority, 7, &pri_spec_default);
9929
9930 nghttp2_frame_pack_priority(&bufs, &frame.priority);
9931
9932 nghttp2_frame_priority_free(&frame.priority);
9933
9934 buf = &bufs.head->buf;
9935 rv = nghttp2_session_mem_recv2(session, buf->pos, nghttp2_buf_len(buf));
9936
9937 assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(buf), ==, rv);
9938
9939 stream = nghttp2_session_find_stream(session, 7);
9940
9941 assert_enum(nghttp2_stream_proto_state, NGHTTP2_STREAM_STATE_IDLE, ==,
9942 nghttp2_stream_get_state(stream));
9943
9944 nghttp2_bufs_reset(&bufs);
9945
9946 nghttp2_hd_deflate_free(&deflater);
9947 nghttp2_session_del(session);
9948
9949 /* Test for client side */
9950
9951 nghttp2_session_client_new(&session, &callbacks, NULL);
9952 nghttp2_hd_deflate_init(&deflater, mem);
9953
9954 nghttp2_submit_request2(session, NULL, reqnv, ARRLEN(reqnv), NULL, NULL);
9955
9956 rv = nghttp2_session_send(session);
9957
9958 assert_ptrdiff(0, ==, rv);
9959
9960 /* Receive PUSH_PROMISE 2 associated to stream 1 */
9961 pack_push_promise(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, 2, reqnv,
9962 ARRLEN(reqnv), mem);
9963
9964 buf = &bufs.head->buf;
9965 rv = nghttp2_session_mem_recv2(session, buf->pos, nghttp2_buf_len(buf));
9966
9967 assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(buf), ==, rv);
9968
9969 stream = nghttp2_session_find_stream(session, 2);
9970
9971 assert_enum(nghttp2_stream_proto_state, NGHTTP2_STREAM_STATE_RESERVED_REMOTE,
9972 ==, nghttp2_stream_get_state(stream));
9973
9974 nghttp2_bufs_reset(&bufs);
9975
9976 /* Receive push response for stream 2 without END_STREAM set */
9977 pack_headers(&bufs, &deflater, 2, NGHTTP2_FLAG_END_HEADERS, resnv,
9978 ARRLEN(resnv), mem);
9979
9980 buf = &bufs.head->buf;
9981 rv = nghttp2_session_mem_recv2(session, buf->pos, nghttp2_buf_len(buf));
9982
9983 assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(buf), ==, rv);
9984
9985 stream = nghttp2_session_find_stream(session, 2);
9986
9987 assert_enum(nghttp2_stream_proto_state,
9988 NGHTTP2_STREAM_STATE_HALF_CLOSED_LOCAL, ==,
9989 nghttp2_stream_get_state(stream));
9990
9991 nghttp2_bufs_reset(&bufs);
9992
9993 nghttp2_hd_deflate_free(&deflater);
9994 nghttp2_session_del(session);
9995
9996 nghttp2_bufs_free(&bufs);
9997 }
9998
test_nghttp2_session_stream_get_something(void)9999 void test_nghttp2_session_stream_get_something(void) {
10000 nghttp2_session *session;
10001 nghttp2_session_callbacks callbacks;
10002 nghttp2_stream *a, *b, *c;
10003
10004 memset(&callbacks, 0, sizeof(callbacks));
10005
10006 nghttp2_session_server_new(&session, &callbacks, NULL);
10007
10008 a = open_stream(session, 1);
10009
10010 assert_ptr_equal(nghttp2_session_get_root_stream(session),
10011 nghttp2_stream_get_parent(a));
10012 assert_null(nghttp2_stream_get_previous_sibling(a));
10013 assert_null(nghttp2_stream_get_next_sibling(a));
10014 assert_null(nghttp2_stream_get_first_child(a));
10015
10016 b = open_stream_with_dep(session, 3, a);
10017 c = open_stream_with_dep_weight(session, 5, 11, a);
10018
10019 assert_ptr_equal(a, nghttp2_stream_get_parent(c));
10020 assert_ptr_equal(a, nghttp2_stream_get_parent(b));
10021
10022 assert_ptr_equal(c, nghttp2_stream_get_first_child(a));
10023
10024 assert_ptr_equal(b, nghttp2_stream_get_next_sibling(c));
10025 assert_ptr_equal(c, nghttp2_stream_get_previous_sibling(b));
10026
10027 assert_int32(27, ==, nghttp2_stream_get_sum_dependency_weight(a));
10028
10029 assert_int32(11, ==, nghttp2_stream_get_weight(c));
10030 assert_int32(5, ==, nghttp2_stream_get_stream_id(c));
10031 assert_int32(0, ==, nghttp2_stream_get_stream_id(&session->root));
10032
10033 nghttp2_session_del(session);
10034 }
10035
test_nghttp2_session_find_stream(void)10036 void test_nghttp2_session_find_stream(void) {
10037 nghttp2_session *session;
10038 nghttp2_session_callbacks callbacks;
10039 nghttp2_stream *stream;
10040
10041 memset(&callbacks, 0, sizeof(callbacks));
10042
10043 nghttp2_session_server_new(&session, &callbacks, NULL);
10044
10045 open_recv_stream(session, 1);
10046
10047 stream = nghttp2_session_find_stream(session, 1);
10048
10049 assert_not_null(stream);
10050 assert_int32(1, ==, stream->stream_id);
10051
10052 stream = nghttp2_session_find_stream(session, 0);
10053
10054 assert_ptr_equal(&session->root, stream);
10055 assert_int32(0, ==, stream->stream_id);
10056
10057 stream = nghttp2_session_find_stream(session, 2);
10058
10059 assert_null(stream);
10060
10061 nghttp2_session_del(session);
10062 }
10063
test_nghttp2_session_keep_closed_stream(void)10064 void test_nghttp2_session_keep_closed_stream(void) {
10065 nghttp2_session *session;
10066 nghttp2_session_callbacks callbacks;
10067 const size_t max_concurrent_streams = 5;
10068 nghttp2_settings_entry iv = {NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS,
10069 (uint32_t)max_concurrent_streams};
10070 size_t i;
10071
10072 memset(&callbacks, 0, sizeof(callbacks));
10073 callbacks.send_callback2 = null_send_callback;
10074
10075 nghttp2_session_server_new(&session, &callbacks, NULL);
10076
10077 nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, &iv, 1);
10078
10079 for (i = 0; i < max_concurrent_streams; ++i) {
10080 open_recv_stream(session, (int32_t)i * 2 + 1);
10081 }
10082
10083 assert_size(0, ==, session->num_closed_streams);
10084
10085 nghttp2_session_close_stream(session, 1, NGHTTP2_NO_ERROR);
10086
10087 assert_size(1, ==, session->num_closed_streams);
10088 assert_int32(1, ==, session->closed_stream_tail->stream_id);
10089 assert_ptr_equal(session->closed_stream_tail, session->closed_stream_head);
10090
10091 nghttp2_session_close_stream(session, 5, NGHTTP2_NO_ERROR);
10092
10093 assert_size(2, ==, session->num_closed_streams);
10094 assert_int32(5, ==, session->closed_stream_tail->stream_id);
10095 assert_int32(1, ==, session->closed_stream_head->stream_id);
10096 assert_ptr_equal(session->closed_stream_head,
10097 session->closed_stream_tail->closed_prev);
10098 assert_null(session->closed_stream_tail->closed_next);
10099 assert_ptr_equal(session->closed_stream_tail,
10100 session->closed_stream_head->closed_next);
10101 assert_null(session->closed_stream_head->closed_prev);
10102
10103 open_recv_stream(session, 11);
10104 nghttp2_session_adjust_closed_stream(session);
10105
10106 assert_size(1, ==, session->num_closed_streams);
10107 assert_int32(5, ==, session->closed_stream_tail->stream_id);
10108 assert_ptr_equal(session->closed_stream_tail, session->closed_stream_head);
10109 assert_null(session->closed_stream_head->closed_prev);
10110 assert_null(session->closed_stream_head->closed_next);
10111
10112 open_recv_stream(session, 13);
10113 nghttp2_session_adjust_closed_stream(session);
10114
10115 assert_size(0, ==, session->num_closed_streams);
10116 assert_null(session->closed_stream_tail);
10117 assert_null(session->closed_stream_head);
10118
10119 nghttp2_session_close_stream(session, 3, NGHTTP2_NO_ERROR);
10120
10121 assert_size(1, ==, session->num_closed_streams);
10122 assert_int32(3, ==, session->closed_stream_head->stream_id);
10123
10124 /* server initiated stream is not counted to max concurrent limit */
10125 open_sent_stream(session, 2);
10126 nghttp2_session_adjust_closed_stream(session);
10127
10128 assert_size(1, ==, session->num_closed_streams);
10129 assert_int32(3, ==, session->closed_stream_head->stream_id);
10130
10131 nghttp2_session_close_stream(session, 2, NGHTTP2_NO_ERROR);
10132
10133 assert_size(1, ==, session->num_closed_streams);
10134 assert_int32(3, ==, session->closed_stream_head->stream_id);
10135
10136 nghttp2_session_del(session);
10137 }
10138
test_nghttp2_session_keep_idle_stream(void)10139 void test_nghttp2_session_keep_idle_stream(void) {
10140 nghttp2_session *session;
10141 nghttp2_session_callbacks callbacks;
10142 const size_t max_concurrent_streams = 1;
10143 nghttp2_settings_entry iv = {NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS,
10144 (uint32_t)max_concurrent_streams};
10145 int i;
10146 int32_t stream_id;
10147
10148 memset(&callbacks, 0, sizeof(callbacks));
10149 callbacks.send_callback2 = null_send_callback;
10150
10151 nghttp2_session_server_new(&session, &callbacks, NULL);
10152
10153 nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, &iv, 1);
10154
10155 /* We at least allow NGHTTP2_MIN_IDLE_STREAM idle streams even if
10156 max concurrent streams is very low. */
10157 for (i = 0; i < NGHTTP2_MIN_IDLE_STREAMS; ++i) {
10158 open_recv_stream2(session, i * 2 + 1, NGHTTP2_STREAM_IDLE);
10159 nghttp2_session_adjust_idle_stream(session);
10160 }
10161
10162 assert_size(NGHTTP2_MIN_IDLE_STREAMS, ==, session->num_idle_streams);
10163
10164 stream_id = (NGHTTP2_MIN_IDLE_STREAMS - 1) * 2 + 1;
10165 assert_int32(1, ==, session->idle_stream_head->stream_id);
10166 assert_int32(stream_id, ==, session->idle_stream_tail->stream_id);
10167
10168 stream_id += 2;
10169
10170 open_recv_stream2(session, stream_id, NGHTTP2_STREAM_IDLE);
10171 nghttp2_session_adjust_idle_stream(session);
10172
10173 assert_size(NGHTTP2_MIN_IDLE_STREAMS, ==, session->num_idle_streams);
10174 assert_int32(3, ==, session->idle_stream_head->stream_id);
10175 assert_int32(stream_id, ==, session->idle_stream_tail->stream_id);
10176
10177 nghttp2_session_del(session);
10178 }
10179
test_nghttp2_session_detach_idle_stream(void)10180 void test_nghttp2_session_detach_idle_stream(void) {
10181 nghttp2_session *session;
10182 nghttp2_session_callbacks callbacks;
10183 int i;
10184 nghttp2_stream *stream;
10185
10186 memset(&callbacks, 0, sizeof(callbacks));
10187 callbacks.send_callback2 = null_send_callback;
10188
10189 nghttp2_session_server_new(&session, &callbacks, NULL);
10190
10191 for (i = 1; i <= 3; ++i) {
10192 nghttp2_session_open_stream(session, i, NGHTTP2_STREAM_FLAG_NONE,
10193 &pri_spec_default, NGHTTP2_STREAM_IDLE, NULL);
10194 }
10195
10196 assert_size(3, ==, session->num_idle_streams);
10197
10198 /* Detach middle stream */
10199 stream = nghttp2_session_get_stream_raw(session, 2);
10200
10201 assert_ptr_equal(session->idle_stream_head, stream->closed_prev);
10202 assert_ptr_equal(session->idle_stream_tail, stream->closed_next);
10203 assert_ptr_equal(stream, session->idle_stream_head->closed_next);
10204 assert_ptr_equal(stream, session->idle_stream_tail->closed_prev);
10205
10206 nghttp2_session_detach_idle_stream(session, stream);
10207
10208 assert_size(2, ==, session->num_idle_streams);
10209
10210 assert_null(stream->closed_prev);
10211 assert_null(stream->closed_next);
10212
10213 assert_ptr_equal(session->idle_stream_head,
10214 session->idle_stream_tail->closed_prev);
10215 assert_ptr_equal(session->idle_stream_tail,
10216 session->idle_stream_head->closed_next);
10217
10218 /* Detach head stream */
10219 stream = session->idle_stream_head;
10220
10221 nghttp2_session_detach_idle_stream(session, stream);
10222
10223 assert_size(1, ==, session->num_idle_streams);
10224
10225 assert_ptr_equal(session->idle_stream_head, session->idle_stream_tail);
10226 assert_null(session->idle_stream_head->closed_prev);
10227 assert_null(session->idle_stream_head->closed_next);
10228
10229 /* Detach last stream */
10230
10231 stream = session->idle_stream_head;
10232
10233 nghttp2_session_detach_idle_stream(session, stream);
10234
10235 assert_size(0, ==, session->num_idle_streams);
10236
10237 assert_null(session->idle_stream_head);
10238 assert_null(session->idle_stream_tail);
10239
10240 for (i = 4; i <= 5; ++i) {
10241 nghttp2_session_open_stream(session, i, NGHTTP2_STREAM_FLAG_NONE,
10242 &pri_spec_default, NGHTTP2_STREAM_IDLE, NULL);
10243 }
10244
10245 assert_size(2, ==, session->num_idle_streams);
10246
10247 /* Detach tail stream */
10248
10249 stream = session->idle_stream_tail;
10250
10251 nghttp2_session_detach_idle_stream(session, stream);
10252
10253 assert_size(1, ==, session->num_idle_streams);
10254
10255 assert_ptr_equal(session->idle_stream_head, session->idle_stream_tail);
10256 assert_null(session->idle_stream_head->closed_prev);
10257 assert_null(session->idle_stream_head->closed_next);
10258
10259 nghttp2_session_del(session);
10260 }
10261
test_nghttp2_session_large_dep_tree(void)10262 void test_nghttp2_session_large_dep_tree(void) {
10263 nghttp2_session *session;
10264 nghttp2_session_callbacks callbacks;
10265 size_t i;
10266 nghttp2_stream *dep_stream = NULL;
10267 nghttp2_stream *stream;
10268 int32_t stream_id;
10269
10270 memset(&callbacks, 0, sizeof(callbacks));
10271 callbacks.send_callback2 = null_send_callback;
10272
10273 nghttp2_session_server_new(&session, &callbacks, NULL);
10274
10275 stream_id = 1;
10276 for (i = 0; i < 250; ++i, stream_id += 2) {
10277 dep_stream = open_stream_with_dep(session, stream_id, dep_stream);
10278 }
10279
10280 stream_id = 1;
10281 for (i = 0; i < 250; ++i, stream_id += 2) {
10282 stream = nghttp2_session_get_stream(session, stream_id);
10283 assert_true(nghttp2_stream_dep_find_ancestor(stream, &session->root));
10284 assert_true(nghttp2_stream_in_dep_tree(stream));
10285 }
10286
10287 nghttp2_session_del(session);
10288 }
10289
test_nghttp2_session_graceful_shutdown(void)10290 void test_nghttp2_session_graceful_shutdown(void) {
10291 nghttp2_session *session;
10292 nghttp2_session_callbacks callbacks;
10293 my_user_data ud;
10294
10295 memset(&callbacks, 0, sizeof(callbacks));
10296 callbacks.send_callback2 = null_send_callback;
10297 callbacks.on_frame_send_callback = on_frame_send_callback;
10298 callbacks.on_stream_close_callback = on_stream_close_callback;
10299
10300 nghttp2_session_server_new(&session, &callbacks, &ud);
10301
10302 open_recv_stream(session, 301);
10303 open_sent_stream(session, 302);
10304 open_recv_stream(session, 309);
10305 open_recv_stream(session, 311);
10306 open_recv_stream(session, 319);
10307
10308 assert_int(0, ==, nghttp2_submit_shutdown_notice(session));
10309
10310 ud.frame_send_cb_called = 0;
10311
10312 assert_int(0, ==, nghttp2_session_send(session));
10313
10314 assert_int(1, ==, ud.frame_send_cb_called);
10315 assert_int32((1u << 31) - 1, ==, session->local_last_stream_id);
10316
10317 assert_int(0, ==,
10318 nghttp2_submit_goaway(session, NGHTTP2_FLAG_NONE, 311,
10319 NGHTTP2_NO_ERROR, NULL, 0));
10320
10321 ud.frame_send_cb_called = 0;
10322 ud.stream_close_cb_called = 0;
10323
10324 assert_int(0, ==, nghttp2_session_send(session));
10325
10326 assert_int(1, ==, ud.frame_send_cb_called);
10327 assert_int32(311, ==, session->local_last_stream_id);
10328 assert_int(1, ==, ud.stream_close_cb_called);
10329
10330 assert_int(
10331 0, ==, nghttp2_session_terminate_session2(session, 301, NGHTTP2_NO_ERROR));
10332
10333 ud.frame_send_cb_called = 0;
10334 ud.stream_close_cb_called = 0;
10335
10336 assert_int(0, ==, nghttp2_session_send(session));
10337
10338 assert_int(1, ==, ud.frame_send_cb_called);
10339 assert_int32(301, ==, session->local_last_stream_id);
10340 assert_int(2, ==, ud.stream_close_cb_called);
10341
10342 assert_not_null(nghttp2_session_get_stream(session, 301));
10343 assert_not_null(nghttp2_session_get_stream(session, 302));
10344 assert_null(nghttp2_session_get_stream(session, 309));
10345 assert_null(nghttp2_session_get_stream(session, 311));
10346 assert_null(nghttp2_session_get_stream(session, 319));
10347
10348 nghttp2_session_del(session);
10349 }
10350
test_nghttp2_session_on_header_temporal_failure(void)10351 void test_nghttp2_session_on_header_temporal_failure(void) {
10352 nghttp2_session *session;
10353 nghttp2_session_callbacks callbacks;
10354 my_user_data ud;
10355 nghttp2_bufs bufs;
10356 nghttp2_buf *buf;
10357 nghttp2_hd_deflater deflater;
10358 nghttp2_nv nv[] = {MAKE_NV("alpha", "bravo"), MAKE_NV("charlie", "delta")};
10359 nghttp2_nv *nva;
10360 size_t hdpos;
10361 nghttp2_ssize rv;
10362 nghttp2_frame frame;
10363 nghttp2_frame_hd hd;
10364 nghttp2_outbound_item *item;
10365 nghttp2_mem *mem;
10366
10367 mem = nghttp2_mem_default();
10368 memset(&callbacks, 0, sizeof(callbacks));
10369 callbacks.on_header_callback = temporal_failure_on_header_callback;
10370
10371 nghttp2_session_server_new(&session, &callbacks, &ud);
10372
10373 frame_pack_bufs_init(&bufs);
10374
10375 nghttp2_hd_deflate_init(&deflater, mem);
10376
10377 nghttp2_nv_array_copy(&nva, reqnv, ARRLEN(reqnv), mem);
10378
10379 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_STREAM, 1,
10380 NGHTTP2_HCAT_REQUEST, NULL, nva, ARRLEN(reqnv));
10381 nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
10382 nghttp2_frame_headers_free(&frame.headers, mem);
10383
10384 /* We are going to create CONTINUATION. First serialize header
10385 block, and then frame header. */
10386 hdpos = nghttp2_bufs_len(&bufs);
10387
10388 buf = &bufs.head->buf;
10389 buf->last += NGHTTP2_FRAME_HDLEN;
10390
10391 nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, &nv[1], 1);
10392
10393 nghttp2_frame_hd_init(&hd,
10394 nghttp2_bufs_len(&bufs) - hdpos - NGHTTP2_FRAME_HDLEN,
10395 NGHTTP2_CONTINUATION, NGHTTP2_FLAG_END_HEADERS, 1);
10396
10397 nghttp2_frame_pack_frame_hd(&buf->pos[hdpos], &hd);
10398
10399 ud.header_cb_called = 0;
10400 rv = nghttp2_session_mem_recv2(session, buf->pos, nghttp2_bufs_len(&bufs));
10401
10402 assert_ptrdiff((nghttp2_ssize)nghttp2_bufs_len(&bufs), ==, rv);
10403 assert_int(1, ==, ud.header_cb_called);
10404
10405 item = nghttp2_session_get_next_ob_item(session);
10406
10407 assert_uint8(NGHTTP2_RST_STREAM, ==, item->frame.hd.type);
10408 assert_int32(1, ==, item->frame.hd.stream_id);
10409
10410 /* Make sure no header decompression error occurred */
10411 assert_uint8(NGHTTP2_GOAWAY_NONE, ==, session->goaway_flags);
10412
10413 nghttp2_hd_deflate_free(&deflater);
10414 nghttp2_session_del(session);
10415
10416 nghttp2_bufs_reset(&bufs);
10417
10418 /* Check for PUSH_PROMISE */
10419 nghttp2_hd_deflate_init(&deflater, mem);
10420 nghttp2_session_client_new(&session, &callbacks, &ud);
10421
10422 open_sent_stream(session, 1);
10423
10424 rv = pack_push_promise(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, 2,
10425 reqnv, ARRLEN(reqnv), mem);
10426 assert_ptrdiff(0, ==, rv);
10427
10428 ud.header_cb_called = 0;
10429 rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
10430 nghttp2_bufs_len(&bufs));
10431 assert_ptrdiff((nghttp2_ssize)nghttp2_bufs_len(&bufs), ==, rv);
10432 assert_int(1, ==, ud.header_cb_called);
10433
10434 item = nghttp2_session_get_next_ob_item(session);
10435 assert_uint8(NGHTTP2_RST_STREAM, ==, item->frame.hd.type);
10436 assert_int32(2, ==, item->frame.hd.stream_id);
10437 assert_uint32(NGHTTP2_INTERNAL_ERROR, ==, item->frame.rst_stream.error_code);
10438
10439 nghttp2_session_del(session);
10440 nghttp2_hd_deflate_free(&deflater);
10441 nghttp2_bufs_free(&bufs);
10442 }
10443
test_nghttp2_session_recv_client_magic(void)10444 void test_nghttp2_session_recv_client_magic(void) {
10445 nghttp2_session *session;
10446 nghttp2_session_callbacks callbacks;
10447 nghttp2_ssize rv;
10448 nghttp2_frame ping_frame;
10449 uint8_t buf[16];
10450
10451 /* enable global nghttp2_enable_strict_preface here */
10452 nghttp2_enable_strict_preface = 1;
10453
10454 memset(&callbacks, 0, sizeof(callbacks));
10455
10456 /* Check success case */
10457 nghttp2_session_server_new(&session, &callbacks, NULL);
10458
10459 rv = nghttp2_session_mem_recv2(session, (const uint8_t *)NGHTTP2_CLIENT_MAGIC,
10460 NGHTTP2_CLIENT_MAGIC_LEN);
10461
10462 assert_ptrdiff(NGHTTP2_CLIENT_MAGIC_LEN, ==, rv);
10463 assert_enum(nghttp2_inbound_state, NGHTTP2_IB_READ_FIRST_SETTINGS, ==,
10464 session->iframe.state);
10465
10466 /* Receiving PING is error because we want SETTINGS. */
10467 nghttp2_frame_ping_init(&ping_frame.ping, NGHTTP2_FLAG_NONE, NULL);
10468
10469 nghttp2_frame_pack_frame_hd(buf, &ping_frame.ping.hd);
10470
10471 rv = nghttp2_session_mem_recv2(session, buf, NGHTTP2_FRAME_HDLEN);
10472 assert_ptrdiff(NGHTTP2_FRAME_HDLEN, ==, rv);
10473 assert_enum(nghttp2_inbound_state, NGHTTP2_IB_IGN_ALL, ==,
10474 session->iframe.state);
10475 assert_size(0, ==, session->iframe.payloadleft);
10476
10477 nghttp2_frame_ping_free(&ping_frame.ping);
10478
10479 nghttp2_session_del(session);
10480
10481 /* Check bad case */
10482 nghttp2_session_server_new(&session, &callbacks, NULL);
10483
10484 /* Feed magic with one byte less */
10485 rv = nghttp2_session_mem_recv2(session, (const uint8_t *)NGHTTP2_CLIENT_MAGIC,
10486 NGHTTP2_CLIENT_MAGIC_LEN - 1);
10487
10488 assert_ptrdiff(NGHTTP2_CLIENT_MAGIC_LEN - 1, ==, rv);
10489 assert_enum(nghttp2_inbound_state, NGHTTP2_IB_READ_CLIENT_MAGIC, ==,
10490 session->iframe.state);
10491 assert_size(1, ==, session->iframe.payloadleft);
10492
10493 rv = nghttp2_session_mem_recv2(session, (const uint8_t *)"\0", 1);
10494
10495 assert_ptrdiff(NGHTTP2_ERR_BAD_CLIENT_MAGIC, ==, rv);
10496
10497 nghttp2_session_del(session);
10498
10499 /* disable global nghttp2_enable_strict_preface here */
10500 nghttp2_enable_strict_preface = 0;
10501 }
10502
test_nghttp2_session_delete_data_item(void)10503 void test_nghttp2_session_delete_data_item(void) {
10504 nghttp2_session *session;
10505 nghttp2_session_callbacks callbacks;
10506 nghttp2_stream *a;
10507 nghttp2_data_provider2 prd;
10508
10509 memset(&callbacks, 0, sizeof(callbacks));
10510
10511 nghttp2_session_server_new(&session, &callbacks, NULL);
10512
10513 a = open_recv_stream(session, 1);
10514 open_recv_stream_with_dep(session, 3, a);
10515
10516 /* We don't care about these members, since we won't send data */
10517 prd.source.ptr = NULL;
10518 prd.read_callback = fail_data_source_read_callback;
10519
10520 assert_int(0, ==, nghttp2_submit_data2(session, NGHTTP2_FLAG_NONE, 1, &prd));
10521 assert_int(0, ==, nghttp2_submit_data2(session, NGHTTP2_FLAG_NONE, 3, &prd));
10522
10523 nghttp2_session_del(session);
10524 }
10525
test_nghttp2_session_open_idle_stream(void)10526 void test_nghttp2_session_open_idle_stream(void) {
10527 nghttp2_session *session;
10528 nghttp2_session_callbacks callbacks;
10529 nghttp2_stream *stream;
10530 nghttp2_stream *opened_stream;
10531 nghttp2_priority_spec pri_spec;
10532 nghttp2_frame frame;
10533 nghttp2_ext_priority_update priority_update;
10534
10535 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
10536
10537 nghttp2_session_server_new(&session, &callbacks, NULL);
10538
10539 nghttp2_priority_spec_init(&pri_spec, 0, 3, 0);
10540
10541 nghttp2_frame_priority_init(&frame.priority, 1, &pri_spec);
10542
10543 assert_int(0, ==, nghttp2_session_on_priority_received(session, &frame));
10544
10545 stream = nghttp2_session_get_stream_raw(session, 1);
10546
10547 assert_enum(nghttp2_stream_state, NGHTTP2_STREAM_IDLE, ==, stream->state);
10548 assert_null(stream->closed_prev);
10549 assert_null(stream->closed_next);
10550 assert_size(1, ==, session->num_idle_streams);
10551 assert_ptr_equal(session->idle_stream_head, stream);
10552 assert_ptr_equal(session->idle_stream_tail, stream);
10553
10554 opened_stream = open_recv_stream2(session, 1, NGHTTP2_STREAM_OPENING);
10555
10556 assert_ptr_equal(stream, opened_stream);
10557 assert_enum(nghttp2_stream_state, NGHTTP2_STREAM_OPENING, ==, stream->state);
10558 assert_size(0, ==, session->num_idle_streams);
10559 assert_null(session->idle_stream_head);
10560 assert_null(session->idle_stream_tail);
10561
10562 nghttp2_frame_priority_free(&frame.priority);
10563
10564 nghttp2_session_del(session);
10565
10566 /* No RFC 7540 priorities */
10567 nghttp2_session_server_new(&session, &callbacks, NULL);
10568
10569 session->pending_no_rfc7540_priorities = 1;
10570
10571 frame.ext.payload = &priority_update;
10572
10573 nghttp2_frame_priority_update_init(&frame.ext, 1, (uint8_t *)"u=3",
10574 strlen("u=3"));
10575
10576 assert_int(0, ==,
10577 nghttp2_session_on_priority_update_received(session, &frame));
10578
10579 stream = nghttp2_session_get_stream_raw(session, 1);
10580
10581 assert_enum(nghttp2_stream_state, NGHTTP2_STREAM_IDLE, ==, stream->state);
10582 assert_null(stream->closed_next);
10583 assert_size(1, ==, session->num_idle_streams);
10584
10585 opened_stream = open_recv_stream2(session, 1, NGHTTP2_STREAM_OPENING);
10586
10587 assert_ptr_equal(stream, opened_stream);
10588 assert_enum(nghttp2_stream_state, NGHTTP2_STREAM_OPENING, ==, stream->state);
10589 assert_size(0, ==, session->num_idle_streams);
10590
10591 nghttp2_frame_priority_free(&frame.priority);
10592
10593 nghttp2_session_del(session);
10594 }
10595
test_nghttp2_session_cancel_reserved_remote(void)10596 void test_nghttp2_session_cancel_reserved_remote(void) {
10597 nghttp2_session *session;
10598 nghttp2_session_callbacks callbacks;
10599 nghttp2_stream *stream;
10600 nghttp2_frame frame;
10601 nghttp2_nv *nva;
10602 size_t nvlen;
10603 nghttp2_hd_deflater deflater;
10604 nghttp2_mem *mem;
10605 nghttp2_bufs bufs;
10606 nghttp2_ssize rv;
10607
10608 mem = nghttp2_mem_default();
10609 frame_pack_bufs_init(&bufs);
10610
10611 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
10612 callbacks.send_callback2 = null_send_callback;
10613
10614 nghttp2_session_client_new(&session, &callbacks, NULL);
10615
10616 nghttp2_hd_deflate_init(&deflater, mem);
10617
10618 stream = open_recv_stream2(session, 2, NGHTTP2_STREAM_RESERVED);
10619
10620 nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, 2, NGHTTP2_CANCEL);
10621
10622 assert_enum(nghttp2_stream_state, NGHTTP2_STREAM_CLOSING, ==, stream->state);
10623
10624 assert_int(0, ==, nghttp2_session_send(session));
10625
10626 nvlen = ARRLEN(resnv);
10627 nghttp2_nv_array_copy(&nva, resnv, nvlen, mem);
10628
10629 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 2,
10630 NGHTTP2_HCAT_PUSH_RESPONSE, NULL, nva, nvlen);
10631 rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
10632
10633 assert_ptrdiff(0, ==, rv);
10634
10635 rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
10636 nghttp2_buf_len(&bufs.head->buf));
10637
10638 assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(&bufs.head->buf), ==, rv);
10639
10640 /* stream is not dangling, so assign NULL */
10641 stream = NULL;
10642
10643 /* No RST_STREAM or GOAWAY is generated since stream should be in
10644 NGHTTP2_STREAM_CLOSING and push response should be ignored. */
10645 assert_size(0, ==, nghttp2_outbound_queue_size(&session->ob_reg));
10646
10647 /* Check that we can receive push response HEADERS while RST_STREAM
10648 is just queued. */
10649 open_recv_stream2(session, 4, NGHTTP2_STREAM_RESERVED);
10650
10651 nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, 2, NGHTTP2_CANCEL);
10652
10653 nghttp2_bufs_reset(&bufs);
10654
10655 frame.hd.stream_id = 4;
10656 rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
10657
10658 assert_ptrdiff(0, ==, rv);
10659
10660 rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
10661 nghttp2_buf_len(&bufs.head->buf));
10662
10663 assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(&bufs.head->buf), ==, rv);
10664
10665 assert_size(1, ==, nghttp2_outbound_queue_size(&session->ob_reg));
10666
10667 nghttp2_frame_headers_free(&frame.headers, mem);
10668
10669 nghttp2_hd_deflate_free(&deflater);
10670
10671 nghttp2_session_del(session);
10672
10673 nghttp2_bufs_free(&bufs);
10674 }
10675
test_nghttp2_session_reset_pending_headers(void)10676 void test_nghttp2_session_reset_pending_headers(void) {
10677 nghttp2_session *session;
10678 nghttp2_session_callbacks callbacks;
10679 nghttp2_stream *stream;
10680 int32_t stream_id;
10681 my_user_data ud;
10682
10683 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
10684 callbacks.send_callback2 = null_send_callback;
10685 callbacks.on_frame_send_callback = on_frame_send_callback;
10686 callbacks.on_frame_not_send_callback = on_frame_not_send_callback;
10687 callbacks.on_stream_close_callback = on_stream_close_callback;
10688
10689 nghttp2_session_client_new(&session, &callbacks, &ud);
10690
10691 stream_id = nghttp2_submit_request2(session, NULL, NULL, 0, NULL, NULL);
10692 assert_int32(1, <=, stream_id);
10693
10694 nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, stream_id,
10695 NGHTTP2_CANCEL);
10696
10697 session->remote_settings.max_concurrent_streams = 0;
10698
10699 /* RST_STREAM cancels pending HEADERS and is not actually sent. */
10700 ud.frame_send_cb_called = 0;
10701 assert_int(0, ==, nghttp2_session_send(session));
10702
10703 assert_int(0, ==, ud.frame_send_cb_called);
10704
10705 stream = nghttp2_session_get_stream(session, stream_id);
10706
10707 assert_null(stream);
10708
10709 /* See HEADERS is not sent. on_stream_close is called just like
10710 transmission failure. */
10711 session->remote_settings.max_concurrent_streams = 1;
10712
10713 ud.frame_not_send_cb_called = 0;
10714 ud.stream_close_error_code = 0;
10715 assert_int(0, ==, nghttp2_session_send(session));
10716
10717 assert_int(1, ==, ud.frame_not_send_cb_called);
10718 assert_uint8(NGHTTP2_HEADERS, ==, ud.not_sent_frame_type);
10719 assert_uint32(NGHTTP2_CANCEL, ==, ud.stream_close_error_code);
10720
10721 stream = nghttp2_session_get_stream(session, stream_id);
10722
10723 assert_null(stream);
10724
10725 nghttp2_session_del(session);
10726 }
10727
test_nghttp2_session_send_data_callback(void)10728 void test_nghttp2_session_send_data_callback(void) {
10729 nghttp2_session *session;
10730 nghttp2_session_callbacks callbacks;
10731 nghttp2_data_provider2 data_prd;
10732 my_user_data ud;
10733 accumulator acc;
10734 nghttp2_frame_hd hd;
10735
10736 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
10737 callbacks.send_callback2 = accumulator_send_callback;
10738 callbacks.send_data_callback = send_data_callback;
10739
10740 data_prd.read_callback = no_copy_data_source_read_callback;
10741
10742 acc.length = 0;
10743 ud.acc = &acc;
10744
10745 ud.data_source_length = NGHTTP2_DATA_PAYLOADLEN * 2;
10746
10747 nghttp2_session_client_new(&session, &callbacks, &ud);
10748
10749 open_sent_stream(session, 1);
10750
10751 nghttp2_submit_data2(session, NGHTTP2_FLAG_END_STREAM, 1, &data_prd);
10752
10753 assert_int(0, ==, nghttp2_session_send(session));
10754
10755 assert_size((NGHTTP2_FRAME_HDLEN + NGHTTP2_DATA_PAYLOADLEN) * 2, ==,
10756 acc.length);
10757
10758 nghttp2_frame_unpack_frame_hd(&hd, acc.buf);
10759
10760 assert_size(16384, ==, hd.length);
10761 assert_uint8(NGHTTP2_DATA, ==, hd.type);
10762 assert_uint8(NGHTTP2_FLAG_NONE, ==, hd.flags);
10763
10764 nghttp2_frame_unpack_frame_hd(&hd, acc.buf + NGHTTP2_FRAME_HDLEN + hd.length);
10765
10766 assert_size(16384, ==, hd.length);
10767 assert_uint8(NGHTTP2_DATA, ==, hd.type);
10768 assert_uint8(NGHTTP2_FLAG_END_STREAM, ==, hd.flags);
10769
10770 nghttp2_session_del(session);
10771 }
10772
test_nghttp2_session_on_begin_headers_temporal_failure(void)10773 void test_nghttp2_session_on_begin_headers_temporal_failure(void) {
10774 nghttp2_session *session;
10775 nghttp2_session_callbacks callbacks;
10776 my_user_data ud;
10777 nghttp2_bufs bufs;
10778 nghttp2_mem *mem;
10779 nghttp2_ssize rv;
10780 nghttp2_hd_deflater deflater;
10781 nghttp2_outbound_item *item;
10782
10783 mem = nghttp2_mem_default();
10784 frame_pack_bufs_init(&bufs);
10785 nghttp2_hd_deflate_init(&deflater, mem);
10786
10787 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
10788 callbacks.on_begin_headers_callback =
10789 temporal_failure_on_begin_headers_callback;
10790 callbacks.on_header_callback = on_header_callback;
10791 callbacks.on_frame_recv_callback = on_frame_recv_callback;
10792 callbacks.send_callback2 = null_send_callback;
10793 nghttp2_session_server_new(&session, &callbacks, &ud);
10794
10795 rv = pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, reqnv,
10796 ARRLEN(reqnv), mem);
10797 assert_ptrdiff(0, ==, rv);
10798
10799 ud.header_cb_called = 0;
10800 ud.frame_recv_cb_called = 0;
10801 rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
10802 nghttp2_bufs_len(&bufs));
10803 assert_ptrdiff((nghttp2_ssize)nghttp2_bufs_len(&bufs), ==, rv);
10804 assert_int(0, ==, ud.header_cb_called);
10805 assert_int(0, ==, ud.frame_recv_cb_called);
10806
10807 item = nghttp2_session_get_next_ob_item(session);
10808 assert_uint8(NGHTTP2_RST_STREAM, ==, item->frame.hd.type);
10809 assert_int32(1, ==, item->frame.hd.stream_id);
10810 assert_uint32(NGHTTP2_INTERNAL_ERROR, ==, item->frame.rst_stream.error_code);
10811
10812 nghttp2_session_del(session);
10813 nghttp2_hd_deflate_free(&deflater);
10814
10815 nghttp2_bufs_reset(&bufs);
10816 /* check for PUSH_PROMISE */
10817 nghttp2_hd_deflate_init(&deflater, mem);
10818 nghttp2_session_client_new(&session, &callbacks, &ud);
10819
10820 open_sent_stream(session, 1);
10821
10822 rv = pack_push_promise(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, 2,
10823 reqnv, ARRLEN(reqnv), mem);
10824 assert_ptrdiff(0, ==, rv);
10825
10826 ud.header_cb_called = 0;
10827 ud.frame_recv_cb_called = 0;
10828 rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
10829 nghttp2_bufs_len(&bufs));
10830 assert_ptrdiff((nghttp2_ssize)nghttp2_bufs_len(&bufs), ==, rv);
10831 assert_int(0, ==, ud.header_cb_called);
10832 assert_int(0, ==, ud.frame_recv_cb_called);
10833
10834 item = nghttp2_session_get_next_ob_item(session);
10835 assert_uint8(NGHTTP2_RST_STREAM, ==, item->frame.hd.type);
10836 assert_int32(2, ==, item->frame.hd.stream_id);
10837 assert_uint32(NGHTTP2_INTERNAL_ERROR, ==, item->frame.rst_stream.error_code);
10838
10839 nghttp2_session_del(session);
10840 nghttp2_hd_deflate_free(&deflater);
10841 nghttp2_bufs_free(&bufs);
10842 }
10843
test_nghttp2_session_defer_then_close(void)10844 void test_nghttp2_session_defer_then_close(void) {
10845 nghttp2_session *session;
10846 nghttp2_session_callbacks callbacks;
10847 nghttp2_data_provider2 prd;
10848 int rv;
10849 const uint8_t *datap;
10850 nghttp2_ssize datalen;
10851 nghttp2_frame frame;
10852
10853 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
10854 callbacks.send_callback2 = null_send_callback;
10855
10856 nghttp2_session_client_new(&session, &callbacks, NULL);
10857
10858 prd.read_callback = defer_data_source_read_callback;
10859
10860 rv = nghttp2_submit_request2(session, NULL, reqnv, ARRLEN(reqnv), &prd, NULL);
10861 assert_ptrdiff(0, <, rv);
10862
10863 /* This sends HEADERS */
10864 datalen = nghttp2_session_mem_send2(session, &datap);
10865
10866 assert_ptrdiff(0, <, datalen);
10867
10868 /* This makes DATA item deferred */
10869 datalen = nghttp2_session_mem_send2(session, &datap);
10870
10871 assert_ptrdiff(0, ==, datalen);
10872
10873 nghttp2_frame_rst_stream_init(&frame.rst_stream, 1, NGHTTP2_CANCEL);
10874
10875 /* Assertion failure; GH-264 */
10876 rv = nghttp2_session_on_rst_stream_received(session, &frame);
10877
10878 assert_int(0, ==, rv);
10879
10880 nghttp2_session_del(session);
10881 }
10882
submit_response_on_stream_close(nghttp2_session * session,int32_t stream_id,uint32_t error_code,void * user_data)10883 static int submit_response_on_stream_close(nghttp2_session *session,
10884 int32_t stream_id,
10885 uint32_t error_code,
10886 void *user_data) {
10887 nghttp2_data_provider2 data_prd;
10888 (void)error_code;
10889 (void)user_data;
10890
10891 data_prd.read_callback = temporal_failure_data_source_read_callback;
10892
10893 // Attempt to submit response or data to the stream being closed
10894 switch (stream_id) {
10895 case 1:
10896 assert_int(0, ==,
10897 nghttp2_submit_response2(session, stream_id, resnv,
10898 ARRLEN(resnv), &data_prd));
10899 break;
10900 case 3:
10901 assert_int(
10902 0, ==,
10903 nghttp2_submit_data2(session, NGHTTP2_FLAG_NONE, stream_id, &data_prd));
10904 break;
10905 }
10906
10907 return 0;
10908 }
10909
test_nghttp2_session_detach_item_from_closed_stream(void)10910 void test_nghttp2_session_detach_item_from_closed_stream(void) {
10911 nghttp2_session *session;
10912 nghttp2_session_callbacks callbacks;
10913
10914 memset(&callbacks, 0, sizeof(callbacks));
10915
10916 callbacks.send_callback2 = null_send_callback;
10917 callbacks.on_stream_close_callback = submit_response_on_stream_close;
10918
10919 nghttp2_session_server_new(&session, &callbacks, NULL);
10920
10921 open_recv_stream(session, 1);
10922 open_recv_stream(session, 3);
10923
10924 nghttp2_session_close_stream(session, 1, NGHTTP2_NO_ERROR);
10925 nghttp2_session_close_stream(session, 3, NGHTTP2_NO_ERROR);
10926
10927 assert_int(0, ==, nghttp2_session_send(session));
10928
10929 nghttp2_session_del(session);
10930
10931 /* No RFC 7540 priorities */
10932 nghttp2_session_server_new(&session, &callbacks, NULL);
10933
10934 session->pending_no_rfc7540_priorities = 1;
10935
10936 open_recv_stream(session, 1);
10937 open_recv_stream(session, 3);
10938
10939 nghttp2_session_close_stream(session, 1, NGHTTP2_NO_ERROR);
10940 nghttp2_session_close_stream(session, 3, NGHTTP2_NO_ERROR);
10941
10942 assert_int(0, ==, nghttp2_session_send(session));
10943
10944 nghttp2_session_del(session);
10945 }
10946
test_nghttp2_session_flooding(void)10947 void test_nghttp2_session_flooding(void) {
10948 nghttp2_session *session;
10949 nghttp2_session_callbacks callbacks;
10950 nghttp2_bufs bufs;
10951 nghttp2_buf *buf;
10952 nghttp2_frame frame;
10953 nghttp2_mem *mem;
10954 size_t i;
10955
10956 mem = nghttp2_mem_default();
10957
10958 frame_pack_bufs_init(&bufs);
10959
10960 memset(&callbacks, 0, sizeof(callbacks));
10961
10962 /* PING ACK */
10963 nghttp2_session_server_new(&session, &callbacks, NULL);
10964
10965 nghttp2_frame_ping_init(&frame.ping, NGHTTP2_FLAG_NONE, NULL);
10966 nghttp2_frame_pack_ping(&bufs, &frame.ping);
10967 nghttp2_frame_ping_free(&frame.ping);
10968
10969 buf = &bufs.head->buf;
10970
10971 for (i = 0; i < NGHTTP2_DEFAULT_MAX_OBQ_FLOOD_ITEM; ++i) {
10972 assert_ptrdiff(
10973 (nghttp2_ssize)nghttp2_buf_len(buf), ==,
10974 nghttp2_session_mem_recv2(session, buf->pos, nghttp2_buf_len(buf)));
10975 }
10976
10977 assert_ptrdiff(
10978 NGHTTP2_ERR_FLOODED, ==,
10979 nghttp2_session_mem_recv2(session, buf->pos, nghttp2_buf_len(buf)));
10980
10981 nghttp2_session_del(session);
10982
10983 /* SETTINGS ACK */
10984 nghttp2_bufs_reset(&bufs);
10985
10986 nghttp2_session_server_new(&session, &callbacks, NULL);
10987
10988 nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE, NULL, 0);
10989 nghttp2_frame_pack_settings(&bufs, &frame.settings);
10990 nghttp2_frame_settings_free(&frame.settings, mem);
10991
10992 buf = &bufs.head->buf;
10993
10994 for (i = 0; i < NGHTTP2_DEFAULT_MAX_OBQ_FLOOD_ITEM; ++i) {
10995 assert_ptrdiff(
10996 (nghttp2_ssize)nghttp2_buf_len(buf), ==,
10997 nghttp2_session_mem_recv2(session, buf->pos, nghttp2_buf_len(buf)));
10998 }
10999
11000 assert_ptrdiff(
11001 NGHTTP2_ERR_FLOODED, ==,
11002 nghttp2_session_mem_recv2(session, buf->pos, nghttp2_buf_len(buf)));
11003
11004 nghttp2_session_del(session);
11005 nghttp2_bufs_free(&bufs);
11006 }
11007
test_nghttp2_session_change_stream_priority(void)11008 void test_nghttp2_session_change_stream_priority(void) {
11009 nghttp2_session *session;
11010 nghttp2_session_callbacks callbacks;
11011 nghttp2_stream *stream1, *stream2, *stream3, *stream5;
11012 nghttp2_priority_spec pri_spec;
11013 int rv;
11014
11015 memset(&callbacks, 0, sizeof(callbacks));
11016
11017 nghttp2_session_server_new(&session, &callbacks, NULL);
11018
11019 stream1 = open_recv_stream(session, 1);
11020 stream3 = open_recv_stream_with_dep_weight(session, 3, 199, stream1);
11021 stream2 = open_sent_stream_with_dep_weight(session, 2, 101, stream3);
11022
11023 nghttp2_priority_spec_init(&pri_spec, 1, 256, 0);
11024
11025 rv = nghttp2_session_change_stream_priority(session, 2, &pri_spec);
11026
11027 assert_int(0, ==, rv);
11028
11029 assert_ptr_equal(stream1, stream2->dep_prev);
11030 assert_int32(256, ==, stream2->weight);
11031
11032 /* Cannot change stream which does not exist */
11033 rv = nghttp2_session_change_stream_priority(session, 5, &pri_spec);
11034 assert_int(NGHTTP2_ERR_INVALID_ARGUMENT, ==, rv);
11035
11036 /* It is an error to depend on itself */
11037 rv = nghttp2_session_change_stream_priority(session, 1, &pri_spec);
11038 assert_int(NGHTTP2_ERR_INVALID_ARGUMENT, ==, rv);
11039
11040 /* It is an error to change priority of root stream (0) */
11041 rv = nghttp2_session_change_stream_priority(session, 0, &pri_spec);
11042 assert_int(NGHTTP2_ERR_INVALID_ARGUMENT, ==, rv);
11043
11044 /* Depends on the non-existing idle stream. This creates that idle
11045 stream. */
11046 nghttp2_priority_spec_init(&pri_spec, 5, 9, 1);
11047
11048 rv = nghttp2_session_change_stream_priority(session, 2, &pri_spec);
11049
11050 assert_int(0, ==, rv);
11051
11052 stream5 = nghttp2_session_get_stream_raw(session, 5);
11053
11054 assert_not_null(stream5);
11055 assert_ptr_equal(&session->root, stream5->dep_prev);
11056 assert_ptr_equal(stream5, stream2->dep_prev);
11057 assert_int32(9, ==, stream2->weight);
11058
11059 nghttp2_session_del(session);
11060
11061 /* Check that this works in client session too */
11062 nghttp2_session_client_new(&session, &callbacks, NULL);
11063
11064 stream1 = open_sent_stream(session, 1);
11065
11066 nghttp2_priority_spec_init(&pri_spec, 5, 9, 1);
11067
11068 rv = nghttp2_session_change_stream_priority(session, 1, &pri_spec);
11069
11070 assert_int(0, ==, rv);
11071
11072 stream5 = nghttp2_session_get_stream_raw(session, 5);
11073
11074 assert_not_null(stream5);
11075 assert_ptr_equal(&session->root, stream5->dep_prev);
11076 assert_ptr_equal(stream5, stream1->dep_prev);
11077 assert_int32(9, ==, stream1->weight);
11078
11079 nghttp2_session_del(session);
11080 }
11081
test_nghttp2_session_change_extpri_stream_priority(void)11082 void test_nghttp2_session_change_extpri_stream_priority(void) {
11083 nghttp2_session *session;
11084 nghttp2_session_callbacks callbacks;
11085 nghttp2_bufs bufs;
11086 nghttp2_buf *buf;
11087 nghttp2_ssize rv;
11088 nghttp2_option *option;
11089 nghttp2_extension frame;
11090 nghttp2_ext_priority_update priority_update;
11091 nghttp2_extpri extpri, nextpri;
11092 nghttp2_stream *stream;
11093 static const uint8_t field_value[] = "u=2";
11094
11095 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
11096
11097 frame_pack_bufs_init(&bufs);
11098
11099 nghttp2_option_new(&option);
11100 nghttp2_option_set_builtin_recv_extension_type(option,
11101 NGHTTP2_PRIORITY_UPDATE);
11102
11103 nghttp2_session_server_new2(&session, &callbacks, NULL, option);
11104
11105 session->pending_no_rfc7540_priorities = 1;
11106
11107 open_recv_stream(session, 1);
11108
11109 extpri.urgency = NGHTTP2_EXTPRI_URGENCY_LOW + 1;
11110 extpri.inc = 1;
11111
11112 rv = nghttp2_session_change_extpri_stream_priority(
11113 session, 1, &extpri, /* ignore_client_signal = */ 0);
11114
11115 assert_ptrdiff(0, ==, rv);
11116
11117 stream = nghttp2_session_get_stream(session, 1);
11118
11119 assert_uint32(NGHTTP2_EXTPRI_URGENCY_LOW, ==,
11120 nghttp2_extpri_uint8_urgency(stream->extpri));
11121 assert_true(nghttp2_extpri_uint8_inc(stream->extpri));
11122
11123 rv = nghttp2_session_get_extpri_stream_priority(session, &nextpri, 1);
11124
11125 assert_ptrdiff(0, ==, rv);
11126 assert_uint32(NGHTTP2_EXTPRI_URGENCY_LOW, ==, nextpri.urgency);
11127 assert_true(nextpri.inc);
11128
11129 /* Client can still update stream priority. */
11130 frame.payload = &priority_update;
11131 nghttp2_frame_priority_update_init(&frame, 1, (uint8_t *)field_value,
11132 sizeof(field_value) - 1);
11133 nghttp2_frame_pack_priority_update(&bufs, &frame);
11134
11135 buf = &bufs.head->buf;
11136 rv = nghttp2_session_mem_recv2(session, buf->pos, nghttp2_buf_len(buf));
11137
11138 assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(buf), ==, rv);
11139 assert_uint8(2, ==, stream->extpri);
11140
11141 /* Start to ignore client priority signal for this stream. */
11142 rv = nghttp2_session_change_extpri_stream_priority(
11143 session, 1, &extpri, /* ignore_client_signal = */ 1);
11144
11145 assert_ptrdiff(0, ==, rv);
11146
11147 stream = nghttp2_session_get_stream(session, 1);
11148
11149 assert_uint32(NGHTTP2_EXTPRI_URGENCY_LOW, ==,
11150 nghttp2_extpri_uint8_urgency(stream->extpri));
11151 assert_true(nghttp2_extpri_uint8_inc(stream->extpri));
11152
11153 buf = &bufs.head->buf;
11154 rv = nghttp2_session_mem_recv2(session, buf->pos, nghttp2_buf_len(buf));
11155
11156 assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(buf), ==, rv);
11157 assert_uint32(NGHTTP2_EXTPRI_URGENCY_LOW, ==,
11158 nghttp2_extpri_uint8_urgency(stream->extpri));
11159 assert_true(nghttp2_extpri_uint8_inc(stream->extpri));
11160
11161 nghttp2_session_del(session);
11162 nghttp2_option_del(option);
11163 nghttp2_bufs_free(&bufs);
11164 }
11165
test_nghttp2_session_create_idle_stream(void)11166 void test_nghttp2_session_create_idle_stream(void) {
11167 nghttp2_session *session;
11168 nghttp2_session_callbacks callbacks;
11169 nghttp2_stream *stream2, *stream4, *stream8, *stream10;
11170 nghttp2_priority_spec pri_spec;
11171 int rv;
11172 int i;
11173
11174 memset(&callbacks, 0, sizeof(callbacks));
11175 callbacks.send_callback2 = null_send_callback;
11176
11177 nghttp2_session_server_new(&session, &callbacks, NULL);
11178
11179 stream2 = open_sent_stream(session, 2);
11180
11181 nghttp2_priority_spec_init(&pri_spec, 2, 111, 1);
11182
11183 rv = nghttp2_session_create_idle_stream(session, 4, &pri_spec);
11184
11185 assert_int(0, ==, rv);
11186
11187 stream4 = nghttp2_session_get_stream_raw(session, 4);
11188
11189 assert_int32(4, ==, stream4->stream_id);
11190 assert_int32(111, ==, stream4->weight);
11191 assert_ptr_equal(stream2, stream4->dep_prev);
11192 assert_ptr_equal(stream4, stream2->dep_next);
11193
11194 /* If pri_spec->stream_id does not exist, and it is idle stream, it
11195 is created too */
11196 nghttp2_priority_spec_init(&pri_spec, 10, 109, 0);
11197
11198 rv = nghttp2_session_create_idle_stream(session, 8, &pri_spec);
11199
11200 assert_int(0, ==, rv);
11201
11202 stream8 = nghttp2_session_get_stream_raw(session, 8);
11203 stream10 = nghttp2_session_get_stream_raw(session, 10);
11204
11205 assert_int32(8, ==, stream8->stream_id);
11206 assert_int32(109, ==, stream8->weight);
11207 assert_int32(10, ==, stream10->stream_id);
11208 assert_int32(16, ==, stream10->weight);
11209 assert_ptr_equal(stream10, stream8->dep_prev);
11210 assert_ptr_equal(&session->root, stream10->dep_prev);
11211
11212 /* It is an error to attempt to create already existing idle
11213 stream */
11214 rv = nghttp2_session_create_idle_stream(session, 4, &pri_spec);
11215
11216 assert_int(NGHTTP2_ERR_INVALID_ARGUMENT, ==, rv);
11217
11218 /* It is an error to depend on itself */
11219 pri_spec.stream_id = 6;
11220
11221 rv = nghttp2_session_create_idle_stream(session, 6, &pri_spec);
11222 assert_int(NGHTTP2_ERR_INVALID_ARGUMENT, ==, rv);
11223
11224 /* It is an error to create root stream (0) as idle stream */
11225 rv = nghttp2_session_create_idle_stream(session, 0, &pri_spec);
11226 assert_int(NGHTTP2_ERR_INVALID_ARGUMENT, ==, rv);
11227
11228 /* It is an error to create non-idle stream */
11229 session->last_sent_stream_id = 20;
11230 pri_spec.stream_id = 2;
11231
11232 rv = nghttp2_session_create_idle_stream(session, 18, &pri_spec);
11233
11234 assert_int(NGHTTP2_ERR_INVALID_ARGUMENT, ==, rv);
11235
11236 nghttp2_session_del(session);
11237
11238 /* Check that this works in client session too */
11239 nghttp2_session_client_new(&session, &callbacks, NULL);
11240
11241 nghttp2_priority_spec_init(&pri_spec, 4, 99, 1);
11242
11243 rv = nghttp2_session_create_idle_stream(session, 2, &pri_spec);
11244
11245 assert_int(0, ==, rv);
11246
11247 stream4 = nghttp2_session_get_stream_raw(session, 4);
11248 stream2 = nghttp2_session_get_stream_raw(session, 2);
11249
11250 assert_not_null(stream4);
11251 assert_not_null(stream2);
11252 assert_ptr_equal(&session->root, stream4->dep_prev);
11253 assert_int32(NGHTTP2_DEFAULT_WEIGHT, ==, stream4->weight);
11254 assert_ptr_equal(stream4, stream2->dep_prev);
11255 assert_int32(99, ==, stream2->weight);
11256
11257 nghttp2_session_del(session);
11258
11259 /* Check that idle stream is reduced when nghttp2_session_send() is
11260 called. */
11261 nghttp2_session_server_new(&session, &callbacks, NULL);
11262
11263 session->local_settings.max_concurrent_streams = 30;
11264
11265 nghttp2_priority_spec_init(&pri_spec, 0, 16, 0);
11266 for (i = 0; i < 100; ++i) {
11267 rv = nghttp2_session_create_idle_stream(session, i * 2 + 1, &pri_spec);
11268
11269 assert_int(0, ==, rv);
11270
11271 nghttp2_priority_spec_init(&pri_spec, i * 2 + 1, 16, 0);
11272 }
11273
11274 assert_size(100, ==, session->num_idle_streams);
11275 assert_int(0, ==, nghttp2_session_send(session));
11276 assert_size(30, ==, session->num_idle_streams);
11277 assert_int32(141, ==, session->idle_stream_head->stream_id);
11278
11279 nghttp2_session_del(session);
11280
11281 /* Check that idle stream is reduced when nghttp2_session_mem_recv2() is
11282 called. */
11283 nghttp2_session_client_new(&session, &callbacks, NULL);
11284
11285 session->local_settings.max_concurrent_streams = 30;
11286
11287 nghttp2_priority_spec_init(&pri_spec, 0, 16, 0);
11288 for (i = 0; i < 100; ++i) {
11289 rv = nghttp2_session_create_idle_stream(session, i * 2 + 1, &pri_spec);
11290
11291 assert_int(0, ==, rv);
11292
11293 nghttp2_priority_spec_init(&pri_spec, i * 2 + 1, 16, 0);
11294 }
11295
11296 assert_size(100, ==, session->num_idle_streams);
11297 assert_ptrdiff(0, ==, nghttp2_session_mem_recv2(session, NULL, 0));
11298 assert_size(30, ==, session->num_idle_streams);
11299 assert_int32(141, ==, session->idle_stream_head->stream_id);
11300
11301 nghttp2_session_del(session);
11302 }
11303
test_nghttp2_session_repeated_priority_change(void)11304 void test_nghttp2_session_repeated_priority_change(void) {
11305 nghttp2_session *session;
11306 nghttp2_session_callbacks callbacks;
11307 nghttp2_frame frame;
11308 nghttp2_priority_spec pri_spec;
11309 int32_t stream_id, last_stream_id;
11310 int32_t max_streams = 20;
11311
11312 memset(&callbacks, 0, sizeof(callbacks));
11313
11314 nghttp2_session_server_new(&session, &callbacks, NULL);
11315
11316 session->local_settings.max_concurrent_streams = (uint32_t)max_streams;
11317
11318 /* 1 -> 0 */
11319 nghttp2_priority_spec_init(&pri_spec, 0, 16, 0);
11320 nghttp2_frame_priority_init(&frame.priority, 1, &pri_spec);
11321
11322 assert_int(0, ==, nghttp2_session_on_priority_received(session, &frame));
11323
11324 nghttp2_frame_priority_free(&frame.priority);
11325
11326 last_stream_id = max_streams * 2 + 1;
11327
11328 for (stream_id = 3; stream_id < last_stream_id; stream_id += 2) {
11329 /* 1 -> stream_id */
11330 nghttp2_priority_spec_init(&pri_spec, stream_id, 16, 0);
11331 nghttp2_frame_priority_init(&frame.priority, 1, &pri_spec);
11332
11333 assert_int(0, ==, nghttp2_session_on_priority_received(session, &frame));
11334
11335 nghttp2_frame_priority_free(&frame.priority);
11336 }
11337
11338 assert_size(20, ==, session->num_idle_streams);
11339 assert_int32(1, ==, session->idle_stream_head->stream_id);
11340
11341 /* 1 -> last_stream_id */
11342 nghttp2_priority_spec_init(&pri_spec, last_stream_id, 16, 0);
11343 nghttp2_frame_priority_init(&frame.priority, 1, &pri_spec);
11344
11345 assert_int(0, ==, nghttp2_session_on_priority_received(session, &frame));
11346
11347 nghttp2_frame_priority_free(&frame.priority);
11348
11349 assert_size(20, ==, session->num_idle_streams);
11350 assert_int32(3, ==, session->idle_stream_head->stream_id);
11351
11352 nghttp2_session_del(session);
11353 }
11354
test_nghttp2_session_repeated_priority_submission(void)11355 void test_nghttp2_session_repeated_priority_submission(void) {
11356 nghttp2_session *session;
11357 nghttp2_session_callbacks callbacks;
11358 nghttp2_priority_spec pri_spec;
11359 int32_t stream_id, last_stream_id;
11360 uint32_t max_streams = NGHTTP2_MIN_IDLE_STREAMS;
11361
11362 memset(&callbacks, 0, sizeof(callbacks));
11363
11364 callbacks.send_callback2 = null_send_callback;
11365
11366 nghttp2_session_client_new(&session, &callbacks, NULL);
11367
11368 session->local_settings.max_concurrent_streams = max_streams;
11369
11370 /* 1 -> 0 */
11371 nghttp2_priority_spec_init(&pri_spec, 0, 16, 0);
11372
11373 assert_int(0, ==,
11374 nghttp2_submit_priority(session, NGHTTP2_FLAG_NONE, 1, &pri_spec));
11375
11376 last_stream_id = (int32_t)(max_streams * 2 + 1);
11377
11378 for (stream_id = 3; stream_id < last_stream_id; stream_id += 2) {
11379 /* 1 -> stream_id */
11380 nghttp2_priority_spec_init(&pri_spec, stream_id, 16, 0);
11381
11382 assert_int(
11383 0, ==, nghttp2_submit_priority(session, NGHTTP2_FLAG_NONE, 1, &pri_spec));
11384 }
11385
11386 assert_int(0, ==, nghttp2_session_send(session));
11387 assert_size(max_streams, ==, session->num_idle_streams);
11388 assert_int32(1, ==, session->idle_stream_head->stream_id);
11389
11390 /* 1 -> last_stream_id */
11391 nghttp2_priority_spec_init(&pri_spec, last_stream_id, 16, 0);
11392
11393 assert_int(0, ==,
11394 nghttp2_submit_priority(session, NGHTTP2_FLAG_NONE, 1, &pri_spec));
11395
11396 assert_int(0, ==, nghttp2_session_send(session));
11397 assert_size(max_streams, ==, session->num_idle_streams);
11398 assert_int32(3, ==, session->idle_stream_head->stream_id);
11399
11400 nghttp2_session_del(session);
11401 }
11402
test_nghttp2_session_set_local_window_size(void)11403 void test_nghttp2_session_set_local_window_size(void) {
11404 nghttp2_session *session;
11405 nghttp2_session_callbacks callbacks;
11406 nghttp2_outbound_item *item;
11407 nghttp2_stream *stream;
11408
11409 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
11410 callbacks.send_callback2 = null_send_callback;
11411
11412 nghttp2_session_client_new(&session, &callbacks, NULL);
11413 stream = open_sent_stream(session, 1);
11414 stream->recv_window_size = 4096;
11415
11416 assert_int(0, ==,
11417 nghttp2_session_set_local_window_size(session, NGHTTP2_FLAG_NONE,
11418 1, 65536));
11419 assert_int32(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE + 1, ==,
11420 stream->local_window_size);
11421 assert_int32(4096, ==, stream->recv_window_size);
11422 assert_int32(65536 - 4096, ==,
11423 nghttp2_session_get_stream_local_window_size(session, 1));
11424
11425 item = nghttp2_session_get_next_ob_item(session);
11426
11427 assert_uint8(NGHTTP2_WINDOW_UPDATE, ==, item->frame.hd.type);
11428 assert_int32(1, ==, item->frame.window_update.hd.stream_id);
11429 assert_int32(1, ==, item->frame.window_update.window_size_increment);
11430
11431 assert_int(0, ==, nghttp2_session_send(session));
11432
11433 /* Go decrement part */
11434 assert_int(0, ==,
11435 nghttp2_session_set_local_window_size(session, NGHTTP2_FLAG_NONE,
11436 1, 32768));
11437 assert_int32(32768, ==, stream->local_window_size);
11438 assert_int32(-28672, ==, stream->recv_window_size);
11439 assert_int32(32768, ==, stream->recv_reduction);
11440 assert_int32(65536 - 4096, ==,
11441 nghttp2_session_get_stream_local_window_size(session, 1));
11442
11443 item = nghttp2_session_get_next_ob_item(session);
11444
11445 assert_null(item);
11446
11447 /* Increase local window size */
11448 assert_int(0, ==,
11449 nghttp2_session_set_local_window_size(session, NGHTTP2_FLAG_NONE,
11450 1, 49152));
11451 assert_int32(49152, ==, stream->local_window_size);
11452 assert_int32(-12288, ==, stream->recv_window_size);
11453 assert_int32(16384, ==, stream->recv_reduction);
11454 assert_int32(65536 - 4096, ==,
11455 nghttp2_session_get_stream_local_window_size(session, 1));
11456 assert_null(nghttp2_session_get_next_ob_item(session));
11457
11458 /* Increase local window again */
11459 assert_int(0, ==,
11460 nghttp2_session_set_local_window_size(session, NGHTTP2_FLAG_NONE,
11461 1, 65537));
11462 assert_int32(65537, ==, stream->local_window_size);
11463 assert_int32(4096, ==, stream->recv_window_size);
11464 assert_int32(0, ==, stream->recv_reduction);
11465 assert_int32(65537 - 4096, ==,
11466 nghttp2_session_get_stream_local_window_size(session, 1));
11467
11468 item = nghttp2_session_get_next_ob_item(session);
11469
11470 assert_int32(1, ==, item->frame.window_update.window_size_increment);
11471
11472 assert_int(0, ==, nghttp2_session_send(session));
11473
11474 /* Check connection-level flow control */
11475 session->recv_window_size = 4096;
11476 assert_int(0, ==,
11477 nghttp2_session_set_local_window_size(session, NGHTTP2_FLAG_NONE,
11478 0, 65536));
11479 assert_int32(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE + 1, ==,
11480 session->local_window_size);
11481 assert_int32(4096, ==, session->recv_window_size);
11482 assert_int32(65536 - 4096, ==,
11483 nghttp2_session_get_local_window_size(session));
11484
11485 item = nghttp2_session_get_next_ob_item(session);
11486
11487 assert_uint8(NGHTTP2_WINDOW_UPDATE, ==, item->frame.hd.type);
11488 assert_int32(0, ==, item->frame.window_update.hd.stream_id);
11489 assert_int32(1, ==, item->frame.window_update.window_size_increment);
11490
11491 assert_int(0, ==, nghttp2_session_send(session));
11492
11493 /* Go decrement part */
11494 assert_int(0, ==,
11495 nghttp2_session_set_local_window_size(session, NGHTTP2_FLAG_NONE,
11496 0, 32768));
11497 assert_int32(32768, ==, session->local_window_size);
11498 assert_int32(-28672, ==, session->recv_window_size);
11499 assert_int32(32768, ==, session->recv_reduction);
11500 assert_int32(65536 - 4096, ==,
11501 nghttp2_session_get_local_window_size(session));
11502
11503 item = nghttp2_session_get_next_ob_item(session);
11504
11505 assert_null(item);
11506
11507 /* Increase local window size */
11508 assert_int(0, ==,
11509 nghttp2_session_set_local_window_size(session, NGHTTP2_FLAG_NONE,
11510 0, 49152));
11511 assert_int32(49152, ==, session->local_window_size);
11512 assert_int32(-12288, ==, session->recv_window_size);
11513 assert_int32(16384, ==, session->recv_reduction);
11514 assert_int32(65536 - 4096, ==,
11515 nghttp2_session_get_local_window_size(session));
11516 assert_null(nghttp2_session_get_next_ob_item(session));
11517
11518 /* Increase local window again */
11519 assert_int(0, ==,
11520 nghttp2_session_set_local_window_size(session, NGHTTP2_FLAG_NONE,
11521 0, 65537));
11522 assert_int32(65537, ==, session->local_window_size);
11523 assert_int32(4096, ==, session->recv_window_size);
11524 assert_int32(0, ==, session->recv_reduction);
11525 assert_int32(65537 - 4096, ==,
11526 nghttp2_session_get_local_window_size(session));
11527
11528 item = nghttp2_session_get_next_ob_item(session);
11529
11530 assert_int32(1, ==, item->frame.window_update.window_size_increment);
11531
11532 assert_int(0, ==, nghttp2_session_send(session));
11533
11534 nghttp2_session_del(session);
11535
11536 /* Make sure that nghttp2_session_set_local_window_size submits
11537 WINDOW_UPDATE if necessary to increase stream-level window. */
11538 nghttp2_session_client_new(&session, &callbacks, NULL);
11539 stream = open_sent_stream(session, 1);
11540 stream->recv_window_size = NGHTTP2_INITIAL_WINDOW_SIZE;
11541
11542 assert_int(
11543 0, ==,
11544 nghttp2_session_set_local_window_size(session, NGHTTP2_FLAG_NONE, 1, 0));
11545 assert_int32(0, ==, stream->recv_window_size);
11546 assert_int32(0, ==, nghttp2_session_get_stream_local_window_size(session, 1));
11547 /* This should submit WINDOW_UPDATE frame because stream-level
11548 receiving window is now full. */
11549 assert_int(0, ==,
11550 nghttp2_session_set_local_window_size(
11551 session, NGHTTP2_FLAG_NONE, 1, NGHTTP2_INITIAL_WINDOW_SIZE));
11552 assert_int32(0, ==, stream->recv_window_size);
11553 assert_int32(NGHTTP2_INITIAL_WINDOW_SIZE, ==,
11554 nghttp2_session_get_stream_local_window_size(session, 1));
11555
11556 item = nghttp2_session_get_next_ob_item(session);
11557
11558 assert_uint8(NGHTTP2_WINDOW_UPDATE, ==, item->frame.hd.type);
11559 assert_int32(1, ==, item->frame.hd.stream_id);
11560 assert_int32(NGHTTP2_INITIAL_WINDOW_SIZE, ==,
11561 item->frame.window_update.window_size_increment);
11562
11563 nghttp2_session_del(session);
11564
11565 /* Make sure that nghttp2_session_set_local_window_size submits
11566 WINDOW_UPDATE if necessary to increase connection-level
11567 window. */
11568 nghttp2_session_client_new(&session, &callbacks, NULL);
11569 session->recv_window_size = NGHTTP2_INITIAL_WINDOW_SIZE;
11570
11571 assert_int(
11572 0, ==,
11573 nghttp2_session_set_local_window_size(session, NGHTTP2_FLAG_NONE, 0, 0));
11574 assert_int32(0, ==, session->recv_window_size);
11575 assert_int32(0, ==, nghttp2_session_get_local_window_size(session));
11576 /* This should submit WINDOW_UPDATE frame because connection-level
11577 receiving window is now full. */
11578 assert_int(0, ==,
11579 nghttp2_session_set_local_window_size(
11580 session, NGHTTP2_FLAG_NONE, 0, NGHTTP2_INITIAL_WINDOW_SIZE));
11581 assert_int32(0, ==, session->recv_window_size);
11582 assert_int32(NGHTTP2_INITIAL_WINDOW_SIZE, ==,
11583 nghttp2_session_get_local_window_size(session));
11584
11585 item = nghttp2_session_get_next_ob_item(session);
11586
11587 assert_uint8(NGHTTP2_WINDOW_UPDATE, ==, item->frame.hd.type);
11588 assert_int32(0, ==, item->frame.hd.stream_id);
11589 assert_int32(NGHTTP2_INITIAL_WINDOW_SIZE, ==,
11590 item->frame.window_update.window_size_increment);
11591
11592 nghttp2_session_del(session);
11593 }
11594
test_nghttp2_session_cancel_from_before_frame_send(void)11595 void test_nghttp2_session_cancel_from_before_frame_send(void) {
11596 int rv;
11597 nghttp2_session *session;
11598 nghttp2_session_callbacks callbacks;
11599 my_user_data ud;
11600 nghttp2_settings_entry iv;
11601 nghttp2_data_provider2 data_prd;
11602 int32_t stream_id;
11603 nghttp2_stream *stream;
11604
11605 memset(&callbacks, 0, sizeof(callbacks));
11606
11607 callbacks.before_frame_send_callback = cancel_before_frame_send_callback;
11608 callbacks.on_frame_not_send_callback = on_frame_not_send_callback;
11609 callbacks.send_callback2 = null_send_callback;
11610
11611 nghttp2_session_client_new(&session, &callbacks, &ud);
11612
11613 iv.settings_id = 0;
11614 iv.value = 1000000009;
11615
11616 rv = nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, &iv, 1);
11617
11618 assert_int(0, ==, rv);
11619
11620 ud.frame_send_cb_called = 0;
11621 ud.before_frame_send_cb_called = 0;
11622 ud.frame_not_send_cb_called = 0;
11623
11624 rv = nghttp2_session_send(session);
11625
11626 assert_int(0, ==, rv);
11627 assert_int(0, ==, ud.frame_send_cb_called);
11628 assert_int(1, ==, ud.before_frame_send_cb_called);
11629 assert_int(1, ==, ud.frame_not_send_cb_called);
11630
11631 data_prd.source.ptr = NULL;
11632 data_prd.read_callback = temporal_failure_data_source_read_callback;
11633
11634 stream_id = nghttp2_submit_request2(session, NULL, reqnv, ARRLEN(reqnv),
11635 &data_prd, NULL);
11636
11637 assert_int32(0, <, stream_id);
11638
11639 ud.frame_send_cb_called = 0;
11640 ud.before_frame_send_cb_called = 0;
11641 ud.frame_not_send_cb_called = 0;
11642
11643 rv = nghttp2_session_send(session);
11644
11645 assert_int(0, ==, rv);
11646 assert_int(0, ==, ud.frame_send_cb_called);
11647 assert_int(1, ==, ud.before_frame_send_cb_called);
11648 assert_int(1, ==, ud.frame_not_send_cb_called);
11649
11650 stream = nghttp2_session_get_stream_raw(session, stream_id);
11651
11652 assert_null(stream);
11653
11654 nghttp2_session_del(session);
11655
11656 nghttp2_session_server_new(&session, &callbacks, &ud);
11657
11658 open_recv_stream(session, 1);
11659
11660 stream_id = nghttp2_submit_push_promise(session, NGHTTP2_FLAG_NONE, 1, reqnv,
11661 ARRLEN(reqnv), NULL);
11662
11663 assert_int32(0, <, stream_id);
11664
11665 ud.frame_send_cb_called = 0;
11666 ud.before_frame_send_cb_called = 0;
11667 ud.frame_not_send_cb_called = 0;
11668
11669 rv = nghttp2_session_send(session);
11670
11671 assert_int(0, ==, rv);
11672 assert_int(0, ==, ud.frame_send_cb_called);
11673 assert_int(1, ==, ud.before_frame_send_cb_called);
11674 assert_int(1, ==, ud.frame_not_send_cb_called);
11675
11676 stream = nghttp2_session_get_stream_raw(session, stream_id);
11677
11678 assert_null(stream);
11679
11680 nghttp2_session_del(session);
11681 }
11682
test_nghttp2_session_too_many_settings(void)11683 void test_nghttp2_session_too_many_settings(void) {
11684 nghttp2_session *session;
11685 nghttp2_option *option;
11686 nghttp2_session_callbacks callbacks;
11687 nghttp2_frame frame;
11688 nghttp2_bufs bufs;
11689 nghttp2_buf *buf;
11690 nghttp2_ssize rv;
11691 my_user_data ud;
11692 nghttp2_settings_entry iv[3];
11693 nghttp2_mem *mem;
11694 nghttp2_outbound_item *item;
11695
11696 mem = nghttp2_mem_default();
11697 frame_pack_bufs_init(&bufs);
11698
11699 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
11700 callbacks.on_frame_recv_callback = on_frame_recv_callback;
11701 callbacks.send_callback2 = null_send_callback;
11702
11703 nghttp2_option_new(&option);
11704 nghttp2_option_set_max_settings(option, 1);
11705
11706 nghttp2_session_client_new2(&session, &callbacks, &ud, option);
11707
11708 assert_size(1, ==, session->max_settings);
11709
11710 nghttp2_option_del(option);
11711
11712 iv[0].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
11713 iv[0].value = 3000;
11714
11715 iv[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
11716 iv[1].value = 16384;
11717
11718 nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE, dup_iv(iv, 2),
11719 2);
11720
11721 rv = nghttp2_frame_pack_settings(&bufs, &frame.settings);
11722
11723 assert_ptrdiff(0, ==, rv);
11724 assert_size(0, <, nghttp2_bufs_len(&bufs));
11725
11726 nghttp2_frame_settings_free(&frame.settings, mem);
11727
11728 buf = &bufs.head->buf;
11729 assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
11730
11731 ud.frame_recv_cb_called = 0;
11732
11733 rv = nghttp2_session_mem_recv2(session, buf->pos, nghttp2_buf_len(buf));
11734 assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(buf), ==, rv);
11735
11736 item = nghttp2_session_get_next_ob_item(session);
11737 assert_uint8(NGHTTP2_GOAWAY, ==, item->frame.hd.type);
11738
11739 nghttp2_bufs_reset(&bufs);
11740 nghttp2_bufs_free(&bufs);
11741 nghttp2_session_del(session);
11742 }
11743
11744 static void
prepare_session_removed_closed_stream(nghttp2_session * session,nghttp2_hd_deflater * deflater)11745 prepare_session_removed_closed_stream(nghttp2_session *session,
11746 nghttp2_hd_deflater *deflater) {
11747 int rv;
11748 nghttp2_settings_entry iv;
11749 nghttp2_bufs bufs;
11750 nghttp2_mem *mem;
11751 nghttp2_ssize nread;
11752 int i;
11753 nghttp2_stream *stream;
11754 nghttp2_frame_hd hd;
11755
11756 mem = nghttp2_mem_default();
11757
11758 frame_pack_bufs_init(&bufs);
11759
11760 iv.settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS;
11761 iv.value = 2;
11762
11763 rv = nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, &iv, 1);
11764
11765 assert_int(0, ==, rv);
11766
11767 rv = nghttp2_session_send(session);
11768
11769 assert_int(0, ==, rv);
11770
11771 for (i = 1; i <= 3; i += 2) {
11772 rv = pack_headers(&bufs, deflater, i,
11773 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM, reqnv,
11774 ARRLEN(reqnv), mem);
11775
11776 assert_int(0, ==, rv);
11777
11778 nread = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
11779 nghttp2_bufs_len(&bufs));
11780
11781 assert_ptrdiff((nghttp2_ssize)nghttp2_bufs_len(&bufs), ==, nread);
11782
11783 nghttp2_bufs_reset(&bufs);
11784 }
11785
11786 nghttp2_session_close_stream(session, 3, NGHTTP2_NO_ERROR);
11787
11788 rv = pack_headers(&bufs, deflater, 5,
11789 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM, reqnv,
11790 ARRLEN(reqnv), mem);
11791
11792 assert_int(0, ==, rv);
11793
11794 /* Receiving stream 5 will erase stream 3 from closed stream list */
11795 nread = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
11796 nghttp2_bufs_len(&bufs));
11797
11798 assert_ptrdiff((nghttp2_ssize)nghttp2_bufs_len(&bufs), ==, nread);
11799
11800 stream = nghttp2_session_get_stream_raw(session, 3);
11801
11802 assert_null(stream);
11803
11804 /* Since the current max concurrent streams is
11805 NGHTTP2_DEFAULT_MAX_CONCURRENT_STREAMS, receiving frame on stream
11806 3 is ignored. */
11807 nghttp2_bufs_reset(&bufs);
11808 rv = pack_headers(&bufs, deflater, 3,
11809 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM,
11810 trailernv, ARRLEN(trailernv), mem);
11811
11812 assert_int(0, ==, rv);
11813
11814 nread = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
11815 nghttp2_bufs_len(&bufs));
11816
11817 assert_ptrdiff((nghttp2_ssize)nghttp2_bufs_len(&bufs), ==, nread);
11818 assert_null(nghttp2_session_get_next_ob_item(session));
11819
11820 nghttp2_frame_hd_init(&hd, 0, NGHTTP2_DATA, NGHTTP2_FLAG_NONE, 3);
11821 nghttp2_bufs_reset(&bufs);
11822 nghttp2_frame_pack_frame_hd(bufs.head->buf.last, &hd);
11823 bufs.head->buf.last += NGHTTP2_FRAME_HDLEN;
11824
11825 nread = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
11826 nghttp2_bufs_len(&bufs));
11827
11828 assert_ptrdiff((nghttp2_ssize)nghttp2_bufs_len(&bufs), ==, nread);
11829 assert_null(nghttp2_session_get_next_ob_item(session));
11830
11831 /* Now server receives SETTINGS ACK */
11832 nghttp2_frame_hd_init(&hd, 0, NGHTTP2_SETTINGS, NGHTTP2_FLAG_ACK, 0);
11833 nghttp2_bufs_reset(&bufs);
11834 nghttp2_frame_pack_frame_hd(bufs.head->buf.last, &hd);
11835 bufs.head->buf.last += NGHTTP2_FRAME_HDLEN;
11836
11837 nread = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
11838 nghttp2_bufs_len(&bufs));
11839
11840 assert_ptrdiff((nghttp2_ssize)nghttp2_bufs_len(&bufs), ==, nread);
11841
11842 nghttp2_bufs_free(&bufs);
11843 }
11844
test_nghttp2_session_removed_closed_stream(void)11845 void test_nghttp2_session_removed_closed_stream(void) {
11846 nghttp2_session *session;
11847 nghttp2_session_callbacks callbacks;
11848 int rv;
11849 nghttp2_hd_deflater deflater;
11850 nghttp2_bufs bufs;
11851 nghttp2_mem *mem;
11852 nghttp2_ssize nread;
11853 nghttp2_frame_hd hd;
11854 nghttp2_outbound_item *item;
11855
11856 mem = nghttp2_mem_default();
11857
11858 frame_pack_bufs_init(&bufs);
11859
11860 memset(&callbacks, 0, sizeof(callbacks));
11861
11862 callbacks.send_callback2 = null_send_callback;
11863
11864 nghttp2_session_server_new(&session, &callbacks, NULL);
11865
11866 /* Now local max concurrent streams is still unlimited, pending max
11867 concurrent streams is now 2. */
11868
11869 nghttp2_hd_deflate_init(&deflater, mem);
11870
11871 prepare_session_removed_closed_stream(session, &deflater);
11872
11873 /* Now current max concurrent streams is 2. Receiving frame on
11874 stream 3 is ignored because we have no stream object for stream
11875 3. */
11876 nghttp2_bufs_reset(&bufs);
11877 rv = pack_headers(&bufs, &deflater, 3,
11878 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM,
11879 trailernv, ARRLEN(trailernv), mem);
11880
11881 assert_int(0, ==, rv);
11882
11883 nread = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
11884 nghttp2_bufs_len(&bufs));
11885
11886 assert_ptrdiff((nghttp2_ssize)nghttp2_bufs_len(&bufs), ==, nread);
11887
11888 item = nghttp2_session_get_next_ob_item(session);
11889
11890 assert_null(item);
11891
11892 nghttp2_hd_deflate_free(&deflater);
11893 nghttp2_session_del(session);
11894
11895 nghttp2_session_server_new(&session, &callbacks, NULL);
11896 nghttp2_hd_deflate_init(&deflater, mem);
11897 /* Same setup, and then receive DATA instead of HEADERS */
11898
11899 prepare_session_removed_closed_stream(session, &deflater);
11900
11901 nghttp2_frame_hd_init(&hd, 0, NGHTTP2_DATA, NGHTTP2_FLAG_NONE, 3);
11902 nghttp2_bufs_reset(&bufs);
11903 nghttp2_frame_pack_frame_hd(bufs.head->buf.last, &hd);
11904 bufs.head->buf.last += NGHTTP2_FRAME_HDLEN;
11905
11906 nread = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
11907 nghttp2_bufs_len(&bufs));
11908
11909 assert_ptrdiff((nghttp2_ssize)nghttp2_bufs_len(&bufs), ==, nread);
11910
11911 item = nghttp2_session_get_next_ob_item(session);
11912
11913 assert_null(item);
11914
11915 nghttp2_hd_deflate_free(&deflater);
11916 nghttp2_session_del(session);
11917
11918 nghttp2_bufs_free(&bufs);
11919 }
11920
pause_once_data_source_read_callback(nghttp2_session * session,int32_t stream_id,uint8_t * buf,size_t len,uint32_t * data_flags,nghttp2_data_source * source,void * user_data)11921 static nghttp2_ssize pause_once_data_source_read_callback(
11922 nghttp2_session *session, int32_t stream_id, uint8_t *buf, size_t len,
11923 uint32_t *data_flags, nghttp2_data_source *source, void *user_data) {
11924 my_user_data *ud = user_data;
11925 if (ud->data_source_read_cb_paused == 0) {
11926 ++ud->data_source_read_cb_paused;
11927 return NGHTTP2_ERR_PAUSE;
11928 }
11929
11930 return fixed_length_data_source_read_callback(session, stream_id, buf, len,
11931 data_flags, source, user_data);
11932 }
11933
test_nghttp2_session_pause_data(void)11934 void test_nghttp2_session_pause_data(void) {
11935 nghttp2_session *session;
11936 nghttp2_session_callbacks callbacks;
11937 nghttp2_data_provider2 data_prd;
11938 my_user_data ud;
11939
11940 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
11941 callbacks.send_callback2 = null_send_callback;
11942 callbacks.on_frame_send_callback = on_frame_send_callback;
11943
11944 data_prd.read_callback = pause_once_data_source_read_callback;
11945 ud.data_source_length = NGHTTP2_DATA_PAYLOADLEN;
11946
11947 nghttp2_session_server_new(&session, &callbacks, &ud);
11948
11949 open_recv_stream(session, 1);
11950
11951 assert_int(
11952 0, ==,
11953 nghttp2_submit_data2(session, NGHTTP2_FLAG_END_STREAM, 1, &data_prd));
11954
11955 ud.frame_send_cb_called = 0;
11956 ud.data_source_read_cb_paused = 0;
11957
11958 assert_int(0, ==, nghttp2_session_send(session));
11959 assert_int(0, ==, ud.frame_send_cb_called);
11960 assert_null(session->aob.item);
11961 assert_int(0, ==, nghttp2_session_send(session));
11962 assert_int(1, ==, ud.frame_send_cb_called);
11963 assert_uint8(NGHTTP2_DATA, ==, ud.sent_frame_type);
11964 assert_null(nghttp2_session_get_next_ob_item(session));
11965
11966 nghttp2_session_del(session);
11967 }
11968
test_nghttp2_session_no_closed_streams(void)11969 void test_nghttp2_session_no_closed_streams(void) {
11970 nghttp2_session *session;
11971 nghttp2_session_callbacks callbacks;
11972 nghttp2_option *option;
11973
11974 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
11975
11976 nghttp2_option_new(&option);
11977 nghttp2_option_set_no_closed_streams(option, 1);
11978
11979 nghttp2_session_server_new2(&session, &callbacks, NULL, option);
11980
11981 open_recv_stream(session, 1);
11982
11983 nghttp2_session_close_stream(session, 1, NGHTTP2_NO_ERROR);
11984
11985 assert_size(0, ==, session->num_closed_streams);
11986
11987 nghttp2_session_del(session);
11988 nghttp2_option_del(option);
11989 }
11990
test_nghttp2_session_set_stream_user_data(void)11991 void test_nghttp2_session_set_stream_user_data(void) {
11992 nghttp2_session *session;
11993 nghttp2_session_callbacks callbacks;
11994 int32_t stream_id;
11995 int user_data1, user_data2;
11996 int rv;
11997 const uint8_t *datap;
11998 nghttp2_ssize datalen;
11999
12000 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
12001
12002 nghttp2_session_client_new(&session, &callbacks, NULL);
12003
12004 stream_id = nghttp2_submit_request2(session, NULL, reqnv, ARRLEN(reqnv), NULL,
12005 &user_data1);
12006
12007 rv = nghttp2_session_set_stream_user_data(session, stream_id, &user_data2);
12008
12009 assert_int(0, ==, rv);
12010
12011 datalen = nghttp2_session_mem_send2(session, &datap);
12012
12013 assert_ptrdiff(0, <, datalen);
12014
12015 assert_ptr_equal(&user_data2,
12016 nghttp2_session_get_stream_user_data(session, stream_id));
12017
12018 assert_int(NGHTTP2_ERR_INVALID_ARGUMENT, ==,
12019 nghttp2_session_set_stream_user_data(session, 2, NULL));
12020
12021 nghttp2_session_del(session);
12022 }
12023
test_nghttp2_session_no_rfc7540_priorities(void)12024 void test_nghttp2_session_no_rfc7540_priorities(void) {
12025 nghttp2_session *session;
12026 nghttp2_session_callbacks callbacks;
12027 nghttp2_data_provider2 data_prd;
12028 my_user_data ud;
12029 nghttp2_outbound_item *item;
12030 nghttp2_mem *mem;
12031 nghttp2_settings_entry iv;
12032 nghttp2_priority_spec pri_spec;
12033
12034 mem = nghttp2_mem_default();
12035
12036 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
12037 callbacks.send_callback2 = null_send_callback;
12038
12039 /* Do not use a dependency tree if SETTINGS_NO_RFC7540_PRIORITIES =
12040 1. */
12041 data_prd.read_callback = fixed_length_data_source_read_callback;
12042
12043 ud.data_source_length = 128 * 1024;
12044 assert_int(0, ==, nghttp2_session_server_new(&session, &callbacks, &ud));
12045
12046 iv.settings_id = NGHTTP2_SETTINGS_NO_RFC7540_PRIORITIES;
12047 iv.value = 1;
12048
12049 assert_int(0, ==,
12050 nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, &iv, 1));
12051 assert_int(0, ==, nghttp2_session_send(session));
12052
12053 open_recv_stream2(session, 1, NGHTTP2_STREAM_OPENING);
12054 assert_int(
12055 0, ==,
12056 nghttp2_submit_response2(session, 1, resnv, ARRLEN(resnv), &data_prd));
12057 item = nghttp2_session_get_next_ob_item(session);
12058 assert_size(ARRLEN(resnv), ==, item->frame.headers.nvlen);
12059 assert_nv_equal(resnv, item->frame.headers.nva, item->frame.headers.nvlen,
12060 mem);
12061
12062 assert_int(0, ==, nghttp2_session_send(session));
12063 assert_size(
12064 1, ==,
12065 nghttp2_pq_size(&session->sched[NGHTTP2_EXTPRI_DEFAULT_URGENCY].ob_data));
12066 assert_true(nghttp2_pq_empty(&session->root.obq));
12067
12068 nghttp2_session_del(session);
12069
12070 /* Priorities are sent as is before client receives
12071 SETTINGS_NO_RFC7540_PRIORITIES = 1 from server. */
12072 assert_int(0, ==, nghttp2_session_client_new(&session, &callbacks, NULL));
12073
12074 iv.settings_id = NGHTTP2_SETTINGS_NO_RFC7540_PRIORITIES;
12075 iv.value = 1;
12076
12077 assert_int(0, ==,
12078 nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, &iv, 1));
12079
12080 pri_spec.stream_id = 5;
12081 pri_spec.weight = 111;
12082 pri_spec.exclusive = 1;
12083
12084 assert_int32(1, ==,
12085 nghttp2_submit_request2(session, &pri_spec, reqnv, ARRLEN(reqnv),
12086 NULL, NULL));
12087
12088 item = nghttp2_outbound_queue_top(&session->ob_syn);
12089
12090 assert_not_null(item);
12091 assert_uint8(NGHTTP2_HEADERS, ==, item->frame.hd.type);
12092 assert_int32(pri_spec.stream_id, ==, item->frame.headers.pri_spec.stream_id);
12093 assert_int32(pri_spec.weight, ==, item->frame.headers.pri_spec.weight);
12094 assert_uint8(pri_spec.exclusive, ==, item->frame.headers.pri_spec.exclusive);
12095
12096 nghttp2_session_del(session);
12097
12098 /* Priorities are defaulted if client received
12099 SETTINGS_NO_RFC7540_PRIORITIES = 1 from server. */
12100 assert_int(0, ==, nghttp2_session_client_new(&session, &callbacks, NULL));
12101
12102 iv.settings_id = NGHTTP2_SETTINGS_NO_RFC7540_PRIORITIES;
12103 iv.value = 1;
12104
12105 assert_int(0, ==,
12106 nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, &iv, 1));
12107
12108 session->remote_settings.no_rfc7540_priorities = 1;
12109
12110 pri_spec.stream_id = 5;
12111 pri_spec.weight = 111;
12112 pri_spec.exclusive = 1;
12113
12114 assert_int32(1, ==,
12115 nghttp2_submit_request2(session, &pri_spec, reqnv, ARRLEN(reqnv),
12116 NULL, NULL));
12117
12118 item = nghttp2_outbound_queue_top(&session->ob_syn);
12119
12120 assert_not_null(item);
12121 assert_uint8(NGHTTP2_HEADERS, ==, item->frame.hd.type);
12122 assert_true(
12123 nghttp2_priority_spec_check_default(&item->frame.headers.pri_spec));
12124
12125 nghttp2_session_del(session);
12126 }
12127
test_nghttp2_session_server_fallback_rfc7540_priorities(void)12128 void test_nghttp2_session_server_fallback_rfc7540_priorities(void) {
12129 nghttp2_session *session;
12130 nghttp2_option *option;
12131 nghttp2_session_callbacks callbacks;
12132 nghttp2_frame frame;
12133 nghttp2_bufs bufs;
12134 nghttp2_buf *buf;
12135 nghttp2_ssize rv;
12136 nghttp2_settings_entry iv;
12137 nghttp2_mem *mem;
12138 nghttp2_hd_deflater deflater;
12139 nghttp2_nv *nva;
12140 size_t nvlen;
12141 nghttp2_priority_spec pri_spec;
12142 nghttp2_stream *anchor_stream, *stream;
12143 my_user_data ud;
12144 nghttp2_ext_priority_update priority_update;
12145 static const uint8_t field_value[] = "u=0";
12146
12147 mem = nghttp2_mem_default();
12148 frame_pack_bufs_init(&bufs);
12149
12150 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
12151 callbacks.send_callback2 = null_send_callback;
12152 callbacks.on_frame_recv_callback = on_frame_recv_callback;
12153
12154 nghttp2_option_new(&option);
12155 nghttp2_option_set_server_fallback_rfc7540_priorities(option, 1);
12156
12157 iv.settings_id = NGHTTP2_SETTINGS_NO_RFC7540_PRIORITIES;
12158 iv.value = 1;
12159
12160 /* Server falls back to RFC 7540 priorities. */
12161 nghttp2_session_server_new2(&session, &callbacks, &ud, option);
12162
12163 rv = nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, &iv, 1);
12164
12165 assert_ptrdiff(0, ==, rv);
12166
12167 rv = nghttp2_session_send(session);
12168
12169 assert_ptrdiff(0, ==, rv);
12170
12171 nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE, NULL, 0);
12172 rv = nghttp2_frame_pack_settings(&bufs, &frame.settings);
12173
12174 assert_ptrdiff(0, ==, rv);
12175
12176 nghttp2_frame_settings_free(&frame.settings, mem);
12177
12178 buf = &bufs.head->buf;
12179 rv = nghttp2_session_mem_recv2(session, buf->pos, nghttp2_buf_len(buf));
12180
12181 assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(buf), ==, rv);
12182 assert_true(session->fallback_rfc7540_priorities);
12183
12184 nghttp2_hd_deflate_init(&deflater, mem);
12185
12186 nvlen = ARRLEN(reqnv);
12187 nghttp2_nv_array_copy(&nva, reqnv, nvlen, mem);
12188 nghttp2_priority_spec_init(&pri_spec, 3, 111, 1);
12189 nghttp2_frame_headers_init(&frame.headers,
12190 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PRIORITY,
12191 1, NGHTTP2_HCAT_HEADERS, &pri_spec, nva, nvlen);
12192 nghttp2_bufs_reset(&bufs);
12193 rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
12194
12195 assert_ptrdiff(0, ==, rv);
12196
12197 nghttp2_frame_headers_free(&frame.headers, mem);
12198
12199 buf = &bufs.head->buf;
12200 rv = nghttp2_session_mem_recv2(session, buf->pos, nghttp2_buf_len(buf));
12201
12202 assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(buf), ==, rv);
12203
12204 anchor_stream = nghttp2_session_get_stream_raw(session, 3);
12205
12206 assert_enum(nghttp2_stream_state, NGHTTP2_STREAM_IDLE, ==,
12207 anchor_stream->state);
12208 assert_false(anchor_stream->flags &
12209 NGHTTP2_STREAM_FLAG_NO_RFC7540_PRIORITIES);
12210 assert_ptr_equal(&session->root, anchor_stream->dep_prev);
12211
12212 stream = nghttp2_session_get_stream(session, 1);
12213
12214 assert_enum(nghttp2_stream_state, NGHTTP2_STREAM_OPENING, ==, stream->state);
12215 assert_false(stream->flags & NGHTTP2_STREAM_FLAG_NO_RFC7540_PRIORITIES);
12216 assert_ptr_equal(anchor_stream, stream->dep_prev);
12217
12218 /* Make sure that PRIORITY frame updates stream priority. */
12219 nghttp2_priority_spec_init(&pri_spec, 5, 1, 0);
12220 nghttp2_frame_priority_init(&frame.priority, 1, &pri_spec);
12221 nghttp2_bufs_reset(&bufs);
12222 nghttp2_frame_pack_priority(&bufs, &frame.priority);
12223
12224 nghttp2_frame_priority_free(&frame.priority);
12225
12226 buf = &bufs.head->buf;
12227 rv = nghttp2_session_mem_recv2(session, buf->pos, nghttp2_buf_len(buf));
12228
12229 assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(buf), ==, rv);
12230
12231 anchor_stream = nghttp2_session_get_stream_raw(session, 5);
12232
12233 assert_enum(nghttp2_stream_state, NGHTTP2_STREAM_IDLE, ==,
12234 anchor_stream->state);
12235 assert_ptr_equal(&session->root, anchor_stream->dep_prev);
12236 assert_ptr_equal(anchor_stream, stream->dep_prev);
12237
12238 /* Make sure that PRIORITY_UPDATE frame is ignored. */
12239 frame.ext.payload = &priority_update;
12240 nghttp2_frame_priority_update_init(&frame.ext, 1, (uint8_t *)field_value,
12241 sizeof(field_value) - 1);
12242 nghttp2_bufs_reset(&bufs);
12243 nghttp2_frame_pack_priority_update(&bufs, &frame.ext);
12244
12245 ud.frame_recv_cb_called = 0;
12246 buf = &bufs.head->buf;
12247 rv = nghttp2_session_mem_recv2(session, buf->pos, nghttp2_buf_len(buf));
12248
12249 assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(buf), ==, rv);
12250 assert_int(0, ==, ud.frame_recv_cb_called);
12251 assert_uint32(NGHTTP2_EXTPRI_DEFAULT_URGENCY, ==, stream->extpri);
12252
12253 nghttp2_hd_deflate_free(&deflater);
12254 nghttp2_session_del(session);
12255
12256 /* Server does not fallback to RFC 7540 priorities. */
12257 nghttp2_session_server_new2(&session, &callbacks, &ud, option);
12258
12259 rv = nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, &iv, 1);
12260
12261 assert_ptrdiff(0, ==, rv);
12262
12263 rv = nghttp2_session_send(session);
12264
12265 assert_ptrdiff(0, ==, rv);
12266
12267 iv.settings_id = NGHTTP2_SETTINGS_NO_RFC7540_PRIORITIES;
12268 iv.value = 0;
12269
12270 nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE,
12271 dup_iv(&iv, 1), 1);
12272 nghttp2_bufs_reset(&bufs);
12273 rv = nghttp2_frame_pack_settings(&bufs, &frame.settings);
12274
12275 assert_ptrdiff(0, ==, rv);
12276
12277 nghttp2_frame_settings_free(&frame.settings, mem);
12278
12279 buf = &bufs.head->buf;
12280 rv = nghttp2_session_mem_recv2(session, buf->pos, nghttp2_buf_len(buf));
12281
12282 assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(buf), ==, rv);
12283 assert_false(session->fallback_rfc7540_priorities);
12284
12285 nghttp2_hd_deflate_init(&deflater, mem);
12286
12287 nvlen = ARRLEN(reqnv);
12288 nghttp2_nv_array_copy(&nva, reqnv, nvlen, mem);
12289 nghttp2_priority_spec_init(&pri_spec, 3, 111, 1);
12290 nghttp2_frame_headers_init(&frame.headers,
12291 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PRIORITY,
12292 1, NGHTTP2_HCAT_HEADERS, &pri_spec, nva, nvlen);
12293 nghttp2_bufs_reset(&bufs);
12294 rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
12295
12296 assert_ptrdiff(0, ==, rv);
12297
12298 nghttp2_frame_headers_free(&frame.headers, mem);
12299
12300 buf = &bufs.head->buf;
12301 rv = nghttp2_session_mem_recv2(session, buf->pos, nghttp2_buf_len(buf));
12302
12303 assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(buf), ==, rv);
12304 assert_null(nghttp2_session_get_stream_raw(session, 3));
12305
12306 stream = nghttp2_session_get_stream(session, 1);
12307
12308 assert_enum(nghttp2_stream_state, NGHTTP2_STREAM_OPENING, ==, stream->state);
12309 assert_true(stream->flags & NGHTTP2_STREAM_FLAG_NO_RFC7540_PRIORITIES);
12310
12311 nghttp2_hd_deflate_free(&deflater);
12312 nghttp2_session_del(session);
12313
12314 nghttp2_option_del(option);
12315 nghttp2_bufs_free(&bufs);
12316 }
12317
test_nghttp2_session_stream_reset_ratelim(void)12318 void test_nghttp2_session_stream_reset_ratelim(void) {
12319 nghttp2_session *session;
12320 nghttp2_session_callbacks callbacks;
12321 nghttp2_frame frame;
12322 nghttp2_ssize rv;
12323 nghttp2_bufs bufs;
12324 nghttp2_buf *buf;
12325 nghttp2_mem *mem;
12326 size_t i;
12327 nghttp2_hd_deflater deflater;
12328 size_t nvlen;
12329 nghttp2_nv *nva;
12330 int32_t stream_id;
12331 nghttp2_outbound_item *item;
12332 nghttp2_option *option;
12333
12334 mem = nghttp2_mem_default();
12335 frame_pack_bufs_init(&bufs);
12336
12337 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
12338 callbacks.send_callback2 = null_send_callback;
12339
12340 nghttp2_option_new(&option);
12341 nghttp2_option_set_stream_reset_rate_limit(
12342 option, NGHTTP2_DEFAULT_STREAM_RESET_BURST, 0);
12343
12344 nghttp2_session_server_new2(&session, &callbacks, NULL, option);
12345
12346 nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE, NULL, 0);
12347 rv = nghttp2_frame_pack_settings(&bufs, &frame.settings);
12348
12349 assert_ptrdiff(0, ==, rv);
12350
12351 nghttp2_frame_settings_free(&frame.settings, mem);
12352
12353 buf = &bufs.head->buf;
12354 rv = nghttp2_session_mem_recv2(session, buf->pos, nghttp2_buf_len(buf));
12355
12356 assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(buf), ==, rv);
12357
12358 /* Send SETTINGS ACK */
12359 rv = nghttp2_session_send(session);
12360
12361 assert_ptrdiff(0, ==, rv);
12362
12363 nghttp2_hd_deflate_init(&deflater, mem);
12364
12365 for (i = 0; i < NGHTTP2_DEFAULT_STREAM_RESET_BURST + 2; ++i) {
12366 stream_id = (int32_t)(i * 2 + 1);
12367
12368 nghttp2_bufs_reset(&bufs);
12369
12370 /* HEADERS */
12371 nvlen = ARRLEN(reqnv);
12372 nghttp2_nv_array_copy(&nva, reqnv, nvlen, mem);
12373 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS,
12374 stream_id, NGHTTP2_HCAT_HEADERS, NULL, nva,
12375 nvlen);
12376 rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
12377
12378 assert_ptrdiff(0, ==, rv);
12379
12380 nghttp2_frame_headers_free(&frame.headers, mem);
12381
12382 buf = &bufs.head->buf;
12383 rv = nghttp2_session_mem_recv2(session, buf->pos, nghttp2_buf_len(buf));
12384
12385 assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(buf), ==, rv);
12386
12387 nghttp2_bufs_reset(&bufs);
12388
12389 /* RST_STREAM */
12390 nghttp2_frame_rst_stream_init(&frame.rst_stream, stream_id,
12391 NGHTTP2_NO_ERROR);
12392 nghttp2_frame_pack_rst_stream(&bufs, &frame.rst_stream);
12393 nghttp2_frame_rst_stream_free(&frame.rst_stream);
12394
12395 buf = &bufs.head->buf;
12396 rv = nghttp2_session_mem_recv2(session, buf->pos, nghttp2_buf_len(buf));
12397
12398 assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(buf), ==, rv);
12399
12400 if (i < NGHTTP2_DEFAULT_STREAM_RESET_BURST) {
12401 assert_size(0, ==, nghttp2_outbound_queue_size(&session->ob_reg));
12402
12403 continue;
12404 }
12405
12406 assert_size(1, ==, nghttp2_outbound_queue_size(&session->ob_reg));
12407
12408 item = nghttp2_session_get_next_ob_item(session);
12409
12410 assert_uint8(NGHTTP2_GOAWAY, ==, item->frame.hd.type);
12411 assert_int32(NGHTTP2_DEFAULT_STREAM_RESET_BURST * 2 + 1, ==,
12412 item->frame.goaway.last_stream_id);
12413 }
12414
12415 nghttp2_hd_deflate_free(&deflater);
12416 nghttp2_session_del(session);
12417 nghttp2_bufs_free(&bufs);
12418 nghttp2_option_del(option);
12419 }
12420
check_nghttp2_http_recv_headers_fail(nghttp2_session * session,nghttp2_hd_deflater * deflater,int32_t stream_id,int stream_state,const nghttp2_nv * nva,size_t nvlen)12421 static void check_nghttp2_http_recv_headers_fail(
12422 nghttp2_session *session, nghttp2_hd_deflater *deflater, int32_t stream_id,
12423 int stream_state, const nghttp2_nv *nva, size_t nvlen) {
12424 nghttp2_mem *mem;
12425 nghttp2_ssize rv;
12426 nghttp2_outbound_item *item;
12427 nghttp2_bufs bufs;
12428 my_user_data *ud;
12429
12430 mem = nghttp2_mem_default();
12431 frame_pack_bufs_init(&bufs);
12432
12433 ud = session->user_data;
12434
12435 if (stream_state != -1) {
12436 if (nghttp2_session_is_my_stream_id(session, stream_id)) {
12437 open_sent_stream2(session, stream_id, (nghttp2_stream_state)stream_state);
12438 } else {
12439 open_recv_stream2(session, stream_id, (nghttp2_stream_state)stream_state);
12440 }
12441 }
12442
12443 rv = pack_headers(&bufs, deflater, stream_id, NGHTTP2_FLAG_END_HEADERS, nva,
12444 nvlen, mem);
12445 assert_ptrdiff(0, ==, rv);
12446
12447 ud->invalid_frame_recv_cb_called = 0;
12448
12449 rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
12450 nghttp2_buf_len(&bufs.head->buf));
12451
12452 assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(&bufs.head->buf), ==, rv);
12453
12454 item = nghttp2_session_get_next_ob_item(session);
12455
12456 assert_uint8(NGHTTP2_RST_STREAM, ==, item->frame.hd.type);
12457 assert_ptrdiff(1, ==, ud->invalid_frame_recv_cb_called);
12458
12459 assert_int(0, ==, nghttp2_session_send(session));
12460
12461 nghttp2_bufs_free(&bufs);
12462 }
12463
check_nghttp2_http_recv_headers_ok(nghttp2_session * session,nghttp2_hd_deflater * deflater,int32_t stream_id,int stream_state,const nghttp2_nv * nva,size_t nvlen)12464 static void check_nghttp2_http_recv_headers_ok(
12465 nghttp2_session *session, nghttp2_hd_deflater *deflater, int32_t stream_id,
12466 int stream_state, const nghttp2_nv *nva, size_t nvlen) {
12467 nghttp2_mem *mem;
12468 nghttp2_ssize rv;
12469 nghttp2_bufs bufs;
12470 my_user_data *ud;
12471
12472 mem = nghttp2_mem_default();
12473 frame_pack_bufs_init(&bufs);
12474
12475 ud = session->user_data;
12476
12477 if (stream_state != -1) {
12478 if (nghttp2_session_is_my_stream_id(session, stream_id)) {
12479 open_sent_stream2(session, stream_id, (nghttp2_stream_state)stream_state);
12480 } else {
12481 open_recv_stream2(session, stream_id, (nghttp2_stream_state)stream_state);
12482 }
12483 }
12484
12485 rv = pack_headers(&bufs, deflater, stream_id, NGHTTP2_FLAG_END_HEADERS, nva,
12486 nvlen, mem);
12487 assert_ptrdiff(0, ==, rv);
12488
12489 ud->frame_recv_cb_called = 0;
12490
12491 rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
12492 nghttp2_buf_len(&bufs.head->buf));
12493
12494 assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(&bufs.head->buf), ==, rv);
12495 assert_null(nghttp2_session_get_next_ob_item(session));
12496 assert_int(1, ==, ud->frame_recv_cb_called);
12497
12498 nghttp2_bufs_free(&bufs);
12499 }
12500
test_nghttp2_http_mandatory_headers(void)12501 void test_nghttp2_http_mandatory_headers(void) {
12502 nghttp2_session *session;
12503 nghttp2_session_callbacks callbacks;
12504 nghttp2_hd_deflater deflater;
12505 nghttp2_mem *mem;
12506 my_user_data ud;
12507 /* test case for response */
12508 const nghttp2_nv nostatus_resnv[] = {MAKE_NV("server", "foo")};
12509 const nghttp2_nv dupstatus_resnv[] = {MAKE_NV(":status", "200"),
12510 MAKE_NV(":status", "200")};
12511 const nghttp2_nv badpseudo_resnv[] = {MAKE_NV(":status", "200"),
12512 MAKE_NV(":scheme", "https")};
12513 const nghttp2_nv latepseudo_resnv[] = {MAKE_NV("server", "foo"),
12514 MAKE_NV(":status", "200")};
12515 const nghttp2_nv badstatus_resnv[] = {MAKE_NV(":status", "2000")};
12516 const nghttp2_nv badcl_resnv[] = {MAKE_NV(":status", "200"),
12517 MAKE_NV("content-length", "-1")};
12518 const nghttp2_nv dupcl_resnv[] = {MAKE_NV(":status", "200"),
12519 MAKE_NV("content-length", "0"),
12520 MAKE_NV("content-length", "0")};
12521 const nghttp2_nv badhd_resnv[] = {MAKE_NV(":status", "200"),
12522 MAKE_NV("connection", "close")};
12523 const nghttp2_nv cl1xx_resnv[] = {MAKE_NV(":status", "100"),
12524 MAKE_NV("content-length", "0")};
12525 const nghttp2_nv cl204_resnv[] = {MAKE_NV(":status", "204"),
12526 MAKE_NV("content-length", "0")};
12527 const nghttp2_nv clnonzero204_resnv[] = {MAKE_NV(":status", "204"),
12528 MAKE_NV("content-length", "100")};
12529 const nghttp2_nv status101_resnv[] = {MAKE_NV(":status", "101")};
12530 const nghttp2_nv unexpectedhost_resnv[] = {MAKE_NV(":status", "200"),
12531 MAKE_NV("host", "/localhost")};
12532
12533 /* test case for request */
12534 const nghttp2_nv nopath_reqnv[] = {MAKE_NV(":scheme", "https"),
12535 MAKE_NV(":method", "GET"),
12536 MAKE_NV(":authority", "localhost")};
12537 const nghttp2_nv earlyconnect_reqnv[] = {
12538 MAKE_NV(":method", "CONNECT"), MAKE_NV(":scheme", "https"),
12539 MAKE_NV(":path", "/"), MAKE_NV(":authority", "localhost")};
12540 const nghttp2_nv lateconnect_reqnv[] = {
12541 MAKE_NV(":scheme", "https"), MAKE_NV(":path", "/"),
12542 MAKE_NV(":method", "CONNECT"), MAKE_NV(":authority", "localhost")};
12543 const nghttp2_nv duppath_reqnv[] = {
12544 MAKE_NV(":scheme", "https"), MAKE_NV(":method", "GET"),
12545 MAKE_NV(":authority", "localhost"), MAKE_NV(":path", "/"),
12546 MAKE_NV(":path", "/")};
12547 const nghttp2_nv badcl_reqnv[] = {
12548 MAKE_NV(":scheme", "https"), MAKE_NV(":method", "POST"),
12549 MAKE_NV(":authority", "localhost"), MAKE_NV(":path", "/"),
12550 MAKE_NV("content-length", "-1")};
12551 const nghttp2_nv dupcl_reqnv[] = {
12552 MAKE_NV(":scheme", "https"), MAKE_NV(":method", "POST"),
12553 MAKE_NV(":authority", "localhost"), MAKE_NV(":path", "/"),
12554 MAKE_NV("content-length", "0"), MAKE_NV("content-length", "0")};
12555 const nghttp2_nv badhd_reqnv[] = {
12556 MAKE_NV(":scheme", "https"), MAKE_NV(":method", "GET"),
12557 MAKE_NV(":authority", "localhost"), MAKE_NV(":path", "/"),
12558 MAKE_NV("connection", "close")};
12559 const nghttp2_nv badauthority_reqnv[] = {
12560 MAKE_NV(":scheme", "https"), MAKE_NV(":method", "GET"),
12561 MAKE_NV(":authority", "\x0d\x0alocalhost"), MAKE_NV(":path", "/")};
12562 const nghttp2_nv badhdbtw_reqnv[] = {
12563 MAKE_NV(":scheme", "https"), MAKE_NV(":method", "GET"),
12564 MAKE_NV("foo", "\x0d\x0a"), MAKE_NV(":authority", "localhost"),
12565 MAKE_NV(":path", "/")};
12566 const nghttp2_nv asteriskget1_reqnv[] = {
12567 MAKE_NV(":path", "*"), MAKE_NV(":scheme", "https"),
12568 MAKE_NV(":authority", "localhost"), MAKE_NV(":method", "GET")};
12569 const nghttp2_nv asteriskget2_reqnv[] = {
12570 MAKE_NV(":scheme", "https"), MAKE_NV(":authority", "localhost"),
12571 MAKE_NV(":method", "GET"), MAKE_NV(":path", "*")};
12572 const nghttp2_nv asteriskoptions1_reqnv[] = {
12573 MAKE_NV(":path", "*"), MAKE_NV(":scheme", "https"),
12574 MAKE_NV(":authority", "localhost"), MAKE_NV(":method", "OPTIONS")};
12575 const nghttp2_nv asteriskoptions2_reqnv[] = {
12576 MAKE_NV(":scheme", "https"), MAKE_NV(":authority", "localhost"),
12577 MAKE_NV(":method", "OPTIONS"), MAKE_NV(":path", "*")};
12578 const nghttp2_nv connectproto_reqnv[] = {
12579 MAKE_NV(":scheme", "https"), MAKE_NV(":path", "/"),
12580 MAKE_NV(":method", "CONNECT"), MAKE_NV(":authority", "localhost"),
12581 MAKE_NV(":protocol", "websocket")};
12582 const nghttp2_nv connectprotoget_reqnv[] = {
12583 MAKE_NV(":scheme", "https"), MAKE_NV(":path", "/"),
12584 MAKE_NV(":method", "GET"), MAKE_NV(":authority", "localhost"),
12585 MAKE_NV(":protocol", "websocket")};
12586 const nghttp2_nv connectprotonopath_reqnv[] = {
12587 MAKE_NV(":scheme", "https"), MAKE_NV(":method", "CONNECT"),
12588 MAKE_NV(":authority", "localhost"), MAKE_NV(":protocol", "websocket")};
12589 const nghttp2_nv connectprotonoauth_reqnv[] = {
12590 MAKE_NV(":scheme", "http"), MAKE_NV(":path", "/"),
12591 MAKE_NV(":method", "CONNECT"), MAKE_NV("host", "localhost"),
12592 MAKE_NV(":protocol", "websocket")};
12593 const nghttp2_nv regularconnect_reqnv[] = {
12594 MAKE_NV(":method", "CONNECT"), MAKE_NV(":authority", "localhost")};
12595
12596 mem = nghttp2_mem_default();
12597
12598 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
12599 callbacks.send_callback2 = null_send_callback;
12600 callbacks.on_frame_recv_callback = on_frame_recv_callback;
12601 callbacks.on_invalid_frame_recv_callback = on_invalid_frame_recv_callback;
12602
12603 nghttp2_session_client_new(&session, &callbacks, &ud);
12604
12605 nghttp2_hd_deflate_init(&deflater, mem);
12606
12607 /* response header lacks :status */
12608 check_nghttp2_http_recv_headers_fail(session, &deflater, 1,
12609 NGHTTP2_STREAM_OPENING, nostatus_resnv,
12610 ARRLEN(nostatus_resnv));
12611
12612 /* response header has 2 :status */
12613 check_nghttp2_http_recv_headers_fail(session, &deflater, 3,
12614 NGHTTP2_STREAM_OPENING, dupstatus_resnv,
12615 ARRLEN(dupstatus_resnv));
12616
12617 /* response header has bad pseudo header :scheme */
12618 check_nghttp2_http_recv_headers_fail(session, &deflater, 5,
12619 NGHTTP2_STREAM_OPENING, badpseudo_resnv,
12620 ARRLEN(badpseudo_resnv));
12621
12622 /* response header has :status after regular header field */
12623 check_nghttp2_http_recv_headers_fail(session, &deflater, 7,
12624 NGHTTP2_STREAM_OPENING, latepseudo_resnv,
12625 ARRLEN(latepseudo_resnv));
12626
12627 /* response header has bad status code */
12628 check_nghttp2_http_recv_headers_fail(session, &deflater, 9,
12629 NGHTTP2_STREAM_OPENING, badstatus_resnv,
12630 ARRLEN(badstatus_resnv));
12631
12632 /* response header has bad content-length */
12633 check_nghttp2_http_recv_headers_fail(session, &deflater, 11,
12634 NGHTTP2_STREAM_OPENING, badcl_resnv,
12635 ARRLEN(badcl_resnv));
12636
12637 /* response header has multiple content-length */
12638 check_nghttp2_http_recv_headers_fail(session, &deflater, 13,
12639 NGHTTP2_STREAM_OPENING, dupcl_resnv,
12640 ARRLEN(dupcl_resnv));
12641
12642 /* response header has disallowed header field */
12643 check_nghttp2_http_recv_headers_fail(session, &deflater, 15,
12644 NGHTTP2_STREAM_OPENING, badhd_resnv,
12645 ARRLEN(badhd_resnv));
12646
12647 /* response header has content-length with 100 status code */
12648 check_nghttp2_http_recv_headers_fail(session, &deflater, 17,
12649 NGHTTP2_STREAM_OPENING, cl1xx_resnv,
12650 ARRLEN(cl1xx_resnv));
12651
12652 /* response header has 0 content-length with 204 status code */
12653 check_nghttp2_http_recv_headers_ok(session, &deflater, 19,
12654 NGHTTP2_STREAM_OPENING, cl204_resnv,
12655 ARRLEN(cl204_resnv));
12656
12657 /* response header has nonzero content-length with 204 status
12658 code */
12659 check_nghttp2_http_recv_headers_fail(
12660 session, &deflater, 21, NGHTTP2_STREAM_OPENING, clnonzero204_resnv,
12661 ARRLEN(clnonzero204_resnv));
12662
12663 /* status code 101 should not be used in HTTP/2 because it is used
12664 for HTTP Upgrade which HTTP/2 removes. */
12665 check_nghttp2_http_recv_headers_fail(session, &deflater, 23,
12666 NGHTTP2_STREAM_OPENING, status101_resnv,
12667 ARRLEN(status101_resnv));
12668
12669 /* Specific characters check for host field in response header
12670 should not be done as its use is undefined. */
12671 check_nghttp2_http_recv_headers_ok(
12672 session, &deflater, 25, NGHTTP2_STREAM_OPENING, unexpectedhost_resnv,
12673 ARRLEN(unexpectedhost_resnv));
12674
12675 nghttp2_hd_deflate_free(&deflater);
12676
12677 nghttp2_session_del(session);
12678
12679 /* check server side */
12680 nghttp2_session_server_new(&session, &callbacks, &ud);
12681
12682 nghttp2_hd_deflate_init(&deflater, mem);
12683
12684 /* request header has no :path */
12685 check_nghttp2_http_recv_headers_fail(session, &deflater, 1, -1, nopath_reqnv,
12686 ARRLEN(nopath_reqnv));
12687
12688 /* request header has CONNECT method, but followed by :path */
12689 check_nghttp2_http_recv_headers_fail(
12690 session, &deflater, 3, -1, earlyconnect_reqnv, ARRLEN(earlyconnect_reqnv));
12691
12692 /* request header has CONNECT method following :path */
12693 check_nghttp2_http_recv_headers_fail(
12694 session, &deflater, 5, -1, lateconnect_reqnv, ARRLEN(lateconnect_reqnv));
12695
12696 /* request header has multiple :path */
12697 check_nghttp2_http_recv_headers_fail(session, &deflater, 7, -1, duppath_reqnv,
12698 ARRLEN(duppath_reqnv));
12699
12700 /* request header has bad content-length */
12701 check_nghttp2_http_recv_headers_fail(session, &deflater, 9, -1, badcl_reqnv,
12702 ARRLEN(badcl_reqnv));
12703
12704 /* request header has multiple content-length */
12705 check_nghttp2_http_recv_headers_fail(session, &deflater, 11, -1, dupcl_reqnv,
12706 ARRLEN(dupcl_reqnv));
12707
12708 /* request header has disallowed header field */
12709 check_nghttp2_http_recv_headers_fail(session, &deflater, 13, -1, badhd_reqnv,
12710 ARRLEN(badhd_reqnv));
12711
12712 /* request header has :authority header field containing illegal
12713 characters */
12714 check_nghttp2_http_recv_headers_fail(
12715 session, &deflater, 15, -1, badauthority_reqnv, ARRLEN(badauthority_reqnv));
12716
12717 /* request header has regular header field containing illegal
12718 character before all mandatory header fields are seen. */
12719 check_nghttp2_http_recv_headers_fail(session, &deflater, 17, -1,
12720 badhdbtw_reqnv, ARRLEN(badhdbtw_reqnv));
12721
12722 /* request header has "*" in :path header field while method is GET.
12723 :path is received before :method */
12724 check_nghttp2_http_recv_headers_fail(
12725 session, &deflater, 19, -1, asteriskget1_reqnv, ARRLEN(asteriskget1_reqnv));
12726
12727 /* request header has "*" in :path header field while method is GET.
12728 :method is received before :path */
12729 check_nghttp2_http_recv_headers_fail(
12730 session, &deflater, 21, -1, asteriskget2_reqnv, ARRLEN(asteriskget2_reqnv));
12731
12732 /* OPTIONS method can include "*" in :path header field. :path is
12733 received before :method. */
12734 check_nghttp2_http_recv_headers_ok(session, &deflater, 23, -1,
12735 asteriskoptions1_reqnv,
12736 ARRLEN(asteriskoptions1_reqnv));
12737
12738 /* OPTIONS method can include "*" in :path header field. :method is
12739 received before :path. */
12740 check_nghttp2_http_recv_headers_ok(session, &deflater, 25, -1,
12741 asteriskoptions2_reqnv,
12742 ARRLEN(asteriskoptions2_reqnv));
12743
12744 /* :protocol is not allowed unless it is enabled by the local
12745 endpoint. */
12746 check_nghttp2_http_recv_headers_fail(
12747 session, &deflater, 27, -1, connectproto_reqnv, ARRLEN(connectproto_reqnv));
12748
12749 nghttp2_hd_deflate_free(&deflater);
12750
12751 nghttp2_session_del(session);
12752
12753 /* enable SETTINGS_CONNECT_PROTOCOL */
12754 nghttp2_session_server_new(&session, &callbacks, &ud);
12755
12756 session->pending_enable_connect_protocol = 1;
12757
12758 nghttp2_hd_deflate_init(&deflater, mem);
12759
12760 /* :protocol is allowed if SETTINGS_CONNECT_PROTOCOL is enabled by
12761 the local endpoint. */
12762 check_nghttp2_http_recv_headers_ok(
12763 session, &deflater, 1, -1, connectproto_reqnv, ARRLEN(connectproto_reqnv));
12764
12765 /* :protocol is only allowed with CONNECT method. */
12766 check_nghttp2_http_recv_headers_fail(session, &deflater, 3, -1,
12767 connectprotoget_reqnv,
12768 ARRLEN(connectprotoget_reqnv));
12769
12770 /* CONNECT method with :protocol requires :path. */
12771 check_nghttp2_http_recv_headers_fail(session, &deflater, 5, -1,
12772 connectprotonopath_reqnv,
12773 ARRLEN(connectprotonopath_reqnv));
12774
12775 /* CONNECT method with :protocol requires :authority. */
12776 check_nghttp2_http_recv_headers_fail(session, &deflater, 7, -1,
12777 connectprotonoauth_reqnv,
12778 ARRLEN(connectprotonoauth_reqnv));
12779
12780 /* regular CONNECT method should succeed with
12781 SETTINGS_CONNECT_PROTOCOL */
12782 check_nghttp2_http_recv_headers_ok(session, &deflater, 9, -1,
12783 regularconnect_reqnv,
12784 ARRLEN(regularconnect_reqnv));
12785
12786 nghttp2_hd_deflate_free(&deflater);
12787
12788 nghttp2_session_del(session);
12789 }
12790
test_nghttp2_http_content_length(void)12791 void test_nghttp2_http_content_length(void) {
12792 nghttp2_session *session;
12793 nghttp2_session_callbacks callbacks;
12794 nghttp2_hd_deflater deflater;
12795 nghttp2_mem *mem;
12796 nghttp2_bufs bufs;
12797 nghttp2_ssize rv;
12798 nghttp2_stream *stream;
12799 const nghttp2_nv cl_resnv[] = {MAKE_NV(":status", "200"),
12800 MAKE_NV("te", "trailers"),
12801 MAKE_NV("content-length", "9000000000")};
12802 const nghttp2_nv cl_reqnv[] = {
12803 MAKE_NV(":path", "/"), MAKE_NV(":method", "PUT"),
12804 MAKE_NV(":scheme", "https"), MAKE_NV("te", "trailers"),
12805 MAKE_NV("host", "localhost"), MAKE_NV("content-length", "9000000000")};
12806
12807 mem = nghttp2_mem_default();
12808 frame_pack_bufs_init(&bufs);
12809
12810 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
12811 callbacks.send_callback2 = null_send_callback;
12812
12813 nghttp2_session_client_new(&session, &callbacks, NULL);
12814
12815 nghttp2_hd_deflate_init(&deflater, mem);
12816
12817 stream = open_sent_stream2(session, 1, NGHTTP2_STREAM_OPENING);
12818
12819 rv = pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, cl_resnv,
12820 ARRLEN(cl_resnv), mem);
12821 assert_ptrdiff(0, ==, rv);
12822
12823 rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
12824 nghttp2_buf_len(&bufs.head->buf));
12825
12826 assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(&bufs.head->buf), ==, rv);
12827 assert_null(nghttp2_session_get_next_ob_item(session));
12828 assert_int64(9000000000LL, ==, stream->content_length);
12829 assert_int16(200, ==, stream->status_code);
12830
12831 nghttp2_hd_deflate_free(&deflater);
12832
12833 nghttp2_session_del(session);
12834
12835 nghttp2_bufs_reset(&bufs);
12836
12837 /* check server side */
12838 nghttp2_session_server_new(&session, &callbacks, NULL);
12839
12840 nghttp2_hd_deflate_init(&deflater, mem);
12841
12842 rv = pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, cl_reqnv,
12843 ARRLEN(cl_reqnv), mem);
12844 assert_ptrdiff(0, ==, rv);
12845
12846 rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
12847 nghttp2_buf_len(&bufs.head->buf));
12848
12849 assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(&bufs.head->buf), ==, rv);
12850
12851 stream = nghttp2_session_get_stream(session, 1);
12852
12853 assert_null(nghttp2_session_get_next_ob_item(session));
12854 assert_int64(9000000000LL, ==, stream->content_length);
12855
12856 nghttp2_hd_deflate_free(&deflater);
12857
12858 nghttp2_session_del(session);
12859
12860 nghttp2_bufs_free(&bufs);
12861 }
12862
test_nghttp2_http_content_length_mismatch(void)12863 void test_nghttp2_http_content_length_mismatch(void) {
12864 nghttp2_session *session;
12865 nghttp2_session_callbacks callbacks;
12866 nghttp2_hd_deflater deflater;
12867 nghttp2_mem *mem;
12868 nghttp2_bufs bufs;
12869 nghttp2_ssize rv;
12870 const nghttp2_nv cl_reqnv[] = {
12871 MAKE_NV(":path", "/"), MAKE_NV(":method", "PUT"),
12872 MAKE_NV(":authority", "localhost"), MAKE_NV(":scheme", "https"),
12873 MAKE_NV("content-length", "20")};
12874 const nghttp2_nv cl_resnv[] = {MAKE_NV(":status", "200"),
12875 MAKE_NV("content-length", "20")};
12876 nghttp2_outbound_item *item;
12877 nghttp2_frame_hd hd;
12878
12879 mem = nghttp2_mem_default();
12880 frame_pack_bufs_init(&bufs);
12881
12882 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
12883 callbacks.send_callback2 = null_send_callback;
12884
12885 nghttp2_session_server_new(&session, &callbacks, NULL);
12886
12887 nghttp2_hd_deflate_init(&deflater, mem);
12888
12889 /* header says content-length: 20, but HEADERS has END_STREAM flag set */
12890 rv = pack_headers(&bufs, &deflater, 1,
12891 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM,
12892 cl_reqnv, ARRLEN(cl_reqnv), mem);
12893 assert_ptrdiff(0, ==, rv);
12894
12895 rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
12896 nghttp2_buf_len(&bufs.head->buf));
12897
12898 assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(&bufs.head->buf), ==, rv);
12899
12900 item = nghttp2_session_get_next_ob_item(session);
12901 assert_uint8(NGHTTP2_RST_STREAM, ==, item->frame.hd.type);
12902
12903 assert_int(0, ==, nghttp2_session_send(session));
12904
12905 nghttp2_bufs_reset(&bufs);
12906
12907 /* header says content-length: 20, but DATA has 0 byte */
12908 rv = pack_headers(&bufs, &deflater, 3, NGHTTP2_FLAG_END_HEADERS, cl_reqnv,
12909 ARRLEN(cl_reqnv), mem);
12910 assert_ptrdiff(0, ==, rv);
12911
12912 nghttp2_frame_hd_init(&hd, 0, NGHTTP2_DATA, NGHTTP2_FLAG_END_STREAM, 3);
12913 nghttp2_frame_pack_frame_hd(bufs.head->buf.last, &hd);
12914 bufs.head->buf.last += NGHTTP2_FRAME_HDLEN;
12915
12916 rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
12917 nghttp2_buf_len(&bufs.head->buf));
12918
12919 assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(&bufs.head->buf), ==, rv);
12920
12921 item = nghttp2_session_get_next_ob_item(session);
12922 assert_uint8(NGHTTP2_RST_STREAM, ==, item->frame.hd.type);
12923
12924 assert_int(0, ==, nghttp2_session_send(session));
12925
12926 nghttp2_bufs_reset(&bufs);
12927
12928 /* header says content-length: 20, but DATA has 21 bytes */
12929 rv = pack_headers(&bufs, &deflater, 5, NGHTTP2_FLAG_END_HEADERS, cl_reqnv,
12930 ARRLEN(cl_reqnv), mem);
12931 assert_ptrdiff(0, ==, rv);
12932
12933 nghttp2_frame_hd_init(&hd, 21, NGHTTP2_DATA, NGHTTP2_FLAG_END_STREAM, 5);
12934 nghttp2_frame_pack_frame_hd(bufs.head->buf.last, &hd);
12935 bufs.head->buf.last += NGHTTP2_FRAME_HDLEN + 21;
12936
12937 rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
12938 nghttp2_buf_len(&bufs.head->buf));
12939
12940 assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(&bufs.head->buf), ==, rv);
12941
12942 item = nghttp2_session_get_next_ob_item(session);
12943 assert_uint8(NGHTTP2_RST_STREAM, ==, item->frame.hd.type);
12944
12945 assert_int(0, ==, nghttp2_session_send(session));
12946
12947 nghttp2_bufs_reset(&bufs);
12948
12949 nghttp2_hd_deflate_free(&deflater);
12950
12951 nghttp2_session_del(session);
12952
12953 /* Check for client */
12954 nghttp2_session_client_new(&session, &callbacks, NULL);
12955
12956 nghttp2_hd_deflate_init(&deflater, mem);
12957
12958 /* header says content-length: 20, but HEADERS has END_STREAM flag set */
12959 nghttp2_submit_request2(session, NULL, reqnv, ARRLEN(reqnv), NULL, NULL);
12960
12961 assert_int(0, ==, nghttp2_session_send(session));
12962
12963 rv = pack_headers(&bufs, &deflater, 1,
12964 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM,
12965 cl_resnv, ARRLEN(cl_resnv), mem);
12966 assert_ptrdiff(0, ==, rv);
12967
12968 rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
12969 nghttp2_buf_len(&bufs.head->buf));
12970
12971 assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(&bufs.head->buf), ==, rv);
12972
12973 item = nghttp2_session_get_next_ob_item(session);
12974 assert_uint8(NGHTTP2_RST_STREAM, ==, item->frame.hd.type);
12975
12976 assert_not_null(nghttp2_session_get_stream(session, 1));
12977 assert_int(0, ==, nghttp2_session_send(session));
12978 /* After sending RST_STREAM, stream must be closed */
12979 assert_null(nghttp2_session_get_stream(session, 1));
12980
12981 nghttp2_bufs_reset(&bufs);
12982
12983 /* header says content-length: 20, but DATA has 0 byte */
12984 nghttp2_submit_request2(session, NULL, reqnv, ARRLEN(reqnv), NULL, NULL);
12985
12986 assert_int(0, ==, nghttp2_session_send(session));
12987
12988 rv = pack_headers(&bufs, &deflater, 3, NGHTTP2_FLAG_END_HEADERS, cl_resnv,
12989 ARRLEN(cl_resnv), mem);
12990 assert_ptrdiff(0, ==, rv);
12991
12992 nghttp2_frame_hd_init(&hd, 0, NGHTTP2_DATA, NGHTTP2_FLAG_END_STREAM, 3);
12993 nghttp2_frame_pack_frame_hd(bufs.head->buf.last, &hd);
12994 bufs.head->buf.last += NGHTTP2_FRAME_HDLEN;
12995
12996 rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
12997 nghttp2_buf_len(&bufs.head->buf));
12998
12999 assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(&bufs.head->buf), ==, rv);
13000
13001 item = nghttp2_session_get_next_ob_item(session);
13002 assert_uint8(NGHTTP2_RST_STREAM, ==, item->frame.hd.type);
13003
13004 assert_not_null(nghttp2_session_get_stream(session, 3));
13005 assert_int(0, ==, nghttp2_session_send(session));
13006 /* After sending RST_STREAM, stream must be closed */
13007 assert_null(nghttp2_session_get_stream(session, 3));
13008
13009 nghttp2_bufs_reset(&bufs);
13010
13011 /* header says content-length: 20, but DATA has 21 bytes */
13012 nghttp2_submit_request2(session, NULL, reqnv, ARRLEN(reqnv), NULL, NULL);
13013
13014 assert_int(0, ==, nghttp2_session_send(session));
13015
13016 rv = pack_headers(&bufs, &deflater, 5, NGHTTP2_FLAG_END_HEADERS, cl_resnv,
13017 ARRLEN(cl_resnv), mem);
13018 assert_ptrdiff(0, ==, rv);
13019
13020 nghttp2_frame_hd_init(&hd, 21, NGHTTP2_DATA, NGHTTP2_FLAG_END_STREAM, 5);
13021 nghttp2_frame_pack_frame_hd(bufs.head->buf.last, &hd);
13022 bufs.head->buf.last += NGHTTP2_FRAME_HDLEN + 21;
13023
13024 rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
13025 nghttp2_buf_len(&bufs.head->buf));
13026
13027 assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(&bufs.head->buf), ==, rv);
13028
13029 item = nghttp2_session_get_next_ob_item(session);
13030 assert_uint8(NGHTTP2_RST_STREAM, ==, item->frame.hd.type);
13031
13032 assert_not_null(nghttp2_session_get_stream(session, 5));
13033 assert_int(0, ==, nghttp2_session_send(session));
13034 /* After sending RST_STREAM, stream must be closed */
13035 assert_null(nghttp2_session_get_stream(session, 5));
13036
13037 nghttp2_bufs_reset(&bufs);
13038
13039 nghttp2_bufs_free(&bufs);
13040
13041 nghttp2_hd_deflate_free(&deflater);
13042
13043 nghttp2_session_del(session);
13044 }
13045
test_nghttp2_http_non_final_response(void)13046 void test_nghttp2_http_non_final_response(void) {
13047 nghttp2_session *session;
13048 nghttp2_session_callbacks callbacks;
13049 nghttp2_hd_deflater deflater;
13050 nghttp2_mem *mem;
13051 nghttp2_bufs bufs;
13052 nghttp2_ssize rv;
13053 const nghttp2_nv nonfinal_resnv[] = {
13054 MAKE_NV(":status", "100"),
13055 };
13056 nghttp2_outbound_item *item;
13057 nghttp2_frame_hd hd;
13058
13059 mem = nghttp2_mem_default();
13060 frame_pack_bufs_init(&bufs);
13061
13062 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
13063 callbacks.send_callback2 = null_send_callback;
13064
13065 nghttp2_session_client_new(&session, &callbacks, NULL);
13066
13067 nghttp2_hd_deflate_init(&deflater, mem);
13068
13069 /* non-final HEADERS with END_STREAM is illegal */
13070 open_sent_stream2(session, 1, NGHTTP2_STREAM_OPENING);
13071
13072 rv = pack_headers(&bufs, &deflater, 1,
13073 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM,
13074 nonfinal_resnv, ARRLEN(nonfinal_resnv), mem);
13075 assert_ptrdiff(0, ==, rv);
13076
13077 rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
13078 nghttp2_buf_len(&bufs.head->buf));
13079
13080 assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(&bufs.head->buf), ==, rv);
13081
13082 item = nghttp2_session_get_next_ob_item(session);
13083 assert_uint8(NGHTTP2_RST_STREAM, ==, item->frame.hd.type);
13084
13085 assert_int(0, ==, nghttp2_session_send(session));
13086
13087 nghttp2_bufs_reset(&bufs);
13088
13089 /* non-final HEADERS followed by non-empty DATA is illegal */
13090 open_sent_stream2(session, 3, NGHTTP2_STREAM_OPENING);
13091
13092 rv = pack_headers(&bufs, &deflater, 3, NGHTTP2_FLAG_END_HEADERS,
13093 nonfinal_resnv, ARRLEN(nonfinal_resnv), mem);
13094 assert_ptrdiff(0, ==, rv);
13095
13096 nghttp2_frame_hd_init(&hd, 10, NGHTTP2_DATA, NGHTTP2_FLAG_END_STREAM, 3);
13097 nghttp2_frame_pack_frame_hd(bufs.head->buf.last, &hd);
13098 bufs.head->buf.last += NGHTTP2_FRAME_HDLEN + 10;
13099
13100 rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
13101 nghttp2_buf_len(&bufs.head->buf));
13102
13103 assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(&bufs.head->buf), ==, rv);
13104
13105 item = nghttp2_session_get_next_ob_item(session);
13106 assert_uint8(NGHTTP2_RST_STREAM, ==, item->frame.hd.type);
13107
13108 assert_int(0, ==, nghttp2_session_send(session));
13109
13110 nghttp2_bufs_reset(&bufs);
13111
13112 /* non-final HEADERS followed by empty DATA (without END_STREAM) is
13113 ok */
13114 open_sent_stream2(session, 5, NGHTTP2_STREAM_OPENING);
13115
13116 rv = pack_headers(&bufs, &deflater, 5, NGHTTP2_FLAG_END_HEADERS,
13117 nonfinal_resnv, ARRLEN(nonfinal_resnv), mem);
13118 assert_ptrdiff(0, ==, rv);
13119
13120 nghttp2_frame_hd_init(&hd, 0, NGHTTP2_DATA, NGHTTP2_FLAG_NONE, 5);
13121 nghttp2_frame_pack_frame_hd(bufs.head->buf.last, &hd);
13122 bufs.head->buf.last += NGHTTP2_FRAME_HDLEN;
13123
13124 rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
13125 nghttp2_buf_len(&bufs.head->buf));
13126
13127 assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(&bufs.head->buf), ==, rv);
13128
13129 assert_null(nghttp2_session_get_next_ob_item(session));
13130
13131 nghttp2_bufs_reset(&bufs);
13132
13133 /* non-final HEADERS followed by empty DATA (with END_STREAM) is
13134 illegal */
13135 open_sent_stream2(session, 7, NGHTTP2_STREAM_OPENING);
13136
13137 rv = pack_headers(&bufs, &deflater, 7, NGHTTP2_FLAG_END_HEADERS,
13138 nonfinal_resnv, ARRLEN(nonfinal_resnv), mem);
13139 assert_ptrdiff(0, ==, rv);
13140
13141 nghttp2_frame_hd_init(&hd, 0, NGHTTP2_DATA, NGHTTP2_FLAG_END_STREAM, 7);
13142 nghttp2_frame_pack_frame_hd(bufs.head->buf.last, &hd);
13143 bufs.head->buf.last += NGHTTP2_FRAME_HDLEN;
13144
13145 rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
13146 nghttp2_buf_len(&bufs.head->buf));
13147
13148 assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(&bufs.head->buf), ==, rv);
13149
13150 item = nghttp2_session_get_next_ob_item(session);
13151
13152 assert_uint8(NGHTTP2_RST_STREAM, ==, item->frame.hd.type);
13153
13154 assert_int(0, ==, nghttp2_session_send(session));
13155
13156 nghttp2_bufs_reset(&bufs);
13157
13158 /* non-final HEADERS followed by final HEADERS is OK */
13159 open_sent_stream2(session, 9, NGHTTP2_STREAM_OPENING);
13160
13161 rv = pack_headers(&bufs, &deflater, 9, NGHTTP2_FLAG_END_HEADERS,
13162 nonfinal_resnv, ARRLEN(nonfinal_resnv), mem);
13163 assert_ptrdiff(0, ==, rv);
13164
13165 rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
13166 nghttp2_buf_len(&bufs.head->buf));
13167
13168 assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(&bufs.head->buf), ==, rv);
13169
13170 nghttp2_bufs_reset(&bufs);
13171
13172 rv = pack_headers(&bufs, &deflater, 9, NGHTTP2_FLAG_END_HEADERS, resnv,
13173 ARRLEN(resnv), mem);
13174 assert_ptrdiff(0, ==, rv);
13175
13176 rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
13177 nghttp2_buf_len(&bufs.head->buf));
13178
13179 assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(&bufs.head->buf), ==, rv);
13180
13181 assert_null(nghttp2_session_get_next_ob_item(session));
13182
13183 nghttp2_bufs_reset(&bufs);
13184
13185 nghttp2_hd_deflate_free(&deflater);
13186
13187 nghttp2_session_del(session);
13188
13189 nghttp2_bufs_free(&bufs);
13190 }
13191
test_nghttp2_http_trailer_headers(void)13192 void test_nghttp2_http_trailer_headers(void) {
13193 nghttp2_session *session;
13194 nghttp2_session_callbacks callbacks;
13195 nghttp2_hd_deflater deflater;
13196 nghttp2_mem *mem;
13197 nghttp2_bufs bufs;
13198 nghttp2_ssize rv;
13199 const nghttp2_nv trailer_reqnv[] = {
13200 MAKE_NV("foo", "bar"),
13201 };
13202 nghttp2_outbound_item *item;
13203
13204 mem = nghttp2_mem_default();
13205 frame_pack_bufs_init(&bufs);
13206
13207 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
13208 callbacks.send_callback2 = null_send_callback;
13209
13210 nghttp2_session_server_new(&session, &callbacks, NULL);
13211
13212 nghttp2_hd_deflate_init(&deflater, mem);
13213
13214 /* good trailer header */
13215 rv = pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, reqnv,
13216 ARRLEN(reqnv), mem);
13217 assert_ptrdiff(0, ==, rv);
13218
13219 rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
13220 nghttp2_buf_len(&bufs.head->buf));
13221
13222 assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(&bufs.head->buf), ==, rv);
13223
13224 nghttp2_bufs_reset(&bufs);
13225
13226 rv = pack_headers(&bufs, &deflater, 1,
13227 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM,
13228 trailer_reqnv, ARRLEN(trailer_reqnv), mem);
13229 assert_ptrdiff(0, ==, rv);
13230
13231 rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
13232 nghttp2_buf_len(&bufs.head->buf));
13233
13234 assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(&bufs.head->buf), ==, rv);
13235
13236 assert_null(nghttp2_session_get_next_ob_item(session));
13237
13238 nghttp2_bufs_reset(&bufs);
13239
13240 /* trailer header without END_STREAM is illegal */
13241 rv = pack_headers(&bufs, &deflater, 3, NGHTTP2_FLAG_END_HEADERS, reqnv,
13242 ARRLEN(reqnv), mem);
13243 assert_ptrdiff(0, ==, rv);
13244
13245 rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
13246 nghttp2_buf_len(&bufs.head->buf));
13247
13248 assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(&bufs.head->buf), ==, rv);
13249
13250 nghttp2_bufs_reset(&bufs);
13251
13252 rv = pack_headers(&bufs, &deflater, 3, NGHTTP2_FLAG_END_HEADERS,
13253 trailer_reqnv, ARRLEN(trailer_reqnv), mem);
13254 assert_ptrdiff(0, ==, rv);
13255
13256 rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
13257 nghttp2_buf_len(&bufs.head->buf));
13258
13259 assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(&bufs.head->buf), ==, rv);
13260
13261 item = nghttp2_session_get_next_ob_item(session);
13262
13263 assert_uint8(NGHTTP2_RST_STREAM, ==, item->frame.hd.type);
13264
13265 assert_int(0, ==, nghttp2_session_send(session));
13266
13267 nghttp2_bufs_reset(&bufs);
13268
13269 /* trailer header including pseudo header field is illegal */
13270 rv = pack_headers(&bufs, &deflater, 5, NGHTTP2_FLAG_END_HEADERS, reqnv,
13271 ARRLEN(reqnv), mem);
13272 assert_ptrdiff(0, ==, rv);
13273
13274 rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
13275 nghttp2_buf_len(&bufs.head->buf));
13276
13277 assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(&bufs.head->buf), ==, rv);
13278
13279 nghttp2_bufs_reset(&bufs);
13280
13281 rv = pack_headers(&bufs, &deflater, 5, NGHTTP2_FLAG_END_HEADERS, reqnv,
13282 ARRLEN(reqnv), mem);
13283 assert_ptrdiff(0, ==, rv);
13284
13285 rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
13286 nghttp2_buf_len(&bufs.head->buf));
13287
13288 assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(&bufs.head->buf), ==, rv);
13289
13290 item = nghttp2_session_get_next_ob_item(session);
13291
13292 assert_uint8(NGHTTP2_RST_STREAM, ==, item->frame.hd.type);
13293
13294 assert_int(0, ==, nghttp2_session_send(session));
13295
13296 nghttp2_bufs_reset(&bufs);
13297
13298 nghttp2_hd_deflate_free(&deflater);
13299
13300 nghttp2_session_del(session);
13301
13302 nghttp2_bufs_free(&bufs);
13303 }
13304
test_nghttp2_http_ignore_regular_header(void)13305 void test_nghttp2_http_ignore_regular_header(void) {
13306 nghttp2_session *session;
13307 nghttp2_session_callbacks callbacks;
13308 nghttp2_hd_deflater deflater;
13309 nghttp2_mem *mem;
13310 nghttp2_bufs bufs;
13311 nghttp2_ssize rv;
13312 my_user_data ud;
13313 const nghttp2_nv bad_reqnv[] = {
13314 MAKE_NV(":authority", "localhost"),
13315 MAKE_NV(":scheme", "https"),
13316 MAKE_NV(":path", "/"),
13317 MAKE_NV(":method", "GET"),
13318 MAKE_NV("foo", "\x0zzz"),
13319 MAKE_NV("bar", "buzz"),
13320 };
13321 const nghttp2_nv bad_ansnv[] = {
13322 MAKE_NV(":authority", "localhost"), MAKE_NV(":scheme", "https"),
13323 MAKE_NV(":path", "/"), MAKE_NV(":method", "GET"), MAKE_NV("bar", "buzz")};
13324 size_t proclen;
13325 size_t i;
13326 nghttp2_outbound_item *item;
13327
13328 mem = nghttp2_mem_default();
13329 frame_pack_bufs_init(&bufs);
13330
13331 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
13332 callbacks.send_callback2 = null_send_callback;
13333 callbacks.on_header_callback = pause_on_header_callback;
13334
13335 nghttp2_session_server_new(&session, &callbacks, &ud);
13336 nghttp2_hd_deflate_init(&deflater, mem);
13337
13338 rv = pack_headers(&bufs, &deflater, 1,
13339 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM,
13340 bad_reqnv, ARRLEN(bad_reqnv), mem);
13341
13342 assert_ptrdiff(0, ==, rv);
13343
13344 nghttp2_hd_deflate_free(&deflater);
13345
13346 proclen = 0;
13347
13348 for (i = 0; i < 4; ++i) {
13349 rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos + proclen,
13350 nghttp2_buf_len(&bufs.head->buf) - proclen);
13351 assert_ptrdiff(0, <, rv);
13352 proclen += (size_t)rv;
13353 assert_true(nghttp2_nv_equal(&bad_ansnv[i], &ud.nv));
13354 }
13355
13356 rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos + proclen,
13357 nghttp2_buf_len(&bufs.head->buf) - proclen);
13358 assert_ptrdiff(0, <, rv);
13359 /* Without on_invalid_frame_recv_callback, bad header causes stream
13360 reset */
13361 item = nghttp2_session_get_next_ob_item(session);
13362
13363 assert_uint8(NGHTTP2_RST_STREAM, ==, item->frame.hd.type);
13364
13365 proclen += (size_t)rv;
13366
13367 assert_size(nghttp2_buf_len(&bufs.head->buf), ==, proclen);
13368
13369 nghttp2_session_del(session);
13370
13371 /* use on_invalid_header_callback */
13372 callbacks.on_invalid_header_callback = pause_on_invalid_header_callback;
13373
13374 nghttp2_session_server_new(&session, &callbacks, &ud);
13375
13376 proclen = 0;
13377
13378 ud.invalid_header_cb_called = 0;
13379
13380 for (i = 0; i < 4; ++i) {
13381 rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos + proclen,
13382 nghttp2_buf_len(&bufs.head->buf) - proclen);
13383 assert_ptrdiff(0, <, rv);
13384 proclen += (size_t)rv;
13385 assert_true(nghttp2_nv_equal(&bad_ansnv[i], &ud.nv));
13386 }
13387
13388 assert_int(0, ==, ud.invalid_header_cb_called);
13389
13390 rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos + proclen,
13391 nghttp2_buf_len(&bufs.head->buf) - proclen);
13392
13393 assert_ptrdiff(0, <, rv);
13394 assert_int(1, ==, ud.invalid_header_cb_called);
13395 assert_true(nghttp2_nv_equal(&bad_reqnv[4], &ud.nv));
13396
13397 proclen += (size_t)rv;
13398
13399 rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos + proclen,
13400 nghttp2_buf_len(&bufs.head->buf) - proclen);
13401
13402 assert_ptrdiff(0, <, rv);
13403 assert_true(nghttp2_nv_equal(&bad_ansnv[4], &ud.nv));
13404
13405 nghttp2_session_del(session);
13406
13407 /* make sure that we can reset stream from
13408 on_invalid_header_callback */
13409 callbacks.on_header_callback = on_header_callback;
13410 callbacks.on_invalid_header_callback = reset_on_invalid_header_callback;
13411
13412 nghttp2_session_server_new(&session, &callbacks, &ud);
13413
13414 rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
13415 nghttp2_buf_len(&bufs.head->buf));
13416
13417 assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(&bufs.head->buf), ==, rv);
13418
13419 item = nghttp2_session_get_next_ob_item(session);
13420
13421 assert_uint8(NGHTTP2_RST_STREAM, ==, item->frame.hd.type);
13422 assert_int32(1, ==, item->frame.hd.stream_id);
13423
13424 nghttp2_session_del(session);
13425 nghttp2_bufs_free(&bufs);
13426 }
13427
test_nghttp2_http_ignore_content_length(void)13428 void test_nghttp2_http_ignore_content_length(void) {
13429 nghttp2_session *session;
13430 nghttp2_session_callbacks callbacks;
13431 nghttp2_hd_deflater deflater;
13432 nghttp2_mem *mem;
13433 nghttp2_bufs bufs;
13434 nghttp2_ssize rv;
13435 const nghttp2_nv cl_resnv[] = {MAKE_NV(":status", "304"),
13436 MAKE_NV("content-length", "20")};
13437 const nghttp2_nv conn_reqnv[] = {MAKE_NV(":authority", "localhost"),
13438 MAKE_NV(":method", "CONNECT"),
13439 MAKE_NV("content-length", "999999")};
13440 const nghttp2_nv conn_cl_resnv[] = {MAKE_NV(":status", "200"),
13441 MAKE_NV("content-length", "0")};
13442 nghttp2_stream *stream;
13443
13444 mem = nghttp2_mem_default();
13445 frame_pack_bufs_init(&bufs);
13446
13447 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
13448 callbacks.send_callback2 = null_send_callback;
13449
13450 nghttp2_session_client_new(&session, &callbacks, NULL);
13451
13452 nghttp2_hd_deflate_init(&deflater, mem);
13453
13454 /* If status 304, content-length must be ignored */
13455 open_sent_stream2(session, 1, NGHTTP2_STREAM_OPENING);
13456
13457 rv = pack_headers(&bufs, &deflater, 1,
13458 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM,
13459 cl_resnv, ARRLEN(cl_resnv), mem);
13460 assert_ptrdiff(0, ==, rv);
13461
13462 rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
13463 nghttp2_buf_len(&bufs.head->buf));
13464
13465 assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(&bufs.head->buf), ==, rv);
13466
13467 assert_null(nghttp2_session_get_next_ob_item(session));
13468
13469 nghttp2_bufs_reset(&bufs);
13470
13471 /* Content-Length in 200 response to CONNECT is ignored */
13472 stream = open_sent_stream2(session, 3, NGHTTP2_STREAM_OPENING);
13473 stream->http_flags |= NGHTTP2_HTTP_FLAG_METH_CONNECT;
13474
13475 rv = pack_headers(&bufs, &deflater, 3, NGHTTP2_FLAG_END_HEADERS,
13476 conn_cl_resnv, ARRLEN(conn_cl_resnv), mem);
13477 assert_ptrdiff(0, ==, rv);
13478
13479 rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
13480 nghttp2_buf_len(&bufs.head->buf));
13481
13482 assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(&bufs.head->buf), ==, rv);
13483
13484 assert_null(nghttp2_session_get_next_ob_item(session));
13485 assert_int64(-1, ==, stream->content_length);
13486
13487 nghttp2_bufs_reset(&bufs);
13488
13489 nghttp2_hd_deflate_free(&deflater);
13490 nghttp2_session_del(session);
13491
13492 /* If request method is CONNECT, content-length must be ignored */
13493 nghttp2_session_server_new(&session, &callbacks, NULL);
13494
13495 nghttp2_hd_deflate_init(&deflater, mem);
13496
13497 rv = pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, conn_reqnv,
13498 ARRLEN(conn_reqnv), mem);
13499
13500 assert_ptrdiff(0, ==, rv);
13501
13502 rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
13503 nghttp2_buf_len(&bufs.head->buf));
13504
13505 assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(&bufs.head->buf), ==, rv);
13506
13507 assert_null(nghttp2_session_get_next_ob_item(session));
13508
13509 stream = nghttp2_session_get_stream(session, 1);
13510
13511 assert_int64(-1, ==, stream->content_length);
13512 assert_true(stream->http_flags & NGHTTP2_HTTP_FLAG_METH_CONNECT);
13513
13514 nghttp2_hd_deflate_free(&deflater);
13515 nghttp2_session_del(session);
13516 nghttp2_bufs_free(&bufs);
13517 }
13518
test_nghttp2_http_record_request_method(void)13519 void test_nghttp2_http_record_request_method(void) {
13520 nghttp2_session *session;
13521 nghttp2_session_callbacks callbacks;
13522 const nghttp2_nv conn_reqnv[] = {MAKE_NV(":method", "CONNECT"),
13523 MAKE_NV(":authority", "localhost")};
13524 const nghttp2_nv conn_resnv[] = {MAKE_NV(":status", "200"),
13525 MAKE_NV("content-length", "9999")};
13526 nghttp2_stream *stream;
13527 nghttp2_ssize rv;
13528 nghttp2_bufs bufs;
13529 nghttp2_hd_deflater deflater;
13530 nghttp2_mem *mem;
13531 nghttp2_outbound_item *item;
13532
13533 mem = nghttp2_mem_default();
13534 frame_pack_bufs_init(&bufs);
13535
13536 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
13537 callbacks.send_callback2 = null_send_callback;
13538
13539 nghttp2_session_client_new(&session, &callbacks, NULL);
13540
13541 nghttp2_hd_deflate_init(&deflater, mem);
13542
13543 assert_int32(1, ==,
13544 nghttp2_submit_request2(session, NULL, conn_reqnv,
13545 ARRLEN(conn_reqnv), NULL, NULL));
13546
13547 assert_int(0, ==, nghttp2_session_send(session));
13548
13549 stream = nghttp2_session_get_stream(session, 1);
13550
13551 assert_uint32(NGHTTP2_HTTP_FLAG_METH_CONNECT, ==, stream->http_flags);
13552
13553 rv = pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, conn_resnv,
13554 ARRLEN(conn_resnv), mem);
13555 assert_ptrdiff(0, ==, rv);
13556
13557 rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
13558 nghttp2_buf_len(&bufs.head->buf));
13559
13560 assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(&bufs.head->buf), ==, rv);
13561
13562 assert_true(NGHTTP2_HTTP_FLAG_METH_CONNECT & stream->http_flags);
13563 assert_int64(-1, ==, stream->content_length);
13564
13565 /* content-length is ignored in 200 response to a CONNECT request */
13566 item = nghttp2_session_get_next_ob_item(session);
13567
13568 assert_null(item);
13569
13570 nghttp2_hd_deflate_free(&deflater);
13571 nghttp2_session_del(session);
13572 nghttp2_bufs_free(&bufs);
13573 }
13574
test_nghttp2_http_push_promise(void)13575 void test_nghttp2_http_push_promise(void) {
13576 nghttp2_session *session;
13577 nghttp2_session_callbacks callbacks;
13578 nghttp2_hd_deflater deflater;
13579 nghttp2_mem *mem;
13580 nghttp2_bufs bufs;
13581 nghttp2_ssize rv;
13582 nghttp2_stream *stream;
13583 const nghttp2_nv bad_reqnv[] = {MAKE_NV(":method", "GET")};
13584 nghttp2_outbound_item *item;
13585
13586 mem = nghttp2_mem_default();
13587 frame_pack_bufs_init(&bufs);
13588
13589 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
13590 callbacks.send_callback2 = null_send_callback;
13591
13592 /* good PUSH_PROMISE case */
13593 nghttp2_session_client_new(&session, &callbacks, NULL);
13594
13595 nghttp2_hd_deflate_init(&deflater, mem);
13596
13597 open_sent_stream2(session, 1, NGHTTP2_STREAM_OPENING);
13598
13599 rv = pack_push_promise(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, 2,
13600 reqnv, ARRLEN(reqnv), mem);
13601 assert_ptrdiff(0, ==, rv);
13602
13603 rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
13604 nghttp2_buf_len(&bufs.head->buf));
13605
13606 assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(&bufs.head->buf), ==, rv);
13607
13608 assert_null(nghttp2_session_get_next_ob_item(session));
13609
13610 stream = nghttp2_session_get_stream(session, 2);
13611 assert_not_null(stream);
13612
13613 nghttp2_bufs_reset(&bufs);
13614
13615 rv = pack_headers(&bufs, &deflater, 2, NGHTTP2_FLAG_END_HEADERS, resnv,
13616 ARRLEN(resnv), mem);
13617
13618 assert_ptrdiff(0, ==, rv);
13619
13620 rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
13621 nghttp2_buf_len(&bufs.head->buf));
13622
13623 assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(&bufs.head->buf), ==, rv);
13624
13625 assert_null(nghttp2_session_get_next_ob_item(session));
13626
13627 assert_int16(200, ==, stream->status_code);
13628
13629 nghttp2_bufs_reset(&bufs);
13630
13631 /* PUSH_PROMISE lacks mandatory header */
13632 rv = pack_push_promise(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, 4,
13633 bad_reqnv, ARRLEN(bad_reqnv), mem);
13634
13635 assert_ptrdiff(0, ==, rv);
13636
13637 rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
13638 nghttp2_buf_len(&bufs.head->buf));
13639
13640 assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(&bufs.head->buf), ==, rv);
13641
13642 item = nghttp2_session_get_next_ob_item(session);
13643
13644 assert_uint8(NGHTTP2_RST_STREAM, ==, item->frame.hd.type);
13645 assert_int32(4, ==, item->frame.hd.stream_id);
13646
13647 nghttp2_bufs_reset(&bufs);
13648
13649 nghttp2_hd_deflate_free(&deflater);
13650 nghttp2_session_del(session);
13651 nghttp2_bufs_free(&bufs);
13652 }
13653
test_nghttp2_http_head_method_upgrade_workaround(void)13654 void test_nghttp2_http_head_method_upgrade_workaround(void) {
13655 nghttp2_session *session;
13656 nghttp2_session_callbacks callbacks;
13657 const nghttp2_nv cl_resnv[] = {MAKE_NV(":status", "200"),
13658 MAKE_NV("content-length", "1000000007")};
13659 nghttp2_bufs bufs;
13660 nghttp2_hd_deflater deflater;
13661 nghttp2_mem *mem;
13662 nghttp2_ssize rv;
13663 nghttp2_stream *stream;
13664
13665 mem = nghttp2_mem_default();
13666 frame_pack_bufs_init(&bufs);
13667
13668 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
13669 callbacks.send_callback2 = null_send_callback;
13670
13671 nghttp2_session_client_new(&session, &callbacks, NULL);
13672
13673 nghttp2_hd_deflate_init(&deflater, mem);
13674
13675 nghttp2_session_upgrade(session, NULL, 0, NULL);
13676
13677 rv = pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, cl_resnv,
13678 ARRLEN(cl_resnv), mem);
13679
13680 assert_ptrdiff(0, ==, rv);
13681
13682 rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
13683 nghttp2_buf_len(&bufs.head->buf));
13684
13685 assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(&bufs.head->buf), ==, rv);
13686
13687 stream = nghttp2_session_get_stream(session, 1);
13688
13689 assert_int64(-1, ==, stream->content_length);
13690
13691 nghttp2_hd_deflate_free(&deflater);
13692 nghttp2_session_del(session);
13693 nghttp2_bufs_free(&bufs);
13694 }
13695
test_nghttp2_http_no_rfc9113_leading_and_trailing_ws_validation(void)13696 void test_nghttp2_http_no_rfc9113_leading_and_trailing_ws_validation(void) {
13697 nghttp2_session *session;
13698 nghttp2_session_callbacks callbacks;
13699 nghttp2_hd_deflater deflater;
13700 nghttp2_mem *mem;
13701 nghttp2_bufs bufs;
13702 nghttp2_ssize rv;
13703 const nghttp2_nv ws_reqnv[] = {
13704 MAKE_NV(":path", "/"),
13705 MAKE_NV(":method", "GET"),
13706 MAKE_NV(":authority", "localhost"),
13707 MAKE_NV(":scheme", "https"),
13708 MAKE_NV("foo", "bar "),
13709 };
13710 nghttp2_outbound_item *item;
13711 nghttp2_option *option;
13712
13713 mem = nghttp2_mem_default();
13714 frame_pack_bufs_init(&bufs);
13715
13716 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
13717 callbacks.send_callback2 = null_send_callback;
13718
13719 /* By default, the leading and trailing white spaces validation is
13720 enabled as per RFC 9113. */
13721 nghttp2_session_server_new(&session, &callbacks, NULL);
13722
13723 nghttp2_hd_deflate_init(&deflater, mem);
13724
13725 rv = pack_headers(&bufs, &deflater, 1,
13726 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM,
13727 ws_reqnv, ARRLEN(ws_reqnv), mem);
13728
13729 assert_ptrdiff(0, ==, rv);
13730
13731 rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
13732 nghttp2_buf_len(&bufs.head->buf));
13733
13734 assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(&bufs.head->buf), ==, rv);
13735
13736 item = nghttp2_session_get_next_ob_item(session);
13737
13738 assert_uint8(NGHTTP2_RST_STREAM, ==, item->frame.hd.type);
13739 assert_int(0, ==, nghttp2_session_send(session));
13740
13741 nghttp2_bufs_reset(&bufs);
13742 nghttp2_hd_deflate_free(&deflater);
13743 nghttp2_session_del(session);
13744
13745 /* Turn off the validation */
13746 nghttp2_option_new(&option);
13747 nghttp2_option_set_no_rfc9113_leading_and_trailing_ws_validation(option, 1);
13748
13749 nghttp2_session_server_new2(&session, &callbacks, NULL, option);
13750
13751 nghttp2_hd_deflate_init(&deflater, mem);
13752
13753 rv = pack_headers(&bufs, &deflater, 1,
13754 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM,
13755 ws_reqnv, ARRLEN(ws_reqnv), mem);
13756
13757 assert_ptrdiff(0, ==, rv);
13758
13759 rv = nghttp2_session_mem_recv2(session, bufs.head->buf.pos,
13760 nghttp2_buf_len(&bufs.head->buf));
13761
13762 assert_ptrdiff((nghttp2_ssize)nghttp2_buf_len(&bufs.head->buf), ==, rv);
13763
13764 item = nghttp2_session_get_next_ob_item(session);
13765
13766 assert_null(item);
13767
13768 nghttp2_bufs_reset(&bufs);
13769 nghttp2_hd_deflate_free(&deflater);
13770 nghttp2_session_del(session);
13771 nghttp2_option_del(option);
13772
13773 nghttp2_bufs_free(&bufs);
13774 }
13775