1 /*
2 * nghttp2 - HTTP/2 C Library
3 *
4 * Copyright (c) 2013 Tatsuhiro Tsujikawa
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining
7 * a copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sublicense, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be
15 * included in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 */
25 #include "nghttp2_session_test.h"
26
27 #include <stdio.h>
28 #include <assert.h>
29
30 #include <CUnit/CUnit.h>
31
32 #include "nghttp2_session.h"
33 #include "nghttp2_stream.h"
34 #include "nghttp2_net.h"
35 #include "nghttp2_helper.h"
36 #include "nghttp2_test_helper.h"
37 #include "nghttp2_priority_spec.h"
38 #include "nghttp2_extpri.h"
39
40 typedef struct {
41 uint8_t buf[65535];
42 size_t length;
43 } accumulator;
44
45 typedef struct {
46 uint8_t data[8192];
47 uint8_t *datamark;
48 uint8_t *datalimit;
49 size_t feedseq[8192];
50 size_t seqidx;
51 } scripted_data_feed;
52
53 typedef struct {
54 accumulator *acc;
55 scripted_data_feed *df;
56 int frame_recv_cb_called, invalid_frame_recv_cb_called;
57 uint8_t recv_frame_type;
58 nghttp2_frame_hd recv_frame_hd;
59 int frame_send_cb_called;
60 uint8_t sent_frame_type;
61 int before_frame_send_cb_called;
62 int frame_not_send_cb_called;
63 uint8_t not_sent_frame_type;
64 int not_sent_error;
65 int stream_close_cb_called;
66 uint32_t stream_close_error_code;
67 size_t data_source_length;
68 int32_t stream_id;
69 size_t block_count;
70 int data_chunk_recv_cb_called;
71 const nghttp2_frame *frame;
72 size_t fixed_sendlen;
73 int header_cb_called;
74 int invalid_header_cb_called;
75 int begin_headers_cb_called;
76 nghttp2_nv nv;
77 size_t data_chunk_len;
78 size_t padlen;
79 int begin_frame_cb_called;
80 nghttp2_buf scratchbuf;
81 size_t data_source_read_cb_paused;
82 } my_user_data;
83
84 static const nghttp2_nv reqnv[] = {
85 MAKE_NV(":method", "GET"),
86 MAKE_NV(":path", "/"),
87 MAKE_NV(":scheme", "https"),
88 MAKE_NV(":authority", "localhost"),
89 };
90
91 static const nghttp2_nv resnv[] = {
92 MAKE_NV(":status", "200"),
93 };
94
95 static const nghttp2_nv trailernv[] = {
96 // from http://tools.ietf.org/html/rfc6249#section-7
97 MAKE_NV("digest", "SHA-256="
98 "MWVkMWQxYTRiMzk5MDQ0MzI3NGU5NDEyZTk5OWY1ZGFmNzgyZTJlODYz"
99 "YjRjYzFhOTlmNTQwYzI2M2QwM2U2MQ=="),
100 };
101
scripted_data_feed_init2(scripted_data_feed * df,nghttp2_bufs * bufs)102 static void scripted_data_feed_init2(scripted_data_feed *df,
103 nghttp2_bufs *bufs) {
104 nghttp2_buf_chain *ci;
105 nghttp2_buf *buf;
106 uint8_t *ptr;
107 size_t len;
108
109 memset(df, 0, sizeof(scripted_data_feed));
110 ptr = df->data;
111 len = 0;
112
113 for (ci = bufs->head; ci; ci = ci->next) {
114 buf = &ci->buf;
115 ptr = nghttp2_cpymem(ptr, buf->pos, nghttp2_buf_len(buf));
116 len += nghttp2_buf_len(buf);
117 }
118
119 df->datamark = df->data;
120 df->datalimit = df->data + len;
121 df->feedseq[0] = len;
122 }
123
null_send_callback(nghttp2_session * session,const uint8_t * data,size_t len,int flags,void * user_data)124 static ssize_t null_send_callback(nghttp2_session *session, const uint8_t *data,
125 size_t len, int flags, void *user_data) {
126 (void)session;
127 (void)data;
128 (void)flags;
129 (void)user_data;
130
131 return (ssize_t)len;
132 }
133
fail_send_callback(nghttp2_session * session,const uint8_t * data,size_t len,int flags,void * user_data)134 static ssize_t fail_send_callback(nghttp2_session *session, const uint8_t *data,
135 size_t len, int flags, void *user_data) {
136 (void)session;
137 (void)data;
138 (void)len;
139 (void)flags;
140 (void)user_data;
141
142 return NGHTTP2_ERR_CALLBACK_FAILURE;
143 }
144
fixed_bytes_send_callback(nghttp2_session * session,const uint8_t * data,size_t len,int flags,void * user_data)145 static ssize_t fixed_bytes_send_callback(nghttp2_session *session,
146 const uint8_t *data, size_t len,
147 int flags, void *user_data) {
148 size_t fixed_sendlen = ((my_user_data *)user_data)->fixed_sendlen;
149 (void)session;
150 (void)data;
151 (void)flags;
152
153 return (ssize_t)(fixed_sendlen < len ? fixed_sendlen : len);
154 }
155
scripted_recv_callback(nghttp2_session * session,uint8_t * data,size_t len,int flags,void * user_data)156 static ssize_t scripted_recv_callback(nghttp2_session *session, uint8_t *data,
157 size_t len, int flags, void *user_data) {
158 scripted_data_feed *df = ((my_user_data *)user_data)->df;
159 size_t wlen = df->feedseq[df->seqidx] > len ? len : df->feedseq[df->seqidx];
160 (void)session;
161 (void)flags;
162
163 memcpy(data, df->datamark, wlen);
164 df->datamark += wlen;
165 df->feedseq[df->seqidx] -= wlen;
166 if (df->feedseq[df->seqidx] == 0) {
167 ++df->seqidx;
168 }
169 return (ssize_t)wlen;
170 }
171
eof_recv_callback(nghttp2_session * session,uint8_t * data,size_t len,int flags,void * user_data)172 static ssize_t eof_recv_callback(nghttp2_session *session, uint8_t *data,
173 size_t len, int flags, void *user_data) {
174 (void)session;
175 (void)data;
176 (void)len;
177 (void)flags;
178 (void)user_data;
179
180 return NGHTTP2_ERR_EOF;
181 }
182
accumulator_send_callback(nghttp2_session * session,const uint8_t * buf,size_t len,int flags,void * user_data)183 static ssize_t accumulator_send_callback(nghttp2_session *session,
184 const uint8_t *buf, size_t len,
185 int flags, void *user_data) {
186 accumulator *acc = ((my_user_data *)user_data)->acc;
187 (void)session;
188 (void)flags;
189
190 assert(acc->length + len < sizeof(acc->buf));
191 memcpy(acc->buf + acc->length, buf, len);
192 acc->length += len;
193 return (ssize_t)len;
194 }
195
on_begin_frame_callback(nghttp2_session * session,const nghttp2_frame_hd * hd,void * user_data)196 static int on_begin_frame_callback(nghttp2_session *session,
197 const nghttp2_frame_hd *hd,
198 void *user_data) {
199 my_user_data *ud = (my_user_data *)user_data;
200 (void)session;
201 (void)hd;
202
203 ++ud->begin_frame_cb_called;
204 return 0;
205 }
206
on_frame_recv_callback(nghttp2_session * session,const nghttp2_frame * frame,void * user_data)207 static int on_frame_recv_callback(nghttp2_session *session,
208 const nghttp2_frame *frame, void *user_data) {
209 my_user_data *ud = (my_user_data *)user_data;
210 (void)session;
211
212 ++ud->frame_recv_cb_called;
213 ud->recv_frame_type = frame->hd.type;
214 ud->recv_frame_hd = frame->hd;
215
216 return 0;
217 }
218
on_invalid_frame_recv_callback(nghttp2_session * session,const nghttp2_frame * frame,int lib_error_code,void * user_data)219 static int on_invalid_frame_recv_callback(nghttp2_session *session,
220 const nghttp2_frame *frame,
221 int lib_error_code, void *user_data) {
222 my_user_data *ud = (my_user_data *)user_data;
223 (void)session;
224 (void)frame;
225 (void)lib_error_code;
226
227 ++ud->invalid_frame_recv_cb_called;
228 return 0;
229 }
230
on_frame_send_callback(nghttp2_session * session,const nghttp2_frame * frame,void * user_data)231 static int on_frame_send_callback(nghttp2_session *session,
232 const nghttp2_frame *frame, void *user_data) {
233 my_user_data *ud = (my_user_data *)user_data;
234 (void)session;
235
236 ++ud->frame_send_cb_called;
237 ud->sent_frame_type = frame->hd.type;
238 return 0;
239 }
240
on_frame_not_send_callback(nghttp2_session * session,const nghttp2_frame * frame,int lib_error,void * user_data)241 static int on_frame_not_send_callback(nghttp2_session *session,
242 const nghttp2_frame *frame, int lib_error,
243 void *user_data) {
244 my_user_data *ud = (my_user_data *)user_data;
245 (void)session;
246
247 ++ud->frame_not_send_cb_called;
248 ud->not_sent_frame_type = frame->hd.type;
249 ud->not_sent_error = lib_error;
250 return 0;
251 }
252
cancel_before_frame_send_callback(nghttp2_session * session,const nghttp2_frame * frame,void * user_data)253 static int cancel_before_frame_send_callback(nghttp2_session *session,
254 const nghttp2_frame *frame,
255 void *user_data) {
256 my_user_data *ud = (my_user_data *)user_data;
257 (void)session;
258 (void)frame;
259
260 ++ud->before_frame_send_cb_called;
261 return NGHTTP2_ERR_CANCEL;
262 }
263
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)264 static int on_data_chunk_recv_callback(nghttp2_session *session, uint8_t flags,
265 int32_t stream_id, const uint8_t *data,
266 size_t len, void *user_data) {
267 my_user_data *ud = (my_user_data *)user_data;
268 (void)session;
269 (void)flags;
270 (void)stream_id;
271 (void)data;
272
273 ++ud->data_chunk_recv_cb_called;
274 ud->data_chunk_len = len;
275 return 0;
276 }
277
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)278 static int pause_on_data_chunk_recv_callback(nghttp2_session *session,
279 uint8_t flags, int32_t stream_id,
280 const uint8_t *data, size_t len,
281 void *user_data) {
282 my_user_data *ud = (my_user_data *)user_data;
283 (void)session;
284 (void)flags;
285 (void)stream_id;
286 (void)data;
287 (void)len;
288
289 ++ud->data_chunk_recv_cb_called;
290 return NGHTTP2_ERR_PAUSE;
291 }
292
select_padding_callback(nghttp2_session * session,const nghttp2_frame * frame,size_t max_payloadlen,void * user_data)293 static ssize_t select_padding_callback(nghttp2_session *session,
294 const nghttp2_frame *frame,
295 size_t max_payloadlen, void *user_data) {
296 my_user_data *ud = (my_user_data *)user_data;
297 (void)session;
298
299 return (ssize_t)nghttp2_min(max_payloadlen, frame->hd.length + ud->padlen);
300 }
301
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)302 static ssize_t too_large_data_source_length_callback(
303 nghttp2_session *session, uint8_t frame_type, int32_t stream_id,
304 int32_t session_remote_window_size, int32_t stream_remote_window_size,
305 uint32_t remote_max_frame_size, void *user_data) {
306 (void)session;
307 (void)frame_type;
308 (void)stream_id;
309 (void)session_remote_window_size;
310 (void)stream_remote_window_size;
311 (void)remote_max_frame_size;
312 (void)user_data;
313
314 return NGHTTP2_MAX_FRAME_SIZE_MAX + 1;
315 }
316
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)317 static ssize_t smallest_length_data_source_length_callback(
318 nghttp2_session *session, uint8_t frame_type, int32_t stream_id,
319 int32_t session_remote_window_size, int32_t stream_remote_window_size,
320 uint32_t remote_max_frame_size, void *user_data) {
321 (void)session;
322 (void)frame_type;
323 (void)stream_id;
324 (void)session_remote_window_size;
325 (void)stream_remote_window_size;
326 (void)remote_max_frame_size;
327 (void)user_data;
328
329 return 1;
330 }
331
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)332 static ssize_t fixed_length_data_source_read_callback(
333 nghttp2_session *session, int32_t stream_id, uint8_t *buf, size_t len,
334 uint32_t *data_flags, nghttp2_data_source *source, void *user_data) {
335 my_user_data *ud = (my_user_data *)user_data;
336 size_t wlen;
337 (void)session;
338 (void)stream_id;
339 (void)buf;
340 (void)source;
341
342 if (len < ud->data_source_length) {
343 wlen = len;
344 } else {
345 wlen = ud->data_source_length;
346 }
347 ud->data_source_length -= wlen;
348 if (ud->data_source_length == 0) {
349 *data_flags |= NGHTTP2_DATA_FLAG_EOF;
350 }
351 return (ssize_t)wlen;
352 }
353
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)354 static ssize_t temporal_failure_data_source_read_callback(
355 nghttp2_session *session, int32_t stream_id, uint8_t *buf, size_t len,
356 uint32_t *data_flags, nghttp2_data_source *source, void *user_data) {
357 (void)session;
358 (void)stream_id;
359 (void)buf;
360 (void)len;
361 (void)data_flags;
362 (void)source;
363 (void)user_data;
364
365 return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
366 }
367
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)368 static ssize_t fail_data_source_read_callback(nghttp2_session *session,
369 int32_t stream_id, uint8_t *buf,
370 size_t len, uint32_t *data_flags,
371 nghttp2_data_source *source,
372 void *user_data) {
373 (void)session;
374 (void)stream_id;
375 (void)buf;
376 (void)len;
377 (void)data_flags;
378 (void)source;
379 (void)user_data;
380
381 return NGHTTP2_ERR_CALLBACK_FAILURE;
382 }
383
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)384 static ssize_t no_end_stream_data_source_read_callback(
385 nghttp2_session *session, int32_t stream_id, uint8_t *buf, size_t len,
386 uint32_t *data_flags, nghttp2_data_source *source, void *user_data) {
387 (void)session;
388 (void)stream_id;
389 (void)buf;
390 (void)len;
391 (void)source;
392 (void)user_data;
393
394 *data_flags |= NGHTTP2_DATA_FLAG_EOF | NGHTTP2_DATA_FLAG_NO_END_STREAM;
395 return 0;
396 }
397
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)398 static ssize_t no_copy_data_source_read_callback(
399 nghttp2_session *session, int32_t stream_id, uint8_t *buf, size_t len,
400 uint32_t *data_flags, nghttp2_data_source *source, void *user_data) {
401 my_user_data *ud = (my_user_data *)user_data;
402 size_t wlen;
403 (void)session;
404 (void)stream_id;
405 (void)buf;
406 (void)source;
407
408 if (len < ud->data_source_length) {
409 wlen = len;
410 } else {
411 wlen = ud->data_source_length;
412 }
413
414 ud->data_source_length -= wlen;
415
416 *data_flags |= NGHTTP2_DATA_FLAG_NO_COPY;
417
418 if (ud->data_source_length == 0) {
419 *data_flags |= NGHTTP2_DATA_FLAG_EOF;
420 }
421 return (ssize_t)wlen;
422 }
423
send_data_callback(nghttp2_session * session,nghttp2_frame * frame,const uint8_t * framehd,size_t length,nghttp2_data_source * source,void * user_data)424 static int send_data_callback(nghttp2_session *session, nghttp2_frame *frame,
425 const uint8_t *framehd, size_t length,
426 nghttp2_data_source *source, void *user_data) {
427 accumulator *acc = ((my_user_data *)user_data)->acc;
428 (void)session;
429 (void)source;
430
431 memcpy(acc->buf + acc->length, framehd, NGHTTP2_FRAME_HDLEN);
432 acc->length += NGHTTP2_FRAME_HDLEN;
433
434 if (frame->data.padlen) {
435 *(acc->buf + acc->length++) = (uint8_t)(frame->data.padlen - 1);
436 }
437
438 acc->length += length;
439
440 if (frame->data.padlen) {
441 acc->length += frame->data.padlen - 1;
442 }
443
444 return 0;
445 }
446
block_count_send_callback(nghttp2_session * session,const uint8_t * data,size_t len,int flags,void * user_data)447 static ssize_t block_count_send_callback(nghttp2_session *session,
448 const uint8_t *data, size_t len,
449 int flags, void *user_data) {
450 my_user_data *ud = (my_user_data *)user_data;
451 (void)session;
452 (void)data;
453 (void)flags;
454
455 if (ud->block_count == 0) {
456 return NGHTTP2_ERR_WOULDBLOCK;
457 }
458
459 --ud->block_count;
460 return (ssize_t)len;
461 }
462
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)463 static int on_header_callback(nghttp2_session *session,
464 const nghttp2_frame *frame, const uint8_t *name,
465 size_t namelen, const uint8_t *value,
466 size_t valuelen, uint8_t flags, void *user_data) {
467 my_user_data *ud = (my_user_data *)user_data;
468 (void)session;
469 (void)flags;
470
471 ++ud->header_cb_called;
472 ud->nv.name = (uint8_t *)name;
473 ud->nv.namelen = namelen;
474 ud->nv.value = (uint8_t *)value;
475 ud->nv.valuelen = valuelen;
476
477 ud->frame = frame;
478 return 0;
479 }
480
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)481 static int pause_on_header_callback(nghttp2_session *session,
482 const nghttp2_frame *frame,
483 const uint8_t *name, size_t namelen,
484 const uint8_t *value, size_t valuelen,
485 uint8_t flags, void *user_data) {
486 on_header_callback(session, frame, name, namelen, value, valuelen, flags,
487 user_data);
488 return NGHTTP2_ERR_PAUSE;
489 }
490
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)491 static int temporal_failure_on_header_callback(
492 nghttp2_session *session, const nghttp2_frame *frame, const uint8_t *name,
493 size_t namelen, const uint8_t *value, size_t valuelen, uint8_t flags,
494 void *user_data) {
495 on_header_callback(session, frame, name, namelen, value, valuelen, flags,
496 user_data);
497 return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
498 }
499
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)500 static int on_invalid_header_callback(nghttp2_session *session,
501 const nghttp2_frame *frame,
502 const uint8_t *name, size_t namelen,
503 const uint8_t *value, size_t valuelen,
504 uint8_t flags, void *user_data) {
505 my_user_data *ud = (my_user_data *)user_data;
506 (void)session;
507 (void)flags;
508
509 ++ud->invalid_header_cb_called;
510 ud->nv.name = (uint8_t *)name;
511 ud->nv.namelen = namelen;
512 ud->nv.value = (uint8_t *)value;
513 ud->nv.valuelen = valuelen;
514
515 ud->frame = frame;
516 return 0;
517 }
518
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)519 static int pause_on_invalid_header_callback(nghttp2_session *session,
520 const nghttp2_frame *frame,
521 const uint8_t *name, size_t namelen,
522 const uint8_t *value,
523 size_t valuelen, uint8_t flags,
524 void *user_data) {
525 on_invalid_header_callback(session, frame, name, namelen, value, valuelen,
526 flags, user_data);
527 return NGHTTP2_ERR_PAUSE;
528 }
529
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)530 static int reset_on_invalid_header_callback(nghttp2_session *session,
531 const nghttp2_frame *frame,
532 const uint8_t *name, size_t namelen,
533 const uint8_t *value,
534 size_t valuelen, uint8_t flags,
535 void *user_data) {
536 on_invalid_header_callback(session, frame, name, namelen, value, valuelen,
537 flags, user_data);
538 return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
539 }
540
on_begin_headers_callback(nghttp2_session * session,const nghttp2_frame * frame,void * user_data)541 static int on_begin_headers_callback(nghttp2_session *session,
542 const nghttp2_frame *frame,
543 void *user_data) {
544 my_user_data *ud = (my_user_data *)user_data;
545 (void)session;
546 (void)frame;
547
548 ++ud->begin_headers_cb_called;
549 return 0;
550 }
551
temporal_failure_on_begin_headers_callback(nghttp2_session * session,const nghttp2_frame * frame,void * user_data)552 static int temporal_failure_on_begin_headers_callback(
553 nghttp2_session *session, const nghttp2_frame *frame, void *user_data) {
554 on_begin_headers_callback(session, frame, user_data);
555 return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
556 }
557
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)558 static ssize_t defer_data_source_read_callback(nghttp2_session *session,
559 int32_t stream_id, uint8_t *buf,
560 size_t len, uint32_t *data_flags,
561 nghttp2_data_source *source,
562 void *user_data) {
563 (void)session;
564 (void)stream_id;
565 (void)buf;
566 (void)len;
567 (void)data_flags;
568 (void)source;
569 (void)user_data;
570
571 return NGHTTP2_ERR_DEFERRED;
572 }
573
on_stream_close_callback(nghttp2_session * session,int32_t stream_id,uint32_t error_code,void * user_data)574 static int on_stream_close_callback(nghttp2_session *session, int32_t stream_id,
575 uint32_t error_code, void *user_data) {
576 my_user_data *my_data = (my_user_data *)user_data;
577 (void)session;
578 (void)stream_id;
579 (void)error_code;
580
581 ++my_data->stream_close_cb_called;
582 my_data->stream_close_error_code = error_code;
583
584 return 0;
585 }
586
fatal_error_on_stream_close_callback(nghttp2_session * session,int32_t stream_id,uint32_t error_code,void * user_data)587 static int fatal_error_on_stream_close_callback(nghttp2_session *session,
588 int32_t stream_id,
589 uint32_t error_code,
590 void *user_data) {
591 on_stream_close_callback(session, stream_id, error_code, user_data);
592
593 return NGHTTP2_ERR_CALLBACK_FAILURE;
594 }
595
pack_extension_callback(nghttp2_session * session,uint8_t * buf,size_t len,const nghttp2_frame * frame,void * user_data)596 static ssize_t pack_extension_callback(nghttp2_session *session, uint8_t *buf,
597 size_t len, const nghttp2_frame *frame,
598 void *user_data) {
599 nghttp2_buf *p = frame->ext.payload;
600 (void)session;
601 (void)len;
602 (void)user_data;
603
604 memcpy(buf, p->pos, nghttp2_buf_len(p));
605
606 return (ssize_t)nghttp2_buf_len(p);
607 }
608
on_extension_chunk_recv_callback(nghttp2_session * session,const nghttp2_frame_hd * hd,const uint8_t * data,size_t len,void * user_data)609 static int on_extension_chunk_recv_callback(nghttp2_session *session,
610 const nghttp2_frame_hd *hd,
611 const uint8_t *data, size_t len,
612 void *user_data) {
613 my_user_data *my_data = (my_user_data *)user_data;
614 nghttp2_buf *buf = &my_data->scratchbuf;
615 (void)session;
616 (void)hd;
617
618 buf->last = nghttp2_cpymem(buf->last, data, len);
619
620 return 0;
621 }
622
cancel_on_extension_chunk_recv_callback(nghttp2_session * session,const nghttp2_frame_hd * hd,const uint8_t * data,size_t len,void * user_data)623 static int cancel_on_extension_chunk_recv_callback(nghttp2_session *session,
624 const nghttp2_frame_hd *hd,
625 const uint8_t *data,
626 size_t len,
627 void *user_data) {
628 (void)session;
629 (void)hd;
630 (void)data;
631 (void)len;
632 (void)user_data;
633
634 return NGHTTP2_ERR_CANCEL;
635 }
636
unpack_extension_callback(nghttp2_session * session,void ** payload,const nghttp2_frame_hd * hd,void * user_data)637 static int unpack_extension_callback(nghttp2_session *session, void **payload,
638 const nghttp2_frame_hd *hd,
639 void *user_data) {
640 my_user_data *my_data = (my_user_data *)user_data;
641 nghttp2_buf *buf = &my_data->scratchbuf;
642 (void)session;
643 (void)hd;
644
645 *payload = buf;
646
647 return 0;
648 }
649
cancel_unpack_extension_callback(nghttp2_session * session,void ** payload,const nghttp2_frame_hd * hd,void * user_data)650 static int cancel_unpack_extension_callback(nghttp2_session *session,
651 void **payload,
652 const nghttp2_frame_hd *hd,
653 void *user_data) {
654 (void)session;
655 (void)payload;
656 (void)hd;
657 (void)user_data;
658
659 return NGHTTP2_ERR_CANCEL;
660 }
661
dup_iv(const nghttp2_settings_entry * iv,size_t niv)662 static nghttp2_settings_entry *dup_iv(const nghttp2_settings_entry *iv,
663 size_t niv) {
664 return nghttp2_frame_iv_copy(iv, niv, nghttp2_mem_default());
665 }
666
667 static nghttp2_priority_spec pri_spec_default = {0, NGHTTP2_DEFAULT_WEIGHT, 0};
668
test_nghttp2_session_recv(void)669 void test_nghttp2_session_recv(void) {
670 nghttp2_session *session;
671 nghttp2_session_callbacks callbacks;
672 scripted_data_feed df;
673 my_user_data user_data;
674 nghttp2_bufs bufs;
675 size_t framelen;
676 nghttp2_frame frame;
677 size_t i;
678 nghttp2_outbound_item *item;
679 nghttp2_nv *nva;
680 size_t nvlen;
681 nghttp2_hd_deflater deflater;
682 int rv;
683 nghttp2_mem *mem;
684
685 mem = nghttp2_mem_default();
686 frame_pack_bufs_init(&bufs);
687
688 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
689 callbacks.send_callback = null_send_callback;
690 callbacks.recv_callback = scripted_recv_callback;
691 callbacks.on_frame_recv_callback = on_frame_recv_callback;
692 callbacks.on_begin_frame_callback = on_begin_frame_callback;
693
694 user_data.df = &df;
695
696 nghttp2_session_server_new(&session, &callbacks, &user_data);
697 nghttp2_hd_deflate_init(&deflater, mem);
698
699 nvlen = ARRLEN(reqnv);
700 nghttp2_nv_array_copy(&nva, reqnv, nvlen, mem);
701 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 1,
702 NGHTTP2_HCAT_HEADERS, NULL, nva, nvlen);
703 rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
704
705 CU_ASSERT(0 == rv);
706
707 scripted_data_feed_init2(&df, &bufs);
708
709 framelen = nghttp2_bufs_len(&bufs);
710
711 /* Send 1 byte per each read */
712 for (i = 0; i < framelen; ++i) {
713 df.feedseq[i] = 1;
714 }
715
716 nghttp2_frame_headers_free(&frame.headers, mem);
717
718 user_data.frame_recv_cb_called = 0;
719 user_data.begin_frame_cb_called = 0;
720
721 while (df.seqidx < framelen) {
722 CU_ASSERT(0 == nghttp2_session_recv(session));
723 }
724 CU_ASSERT(1 == user_data.frame_recv_cb_called);
725 CU_ASSERT(1 == user_data.begin_frame_cb_called);
726
727 nghttp2_bufs_reset(&bufs);
728
729 /* Receive PRIORITY */
730 nghttp2_frame_priority_init(&frame.priority, 5, &pri_spec_default);
731
732 nghttp2_frame_pack_priority(&bufs, &frame.priority);
733
734 nghttp2_frame_priority_free(&frame.priority);
735
736 scripted_data_feed_init2(&df, &bufs);
737
738 user_data.frame_recv_cb_called = 0;
739 user_data.begin_frame_cb_called = 0;
740
741 CU_ASSERT(0 == nghttp2_session_recv(session));
742 CU_ASSERT(1 == user_data.frame_recv_cb_called);
743 CU_ASSERT(1 == user_data.begin_frame_cb_called);
744
745 nghttp2_bufs_reset(&bufs);
746
747 nghttp2_hd_deflate_free(&deflater);
748 nghttp2_session_del(session);
749
750 /* Some tests for frame too large */
751 nghttp2_session_server_new(&session, &callbacks, &user_data);
752
753 /* Receive PING with too large payload */
754 nghttp2_frame_ping_init(&frame.ping, NGHTTP2_FLAG_NONE, NULL);
755
756 nghttp2_frame_pack_ping(&bufs, &frame.ping);
757
758 /* Add extra 16 bytes */
759 nghttp2_bufs_seek_last_present(&bufs);
760 assert(nghttp2_buf_len(&bufs.cur->buf) >= 16);
761
762 bufs.cur->buf.last += 16;
763 nghttp2_put_uint32be(
764 bufs.cur->buf.pos,
765 (uint32_t)(((frame.hd.length + 16) << 8) + bufs.cur->buf.pos[3]));
766
767 nghttp2_frame_ping_free(&frame.ping);
768
769 scripted_data_feed_init2(&df, &bufs);
770 user_data.frame_recv_cb_called = 0;
771 user_data.begin_frame_cb_called = 0;
772
773 CU_ASSERT(0 == nghttp2_session_recv(session));
774 CU_ASSERT(0 == user_data.frame_recv_cb_called);
775 CU_ASSERT(0 == user_data.begin_frame_cb_called);
776
777 item = nghttp2_session_get_next_ob_item(session);
778 CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
779 CU_ASSERT(NGHTTP2_FRAME_SIZE_ERROR == item->frame.goaway.error_code);
780 CU_ASSERT(0 == nghttp2_session_send(session));
781
782 nghttp2_bufs_free(&bufs);
783 nghttp2_session_del(session);
784 }
785
test_nghttp2_session_recv_invalid_stream_id(void)786 void test_nghttp2_session_recv_invalid_stream_id(void) {
787 nghttp2_session *session;
788 nghttp2_session_callbacks callbacks;
789 scripted_data_feed df;
790 my_user_data user_data;
791 nghttp2_bufs bufs;
792 nghttp2_frame frame;
793 nghttp2_hd_deflater deflater;
794 int rv;
795 nghttp2_mem *mem;
796 nghttp2_nv *nva;
797 size_t nvlen;
798
799 mem = nghttp2_mem_default();
800 frame_pack_bufs_init(&bufs);
801
802 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
803 callbacks.recv_callback = scripted_recv_callback;
804 callbacks.on_invalid_frame_recv_callback = on_invalid_frame_recv_callback;
805
806 user_data.df = &df;
807 user_data.invalid_frame_recv_cb_called = 0;
808 nghttp2_session_server_new(&session, &callbacks, &user_data);
809 nghttp2_hd_deflate_init(&deflater, mem);
810
811 nvlen = ARRLEN(reqnv);
812 nghttp2_nv_array_copy(&nva, reqnv, nvlen, mem);
813 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 2,
814 NGHTTP2_HCAT_HEADERS, NULL, nva, nvlen);
815 rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
816
817 CU_ASSERT(0 == rv);
818 CU_ASSERT(nghttp2_bufs_len(&bufs) > 0);
819
820 scripted_data_feed_init2(&df, &bufs);
821 nghttp2_frame_headers_free(&frame.headers, mem);
822
823 CU_ASSERT(0 == nghttp2_session_recv(session));
824 CU_ASSERT(1 == user_data.invalid_frame_recv_cb_called);
825
826 nghttp2_bufs_free(&bufs);
827 nghttp2_hd_deflate_free(&deflater);
828 nghttp2_session_del(session);
829 }
830
test_nghttp2_session_recv_invalid_frame(void)831 void test_nghttp2_session_recv_invalid_frame(void) {
832 nghttp2_session *session;
833 nghttp2_session_callbacks callbacks;
834 scripted_data_feed df;
835 my_user_data user_data;
836 nghttp2_bufs bufs;
837 nghttp2_frame frame;
838 nghttp2_nv *nva;
839 size_t nvlen;
840 nghttp2_hd_deflater deflater;
841 int rv;
842 nghttp2_mem *mem;
843
844 mem = nghttp2_mem_default();
845 frame_pack_bufs_init(&bufs);
846
847 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
848 callbacks.recv_callback = scripted_recv_callback;
849 callbacks.send_callback = null_send_callback;
850 callbacks.on_frame_send_callback = on_frame_send_callback;
851
852 user_data.df = &df;
853 user_data.frame_send_cb_called = 0;
854 nghttp2_session_server_new(&session, &callbacks, &user_data);
855 nghttp2_hd_deflate_init(&deflater, mem);
856 nvlen = ARRLEN(reqnv);
857 nghttp2_nv_array_copy(&nva, reqnv, nvlen, mem);
858 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 1,
859 NGHTTP2_HCAT_HEADERS, NULL, nva, nvlen);
860 rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
861
862 CU_ASSERT(0 == rv);
863 CU_ASSERT(nghttp2_bufs_len(&bufs) > 0);
864
865 scripted_data_feed_init2(&df, &bufs);
866
867 CU_ASSERT(0 == nghttp2_session_recv(session));
868 CU_ASSERT(0 == nghttp2_session_send(session));
869 CU_ASSERT(0 == user_data.frame_send_cb_called);
870
871 /* Receive exactly same bytes of HEADERS is treated as error, because it has
872 * pseudo headers and without END_STREAM flag set */
873 scripted_data_feed_init2(&df, &bufs);
874
875 CU_ASSERT(0 == nghttp2_session_recv(session));
876 CU_ASSERT(0 == nghttp2_session_send(session));
877 CU_ASSERT(1 == user_data.frame_send_cb_called);
878 CU_ASSERT(NGHTTP2_RST_STREAM == user_data.sent_frame_type);
879
880 nghttp2_bufs_free(&bufs);
881 nghttp2_frame_headers_free(&frame.headers, mem);
882
883 nghttp2_hd_deflate_free(&deflater);
884 nghttp2_session_del(session);
885 }
886
test_nghttp2_session_recv_eof(void)887 void test_nghttp2_session_recv_eof(void) {
888 nghttp2_session *session;
889 nghttp2_session_callbacks callbacks;
890
891 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
892 callbacks.send_callback = null_send_callback;
893 callbacks.recv_callback = eof_recv_callback;
894
895 nghttp2_session_client_new(&session, &callbacks, NULL);
896 CU_ASSERT(NGHTTP2_ERR_EOF == nghttp2_session_recv(session));
897
898 nghttp2_session_del(session);
899 }
900
test_nghttp2_session_recv_data(void)901 void test_nghttp2_session_recv_data(void) {
902 nghttp2_session *session;
903 nghttp2_session_callbacks callbacks;
904 my_user_data ud;
905 uint8_t data[8092];
906 ssize_t rv;
907 nghttp2_outbound_item *item;
908 nghttp2_stream *stream;
909 nghttp2_frame_hd hd;
910 int i;
911
912 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
913 callbacks.send_callback = null_send_callback;
914 callbacks.on_data_chunk_recv_callback = on_data_chunk_recv_callback;
915 callbacks.on_frame_recv_callback = on_frame_recv_callback;
916 callbacks.on_frame_send_callback = on_frame_send_callback;
917
918 nghttp2_session_client_new(&session, &callbacks, &ud);
919
920 /* Create DATA frame with length 4KiB */
921 memset(data, 0, sizeof(data));
922 hd.length = 4096;
923 hd.type = NGHTTP2_DATA;
924 hd.flags = NGHTTP2_FLAG_NONE;
925 hd.stream_id = 1;
926 nghttp2_frame_pack_frame_hd(data, &hd);
927
928 /* stream 1 is not opened, so it must be responded with connection
929 error. This is not mandated by the spec */
930 ud.data_chunk_recv_cb_called = 0;
931 ud.frame_recv_cb_called = 0;
932 rv = nghttp2_session_mem_recv(session, data, NGHTTP2_FRAME_HDLEN + 4096);
933 CU_ASSERT(NGHTTP2_FRAME_HDLEN + 4096 == rv);
934
935 CU_ASSERT(0 == ud.data_chunk_recv_cb_called);
936 CU_ASSERT(0 == ud.frame_recv_cb_called);
937 item = nghttp2_session_get_next_ob_item(session);
938 CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
939
940 nghttp2_session_del(session);
941
942 nghttp2_session_client_new(&session, &callbacks, &ud);
943
944 /* Create stream 1 with CLOSING state. DATA is ignored. */
945 stream = open_sent_stream2(session, 1, NGHTTP2_STREAM_CLOSING);
946
947 /* Set initial window size 16383 to check stream flow control,
948 isolating it from the connection flow control */
949 stream->local_window_size = 16383;
950
951 ud.data_chunk_recv_cb_called = 0;
952 ud.frame_recv_cb_called = 0;
953 rv = nghttp2_session_mem_recv(session, data, NGHTTP2_FRAME_HDLEN + 4096);
954 CU_ASSERT(NGHTTP2_FRAME_HDLEN + 4096 == rv);
955
956 CU_ASSERT(0 == ud.data_chunk_recv_cb_called);
957 CU_ASSERT(0 == ud.frame_recv_cb_called);
958 item = nghttp2_session_get_next_ob_item(session);
959 CU_ASSERT(NULL == item);
960
961 /* This is normal case. DATA is acceptable. */
962 stream->state = NGHTTP2_STREAM_OPENED;
963
964 ud.data_chunk_recv_cb_called = 0;
965 ud.frame_recv_cb_called = 0;
966 rv = nghttp2_session_mem_recv(session, data, NGHTTP2_FRAME_HDLEN + 4096);
967 CU_ASSERT(NGHTTP2_FRAME_HDLEN + 4096 == rv);
968
969 CU_ASSERT(1 == ud.data_chunk_recv_cb_called);
970 CU_ASSERT(1 == ud.frame_recv_cb_called);
971
972 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
973
974 ud.data_chunk_recv_cb_called = 0;
975 ud.frame_recv_cb_called = 0;
976 rv = nghttp2_session_mem_recv(session, data, NGHTTP2_FRAME_HDLEN + 4096);
977 CU_ASSERT(NGHTTP2_FRAME_HDLEN + 4096 == rv);
978
979 /* Now we got data more than initial-window-size / 2, WINDOW_UPDATE
980 must be queued */
981 CU_ASSERT(1 == ud.data_chunk_recv_cb_called);
982 CU_ASSERT(1 == ud.frame_recv_cb_called);
983 item = nghttp2_session_get_next_ob_item(session);
984 CU_ASSERT(NGHTTP2_WINDOW_UPDATE == item->frame.hd.type);
985 CU_ASSERT(1 == item->frame.window_update.hd.stream_id);
986 CU_ASSERT(0 == nghttp2_session_send(session));
987
988 /* Set initial window size to 1MiB, so that we can check connection
989 flow control individually */
990 stream->local_window_size = 1 << 20;
991 /* Connection flow control takes into account DATA which is received
992 in the error condition. We have received 4096 * 4 bytes of
993 DATA. Additional 4 DATA frames, connection flow control will kick
994 in. */
995 for (i = 0; i < 5; ++i) {
996 rv = nghttp2_session_mem_recv(session, data, NGHTTP2_FRAME_HDLEN + 4096);
997 CU_ASSERT(NGHTTP2_FRAME_HDLEN + 4096 == rv);
998 }
999 item = nghttp2_session_get_next_ob_item(session);
1000 CU_ASSERT(NGHTTP2_WINDOW_UPDATE == item->frame.hd.type);
1001 CU_ASSERT(0 == item->frame.window_update.hd.stream_id);
1002 CU_ASSERT(0 == nghttp2_session_send(session));
1003
1004 /* Reception of DATA with stream ID = 0 causes connection error */
1005 hd.length = 4096;
1006 hd.type = NGHTTP2_DATA;
1007 hd.flags = NGHTTP2_FLAG_NONE;
1008 hd.stream_id = 0;
1009 nghttp2_frame_pack_frame_hd(data, &hd);
1010
1011 ud.data_chunk_recv_cb_called = 0;
1012 ud.frame_recv_cb_called = 0;
1013 rv = nghttp2_session_mem_recv(session, data, NGHTTP2_FRAME_HDLEN + 4096);
1014 CU_ASSERT(NGHTTP2_FRAME_HDLEN + 4096 == rv);
1015
1016 CU_ASSERT(0 == ud.data_chunk_recv_cb_called);
1017 CU_ASSERT(0 == ud.frame_recv_cb_called);
1018 item = nghttp2_session_get_next_ob_item(session);
1019 CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
1020 CU_ASSERT(NGHTTP2_PROTOCOL_ERROR == item->frame.goaway.error_code);
1021
1022 nghttp2_session_del(session);
1023
1024 /* Check window_update_queued flag in both session and stream */
1025 nghttp2_session_server_new(&session, &callbacks, &ud);
1026
1027 hd.length = 4096;
1028 hd.type = NGHTTP2_DATA;
1029 hd.flags = NGHTTP2_FLAG_NONE;
1030 hd.stream_id = 1;
1031 nghttp2_frame_pack_frame_hd(data, &hd);
1032
1033 stream = open_recv_stream(session, 1);
1034
1035 /* Send 32767 bytes of DATA. In our current flow control algorithm,
1036 it triggers first WINDOW_UPDATE of window_size_increment
1037 32767. */
1038 for (i = 0; i < 7; ++i) {
1039 rv = nghttp2_session_mem_recv(session, data, NGHTTP2_FRAME_HDLEN + 4096);
1040 CU_ASSERT(NGHTTP2_FRAME_HDLEN + 4096 == rv);
1041 }
1042
1043 hd.length = 4095;
1044 nghttp2_frame_pack_frame_hd(data, &hd);
1045 rv = nghttp2_session_mem_recv(session, data, NGHTTP2_FRAME_HDLEN + 4095);
1046 CU_ASSERT(NGHTTP2_FRAME_HDLEN + 4095 == rv);
1047
1048 /* Now 2 WINDOW_UPDATEs for session and stream should be queued. */
1049 CU_ASSERT(0 == stream->recv_window_size);
1050 CU_ASSERT(0 == session->recv_window_size);
1051 CU_ASSERT(1 == stream->window_update_queued);
1052 CU_ASSERT(1 == session->window_update_queued);
1053
1054 /* Then send 32768 bytes of DATA. Since we have not sent queued
1055 WINDOW_UDPATE frame, recv_window_size should not be decreased */
1056 hd.length = 4096;
1057 nghttp2_frame_pack_frame_hd(data, &hd);
1058
1059 for (i = 0; i < 8; ++i) {
1060 rv = nghttp2_session_mem_recv(session, data, NGHTTP2_FRAME_HDLEN + 4096);
1061 CU_ASSERT(NGHTTP2_FRAME_HDLEN + 4096 == rv);
1062 }
1063
1064 /* WINDOW_UPDATE is blocked for session and stream, so
1065 recv_window_size must not be decreased. */
1066 CU_ASSERT(32768 == stream->recv_window_size);
1067 CU_ASSERT(32768 == session->recv_window_size);
1068 CU_ASSERT(1 == stream->window_update_queued);
1069 CU_ASSERT(1 == session->window_update_queued);
1070
1071 ud.frame_send_cb_called = 0;
1072
1073 /* This sends queued WINDOW_UPDATES. And then check
1074 recv_window_size, and queue WINDOW_UPDATEs for both session and
1075 stream, and send them at once. */
1076 CU_ASSERT(0 == nghttp2_session_send(session));
1077
1078 CU_ASSERT(4 == ud.frame_send_cb_called);
1079 CU_ASSERT(0 == stream->recv_window_size);
1080 CU_ASSERT(0 == session->recv_window_size);
1081 CU_ASSERT(0 == stream->window_update_queued);
1082 CU_ASSERT(0 == session->window_update_queued);
1083
1084 nghttp2_session_del(session);
1085 }
1086
test_nghttp2_session_recv_data_no_auto_flow_control(void)1087 void test_nghttp2_session_recv_data_no_auto_flow_control(void) {
1088 nghttp2_session *session;
1089 nghttp2_session_callbacks callbacks;
1090 my_user_data ud;
1091 nghttp2_option *option;
1092 nghttp2_frame_hd hd;
1093 size_t padlen;
1094 uint8_t data[8192];
1095 ssize_t rv;
1096 size_t sendlen;
1097 nghttp2_stream *stream;
1098 size_t i;
1099
1100 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
1101 callbacks.send_callback = null_send_callback;
1102 callbacks.on_frame_send_callback = on_frame_send_callback;
1103
1104 nghttp2_option_new(&option);
1105 nghttp2_option_set_no_auto_window_update(option, 1);
1106
1107 nghttp2_session_server_new2(&session, &callbacks, &ud, option);
1108
1109 /* Create DATA frame with length 4KiB + 11 bytes padding*/
1110 padlen = 11;
1111 memset(data, 0, sizeof(data));
1112 hd.length = 4096 + 1 + padlen;
1113 hd.type = NGHTTP2_DATA;
1114 hd.flags = NGHTTP2_FLAG_PADDED;
1115 hd.stream_id = 1;
1116 nghttp2_frame_pack_frame_hd(data, &hd);
1117 data[NGHTTP2_FRAME_HDLEN] = (uint8_t)padlen;
1118
1119 /* First create stream 1, then close it. Check that data is
1120 consumed for connection in this situation */
1121 open_recv_stream(session, 1);
1122
1123 /* Receive first 100 bytes */
1124 sendlen = 100;
1125 rv = nghttp2_session_mem_recv(session, data, sendlen);
1126 CU_ASSERT((ssize_t)sendlen == rv);
1127
1128 /* We consumed pad length field (1 byte) */
1129 CU_ASSERT(1 == session->consumed_size);
1130
1131 /* close stream here */
1132 nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, 1, NGHTTP2_NO_ERROR);
1133 nghttp2_session_send(session);
1134
1135 /* stream 1 has been closed, and we disabled auto flow-control, so
1136 data must be immediately consumed for connection. */
1137 rv = nghttp2_session_mem_recv(session, data + sendlen,
1138 NGHTTP2_FRAME_HDLEN + hd.length - sendlen);
1139 CU_ASSERT((ssize_t)(NGHTTP2_FRAME_HDLEN + hd.length - sendlen) == rv);
1140
1141 /* We already consumed pad length field (1 byte), so do +1 here */
1142 CU_ASSERT((int32_t)(NGHTTP2_FRAME_HDLEN + hd.length - sendlen + 1) ==
1143 session->consumed_size);
1144
1145 nghttp2_session_del(session);
1146
1147 /* Reuse DATA created previously. */
1148
1149 nghttp2_session_server_new2(&session, &callbacks, &ud, option);
1150
1151 /* Now we are expecting final response header, which means receiving
1152 DATA for that stream is illegal. */
1153 stream = open_recv_stream(session, 1);
1154 stream->http_flags |= NGHTTP2_HTTP_FLAG_EXPECT_FINAL_RESPONSE;
1155
1156 rv = nghttp2_session_mem_recv(session, data, NGHTTP2_FRAME_HDLEN + hd.length);
1157 CU_ASSERT((ssize_t)(NGHTTP2_FRAME_HDLEN + hd.length) == rv);
1158
1159 /* Whole payload must be consumed now because HTTP messaging rule
1160 was not honored. */
1161 CU_ASSERT((int32_t)hd.length == session->consumed_size);
1162
1163 nghttp2_session_del(session);
1164
1165 /* Check window_update_queued flag in both session and stream */
1166 nghttp2_session_server_new2(&session, &callbacks, &ud, option);
1167
1168 stream = open_recv_stream(session, 1);
1169
1170 hd.length = 4096;
1171 hd.type = NGHTTP2_DATA;
1172 hd.flags = NGHTTP2_FLAG_NONE;
1173 hd.stream_id = 1;
1174 nghttp2_frame_pack_frame_hd(data, &hd);
1175
1176 /* Receive up to 65535 bytes of DATA */
1177 for (i = 0; i < 15; ++i) {
1178 rv = nghttp2_session_mem_recv(session, data, NGHTTP2_FRAME_HDLEN + 4096);
1179 CU_ASSERT(NGHTTP2_FRAME_HDLEN + 4096 == rv);
1180 }
1181
1182 hd.length = 4095;
1183 nghttp2_frame_pack_frame_hd(data, &hd);
1184
1185 rv = nghttp2_session_mem_recv(session, data, NGHTTP2_FRAME_HDLEN + 4095);
1186 CU_ASSERT(NGHTTP2_FRAME_HDLEN + 4095 == rv);
1187
1188 CU_ASSERT(65535 == session->recv_window_size);
1189 CU_ASSERT(65535 == stream->recv_window_size);
1190
1191 /* The first call of nghttp2_session_consume_connection() will queue
1192 WINDOW_UPDATE. Next call does not. */
1193 nghttp2_session_consume_connection(session, 32767);
1194 nghttp2_session_consume_connection(session, 32768);
1195
1196 CU_ASSERT(32768 == session->recv_window_size);
1197 CU_ASSERT(65535 == stream->recv_window_size);
1198 CU_ASSERT(1 == session->window_update_queued);
1199 CU_ASSERT(0 == stream->window_update_queued);
1200
1201 ud.frame_send_cb_called = 0;
1202
1203 /* This will send WINDOW_UPDATE, and check whether we should send
1204 WINDOW_UPDATE, and queue and send it at once. */
1205 CU_ASSERT(0 == nghttp2_session_send(session));
1206 CU_ASSERT(0 == session->recv_window_size);
1207 CU_ASSERT(65535 == stream->recv_window_size);
1208 CU_ASSERT(0 == session->window_update_queued);
1209 CU_ASSERT(0 == stream->window_update_queued);
1210 CU_ASSERT(2 == ud.frame_send_cb_called);
1211
1212 /* Do the same for stream */
1213 nghttp2_session_consume_stream(session, 1, 32767);
1214 nghttp2_session_consume_stream(session, 1, 32768);
1215
1216 CU_ASSERT(0 == session->recv_window_size);
1217 CU_ASSERT(32768 == stream->recv_window_size);
1218 CU_ASSERT(0 == session->window_update_queued);
1219 CU_ASSERT(1 == stream->window_update_queued);
1220
1221 ud.frame_send_cb_called = 0;
1222
1223 CU_ASSERT(0 == nghttp2_session_send(session));
1224 CU_ASSERT(0 == session->recv_window_size);
1225 CU_ASSERT(0 == stream->recv_window_size);
1226 CU_ASSERT(0 == session->window_update_queued);
1227 CU_ASSERT(0 == stream->window_update_queued);
1228 CU_ASSERT(2 == ud.frame_send_cb_called);
1229
1230 nghttp2_session_del(session);
1231 nghttp2_option_del(option);
1232 }
1233
test_nghttp2_session_recv_continuation(void)1234 void test_nghttp2_session_recv_continuation(void) {
1235 nghttp2_session *session;
1236 nghttp2_session_callbacks callbacks;
1237 nghttp2_nv *nva;
1238 size_t nvlen;
1239 nghttp2_frame frame;
1240 nghttp2_bufs bufs;
1241 nghttp2_buf *buf;
1242 ssize_t rv;
1243 my_user_data ud;
1244 nghttp2_hd_deflater deflater;
1245 uint8_t data[1024];
1246 size_t datalen;
1247 nghttp2_frame_hd cont_hd;
1248 nghttp2_priority_spec pri_spec;
1249 nghttp2_mem *mem;
1250
1251 mem = nghttp2_mem_default();
1252 frame_pack_bufs_init(&bufs);
1253
1254 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
1255 callbacks.on_header_callback = on_header_callback;
1256 callbacks.on_begin_headers_callback = on_begin_headers_callback;
1257 callbacks.on_begin_frame_callback = on_begin_frame_callback;
1258
1259 nghttp2_session_server_new(&session, &callbacks, &ud);
1260
1261 nghttp2_hd_deflate_init(&deflater, mem);
1262
1263 /* Make 1 HEADERS and insert CONTINUATION header */
1264 nvlen = ARRLEN(reqnv);
1265 nghttp2_nv_array_copy(&nva, reqnv, nvlen, mem);
1266 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_NONE, 1,
1267 NGHTTP2_HCAT_HEADERS, NULL, nva, nvlen);
1268 rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
1269
1270 CU_ASSERT(0 == rv);
1271 CU_ASSERT(nghttp2_bufs_len(&bufs) > 0);
1272
1273 /* make sure that all data is in the first buf */
1274 buf = &bufs.head->buf;
1275 assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
1276
1277 nghttp2_frame_headers_free(&frame.headers, mem);
1278
1279 /* HEADERS's payload is 1 byte */
1280 memcpy(data, buf->pos, NGHTTP2_FRAME_HDLEN + 1);
1281 datalen = NGHTTP2_FRAME_HDLEN + 1;
1282 buf->pos += NGHTTP2_FRAME_HDLEN + 1;
1283
1284 nghttp2_put_uint32be(data, (uint32_t)((1 << 8) + data[3]));
1285
1286 /* First CONTINUATION, 2 bytes */
1287 nghttp2_frame_hd_init(&cont_hd, 2, NGHTTP2_CONTINUATION, NGHTTP2_FLAG_NONE,
1288 1);
1289
1290 nghttp2_frame_pack_frame_hd(data + datalen, &cont_hd);
1291 datalen += NGHTTP2_FRAME_HDLEN;
1292
1293 memcpy(data + datalen, buf->pos, cont_hd.length);
1294 datalen += cont_hd.length;
1295 buf->pos += cont_hd.length;
1296
1297 /* Second CONTINUATION, rest of the bytes */
1298 nghttp2_frame_hd_init(&cont_hd, nghttp2_buf_len(buf), NGHTTP2_CONTINUATION,
1299 NGHTTP2_FLAG_END_HEADERS, 1);
1300
1301 nghttp2_frame_pack_frame_hd(data + datalen, &cont_hd);
1302 datalen += NGHTTP2_FRAME_HDLEN;
1303
1304 memcpy(data + datalen, buf->pos, cont_hd.length);
1305 datalen += cont_hd.length;
1306 buf->pos += cont_hd.length;
1307
1308 CU_ASSERT(0 == nghttp2_buf_len(buf));
1309
1310 ud.header_cb_called = 0;
1311 ud.begin_frame_cb_called = 0;
1312
1313 rv = nghttp2_session_mem_recv(session, data, datalen);
1314 CU_ASSERT((ssize_t)datalen == rv);
1315 CU_ASSERT(4 == ud.header_cb_called);
1316 CU_ASSERT(3 == ud.begin_frame_cb_called);
1317
1318 nghttp2_hd_deflate_free(&deflater);
1319 nghttp2_session_del(session);
1320
1321 /* HEADERS with padding followed by CONTINUATION */
1322 nghttp2_session_server_new(&session, &callbacks, &ud);
1323
1324 nghttp2_hd_deflate_init(&deflater, mem);
1325
1326 nvlen = ARRLEN(reqnv);
1327 nghttp2_nv_array_copy(&nva, reqnv, nvlen, mem);
1328 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_NONE, 1,
1329 NGHTTP2_HCAT_HEADERS, NULL, nva, nvlen);
1330
1331 nghttp2_bufs_reset(&bufs);
1332 rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
1333
1334 CU_ASSERT(0 == rv);
1335
1336 nghttp2_frame_headers_free(&frame.headers, mem);
1337
1338 /* make sure that all data is in the first buf */
1339 buf = &bufs.head->buf;
1340 assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
1341
1342 /* HEADERS payload is 3 byte (1 for padding field, 1 for padding) */
1343 memcpy(data, buf->pos, NGHTTP2_FRAME_HDLEN);
1344 nghttp2_put_uint32be(data, (uint32_t)((3 << 8) + data[3]));
1345 data[4] |= NGHTTP2_FLAG_PADDED;
1346 /* padding field */
1347 data[NGHTTP2_FRAME_HDLEN] = 1;
1348 data[NGHTTP2_FRAME_HDLEN + 1] = buf->pos[NGHTTP2_FRAME_HDLEN];
1349 /* padding */
1350 data[NGHTTP2_FRAME_HDLEN + 2] = 0;
1351 datalen = NGHTTP2_FRAME_HDLEN + 3;
1352 buf->pos += NGHTTP2_FRAME_HDLEN + 1;
1353
1354 /* CONTINUATION, rest of the bytes */
1355 nghttp2_frame_hd_init(&cont_hd, nghttp2_buf_len(buf), NGHTTP2_CONTINUATION,
1356 NGHTTP2_FLAG_END_HEADERS, 1);
1357 nghttp2_frame_pack_frame_hd(data + datalen, &cont_hd);
1358 datalen += NGHTTP2_FRAME_HDLEN;
1359
1360 memcpy(data + datalen, buf->pos, cont_hd.length);
1361 datalen += cont_hd.length;
1362 buf->pos += cont_hd.length;
1363
1364 CU_ASSERT(0 == nghttp2_buf_len(buf));
1365
1366 ud.header_cb_called = 0;
1367 ud.begin_frame_cb_called = 0;
1368
1369 rv = nghttp2_session_mem_recv(session, data, datalen);
1370
1371 CU_ASSERT((ssize_t)datalen == rv);
1372 CU_ASSERT(4 == ud.header_cb_called);
1373 CU_ASSERT(2 == ud.begin_frame_cb_called);
1374
1375 nghttp2_hd_deflate_free(&deflater);
1376 nghttp2_session_del(session);
1377
1378 /* Expecting CONTINUATION, but get the other frame */
1379 nghttp2_session_server_new(&session, &callbacks, &ud);
1380
1381 nghttp2_hd_deflate_init(&deflater, mem);
1382
1383 /* HEADERS without END_HEADERS flag */
1384 nvlen = ARRLEN(reqnv);
1385 nghttp2_nv_array_copy(&nva, reqnv, nvlen, mem);
1386 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_NONE, 1,
1387 NGHTTP2_HCAT_HEADERS, NULL, nva, nvlen);
1388 nghttp2_bufs_reset(&bufs);
1389 rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
1390
1391 CU_ASSERT(0 == rv);
1392 CU_ASSERT(nghttp2_bufs_len(&bufs) > 0);
1393
1394 nghttp2_frame_headers_free(&frame.headers, mem);
1395
1396 /* make sure that all data is in the first buf */
1397 buf = &bufs.head->buf;
1398 assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
1399
1400 memcpy(data, buf->pos, nghttp2_buf_len(buf));
1401 datalen = nghttp2_buf_len(buf);
1402
1403 /* Followed by PRIORITY */
1404 nghttp2_priority_spec_default_init(&pri_spec);
1405
1406 nghttp2_frame_priority_init(&frame.priority, 1, &pri_spec);
1407 nghttp2_bufs_reset(&bufs);
1408
1409 nghttp2_frame_pack_priority(&bufs, &frame.priority);
1410
1411 CU_ASSERT(nghttp2_bufs_len(&bufs) > 0);
1412
1413 memcpy(data + datalen, buf->pos, nghttp2_buf_len(buf));
1414 datalen += nghttp2_buf_len(buf);
1415
1416 ud.begin_headers_cb_called = 0;
1417 rv = nghttp2_session_mem_recv(session, data, datalen);
1418 CU_ASSERT((ssize_t)datalen == rv);
1419
1420 CU_ASSERT(1 == ud.begin_headers_cb_called);
1421 CU_ASSERT(NGHTTP2_GOAWAY ==
1422 nghttp2_session_get_next_ob_item(session)->frame.hd.type);
1423
1424 nghttp2_bufs_free(&bufs);
1425 nghttp2_hd_deflate_free(&deflater);
1426 nghttp2_session_del(session);
1427 }
1428
test_nghttp2_session_recv_headers_with_priority(void)1429 void test_nghttp2_session_recv_headers_with_priority(void) {
1430 nghttp2_session *session;
1431 nghttp2_session_callbacks callbacks;
1432 nghttp2_nv *nva;
1433 size_t nvlen;
1434 nghttp2_frame frame;
1435 nghttp2_bufs bufs;
1436 nghttp2_buf *buf;
1437 ssize_t rv;
1438 my_user_data ud;
1439 nghttp2_hd_deflater deflater;
1440 nghttp2_outbound_item *item;
1441 nghttp2_priority_spec pri_spec;
1442 nghttp2_stream *stream;
1443 nghttp2_mem *mem;
1444
1445 mem = nghttp2_mem_default();
1446 frame_pack_bufs_init(&bufs);
1447
1448 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
1449 callbacks.on_frame_recv_callback = on_frame_recv_callback;
1450
1451 nghttp2_session_server_new(&session, &callbacks, &ud);
1452
1453 nghttp2_hd_deflate_init(&deflater, mem);
1454
1455 open_recv_stream(session, 1);
1456
1457 /* With NGHTTP2_FLAG_PRIORITY without exclusive flag set */
1458 nvlen = ARRLEN(reqnv);
1459 nghttp2_nv_array_copy(&nva, reqnv, nvlen, mem);
1460
1461 nghttp2_priority_spec_init(&pri_spec, 1, 99, 0);
1462
1463 nghttp2_frame_headers_init(&frame.headers,
1464 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PRIORITY,
1465 3, NGHTTP2_HCAT_HEADERS, &pri_spec, nva, nvlen);
1466
1467 rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
1468
1469 CU_ASSERT(0 == rv);
1470 CU_ASSERT(nghttp2_bufs_len(&bufs) > 0);
1471
1472 nghttp2_frame_headers_free(&frame.headers, mem);
1473
1474 buf = &bufs.head->buf;
1475 assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
1476
1477 ud.frame_recv_cb_called = 0;
1478
1479 rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
1480
1481 CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv);
1482 CU_ASSERT(1 == ud.frame_recv_cb_called);
1483
1484 stream = nghttp2_session_get_stream(session, 3);
1485
1486 CU_ASSERT(99 == stream->weight);
1487 CU_ASSERT(1 == stream->dep_prev->stream_id);
1488
1489 nghttp2_bufs_reset(&bufs);
1490
1491 /* With NGHTTP2_FLAG_PRIORITY, but cut last 1 byte to make it
1492 invalid. */
1493 nvlen = ARRLEN(reqnv);
1494 nghttp2_nv_array_copy(&nva, reqnv, nvlen, mem);
1495
1496 nghttp2_priority_spec_init(&pri_spec, 0, 99, 0);
1497
1498 nghttp2_frame_headers_init(&frame.headers,
1499 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PRIORITY,
1500 5, NGHTTP2_HCAT_HEADERS, &pri_spec, nva, nvlen);
1501
1502 rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
1503
1504 CU_ASSERT(0 == rv);
1505 CU_ASSERT(nghttp2_bufs_len(&bufs) > NGHTTP2_FRAME_HDLEN + 5);
1506
1507 nghttp2_frame_headers_free(&frame.headers, mem);
1508
1509 buf = &bufs.head->buf;
1510 /* Make payload shorter than required length to store priority
1511 group */
1512 nghttp2_put_uint32be(buf->pos, (uint32_t)((4 << 8) + buf->pos[3]));
1513
1514 ud.frame_recv_cb_called = 0;
1515
1516 rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
1517
1518 CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv);
1519 CU_ASSERT(0 == ud.frame_recv_cb_called);
1520
1521 stream = nghttp2_session_get_stream(session, 5);
1522
1523 CU_ASSERT(NULL == stream);
1524
1525 item = nghttp2_session_get_next_ob_item(session);
1526 CU_ASSERT(NULL != item);
1527 CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
1528 CU_ASSERT(NGHTTP2_FRAME_SIZE_ERROR == item->frame.goaway.error_code);
1529
1530 nghttp2_bufs_reset(&bufs);
1531
1532 nghttp2_hd_deflate_free(&deflater);
1533 nghttp2_session_del(session);
1534
1535 /* Check dep_stream_id == stream_id */
1536 nghttp2_session_server_new(&session, &callbacks, &ud);
1537
1538 nghttp2_hd_deflate_init(&deflater, mem);
1539
1540 nvlen = ARRLEN(reqnv);
1541 nghttp2_nv_array_copy(&nva, reqnv, nvlen, mem);
1542
1543 nghttp2_priority_spec_init(&pri_spec, 1, 0, 0);
1544
1545 nghttp2_frame_headers_init(&frame.headers,
1546 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PRIORITY,
1547 1, NGHTTP2_HCAT_HEADERS, &pri_spec, nva, nvlen);
1548
1549 rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
1550
1551 CU_ASSERT(0 == rv);
1552 CU_ASSERT(nghttp2_bufs_len(&bufs) > 0);
1553
1554 nghttp2_frame_headers_free(&frame.headers, mem);
1555
1556 buf = &bufs.head->buf;
1557 assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
1558
1559 ud.frame_recv_cb_called = 0;
1560
1561 rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
1562
1563 CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv);
1564 CU_ASSERT(0 == ud.frame_recv_cb_called);
1565
1566 stream = nghttp2_session_get_stream(session, 1);
1567
1568 CU_ASSERT(NULL == stream);
1569
1570 item = nghttp2_session_get_next_ob_item(session);
1571 CU_ASSERT(NULL != item);
1572 CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
1573 CU_ASSERT(NGHTTP2_PROTOCOL_ERROR == item->frame.goaway.error_code);
1574
1575 nghttp2_bufs_reset(&bufs);
1576
1577 nghttp2_bufs_free(&bufs);
1578 nghttp2_hd_deflate_free(&deflater);
1579 nghttp2_session_del(session);
1580 }
1581
test_nghttp2_session_recv_headers_with_padding(void)1582 void test_nghttp2_session_recv_headers_with_padding(void) {
1583 nghttp2_session *session;
1584 nghttp2_session_callbacks callbacks;
1585 nghttp2_bufs bufs;
1586 nghttp2_buf *buf;
1587 nghttp2_frame_hd hd;
1588 nghttp2_outbound_item *item;
1589 my_user_data ud;
1590 ssize_t rv;
1591
1592 frame_pack_bufs_init(&bufs);
1593
1594 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
1595 callbacks.on_frame_recv_callback = on_frame_recv_callback;
1596 callbacks.send_callback = null_send_callback;
1597
1598 /* HEADERS: Wrong padding length */
1599 nghttp2_session_server_new(&session, &callbacks, &ud);
1600 nghttp2_session_send(session);
1601
1602 nghttp2_frame_hd_init(&hd, 10, NGHTTP2_HEADERS,
1603 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PRIORITY |
1604 NGHTTP2_FLAG_PADDED,
1605 1);
1606 buf = &bufs.head->buf;
1607 nghttp2_frame_pack_frame_hd(buf->last, &hd);
1608 buf->last += NGHTTP2_FRAME_HDLEN;
1609 /* padding is 6 bytes */
1610 *buf->last++ = 5;
1611 /* priority field */
1612 nghttp2_put_uint32be(buf->last, 3);
1613 buf->last += sizeof(uint32_t);
1614 *buf->last++ = 1;
1615 /* rest is garbage */
1616 memset(buf->last, 0, 4);
1617 buf->last += 4;
1618
1619 ud.frame_recv_cb_called = 0;
1620
1621 rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
1622
1623 CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv);
1624 CU_ASSERT(0 == ud.frame_recv_cb_called);
1625
1626 item = nghttp2_session_get_next_ob_item(session);
1627
1628 CU_ASSERT(NULL != item);
1629 CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
1630
1631 nghttp2_bufs_reset(&bufs);
1632 nghttp2_session_del(session);
1633
1634 /* PUSH_PROMISE: Wrong padding length */
1635 nghttp2_session_client_new(&session, &callbacks, &ud);
1636 nghttp2_session_send(session);
1637
1638 open_sent_stream(session, 1);
1639
1640 nghttp2_frame_hd_init(&hd, 9, NGHTTP2_PUSH_PROMISE,
1641 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PADDED, 1);
1642 buf = &bufs.head->buf;
1643 nghttp2_frame_pack_frame_hd(buf->last, &hd);
1644 buf->last += NGHTTP2_FRAME_HDLEN;
1645 /* padding is 6 bytes */
1646 *buf->last++ = 5;
1647 /* promised stream ID field */
1648 nghttp2_put_uint32be(buf->last, 2);
1649 buf->last += sizeof(uint32_t);
1650 /* rest is garbage */
1651 memset(buf->last, 0, 4);
1652 buf->last += 4;
1653
1654 ud.frame_recv_cb_called = 0;
1655
1656 rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
1657
1658 CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv);
1659 CU_ASSERT(0 == ud.frame_recv_cb_called);
1660
1661 item = nghttp2_session_get_next_ob_item(session);
1662
1663 CU_ASSERT(NULL != item);
1664 CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
1665
1666 nghttp2_bufs_free(&bufs);
1667 nghttp2_session_del(session);
1668 }
1669
response_on_begin_frame_callback(nghttp2_session * session,const nghttp2_frame_hd * hd,void * user_data)1670 static int response_on_begin_frame_callback(nghttp2_session *session,
1671 const nghttp2_frame_hd *hd,
1672 void *user_data) {
1673 int rv;
1674 (void)user_data;
1675
1676 if (hd->type != NGHTTP2_HEADERS) {
1677 return 0;
1678 }
1679
1680 rv = nghttp2_submit_response(session, hd->stream_id, resnv, ARRLEN(resnv),
1681 NULL);
1682
1683 CU_ASSERT(0 == rv);
1684
1685 return 0;
1686 }
1687
test_nghttp2_session_recv_headers_early_response(void)1688 void test_nghttp2_session_recv_headers_early_response(void) {
1689 nghttp2_session *session;
1690 nghttp2_session_callbacks callbacks;
1691 nghttp2_bufs bufs;
1692 nghttp2_buf *buf;
1693 nghttp2_hd_deflater deflater;
1694 nghttp2_mem *mem;
1695 nghttp2_nv *nva;
1696 size_t nvlen;
1697 nghttp2_frame frame;
1698 ssize_t rv;
1699 nghttp2_stream *stream;
1700
1701 mem = nghttp2_mem_default();
1702 frame_pack_bufs_init(&bufs);
1703
1704 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
1705 callbacks.send_callback = null_send_callback;
1706 callbacks.on_begin_frame_callback = response_on_begin_frame_callback;
1707
1708 nghttp2_session_server_new(&session, &callbacks, NULL);
1709
1710 nghttp2_hd_deflate_init(&deflater, mem);
1711
1712 nvlen = ARRLEN(reqnv);
1713 nghttp2_nv_array_copy(&nva, reqnv, nvlen, mem);
1714 nghttp2_frame_headers_init(&frame.headers,
1715 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM,
1716 1, NGHTTP2_HCAT_REQUEST, NULL, nva, nvlen);
1717
1718 rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
1719
1720 CU_ASSERT(0 == rv);
1721
1722 nghttp2_frame_headers_free(&frame.headers, mem);
1723
1724 buf = &bufs.head->buf;
1725
1726 /* Only receive 9 bytes headers, and invoke
1727 on_begin_frame_callback */
1728 rv = nghttp2_session_mem_recv(session, buf->pos, 9);
1729
1730 CU_ASSERT(9 == rv);
1731
1732 rv = nghttp2_session_send(session);
1733
1734 CU_ASSERT(0 == rv);
1735
1736 rv =
1737 nghttp2_session_mem_recv(session, buf->pos + 9, nghttp2_buf_len(buf) - 9);
1738
1739 CU_ASSERT((ssize_t)nghttp2_buf_len(buf) - 9 == rv);
1740
1741 stream = nghttp2_session_get_stream_raw(session, 1);
1742
1743 CU_ASSERT(stream->flags & NGHTTP2_STREAM_FLAG_CLOSED);
1744
1745 nghttp2_hd_deflate_free(&deflater);
1746 nghttp2_session_del(session);
1747 nghttp2_bufs_free(&bufs);
1748 }
1749
test_nghttp2_session_recv_headers_for_closed_stream(void)1750 void test_nghttp2_session_recv_headers_for_closed_stream(void) {
1751 nghttp2_session *session;
1752 nghttp2_session_callbacks callbacks;
1753 nghttp2_nv *nva;
1754 size_t nvlen;
1755 nghttp2_frame frame;
1756 nghttp2_bufs bufs;
1757 nghttp2_buf *buf;
1758 ssize_t rv;
1759 my_user_data ud;
1760 nghttp2_hd_deflater deflater;
1761 nghttp2_stream *stream;
1762 nghttp2_mem *mem;
1763 const uint8_t *data;
1764
1765 mem = nghttp2_mem_default();
1766 frame_pack_bufs_init(&bufs);
1767
1768 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
1769 callbacks.on_frame_recv_callback = on_frame_recv_callback;
1770 callbacks.on_header_callback = on_header_callback;
1771
1772 nghttp2_session_server_new(&session, &callbacks, &ud);
1773
1774 nghttp2_hd_deflate_init(&deflater, mem);
1775
1776 /* Make sure that on_header callback never be invoked for closed
1777 stream */
1778 nvlen = ARRLEN(reqnv);
1779 nghttp2_nv_array_copy(&nva, reqnv, nvlen, mem);
1780
1781 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 1,
1782 NGHTTP2_HCAT_HEADERS, NULL, nva, nvlen);
1783
1784 rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
1785
1786 CU_ASSERT(0 == rv);
1787 CU_ASSERT(nghttp2_bufs_len(&bufs) > 0);
1788
1789 nghttp2_frame_headers_free(&frame.headers, mem);
1790
1791 buf = &bufs.head->buf;
1792 assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
1793
1794 ud.header_cb_called = 0;
1795 ud.frame_recv_cb_called = 0;
1796
1797 rv = nghttp2_session_mem_recv(session, buf->pos, NGHTTP2_FRAME_HDLEN);
1798
1799 CU_ASSERT(NGHTTP2_FRAME_HDLEN == rv);
1800 CU_ASSERT(0 == ud.header_cb_called);
1801 CU_ASSERT(0 == ud.frame_recv_cb_called);
1802
1803 stream = nghttp2_session_get_stream(session, 1);
1804
1805 CU_ASSERT(NULL != stream);
1806
1807 rv = nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, 1,
1808 NGHTTP2_NO_ERROR);
1809
1810 CU_ASSERT(0 == rv);
1811
1812 rv = nghttp2_session_mem_send(session, &data);
1813
1814 CU_ASSERT(rv > 0);
1815
1816 stream = nghttp2_session_get_stream(session, 1);
1817
1818 CU_ASSERT(NULL == stream);
1819
1820 ud.header_cb_called = 0;
1821 ud.frame_recv_cb_called = 0;
1822
1823 rv = nghttp2_session_mem_recv(session, buf->pos + NGHTTP2_FRAME_HDLEN,
1824 nghttp2_buf_len(buf) - NGHTTP2_FRAME_HDLEN);
1825
1826 CU_ASSERT((ssize_t)nghttp2_buf_len(buf) - NGHTTP2_FRAME_HDLEN == rv);
1827 CU_ASSERT(0 == ud.header_cb_called);
1828 CU_ASSERT(0 == ud.frame_recv_cb_called);
1829
1830 nghttp2_bufs_free(&bufs);
1831 nghttp2_hd_deflate_free(&deflater);
1832 nghttp2_session_del(session);
1833 }
1834
test_nghttp2_session_recv_headers_with_extpri(void)1835 void test_nghttp2_session_recv_headers_with_extpri(void) {
1836 nghttp2_session *session;
1837 nghttp2_session_callbacks callbacks;
1838 nghttp2_nv *nva;
1839 size_t nvlen;
1840 nghttp2_frame frame;
1841 nghttp2_bufs bufs;
1842 nghttp2_buf *buf;
1843 ssize_t rv;
1844 nghttp2_hd_deflater deflater;
1845 nghttp2_stream *stream;
1846 nghttp2_mem *mem;
1847 const nghttp2_nv extpri_reqnv[] = {
1848 MAKE_NV(":method", "GET"), MAKE_NV(":path", "/"),
1849 MAKE_NV(":scheme", "https"), MAKE_NV(":authority", "localhost"),
1850 MAKE_NV("priority", "i,u=2"),
1851 };
1852 nghttp2_settings_entry iv;
1853
1854 mem = nghttp2_mem_default();
1855 frame_pack_bufs_init(&bufs);
1856
1857 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
1858
1859 nghttp2_session_server_new(&session, &callbacks, NULL);
1860
1861 iv.settings_id = NGHTTP2_SETTINGS_NO_RFC7540_PRIORITIES;
1862 iv.value = 1;
1863
1864 nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, &iv, 1);
1865
1866 nghttp2_hd_deflate_init(&deflater, mem);
1867
1868 nvlen = ARRLEN(extpri_reqnv);
1869 nghttp2_nv_array_copy(&nva, extpri_reqnv, nvlen, mem);
1870
1871 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 1,
1872 NGHTTP2_HCAT_HEADERS, NULL, nva, nvlen);
1873
1874 rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
1875
1876 CU_ASSERT(0 == rv);
1877 CU_ASSERT(nghttp2_bufs_len(&bufs) > 0);
1878
1879 nghttp2_frame_headers_free(&frame.headers, mem);
1880
1881 buf = &bufs.head->buf;
1882 assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
1883
1884 rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
1885
1886 stream = nghttp2_session_get_stream(session, 1);
1887
1888 CU_ASSERT(2 == nghttp2_extpri_uint8_urgency(stream->extpri));
1889 CU_ASSERT(1 == nghttp2_extpri_uint8_inc(stream->extpri));
1890
1891 nghttp2_hd_deflate_free(&deflater);
1892 nghttp2_session_del(session);
1893
1894 nghttp2_bufs_reset(&bufs);
1895
1896 /* Client should ignore priority header field included in
1897 PUSH_PROMISE. */
1898 nghttp2_session_client_new(&session, &callbacks, NULL);
1899
1900 nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, &iv, 1);
1901
1902 open_sent_stream(session, 1);
1903
1904 nghttp2_hd_deflate_init(&deflater, mem);
1905
1906 nvlen = ARRLEN(extpri_reqnv);
1907 nghttp2_nv_array_copy(&nva, extpri_reqnv, nvlen, mem);
1908
1909 nghttp2_frame_push_promise_init(&frame.push_promise, NGHTTP2_FLAG_END_HEADERS,
1910 1, 2, nva, nvlen);
1911
1912 rv = nghttp2_frame_pack_push_promise(&bufs, &frame.push_promise, &deflater);
1913
1914 CU_ASSERT(0 == rv);
1915 CU_ASSERT(nghttp2_bufs_len(&bufs) > 0);
1916
1917 nghttp2_frame_push_promise_free(&frame.push_promise, mem);
1918
1919 buf = &bufs.head->buf;
1920 assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
1921
1922 rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
1923
1924 stream = nghttp2_session_get_stream(session, 2);
1925
1926 CU_ASSERT(NGHTTP2_EXTPRI_DEFAULT_URGENCY ==
1927 nghttp2_extpri_uint8_urgency(stream->http_extpri));
1928 CU_ASSERT(NGHTTP2_EXTPRI_DEFAULT_URGENCY ==
1929 nghttp2_extpri_uint8_urgency(stream->extpri));
1930
1931 nghttp2_hd_deflate_free(&deflater);
1932 nghttp2_session_del(session);
1933 nghttp2_bufs_free(&bufs);
1934 }
1935
test_nghttp2_session_server_recv_push_response(void)1936 void test_nghttp2_session_server_recv_push_response(void) {
1937 nghttp2_session *session;
1938 nghttp2_session_callbacks callbacks;
1939 nghttp2_bufs bufs;
1940 nghttp2_buf *buf;
1941 ssize_t rv;
1942 my_user_data ud;
1943 nghttp2_mem *mem;
1944 nghttp2_frame frame;
1945 nghttp2_hd_deflater deflater;
1946 nghttp2_nv *nva;
1947 size_t nvlen;
1948
1949 mem = nghttp2_mem_default();
1950 frame_pack_bufs_init(&bufs);
1951
1952 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
1953 callbacks.on_invalid_frame_recv_callback = on_invalid_frame_recv_callback;
1954
1955 nghttp2_session_server_new(&session, &callbacks, &ud);
1956
1957 nghttp2_hd_deflate_init(&deflater, mem);
1958
1959 open_sent_stream2(session, 2, NGHTTP2_STREAM_RESERVED);
1960
1961 nvlen = ARRLEN(resnv);
1962 nghttp2_nv_array_copy(&nva, resnv, nvlen, mem);
1963 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 2,
1964 NGHTTP2_HCAT_HEADERS, &pri_spec_default, nva,
1965 nvlen);
1966 rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
1967
1968 CU_ASSERT(0 == rv);
1969 CU_ASSERT(nghttp2_bufs_len(&bufs) > 0);
1970
1971 nghttp2_frame_headers_free(&frame.headers, mem);
1972
1973 buf = &bufs.head->buf;
1974
1975 ud.invalid_frame_recv_cb_called = 0;
1976
1977 rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
1978
1979 CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv);
1980 CU_ASSERT(1 == ud.invalid_frame_recv_cb_called);
1981
1982 nghttp2_bufs_free(&bufs);
1983 nghttp2_hd_deflate_free(&deflater);
1984 nghttp2_session_del(session);
1985 }
1986
test_nghttp2_session_recv_premature_headers(void)1987 void test_nghttp2_session_recv_premature_headers(void) {
1988 nghttp2_session *session;
1989 nghttp2_session_callbacks callbacks;
1990 nghttp2_bufs bufs;
1991 nghttp2_buf *buf;
1992 ssize_t rv;
1993 my_user_data ud;
1994 nghttp2_hd_deflater deflater;
1995 nghttp2_outbound_item *item;
1996 nghttp2_mem *mem;
1997 uint32_t payloadlen;
1998
1999 mem = nghttp2_mem_default();
2000 frame_pack_bufs_init(&bufs);
2001
2002 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
2003 callbacks.send_callback = null_send_callback;
2004
2005 nghttp2_session_server_new(&session, &callbacks, &ud);
2006
2007 nghttp2_hd_deflate_init(&deflater, mem);
2008
2009 pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, reqnv,
2010 ARRLEN(reqnv), mem);
2011
2012 buf = &bufs.head->buf;
2013 /* Intentionally feed payload cutting last 1 byte off */
2014 payloadlen = nghttp2_get_uint32(buf->pos) >> 8;
2015 nghttp2_put_uint32be(buf->pos, ((payloadlen - 1) << 8) + buf->pos[3]);
2016 rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf) - 1);
2017
2018 CU_ASSERT((ssize_t)(nghttp2_buf_len(buf) - 1) == rv);
2019
2020 item = nghttp2_session_get_next_ob_item(session);
2021
2022 CU_ASSERT(NULL != item);
2023 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
2024 CU_ASSERT(NGHTTP2_COMPRESSION_ERROR == item->frame.rst_stream.error_code);
2025 CU_ASSERT(1 == item->frame.hd.stream_id);
2026 CU_ASSERT(0 == nghttp2_session_send(session));
2027
2028 nghttp2_bufs_reset(&bufs);
2029 nghttp2_hd_deflate_free(&deflater);
2030 nghttp2_session_del(session);
2031
2032 /* Test for PUSH_PROMISE */
2033 nghttp2_session_client_new(&session, &callbacks, &ud);
2034 nghttp2_hd_deflate_init(&deflater, mem);
2035
2036 open_sent_stream3(session, 1, NGHTTP2_STREAM_FLAG_NONE, &pri_spec_default,
2037 NGHTTP2_STREAM_OPENING, NULL);
2038
2039 rv = pack_push_promise(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, 2,
2040 reqnv, ARRLEN(reqnv), mem);
2041
2042 CU_ASSERT(0 == rv);
2043
2044 buf = &bufs.head->buf;
2045 payloadlen = nghttp2_get_uint32(buf->pos) >> 8;
2046 /* Intentionally feed payload cutting last 1 byte off */
2047 nghttp2_put_uint32be(buf->pos, ((payloadlen - 1) << 8) + buf->pos[3]);
2048 rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf) - 1);
2049
2050 CU_ASSERT((ssize_t)(nghttp2_buf_len(buf) - 1) == rv);
2051
2052 item = nghttp2_session_get_next_ob_item(session);
2053
2054 CU_ASSERT(NULL != item);
2055 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
2056 CU_ASSERT(NGHTTP2_COMPRESSION_ERROR == item->frame.rst_stream.error_code);
2057 CU_ASSERT(2 == item->frame.hd.stream_id);
2058 CU_ASSERT(0 == nghttp2_session_send(session));
2059
2060 nghttp2_hd_deflate_free(&deflater);
2061 nghttp2_session_del(session);
2062 nghttp2_bufs_free(&bufs);
2063 }
2064
test_nghttp2_session_recv_unknown_frame(void)2065 void test_nghttp2_session_recv_unknown_frame(void) {
2066 nghttp2_session *session;
2067 nghttp2_session_callbacks callbacks;
2068 my_user_data ud;
2069 uint8_t data[16384];
2070 size_t datalen;
2071 nghttp2_frame_hd hd;
2072 ssize_t rv;
2073
2074 nghttp2_frame_hd_init(&hd, 16000, 99, NGHTTP2_FLAG_NONE, 0);
2075
2076 nghttp2_frame_pack_frame_hd(data, &hd);
2077 datalen = NGHTTP2_FRAME_HDLEN + hd.length;
2078
2079 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
2080 callbacks.on_frame_recv_callback = on_frame_recv_callback;
2081
2082 nghttp2_session_server_new(&session, &callbacks, &ud);
2083
2084 ud.frame_recv_cb_called = 0;
2085
2086 /* Unknown frame must be ignored */
2087 rv = nghttp2_session_mem_recv(session, data, datalen);
2088
2089 CU_ASSERT(rv == (ssize_t)datalen);
2090 CU_ASSERT(0 == ud.frame_recv_cb_called);
2091 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
2092
2093 nghttp2_session_del(session);
2094 }
2095
test_nghttp2_session_recv_unexpected_continuation(void)2096 void test_nghttp2_session_recv_unexpected_continuation(void) {
2097 nghttp2_session *session;
2098 nghttp2_session_callbacks callbacks;
2099 my_user_data ud;
2100 uint8_t data[16384];
2101 size_t datalen;
2102 nghttp2_frame_hd hd;
2103 ssize_t rv;
2104 nghttp2_outbound_item *item;
2105
2106 nghttp2_frame_hd_init(&hd, 16000, NGHTTP2_CONTINUATION,
2107 NGHTTP2_FLAG_END_HEADERS, 1);
2108
2109 nghttp2_frame_pack_frame_hd(data, &hd);
2110 datalen = NGHTTP2_FRAME_HDLEN + hd.length;
2111
2112 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
2113 callbacks.on_frame_recv_callback = on_frame_recv_callback;
2114
2115 nghttp2_session_server_new(&session, &callbacks, &ud);
2116
2117 open_recv_stream(session, 1);
2118
2119 ud.frame_recv_cb_called = 0;
2120
2121 /* unexpected CONTINUATION must be treated as connection error */
2122 rv = nghttp2_session_mem_recv(session, data, datalen);
2123
2124 CU_ASSERT(rv == (ssize_t)datalen);
2125 CU_ASSERT(0 == ud.frame_recv_cb_called);
2126
2127 item = nghttp2_session_get_next_ob_item(session);
2128
2129 CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
2130
2131 nghttp2_session_del(session);
2132 }
2133
test_nghttp2_session_recv_settings_header_table_size(void)2134 void test_nghttp2_session_recv_settings_header_table_size(void) {
2135 nghttp2_session *session;
2136 nghttp2_session_callbacks callbacks;
2137 nghttp2_frame frame;
2138 nghttp2_bufs bufs;
2139 nghttp2_buf *buf;
2140 ssize_t rv;
2141 my_user_data ud;
2142 nghttp2_settings_entry iv[3];
2143 nghttp2_nv nv = MAKE_NV(":authority", "example.org");
2144 nghttp2_mem *mem;
2145
2146 mem = nghttp2_mem_default();
2147 frame_pack_bufs_init(&bufs);
2148
2149 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
2150 callbacks.on_frame_recv_callback = on_frame_recv_callback;
2151 callbacks.send_callback = null_send_callback;
2152
2153 nghttp2_session_client_new(&session, &callbacks, &ud);
2154
2155 iv[0].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
2156 iv[0].value = 3000;
2157
2158 iv[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
2159 iv[1].value = 16384;
2160
2161 nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE, dup_iv(iv, 2),
2162 2);
2163
2164 rv = nghttp2_frame_pack_settings(&bufs, &frame.settings);
2165
2166 CU_ASSERT(0 == rv);
2167 CU_ASSERT(nghttp2_bufs_len(&bufs) > 0);
2168
2169 nghttp2_frame_settings_free(&frame.settings, mem);
2170
2171 buf = &bufs.head->buf;
2172 assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
2173
2174 ud.frame_recv_cb_called = 0;
2175
2176 rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
2177
2178 CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv);
2179 CU_ASSERT(1 == ud.frame_recv_cb_called);
2180
2181 CU_ASSERT(3000 == session->remote_settings.header_table_size);
2182 CU_ASSERT(16384 == session->remote_settings.initial_window_size);
2183
2184 nghttp2_bufs_reset(&bufs);
2185
2186 /* 2 SETTINGS_HEADER_TABLE_SIZE */
2187 iv[0].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
2188 iv[0].value = 3001;
2189
2190 iv[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
2191 iv[1].value = 16383;
2192
2193 iv[2].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
2194 iv[2].value = 3001;
2195
2196 nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE, dup_iv(iv, 3),
2197 3);
2198
2199 rv = nghttp2_frame_pack_settings(&bufs, &frame.settings);
2200
2201 CU_ASSERT(0 == rv);
2202 CU_ASSERT(nghttp2_bufs_len(&bufs) > 0);
2203
2204 nghttp2_frame_settings_free(&frame.settings, mem);
2205
2206 buf = &bufs.head->buf;
2207 assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
2208
2209 ud.frame_recv_cb_called = 0;
2210
2211 rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
2212
2213 CU_ASSERT((ssize_t)(nghttp2_buf_len(buf)) == rv);
2214 CU_ASSERT(1 == ud.frame_recv_cb_called);
2215
2216 CU_ASSERT(3001 == session->remote_settings.header_table_size);
2217 CU_ASSERT(16383 == session->remote_settings.initial_window_size);
2218
2219 nghttp2_bufs_reset(&bufs);
2220
2221 /* 2 SETTINGS_HEADER_TABLE_SIZE; first entry clears dynamic header
2222 table. */
2223
2224 nghttp2_submit_request(session, NULL, &nv, 1, NULL, NULL);
2225 nghttp2_session_send(session);
2226
2227 CU_ASSERT(0 < session->hd_deflater.ctx.hd_table.len);
2228
2229 iv[0].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
2230 iv[0].value = 0;
2231
2232 iv[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
2233 iv[1].value = 16382;
2234
2235 iv[2].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
2236 iv[2].value = 4096;
2237
2238 nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE, dup_iv(iv, 3),
2239 3);
2240
2241 rv = nghttp2_frame_pack_settings(&bufs, &frame.settings);
2242
2243 CU_ASSERT(0 == rv);
2244 CU_ASSERT(nghttp2_bufs_len(&bufs) > 0);
2245
2246 nghttp2_frame_settings_free(&frame.settings, mem);
2247
2248 buf = &bufs.head->buf;
2249 assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
2250
2251 ud.frame_recv_cb_called = 0;
2252
2253 rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
2254
2255 CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv);
2256 CU_ASSERT(1 == ud.frame_recv_cb_called);
2257
2258 CU_ASSERT(4096 == session->remote_settings.header_table_size);
2259 CU_ASSERT(16382 == session->remote_settings.initial_window_size);
2260 CU_ASSERT(0 == session->hd_deflater.ctx.hd_table.len);
2261
2262 nghttp2_bufs_reset(&bufs);
2263
2264 /* 2 SETTINGS_HEADER_TABLE_SIZE; second entry clears dynamic header
2265 table. */
2266
2267 nghttp2_submit_request(session, NULL, &nv, 1, NULL, NULL);
2268 nghttp2_session_send(session);
2269
2270 CU_ASSERT(0 < session->hd_deflater.ctx.hd_table.len);
2271
2272 iv[0].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
2273 iv[0].value = 3000;
2274
2275 iv[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
2276 iv[1].value = 16381;
2277
2278 iv[2].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
2279 iv[2].value = 0;
2280
2281 nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE, dup_iv(iv, 3),
2282 3);
2283
2284 rv = nghttp2_frame_pack_settings(&bufs, &frame.settings);
2285
2286 CU_ASSERT(0 == rv);
2287 CU_ASSERT(nghttp2_bufs_len(&bufs) > 0);
2288
2289 nghttp2_frame_settings_free(&frame.settings, mem);
2290
2291 buf = &bufs.head->buf;
2292 assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
2293
2294 ud.frame_recv_cb_called = 0;
2295
2296 rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
2297
2298 CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv);
2299 CU_ASSERT(1 == ud.frame_recv_cb_called);
2300
2301 CU_ASSERT(0 == session->remote_settings.header_table_size);
2302 CU_ASSERT(16381 == session->remote_settings.initial_window_size);
2303 CU_ASSERT(0 == session->hd_deflater.ctx.hd_table.len);
2304
2305 nghttp2_bufs_reset(&bufs);
2306
2307 nghttp2_bufs_free(&bufs);
2308 nghttp2_session_del(session);
2309 }
2310
test_nghttp2_session_recv_too_large_frame_length(void)2311 void test_nghttp2_session_recv_too_large_frame_length(void) {
2312 nghttp2_session *session;
2313 nghttp2_session_callbacks callbacks;
2314 uint8_t buf[NGHTTP2_FRAME_HDLEN];
2315 nghttp2_outbound_item *item;
2316 nghttp2_frame_hd hd;
2317
2318 /* Initial max frame size is NGHTTP2_MAX_FRAME_SIZE_MIN */
2319 nghttp2_frame_hd_init(&hd, NGHTTP2_MAX_FRAME_SIZE_MIN + 1, NGHTTP2_HEADERS,
2320 NGHTTP2_FLAG_NONE, 1);
2321
2322 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
2323
2324 nghttp2_session_server_new(&session, &callbacks, NULL);
2325
2326 nghttp2_frame_pack_frame_hd(buf, &hd);
2327
2328 CU_ASSERT(sizeof(buf) == nghttp2_session_mem_recv(session, buf, sizeof(buf)));
2329
2330 item = nghttp2_session_get_next_ob_item(session);
2331
2332 CU_ASSERT(item != NULL);
2333 CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
2334
2335 nghttp2_session_del(session);
2336 }
2337
test_nghttp2_session_recv_extension(void)2338 void test_nghttp2_session_recv_extension(void) {
2339 nghttp2_session *session;
2340 nghttp2_session_callbacks callbacks;
2341 my_user_data ud;
2342 nghttp2_buf buf;
2343 nghttp2_frame_hd hd;
2344 nghttp2_mem *mem;
2345 const char data[] = "Hello World!";
2346 ssize_t rv;
2347 nghttp2_option *option;
2348
2349 mem = nghttp2_mem_default();
2350
2351 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
2352
2353 callbacks.on_extension_chunk_recv_callback = on_extension_chunk_recv_callback;
2354 callbacks.unpack_extension_callback = unpack_extension_callback;
2355 callbacks.on_frame_recv_callback = on_frame_recv_callback;
2356
2357 nghttp2_option_new(&option);
2358 nghttp2_option_set_user_recv_extension_type(option, 111);
2359
2360 nghttp2_buf_init2(&ud.scratchbuf, 4096, mem);
2361 nghttp2_buf_init2(&buf, 4096, mem);
2362
2363 nghttp2_frame_hd_init(&hd, sizeof(data), 111, 0xab, 1000000007);
2364 nghttp2_frame_pack_frame_hd(buf.last, &hd);
2365 buf.last += NGHTTP2_FRAME_HDLEN;
2366 buf.last = nghttp2_cpymem(buf.last, data, sizeof(data));
2367
2368 nghttp2_session_client_new2(&session, &callbacks, &ud, option);
2369
2370 nghttp2_frame_hd_init(&ud.recv_frame_hd, 0, 0, 0, 0);
2371 rv = nghttp2_session_mem_recv(session, buf.pos, nghttp2_buf_len(&buf));
2372
2373 CU_ASSERT(NGHTTP2_FRAME_HDLEN + hd.length == (size_t)rv);
2374 CU_ASSERT(111 == ud.recv_frame_hd.type);
2375 CU_ASSERT(0xab == ud.recv_frame_hd.flags);
2376 CU_ASSERT(1000000007 == ud.recv_frame_hd.stream_id);
2377 CU_ASSERT(0 == memcmp(data, ud.scratchbuf.pos, sizeof(data)));
2378
2379 nghttp2_session_del(session);
2380
2381 /* cancel in on_extension_chunk_recv_callback */
2382 nghttp2_buf_reset(&ud.scratchbuf);
2383
2384 callbacks.on_extension_chunk_recv_callback =
2385 cancel_on_extension_chunk_recv_callback;
2386
2387 nghttp2_session_server_new2(&session, &callbacks, &ud, option);
2388
2389 ud.frame_recv_cb_called = 0;
2390 rv = nghttp2_session_mem_recv(session, buf.pos, nghttp2_buf_len(&buf));
2391
2392 CU_ASSERT(NGHTTP2_FRAME_HDLEN + hd.length == (size_t)rv);
2393 CU_ASSERT(0 == ud.frame_recv_cb_called);
2394
2395 nghttp2_session_del(session);
2396
2397 /* cancel in unpack_extension_callback */
2398 nghttp2_buf_reset(&ud.scratchbuf);
2399
2400 callbacks.on_extension_chunk_recv_callback = on_extension_chunk_recv_callback;
2401 callbacks.unpack_extension_callback = cancel_unpack_extension_callback;
2402
2403 nghttp2_session_server_new2(&session, &callbacks, &ud, option);
2404
2405 ud.frame_recv_cb_called = 0;
2406 rv = nghttp2_session_mem_recv(session, buf.pos, nghttp2_buf_len(&buf));
2407
2408 CU_ASSERT(NGHTTP2_FRAME_HDLEN + hd.length == (size_t)rv);
2409 CU_ASSERT(0 == ud.frame_recv_cb_called);
2410
2411 nghttp2_session_del(session);
2412
2413 nghttp2_buf_free(&buf, mem);
2414 nghttp2_buf_free(&ud.scratchbuf, mem);
2415
2416 nghttp2_option_del(option);
2417 }
2418
test_nghttp2_session_recv_altsvc(void)2419 void test_nghttp2_session_recv_altsvc(void) {
2420 nghttp2_session *session;
2421 nghttp2_session_callbacks callbacks;
2422 my_user_data ud;
2423 nghttp2_buf buf;
2424 nghttp2_frame_hd hd;
2425 nghttp2_mem *mem;
2426 ssize_t rv;
2427 nghttp2_option *option;
2428 static const uint8_t origin[] = "nghttp2.org";
2429 static const uint8_t field_value[] = "h2=\":443\"";
2430
2431 mem = nghttp2_mem_default();
2432
2433 nghttp2_buf_init2(&buf, NGHTTP2_FRAME_HDLEN + NGHTTP2_MAX_FRAME_SIZE_MIN,
2434 mem);
2435
2436 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
2437
2438 callbacks.on_frame_recv_callback = on_frame_recv_callback;
2439 callbacks.on_invalid_frame_recv_callback = on_invalid_frame_recv_callback;
2440
2441 nghttp2_option_new(&option);
2442 nghttp2_option_set_builtin_recv_extension_type(option, NGHTTP2_ALTSVC);
2443
2444 nghttp2_session_client_new2(&session, &callbacks, &ud, option);
2445
2446 nghttp2_frame_hd_init(&hd, 2 + sizeof(origin) - 1 + sizeof(field_value) - 1,
2447 NGHTTP2_ALTSVC, NGHTTP2_FLAG_NONE, 0);
2448 nghttp2_frame_pack_frame_hd(buf.last, &hd);
2449 buf.last += NGHTTP2_FRAME_HDLEN;
2450 nghttp2_put_uint16be(buf.last, sizeof(origin) - 1);
2451 buf.last += 2;
2452 buf.last = nghttp2_cpymem(buf.last, origin, sizeof(origin) - 1);
2453 buf.last = nghttp2_cpymem(buf.last, field_value, sizeof(field_value) - 1);
2454
2455 ud.frame_recv_cb_called = 0;
2456 rv = nghttp2_session_mem_recv(session, buf.pos, nghttp2_buf_len(&buf));
2457
2458 CU_ASSERT((ssize_t)nghttp2_buf_len(&buf) == rv);
2459 CU_ASSERT(1 == ud.frame_recv_cb_called);
2460 CU_ASSERT(NGHTTP2_ALTSVC == ud.recv_frame_hd.type);
2461 CU_ASSERT(NGHTTP2_FLAG_NONE == ud.recv_frame_hd.flags);
2462 CU_ASSERT(0 == ud.recv_frame_hd.stream_id);
2463
2464 nghttp2_session_del(session);
2465
2466 /* size of origin is larger than frame length */
2467 nghttp2_buf_reset(&buf);
2468
2469 nghttp2_session_client_new2(&session, &callbacks, &ud, option);
2470
2471 nghttp2_frame_hd_init(&hd, 2 + sizeof(origin) - 1 - 1, NGHTTP2_ALTSVC,
2472 NGHTTP2_FLAG_NONE, 0);
2473 nghttp2_frame_pack_frame_hd(buf.last, &hd);
2474 buf.last += NGHTTP2_FRAME_HDLEN;
2475 nghttp2_put_uint16be(buf.last, sizeof(origin) - 1);
2476 buf.last += 2;
2477 buf.last = nghttp2_cpymem(buf.last, origin, sizeof(origin) - 1 - 1);
2478
2479 ud.frame_recv_cb_called = 0;
2480 rv = nghttp2_session_mem_recv(session, buf.pos, nghttp2_buf_len(&buf));
2481
2482 CU_ASSERT((ssize_t)nghttp2_buf_len(&buf) == rv);
2483 CU_ASSERT(0 == ud.frame_recv_cb_called);
2484
2485 nghttp2_session_del(session);
2486
2487 /* zero-length value */
2488 nghttp2_buf_reset(&buf);
2489
2490 nghttp2_session_client_new2(&session, &callbacks, &ud, option);
2491
2492 nghttp2_frame_hd_init(&hd, 2 + sizeof(origin) - 1, NGHTTP2_ALTSVC,
2493 NGHTTP2_FLAG_NONE, 0);
2494 nghttp2_frame_pack_frame_hd(buf.last, &hd);
2495 buf.last += NGHTTP2_FRAME_HDLEN;
2496 nghttp2_put_uint16be(buf.last, sizeof(origin) - 1);
2497 buf.last += 2;
2498 buf.last = nghttp2_cpymem(buf.last, origin, sizeof(origin) - 1);
2499
2500 ud.invalid_frame_recv_cb_called = 0;
2501 rv = nghttp2_session_mem_recv(session, buf.pos, nghttp2_buf_len(&buf));
2502
2503 CU_ASSERT((ssize_t)nghttp2_buf_len(&buf) == rv);
2504 CU_ASSERT(1 == ud.invalid_frame_recv_cb_called);
2505
2506 nghttp2_session_del(session);
2507
2508 /* non-empty origin to a stream other than 0 */
2509 nghttp2_buf_reset(&buf);
2510
2511 nghttp2_session_client_new2(&session, &callbacks, &ud, option);
2512
2513 open_sent_stream(session, 1);
2514
2515 nghttp2_frame_hd_init(&hd, 2 + sizeof(origin) - 1 + sizeof(field_value) - 1,
2516 NGHTTP2_ALTSVC, NGHTTP2_FLAG_NONE, 1);
2517 nghttp2_frame_pack_frame_hd(buf.last, &hd);
2518 buf.last += NGHTTP2_FRAME_HDLEN;
2519 nghttp2_put_uint16be(buf.last, sizeof(origin) - 1);
2520 buf.last += 2;
2521 buf.last = nghttp2_cpymem(buf.last, origin, sizeof(origin) - 1);
2522 buf.last = nghttp2_cpymem(buf.last, field_value, sizeof(field_value) - 1);
2523
2524 ud.invalid_frame_recv_cb_called = 0;
2525 rv = nghttp2_session_mem_recv(session, buf.pos, nghttp2_buf_len(&buf));
2526
2527 CU_ASSERT((ssize_t)nghttp2_buf_len(&buf) == rv);
2528 CU_ASSERT(1 == ud.invalid_frame_recv_cb_called);
2529
2530 nghttp2_session_del(session);
2531
2532 /* empty origin to stream 0 */
2533 nghttp2_buf_reset(&buf);
2534
2535 nghttp2_session_client_new2(&session, &callbacks, &ud, option);
2536
2537 nghttp2_frame_hd_init(&hd, 2 + sizeof(field_value) - 1, NGHTTP2_ALTSVC,
2538 NGHTTP2_FLAG_NONE, 0);
2539 nghttp2_frame_pack_frame_hd(buf.last, &hd);
2540 buf.last += NGHTTP2_FRAME_HDLEN;
2541 nghttp2_put_uint16be(buf.last, 0);
2542 buf.last += 2;
2543 buf.last = nghttp2_cpymem(buf.last, field_value, sizeof(field_value) - 1);
2544
2545 ud.invalid_frame_recv_cb_called = 0;
2546 rv = nghttp2_session_mem_recv(session, buf.pos, nghttp2_buf_len(&buf));
2547
2548 CU_ASSERT((ssize_t)nghttp2_buf_len(&buf) == rv);
2549 CU_ASSERT(1 == ud.invalid_frame_recv_cb_called);
2550
2551 nghttp2_session_del(session);
2552
2553 /* send large frame (16KiB) */
2554 nghttp2_buf_reset(&buf);
2555
2556 nghttp2_session_client_new2(&session, &callbacks, &ud, option);
2557
2558 nghttp2_frame_hd_init(&hd, NGHTTP2_MAX_FRAME_SIZE_MIN, NGHTTP2_ALTSVC,
2559 NGHTTP2_FLAG_NONE, 0);
2560 nghttp2_frame_pack_frame_hd(buf.last, &hd);
2561 buf.last += NGHTTP2_FRAME_HDLEN;
2562 nghttp2_put_uint16be(buf.last, sizeof(origin) - 1);
2563 buf.last += 2;
2564 buf.last = nghttp2_cpymem(buf.last, origin, sizeof(origin) - 1);
2565 memset(buf.last, 0, nghttp2_buf_avail(&buf));
2566 buf.last += nghttp2_buf_avail(&buf);
2567
2568 ud.frame_recv_cb_called = 0;
2569 rv = nghttp2_session_mem_recv(session, buf.pos, nghttp2_buf_len(&buf));
2570
2571 CU_ASSERT((ssize_t)nghttp2_buf_len(&buf) == rv);
2572 CU_ASSERT(1 == ud.frame_recv_cb_called);
2573 CU_ASSERT(NGHTTP2_ALTSVC == ud.recv_frame_hd.type);
2574 CU_ASSERT(NGHTTP2_MAX_FRAME_SIZE_MIN == ud.recv_frame_hd.length);
2575
2576 nghttp2_session_del(session);
2577
2578 /* send too large frame */
2579 nghttp2_buf_reset(&buf);
2580
2581 nghttp2_session_client_new2(&session, &callbacks, &ud, option);
2582
2583 session->local_settings.max_frame_size = NGHTTP2_MAX_FRAME_SIZE_MIN - 1;
2584
2585 nghttp2_frame_hd_init(&hd, NGHTTP2_MAX_FRAME_SIZE_MIN + 1, NGHTTP2_ALTSVC,
2586 NGHTTP2_FLAG_NONE, 0);
2587 nghttp2_frame_pack_frame_hd(buf.last, &hd);
2588 buf.last += NGHTTP2_FRAME_HDLEN;
2589 nghttp2_put_uint16be(buf.last, sizeof(origin) - 1);
2590 buf.last += 2;
2591 buf.last = nghttp2_cpymem(buf.last, origin, sizeof(origin) - 1);
2592 memset(buf.last, 0, nghttp2_buf_avail(&buf));
2593 buf.last += nghttp2_buf_avail(&buf);
2594
2595 ud.frame_recv_cb_called = 0;
2596 rv = nghttp2_session_mem_recv(session, buf.pos, nghttp2_buf_len(&buf));
2597
2598 CU_ASSERT((ssize_t)nghttp2_buf_len(&buf) == rv);
2599 CU_ASSERT(0 == ud.frame_recv_cb_called);
2600
2601 nghttp2_session_del(session);
2602
2603 /* received by server */
2604 nghttp2_buf_reset(&buf);
2605
2606 nghttp2_session_server_new2(&session, &callbacks, &ud, option);
2607
2608 nghttp2_frame_hd_init(&hd, 2 + sizeof(origin) - 1 + sizeof(field_value) - 1,
2609 NGHTTP2_ALTSVC, NGHTTP2_FLAG_NONE, 0);
2610 nghttp2_frame_pack_frame_hd(buf.last, &hd);
2611 buf.last += NGHTTP2_FRAME_HDLEN;
2612 nghttp2_put_uint16be(buf.last, sizeof(origin) - 1);
2613 buf.last += 2;
2614 buf.last = nghttp2_cpymem(buf.last, origin, sizeof(origin) - 1);
2615 buf.last = nghttp2_cpymem(buf.last, field_value, sizeof(field_value) - 1);
2616
2617 ud.frame_recv_cb_called = 0;
2618 rv = nghttp2_session_mem_recv(session, buf.pos, nghttp2_buf_len(&buf));
2619
2620 CU_ASSERT((ssize_t)nghttp2_buf_len(&buf) == rv);
2621 CU_ASSERT(0 == ud.frame_recv_cb_called);
2622
2623 nghttp2_session_del(session);
2624
2625 nghttp2_buf_free(&buf, mem);
2626 nghttp2_option_del(option);
2627 }
2628
test_nghttp2_session_recv_origin(void)2629 void test_nghttp2_session_recv_origin(void) {
2630 nghttp2_session *session;
2631 nghttp2_session_callbacks callbacks;
2632 my_user_data ud;
2633 nghttp2_bufs bufs;
2634 ssize_t rv;
2635 nghttp2_option *option;
2636 nghttp2_extension frame;
2637 nghttp2_ext_origin origin;
2638 nghttp2_origin_entry ov;
2639 static const uint8_t nghttp2[] = "https://nghttp2.org";
2640
2641 frame_pack_bufs_init(&bufs);
2642
2643 frame.payload = &origin;
2644
2645 ov.origin = (uint8_t *)nghttp2;
2646 ov.origin_len = sizeof(nghttp2) - 1;
2647
2648 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
2649
2650 callbacks.on_frame_recv_callback = on_frame_recv_callback;
2651
2652 nghttp2_option_new(&option);
2653 nghttp2_option_set_builtin_recv_extension_type(option, NGHTTP2_ORIGIN);
2654
2655 nghttp2_session_client_new2(&session, &callbacks, &ud, option);
2656
2657 nghttp2_frame_origin_init(&frame, &ov, 1);
2658
2659 rv = nghttp2_frame_pack_origin(&bufs, &frame);
2660
2661 CU_ASSERT(0 == rv);
2662
2663 ud.frame_recv_cb_called = 0;
2664 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
2665 nghttp2_bufs_len(&bufs));
2666
2667 CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == rv);
2668 CU_ASSERT(1 == ud.frame_recv_cb_called);
2669 CU_ASSERT(NGHTTP2_ORIGIN == ud.recv_frame_hd.type);
2670 CU_ASSERT(NGHTTP2_FLAG_NONE == ud.recv_frame_hd.flags);
2671 CU_ASSERT(0 == ud.recv_frame_hd.stream_id);
2672
2673 nghttp2_session_del(session);
2674 nghttp2_bufs_reset(&bufs);
2675
2676 /* The length of origin is larger than payload length. */
2677 nghttp2_session_client_new2(&session, &callbacks, &ud, option);
2678
2679 nghttp2_frame_origin_init(&frame, &ov, 1);
2680 rv = nghttp2_frame_pack_origin(&bufs, &frame);
2681
2682 CU_ASSERT(0 == rv);
2683
2684 nghttp2_put_uint16be(bufs.head->buf.pos + NGHTTP2_FRAME_HDLEN,
2685 (uint16_t)sizeof(nghttp2));
2686
2687 ud.frame_recv_cb_called = 0;
2688 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
2689 nghttp2_bufs_len(&bufs));
2690
2691 CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == rv);
2692 CU_ASSERT(0 == ud.frame_recv_cb_called);
2693
2694 nghttp2_session_del(session);
2695 nghttp2_bufs_reset(&bufs);
2696
2697 /* A frame should be ignored if it is sent to a stream other than
2698 stream 0. */
2699 nghttp2_session_client_new2(&session, &callbacks, &ud, option);
2700
2701 nghttp2_frame_origin_init(&frame, &ov, 1);
2702 frame.hd.stream_id = 1;
2703 rv = nghttp2_frame_pack_origin(&bufs, &frame);
2704
2705 CU_ASSERT(0 == rv);
2706
2707 ud.frame_recv_cb_called = 0;
2708 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
2709 nghttp2_bufs_len(&bufs));
2710
2711 CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == rv);
2712 CU_ASSERT(0 == ud.frame_recv_cb_called);
2713
2714 nghttp2_session_del(session);
2715 nghttp2_bufs_reset(&bufs);
2716
2717 /* A frame should be ignored if the reserved flag is set */
2718 nghttp2_session_client_new2(&session, &callbacks, &ud, option);
2719
2720 nghttp2_frame_origin_init(&frame, &ov, 1);
2721 frame.hd.flags = 0xf0;
2722 rv = nghttp2_frame_pack_origin(&bufs, &frame);
2723
2724 CU_ASSERT(0 == rv);
2725
2726 ud.frame_recv_cb_called = 0;
2727 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
2728 nghttp2_bufs_len(&bufs));
2729
2730 CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == rv);
2731 CU_ASSERT(0 == ud.frame_recv_cb_called);
2732
2733 nghttp2_session_del(session);
2734 nghttp2_bufs_reset(&bufs);
2735
2736 /* A frame should be ignored if it is received by a server. */
2737 nghttp2_session_server_new2(&session, &callbacks, &ud, option);
2738
2739 nghttp2_frame_origin_init(&frame, &ov, 1);
2740 rv = nghttp2_frame_pack_origin(&bufs, &frame);
2741
2742 CU_ASSERT(0 == rv);
2743
2744 ud.frame_recv_cb_called = 0;
2745 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
2746 nghttp2_bufs_len(&bufs));
2747
2748 CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == rv);
2749 CU_ASSERT(0 == ud.frame_recv_cb_called);
2750
2751 nghttp2_session_del(session);
2752 nghttp2_bufs_reset(&bufs);
2753
2754 /* Receiving empty ORIGIN frame */
2755 nghttp2_session_client_new2(&session, &callbacks, &ud, option);
2756
2757 nghttp2_frame_origin_init(&frame, NULL, 0);
2758 rv = nghttp2_frame_pack_origin(&bufs, &frame);
2759
2760 CU_ASSERT(0 == rv);
2761
2762 ud.frame_recv_cb_called = 0;
2763 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
2764 nghttp2_bufs_len(&bufs));
2765
2766 CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == rv);
2767 CU_ASSERT(1 == ud.frame_recv_cb_called);
2768 CU_ASSERT(NGHTTP2_ORIGIN == ud.recv_frame_hd.type);
2769
2770 nghttp2_session_del(session);
2771
2772 nghttp2_option_del(option);
2773 nghttp2_bufs_free(&bufs);
2774 }
2775
test_nghttp2_session_recv_priority_update(void)2776 void test_nghttp2_session_recv_priority_update(void) {
2777 nghttp2_session *session;
2778 nghttp2_session_callbacks callbacks;
2779 my_user_data ud;
2780 nghttp2_bufs bufs;
2781 ssize_t rv;
2782 nghttp2_option *option;
2783 nghttp2_extension frame;
2784 nghttp2_ext_priority_update priority_update;
2785 nghttp2_stream *stream;
2786 nghttp2_hd_deflater deflater;
2787 nghttp2_mem *mem;
2788 uint8_t large_field_value[sizeof(session->iframe.raw_sbuf) + 1];
2789 nghttp2_outbound_item *item;
2790 size_t i;
2791 int32_t stream_id;
2792 static const uint8_t field_value[] = "u=2,i";
2793
2794 mem = nghttp2_mem_default();
2795
2796 memset(large_field_value, ' ', sizeof(large_field_value));
2797 memcpy(large_field_value, field_value, sizeof(field_value) - 1);
2798
2799 frame_pack_bufs_init(&bufs);
2800
2801 frame.payload = &priority_update;
2802
2803 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
2804
2805 callbacks.on_frame_recv_callback = on_frame_recv_callback;
2806
2807 nghttp2_option_new(&option);
2808 nghttp2_option_set_builtin_recv_extension_type(option,
2809 NGHTTP2_PRIORITY_UPDATE);
2810
2811 nghttp2_session_server_new2(&session, &callbacks, &ud, option);
2812
2813 session->pending_no_rfc7540_priorities = 1;
2814
2815 nghttp2_frame_priority_update_init(&frame, 1, (uint8_t *)field_value,
2816 sizeof(field_value) - 1);
2817
2818 nghttp2_frame_pack_priority_update(&bufs, &frame);
2819
2820 open_recv_stream(session, 1);
2821
2822 ud.frame_recv_cb_called = 0;
2823 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
2824 nghttp2_bufs_len(&bufs));
2825
2826 CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == rv);
2827 CU_ASSERT(1 == ud.frame_recv_cb_called);
2828 CU_ASSERT(NGHTTP2_PRIORITY_UPDATE == ud.recv_frame_hd.type);
2829 CU_ASSERT(NGHTTP2_FLAG_NONE == ud.recv_frame_hd.flags);
2830 CU_ASSERT(0 == ud.recv_frame_hd.stream_id);
2831
2832 stream = nghttp2_session_get_stream_raw(session, 1);
2833
2834 CU_ASSERT(2 == nghttp2_extpri_uint8_urgency(stream->extpri));
2835 CU_ASSERT(1 == nghttp2_extpri_uint8_inc(stream->extpri));
2836
2837 nghttp2_session_del(session);
2838 nghttp2_bufs_reset(&bufs);
2839
2840 /* Check that priority which is received in idle state is
2841 retained. */
2842 nghttp2_session_server_new2(&session, &callbacks, &ud, option);
2843
2844 session->pending_no_rfc7540_priorities = 1;
2845
2846 nghttp2_frame_priority_update_init(&frame, 1, (uint8_t *)field_value,
2847 sizeof(field_value) - 1);
2848
2849 nghttp2_frame_pack_priority_update(&bufs, &frame);
2850
2851 ud.frame_recv_cb_called = 0;
2852 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
2853 nghttp2_bufs_len(&bufs));
2854
2855 CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == rv);
2856 CU_ASSERT(1 == ud.frame_recv_cb_called);
2857 CU_ASSERT(NGHTTP2_PRIORITY_UPDATE == ud.recv_frame_hd.type);
2858 CU_ASSERT(NGHTTP2_FLAG_NONE == ud.recv_frame_hd.flags);
2859 CU_ASSERT(0 == ud.recv_frame_hd.stream_id);
2860
2861 stream = nghttp2_session_get_stream_raw(session, 1);
2862
2863 CU_ASSERT(NGHTTP2_STREAM_IDLE == stream->state);
2864 CU_ASSERT(2 == nghttp2_extpri_uint8_urgency(stream->extpri));
2865 CU_ASSERT(1 == nghttp2_extpri_uint8_inc(stream->extpri));
2866
2867 nghttp2_hd_deflate_init(&deflater, mem);
2868 nghttp2_bufs_reset(&bufs);
2869 rv = pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, reqnv,
2870 ARRLEN(reqnv), mem);
2871
2872 CU_ASSERT(0 == rv);
2873
2874 ud.frame_recv_cb_called = 0;
2875 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
2876 nghttp2_bufs_len(&bufs));
2877
2878 CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == rv);
2879 CU_ASSERT(1 == ud.frame_recv_cb_called);
2880 CU_ASSERT(NGHTTP2_HEADERS == ud.recv_frame_hd.type);
2881 CU_ASSERT(NGHTTP2_STREAM_OPENING == stream->state);
2882 CU_ASSERT(2 == nghttp2_extpri_uint8_urgency(stream->extpri));
2883 CU_ASSERT(1 == nghttp2_extpri_uint8_inc(stream->extpri));
2884
2885 nghttp2_hd_deflate_free(&deflater);
2886
2887 nghttp2_session_del(session);
2888 nghttp2_bufs_reset(&bufs);
2889
2890 /* PRIORITY_UPDATE with too large field_value is discarded */
2891 nghttp2_session_server_new2(&session, &callbacks, &ud, option);
2892
2893 session->pending_no_rfc7540_priorities = 1;
2894
2895 nghttp2_frame_priority_update_init(&frame, 1, large_field_value,
2896 sizeof(large_field_value));
2897
2898 nghttp2_frame_pack_priority_update(&bufs, &frame);
2899
2900 open_recv_stream(session, 1);
2901
2902 ud.frame_recv_cb_called = 0;
2903 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
2904 nghttp2_bufs_len(&bufs));
2905
2906 CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == rv);
2907 CU_ASSERT(0 == ud.frame_recv_cb_called);
2908
2909 stream = nghttp2_session_get_stream_raw(session, 1);
2910
2911 CU_ASSERT(NGHTTP2_EXTPRI_DEFAULT_URGENCY == stream->extpri);
2912
2913 nghttp2_session_del(session);
2914 nghttp2_bufs_reset(&bufs);
2915
2916 /* Connection error if client receives PRIORITY_UPDATE. */
2917 nghttp2_session_client_new2(&session, &callbacks, &ud, option);
2918
2919 session->pending_no_rfc7540_priorities = 1;
2920
2921 nghttp2_frame_priority_update_init(&frame, 1, (uint8_t *)field_value,
2922 sizeof(field_value) - 1);
2923
2924 nghttp2_frame_pack_priority_update(&bufs, &frame);
2925
2926 open_sent_stream(session, 1);
2927
2928 ud.frame_recv_cb_called = 0;
2929 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
2930 nghttp2_bufs_len(&bufs));
2931
2932 CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == rv);
2933 CU_ASSERT(0 == ud.frame_recv_cb_called);
2934
2935 item = nghttp2_session_get_next_ob_item(session);
2936 CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
2937 CU_ASSERT(NGHTTP2_PROTOCOL_ERROR == item->frame.goaway.error_code);
2938
2939 nghttp2_session_del(session);
2940 nghttp2_bufs_reset(&bufs);
2941
2942 /* The number of idle streams exceeds the maximum. */
2943 nghttp2_session_server_new2(&session, &callbacks, &ud, option);
2944
2945 session->pending_no_rfc7540_priorities = 1;
2946 session->local_settings.max_concurrent_streams = 100;
2947
2948 for (i = 0; i < 101; ++i) {
2949 stream_id = (int32_t)(i * 2 + 1);
2950 nghttp2_frame_priority_update_init(
2951 &frame, stream_id, (uint8_t *)field_value, sizeof(field_value) - 1);
2952
2953 nghttp2_frame_pack_priority_update(&bufs, &frame);
2954
2955 ud.frame_recv_cb_called = 0;
2956 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
2957 nghttp2_bufs_len(&bufs));
2958
2959 if (i < 100) {
2960 CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == rv);
2961 CU_ASSERT(1 == ud.frame_recv_cb_called);
2962 CU_ASSERT(NGHTTP2_PRIORITY_UPDATE == ud.recv_frame_hd.type);
2963 } else {
2964 CU_ASSERT(0 == ud.frame_recv_cb_called);
2965 }
2966
2967 nghttp2_bufs_reset(&bufs);
2968 }
2969
2970 item = nghttp2_session_get_next_ob_item(session);
2971 CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
2972 CU_ASSERT(NGHTTP2_PROTOCOL_ERROR == item->frame.goaway.error_code);
2973
2974 nghttp2_session_del(session);
2975 nghttp2_option_del(option);
2976 nghttp2_bufs_free(&bufs);
2977 }
2978
test_nghttp2_session_continue(void)2979 void test_nghttp2_session_continue(void) {
2980 nghttp2_session *session;
2981 nghttp2_session_callbacks callbacks;
2982 my_user_data user_data;
2983 const nghttp2_nv nv1[] = {MAKE_NV(":method", "GET"), MAKE_NV(":path", "/")};
2984 const nghttp2_nv nv2[] = {MAKE_NV("user-agent", "nghttp2/1.0.0"),
2985 MAKE_NV("alpha", "bravo")};
2986 nghttp2_bufs bufs;
2987 nghttp2_buf *buf;
2988 size_t framelen1, framelen2;
2989 ssize_t rv;
2990 uint8_t buffer[4096];
2991 nghttp2_buf databuf;
2992 nghttp2_frame frame;
2993 nghttp2_nv *nva;
2994 size_t nvlen;
2995 const nghttp2_frame *recv_frame;
2996 nghttp2_frame_hd data_hd;
2997 nghttp2_hd_deflater deflater;
2998 nghttp2_mem *mem;
2999
3000 mem = nghttp2_mem_default();
3001 frame_pack_bufs_init(&bufs);
3002 nghttp2_buf_wrap_init(&databuf, buffer, sizeof(buffer));
3003
3004 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
3005 callbacks.send_callback = null_send_callback;
3006 callbacks.on_frame_recv_callback = on_frame_recv_callback;
3007 callbacks.on_data_chunk_recv_callback = pause_on_data_chunk_recv_callback;
3008 callbacks.on_header_callback = pause_on_header_callback;
3009 callbacks.on_begin_headers_callback = on_begin_headers_callback;
3010
3011 nghttp2_session_server_new(&session, &callbacks, &user_data);
3012 /* disable strict HTTP layering checks */
3013 session->opt_flags |= NGHTTP2_OPTMASK_NO_HTTP_MESSAGING;
3014
3015 nghttp2_hd_deflate_init(&deflater, mem);
3016
3017 /* Make 2 HEADERS frames */
3018 nvlen = ARRLEN(nv1);
3019 nghttp2_nv_array_copy(&nva, nv1, nvlen, mem);
3020 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 1,
3021 NGHTTP2_HCAT_HEADERS, NULL, nva, nvlen);
3022 rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
3023
3024 CU_ASSERT(0 == rv);
3025 CU_ASSERT(nghttp2_bufs_len(&bufs) > 0);
3026
3027 nghttp2_frame_headers_free(&frame.headers, mem);
3028
3029 buf = &bufs.head->buf;
3030 assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
3031
3032 framelen1 = nghttp2_buf_len(buf);
3033 databuf.last = nghttp2_cpymem(databuf.last, buf->pos, nghttp2_buf_len(buf));
3034
3035 nvlen = ARRLEN(nv2);
3036 nghttp2_nv_array_copy(&nva, nv2, nvlen, mem);
3037 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 3,
3038 NGHTTP2_HCAT_HEADERS, NULL, nva, nvlen);
3039 nghttp2_bufs_reset(&bufs);
3040 rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
3041
3042 CU_ASSERT(0 == rv);
3043 CU_ASSERT(nghttp2_bufs_len(&bufs) > 0);
3044
3045 nghttp2_frame_headers_free(&frame.headers, mem);
3046
3047 assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
3048
3049 framelen2 = nghttp2_buf_len(buf);
3050 databuf.last = nghttp2_cpymem(databuf.last, buf->pos, nghttp2_buf_len(buf));
3051
3052 /* Receive 1st HEADERS and pause */
3053 user_data.begin_headers_cb_called = 0;
3054 user_data.header_cb_called = 0;
3055 rv =
3056 nghttp2_session_mem_recv(session, databuf.pos, nghttp2_buf_len(&databuf));
3057
3058 CU_ASSERT(rv >= 0);
3059 databuf.pos += rv;
3060
3061 recv_frame = user_data.frame;
3062 CU_ASSERT(NGHTTP2_HEADERS == recv_frame->hd.type);
3063 CU_ASSERT(framelen1 - NGHTTP2_FRAME_HDLEN == recv_frame->hd.length);
3064
3065 CU_ASSERT(1 == user_data.begin_headers_cb_called);
3066 CU_ASSERT(1 == user_data.header_cb_called);
3067
3068 CU_ASSERT(nghttp2_nv_equal(&nv1[0], &user_data.nv));
3069
3070 /* get 2nd header field */
3071 user_data.begin_headers_cb_called = 0;
3072 user_data.header_cb_called = 0;
3073 rv =
3074 nghttp2_session_mem_recv(session, databuf.pos, nghttp2_buf_len(&databuf));
3075
3076 CU_ASSERT(rv >= 0);
3077 databuf.pos += rv;
3078
3079 CU_ASSERT(0 == user_data.begin_headers_cb_called);
3080 CU_ASSERT(1 == user_data.header_cb_called);
3081
3082 CU_ASSERT(nghttp2_nv_equal(&nv1[1], &user_data.nv));
3083
3084 /* will call end_headers_callback and receive 2nd HEADERS and pause */
3085 user_data.begin_headers_cb_called = 0;
3086 user_data.header_cb_called = 0;
3087 rv =
3088 nghttp2_session_mem_recv(session, databuf.pos, nghttp2_buf_len(&databuf));
3089
3090 CU_ASSERT(rv >= 0);
3091 databuf.pos += rv;
3092
3093 recv_frame = user_data.frame;
3094 CU_ASSERT(NGHTTP2_HEADERS == recv_frame->hd.type);
3095 CU_ASSERT(framelen2 - NGHTTP2_FRAME_HDLEN == recv_frame->hd.length);
3096
3097 CU_ASSERT(1 == user_data.begin_headers_cb_called);
3098 CU_ASSERT(1 == user_data.header_cb_called);
3099
3100 CU_ASSERT(nghttp2_nv_equal(&nv2[0], &user_data.nv));
3101
3102 /* get 2nd header field */
3103 user_data.begin_headers_cb_called = 0;
3104 user_data.header_cb_called = 0;
3105 rv =
3106 nghttp2_session_mem_recv(session, databuf.pos, nghttp2_buf_len(&databuf));
3107
3108 CU_ASSERT(rv >= 0);
3109 databuf.pos += rv;
3110
3111 CU_ASSERT(0 == user_data.begin_headers_cb_called);
3112 CU_ASSERT(1 == user_data.header_cb_called);
3113
3114 CU_ASSERT(nghttp2_nv_equal(&nv2[1], &user_data.nv));
3115
3116 /* No input data, frame_recv_callback is called */
3117 user_data.begin_headers_cb_called = 0;
3118 user_data.header_cb_called = 0;
3119 user_data.frame_recv_cb_called = 0;
3120 rv =
3121 nghttp2_session_mem_recv(session, databuf.pos, nghttp2_buf_len(&databuf));
3122
3123 CU_ASSERT(rv >= 0);
3124 databuf.pos += rv;
3125
3126 CU_ASSERT(0 == user_data.begin_headers_cb_called);
3127 CU_ASSERT(0 == user_data.header_cb_called);
3128 CU_ASSERT(1 == user_data.frame_recv_cb_called);
3129
3130 /* Receive DATA */
3131 nghttp2_frame_hd_init(&data_hd, 16, NGHTTP2_DATA, NGHTTP2_FLAG_NONE, 1);
3132
3133 nghttp2_buf_reset(&databuf);
3134 nghttp2_frame_pack_frame_hd(databuf.pos, &data_hd);
3135
3136 /* Intentionally specify larger buffer size to see pause is kicked
3137 in. */
3138 databuf.last = databuf.end;
3139
3140 user_data.frame_recv_cb_called = 0;
3141 rv =
3142 nghttp2_session_mem_recv(session, databuf.pos, nghttp2_buf_len(&databuf));
3143
3144 CU_ASSERT(16 + NGHTTP2_FRAME_HDLEN == rv);
3145 CU_ASSERT(0 == user_data.frame_recv_cb_called);
3146
3147 /* Next nghttp2_session_mem_recv invokes on_frame_recv_callback and
3148 pause again in on_data_chunk_recv_callback since we pass same
3149 DATA frame. */
3150 user_data.frame_recv_cb_called = 0;
3151 rv =
3152 nghttp2_session_mem_recv(session, databuf.pos, nghttp2_buf_len(&databuf));
3153 CU_ASSERT(16 + NGHTTP2_FRAME_HDLEN == rv);
3154 CU_ASSERT(1 == user_data.frame_recv_cb_called);
3155
3156 /* And finally call on_frame_recv_callback with 0 size input */
3157 user_data.frame_recv_cb_called = 0;
3158 rv = nghttp2_session_mem_recv(session, NULL, 0);
3159 CU_ASSERT(0 == rv);
3160 CU_ASSERT(1 == user_data.frame_recv_cb_called);
3161
3162 nghttp2_bufs_free(&bufs);
3163 nghttp2_hd_deflate_free(&deflater);
3164 nghttp2_session_del(session);
3165 }
3166
test_nghttp2_session_add_frame(void)3167 void test_nghttp2_session_add_frame(void) {
3168 nghttp2_session *session;
3169 nghttp2_session_callbacks callbacks;
3170 accumulator acc;
3171 my_user_data user_data;
3172 nghttp2_outbound_item *item;
3173 nghttp2_frame *frame;
3174 nghttp2_nv *nva;
3175 size_t nvlen;
3176 nghttp2_mem *mem;
3177
3178 mem = nghttp2_mem_default();
3179 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
3180 callbacks.send_callback = accumulator_send_callback;
3181
3182 acc.length = 0;
3183 user_data.acc = &acc;
3184
3185 CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, &user_data));
3186
3187 item = mem->malloc(sizeof(nghttp2_outbound_item), NULL);
3188
3189 nghttp2_outbound_item_init(item);
3190
3191 frame = &item->frame;
3192
3193 nvlen = ARRLEN(reqnv);
3194 nghttp2_nv_array_copy(&nva, reqnv, nvlen, mem);
3195
3196 nghttp2_frame_headers_init(
3197 &frame->headers, NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PRIORITY,
3198 (int32_t)session->next_stream_id, NGHTTP2_HCAT_REQUEST, NULL, nva, nvlen);
3199
3200 session->next_stream_id += 2;
3201
3202 CU_ASSERT(0 == nghttp2_session_add_item(session, item));
3203 CU_ASSERT(NULL != nghttp2_outbound_queue_top(&session->ob_syn));
3204 CU_ASSERT(0 == nghttp2_session_send(session));
3205 CU_ASSERT(NGHTTP2_HEADERS == acc.buf[3]);
3206 CU_ASSERT((NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PRIORITY) == acc.buf[4]);
3207 /* check stream id */
3208 CU_ASSERT(1 == nghttp2_get_uint32(&acc.buf[5]));
3209
3210 nghttp2_session_del(session);
3211 }
3212
test_nghttp2_session_on_request_headers_received(void)3213 void test_nghttp2_session_on_request_headers_received(void) {
3214 nghttp2_session *session;
3215 nghttp2_session_callbacks callbacks;
3216 my_user_data user_data;
3217 nghttp2_frame frame;
3218 nghttp2_stream *stream;
3219 int32_t stream_id = 1;
3220 nghttp2_nv malformed_nva[] = {MAKE_NV(":path", "\x01")};
3221 nghttp2_nv *nva;
3222 size_t nvlen;
3223 nghttp2_priority_spec pri_spec;
3224 nghttp2_mem *mem;
3225
3226 mem = nghttp2_mem_default();
3227 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
3228 callbacks.on_begin_headers_callback = on_begin_headers_callback;
3229 callbacks.on_invalid_frame_recv_callback = on_invalid_frame_recv_callback;
3230
3231 nghttp2_session_server_new(&session, &callbacks, &user_data);
3232
3233 nghttp2_priority_spec_init(&pri_spec, 0, 255, 0);
3234
3235 nghttp2_frame_headers_init(
3236 &frame.headers, NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PRIORITY,
3237 stream_id, NGHTTP2_HCAT_REQUEST, &pri_spec, NULL, 0);
3238
3239 user_data.begin_headers_cb_called = 0;
3240 user_data.invalid_frame_recv_cb_called = 0;
3241
3242 CU_ASSERT(0 == nghttp2_session_on_request_headers_received(session, &frame));
3243 CU_ASSERT(1 == user_data.begin_headers_cb_called);
3244 stream = nghttp2_session_get_stream(session, stream_id);
3245 CU_ASSERT(NGHTTP2_STREAM_OPENING == stream->state);
3246 CU_ASSERT(255 == stream->weight);
3247
3248 nghttp2_frame_headers_free(&frame.headers, mem);
3249
3250 /* More than un-ACKed max concurrent streams leads REFUSED_STREAM */
3251 session->pending_local_max_concurrent_stream = 1;
3252 nghttp2_frame_headers_init(&frame.headers,
3253 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PRIORITY,
3254 3, NGHTTP2_HCAT_HEADERS, NULL, NULL, 0);
3255 user_data.invalid_frame_recv_cb_called = 0;
3256 CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
3257 nghttp2_session_on_request_headers_received(session, &frame));
3258 CU_ASSERT(1 == user_data.invalid_frame_recv_cb_called);
3259 CU_ASSERT(0 == (session->goaway_flags & NGHTTP2_GOAWAY_TERM_ON_SEND));
3260
3261 nghttp2_frame_headers_free(&frame.headers, mem);
3262 session->local_settings.max_concurrent_streams =
3263 NGHTTP2_DEFAULT_MAX_CONCURRENT_STREAMS;
3264
3265 /* Stream ID less than or equal to the previously received request
3266 HEADERS is just ignored due to race condition */
3267 nghttp2_frame_headers_init(&frame.headers,
3268 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PRIORITY,
3269 3, NGHTTP2_HCAT_HEADERS, NULL, NULL, 0);
3270 user_data.invalid_frame_recv_cb_called = 0;
3271 CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
3272 nghttp2_session_on_request_headers_received(session, &frame));
3273 CU_ASSERT(0 == user_data.invalid_frame_recv_cb_called);
3274 CU_ASSERT(0 == (session->goaway_flags & NGHTTP2_GOAWAY_TERM_ON_SEND));
3275
3276 nghttp2_frame_headers_free(&frame.headers, mem);
3277
3278 /* Stream ID is our side and it is idle stream ID, then treat it as
3279 connection error */
3280 nghttp2_frame_headers_init(&frame.headers,
3281 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PRIORITY,
3282 2, NGHTTP2_HCAT_HEADERS, NULL, NULL, 0);
3283 user_data.invalid_frame_recv_cb_called = 0;
3284 CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
3285 nghttp2_session_on_request_headers_received(session, &frame));
3286 CU_ASSERT(1 == user_data.invalid_frame_recv_cb_called);
3287 CU_ASSERT(session->goaway_flags & NGHTTP2_GOAWAY_TERM_ON_SEND);
3288
3289 nghttp2_frame_headers_free(&frame.headers, mem);
3290
3291 nghttp2_session_del(session);
3292
3293 /* Check malformed headers. The library accept it. */
3294 nghttp2_session_server_new(&session, &callbacks, &user_data);
3295
3296 nvlen = ARRLEN(malformed_nva);
3297 nghttp2_nv_array_copy(&nva, malformed_nva, nvlen, mem);
3298 nghttp2_frame_headers_init(&frame.headers,
3299 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PRIORITY,
3300 1, NGHTTP2_HCAT_HEADERS, NULL, nva, nvlen);
3301 user_data.begin_headers_cb_called = 0;
3302 user_data.invalid_frame_recv_cb_called = 0;
3303 CU_ASSERT(0 == nghttp2_session_on_request_headers_received(session, &frame));
3304 CU_ASSERT(1 == user_data.begin_headers_cb_called);
3305 CU_ASSERT(0 == user_data.invalid_frame_recv_cb_called);
3306
3307 nghttp2_frame_headers_free(&frame.headers, mem);
3308
3309 nghttp2_session_del(session);
3310
3311 /* Check client side */
3312 nghttp2_session_client_new(&session, &callbacks, &user_data);
3313
3314 /* Receiving peer's idle stream ID is subject to connection error */
3315 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 2,
3316 NGHTTP2_HCAT_REQUEST, NULL, NULL, 0);
3317
3318 user_data.invalid_frame_recv_cb_called = 0;
3319 CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
3320 nghttp2_session_on_request_headers_received(session, &frame));
3321 CU_ASSERT(1 == user_data.invalid_frame_recv_cb_called);
3322 CU_ASSERT(session->goaway_flags & NGHTTP2_GOAWAY_TERM_ON_SEND);
3323
3324 nghttp2_frame_headers_free(&frame.headers, mem);
3325
3326 nghttp2_session_del(session);
3327
3328 nghttp2_session_client_new(&session, &callbacks, &user_data);
3329
3330 /* Receiving our's idle stream ID is subject to connection error */
3331 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 1,
3332 NGHTTP2_HCAT_REQUEST, NULL, NULL, 0);
3333
3334 user_data.invalid_frame_recv_cb_called = 0;
3335 CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
3336 nghttp2_session_on_request_headers_received(session, &frame));
3337 CU_ASSERT(1 == user_data.invalid_frame_recv_cb_called);
3338 CU_ASSERT(session->goaway_flags & NGHTTP2_GOAWAY_TERM_ON_SEND);
3339
3340 nghttp2_frame_headers_free(&frame.headers, mem);
3341
3342 nghttp2_session_del(session);
3343
3344 nghttp2_session_client_new(&session, &callbacks, &user_data);
3345
3346 session->next_stream_id = 5;
3347 session->last_sent_stream_id = 3;
3348
3349 /* Stream ID which is not idle and not in stream map is just
3350 ignored */
3351 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 3,
3352 NGHTTP2_HCAT_REQUEST, NULL, NULL, 0);
3353
3354 user_data.invalid_frame_recv_cb_called = 0;
3355 CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
3356 nghttp2_session_on_request_headers_received(session, &frame));
3357 CU_ASSERT(0 == user_data.invalid_frame_recv_cb_called);
3358 CU_ASSERT(0 == (session->goaway_flags & NGHTTP2_GOAWAY_TERM_ON_SEND));
3359
3360 nghttp2_frame_headers_free(&frame.headers, mem);
3361
3362 nghttp2_session_del(session);
3363
3364 nghttp2_session_server_new(&session, &callbacks, &user_data);
3365
3366 /* Stream ID which is equal to local_last_stream_id is ok. */
3367 session->local_last_stream_id = 3;
3368
3369 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 3,
3370 NGHTTP2_HCAT_REQUEST, NULL, NULL, 0);
3371
3372 CU_ASSERT(0 == nghttp2_session_on_request_headers_received(session, &frame));
3373
3374 nghttp2_frame_headers_free(&frame.headers, mem);
3375
3376 /* If GOAWAY has been sent, new stream is ignored */
3377 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 5,
3378 NGHTTP2_HCAT_REQUEST, NULL, NULL, 0);
3379
3380 session->goaway_flags |= NGHTTP2_GOAWAY_SENT;
3381 user_data.invalid_frame_recv_cb_called = 0;
3382 CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
3383 nghttp2_session_on_request_headers_received(session, &frame));
3384 CU_ASSERT(0 == user_data.invalid_frame_recv_cb_called);
3385 CU_ASSERT(0 == (session->goaway_flags & NGHTTP2_GOAWAY_TERM_ON_SEND));
3386
3387 nghttp2_frame_headers_free(&frame.headers, mem);
3388
3389 nghttp2_session_del(session);
3390
3391 nghttp2_session_server_new(&session, &callbacks, &user_data);
3392
3393 /* HEADERS to closed stream */
3394 stream = open_recv_stream(session, 1);
3395 nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_RD);
3396 nghttp2_session_close_stream(session, 1, NGHTTP2_NO_ERROR);
3397
3398 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 1,
3399 NGHTTP2_HCAT_REQUEST, NULL, NULL, 0);
3400
3401 CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
3402 nghttp2_session_on_request_headers_received(session, &frame));
3403 CU_ASSERT(session->goaway_flags & NGHTTP2_GOAWAY_TERM_ON_SEND);
3404
3405 nghttp2_frame_headers_free(&frame.headers, mem);
3406
3407 nghttp2_session_del(session);
3408 }
3409
test_nghttp2_session_on_response_headers_received(void)3410 void test_nghttp2_session_on_response_headers_received(void) {
3411 nghttp2_session *session;
3412 nghttp2_session_callbacks callbacks;
3413 my_user_data user_data;
3414 nghttp2_frame frame;
3415 nghttp2_stream *stream;
3416 nghttp2_mem *mem;
3417
3418 mem = nghttp2_mem_default();
3419 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
3420 callbacks.on_begin_headers_callback = on_begin_headers_callback;
3421 callbacks.on_invalid_frame_recv_callback = on_invalid_frame_recv_callback;
3422
3423 nghttp2_session_client_new(&session, &callbacks, &user_data);
3424 stream = open_sent_stream2(session, 1, NGHTTP2_STREAM_OPENING);
3425 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 1,
3426 NGHTTP2_HCAT_HEADERS, NULL, NULL, 0);
3427
3428 user_data.begin_headers_cb_called = 0;
3429 user_data.invalid_frame_recv_cb_called = 0;
3430
3431 CU_ASSERT(0 == nghttp2_session_on_response_headers_received(session, &frame,
3432 stream));
3433 CU_ASSERT(1 == user_data.begin_headers_cb_called);
3434 CU_ASSERT(NGHTTP2_STREAM_OPENED == stream->state);
3435
3436 nghttp2_frame_headers_free(&frame.headers, mem);
3437 nghttp2_session_del(session);
3438 }
3439
test_nghttp2_session_on_headers_received(void)3440 void test_nghttp2_session_on_headers_received(void) {
3441 nghttp2_session *session;
3442 nghttp2_session_callbacks callbacks;
3443 my_user_data user_data;
3444 nghttp2_frame frame;
3445 nghttp2_stream *stream;
3446 nghttp2_mem *mem;
3447
3448 mem = nghttp2_mem_default();
3449 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
3450 callbacks.on_begin_headers_callback = on_begin_headers_callback;
3451 callbacks.on_invalid_frame_recv_callback = on_invalid_frame_recv_callback;
3452
3453 nghttp2_session_client_new(&session, &callbacks, &user_data);
3454 stream = open_sent_stream2(session, 1, NGHTTP2_STREAM_OPENED);
3455 nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_WR);
3456 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 1,
3457 NGHTTP2_HCAT_HEADERS, NULL, NULL, 0);
3458
3459 user_data.begin_headers_cb_called = 0;
3460 user_data.invalid_frame_recv_cb_called = 0;
3461
3462 CU_ASSERT(0 == nghttp2_session_on_headers_received(session, &frame, stream));
3463 CU_ASSERT(1 == user_data.begin_headers_cb_called);
3464 CU_ASSERT(NGHTTP2_STREAM_OPENED == stream->state);
3465
3466 /* stream closed */
3467 frame.hd.flags |= NGHTTP2_FLAG_END_STREAM;
3468
3469 CU_ASSERT(0 == nghttp2_session_on_headers_received(session, &frame, stream));
3470 CU_ASSERT(2 == user_data.begin_headers_cb_called);
3471
3472 /* Check to see when NGHTTP2_STREAM_CLOSING, incoming HEADERS is
3473 discarded. */
3474 stream = open_sent_stream2(session, 3, NGHTTP2_STREAM_CLOSING);
3475 frame.hd.stream_id = 3;
3476 frame.hd.flags = NGHTTP2_FLAG_END_HEADERS;
3477 CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
3478 nghttp2_session_on_headers_received(session, &frame, stream));
3479 /* See no counters are updated */
3480 CU_ASSERT(2 == user_data.begin_headers_cb_called);
3481 CU_ASSERT(0 == user_data.invalid_frame_recv_cb_called);
3482
3483 /* Server initiated stream */
3484 stream = open_recv_stream(session, 2);
3485
3486 frame.hd.flags = NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM;
3487 frame.hd.stream_id = 2;
3488
3489 CU_ASSERT(0 == nghttp2_session_on_headers_received(session, &frame, stream));
3490 CU_ASSERT(3 == user_data.begin_headers_cb_called);
3491 CU_ASSERT(NGHTTP2_STREAM_OPENED == stream->state);
3492
3493 nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_RD);
3494
3495 /* Further reception of HEADERS is subject to stream error */
3496 CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
3497 nghttp2_session_on_headers_received(session, &frame, stream));
3498 CU_ASSERT(1 == user_data.invalid_frame_recv_cb_called);
3499
3500 nghttp2_frame_headers_free(&frame.headers, mem);
3501
3502 nghttp2_session_del(session);
3503 }
3504
test_nghttp2_session_on_push_response_headers_received(void)3505 void test_nghttp2_session_on_push_response_headers_received(void) {
3506 nghttp2_session *session;
3507 nghttp2_session_callbacks callbacks;
3508 my_user_data user_data;
3509 nghttp2_frame frame;
3510 nghttp2_stream *stream;
3511 nghttp2_outbound_item *item;
3512 nghttp2_mem *mem;
3513
3514 mem = nghttp2_mem_default();
3515 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
3516 callbacks.send_callback = null_send_callback;
3517 callbacks.on_begin_headers_callback = on_begin_headers_callback;
3518 callbacks.on_invalid_frame_recv_callback = on_invalid_frame_recv_callback;
3519
3520 nghttp2_session_client_new(&session, &callbacks, &user_data);
3521 stream = open_recv_stream2(session, 2, NGHTTP2_STREAM_RESERVED);
3522 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 2,
3523 NGHTTP2_HCAT_HEADERS, NULL, NULL, 0);
3524 /* nghttp2_session_on_push_response_headers_received assumes
3525 stream's state is NGHTTP2_STREAM_RESERVED and session->server is
3526 0. */
3527
3528 user_data.begin_headers_cb_called = 0;
3529 user_data.invalid_frame_recv_cb_called = 0;
3530
3531 CU_ASSERT(1 == session->num_incoming_reserved_streams);
3532 CU_ASSERT(0 == nghttp2_session_on_push_response_headers_received(
3533 session, &frame, stream));
3534 CU_ASSERT(1 == user_data.begin_headers_cb_called);
3535 CU_ASSERT(0 == session->num_incoming_reserved_streams);
3536 CU_ASSERT(NGHTTP2_STREAM_OPENED == stream->state);
3537 CU_ASSERT(1 == session->num_incoming_streams);
3538 CU_ASSERT(0 == (stream->flags & NGHTTP2_STREAM_FLAG_PUSH));
3539
3540 /* If un-ACKed max concurrent streams limit is exceeded,
3541 RST_STREAMed */
3542 session->pending_local_max_concurrent_stream = 1;
3543 stream = open_recv_stream2(session, 4, NGHTTP2_STREAM_RESERVED);
3544 frame.hd.stream_id = 4;
3545 CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
3546 nghttp2_session_on_push_response_headers_received(session, &frame,
3547 stream));
3548 item = nghttp2_session_get_next_ob_item(session);
3549 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
3550 CU_ASSERT(NGHTTP2_REFUSED_STREAM == item->frame.rst_stream.error_code);
3551 CU_ASSERT(1 == session->num_incoming_streams);
3552 CU_ASSERT(1 == session->num_incoming_reserved_streams);
3553
3554 CU_ASSERT(0 == nghttp2_session_send(session));
3555 CU_ASSERT(1 == session->num_incoming_streams);
3556
3557 /* If ACKed max concurrent streams limit is exceeded, GOAWAY is
3558 issued */
3559 session->local_settings.max_concurrent_streams = 1;
3560
3561 stream = open_recv_stream2(session, 6, NGHTTP2_STREAM_RESERVED);
3562 frame.hd.stream_id = 6;
3563
3564 CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
3565 nghttp2_session_on_push_response_headers_received(session, &frame,
3566 stream));
3567 item = nghttp2_session_get_next_ob_item(session);
3568 CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
3569 CU_ASSERT(NGHTTP2_PROTOCOL_ERROR == item->frame.goaway.error_code);
3570 CU_ASSERT(1 == session->num_incoming_streams);
3571 CU_ASSERT(1 == session->num_incoming_reserved_streams);
3572
3573 nghttp2_frame_headers_free(&frame.headers, mem);
3574 nghttp2_session_del(session);
3575 }
3576
test_nghttp2_session_on_priority_received(void)3577 void test_nghttp2_session_on_priority_received(void) {
3578 nghttp2_session *session;
3579 nghttp2_session_callbacks callbacks;
3580 my_user_data user_data;
3581 nghttp2_frame frame;
3582 nghttp2_stream *stream, *dep_stream;
3583 nghttp2_priority_spec pri_spec;
3584 nghttp2_outbound_item *item;
3585
3586 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
3587 callbacks.on_frame_recv_callback = on_frame_recv_callback;
3588 callbacks.on_invalid_frame_recv_callback = on_invalid_frame_recv_callback;
3589
3590 nghttp2_session_server_new(&session, &callbacks, &user_data);
3591 stream = open_recv_stream(session, 1);
3592
3593 nghttp2_priority_spec_init(&pri_spec, 0, 2, 0);
3594
3595 nghttp2_frame_priority_init(&frame.priority, 1, &pri_spec);
3596
3597 /* depend on stream 0 */
3598 CU_ASSERT(0 == nghttp2_session_on_priority_received(session, &frame));
3599
3600 CU_ASSERT(2 == stream->weight);
3601
3602 stream = open_sent_stream(session, 2);
3603 dep_stream = open_recv_stream(session, 3);
3604
3605 frame.hd.stream_id = 2;
3606
3607 /* using dependency stream */
3608 nghttp2_priority_spec_init(&frame.priority.pri_spec, 3, 1, 0);
3609
3610 CU_ASSERT(0 == nghttp2_session_on_priority_received(session, &frame));
3611 CU_ASSERT(dep_stream == stream->dep_prev);
3612
3613 /* PRIORITY against idle stream */
3614
3615 frame.hd.stream_id = 100;
3616
3617 CU_ASSERT(0 == nghttp2_session_on_priority_received(session, &frame));
3618
3619 stream = nghttp2_session_get_stream_raw(session, frame.hd.stream_id);
3620
3621 CU_ASSERT(NGHTTP2_STREAM_IDLE == stream->state);
3622 CU_ASSERT(dep_stream == stream->dep_prev);
3623
3624 nghttp2_frame_priority_free(&frame.priority);
3625 nghttp2_session_del(session);
3626
3627 /* Check dep_stream_id == stream_id case */
3628 nghttp2_session_server_new(&session, &callbacks, &user_data);
3629 open_recv_stream(session, 1);
3630
3631 nghttp2_priority_spec_init(&pri_spec, 1, 0, 0);
3632
3633 nghttp2_frame_priority_init(&frame.priority, 1, &pri_spec);
3634
3635 CU_ASSERT(0 == nghttp2_session_on_priority_received(session, &frame));
3636
3637 item = nghttp2_session_get_next_ob_item(session);
3638
3639 CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
3640
3641 nghttp2_frame_priority_free(&frame.priority);
3642 nghttp2_session_del(session);
3643
3644 /* Check again dep_stream_id == stream_id, and stream_id is idle */
3645 nghttp2_session_server_new(&session, &callbacks, &user_data);
3646
3647 nghttp2_priority_spec_init(&pri_spec, 1, 16, 0);
3648
3649 nghttp2_frame_priority_init(&frame.priority, 1, &pri_spec);
3650
3651 CU_ASSERT(0 == nghttp2_session_on_priority_received(session, &frame));
3652
3653 item = nghttp2_session_get_next_ob_item(session);
3654
3655 CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
3656
3657 nghttp2_frame_priority_free(&frame.priority);
3658 nghttp2_session_del(session);
3659 }
3660
test_nghttp2_session_on_rst_stream_received(void)3661 void test_nghttp2_session_on_rst_stream_received(void) {
3662 nghttp2_session *session;
3663 nghttp2_session_callbacks callbacks;
3664 my_user_data user_data;
3665 nghttp2_frame frame;
3666 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
3667 nghttp2_session_server_new(&session, &callbacks, &user_data);
3668 open_recv_stream(session, 1);
3669
3670 nghttp2_frame_rst_stream_init(&frame.rst_stream, 1, NGHTTP2_PROTOCOL_ERROR);
3671
3672 CU_ASSERT(0 == nghttp2_session_on_rst_stream_received(session, &frame));
3673 CU_ASSERT(NULL == nghttp2_session_get_stream(session, 1));
3674
3675 nghttp2_frame_rst_stream_free(&frame.rst_stream);
3676 nghttp2_session_del(session);
3677 }
3678
test_nghttp2_session_on_settings_received(void)3679 void test_nghttp2_session_on_settings_received(void) {
3680 nghttp2_session *session;
3681 nghttp2_session_callbacks callbacks;
3682 my_user_data user_data;
3683 nghttp2_stream *stream1, *stream2;
3684 nghttp2_frame frame;
3685 const size_t niv = 5;
3686 nghttp2_settings_entry iv[255];
3687 nghttp2_outbound_item *item;
3688 nghttp2_nv nv = MAKE_NV(":authority", "example.org");
3689 nghttp2_mem *mem;
3690 nghttp2_option *option;
3691 uint8_t data[2048];
3692 nghttp2_frame_hd hd;
3693 int rv;
3694 ssize_t nread;
3695 nghttp2_stream *stream;
3696
3697 mem = nghttp2_mem_default();
3698
3699 iv[0].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS;
3700 iv[0].value = 50;
3701
3702 iv[1].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS;
3703 iv[1].value = 1000000009;
3704
3705 iv[2].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
3706 iv[2].value = 64 * 1024;
3707
3708 iv[3].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
3709 iv[3].value = 1024;
3710
3711 iv[4].settings_id = NGHTTP2_SETTINGS_ENABLE_PUSH;
3712 iv[4].value = 0;
3713
3714 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
3715 callbacks.send_callback = null_send_callback;
3716
3717 nghttp2_session_client_new(&session, &callbacks, &user_data);
3718 session->remote_settings.initial_window_size = 16 * 1024;
3719
3720 stream1 = open_sent_stream(session, 1);
3721 stream2 = open_recv_stream(session, 2);
3722
3723 /* Set window size for each streams and will see how settings
3724 updates these values */
3725 stream1->remote_window_size = 16 * 1024;
3726 stream2->remote_window_size = -48 * 1024;
3727
3728 nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE,
3729 dup_iv(iv, niv), niv);
3730
3731 CU_ASSERT(0 == nghttp2_session_on_settings_received(session, &frame, 0));
3732 CU_ASSERT(1000000009 == session->remote_settings.max_concurrent_streams);
3733 CU_ASSERT(64 * 1024 == session->remote_settings.initial_window_size);
3734 CU_ASSERT(1024 == session->remote_settings.header_table_size);
3735 CU_ASSERT(0 == session->remote_settings.enable_push);
3736
3737 CU_ASSERT(64 * 1024 == stream1->remote_window_size);
3738 CU_ASSERT(0 == stream2->remote_window_size);
3739
3740 frame.settings.iv[2].value = 16 * 1024;
3741
3742 CU_ASSERT(0 == nghttp2_session_on_settings_received(session, &frame, 0));
3743
3744 CU_ASSERT(16 * 1024 == stream1->remote_window_size);
3745 CU_ASSERT(-48 * 1024 == stream2->remote_window_size);
3746
3747 CU_ASSERT(16 * 1024 == nghttp2_session_get_stream_remote_window_size(
3748 session, stream1->stream_id));
3749 CU_ASSERT(0 == nghttp2_session_get_stream_remote_window_size(
3750 session, stream2->stream_id));
3751
3752 nghttp2_frame_settings_free(&frame.settings, mem);
3753
3754 nghttp2_session_del(session);
3755
3756 /* Check ACK with niv > 0 */
3757 nghttp2_session_server_new(&session, &callbacks, NULL);
3758 nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_ACK, dup_iv(iv, 1),
3759 1);
3760 CU_ASSERT(0 == nghttp2_session_on_settings_received(session, &frame, 0));
3761 item = nghttp2_session_get_next_ob_item(session);
3762 CU_ASSERT(item != NULL);
3763 CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
3764
3765 nghttp2_frame_settings_free(&frame.settings, mem);
3766 nghttp2_session_del(session);
3767
3768 /* Check ACK against no inflight SETTINGS */
3769 nghttp2_session_server_new(&session, &callbacks, NULL);
3770 nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_ACK, NULL, 0);
3771
3772 CU_ASSERT(0 == nghttp2_session_on_settings_received(session, &frame, 0));
3773 item = nghttp2_session_get_next_ob_item(session);
3774 CU_ASSERT(item != NULL);
3775 CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
3776
3777 nghttp2_frame_settings_free(&frame.settings, mem);
3778 nghttp2_session_del(session);
3779
3780 /* Check that 2 SETTINGS_HEADER_TABLE_SIZE 0 and 4096 are included
3781 and header table size is once cleared to 0. */
3782 nghttp2_session_client_new(&session, &callbacks, NULL);
3783
3784 nghttp2_submit_request(session, NULL, &nv, 1, NULL, NULL);
3785
3786 nghttp2_session_send(session);
3787
3788 CU_ASSERT(session->hd_deflater.ctx.hd_table.len > 0);
3789
3790 iv[0].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
3791 iv[0].value = 0;
3792
3793 iv[1].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
3794 iv[1].value = 2048;
3795
3796 nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE, dup_iv(iv, 2),
3797 2);
3798
3799 CU_ASSERT(0 == nghttp2_session_on_settings_received(session, &frame, 0));
3800
3801 CU_ASSERT(0 == session->hd_deflater.ctx.hd_table.len);
3802 CU_ASSERT(2048 == session->hd_deflater.ctx.hd_table_bufsize_max);
3803 CU_ASSERT(2048 == session->remote_settings.header_table_size);
3804
3805 nghttp2_frame_settings_free(&frame.settings, mem);
3806 nghttp2_session_del(session);
3807
3808 /* Check that remote SETTINGS_MAX_CONCURRENT_STREAMS is set to a value set by
3809 nghttp2_option_set_peer_max_concurrent_streams() and reset to the default
3810 value (unlimited) after receiving initial SETTINGS frame from the peer. */
3811 nghttp2_option_new(&option);
3812 nghttp2_option_set_peer_max_concurrent_streams(option, 1000);
3813 nghttp2_session_client_new2(&session, &callbacks, NULL, option);
3814 CU_ASSERT(1000 == session->remote_settings.max_concurrent_streams);
3815
3816 nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE, NULL, 0);
3817 CU_ASSERT(0 == nghttp2_session_on_settings_received(session, &frame, 0));
3818 CU_ASSERT(NGHTTP2_DEFAULT_MAX_CONCURRENT_STREAMS ==
3819 session->remote_settings.max_concurrent_streams);
3820
3821 nghttp2_frame_settings_free(&frame.settings, mem);
3822 nghttp2_session_del(session);
3823 nghttp2_option_del(option);
3824
3825 /* Check too large SETTINGS_MAX_FRAME_SIZE */
3826 nghttp2_session_server_new(&session, &callbacks, NULL);
3827
3828 iv[0].settings_id = NGHTTP2_SETTINGS_MAX_FRAME_SIZE;
3829 iv[0].value = NGHTTP2_MAX_FRAME_SIZE_MAX + 1;
3830
3831 nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE, dup_iv(iv, 1),
3832 1);
3833
3834 CU_ASSERT(0 == nghttp2_session_on_settings_received(session, &frame, 0));
3835
3836 item = nghttp2_session_get_next_ob_item(session);
3837
3838 CU_ASSERT(item != NULL);
3839 CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
3840
3841 nghttp2_frame_settings_free(&frame.settings, mem);
3842 nghttp2_session_del(session);
3843
3844 /* Check the case where stream window size overflows */
3845 nghttp2_session_server_new(&session, &callbacks, NULL);
3846
3847 stream1 = open_recv_stream(session, 1);
3848
3849 /* This will increment window size by 1 */
3850 nghttp2_frame_window_update_init(&frame.window_update, NGHTTP2_FLAG_NONE, 1,
3851 1);
3852
3853 CU_ASSERT(0 == nghttp2_session_on_window_update_received(session, &frame));
3854
3855 nghttp2_frame_window_update_free(&frame.window_update);
3856
3857 iv[0].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
3858 iv[0].value = NGHTTP2_MAX_WINDOW_SIZE;
3859
3860 nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE, dup_iv(iv, 1),
3861 1);
3862
3863 /* Now window size gets NGHTTP2_MAX_WINDOW_SIZE + 1, which is
3864 unacceptable situation in protocol spec. */
3865 CU_ASSERT(0 == nghttp2_session_on_settings_received(session, &frame, 0));
3866
3867 nghttp2_frame_settings_free(&frame.settings, mem);
3868
3869 item = nghttp2_session_get_next_ob_item(session);
3870
3871 CU_ASSERT(NULL != item);
3872 CU_ASSERT(NGHTTP2_SETTINGS == item->frame.hd.type);
3873
3874 item = nghttp2_outbound_queue_top(&session->ob_reg);
3875
3876 CU_ASSERT(NULL != item);
3877 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
3878 CU_ASSERT(NGHTTP2_STREAM_CLOSING == stream1->state);
3879
3880 nghttp2_session_del(session);
3881
3882 /* It is invalid that peer disables ENABLE_CONNECT_PROTOCOL once it
3883 has been enabled. */
3884 nghttp2_session_client_new(&session, &callbacks, NULL);
3885
3886 session->remote_settings.enable_connect_protocol = 1;
3887
3888 iv[0].settings_id = NGHTTP2_SETTINGS_ENABLE_CONNECT_PROTOCOL;
3889 iv[0].value = 0;
3890
3891 nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE, dup_iv(iv, 1),
3892 1);
3893
3894 CU_ASSERT(0 == nghttp2_session_on_settings_received(session, &frame, 0));
3895
3896 nghttp2_frame_settings_free(&frame.settings, mem);
3897
3898 item = nghttp2_session_get_next_ob_item(session);
3899
3900 CU_ASSERT(NULL != item);
3901 CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
3902
3903 nghttp2_session_del(session);
3904
3905 /* Should send WINDOW_UPDATE with no_auto_window_update option on if
3906 the initial window size is decreased and becomes smaller than or
3907 equal to the amount of data that has already received. */
3908 nghttp2_option_new(&option);
3909 nghttp2_option_set_no_auto_window_update(option, 1);
3910
3911 nghttp2_session_server_new2(&session, &callbacks, NULL, option);
3912
3913 iv[0].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
3914 iv[0].value = 1024;
3915
3916 rv = nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, iv, 1);
3917
3918 CU_ASSERT(0 == rv);
3919
3920 rv = nghttp2_session_send(session);
3921
3922 CU_ASSERT(0 == rv);
3923
3924 stream = open_recv_stream(session, 1);
3925
3926 memset(data, 0, sizeof(data));
3927 hd.length = 1024;
3928 hd.type = NGHTTP2_DATA;
3929 hd.flags = NGHTTP2_FLAG_NONE;
3930 hd.stream_id = 1;
3931 nghttp2_frame_pack_frame_hd(data, &hd);
3932
3933 nread =
3934 nghttp2_session_mem_recv(session, data, NGHTTP2_FRAME_HDLEN + hd.length);
3935
3936 CU_ASSERT((ssize_t)(NGHTTP2_FRAME_HDLEN + hd.length) == nread);
3937
3938 rv = nghttp2_session_consume(session, 1, hd.length);
3939
3940 CU_ASSERT(0 == rv);
3941 CU_ASSERT((int32_t)hd.length == stream->recv_window_size);
3942 CU_ASSERT((int32_t)hd.length == stream->consumed_size);
3943
3944 nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_ACK, NULL, 0);
3945
3946 rv = nghttp2_session_on_settings_received(session, &frame, 0);
3947
3948 CU_ASSERT(0 == rv);
3949 CU_ASSERT(1024 == stream->local_window_size);
3950 CU_ASSERT(0 == stream->recv_window_size);
3951 CU_ASSERT(0 == stream->consumed_size);
3952
3953 item = nghttp2_session_get_next_ob_item(session);
3954
3955 CU_ASSERT(NULL != item);
3956 CU_ASSERT(NGHTTP2_WINDOW_UPDATE == item->frame.hd.type);
3957 CU_ASSERT((int32_t)hd.length ==
3958 item->frame.window_update.window_size_increment);
3959
3960 nghttp2_session_del(session);
3961 nghttp2_option_del(option);
3962
3963 /* It is invalid to change SETTINGS_NO_RFC7540_PRIORITIES in the
3964 following SETTINGS. */
3965 nghttp2_session_client_new(&session, &callbacks, NULL);
3966
3967 session->remote_settings.no_rfc7540_priorities = 1;
3968
3969 iv[0].settings_id = NGHTTP2_SETTINGS_NO_RFC7540_PRIORITIES;
3970 iv[0].value = 0;
3971
3972 nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE, dup_iv(iv, 1),
3973 1);
3974
3975 CU_ASSERT(0 == nghttp2_session_on_settings_received(session, &frame, 0));
3976
3977 nghttp2_frame_settings_free(&frame.settings, mem);
3978
3979 item = nghttp2_session_get_next_ob_item(session);
3980
3981 CU_ASSERT(NULL != item);
3982 CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
3983
3984 nghttp2_session_del(session);
3985 }
3986
test_nghttp2_session_on_push_promise_received(void)3987 void test_nghttp2_session_on_push_promise_received(void) {
3988 nghttp2_session *session;
3989 nghttp2_session_callbacks callbacks;
3990 my_user_data user_data;
3991 nghttp2_frame frame;
3992 nghttp2_stream *stream, *promised_stream;
3993 nghttp2_outbound_item *item;
3994 nghttp2_nv malformed_nva[] = {MAKE_NV(":path", "\x01")};
3995 nghttp2_nv *nva;
3996 size_t nvlen;
3997 nghttp2_mem *mem;
3998 nghttp2_settings_entry iv = {NGHTTP2_SETTINGS_ENABLE_PUSH, 0};
3999
4000 mem = nghttp2_mem_default();
4001 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4002 callbacks.send_callback = null_send_callback;
4003 callbacks.on_begin_headers_callback = on_begin_headers_callback;
4004 callbacks.on_invalid_frame_recv_callback = on_invalid_frame_recv_callback;
4005
4006 nghttp2_session_client_new(&session, &callbacks, &user_data);
4007
4008 stream = open_sent_stream(session, 1);
4009
4010 nghttp2_frame_push_promise_init(&frame.push_promise, NGHTTP2_FLAG_END_HEADERS,
4011 1, 2, NULL, 0);
4012
4013 user_data.begin_headers_cb_called = 0;
4014 user_data.invalid_frame_recv_cb_called = 0;
4015
4016 CU_ASSERT(0 == nghttp2_session_on_push_promise_received(session, &frame));
4017
4018 CU_ASSERT(1 == user_data.begin_headers_cb_called);
4019 CU_ASSERT(1 == session->num_incoming_reserved_streams);
4020 promised_stream = nghttp2_session_get_stream(session, 2);
4021 CU_ASSERT(NGHTTP2_STREAM_RESERVED == promised_stream->state);
4022 CU_ASSERT(2 == session->last_recv_stream_id);
4023
4024 /* Attempt to PUSH_PROMISE against half close (remote) */
4025 nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_RD);
4026 frame.push_promise.promised_stream_id = 4;
4027
4028 user_data.begin_headers_cb_called = 0;
4029 user_data.invalid_frame_recv_cb_called = 0;
4030 CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
4031 nghttp2_session_on_push_promise_received(session, &frame));
4032
4033 CU_ASSERT(0 == user_data.begin_headers_cb_called);
4034 CU_ASSERT(1 == user_data.invalid_frame_recv_cb_called);
4035 CU_ASSERT(1 == session->num_incoming_reserved_streams);
4036 CU_ASSERT(NULL == nghttp2_session_get_stream(session, 4));
4037 item = nghttp2_session_get_next_ob_item(session);
4038 CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
4039 CU_ASSERT(NGHTTP2_STREAM_CLOSED == item->frame.goaway.error_code);
4040 CU_ASSERT(0 == nghttp2_session_send(session));
4041 CU_ASSERT(4 == session->last_recv_stream_id);
4042
4043 nghttp2_session_del(session);
4044
4045 nghttp2_session_client_new(&session, &callbacks, &user_data);
4046
4047 stream = open_sent_stream(session, 1);
4048
4049 /* Attempt to PUSH_PROMISE against stream in closing state */
4050 stream->state = NGHTTP2_STREAM_CLOSING;
4051 frame.push_promise.promised_stream_id = 6;
4052
4053 user_data.begin_headers_cb_called = 0;
4054 user_data.invalid_frame_recv_cb_called = 0;
4055 CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
4056 nghttp2_session_on_push_promise_received(session, &frame));
4057
4058 CU_ASSERT(0 == user_data.begin_headers_cb_called);
4059 CU_ASSERT(0 == session->num_incoming_reserved_streams);
4060 CU_ASSERT(NULL == nghttp2_session_get_stream(session, 6));
4061 item = nghttp2_session_get_next_ob_item(session);
4062 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
4063 CU_ASSERT(6 == item->frame.hd.stream_id);
4064 CU_ASSERT(NGHTTP2_CANCEL == item->frame.rst_stream.error_code);
4065 CU_ASSERT(0 == nghttp2_session_send(session));
4066
4067 /* Attempt to PUSH_PROMISE against idle stream */
4068 frame.hd.stream_id = 3;
4069 frame.push_promise.promised_stream_id = 8;
4070
4071 user_data.begin_headers_cb_called = 0;
4072 user_data.invalid_frame_recv_cb_called = 0;
4073 CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
4074 nghttp2_session_on_push_promise_received(session, &frame));
4075
4076 CU_ASSERT(0 == user_data.begin_headers_cb_called);
4077 CU_ASSERT(0 == session->num_incoming_reserved_streams);
4078 CU_ASSERT(NULL == nghttp2_session_get_stream(session, 8));
4079 item = nghttp2_session_get_next_ob_item(session);
4080 CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
4081 CU_ASSERT(0 == item->frame.hd.stream_id);
4082 CU_ASSERT(NGHTTP2_PROTOCOL_ERROR == item->frame.goaway.error_code);
4083 CU_ASSERT(0 == nghttp2_session_send(session));
4084
4085 nghttp2_session_del(session);
4086
4087 nghttp2_session_client_new(&session, &callbacks, &user_data);
4088
4089 stream = open_sent_stream(session, 1);
4090
4091 /* Same ID twice */
4092 frame.hd.stream_id = 1;
4093 frame.push_promise.promised_stream_id = 2;
4094
4095 user_data.begin_headers_cb_called = 0;
4096 user_data.invalid_frame_recv_cb_called = 0;
4097 CU_ASSERT(0 == nghttp2_session_on_push_promise_received(session, &frame));
4098
4099 CU_ASSERT(1 == user_data.begin_headers_cb_called);
4100 CU_ASSERT(1 == session->num_incoming_reserved_streams);
4101 CU_ASSERT(NULL != nghttp2_session_get_stream(session, 2));
4102
4103 user_data.begin_headers_cb_called = 0;
4104 user_data.invalid_frame_recv_cb_called = 0;
4105 CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
4106 nghttp2_session_on_push_promise_received(session, &frame));
4107
4108 CU_ASSERT(0 == user_data.begin_headers_cb_called);
4109 CU_ASSERT(1 == session->num_incoming_reserved_streams);
4110 CU_ASSERT(NULL == nghttp2_session_get_stream(session, 8));
4111 item = nghttp2_session_get_next_ob_item(session);
4112 CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
4113 CU_ASSERT(NGHTTP2_PROTOCOL_ERROR == item->frame.goaway.error_code);
4114 CU_ASSERT(0 == nghttp2_session_send(session));
4115
4116 /* After GOAWAY, PUSH_PROMISE will be discarded */
4117 frame.push_promise.promised_stream_id = 10;
4118
4119 user_data.begin_headers_cb_called = 0;
4120 user_data.invalid_frame_recv_cb_called = 0;
4121 CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
4122 nghttp2_session_on_push_promise_received(session, &frame));
4123
4124 CU_ASSERT(0 == user_data.begin_headers_cb_called);
4125 CU_ASSERT(1 == session->num_incoming_reserved_streams);
4126 CU_ASSERT(NULL == nghttp2_session_get_stream(session, 10));
4127 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
4128
4129 nghttp2_frame_push_promise_free(&frame.push_promise, mem);
4130 nghttp2_session_del(session);
4131
4132 nghttp2_session_client_new(&session, &callbacks, &user_data);
4133
4134 open_recv_stream2(session, 2, NGHTTP2_STREAM_RESERVED);
4135
4136 /* Attempt to PUSH_PROMISE against reserved (remote) stream */
4137 nghttp2_frame_push_promise_init(&frame.push_promise, NGHTTP2_FLAG_END_HEADERS,
4138 2, 4, NULL, 0);
4139
4140 user_data.begin_headers_cb_called = 0;
4141 user_data.invalid_frame_recv_cb_called = 0;
4142 CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
4143 nghttp2_session_on_push_promise_received(session, &frame));
4144
4145 CU_ASSERT(0 == user_data.begin_headers_cb_called);
4146 CU_ASSERT(1 == user_data.invalid_frame_recv_cb_called);
4147 CU_ASSERT(1 == session->num_incoming_reserved_streams);
4148
4149 nghttp2_frame_push_promise_free(&frame.push_promise, mem);
4150 nghttp2_session_del(session);
4151
4152 /* Disable PUSH */
4153 nghttp2_session_client_new(&session, &callbacks, &user_data);
4154
4155 open_sent_stream(session, 1);
4156
4157 session->local_settings.enable_push = 0;
4158
4159 nghttp2_frame_push_promise_init(&frame.push_promise, NGHTTP2_FLAG_END_HEADERS,
4160 1, 2, NULL, 0);
4161
4162 user_data.begin_headers_cb_called = 0;
4163 user_data.invalid_frame_recv_cb_called = 0;
4164 CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
4165 nghttp2_session_on_push_promise_received(session, &frame));
4166
4167 CU_ASSERT(0 == user_data.begin_headers_cb_called);
4168 CU_ASSERT(1 == user_data.invalid_frame_recv_cb_called);
4169 CU_ASSERT(0 == session->num_incoming_reserved_streams);
4170
4171 nghttp2_frame_push_promise_free(&frame.push_promise, mem);
4172 nghttp2_session_del(session);
4173
4174 /* Check malformed headers. We accept malformed headers */
4175 nghttp2_session_client_new(&session, &callbacks, &user_data);
4176
4177 open_sent_stream(session, 1);
4178
4179 nvlen = ARRLEN(malformed_nva);
4180 nghttp2_nv_array_copy(&nva, malformed_nva, nvlen, mem);
4181 nghttp2_frame_push_promise_init(&frame.push_promise, NGHTTP2_FLAG_END_HEADERS,
4182 1, 2, nva, nvlen);
4183 user_data.begin_headers_cb_called = 0;
4184 user_data.invalid_frame_recv_cb_called = 0;
4185 CU_ASSERT(0 == nghttp2_session_on_push_promise_received(session, &frame));
4186
4187 CU_ASSERT(1 == user_data.begin_headers_cb_called);
4188 CU_ASSERT(0 == user_data.invalid_frame_recv_cb_called);
4189
4190 nghttp2_frame_push_promise_free(&frame.push_promise, mem);
4191 nghttp2_session_del(session);
4192
4193 /* If local_settings.enable_push = 0 is pending, but not acked from
4194 peer, incoming PUSH_PROMISE is rejected */
4195 nghttp2_session_client_new(&session, &callbacks, &user_data);
4196
4197 open_sent_stream(session, 1);
4198
4199 /* Submit settings with ENABLE_PUSH = 0 (thus disabling push) */
4200 nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, &iv, 1);
4201
4202 nghttp2_frame_push_promise_init(&frame.push_promise, NGHTTP2_FLAG_END_HEADERS,
4203 1, 2, NULL, 0);
4204
4205 CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
4206 nghttp2_session_on_push_promise_received(session, &frame));
4207
4208 CU_ASSERT(0 == session->num_incoming_reserved_streams);
4209
4210 nghttp2_frame_push_promise_free(&frame.push_promise, mem);
4211 nghttp2_session_del(session);
4212
4213 /* Check max_incoming_reserved_streams */
4214 nghttp2_session_client_new(&session, &callbacks, &user_data);
4215 session->max_incoming_reserved_streams = 1;
4216
4217 open_sent_stream(session, 1);
4218 open_recv_stream2(session, 2, NGHTTP2_STREAM_RESERVED);
4219
4220 CU_ASSERT(1 == session->num_incoming_reserved_streams);
4221
4222 nghttp2_frame_push_promise_init(&frame.push_promise, NGHTTP2_FLAG_END_HEADERS,
4223 1, 4, NULL, 0);
4224
4225 CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
4226 nghttp2_session_on_push_promise_received(session, &frame));
4227
4228 CU_ASSERT(1 == session->num_incoming_reserved_streams);
4229
4230 item = nghttp2_session_get_next_ob_item(session);
4231
4232 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
4233 CU_ASSERT(NGHTTP2_CANCEL == item->frame.rst_stream.error_code);
4234
4235 nghttp2_frame_push_promise_free(&frame.push_promise, mem);
4236 nghttp2_session_del(session);
4237 }
4238
test_nghttp2_session_on_ping_received(void)4239 void test_nghttp2_session_on_ping_received(void) {
4240 nghttp2_session *session;
4241 nghttp2_session_callbacks callbacks;
4242 my_user_data user_data;
4243 nghttp2_frame frame;
4244 nghttp2_outbound_item *top;
4245 const uint8_t opaque_data[] = "01234567";
4246 nghttp2_option *option;
4247
4248 user_data.frame_recv_cb_called = 0;
4249 user_data.invalid_frame_recv_cb_called = 0;
4250
4251 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4252 callbacks.on_frame_recv_callback = on_frame_recv_callback;
4253 callbacks.on_invalid_frame_recv_callback = on_invalid_frame_recv_callback;
4254
4255 nghttp2_session_client_new(&session, &callbacks, &user_data);
4256 nghttp2_frame_ping_init(&frame.ping, NGHTTP2_FLAG_ACK, opaque_data);
4257
4258 CU_ASSERT(0 == nghttp2_session_on_ping_received(session, &frame));
4259 CU_ASSERT(1 == user_data.frame_recv_cb_called);
4260
4261 /* Since this ping frame has ACK flag set, no further action is
4262 performed. */
4263 CU_ASSERT(NULL == nghttp2_outbound_queue_top(&session->ob_urgent));
4264
4265 /* Clear the flag, and receive it again */
4266 frame.hd.flags = NGHTTP2_FLAG_NONE;
4267
4268 CU_ASSERT(0 == nghttp2_session_on_ping_received(session, &frame));
4269 CU_ASSERT(2 == user_data.frame_recv_cb_called);
4270 top = nghttp2_outbound_queue_top(&session->ob_urgent);
4271 CU_ASSERT(NGHTTP2_PING == top->frame.hd.type);
4272 CU_ASSERT(NGHTTP2_FLAG_ACK == top->frame.hd.flags);
4273 CU_ASSERT(memcmp(opaque_data, top->frame.ping.opaque_data, 8) == 0);
4274
4275 nghttp2_frame_ping_free(&frame.ping);
4276 nghttp2_session_del(session);
4277
4278 /* Use nghttp2_option_set_no_auto_ping_ack() */
4279 nghttp2_option_new(&option);
4280 nghttp2_option_set_no_auto_ping_ack(option, 1);
4281
4282 nghttp2_session_server_new2(&session, &callbacks, &user_data, option);
4283 nghttp2_frame_ping_init(&frame.ping, NGHTTP2_FLAG_NONE, NULL);
4284
4285 user_data.frame_recv_cb_called = 0;
4286
4287 CU_ASSERT(0 == nghttp2_session_on_ping_received(session, &frame));
4288 CU_ASSERT(1 == user_data.frame_recv_cb_called);
4289 CU_ASSERT(NULL == nghttp2_outbound_queue_top(&session->ob_urgent));
4290
4291 nghttp2_frame_ping_free(&frame.ping);
4292 nghttp2_session_del(session);
4293 nghttp2_option_del(option);
4294 }
4295
test_nghttp2_session_on_goaway_received(void)4296 void test_nghttp2_session_on_goaway_received(void) {
4297 nghttp2_session *session;
4298 nghttp2_session_callbacks callbacks;
4299 my_user_data user_data;
4300 nghttp2_frame frame;
4301 int i;
4302 nghttp2_mem *mem;
4303 const uint8_t *data;
4304 ssize_t datalen;
4305
4306 mem = nghttp2_mem_default();
4307 user_data.frame_recv_cb_called = 0;
4308 user_data.invalid_frame_recv_cb_called = 0;
4309
4310 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4311 callbacks.on_frame_recv_callback = on_frame_recv_callback;
4312 callbacks.on_invalid_frame_recv_callback = on_invalid_frame_recv_callback;
4313 callbacks.on_stream_close_callback = on_stream_close_callback;
4314
4315 nghttp2_session_client_new(&session, &callbacks, &user_data);
4316
4317 for (i = 1; i <= 7; ++i) {
4318 if (nghttp2_session_is_my_stream_id(session, i)) {
4319 open_sent_stream(session, i);
4320 } else {
4321 open_recv_stream(session, i);
4322 }
4323 }
4324
4325 nghttp2_frame_goaway_init(&frame.goaway, 3, NGHTTP2_PROTOCOL_ERROR, NULL, 0);
4326
4327 user_data.stream_close_cb_called = 0;
4328
4329 CU_ASSERT(0 == nghttp2_session_on_goaway_received(session, &frame));
4330
4331 CU_ASSERT(1 == user_data.frame_recv_cb_called);
4332 CU_ASSERT(3 == session->remote_last_stream_id);
4333 /* on_stream_close should be callsed for 2 times (stream 5 and 7) */
4334 CU_ASSERT(2 == user_data.stream_close_cb_called);
4335
4336 CU_ASSERT(NULL != nghttp2_session_get_stream(session, 1));
4337 CU_ASSERT(NULL != nghttp2_session_get_stream(session, 2));
4338 CU_ASSERT(NULL != nghttp2_session_get_stream(session, 3));
4339 CU_ASSERT(NULL != nghttp2_session_get_stream(session, 4));
4340 CU_ASSERT(NULL == nghttp2_session_get_stream(session, 5));
4341 CU_ASSERT(NULL != nghttp2_session_get_stream(session, 6));
4342 CU_ASSERT(NULL == nghttp2_session_get_stream(session, 7));
4343
4344 nghttp2_frame_goaway_free(&frame.goaway, mem);
4345 nghttp2_session_del(session);
4346
4347 /* Make sure that no memory leak when stream_close callback fails
4348 with a fatal error */
4349 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4350 callbacks.on_stream_close_callback = fatal_error_on_stream_close_callback;
4351
4352 memset(&user_data, 0, sizeof(user_data));
4353
4354 nghttp2_session_client_new(&session, &callbacks, &user_data);
4355
4356 nghttp2_frame_goaway_init(&frame.goaway, 0, NGHTTP2_NO_ERROR, NULL, 0);
4357
4358 CU_ASSERT(0 == nghttp2_session_on_goaway_received(session, &frame));
4359
4360 nghttp2_submit_request(session, NULL, reqnv, ARRLEN(reqnv), NULL, NULL);
4361
4362 datalen = nghttp2_session_mem_send(session, &data);
4363
4364 CU_ASSERT(NGHTTP2_ERR_CALLBACK_FAILURE == datalen);
4365 CU_ASSERT(1 == user_data.stream_close_cb_called);
4366
4367 nghttp2_frame_goaway_free(&frame.goaway, mem);
4368 nghttp2_session_del(session);
4369 }
4370
test_nghttp2_session_on_window_update_received(void)4371 void test_nghttp2_session_on_window_update_received(void) {
4372 nghttp2_session *session;
4373 nghttp2_session_callbacks callbacks;
4374 my_user_data user_data;
4375 nghttp2_frame frame;
4376 nghttp2_stream *stream;
4377 nghttp2_outbound_item *data_item;
4378 nghttp2_mem *mem;
4379
4380 mem = nghttp2_mem_default();
4381
4382 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4383 callbacks.on_frame_recv_callback = on_frame_recv_callback;
4384 callbacks.on_invalid_frame_recv_callback = on_invalid_frame_recv_callback;
4385 user_data.frame_recv_cb_called = 0;
4386 user_data.invalid_frame_recv_cb_called = 0;
4387
4388 nghttp2_session_client_new(&session, &callbacks, &user_data);
4389
4390 stream = open_sent_stream(session, 1);
4391
4392 data_item = create_data_ob_item(mem);
4393
4394 CU_ASSERT(0 == nghttp2_stream_attach_item(stream, data_item));
4395
4396 nghttp2_frame_window_update_init(&frame.window_update, NGHTTP2_FLAG_NONE, 1,
4397 16 * 1024);
4398
4399 CU_ASSERT(0 == nghttp2_session_on_window_update_received(session, &frame));
4400 CU_ASSERT(1 == user_data.frame_recv_cb_called);
4401 CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE + 16 * 1024 ==
4402 stream->remote_window_size);
4403
4404 nghttp2_stream_defer_item(stream, NGHTTP2_STREAM_FLAG_DEFERRED_FLOW_CONTROL);
4405
4406 CU_ASSERT(0 == nghttp2_session_on_window_update_received(session, &frame));
4407 CU_ASSERT(2 == user_data.frame_recv_cb_called);
4408 CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE + 16 * 1024 * 2 ==
4409 stream->remote_window_size);
4410 CU_ASSERT(0 == (stream->flags & NGHTTP2_STREAM_FLAG_DEFERRED_ALL));
4411
4412 nghttp2_frame_window_update_free(&frame.window_update);
4413
4414 /* Receiving WINDOW_UPDATE on reserved (remote) stream is a
4415 connection error */
4416 open_recv_stream2(session, 2, NGHTTP2_STREAM_RESERVED);
4417
4418 nghttp2_frame_window_update_init(&frame.window_update, NGHTTP2_FLAG_NONE, 2,
4419 4096);
4420
4421 CU_ASSERT(!(session->goaway_flags & NGHTTP2_GOAWAY_TERM_ON_SEND));
4422 CU_ASSERT(0 == nghttp2_session_on_window_update_received(session, &frame));
4423 CU_ASSERT(session->goaway_flags & NGHTTP2_GOAWAY_TERM_ON_SEND);
4424
4425 nghttp2_frame_window_update_free(&frame.window_update);
4426
4427 nghttp2_session_del(session);
4428
4429 /* Receiving WINDOW_UPDATE on reserved (local) stream is allowed */
4430 nghttp2_session_server_new(&session, &callbacks, &user_data);
4431
4432 stream = open_sent_stream2(session, 2, NGHTTP2_STREAM_RESERVED);
4433
4434 nghttp2_frame_window_update_init(&frame.window_update, NGHTTP2_FLAG_NONE, 2,
4435 4096);
4436
4437 CU_ASSERT(0 == nghttp2_session_on_window_update_received(session, &frame));
4438 CU_ASSERT(!(session->goaway_flags & NGHTTP2_GOAWAY_TERM_ON_SEND));
4439
4440 CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE + 4096 == stream->remote_window_size);
4441
4442 nghttp2_frame_window_update_free(&frame.window_update);
4443
4444 nghttp2_session_del(session);
4445 }
4446
test_nghttp2_session_on_data_received(void)4447 void test_nghttp2_session_on_data_received(void) {
4448 nghttp2_session *session;
4449 nghttp2_session_callbacks callbacks;
4450 my_user_data user_data;
4451 nghttp2_outbound_item *top;
4452 nghttp2_stream *stream;
4453 nghttp2_frame frame;
4454
4455 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4456
4457 nghttp2_session_client_new(&session, &callbacks, &user_data);
4458 stream = open_recv_stream(session, 2);
4459
4460 nghttp2_frame_hd_init(&frame.hd, 4096, NGHTTP2_DATA, NGHTTP2_FLAG_NONE, 2);
4461
4462 CU_ASSERT(0 == nghttp2_session_on_data_received(session, &frame));
4463 CU_ASSERT(0 == stream->shut_flags);
4464
4465 frame.hd.flags = NGHTTP2_FLAG_END_STREAM;
4466
4467 CU_ASSERT(0 == nghttp2_session_on_data_received(session, &frame));
4468 CU_ASSERT(NGHTTP2_SHUT_RD == stream->shut_flags);
4469
4470 /* If NGHTTP2_STREAM_CLOSING state, DATA frame is discarded. */
4471 open_sent_stream2(session, 1, NGHTTP2_STREAM_CLOSING);
4472
4473 frame.hd.flags = NGHTTP2_FLAG_NONE;
4474 frame.hd.stream_id = 1;
4475
4476 CU_ASSERT(0 == nghttp2_session_on_data_received(session, &frame));
4477 CU_ASSERT(NULL == nghttp2_outbound_queue_top(&session->ob_reg));
4478
4479 /* Check INVALID_STREAM case: DATA frame with stream ID which does
4480 not exist. */
4481
4482 frame.hd.stream_id = 3;
4483
4484 CU_ASSERT(0 == nghttp2_session_on_data_received(session, &frame));
4485 top = nghttp2_outbound_queue_top(&session->ob_reg);
4486 /* DATA against nonexistent stream is just ignored for now. */
4487 CU_ASSERT(top == NULL);
4488
4489 nghttp2_session_del(session);
4490 }
4491
test_nghttp2_session_on_data_received_fail_fast(void)4492 void test_nghttp2_session_on_data_received_fail_fast(void) {
4493 nghttp2_session *session;
4494 nghttp2_session_callbacks callbacks;
4495 uint8_t buf[9];
4496 nghttp2_stream *stream;
4497 nghttp2_frame_hd hd;
4498 nghttp2_outbound_item *item;
4499
4500 memset(&callbacks, 0, sizeof(callbacks));
4501
4502 nghttp2_frame_hd_init(&hd, 0, NGHTTP2_DATA, NGHTTP2_FLAG_NONE, 1);
4503 nghttp2_frame_pack_frame_hd(buf, &hd);
4504
4505 nghttp2_session_server_new(&session, &callbacks, NULL);
4506
4507 /* DATA to closed (remote) */
4508 stream = open_recv_stream(session, 1);
4509 nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_RD);
4510
4511 CU_ASSERT((ssize_t)sizeof(buf) ==
4512 nghttp2_session_mem_recv(session, buf, sizeof(buf)));
4513
4514 item = nghttp2_session_get_next_ob_item(session);
4515
4516 CU_ASSERT(NULL != item);
4517 CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
4518
4519 nghttp2_session_del(session);
4520
4521 nghttp2_session_server_new(&session, &callbacks, NULL);
4522
4523 /* DATA to closed stream with explicit closed (remote) */
4524 stream = open_recv_stream(session, 1);
4525 nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_RD);
4526 nghttp2_session_close_stream(session, 1, NGHTTP2_NO_ERROR);
4527
4528 CU_ASSERT((ssize_t)sizeof(buf) ==
4529 nghttp2_session_mem_recv(session, buf, sizeof(buf)));
4530
4531 item = nghttp2_session_get_next_ob_item(session);
4532
4533 CU_ASSERT(NULL != item);
4534 CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
4535
4536 nghttp2_session_del(session);
4537 }
4538
test_nghttp2_session_on_altsvc_received(void)4539 void test_nghttp2_session_on_altsvc_received(void) {
4540 nghttp2_session *session;
4541 nghttp2_session_callbacks callbacks;
4542 my_user_data ud;
4543 nghttp2_frame frame;
4544 nghttp2_option *option;
4545 uint8_t origin[] = "nghttp2.org";
4546 uint8_t field_value[] = "h2=\":443\"";
4547 int rv;
4548
4549 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4550 callbacks.on_frame_recv_callback = on_frame_recv_callback;
4551
4552 nghttp2_option_new(&option);
4553 nghttp2_option_set_builtin_recv_extension_type(option, NGHTTP2_ALTSVC);
4554
4555 nghttp2_session_client_new2(&session, &callbacks, &ud, option);
4556
4557 frame.ext.payload = &session->iframe.ext_frame_payload;
4558
4559 /* We just pass the strings without making a copy. This is OK,
4560 since we never call nghttp2_frame_altsvc_free(). */
4561 nghttp2_frame_altsvc_init(&frame.ext, 0, origin, sizeof(origin) - 1,
4562 field_value, sizeof(field_value) - 1);
4563
4564 ud.frame_recv_cb_called = 0;
4565 rv = nghttp2_session_on_altsvc_received(session, &frame);
4566
4567 CU_ASSERT(0 == rv);
4568 CU_ASSERT(1 == ud.frame_recv_cb_called);
4569
4570 nghttp2_session_del(session);
4571
4572 /* Receiving empty origin with stream ID == 0 */
4573 nghttp2_session_client_new2(&session, &callbacks, &ud, option);
4574
4575 frame.ext.payload = &session->iframe.ext_frame_payload;
4576
4577 nghttp2_frame_altsvc_init(&frame.ext, 0, origin, 0, field_value,
4578 sizeof(field_value) - 1);
4579
4580 ud.frame_recv_cb_called = 0;
4581 rv = nghttp2_session_on_altsvc_received(session, &frame);
4582
4583 CU_ASSERT(0 == rv);
4584 CU_ASSERT(0 == ud.frame_recv_cb_called);
4585
4586 nghttp2_session_del(session);
4587
4588 /* Receiving non-empty origin with stream ID != 0 */
4589 nghttp2_session_client_new2(&session, &callbacks, &ud, option);
4590
4591 frame.ext.payload = &session->iframe.ext_frame_payload;
4592
4593 open_sent_stream(session, 1);
4594
4595 nghttp2_frame_altsvc_init(&frame.ext, 1, origin, sizeof(origin) - 1,
4596 field_value, sizeof(field_value) - 1);
4597
4598 ud.frame_recv_cb_called = 0;
4599 rv = nghttp2_session_on_altsvc_received(session, &frame);
4600
4601 CU_ASSERT(0 == rv);
4602 CU_ASSERT(0 == ud.frame_recv_cb_called);
4603
4604 nghttp2_session_del(session);
4605
4606 /* Receiving empty origin with stream ID != 0; this is OK */
4607 nghttp2_session_client_new2(&session, &callbacks, &ud, option);
4608
4609 frame.ext.payload = &session->iframe.ext_frame_payload;
4610
4611 open_sent_stream(session, 1);
4612
4613 nghttp2_frame_altsvc_init(&frame.ext, 1, origin, 0, field_value,
4614 sizeof(field_value) - 1);
4615
4616 ud.frame_recv_cb_called = 0;
4617 rv = nghttp2_session_on_altsvc_received(session, &frame);
4618
4619 CU_ASSERT(0 == rv);
4620 CU_ASSERT(1 == ud.frame_recv_cb_called);
4621
4622 nghttp2_session_del(session);
4623
4624 /* Stream does not exist; ALTSVC will be ignored. */
4625 nghttp2_session_client_new2(&session, &callbacks, &ud, option);
4626
4627 frame.ext.payload = &session->iframe.ext_frame_payload;
4628
4629 nghttp2_frame_altsvc_init(&frame.ext, 1, origin, 0, field_value,
4630 sizeof(field_value) - 1);
4631
4632 ud.frame_recv_cb_called = 0;
4633 rv = nghttp2_session_on_altsvc_received(session, &frame);
4634
4635 CU_ASSERT(0 == rv);
4636 CU_ASSERT(0 == ud.frame_recv_cb_called);
4637
4638 nghttp2_session_del(session);
4639
4640 nghttp2_option_del(option);
4641 }
4642
test_nghttp2_session_send_headers_start_stream(void)4643 void test_nghttp2_session_send_headers_start_stream(void) {
4644 nghttp2_session *session;
4645 nghttp2_session_callbacks callbacks;
4646 nghttp2_outbound_item *item;
4647 nghttp2_frame *frame;
4648 nghttp2_stream *stream;
4649 nghttp2_mem *mem;
4650
4651 mem = nghttp2_mem_default();
4652
4653 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4654 callbacks.send_callback = null_send_callback;
4655
4656 nghttp2_session_client_new(&session, &callbacks, NULL);
4657
4658 item = mem->malloc(sizeof(nghttp2_outbound_item), NULL);
4659
4660 nghttp2_outbound_item_init(item);
4661
4662 frame = &item->frame;
4663
4664 nghttp2_frame_headers_init(&frame->headers, NGHTTP2_FLAG_END_HEADERS,
4665 (int32_t)session->next_stream_id,
4666 NGHTTP2_HCAT_REQUEST, NULL, NULL, 0);
4667 session->next_stream_id += 2;
4668
4669 nghttp2_session_add_item(session, item);
4670 CU_ASSERT(0 == nghttp2_session_send(session));
4671 stream = nghttp2_session_get_stream(session, 1);
4672 CU_ASSERT(NGHTTP2_STREAM_OPENING == stream->state);
4673
4674 nghttp2_session_del(session);
4675 }
4676
test_nghttp2_session_send_headers_reply(void)4677 void test_nghttp2_session_send_headers_reply(void) {
4678 nghttp2_session *session;
4679 nghttp2_session_callbacks callbacks;
4680 nghttp2_outbound_item *item;
4681 nghttp2_frame *frame;
4682 nghttp2_stream *stream;
4683 nghttp2_mem *mem;
4684
4685 mem = nghttp2_mem_default();
4686
4687 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4688 callbacks.send_callback = null_send_callback;
4689
4690 CU_ASSERT(0 == nghttp2_session_server_new(&session, &callbacks, NULL));
4691 open_recv_stream2(session, 1, NGHTTP2_STREAM_OPENING);
4692
4693 item = mem->malloc(sizeof(nghttp2_outbound_item), NULL);
4694
4695 nghttp2_outbound_item_init(item);
4696
4697 frame = &item->frame;
4698
4699 nghttp2_frame_headers_init(&frame->headers, NGHTTP2_FLAG_END_HEADERS, 1,
4700 NGHTTP2_HCAT_HEADERS, NULL, NULL, 0);
4701 nghttp2_session_add_item(session, item);
4702 CU_ASSERT(0 == nghttp2_session_send(session));
4703 stream = nghttp2_session_get_stream(session, 1);
4704 CU_ASSERT(NGHTTP2_STREAM_OPENED == stream->state);
4705
4706 nghttp2_session_del(session);
4707 }
4708
test_nghttp2_session_send_headers_frame_size_error(void)4709 void test_nghttp2_session_send_headers_frame_size_error(void) {
4710 nghttp2_session *session;
4711 nghttp2_session_callbacks callbacks;
4712 nghttp2_outbound_item *item;
4713 nghttp2_frame *frame;
4714 nghttp2_nv *nva;
4715 size_t nvlen;
4716 size_t vallen = NGHTTP2_HD_MAX_NV;
4717 nghttp2_nv nv[28];
4718 size_t nnv = ARRLEN(nv);
4719 size_t i;
4720 my_user_data ud;
4721 nghttp2_mem *mem;
4722
4723 mem = nghttp2_mem_default();
4724
4725 for (i = 0; i < nnv; ++i) {
4726 nv[i].name = (uint8_t *)"header";
4727 nv[i].namelen = strlen((const char *)nv[i].name);
4728 nv[i].value = mem->malloc(vallen + 1, NULL);
4729 memset(nv[i].value, '0' + (int)i, vallen);
4730 nv[i].value[vallen] = '\0';
4731 nv[i].valuelen = vallen;
4732 nv[i].flags = NGHTTP2_NV_FLAG_NONE;
4733 }
4734
4735 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4736 callbacks.send_callback = null_send_callback;
4737 callbacks.on_frame_not_send_callback = on_frame_not_send_callback;
4738
4739 nghttp2_session_client_new(&session, &callbacks, &ud);
4740 nvlen = nnv;
4741 nghttp2_nv_array_copy(&nva, nv, nvlen, mem);
4742
4743 item = mem->malloc(sizeof(nghttp2_outbound_item), NULL);
4744
4745 nghttp2_outbound_item_init(item);
4746
4747 frame = &item->frame;
4748
4749 nghttp2_frame_headers_init(&frame->headers, NGHTTP2_FLAG_END_HEADERS,
4750 (int32_t)session->next_stream_id,
4751 NGHTTP2_HCAT_REQUEST, NULL, nva, nvlen);
4752
4753 session->next_stream_id += 2;
4754
4755 nghttp2_session_add_item(session, item);
4756
4757 ud.frame_not_send_cb_called = 0;
4758
4759 CU_ASSERT(0 == nghttp2_session_send(session));
4760
4761 CU_ASSERT(1 == ud.frame_not_send_cb_called);
4762 CU_ASSERT(NGHTTP2_HEADERS == ud.not_sent_frame_type);
4763 CU_ASSERT(NGHTTP2_ERR_FRAME_SIZE_ERROR == ud.not_sent_error);
4764
4765 for (i = 0; i < nnv; ++i) {
4766 mem->free(nv[i].value, NULL);
4767 }
4768 nghttp2_session_del(session);
4769 }
4770
test_nghttp2_session_send_headers_push_reply(void)4771 void test_nghttp2_session_send_headers_push_reply(void) {
4772 nghttp2_session *session;
4773 nghttp2_session_callbacks callbacks;
4774 nghttp2_outbound_item *item;
4775 nghttp2_frame *frame;
4776 nghttp2_stream *stream;
4777 nghttp2_mem *mem;
4778
4779 mem = nghttp2_mem_default();
4780
4781 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4782 callbacks.send_callback = null_send_callback;
4783
4784 CU_ASSERT(0 == nghttp2_session_server_new(&session, &callbacks, NULL));
4785 open_sent_stream2(session, 2, NGHTTP2_STREAM_RESERVED);
4786
4787 item = mem->malloc(sizeof(nghttp2_outbound_item), NULL);
4788
4789 nghttp2_outbound_item_init(item);
4790
4791 frame = &item->frame;
4792
4793 nghttp2_frame_headers_init(&frame->headers, NGHTTP2_FLAG_END_HEADERS, 2,
4794 NGHTTP2_HCAT_HEADERS, NULL, NULL, 0);
4795 nghttp2_session_add_item(session, item);
4796 CU_ASSERT(0 == session->num_outgoing_streams);
4797 CU_ASSERT(0 == nghttp2_session_send(session));
4798 CU_ASSERT(1 == session->num_outgoing_streams);
4799 stream = nghttp2_session_get_stream(session, 2);
4800 CU_ASSERT(NGHTTP2_STREAM_OPENED == stream->state);
4801 CU_ASSERT(0 == (stream->flags & NGHTTP2_STREAM_FLAG_PUSH));
4802 nghttp2_session_del(session);
4803 }
4804
test_nghttp2_session_send_rst_stream(void)4805 void test_nghttp2_session_send_rst_stream(void) {
4806 nghttp2_session *session;
4807 nghttp2_session_callbacks callbacks;
4808 my_user_data user_data;
4809 nghttp2_outbound_item *item;
4810 nghttp2_frame *frame;
4811 nghttp2_mem *mem;
4812
4813 mem = nghttp2_mem_default();
4814
4815 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4816 callbacks.send_callback = null_send_callback;
4817 nghttp2_session_client_new(&session, &callbacks, &user_data);
4818 open_sent_stream(session, 1);
4819
4820 item = mem->malloc(sizeof(nghttp2_outbound_item), NULL);
4821
4822 nghttp2_outbound_item_init(item);
4823
4824 frame = &item->frame;
4825
4826 nghttp2_frame_rst_stream_init(&frame->rst_stream, 1, NGHTTP2_PROTOCOL_ERROR);
4827 nghttp2_session_add_item(session, item);
4828 CU_ASSERT(0 == nghttp2_session_send(session));
4829
4830 CU_ASSERT(NULL == nghttp2_session_get_stream(session, 1));
4831
4832 nghttp2_session_del(session);
4833 }
4834
test_nghttp2_session_send_push_promise(void)4835 void test_nghttp2_session_send_push_promise(void) {
4836 nghttp2_session *session;
4837 nghttp2_session_callbacks callbacks;
4838 nghttp2_outbound_item *item;
4839 nghttp2_frame *frame;
4840 nghttp2_stream *stream;
4841 nghttp2_settings_entry iv;
4842 my_user_data ud;
4843 nghttp2_mem *mem;
4844
4845 mem = nghttp2_mem_default();
4846 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4847 callbacks.send_callback = null_send_callback;
4848 callbacks.on_frame_not_send_callback = on_frame_not_send_callback;
4849
4850 nghttp2_session_server_new(&session, &callbacks, &ud);
4851 open_recv_stream(session, 1);
4852
4853 item = mem->malloc(sizeof(nghttp2_outbound_item), NULL);
4854
4855 nghttp2_outbound_item_init(item);
4856
4857 frame = &item->frame;
4858
4859 nghttp2_frame_push_promise_init(&frame->push_promise,
4860 NGHTTP2_FLAG_END_HEADERS, 1,
4861 (int32_t)session->next_stream_id, NULL, 0);
4862
4863 session->next_stream_id += 2;
4864
4865 nghttp2_session_add_item(session, item);
4866
4867 CU_ASSERT(0 == nghttp2_session_send(session));
4868 stream = nghttp2_session_get_stream(session, 2);
4869 CU_ASSERT(NGHTTP2_STREAM_RESERVED == stream->state);
4870
4871 /* Received ENABLE_PUSH = 0 */
4872 iv.settings_id = NGHTTP2_SETTINGS_ENABLE_PUSH;
4873 iv.value = 0;
4874 frame = mem->malloc(sizeof(nghttp2_frame), NULL);
4875 nghttp2_frame_settings_init(&frame->settings, NGHTTP2_FLAG_NONE,
4876 dup_iv(&iv, 1), 1);
4877 nghttp2_session_on_settings_received(session, frame, 1);
4878 nghttp2_frame_settings_free(&frame->settings, mem);
4879 mem->free(frame, NULL);
4880
4881 item = mem->malloc(sizeof(nghttp2_outbound_item), NULL);
4882
4883 nghttp2_outbound_item_init(item);
4884
4885 frame = &item->frame;
4886
4887 nghttp2_frame_push_promise_init(&frame->push_promise,
4888 NGHTTP2_FLAG_END_HEADERS, 1, -1, NULL, 0);
4889 nghttp2_session_add_item(session, item);
4890
4891 ud.frame_not_send_cb_called = 0;
4892 CU_ASSERT(0 == nghttp2_session_send(session));
4893
4894 CU_ASSERT(1 == ud.frame_not_send_cb_called);
4895 CU_ASSERT(NGHTTP2_PUSH_PROMISE == ud.not_sent_frame_type);
4896 CU_ASSERT(NGHTTP2_ERR_PUSH_DISABLED == ud.not_sent_error);
4897
4898 nghttp2_session_del(session);
4899
4900 /* PUSH_PROMISE from client is error */
4901 nghttp2_session_client_new(&session, &callbacks, &ud);
4902 open_sent_stream(session, 1);
4903 item = mem->malloc(sizeof(nghttp2_outbound_item), NULL);
4904
4905 nghttp2_outbound_item_init(item);
4906
4907 frame = &item->frame;
4908
4909 nghttp2_frame_push_promise_init(&frame->push_promise,
4910 NGHTTP2_FLAG_END_HEADERS, 1, -1, NULL, 0);
4911 nghttp2_session_add_item(session, item);
4912
4913 CU_ASSERT(0 == nghttp2_session_send(session));
4914 CU_ASSERT(NULL == nghttp2_session_get_stream(session, 3));
4915
4916 nghttp2_session_del(session);
4917 }
4918
test_nghttp2_session_is_my_stream_id(void)4919 void test_nghttp2_session_is_my_stream_id(void) {
4920 nghttp2_session *session;
4921 nghttp2_session_callbacks callbacks;
4922 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4923 nghttp2_session_server_new(&session, &callbacks, NULL);
4924
4925 CU_ASSERT(0 == nghttp2_session_is_my_stream_id(session, 0));
4926 CU_ASSERT(0 == nghttp2_session_is_my_stream_id(session, 1));
4927 CU_ASSERT(1 == nghttp2_session_is_my_stream_id(session, 2));
4928
4929 nghttp2_session_del(session);
4930
4931 nghttp2_session_client_new(&session, &callbacks, NULL);
4932
4933 CU_ASSERT(0 == nghttp2_session_is_my_stream_id(session, 0));
4934 CU_ASSERT(1 == nghttp2_session_is_my_stream_id(session, 1));
4935 CU_ASSERT(0 == nghttp2_session_is_my_stream_id(session, 2));
4936
4937 nghttp2_session_del(session);
4938 }
4939
test_nghttp2_session_upgrade2(void)4940 void test_nghttp2_session_upgrade2(void) {
4941 nghttp2_session *session;
4942 nghttp2_session_callbacks callbacks;
4943 uint8_t settings_payload[128];
4944 size_t settings_payloadlen;
4945 nghttp2_settings_entry iv[16];
4946 nghttp2_stream *stream;
4947 nghttp2_outbound_item *item;
4948 ssize_t rv;
4949 nghttp2_bufs bufs;
4950 nghttp2_buf *buf;
4951 nghttp2_hd_deflater deflater;
4952 nghttp2_mem *mem;
4953
4954 mem = nghttp2_mem_default();
4955 frame_pack_bufs_init(&bufs);
4956
4957 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
4958 callbacks.send_callback = null_send_callback;
4959 iv[0].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS;
4960 iv[0].value = 1;
4961 iv[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
4962 iv[1].value = 4095;
4963 settings_payloadlen = (size_t)nghttp2_pack_settings_payload(
4964 settings_payload, sizeof(settings_payload), iv, 2);
4965
4966 /* Check client side */
4967 nghttp2_session_client_new(&session, &callbacks, NULL);
4968 CU_ASSERT(0 == nghttp2_session_upgrade2(session, settings_payload,
4969 settings_payloadlen, 0, &callbacks));
4970 CU_ASSERT(1 == session->last_sent_stream_id);
4971 stream = nghttp2_session_get_stream(session, 1);
4972 CU_ASSERT(stream != NULL);
4973 CU_ASSERT(&callbacks == stream->stream_user_data);
4974 CU_ASSERT(NGHTTP2_SHUT_WR == stream->shut_flags);
4975 item = nghttp2_session_get_next_ob_item(session);
4976 CU_ASSERT(NGHTTP2_SETTINGS == item->frame.hd.type);
4977 CU_ASSERT(2 == item->frame.settings.niv);
4978 CU_ASSERT(NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS ==
4979 item->frame.settings.iv[0].settings_id);
4980 CU_ASSERT(1 == item->frame.settings.iv[0].value);
4981 CU_ASSERT(NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE ==
4982 item->frame.settings.iv[1].settings_id);
4983 CU_ASSERT(4095 == item->frame.settings.iv[1].value);
4984
4985 /* Call nghttp2_session_upgrade2() again is error */
4986 CU_ASSERT(NGHTTP2_ERR_PROTO ==
4987 nghttp2_session_upgrade2(session, settings_payload,
4988 settings_payloadlen, 0, &callbacks));
4989 nghttp2_session_del(session);
4990
4991 /* Make sure that response from server can be received */
4992 nghttp2_session_client_new(&session, &callbacks, NULL);
4993
4994 CU_ASSERT(0 == nghttp2_session_upgrade2(session, settings_payload,
4995 settings_payloadlen, 0, &callbacks));
4996
4997 stream = nghttp2_session_get_stream(session, 1);
4998
4999 CU_ASSERT(NGHTTP2_STREAM_OPENING == stream->state);
5000
5001 nghttp2_hd_deflate_init(&deflater, mem);
5002 rv = pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, resnv,
5003 ARRLEN(resnv), mem);
5004
5005 CU_ASSERT(0 == rv);
5006
5007 buf = &bufs.head->buf;
5008
5009 rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
5010
5011 CU_ASSERT(rv == (ssize_t)nghttp2_buf_len(buf));
5012 CU_ASSERT(NGHTTP2_STREAM_OPENED == stream->state);
5013
5014 nghttp2_hd_deflate_free(&deflater);
5015 nghttp2_session_del(session);
5016
5017 nghttp2_bufs_reset(&bufs);
5018
5019 /* Check server side */
5020 nghttp2_session_server_new(&session, &callbacks, NULL);
5021 CU_ASSERT(0 == nghttp2_session_upgrade2(session, settings_payload,
5022 settings_payloadlen, 0, &callbacks));
5023 CU_ASSERT(1 == session->last_recv_stream_id);
5024 stream = nghttp2_session_get_stream(session, 1);
5025 CU_ASSERT(stream != NULL);
5026 CU_ASSERT(NULL == stream->stream_user_data);
5027 CU_ASSERT(NGHTTP2_SHUT_RD == stream->shut_flags);
5028 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
5029 CU_ASSERT(1 == session->remote_settings.max_concurrent_streams);
5030 CU_ASSERT(4095 == session->remote_settings.initial_window_size);
5031 /* Call nghttp2_session_upgrade2() again is error */
5032 CU_ASSERT(NGHTTP2_ERR_PROTO ==
5033 nghttp2_session_upgrade2(session, settings_payload,
5034 settings_payloadlen, 0, &callbacks));
5035 nghttp2_session_del(session);
5036
5037 /* Empty SETTINGS is OK */
5038 settings_payloadlen = (size_t)nghttp2_pack_settings_payload(
5039 settings_payload, sizeof(settings_payload), NULL, 0);
5040
5041 nghttp2_session_client_new(&session, &callbacks, NULL);
5042 CU_ASSERT(0 == nghttp2_session_upgrade2(session, settings_payload,
5043 settings_payloadlen, 0, NULL));
5044 nghttp2_session_del(session);
5045 nghttp2_bufs_free(&bufs);
5046 }
5047
test_nghttp2_session_reprioritize_stream(void)5048 void test_nghttp2_session_reprioritize_stream(void) {
5049 nghttp2_session *session;
5050 nghttp2_session_callbacks callbacks;
5051 nghttp2_stream *stream;
5052 nghttp2_stream *dep_stream;
5053 nghttp2_priority_spec pri_spec;
5054 int rv;
5055
5056 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
5057 callbacks.send_callback = block_count_send_callback;
5058
5059 nghttp2_session_server_new(&session, &callbacks, NULL);
5060
5061 stream = open_recv_stream(session, 1);
5062
5063 nghttp2_priority_spec_init(&pri_spec, 0, 10, 0);
5064
5065 rv = nghttp2_session_reprioritize_stream(session, stream, &pri_spec);
5066
5067 CU_ASSERT(0 == rv);
5068 CU_ASSERT(10 == stream->weight);
5069 CU_ASSERT(&session->root == stream->dep_prev);
5070
5071 /* If dependency to idle stream which is not in dependency tree yet */
5072
5073 nghttp2_priority_spec_init(&pri_spec, 3, 99, 0);
5074
5075 rv = nghttp2_session_reprioritize_stream(session, stream, &pri_spec);
5076
5077 CU_ASSERT(0 == rv);
5078 CU_ASSERT(99 == stream->weight);
5079 CU_ASSERT(3 == stream->dep_prev->stream_id);
5080
5081 dep_stream = nghttp2_session_get_stream_raw(session, 3);
5082
5083 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == dep_stream->weight);
5084
5085 dep_stream = open_recv_stream(session, 3);
5086
5087 /* Change weight */
5088 pri_spec.weight = 128;
5089
5090 rv = nghttp2_session_reprioritize_stream(session, stream, &pri_spec);
5091
5092 CU_ASSERT(0 == rv);
5093 CU_ASSERT(128 == stream->weight);
5094 CU_ASSERT(dep_stream == stream->dep_prev);
5095
5096 /* Change weight again to test short-path case */
5097 pri_spec.weight = 100;
5098
5099 rv = nghttp2_session_reprioritize_stream(session, stream, &pri_spec);
5100
5101 CU_ASSERT(0 == rv);
5102 CU_ASSERT(100 == stream->weight);
5103 CU_ASSERT(dep_stream == stream->dep_prev);
5104 CU_ASSERT(100 == dep_stream->sum_dep_weight);
5105
5106 /* Test circular dependency; stream 1 is first removed and becomes
5107 root. Then stream 3 depends on it. */
5108 nghttp2_priority_spec_init(&pri_spec, 1, 1, 0);
5109
5110 rv = nghttp2_session_reprioritize_stream(session, dep_stream, &pri_spec);
5111
5112 CU_ASSERT(0 == rv);
5113 CU_ASSERT(1 == dep_stream->weight);
5114 CU_ASSERT(stream == dep_stream->dep_prev);
5115
5116 /* Making priority to closed stream will result in default
5117 priority */
5118 session->last_recv_stream_id = 9;
5119
5120 nghttp2_priority_spec_init(&pri_spec, 5, 5, 0);
5121
5122 rv = nghttp2_session_reprioritize_stream(session, stream, &pri_spec);
5123
5124 CU_ASSERT(0 == rv);
5125 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == stream->weight);
5126
5127 nghttp2_session_del(session);
5128
5129 nghttp2_session_server_new(&session, &callbacks, NULL);
5130
5131 /* circular dependency; in case of stream which is not a direct
5132 descendant of root. Use exclusive dependency. */
5133 stream = open_recv_stream(session, 1);
5134 stream = open_recv_stream_with_dep(session, 3, stream);
5135 stream = open_recv_stream_with_dep(session, 5, stream);
5136 stream = open_recv_stream_with_dep(session, 7, stream);
5137 open_recv_stream_with_dep(session, 9, stream);
5138
5139 nghttp2_priority_spec_init(&pri_spec, 7, 1, 1);
5140
5141 stream = nghttp2_session_get_stream(session, 3);
5142 rv = nghttp2_session_reprioritize_stream(session, stream, &pri_spec);
5143
5144 CU_ASSERT(0 == rv);
5145 CU_ASSERT(7 == stream->dep_prev->stream_id);
5146
5147 stream = nghttp2_session_get_stream(session, 7);
5148
5149 CU_ASSERT(1 == stream->dep_prev->stream_id);
5150
5151 stream = nghttp2_session_get_stream(session, 9);
5152
5153 CU_ASSERT(3 == stream->dep_prev->stream_id);
5154
5155 stream = nghttp2_session_get_stream(session, 5);
5156
5157 CU_ASSERT(3 == stream->dep_prev->stream_id);
5158
5159 nghttp2_session_del(session);
5160
5161 nghttp2_session_server_new(&session, &callbacks, NULL);
5162
5163 /* circular dependency; in case of stream which is not a direct
5164 descendant of root. Without exclusive dependency. */
5165 stream = open_recv_stream(session, 1);
5166 stream = open_recv_stream_with_dep(session, 3, stream);
5167 stream = open_recv_stream_with_dep(session, 5, stream);
5168 stream = open_recv_stream_with_dep(session, 7, stream);
5169 open_recv_stream_with_dep(session, 9, stream);
5170
5171 nghttp2_priority_spec_init(&pri_spec, 7, 1, 0);
5172
5173 stream = nghttp2_session_get_stream(session, 3);
5174 rv = nghttp2_session_reprioritize_stream(session, stream, &pri_spec);
5175
5176 CU_ASSERT(0 == rv);
5177 CU_ASSERT(7 == stream->dep_prev->stream_id);
5178
5179 stream = nghttp2_session_get_stream(session, 7);
5180
5181 CU_ASSERT(1 == stream->dep_prev->stream_id);
5182
5183 stream = nghttp2_session_get_stream(session, 9);
5184
5185 CU_ASSERT(7 == stream->dep_prev->stream_id);
5186
5187 stream = nghttp2_session_get_stream(session, 5);
5188
5189 CU_ASSERT(3 == stream->dep_prev->stream_id);
5190
5191 nghttp2_session_del(session);
5192 }
5193
test_nghttp2_session_reprioritize_stream_with_idle_stream_dep(void)5194 void test_nghttp2_session_reprioritize_stream_with_idle_stream_dep(void) {
5195 nghttp2_session *session;
5196 nghttp2_session_callbacks callbacks;
5197 nghttp2_stream *stream;
5198 nghttp2_priority_spec pri_spec;
5199
5200 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
5201 callbacks.send_callback = block_count_send_callback;
5202
5203 nghttp2_session_server_new(&session, &callbacks, NULL);
5204
5205 stream = open_recv_stream(session, 1);
5206
5207 session->pending_local_max_concurrent_stream = 1;
5208
5209 nghttp2_priority_spec_init(&pri_spec, 101, 10, 0);
5210
5211 nghttp2_session_reprioritize_stream(session, stream, &pri_spec);
5212
5213 /* idle stream is not counteed to max concurrent streams */
5214
5215 CU_ASSERT(10 == stream->weight);
5216 CU_ASSERT(101 == stream->dep_prev->stream_id);
5217
5218 stream = nghttp2_session_get_stream_raw(session, 101);
5219
5220 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == stream->weight);
5221
5222 nghttp2_session_del(session);
5223 }
5224
test_nghttp2_submit_data(void)5225 void test_nghttp2_submit_data(void) {
5226 nghttp2_session *session;
5227 nghttp2_session_callbacks callbacks;
5228 nghttp2_data_provider data_prd;
5229 my_user_data ud;
5230 nghttp2_frame *frame;
5231 nghttp2_frame_hd hd;
5232 nghttp2_active_outbound_item *aob;
5233 nghttp2_bufs *framebufs;
5234 nghttp2_buf *buf;
5235
5236 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
5237 callbacks.send_callback = block_count_send_callback;
5238
5239 data_prd.read_callback = fixed_length_data_source_read_callback;
5240 ud.data_source_length = NGHTTP2_DATA_PAYLOADLEN * 2;
5241 CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, &ud));
5242 aob = &session->aob;
5243 framebufs = &aob->framebufs;
5244
5245 open_sent_stream(session, 1);
5246
5247 CU_ASSERT(
5248 0 == nghttp2_submit_data(session, NGHTTP2_FLAG_END_STREAM, 1, &data_prd));
5249
5250 ud.block_count = 0;
5251 CU_ASSERT(0 == nghttp2_session_send(session));
5252 frame = &aob->item->frame;
5253
5254 buf = &framebufs->head->buf;
5255 nghttp2_frame_unpack_frame_hd(&hd, buf->pos);
5256
5257 CU_ASSERT(NGHTTP2_FLAG_NONE == hd.flags);
5258 CU_ASSERT(NGHTTP2_FLAG_NONE == frame->hd.flags);
5259 /* aux_data.data.flags has these flags */
5260 CU_ASSERT(NGHTTP2_FLAG_END_STREAM == aob->item->aux_data.data.flags);
5261
5262 nghttp2_session_del(session);
5263 }
5264
test_nghttp2_submit_data_read_length_too_large(void)5265 void test_nghttp2_submit_data_read_length_too_large(void) {
5266 nghttp2_session *session;
5267 nghttp2_session_callbacks callbacks;
5268 nghttp2_data_provider data_prd;
5269 my_user_data ud;
5270 nghttp2_frame *frame;
5271 nghttp2_frame_hd hd;
5272 nghttp2_active_outbound_item *aob;
5273 nghttp2_bufs *framebufs;
5274 nghttp2_buf *buf;
5275 size_t payloadlen;
5276
5277 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
5278 callbacks.send_callback = block_count_send_callback;
5279 callbacks.read_length_callback = too_large_data_source_length_callback;
5280
5281 data_prd.read_callback = fixed_length_data_source_read_callback;
5282 ud.data_source_length = NGHTTP2_DATA_PAYLOADLEN * 2;
5283 CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, &ud));
5284 aob = &session->aob;
5285 framebufs = &aob->framebufs;
5286
5287 open_sent_stream(session, 1);
5288
5289 CU_ASSERT(
5290 0 == nghttp2_submit_data(session, NGHTTP2_FLAG_END_STREAM, 1, &data_prd));
5291
5292 ud.block_count = 0;
5293 CU_ASSERT(0 == nghttp2_session_send(session));
5294 frame = &aob->item->frame;
5295
5296 buf = &framebufs->head->buf;
5297 nghttp2_frame_unpack_frame_hd(&hd, buf->pos);
5298
5299 CU_ASSERT(NGHTTP2_FLAG_NONE == hd.flags);
5300 CU_ASSERT(NGHTTP2_FLAG_NONE == frame->hd.flags);
5301 CU_ASSERT(16384 == hd.length)
5302 /* aux_data.data.flags has these flags */
5303 CU_ASSERT(NGHTTP2_FLAG_END_STREAM == aob->item->aux_data.data.flags);
5304
5305 nghttp2_session_del(session);
5306
5307 /* Check that buffers are expanded */
5308 CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, &ud));
5309
5310 ud.data_source_length = NGHTTP2_MAX_FRAME_SIZE_MAX;
5311
5312 session->remote_settings.max_frame_size = NGHTTP2_MAX_FRAME_SIZE_MAX;
5313
5314 open_sent_stream(session, 1);
5315
5316 CU_ASSERT(
5317 0 == nghttp2_submit_data(session, NGHTTP2_FLAG_END_STREAM, 1, &data_prd));
5318
5319 ud.block_count = 0;
5320 CU_ASSERT(0 == nghttp2_session_send(session));
5321
5322 aob = &session->aob;
5323
5324 frame = &aob->item->frame;
5325
5326 framebufs = &aob->framebufs;
5327
5328 buf = &framebufs->head->buf;
5329 nghttp2_frame_unpack_frame_hd(&hd, buf->pos);
5330
5331 payloadlen = nghttp2_min(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE,
5332 NGHTTP2_INITIAL_WINDOW_SIZE);
5333
5334 CU_ASSERT(NGHTTP2_FRAME_HDLEN + 1 + payloadlen ==
5335 (size_t)nghttp2_buf_cap(buf));
5336 CU_ASSERT(NGHTTP2_FLAG_NONE == hd.flags);
5337 CU_ASSERT(NGHTTP2_FLAG_NONE == frame->hd.flags);
5338 CU_ASSERT(payloadlen == hd.length);
5339 /* aux_data.data.flags has these flags */
5340 CU_ASSERT(NGHTTP2_FLAG_END_STREAM == aob->item->aux_data.data.flags);
5341
5342 nghttp2_session_del(session);
5343 }
5344
test_nghttp2_submit_data_read_length_smallest(void)5345 void test_nghttp2_submit_data_read_length_smallest(void) {
5346 nghttp2_session *session;
5347 nghttp2_session_callbacks callbacks;
5348 nghttp2_data_provider data_prd;
5349 my_user_data ud;
5350 nghttp2_frame *frame;
5351 nghttp2_frame_hd hd;
5352 nghttp2_active_outbound_item *aob;
5353 nghttp2_bufs *framebufs;
5354 nghttp2_buf *buf;
5355
5356 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
5357 callbacks.send_callback = block_count_send_callback;
5358 callbacks.read_length_callback = smallest_length_data_source_length_callback;
5359
5360 data_prd.read_callback = fixed_length_data_source_read_callback;
5361 ud.data_source_length = NGHTTP2_DATA_PAYLOADLEN * 2;
5362 CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, &ud));
5363 aob = &session->aob;
5364 framebufs = &aob->framebufs;
5365
5366 open_sent_stream(session, 1);
5367
5368 CU_ASSERT(
5369 0 == nghttp2_submit_data(session, NGHTTP2_FLAG_END_STREAM, 1, &data_prd));
5370
5371 ud.block_count = 0;
5372 CU_ASSERT(0 == nghttp2_session_send(session));
5373 frame = &aob->item->frame;
5374
5375 buf = &framebufs->head->buf;
5376 nghttp2_frame_unpack_frame_hd(&hd, buf->pos);
5377
5378 CU_ASSERT(NGHTTP2_FLAG_NONE == hd.flags);
5379 CU_ASSERT(NGHTTP2_FLAG_NONE == frame->hd.flags);
5380 CU_ASSERT(1 == hd.length)
5381 /* aux_data.data.flags has these flags */
5382 CU_ASSERT(NGHTTP2_FLAG_END_STREAM == aob->item->aux_data.data.flags);
5383
5384 nghttp2_session_del(session);
5385 }
5386
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)5387 static ssize_t submit_data_twice_data_source_read_callback(
5388 nghttp2_session *session, int32_t stream_id, uint8_t *buf, size_t len,
5389 uint32_t *data_flags, nghttp2_data_source *source, void *user_data) {
5390 (void)session;
5391 (void)stream_id;
5392 (void)buf;
5393 (void)source;
5394 (void)user_data;
5395
5396 *data_flags |= NGHTTP2_DATA_FLAG_EOF;
5397 return (ssize_t)nghttp2_min(len, 16);
5398 }
5399
submit_data_twice_on_frame_send_callback(nghttp2_session * session,const nghttp2_frame * frame,void * user_data)5400 static int submit_data_twice_on_frame_send_callback(nghttp2_session *session,
5401 const nghttp2_frame *frame,
5402 void *user_data) {
5403 static int called = 0;
5404 int rv;
5405 nghttp2_data_provider data_prd;
5406 (void)user_data;
5407
5408 if (called == 0) {
5409 called = 1;
5410
5411 data_prd.read_callback = submit_data_twice_data_source_read_callback;
5412
5413 rv = nghttp2_submit_data(session, NGHTTP2_FLAG_END_STREAM,
5414 frame->hd.stream_id, &data_prd);
5415 CU_ASSERT(0 == rv);
5416 }
5417
5418 return 0;
5419 }
5420
test_nghttp2_submit_data_twice(void)5421 void test_nghttp2_submit_data_twice(void) {
5422 nghttp2_session *session;
5423 nghttp2_session_callbacks callbacks;
5424 nghttp2_data_provider data_prd;
5425 my_user_data ud;
5426 accumulator acc;
5427
5428 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
5429 callbacks.send_callback = accumulator_send_callback;
5430 callbacks.on_frame_send_callback = submit_data_twice_on_frame_send_callback;
5431
5432 data_prd.read_callback = submit_data_twice_data_source_read_callback;
5433
5434 acc.length = 0;
5435 ud.acc = &acc;
5436
5437 CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, &ud));
5438
5439 open_sent_stream(session, 1);
5440
5441 CU_ASSERT(0 == nghttp2_submit_data(session, NGHTTP2_FLAG_NONE, 1, &data_prd));
5442 CU_ASSERT(0 == nghttp2_session_send(session));
5443
5444 /* We should have sent 2 DATA frame with 16 bytes payload each */
5445 CU_ASSERT(NGHTTP2_FRAME_HDLEN * 2 + 16 * 2 == acc.length);
5446
5447 nghttp2_session_del(session);
5448 }
5449
test_nghttp2_submit_request_with_data(void)5450 void test_nghttp2_submit_request_with_data(void) {
5451 nghttp2_session *session;
5452 nghttp2_session_callbacks callbacks;
5453 nghttp2_data_provider data_prd;
5454 my_user_data ud;
5455 nghttp2_outbound_item *item;
5456 nghttp2_mem *mem;
5457
5458 mem = nghttp2_mem_default();
5459
5460 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
5461 callbacks.send_callback = null_send_callback;
5462
5463 data_prd.read_callback = fixed_length_data_source_read_callback;
5464 ud.data_source_length = 64 * 1024 - 1;
5465 CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, &ud));
5466 CU_ASSERT(1 == nghttp2_submit_request(session, NULL, reqnv, ARRLEN(reqnv),
5467 &data_prd, NULL));
5468 item = nghttp2_session_get_next_ob_item(session);
5469 CU_ASSERT(ARRLEN(reqnv) == item->frame.headers.nvlen);
5470 assert_nv_equal(reqnv, item->frame.headers.nva, item->frame.headers.nvlen,
5471 mem);
5472 CU_ASSERT(0 == nghttp2_session_send(session));
5473 CU_ASSERT(0 == ud.data_source_length);
5474
5475 nghttp2_session_del(session);
5476
5477 /* nghttp2_submit_request() with server session is error */
5478 nghttp2_session_server_new(&session, &callbacks, NULL);
5479
5480 CU_ASSERT(NGHTTP2_ERR_PROTO == nghttp2_submit_request(session, NULL, reqnv,
5481 ARRLEN(reqnv), NULL,
5482 NULL));
5483
5484 nghttp2_session_del(session);
5485 }
5486
test_nghttp2_submit_request_without_data(void)5487 void test_nghttp2_submit_request_without_data(void) {
5488 nghttp2_session *session;
5489 nghttp2_session_callbacks callbacks;
5490 accumulator acc;
5491 nghttp2_data_provider data_prd = {{-1}, NULL};
5492 nghttp2_outbound_item *item;
5493 my_user_data ud;
5494 nghttp2_frame frame;
5495 nghttp2_hd_inflater inflater;
5496 nva_out out;
5497 nghttp2_bufs bufs;
5498 nghttp2_mem *mem;
5499 nghttp2_priority_spec pri_spec;
5500
5501 mem = nghttp2_mem_default();
5502 frame_pack_bufs_init(&bufs);
5503
5504 nva_out_init(&out);
5505 acc.length = 0;
5506 ud.acc = &acc;
5507 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
5508 callbacks.send_callback = accumulator_send_callback;
5509 CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, &ud));
5510
5511 nghttp2_hd_inflate_init(&inflater, mem);
5512 CU_ASSERT(1 == nghttp2_submit_request(session, NULL, reqnv, ARRLEN(reqnv),
5513 &data_prd, NULL));
5514 item = nghttp2_session_get_next_ob_item(session);
5515 CU_ASSERT(ARRLEN(reqnv) == item->frame.headers.nvlen);
5516 assert_nv_equal(reqnv, item->frame.headers.nva, item->frame.headers.nvlen,
5517 mem);
5518 CU_ASSERT(item->frame.hd.flags & NGHTTP2_FLAG_END_STREAM);
5519
5520 CU_ASSERT(0 == nghttp2_session_send(session));
5521 CU_ASSERT(0 == unpack_frame(&frame, acc.buf, acc.length));
5522
5523 nghttp2_bufs_add(&bufs, acc.buf, acc.length);
5524 inflate_hd(&inflater, &out, &bufs, NGHTTP2_FRAME_HDLEN, mem);
5525
5526 CU_ASSERT(ARRLEN(reqnv) == out.nvlen);
5527 assert_nv_equal(reqnv, out.nva, out.nvlen, mem);
5528 nghttp2_frame_headers_free(&frame.headers, mem);
5529 nva_out_reset(&out, mem);
5530
5531 nghttp2_bufs_free(&bufs);
5532 nghttp2_hd_inflate_free(&inflater);
5533
5534 /* Try to depend on itself is error */
5535 nghttp2_priority_spec_init(&pri_spec, (int32_t)session->next_stream_id, 16,
5536 0);
5537
5538 CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT ==
5539 nghttp2_submit_request(session, &pri_spec, reqnv, ARRLEN(reqnv),
5540 NULL, NULL));
5541
5542 nghttp2_session_del(session);
5543 }
5544
test_nghttp2_submit_response_with_data(void)5545 void test_nghttp2_submit_response_with_data(void) {
5546 nghttp2_session *session;
5547 nghttp2_session_callbacks callbacks;
5548 nghttp2_data_provider data_prd;
5549 my_user_data ud;
5550 nghttp2_outbound_item *item;
5551 nghttp2_mem *mem;
5552
5553 mem = nghttp2_mem_default();
5554
5555 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
5556 callbacks.send_callback = null_send_callback;
5557
5558 data_prd.read_callback = fixed_length_data_source_read_callback;
5559 ud.data_source_length = 64 * 1024 - 1;
5560 CU_ASSERT(0 == nghttp2_session_server_new(&session, &callbacks, &ud));
5561 open_recv_stream2(session, 1, NGHTTP2_STREAM_OPENING);
5562 CU_ASSERT(0 == nghttp2_submit_response(session, 1, resnv, ARRLEN(resnv),
5563 &data_prd));
5564 item = nghttp2_session_get_next_ob_item(session);
5565 CU_ASSERT(ARRLEN(resnv) == item->frame.headers.nvlen);
5566 assert_nv_equal(resnv, item->frame.headers.nva, item->frame.headers.nvlen,
5567 mem);
5568 CU_ASSERT(0 == nghttp2_session_send(session));
5569 CU_ASSERT(0 == ud.data_source_length);
5570
5571 nghttp2_session_del(session);
5572
5573 /* Various error cases */
5574 nghttp2_session_client_new(&session, &callbacks, NULL);
5575
5576 /* Calling nghttp2_submit_response() with client session is error */
5577 CU_ASSERT(NGHTTP2_ERR_PROTO ==
5578 nghttp2_submit_response(session, 1, resnv, ARRLEN(resnv), NULL));
5579
5580 /* Stream ID <= 0 is error */
5581 CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT ==
5582 nghttp2_submit_response(session, 0, resnv, ARRLEN(resnv), NULL));
5583
5584 nghttp2_session_del(session);
5585 }
5586
test_nghttp2_submit_response_without_data(void)5587 void test_nghttp2_submit_response_without_data(void) {
5588 nghttp2_session *session;
5589 nghttp2_session_callbacks callbacks;
5590 accumulator acc;
5591 nghttp2_data_provider data_prd = {{-1}, NULL};
5592 nghttp2_outbound_item *item;
5593 my_user_data ud;
5594 nghttp2_frame frame;
5595 nghttp2_hd_inflater inflater;
5596 nva_out out;
5597 nghttp2_bufs bufs;
5598 nghttp2_mem *mem;
5599
5600 mem = nghttp2_mem_default();
5601 frame_pack_bufs_init(&bufs);
5602
5603 nva_out_init(&out);
5604 acc.length = 0;
5605 ud.acc = &acc;
5606 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
5607 callbacks.send_callback = accumulator_send_callback;
5608 CU_ASSERT(0 == nghttp2_session_server_new(&session, &callbacks, &ud));
5609
5610 nghttp2_hd_inflate_init(&inflater, mem);
5611 open_recv_stream2(session, 1, NGHTTP2_STREAM_OPENING);
5612 CU_ASSERT(0 == nghttp2_submit_response(session, 1, resnv, ARRLEN(resnv),
5613 &data_prd));
5614 item = nghttp2_session_get_next_ob_item(session);
5615 CU_ASSERT(ARRLEN(resnv) == item->frame.headers.nvlen);
5616 assert_nv_equal(resnv, item->frame.headers.nva, item->frame.headers.nvlen,
5617 mem);
5618 CU_ASSERT(item->frame.hd.flags & NGHTTP2_FLAG_END_STREAM);
5619
5620 CU_ASSERT(0 == nghttp2_session_send(session));
5621 CU_ASSERT(0 == unpack_frame(&frame, acc.buf, acc.length));
5622
5623 nghttp2_bufs_add(&bufs, acc.buf, acc.length);
5624 inflate_hd(&inflater, &out, &bufs, NGHTTP2_FRAME_HDLEN, mem);
5625
5626 CU_ASSERT(ARRLEN(resnv) == out.nvlen);
5627 assert_nv_equal(resnv, out.nva, out.nvlen, mem);
5628
5629 nva_out_reset(&out, mem);
5630 nghttp2_bufs_free(&bufs);
5631 nghttp2_frame_headers_free(&frame.headers, mem);
5632 nghttp2_hd_inflate_free(&inflater);
5633 nghttp2_session_del(session);
5634 }
5635
test_nghttp2_submit_response_push_response(void)5636 void test_nghttp2_submit_response_push_response(void) {
5637 nghttp2_session *session;
5638 nghttp2_session_callbacks callbacks;
5639 my_user_data ud;
5640
5641 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
5642 callbacks.send_callback = null_send_callback;
5643 callbacks.on_frame_not_send_callback = on_frame_not_send_callback;
5644
5645 nghttp2_session_server_new(&session, &callbacks, &ud);
5646
5647 open_sent_stream2(session, 2, NGHTTP2_STREAM_RESERVED);
5648
5649 session->goaway_flags |= NGHTTP2_GOAWAY_RECV;
5650
5651 CU_ASSERT(0 ==
5652 nghttp2_submit_response(session, 2, resnv, ARRLEN(resnv), NULL));
5653
5654 ud.frame_not_send_cb_called = 0;
5655
5656 CU_ASSERT(0 == nghttp2_session_send(session));
5657 CU_ASSERT(1 == ud.frame_not_send_cb_called);
5658
5659 nghttp2_session_del(session);
5660 }
5661
test_nghttp2_submit_trailer(void)5662 void test_nghttp2_submit_trailer(void) {
5663 nghttp2_session *session;
5664 nghttp2_session_callbacks callbacks;
5665 accumulator acc;
5666 nghttp2_data_provider data_prd;
5667 nghttp2_outbound_item *item;
5668 my_user_data ud;
5669 nghttp2_frame frame;
5670 nghttp2_hd_inflater inflater;
5671 nva_out out;
5672 nghttp2_bufs bufs;
5673 nghttp2_mem *mem;
5674
5675 mem = nghttp2_mem_default();
5676 frame_pack_bufs_init(&bufs);
5677
5678 data_prd.read_callback = no_end_stream_data_source_read_callback;
5679 nva_out_init(&out);
5680 acc.length = 0;
5681 ud.acc = &acc;
5682 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
5683 callbacks.send_callback = null_send_callback;
5684 CU_ASSERT(0 == nghttp2_session_server_new(&session, &callbacks, &ud));
5685
5686 nghttp2_hd_inflate_init(&inflater, mem);
5687 open_recv_stream2(session, 1, NGHTTP2_STREAM_OPENING);
5688 CU_ASSERT(0 == nghttp2_submit_response(session, 1, resnv, ARRLEN(resnv),
5689 &data_prd));
5690 CU_ASSERT(0 == nghttp2_session_send(session));
5691
5692 CU_ASSERT(0 ==
5693 nghttp2_submit_trailer(session, 1, trailernv, ARRLEN(trailernv)));
5694
5695 session->callbacks.send_callback = accumulator_send_callback;
5696
5697 item = nghttp2_session_get_next_ob_item(session);
5698 CU_ASSERT(NGHTTP2_HEADERS == item->frame.hd.type);
5699 CU_ASSERT(NGHTTP2_HCAT_HEADERS == item->frame.headers.cat);
5700 CU_ASSERT(item->frame.hd.flags & NGHTTP2_FLAG_END_STREAM);
5701
5702 CU_ASSERT(0 == nghttp2_session_send(session));
5703 CU_ASSERT(0 == unpack_frame(&frame, acc.buf, acc.length));
5704
5705 nghttp2_bufs_add(&bufs, acc.buf, acc.length);
5706 inflate_hd(&inflater, &out, &bufs, NGHTTP2_FRAME_HDLEN, mem);
5707
5708 CU_ASSERT(ARRLEN(trailernv) == out.nvlen);
5709 assert_nv_equal(trailernv, out.nva, out.nvlen, mem);
5710
5711 nva_out_reset(&out, mem);
5712 nghttp2_bufs_free(&bufs);
5713 nghttp2_frame_headers_free(&frame.headers, mem);
5714 nghttp2_hd_inflate_free(&inflater);
5715 nghttp2_session_del(session);
5716
5717 /* Specifying stream ID <= 0 is error */
5718 nghttp2_session_server_new(&session, &callbacks, NULL);
5719 open_recv_stream(session, 1);
5720
5721 CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT ==
5722 nghttp2_submit_trailer(session, 0, trailernv, ARRLEN(trailernv)));
5723
5724 CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT ==
5725 nghttp2_submit_trailer(session, -1, trailernv, ARRLEN(trailernv)));
5726
5727 nghttp2_session_del(session);
5728 }
5729
test_nghttp2_submit_headers_start_stream(void)5730 void test_nghttp2_submit_headers_start_stream(void) {
5731 nghttp2_session *session;
5732 nghttp2_session_callbacks callbacks;
5733 nghttp2_outbound_item *item;
5734 nghttp2_mem *mem;
5735
5736 mem = nghttp2_mem_default();
5737
5738 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
5739 CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, NULL));
5740 CU_ASSERT(1 == nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, -1,
5741 NULL, reqnv, ARRLEN(reqnv), NULL));
5742 item = nghttp2_session_get_next_ob_item(session);
5743 CU_ASSERT(ARRLEN(reqnv) == item->frame.headers.nvlen);
5744 assert_nv_equal(reqnv, item->frame.headers.nva, item->frame.headers.nvlen,
5745 mem);
5746 CU_ASSERT((NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM) ==
5747 item->frame.hd.flags);
5748 CU_ASSERT(0 == (item->frame.hd.flags & NGHTTP2_FLAG_PRIORITY));
5749
5750 nghttp2_session_del(session);
5751 }
5752
test_nghttp2_submit_headers_reply(void)5753 void test_nghttp2_submit_headers_reply(void) {
5754 nghttp2_session *session;
5755 nghttp2_session_callbacks callbacks;
5756 my_user_data ud;
5757 nghttp2_outbound_item *item;
5758 nghttp2_stream *stream;
5759 nghttp2_mem *mem;
5760
5761 mem = nghttp2_mem_default();
5762
5763 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
5764 callbacks.send_callback = null_send_callback;
5765 callbacks.on_frame_send_callback = on_frame_send_callback;
5766
5767 CU_ASSERT(0 == nghttp2_session_server_new(&session, &callbacks, &ud));
5768 CU_ASSERT(0 == nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, 1,
5769 NULL, resnv, ARRLEN(resnv), NULL));
5770 item = nghttp2_session_get_next_ob_item(session);
5771 CU_ASSERT(ARRLEN(resnv) == item->frame.headers.nvlen);
5772 assert_nv_equal(resnv, item->frame.headers.nva, item->frame.headers.nvlen,
5773 mem);
5774 CU_ASSERT((NGHTTP2_FLAG_END_STREAM | NGHTTP2_FLAG_END_HEADERS) ==
5775 item->frame.hd.flags);
5776
5777 ud.frame_send_cb_called = 0;
5778 ud.sent_frame_type = 0;
5779 /* The transimission will be canceled because the stream 1 is not
5780 open. */
5781 CU_ASSERT(0 == nghttp2_session_send(session));
5782 CU_ASSERT(0 == ud.frame_send_cb_called);
5783
5784 stream = open_recv_stream2(session, 1, NGHTTP2_STREAM_OPENING);
5785
5786 CU_ASSERT(0 == nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, 1,
5787 NULL, resnv, ARRLEN(resnv), NULL));
5788 CU_ASSERT(0 == nghttp2_session_send(session));
5789 CU_ASSERT(1 == ud.frame_send_cb_called);
5790 CU_ASSERT(NGHTTP2_HEADERS == ud.sent_frame_type);
5791 CU_ASSERT(stream->shut_flags & NGHTTP2_SHUT_WR);
5792
5793 nghttp2_session_del(session);
5794 }
5795
test_nghttp2_submit_headers_push_reply(void)5796 void test_nghttp2_submit_headers_push_reply(void) {
5797 nghttp2_session *session;
5798 nghttp2_session_callbacks callbacks;
5799 my_user_data ud;
5800 nghttp2_stream *stream;
5801 int foo;
5802
5803 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
5804 callbacks.send_callback = null_send_callback;
5805 callbacks.on_frame_send_callback = on_frame_send_callback;
5806
5807 CU_ASSERT(0 == nghttp2_session_server_new(&session, &callbacks, &ud));
5808 stream = open_sent_stream2(session, 2, NGHTTP2_STREAM_RESERVED);
5809 CU_ASSERT(0 == nghttp2_submit_headers(session, NGHTTP2_FLAG_NONE, 2, NULL,
5810 resnv, ARRLEN(resnv), &foo));
5811
5812 ud.frame_send_cb_called = 0;
5813 ud.sent_frame_type = 0;
5814 CU_ASSERT(0 == nghttp2_session_send(session));
5815 CU_ASSERT(1 == ud.frame_send_cb_called);
5816 CU_ASSERT(NGHTTP2_HEADERS == ud.sent_frame_type);
5817 CU_ASSERT(NGHTTP2_STREAM_OPENED == stream->state);
5818 CU_ASSERT(&foo == stream->stream_user_data);
5819
5820 nghttp2_session_del(session);
5821
5822 /* Sending HEADERS from client against stream in reserved state is
5823 error */
5824 CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, &ud));
5825 open_recv_stream2(session, 2, NGHTTP2_STREAM_RESERVED);
5826 CU_ASSERT(0 == nghttp2_submit_headers(session, NGHTTP2_FLAG_NONE, 2, NULL,
5827 reqnv, ARRLEN(reqnv), NULL));
5828
5829 ud.frame_send_cb_called = 0;
5830 ud.sent_frame_type = 0;
5831 CU_ASSERT(0 == nghttp2_session_send(session));
5832 CU_ASSERT(0 == ud.frame_send_cb_called);
5833
5834 nghttp2_session_del(session);
5835 }
5836
test_nghttp2_submit_headers(void)5837 void test_nghttp2_submit_headers(void) {
5838 nghttp2_session *session;
5839 nghttp2_session_callbacks callbacks;
5840 my_user_data ud;
5841 nghttp2_outbound_item *item;
5842 nghttp2_stream *stream;
5843 accumulator acc;
5844 nghttp2_frame frame;
5845 nghttp2_hd_inflater inflater;
5846 nva_out out;
5847 nghttp2_bufs bufs;
5848 nghttp2_mem *mem;
5849 nghttp2_priority_spec pri_spec;
5850
5851 mem = nghttp2_mem_default();
5852 frame_pack_bufs_init(&bufs);
5853
5854 nva_out_init(&out);
5855 acc.length = 0;
5856 ud.acc = &acc;
5857 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
5858 callbacks.send_callback = accumulator_send_callback;
5859 callbacks.on_frame_send_callback = on_frame_send_callback;
5860
5861 CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, &ud));
5862
5863 nghttp2_hd_inflate_init(&inflater, mem);
5864 CU_ASSERT(0 == nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, 1,
5865 NULL, reqnv, ARRLEN(reqnv), NULL));
5866 item = nghttp2_session_get_next_ob_item(session);
5867 CU_ASSERT(ARRLEN(reqnv) == item->frame.headers.nvlen);
5868 assert_nv_equal(reqnv, item->frame.headers.nva, item->frame.headers.nvlen,
5869 mem);
5870 CU_ASSERT((NGHTTP2_FLAG_END_STREAM | NGHTTP2_FLAG_END_HEADERS) ==
5871 item->frame.hd.flags);
5872
5873 ud.frame_send_cb_called = 0;
5874 ud.sent_frame_type = 0;
5875 /* The transimission will be canceled because the stream 1 is not
5876 open. */
5877 CU_ASSERT(0 == nghttp2_session_send(session));
5878 CU_ASSERT(0 == ud.frame_send_cb_called);
5879
5880 stream = open_sent_stream(session, 1);
5881
5882 CU_ASSERT(0 == nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, 1,
5883 NULL, reqnv, ARRLEN(reqnv), NULL));
5884 CU_ASSERT(0 == nghttp2_session_send(session));
5885 CU_ASSERT(1 == ud.frame_send_cb_called);
5886 CU_ASSERT(NGHTTP2_HEADERS == ud.sent_frame_type);
5887 CU_ASSERT(stream->shut_flags & NGHTTP2_SHUT_WR);
5888
5889 CU_ASSERT(0 == unpack_frame(&frame, acc.buf, acc.length));
5890
5891 nghttp2_bufs_add(&bufs, acc.buf, acc.length);
5892 inflate_hd(&inflater, &out, &bufs, NGHTTP2_FRAME_HDLEN, mem);
5893
5894 CU_ASSERT(ARRLEN(reqnv) == out.nvlen);
5895 assert_nv_equal(reqnv, out.nva, out.nvlen, mem);
5896
5897 nva_out_reset(&out, mem);
5898 nghttp2_bufs_free(&bufs);
5899 nghttp2_frame_headers_free(&frame.headers, mem);
5900
5901 nghttp2_hd_inflate_free(&inflater);
5902
5903 /* Try to depend on itself */
5904 nghttp2_priority_spec_init(&pri_spec, 3, 16, 0);
5905
5906 CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT ==
5907 nghttp2_submit_headers(session, NGHTTP2_FLAG_NONE, 3, &pri_spec,
5908 reqnv, ARRLEN(reqnv), NULL));
5909
5910 session->next_stream_id = 5;
5911 nghttp2_priority_spec_init(&pri_spec, 5, 16, 0);
5912
5913 CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT ==
5914 nghttp2_submit_headers(session, NGHTTP2_FLAG_NONE, -1, &pri_spec,
5915 reqnv, ARRLEN(reqnv), NULL));
5916
5917 nghttp2_session_del(session);
5918
5919 /* Error cases with invalid stream ID */
5920 nghttp2_session_server_new(&session, &callbacks, NULL);
5921
5922 /* Sending nghttp2_submit_headers() with stream_id == 1 and server
5923 session is error */
5924 CU_ASSERT(NGHTTP2_ERR_PROTO ==
5925 nghttp2_submit_headers(session, NGHTTP2_FLAG_NONE, -1, NULL, reqnv,
5926 ARRLEN(reqnv), NULL));
5927
5928 /* Sending stream ID <= 0 is error */
5929 CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT ==
5930 nghttp2_submit_headers(session, NGHTTP2_FLAG_NONE, 0, NULL, resnv,
5931 ARRLEN(resnv), NULL));
5932
5933 nghttp2_session_del(session);
5934 }
5935
test_nghttp2_submit_headers_continuation(void)5936 void test_nghttp2_submit_headers_continuation(void) {
5937 nghttp2_session *session;
5938 nghttp2_session_callbacks callbacks;
5939 nghttp2_nv nv[] = {
5940 MAKE_NV("h1", ""), MAKE_NV("h1", ""), MAKE_NV("h1", ""),
5941 MAKE_NV("h1", ""), MAKE_NV("h1", ""), MAKE_NV("h1", ""),
5942 MAKE_NV("h1", ""),
5943 };
5944 nghttp2_outbound_item *item;
5945 uint8_t data[4096];
5946 size_t i;
5947 my_user_data ud;
5948
5949 memset(data, '0', sizeof(data));
5950 for (i = 0; i < ARRLEN(nv); ++i) {
5951 nv[i].valuelen = sizeof(data);
5952 nv[i].value = data;
5953 }
5954
5955 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
5956 callbacks.send_callback = null_send_callback;
5957 callbacks.on_frame_send_callback = on_frame_send_callback;
5958
5959 CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, &ud));
5960 CU_ASSERT(1 == nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, -1,
5961 NULL, nv, ARRLEN(nv), NULL));
5962 item = nghttp2_session_get_next_ob_item(session);
5963 CU_ASSERT(NGHTTP2_HEADERS == item->frame.hd.type);
5964 CU_ASSERT((NGHTTP2_FLAG_END_STREAM | NGHTTP2_FLAG_END_HEADERS) ==
5965 item->frame.hd.flags);
5966 CU_ASSERT(0 == (item->frame.hd.flags & NGHTTP2_FLAG_PRIORITY));
5967
5968 ud.frame_send_cb_called = 0;
5969 CU_ASSERT(0 == nghttp2_session_send(session));
5970 CU_ASSERT(1 == ud.frame_send_cb_called);
5971
5972 nghttp2_session_del(session);
5973 }
5974
test_nghttp2_submit_headers_continuation_extra_large(void)5975 void test_nghttp2_submit_headers_continuation_extra_large(void) {
5976 nghttp2_session *session;
5977 nghttp2_session_callbacks callbacks;
5978 nghttp2_nv nv[] = {
5979 MAKE_NV("h1", ""), MAKE_NV("h1", ""), MAKE_NV("h1", ""),
5980 MAKE_NV("h1", ""), MAKE_NV("h1", ""), MAKE_NV("h1", ""),
5981 };
5982 nghttp2_outbound_item *item;
5983 uint8_t data[16384];
5984 size_t i;
5985 my_user_data ud;
5986 nghttp2_option *opt;
5987
5988 memset(data, '0', sizeof(data));
5989 for (i = 0; i < ARRLEN(nv); ++i) {
5990 nv[i].valuelen = sizeof(data);
5991 nv[i].value = data;
5992 }
5993
5994 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
5995 callbacks.send_callback = null_send_callback;
5996 callbacks.on_frame_send_callback = on_frame_send_callback;
5997
5998 /* The default size of max send header block length is too small to
5999 send these header fields. Expand it. */
6000 nghttp2_option_new(&opt);
6001 nghttp2_option_set_max_send_header_block_length(opt, 102400);
6002
6003 CU_ASSERT(0 == nghttp2_session_client_new2(&session, &callbacks, &ud, opt));
6004 CU_ASSERT(1 == nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, -1,
6005 NULL, nv, ARRLEN(nv), NULL));
6006 item = nghttp2_session_get_next_ob_item(session);
6007 CU_ASSERT(NGHTTP2_HEADERS == item->frame.hd.type);
6008 CU_ASSERT((NGHTTP2_FLAG_END_STREAM | NGHTTP2_FLAG_END_HEADERS) ==
6009 item->frame.hd.flags);
6010 CU_ASSERT(0 == (item->frame.hd.flags & NGHTTP2_FLAG_PRIORITY));
6011
6012 ud.frame_send_cb_called = 0;
6013 CU_ASSERT(0 == nghttp2_session_send(session));
6014 CU_ASSERT(1 == ud.frame_send_cb_called);
6015
6016 nghttp2_session_del(session);
6017 nghttp2_option_del(opt);
6018 }
6019
test_nghttp2_submit_priority(void)6020 void test_nghttp2_submit_priority(void) {
6021 nghttp2_session *session;
6022 nghttp2_session_callbacks callbacks;
6023 nghttp2_stream *stream;
6024 my_user_data ud;
6025 nghttp2_priority_spec pri_spec;
6026
6027 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6028 callbacks.send_callback = null_send_callback;
6029 callbacks.on_frame_send_callback = on_frame_send_callback;
6030
6031 nghttp2_session_client_new(&session, &callbacks, &ud);
6032 stream = open_sent_stream(session, 1);
6033
6034 nghttp2_priority_spec_init(&pri_spec, 0, 3, 0);
6035
6036 /* depends on stream 0 */
6037 CU_ASSERT(0 ==
6038 nghttp2_submit_priority(session, NGHTTP2_FLAG_NONE, 1, &pri_spec));
6039 CU_ASSERT(0 == nghttp2_session_send(session));
6040 CU_ASSERT(3 == stream->weight);
6041
6042 /* submit against idle stream */
6043 CU_ASSERT(0 ==
6044 nghttp2_submit_priority(session, NGHTTP2_FLAG_NONE, 3, &pri_spec));
6045
6046 ud.frame_send_cb_called = 0;
6047 CU_ASSERT(0 == nghttp2_session_send(session));
6048 CU_ASSERT(1 == ud.frame_send_cb_called);
6049
6050 nghttp2_session_del(session);
6051 }
6052
test_nghttp2_submit_settings(void)6053 void test_nghttp2_submit_settings(void) {
6054 nghttp2_session *session;
6055 nghttp2_session_callbacks callbacks;
6056 my_user_data ud;
6057 nghttp2_outbound_item *item;
6058 nghttp2_frame *frame;
6059 nghttp2_settings_entry iv[7];
6060 nghttp2_frame ack_frame;
6061 const int32_t UNKNOWN_ID = 1000000007;
6062 nghttp2_mem *mem;
6063
6064 mem = nghttp2_mem_default();
6065
6066 iv[0].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS;
6067 iv[0].value = 5;
6068
6069 iv[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
6070 iv[1].value = 16 * 1024;
6071
6072 iv[2].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS;
6073 iv[2].value = 50;
6074
6075 iv[3].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
6076 iv[3].value = 111;
6077
6078 iv[4].settings_id = UNKNOWN_ID;
6079 iv[4].value = 999;
6080
6081 iv[5].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
6082 iv[5].value = 1023;
6083
6084 iv[6].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
6085 iv[6].value = (uint32_t)NGHTTP2_MAX_WINDOW_SIZE + 1;
6086
6087 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6088 callbacks.send_callback = null_send_callback;
6089 callbacks.on_frame_send_callback = on_frame_send_callback;
6090 nghttp2_session_server_new(&session, &callbacks, &ud);
6091
6092 CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT ==
6093 nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, iv, 7));
6094
6095 /* Make sure that local settings are not changed */
6096 CU_ASSERT(NGHTTP2_DEFAULT_MAX_CONCURRENT_STREAMS ==
6097 session->local_settings.max_concurrent_streams);
6098 CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE ==
6099 session->local_settings.initial_window_size);
6100
6101 /* Now sends without 6th one */
6102 CU_ASSERT(0 == nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, iv, 6));
6103
6104 item = nghttp2_session_get_next_ob_item(session);
6105
6106 CU_ASSERT(NGHTTP2_SETTINGS == item->frame.hd.type);
6107
6108 frame = &item->frame;
6109 CU_ASSERT(6 == frame->settings.niv);
6110 CU_ASSERT(5 == frame->settings.iv[0].value);
6111 CU_ASSERT(NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS ==
6112 frame->settings.iv[0].settings_id);
6113
6114 CU_ASSERT(16 * 1024 == frame->settings.iv[1].value);
6115 CU_ASSERT(NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE ==
6116 frame->settings.iv[1].settings_id);
6117
6118 CU_ASSERT(UNKNOWN_ID == frame->settings.iv[4].settings_id);
6119 CU_ASSERT(999 == frame->settings.iv[4].value);
6120
6121 ud.frame_send_cb_called = 0;
6122 CU_ASSERT(0 == nghttp2_session_send(session));
6123 CU_ASSERT(1 == ud.frame_send_cb_called);
6124
6125 CU_ASSERT(50 == session->pending_local_max_concurrent_stream);
6126
6127 /* before receiving SETTINGS ACK, local settings have still default
6128 values */
6129 CU_ASSERT(NGHTTP2_DEFAULT_MAX_CONCURRENT_STREAMS ==
6130 nghttp2_session_get_local_settings(
6131 session, NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS));
6132 CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE ==
6133 nghttp2_session_get_local_settings(
6134 session, NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE));
6135
6136 nghttp2_frame_settings_init(&ack_frame.settings, NGHTTP2_FLAG_ACK, NULL, 0);
6137 CU_ASSERT(0 == nghttp2_session_on_settings_received(session, &ack_frame, 0));
6138 nghttp2_frame_settings_free(&ack_frame.settings, mem);
6139
6140 CU_ASSERT(16 * 1024 == session->local_settings.initial_window_size);
6141 CU_ASSERT(111 == session->hd_inflater.ctx.hd_table_bufsize_max);
6142 CU_ASSERT(111 == session->hd_inflater.min_hd_table_bufsize_max);
6143 CU_ASSERT(50 == session->local_settings.max_concurrent_streams);
6144
6145 CU_ASSERT(50 == nghttp2_session_get_local_settings(
6146 session, NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS));
6147 CU_ASSERT(16 * 1024 == nghttp2_session_get_local_settings(
6148 session, NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE));
6149
6150 /* We just keep the last seen value */
6151 CU_ASSERT(50 == session->pending_local_max_concurrent_stream);
6152
6153 nghttp2_session_del(session);
6154
6155 /* Bail out if there are contradicting
6156 SETTINGS_NO_RFC7540_PRIORITIES in one SETTINGS. */
6157 nghttp2_session_server_new(&session, &callbacks, &ud);
6158
6159 iv[0].settings_id = NGHTTP2_SETTINGS_NO_RFC7540_PRIORITIES;
6160 iv[0].value = 1;
6161 iv[1].settings_id = NGHTTP2_SETTINGS_NO_RFC7540_PRIORITIES;
6162 iv[1].value = 0;
6163
6164 CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT ==
6165 nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, iv, 2));
6166
6167 nghttp2_session_del(session);
6168
6169 /* Attempt to change SETTINGS_NO_RFC7540_PRIORITIES in the 2nd
6170 SETTINGS. */
6171 nghttp2_session_server_new(&session, &callbacks, &ud);
6172
6173 iv[0].settings_id = NGHTTP2_SETTINGS_NO_RFC7540_PRIORITIES;
6174 iv[0].value = 1;
6175
6176 CU_ASSERT(0 == nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, iv, 1));
6177
6178 iv[0].settings_id = NGHTTP2_SETTINGS_NO_RFC7540_PRIORITIES;
6179 iv[0].value = 0;
6180
6181 CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT ==
6182 nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, iv, 1));
6183
6184 nghttp2_session_del(session);
6185 }
6186
test_nghttp2_submit_settings_update_local_window_size(void)6187 void test_nghttp2_submit_settings_update_local_window_size(void) {
6188 nghttp2_session *session;
6189 nghttp2_session_callbacks callbacks;
6190 nghttp2_outbound_item *item;
6191 nghttp2_settings_entry iv[4];
6192 nghttp2_stream *stream;
6193 nghttp2_frame ack_frame;
6194 nghttp2_mem *mem;
6195 nghttp2_option *option;
6196
6197 mem = nghttp2_mem_default();
6198 nghttp2_frame_settings_init(&ack_frame.settings, NGHTTP2_FLAG_ACK, NULL, 0);
6199
6200 iv[0].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
6201 iv[0].value = 16 * 1024;
6202
6203 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6204 callbacks.send_callback = null_send_callback;
6205
6206 nghttp2_session_server_new(&session, &callbacks, NULL);
6207
6208 stream = open_recv_stream(session, 1);
6209 stream->local_window_size = NGHTTP2_INITIAL_WINDOW_SIZE + 100;
6210 stream->recv_window_size = 32768;
6211
6212 open_recv_stream(session, 3);
6213
6214 CU_ASSERT(0 == nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, iv, 1));
6215 CU_ASSERT(0 == nghttp2_session_send(session));
6216 CU_ASSERT(0 == nghttp2_session_on_settings_received(session, &ack_frame, 0));
6217
6218 stream = nghttp2_session_get_stream(session, 1);
6219 CU_ASSERT(0 == stream->recv_window_size);
6220 CU_ASSERT(16 * 1024 + 100 == stream->local_window_size);
6221
6222 stream = nghttp2_session_get_stream(session, 3);
6223 CU_ASSERT(16 * 1024 == stream->local_window_size);
6224
6225 item = nghttp2_session_get_next_ob_item(session);
6226 CU_ASSERT(NGHTTP2_WINDOW_UPDATE == item->frame.hd.type);
6227 CU_ASSERT(32768 == item->frame.window_update.window_size_increment);
6228
6229 nghttp2_session_del(session);
6230
6231 /* Without auto-window update */
6232 nghttp2_option_new(&option);
6233 nghttp2_option_set_no_auto_window_update(option, 1);
6234
6235 nghttp2_session_server_new2(&session, &callbacks, NULL, option);
6236
6237 nghttp2_option_del(option);
6238
6239 stream = open_recv_stream(session, 1);
6240 stream->local_window_size = NGHTTP2_INITIAL_WINDOW_SIZE + 100;
6241 stream->recv_window_size = 32768;
6242
6243 CU_ASSERT(0 == nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, iv, 1));
6244 CU_ASSERT(0 == nghttp2_session_send(session));
6245 CU_ASSERT(0 == nghttp2_session_on_settings_received(session, &ack_frame, 0));
6246
6247 stream = nghttp2_session_get_stream(session, 1);
6248
6249 CU_ASSERT(32768 == stream->recv_window_size);
6250 CU_ASSERT(16 * 1024 + 100 == stream->local_window_size);
6251 /* Check that we can handle the case where local_window_size <
6252 recv_window_size */
6253 CU_ASSERT(0 == nghttp2_session_get_stream_local_window_size(session, 1));
6254
6255 nghttp2_session_del(session);
6256
6257 /* Check overflow case */
6258 iv[0].value = 128 * 1024;
6259 nghttp2_session_server_new(&session, &callbacks, NULL);
6260 stream = open_recv_stream(session, 1);
6261 stream->local_window_size = NGHTTP2_MAX_WINDOW_SIZE;
6262
6263 CU_ASSERT(0 == nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, iv, 1));
6264 CU_ASSERT(0 == nghttp2_session_send(session));
6265 CU_ASSERT(0 == nghttp2_session_on_settings_received(session, &ack_frame, 0));
6266
6267 item = nghttp2_session_get_next_ob_item(session);
6268 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
6269 CU_ASSERT(NGHTTP2_FLOW_CONTROL_ERROR == item->frame.rst_stream.error_code);
6270
6271 nghttp2_session_del(session);
6272 nghttp2_frame_settings_free(&ack_frame.settings, mem);
6273 }
6274
test_nghttp2_submit_settings_multiple_times(void)6275 void test_nghttp2_submit_settings_multiple_times(void) {
6276 nghttp2_session *session;
6277 nghttp2_session_callbacks callbacks;
6278 nghttp2_settings_entry iv[4];
6279 nghttp2_frame frame;
6280 nghttp2_inflight_settings *inflight_settings;
6281
6282 memset(&callbacks, 0, sizeof(callbacks));
6283 callbacks.send_callback = null_send_callback;
6284
6285 nghttp2_session_client_new(&session, &callbacks, NULL);
6286
6287 /* first SETTINGS */
6288 iv[0].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS;
6289 iv[0].value = 100;
6290
6291 iv[1].settings_id = NGHTTP2_SETTINGS_ENABLE_PUSH;
6292 iv[1].value = 0;
6293
6294 CU_ASSERT(0 == nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, iv, 2));
6295
6296 inflight_settings = session->inflight_settings_head;
6297
6298 CU_ASSERT(NULL != inflight_settings);
6299 CU_ASSERT(NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS ==
6300 inflight_settings->iv[0].settings_id);
6301 CU_ASSERT(100 == inflight_settings->iv[0].value);
6302 CU_ASSERT(2 == inflight_settings->niv);
6303 CU_ASSERT(NULL == inflight_settings->next);
6304
6305 CU_ASSERT(100 == session->pending_local_max_concurrent_stream);
6306 CU_ASSERT(0 == session->pending_enable_push);
6307
6308 /* second SETTINGS */
6309 iv[0].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS;
6310 iv[0].value = 99;
6311
6312 CU_ASSERT(0 == nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, iv, 1));
6313
6314 inflight_settings = session->inflight_settings_head->next;
6315
6316 CU_ASSERT(NULL != inflight_settings);
6317 CU_ASSERT(NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS ==
6318 inflight_settings->iv[0].settings_id);
6319 CU_ASSERT(99 == inflight_settings->iv[0].value);
6320 CU_ASSERT(1 == inflight_settings->niv);
6321 CU_ASSERT(NULL == inflight_settings->next);
6322
6323 CU_ASSERT(99 == session->pending_local_max_concurrent_stream);
6324 CU_ASSERT(0 == session->pending_enable_push);
6325
6326 nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_ACK, NULL, 0);
6327
6328 /* receive SETTINGS ACK */
6329 CU_ASSERT(0 == nghttp2_session_on_settings_received(session, &frame, 0));
6330
6331 inflight_settings = session->inflight_settings_head;
6332
6333 /* first inflight SETTINGS was removed */
6334 CU_ASSERT(NULL != inflight_settings);
6335 CU_ASSERT(NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS ==
6336 inflight_settings->iv[0].settings_id);
6337 CU_ASSERT(99 == inflight_settings->iv[0].value);
6338 CU_ASSERT(1 == inflight_settings->niv);
6339 CU_ASSERT(NULL == inflight_settings->next);
6340
6341 CU_ASSERT(100 == session->local_settings.max_concurrent_streams);
6342
6343 /* receive SETTINGS ACK again */
6344 CU_ASSERT(0 == nghttp2_session_on_settings_received(session, &frame, 0));
6345
6346 CU_ASSERT(NULL == session->inflight_settings_head);
6347 CU_ASSERT(99 == session->local_settings.max_concurrent_streams);
6348
6349 nghttp2_session_del(session);
6350 }
6351
test_nghttp2_submit_push_promise(void)6352 void test_nghttp2_submit_push_promise(void) {
6353 nghttp2_session *session;
6354 nghttp2_session_callbacks callbacks;
6355 my_user_data ud;
6356 nghttp2_stream *stream;
6357
6358 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6359 callbacks.send_callback = null_send_callback;
6360 callbacks.on_frame_send_callback = on_frame_send_callback;
6361 callbacks.on_frame_not_send_callback = on_frame_not_send_callback;
6362
6363 CU_ASSERT(0 == nghttp2_session_server_new(&session, &callbacks, &ud));
6364 open_recv_stream(session, 1);
6365 CU_ASSERT(2 == nghttp2_submit_push_promise(session, NGHTTP2_FLAG_NONE, 1,
6366 reqnv, ARRLEN(reqnv), &ud));
6367
6368 stream = nghttp2_session_get_stream(session, 2);
6369
6370 CU_ASSERT(NULL != stream);
6371 CU_ASSERT(NGHTTP2_STREAM_RESERVED == stream->state);
6372 CU_ASSERT(&ud == nghttp2_session_get_stream_user_data(session, 2));
6373
6374 ud.frame_send_cb_called = 0;
6375 ud.sent_frame_type = 0;
6376
6377 CU_ASSERT(0 == nghttp2_session_send(session));
6378 CU_ASSERT(1 == ud.frame_send_cb_called);
6379 CU_ASSERT(NGHTTP2_PUSH_PROMISE == ud.sent_frame_type);
6380
6381 stream = nghttp2_session_get_stream(session, 2);
6382
6383 CU_ASSERT(NGHTTP2_STREAM_RESERVED == stream->state);
6384 CU_ASSERT(&ud == nghttp2_session_get_stream_user_data(session, 2));
6385
6386 /* submit PUSH_PROMISE while associated stream is not opened */
6387 CU_ASSERT(NGHTTP2_ERR_STREAM_CLOSED ==
6388 nghttp2_submit_push_promise(session, NGHTTP2_FLAG_NONE, 3, reqnv,
6389 ARRLEN(reqnv), NULL));
6390
6391 /* Stream ID <= 0 is error */
6392 CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT ==
6393 nghttp2_submit_push_promise(session, NGHTTP2_FLAG_NONE, 0, reqnv,
6394 ARRLEN(reqnv), NULL));
6395
6396 nghttp2_session_del(session);
6397 }
6398
test_nghttp2_submit_window_update(void)6399 void test_nghttp2_submit_window_update(void) {
6400 nghttp2_session *session;
6401 nghttp2_session_callbacks callbacks;
6402 my_user_data ud;
6403 nghttp2_outbound_item *item;
6404 nghttp2_stream *stream;
6405
6406 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6407 callbacks.send_callback = null_send_callback;
6408
6409 nghttp2_session_client_new(&session, &callbacks, &ud);
6410 stream = open_recv_stream(session, 2);
6411 stream->recv_window_size = 4096;
6412
6413 CU_ASSERT(0 ==
6414 nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 2, 1024));
6415 item = nghttp2_session_get_next_ob_item(session);
6416 CU_ASSERT(NGHTTP2_WINDOW_UPDATE == item->frame.hd.type);
6417 CU_ASSERT(1024 == item->frame.window_update.window_size_increment);
6418 CU_ASSERT(0 == nghttp2_session_send(session));
6419 CU_ASSERT(3072 == stream->recv_window_size);
6420
6421 CU_ASSERT(0 ==
6422 nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 2, 4096));
6423 item = nghttp2_session_get_next_ob_item(session);
6424 CU_ASSERT(NGHTTP2_WINDOW_UPDATE == item->frame.hd.type);
6425 CU_ASSERT(4096 == item->frame.window_update.window_size_increment);
6426 CU_ASSERT(0 == nghttp2_session_send(session));
6427 CU_ASSERT(0 == stream->recv_window_size);
6428
6429 CU_ASSERT(0 ==
6430 nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 2, 4096));
6431 item = nghttp2_session_get_next_ob_item(session);
6432 CU_ASSERT(NGHTTP2_WINDOW_UPDATE == item->frame.hd.type);
6433 CU_ASSERT(4096 == item->frame.window_update.window_size_increment);
6434 CU_ASSERT(0 == nghttp2_session_send(session));
6435 CU_ASSERT(0 == stream->recv_window_size);
6436
6437 CU_ASSERT(0 ==
6438 nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 2, 0));
6439 /* It is ok if stream is closed or does not exist at the call
6440 time */
6441 CU_ASSERT(0 ==
6442 nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 4, 4096));
6443
6444 nghttp2_session_del(session);
6445 }
6446
test_nghttp2_submit_window_update_local_window_size(void)6447 void test_nghttp2_submit_window_update_local_window_size(void) {
6448 nghttp2_session *session;
6449 nghttp2_session_callbacks callbacks;
6450 nghttp2_outbound_item *item;
6451 nghttp2_stream *stream;
6452
6453 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6454 callbacks.send_callback = null_send_callback;
6455
6456 nghttp2_session_client_new(&session, &callbacks, NULL);
6457 stream = open_recv_stream(session, 2);
6458 stream->recv_window_size = 4096;
6459
6460 CU_ASSERT(0 == nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 2,
6461 stream->recv_window_size + 1));
6462 CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE + 1 == stream->local_window_size);
6463 CU_ASSERT(0 == stream->recv_window_size);
6464 item = nghttp2_session_get_next_ob_item(session);
6465 CU_ASSERT(NGHTTP2_WINDOW_UPDATE == item->frame.hd.type);
6466 CU_ASSERT(4097 == item->frame.window_update.window_size_increment);
6467
6468 CU_ASSERT(0 == nghttp2_session_send(session));
6469
6470 /* Let's decrement local window size */
6471 stream->recv_window_size = 4096;
6472 CU_ASSERT(0 == nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 2,
6473 -stream->local_window_size / 2));
6474 CU_ASSERT(32768 == stream->local_window_size);
6475 CU_ASSERT(-28672 == stream->recv_window_size);
6476 CU_ASSERT(32768 == stream->recv_reduction);
6477
6478 item = nghttp2_session_get_next_ob_item(session);
6479 CU_ASSERT(item == NULL);
6480
6481 /* Increase local window size */
6482 CU_ASSERT(0 ==
6483 nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 2, 16384));
6484 CU_ASSERT(49152 == stream->local_window_size);
6485 CU_ASSERT(-12288 == stream->recv_window_size);
6486 CU_ASSERT(16384 == stream->recv_reduction);
6487 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
6488
6489 CU_ASSERT(NGHTTP2_ERR_FLOW_CONTROL ==
6490 nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 2,
6491 NGHTTP2_MAX_WINDOW_SIZE));
6492
6493 CU_ASSERT(0 == nghttp2_session_send(session));
6494
6495 /* Check connection-level flow control */
6496 session->recv_window_size = 4096;
6497 CU_ASSERT(0 == nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 0,
6498 session->recv_window_size + 1));
6499 CU_ASSERT(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE + 1 ==
6500 session->local_window_size);
6501 CU_ASSERT(0 == session->recv_window_size);
6502 item = nghttp2_session_get_next_ob_item(session);
6503 CU_ASSERT(NGHTTP2_WINDOW_UPDATE == item->frame.hd.type);
6504 CU_ASSERT(4097 == item->frame.window_update.window_size_increment);
6505
6506 CU_ASSERT(0 == nghttp2_session_send(session));
6507
6508 /* Go decrement part */
6509 session->recv_window_size = 4096;
6510 CU_ASSERT(0 == nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 0,
6511 -session->local_window_size / 2));
6512 CU_ASSERT(32768 == session->local_window_size);
6513 CU_ASSERT(-28672 == session->recv_window_size);
6514 CU_ASSERT(32768 == session->recv_reduction);
6515 item = nghttp2_session_get_next_ob_item(session);
6516 CU_ASSERT(item == NULL);
6517
6518 /* Increase local window size */
6519 CU_ASSERT(0 ==
6520 nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 0, 16384));
6521 CU_ASSERT(49152 == session->local_window_size);
6522 CU_ASSERT(-12288 == session->recv_window_size);
6523 CU_ASSERT(16384 == session->recv_reduction);
6524 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
6525
6526 CU_ASSERT(NGHTTP2_ERR_FLOW_CONTROL ==
6527 nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 0,
6528 NGHTTP2_MAX_WINDOW_SIZE));
6529
6530 nghttp2_session_del(session);
6531 }
6532
test_nghttp2_submit_shutdown_notice(void)6533 void test_nghttp2_submit_shutdown_notice(void) {
6534 nghttp2_session *session;
6535 nghttp2_session_callbacks callbacks;
6536 my_user_data ud;
6537
6538 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6539 callbacks.send_callback = null_send_callback;
6540 callbacks.on_frame_send_callback = on_frame_send_callback;
6541 callbacks.on_frame_not_send_callback = on_frame_not_send_callback;
6542
6543 nghttp2_session_server_new(&session, &callbacks, &ud);
6544
6545 CU_ASSERT(0 == nghttp2_submit_shutdown_notice(session));
6546
6547 ud.frame_send_cb_called = 0;
6548
6549 nghttp2_session_send(session);
6550
6551 CU_ASSERT(1 == ud.frame_send_cb_called);
6552 CU_ASSERT(NGHTTP2_GOAWAY == ud.sent_frame_type);
6553 CU_ASSERT((1u << 31) - 1 == session->local_last_stream_id);
6554
6555 /* After another GOAWAY, nghttp2_submit_shutdown_notice() is
6556 noop. */
6557 CU_ASSERT(0 == nghttp2_session_terminate_session(session, NGHTTP2_NO_ERROR));
6558
6559 ud.frame_send_cb_called = 0;
6560
6561 nghttp2_session_send(session);
6562
6563 CU_ASSERT(1 == ud.frame_send_cb_called);
6564 CU_ASSERT(NGHTTP2_GOAWAY == ud.sent_frame_type);
6565 CU_ASSERT(0 == session->local_last_stream_id);
6566
6567 CU_ASSERT(0 == nghttp2_submit_shutdown_notice(session));
6568
6569 ud.frame_send_cb_called = 0;
6570 ud.frame_not_send_cb_called = 0;
6571
6572 nghttp2_session_send(session);
6573
6574 CU_ASSERT(0 == ud.frame_send_cb_called);
6575 CU_ASSERT(0 == ud.frame_not_send_cb_called);
6576
6577 nghttp2_session_del(session);
6578
6579 /* Using nghttp2_submit_shutdown_notice() with client side session
6580 is error */
6581 nghttp2_session_client_new(&session, &callbacks, NULL);
6582
6583 CU_ASSERT(NGHTTP2_ERR_INVALID_STATE ==
6584 nghttp2_submit_shutdown_notice(session));
6585
6586 nghttp2_session_del(session);
6587 }
6588
test_nghttp2_submit_invalid_nv(void)6589 void test_nghttp2_submit_invalid_nv(void) {
6590 nghttp2_session *session;
6591 nghttp2_session_callbacks callbacks;
6592 nghttp2_nv empty_name_nv[] = {MAKE_NV("Version", "HTTP/1.1"),
6593 MAKE_NV("", "empty name")};
6594
6595 /* Now invalid header name/value pair in HTTP/1.1 is accepted in
6596 nghttp2 */
6597
6598 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6599
6600 CU_ASSERT(0 == nghttp2_session_server_new(&session, &callbacks, NULL));
6601
6602 /* nghttp2_submit_response */
6603 CU_ASSERT(0 == nghttp2_submit_response(session, 2, empty_name_nv,
6604 ARRLEN(empty_name_nv), NULL));
6605
6606 /* nghttp2_submit_push_promise */
6607 open_recv_stream(session, 1);
6608
6609 CU_ASSERT(0 < nghttp2_submit_push_promise(session, NGHTTP2_FLAG_NONE, 1,
6610 empty_name_nv,
6611 ARRLEN(empty_name_nv), NULL));
6612
6613 nghttp2_session_del(session);
6614
6615 CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, NULL));
6616
6617 /* nghttp2_submit_request */
6618 CU_ASSERT(0 < nghttp2_submit_request(session, NULL, empty_name_nv,
6619 ARRLEN(empty_name_nv), NULL, NULL));
6620
6621 /* nghttp2_submit_headers */
6622 CU_ASSERT(0 < nghttp2_submit_headers(session, NGHTTP2_FLAG_NONE, -1, NULL,
6623 empty_name_nv, ARRLEN(empty_name_nv),
6624 NULL));
6625
6626 nghttp2_session_del(session);
6627 }
6628
test_nghttp2_submit_extension(void)6629 void test_nghttp2_submit_extension(void) {
6630 nghttp2_session *session;
6631 nghttp2_session_callbacks callbacks;
6632 my_user_data ud;
6633 accumulator acc;
6634 nghttp2_mem *mem;
6635 const char data[] = "Hello World!";
6636 size_t len;
6637 int32_t stream_id;
6638 int rv;
6639
6640 mem = nghttp2_mem_default();
6641
6642 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6643
6644 callbacks.pack_extension_callback = pack_extension_callback;
6645 callbacks.send_callback = accumulator_send_callback;
6646
6647 nghttp2_buf_init2(&ud.scratchbuf, 4096, mem);
6648
6649 nghttp2_session_client_new(&session, &callbacks, &ud);
6650
6651 ud.scratchbuf.last = nghttp2_cpymem(ud.scratchbuf.last, data, sizeof(data));
6652 ud.acc = &acc;
6653
6654 rv = nghttp2_submit_extension(session, 211, 0x01, 3, &ud.scratchbuf);
6655
6656 CU_ASSERT(0 == rv);
6657
6658 acc.length = 0;
6659
6660 rv = nghttp2_session_send(session);
6661
6662 CU_ASSERT(0 == rv);
6663 CU_ASSERT(NGHTTP2_FRAME_HDLEN + sizeof(data) == acc.length);
6664
6665 len = nghttp2_get_uint32(acc.buf) >> 8;
6666
6667 CU_ASSERT(sizeof(data) == len);
6668 CU_ASSERT(211 == acc.buf[3]);
6669 CU_ASSERT(0x01 == acc.buf[4]);
6670
6671 stream_id = (int32_t)nghttp2_get_uint32(acc.buf + 5);
6672
6673 CU_ASSERT(3 == stream_id);
6674 CU_ASSERT(0 == memcmp(data, &acc.buf[NGHTTP2_FRAME_HDLEN], sizeof(data)));
6675
6676 nghttp2_session_del(session);
6677
6678 /* submitting standard HTTP/2 frame is error */
6679 nghttp2_session_server_new(&session, &callbacks, &ud);
6680
6681 rv = nghttp2_submit_extension(session, NGHTTP2_GOAWAY, NGHTTP2_FLAG_NONE, 0,
6682 NULL);
6683
6684 CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT == rv);
6685
6686 nghttp2_session_del(session);
6687 nghttp2_buf_free(&ud.scratchbuf, mem);
6688 }
6689
test_nghttp2_submit_altsvc(void)6690 void test_nghttp2_submit_altsvc(void) {
6691 nghttp2_session *session;
6692 nghttp2_session_callbacks callbacks;
6693 my_user_data ud;
6694 int rv;
6695 ssize_t len;
6696 const uint8_t *data;
6697 nghttp2_frame_hd hd;
6698 size_t origin_len;
6699 const uint8_t origin[] = "nghttp2.org";
6700 const uint8_t field_value[] = "h2=\":443\"";
6701
6702 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6703
6704 nghttp2_session_server_new(&session, &callbacks, &ud);
6705
6706 rv = nghttp2_submit_altsvc(session, NGHTTP2_FLAG_NONE, 0, origin,
6707 sizeof(origin) - 1, field_value,
6708 sizeof(field_value) - 1);
6709
6710 CU_ASSERT(0 == rv);
6711
6712 ud.frame_send_cb_called = 0;
6713
6714 len = nghttp2_session_mem_send(session, &data);
6715
6716 CU_ASSERT(len == NGHTTP2_FRAME_HDLEN + 2 + sizeof(origin) - 1 +
6717 sizeof(field_value) - 1);
6718
6719 nghttp2_frame_unpack_frame_hd(&hd, data);
6720
6721 CU_ASSERT(2 + sizeof(origin) - 1 + sizeof(field_value) - 1 == hd.length);
6722 CU_ASSERT(NGHTTP2_ALTSVC == hd.type);
6723 CU_ASSERT(NGHTTP2_FLAG_NONE == hd.flags);
6724
6725 origin_len = nghttp2_get_uint16(data + NGHTTP2_FRAME_HDLEN);
6726
6727 CU_ASSERT(sizeof(origin) - 1 == origin_len);
6728 CU_ASSERT(0 ==
6729 memcmp(origin, data + NGHTTP2_FRAME_HDLEN + 2, sizeof(origin) - 1));
6730 CU_ASSERT(0 == memcmp(field_value,
6731 data + NGHTTP2_FRAME_HDLEN + 2 + sizeof(origin) - 1,
6732 hd.length - (sizeof(origin) - 1) - 2));
6733
6734 /* submitting empty origin with stream_id == 0 is error */
6735 rv = nghttp2_submit_altsvc(session, NGHTTP2_FLAG_NONE, 0, NULL, 0,
6736 field_value, sizeof(field_value) - 1);
6737
6738 CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT == rv);
6739
6740 /* submitting non-empty origin with stream_id != 0 is error */
6741 rv = nghttp2_submit_altsvc(session, NGHTTP2_FLAG_NONE, 1, origin,
6742 sizeof(origin) - 1, field_value,
6743 sizeof(field_value) - 1);
6744
6745 CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT == rv);
6746
6747 nghttp2_session_del(session);
6748
6749 /* submitting from client side session is error */
6750 nghttp2_session_client_new(&session, &callbacks, NULL);
6751
6752 rv = nghttp2_submit_altsvc(session, NGHTTP2_FLAG_NONE, 0, origin,
6753 sizeof(origin) - 1, field_value,
6754 sizeof(field_value) - 1);
6755
6756 CU_ASSERT(NGHTTP2_ERR_INVALID_STATE == rv);
6757
6758 nghttp2_session_del(session);
6759 }
6760
test_nghttp2_submit_origin(void)6761 void test_nghttp2_submit_origin(void) {
6762 nghttp2_session *session;
6763 nghttp2_session_callbacks callbacks;
6764 my_user_data ud;
6765 int rv;
6766 ssize_t len;
6767 const uint8_t *data;
6768 static const uint8_t nghttp2[] = "https://nghttp2.org";
6769 static const uint8_t examples[] = "https://examples.com";
6770 static const nghttp2_origin_entry ov[] = {
6771 {
6772 (uint8_t *)nghttp2,
6773 sizeof(nghttp2) - 1,
6774 },
6775 {
6776 (uint8_t *)examples,
6777 sizeof(examples) - 1,
6778 },
6779 };
6780 nghttp2_frame frame;
6781 nghttp2_ext_origin origin;
6782 nghttp2_mem *mem;
6783
6784 mem = nghttp2_mem_default();
6785
6786 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6787 callbacks.on_frame_send_callback = on_frame_send_callback;
6788
6789 frame.ext.payload = &origin;
6790
6791 nghttp2_session_server_new(&session, &callbacks, &ud);
6792
6793 rv = nghttp2_submit_origin(session, NGHTTP2_FLAG_NONE, ov, 2);
6794
6795 CU_ASSERT(0 == rv);
6796
6797 ud.frame_send_cb_called = 0;
6798 len = nghttp2_session_mem_send(session, &data);
6799
6800 CU_ASSERT(len > 0);
6801 CU_ASSERT(1 == ud.frame_send_cb_called);
6802
6803 nghttp2_frame_unpack_frame_hd(&frame.hd, data);
6804 rv = nghttp2_frame_unpack_origin_payload(
6805 &frame.ext, data + NGHTTP2_FRAME_HDLEN, (size_t)len - NGHTTP2_FRAME_HDLEN,
6806 mem);
6807
6808 CU_ASSERT(0 == rv);
6809 CU_ASSERT(0 == frame.hd.stream_id);
6810 CU_ASSERT(NGHTTP2_ORIGIN == frame.hd.type);
6811 CU_ASSERT(2 == origin.nov);
6812 CU_ASSERT(0 == memcmp(nghttp2, origin.ov[0].origin, sizeof(nghttp2) - 1));
6813 CU_ASSERT(sizeof(nghttp2) - 1 == origin.ov[0].origin_len);
6814 CU_ASSERT(0 == memcmp(examples, origin.ov[1].origin, sizeof(examples) - 1));
6815 CU_ASSERT(sizeof(examples) - 1 == origin.ov[1].origin_len);
6816
6817 nghttp2_frame_origin_free(&frame.ext, mem);
6818
6819 nghttp2_session_del(session);
6820
6821 /* Submitting ORIGIN frame from client session is error */
6822 nghttp2_session_client_new(&session, &callbacks, NULL);
6823
6824 rv = nghttp2_submit_origin(session, NGHTTP2_FLAG_NONE, ov, 1);
6825
6826 CU_ASSERT(NGHTTP2_ERR_INVALID_STATE == rv);
6827
6828 nghttp2_session_del(session);
6829
6830 /* Submitting empty ORIGIN frame */
6831 nghttp2_session_server_new(&session, &callbacks, &ud);
6832
6833 rv = nghttp2_submit_origin(session, NGHTTP2_FLAG_NONE, NULL, 0);
6834
6835 CU_ASSERT(0 == rv);
6836
6837 ud.frame_send_cb_called = 0;
6838 len = nghttp2_session_mem_send(session, &data);
6839
6840 CU_ASSERT(len == NGHTTP2_FRAME_HDLEN);
6841 CU_ASSERT(1 == ud.frame_send_cb_called);
6842
6843 nghttp2_frame_unpack_frame_hd(&frame.hd, data);
6844
6845 CU_ASSERT(NGHTTP2_ORIGIN == frame.hd.type);
6846
6847 nghttp2_session_del(session);
6848 }
6849
test_nghttp2_submit_priority_update(void)6850 void test_nghttp2_submit_priority_update(void) {
6851 nghttp2_session *session;
6852 nghttp2_session_callbacks callbacks;
6853 const uint8_t field_value[] = "i";
6854 my_user_data ud;
6855 const uint8_t *data;
6856 int rv;
6857 nghttp2_frame frame;
6858 nghttp2_ext_priority_update priority_update;
6859 ssize_t len;
6860 int32_t stream_id;
6861
6862 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6863 callbacks.on_frame_send_callback = on_frame_send_callback;
6864
6865 nghttp2_session_client_new(&session, &callbacks, &ud);
6866
6867 session->pending_no_rfc7540_priorities = 1;
6868
6869 stream_id =
6870 nghttp2_submit_request(session, NULL, reqnv, ARRLEN(reqnv), NULL, NULL);
6871
6872 CU_ASSERT(1 == stream_id);
6873
6874 len = nghttp2_session_mem_send(session, &data);
6875
6876 CU_ASSERT(len > 0);
6877
6878 rv = nghttp2_submit_priority_update(session, NGHTTP2_FLAG_NONE, stream_id,
6879 field_value, sizeof(field_value) - 1);
6880
6881 CU_ASSERT(0 == rv);
6882
6883 frame.ext.payload = &priority_update;
6884
6885 ud.frame_send_cb_called = 0;
6886 len = nghttp2_session_mem_send(session, &data);
6887
6888 CU_ASSERT(len > 0);
6889 CU_ASSERT(1 == ud.frame_send_cb_called);
6890
6891 nghttp2_frame_unpack_frame_hd(&frame.hd, data);
6892 nghttp2_frame_unpack_priority_update_payload(
6893 &frame.ext, (uint8_t *)(data + NGHTTP2_FRAME_HDLEN),
6894 (size_t)len - NGHTTP2_FRAME_HDLEN);
6895
6896 CU_ASSERT(0 == frame.hd.stream_id);
6897 CU_ASSERT(NGHTTP2_PRIORITY_UPDATE == frame.hd.type);
6898 CU_ASSERT(stream_id == priority_update.stream_id);
6899 CU_ASSERT(sizeof(field_value) - 1 == priority_update.field_value_len);
6900 CU_ASSERT(0 == memcmp(field_value, priority_update.field_value,
6901 sizeof(field_value) - 1));
6902
6903 nghttp2_session_del(session);
6904
6905 /* Submitting PRIORITY_UPDATE frame from server session is error */
6906 nghttp2_session_server_new(&session, &callbacks, &ud);
6907
6908 open_recv_stream(session, 1);
6909
6910 rv = nghttp2_submit_priority_update(session, NGHTTP2_FLAG_NONE, 1,
6911 field_value, sizeof(field_value) - 1);
6912
6913 CU_ASSERT(NGHTTP2_ERR_INVALID_STATE == rv);
6914
6915 nghttp2_session_del(session);
6916
6917 /* Submitting PRIORITY_UPDATE with empty field_value */
6918 nghttp2_session_client_new(&session, &callbacks, &ud);
6919
6920 stream_id =
6921 nghttp2_submit_request(session, NULL, reqnv, ARRLEN(reqnv), NULL, NULL);
6922
6923 CU_ASSERT(1 == stream_id);
6924
6925 len = nghttp2_session_mem_send(session, &data);
6926
6927 CU_ASSERT(len > 0);
6928
6929 rv = nghttp2_submit_priority_update(session, NGHTTP2_FLAG_NONE, stream_id,
6930 NULL, 0);
6931
6932 CU_ASSERT(0 == rv);
6933
6934 frame.ext.payload = &priority_update;
6935
6936 len = nghttp2_session_mem_send(session, &data);
6937
6938 CU_ASSERT(len > 0);
6939
6940 nghttp2_frame_unpack_frame_hd(&frame.hd, data);
6941 nghttp2_frame_unpack_priority_update_payload(
6942 &frame.ext, (uint8_t *)(data + NGHTTP2_FRAME_HDLEN),
6943 (size_t)len - NGHTTP2_FRAME_HDLEN);
6944
6945 CU_ASSERT(0 == frame.hd.stream_id);
6946 CU_ASSERT(NGHTTP2_PRIORITY_UPDATE == frame.hd.type);
6947 CU_ASSERT(stream_id == priority_update.stream_id);
6948 CU_ASSERT(0 == priority_update.field_value_len);
6949 CU_ASSERT(NULL == priority_update.field_value);
6950
6951 nghttp2_session_del(session);
6952 }
6953
test_nghttp2_submit_rst_stream(void)6954 void test_nghttp2_submit_rst_stream(void) {
6955 nghttp2_session *session;
6956 nghttp2_session_callbacks callbacks;
6957 nghttp2_outbound_item *item;
6958 int rv;
6959 int32_t stream_id;
6960
6961 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6962
6963 /* Sending RST_STREAM to idle stream (local) is ignored */
6964 nghttp2_session_client_new(&session, &callbacks, NULL);
6965
6966 rv = nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, 1,
6967 NGHTTP2_NO_ERROR);
6968
6969 CU_ASSERT(0 == rv);
6970
6971 item = nghttp2_outbound_queue_top(&session->ob_reg);
6972
6973 CU_ASSERT(NULL == item);
6974
6975 nghttp2_session_del(session);
6976
6977 /* Sending RST_STREAM to idle stream (remote) is ignored */
6978 nghttp2_session_client_new(&session, &callbacks, NULL);
6979
6980 rv = nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, 2,
6981 NGHTTP2_NO_ERROR);
6982
6983 CU_ASSERT(0 == rv);
6984
6985 item = nghttp2_outbound_queue_top(&session->ob_reg);
6986
6987 CU_ASSERT(NULL == item);
6988
6989 nghttp2_session_del(session);
6990
6991 /* Sending RST_STREAM to non-idle stream (local) */
6992 nghttp2_session_client_new(&session, &callbacks, NULL);
6993
6994 open_sent_stream(session, 1);
6995
6996 rv = nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, 1,
6997 NGHTTP2_NO_ERROR);
6998
6999 CU_ASSERT(0 == rv);
7000
7001 item = nghttp2_outbound_queue_top(&session->ob_reg);
7002
7003 CU_ASSERT(NULL != item);
7004 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
7005 CU_ASSERT(1 == item->frame.hd.stream_id);
7006
7007 nghttp2_session_del(session);
7008
7009 /* Sending RST_STREAM to non-idle stream (remote) */
7010 nghttp2_session_client_new(&session, &callbacks, NULL);
7011
7012 open_recv_stream(session, 2);
7013
7014 rv = nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, 2,
7015 NGHTTP2_NO_ERROR);
7016
7017 CU_ASSERT(0 == rv);
7018
7019 item = nghttp2_outbound_queue_top(&session->ob_reg);
7020
7021 CU_ASSERT(NULL != item);
7022 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
7023 CU_ASSERT(2 == item->frame.hd.stream_id);
7024
7025 nghttp2_session_del(session);
7026
7027 /* Sending RST_STREAM to pending stream */
7028 nghttp2_session_client_new(&session, &callbacks, NULL);
7029
7030 stream_id =
7031 nghttp2_submit_request(session, NULL, reqnv, ARRLEN(reqnv), NULL, NULL);
7032
7033 CU_ASSERT(stream_id > 0);
7034
7035 item = nghttp2_outbound_queue_top(&session->ob_syn);
7036
7037 CU_ASSERT(NULL != item);
7038 CU_ASSERT(NGHTTP2_HEADERS == item->frame.hd.type);
7039 CU_ASSERT(0 == item->aux_data.headers.canceled);
7040
7041 rv = nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, stream_id,
7042 NGHTTP2_NO_ERROR);
7043
7044 CU_ASSERT(0 == rv);
7045
7046 item = nghttp2_outbound_queue_top(&session->ob_syn);
7047
7048 CU_ASSERT(NULL != item);
7049 CU_ASSERT(NGHTTP2_HEADERS == item->frame.hd.type);
7050 CU_ASSERT(1 == item->aux_data.headers.canceled);
7051
7052 nghttp2_session_del(session);
7053 }
7054
test_nghttp2_session_open_stream(void)7055 void test_nghttp2_session_open_stream(void) {
7056 nghttp2_session *session;
7057 nghttp2_session_callbacks callbacks;
7058 nghttp2_stream *stream;
7059 nghttp2_priority_spec pri_spec;
7060
7061 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7062 nghttp2_session_server_new(&session, &callbacks, NULL);
7063
7064 nghttp2_priority_spec_init(&pri_spec, 0, 245, 0);
7065
7066 stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
7067 &pri_spec, NGHTTP2_STREAM_OPENED, NULL);
7068 CU_ASSERT(1 == session->num_incoming_streams);
7069 CU_ASSERT(0 == session->num_outgoing_streams);
7070 CU_ASSERT(NGHTTP2_STREAM_OPENED == stream->state);
7071 CU_ASSERT(245 == stream->weight);
7072 CU_ASSERT(&session->root == stream->dep_prev);
7073 CU_ASSERT(NGHTTP2_SHUT_NONE == stream->shut_flags);
7074
7075 stream = nghttp2_session_open_stream(session, 2, NGHTTP2_STREAM_FLAG_NONE,
7076 &pri_spec_default,
7077 NGHTTP2_STREAM_OPENING, NULL);
7078 CU_ASSERT(1 == session->num_incoming_streams);
7079 CU_ASSERT(1 == session->num_outgoing_streams);
7080 CU_ASSERT(&session->root == stream->dep_prev);
7081 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == stream->weight);
7082 CU_ASSERT(NGHTTP2_SHUT_NONE == stream->shut_flags);
7083
7084 stream = nghttp2_session_open_stream(session, 4, NGHTTP2_STREAM_FLAG_NONE,
7085 &pri_spec_default,
7086 NGHTTP2_STREAM_RESERVED, NULL);
7087 CU_ASSERT(1 == session->num_incoming_streams);
7088 CU_ASSERT(1 == session->num_outgoing_streams);
7089 CU_ASSERT(&session->root == stream->dep_prev);
7090 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == stream->weight);
7091 CU_ASSERT(NGHTTP2_SHUT_RD == stream->shut_flags);
7092
7093 nghttp2_priority_spec_init(&pri_spec, 1, 17, 1);
7094
7095 stream = nghttp2_session_open_stream(session, 3, NGHTTP2_STREAM_FLAG_NONE,
7096 &pri_spec, NGHTTP2_STREAM_OPENED, NULL);
7097 CU_ASSERT(17 == stream->weight);
7098 CU_ASSERT(1 == stream->dep_prev->stream_id);
7099
7100 /* Dependency to idle stream */
7101 nghttp2_priority_spec_init(&pri_spec, 1000000007, 240, 1);
7102
7103 stream = nghttp2_session_open_stream(session, 5, NGHTTP2_STREAM_FLAG_NONE,
7104 &pri_spec, NGHTTP2_STREAM_OPENED, NULL);
7105 CU_ASSERT(240 == stream->weight);
7106 CU_ASSERT(1000000007 == stream->dep_prev->stream_id);
7107
7108 stream = nghttp2_session_get_stream_raw(session, 1000000007);
7109
7110 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == stream->weight);
7111 CU_ASSERT(&session->root == stream->dep_prev);
7112
7113 /* Dependency to closed stream which is not in dependency tree */
7114 session->last_recv_stream_id = 7;
7115
7116 nghttp2_priority_spec_init(&pri_spec, 7, 10, 0);
7117
7118 stream = nghttp2_session_open_stream(session, 9, NGHTTP2_FLAG_NONE, &pri_spec,
7119 NGHTTP2_STREAM_OPENED, NULL);
7120
7121 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == stream->weight);
7122 CU_ASSERT(&session->root == stream->dep_prev);
7123
7124 nghttp2_session_del(session);
7125
7126 nghttp2_session_client_new(&session, &callbacks, NULL);
7127 stream = nghttp2_session_open_stream(session, 4, NGHTTP2_STREAM_FLAG_NONE,
7128 &pri_spec_default,
7129 NGHTTP2_STREAM_RESERVED, NULL);
7130 CU_ASSERT(0 == session->num_incoming_streams);
7131 CU_ASSERT(0 == session->num_outgoing_streams);
7132 CU_ASSERT(&session->root == stream->dep_prev);
7133 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == stream->weight);
7134 CU_ASSERT(NGHTTP2_SHUT_WR == stream->shut_flags);
7135
7136 nghttp2_session_del(session);
7137 }
7138
test_nghttp2_session_open_stream_with_idle_stream_dep(void)7139 void test_nghttp2_session_open_stream_with_idle_stream_dep(void) {
7140 nghttp2_session *session;
7141 nghttp2_session_callbacks callbacks;
7142 nghttp2_stream *stream;
7143 nghttp2_priority_spec pri_spec;
7144
7145 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7146 nghttp2_session_server_new(&session, &callbacks, NULL);
7147
7148 /* Dependency to idle stream */
7149 nghttp2_priority_spec_init(&pri_spec, 101, 245, 0);
7150
7151 stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
7152 &pri_spec, NGHTTP2_STREAM_OPENED, NULL);
7153
7154 CU_ASSERT(245 == stream->weight);
7155 CU_ASSERT(101 == stream->dep_prev->stream_id);
7156
7157 stream = nghttp2_session_get_stream_raw(session, 101);
7158
7159 CU_ASSERT(NGHTTP2_STREAM_IDLE == stream->state);
7160 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == stream->weight);
7161
7162 nghttp2_priority_spec_init(&pri_spec, 211, 1, 0);
7163
7164 /* stream 101 was already created as idle. */
7165 stream = nghttp2_session_open_stream(session, 101, NGHTTP2_STREAM_FLAG_NONE,
7166 &pri_spec, NGHTTP2_STREAM_OPENED, NULL);
7167
7168 CU_ASSERT(1 == stream->weight);
7169 CU_ASSERT(211 == stream->dep_prev->stream_id);
7170
7171 stream = nghttp2_session_get_stream_raw(session, 211);
7172
7173 CU_ASSERT(NGHTTP2_STREAM_IDLE == stream->state);
7174 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == stream->weight);
7175
7176 nghttp2_session_del(session);
7177 }
7178
test_nghttp2_session_get_next_ob_item(void)7179 void test_nghttp2_session_get_next_ob_item(void) {
7180 nghttp2_session *session;
7181 nghttp2_session_callbacks callbacks;
7182 nghttp2_priority_spec pri_spec;
7183
7184 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7185 callbacks.send_callback = null_send_callback;
7186
7187 nghttp2_session_client_new(&session, &callbacks, NULL);
7188 session->remote_settings.max_concurrent_streams = 2;
7189
7190 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
7191 nghttp2_submit_ping(session, NGHTTP2_FLAG_NONE, NULL);
7192 CU_ASSERT(NGHTTP2_PING ==
7193 nghttp2_session_get_next_ob_item(session)->frame.hd.type);
7194
7195 CU_ASSERT(1 == nghttp2_submit_request(session, NULL, NULL, 0, NULL, NULL));
7196 CU_ASSERT(NGHTTP2_PING ==
7197 nghttp2_session_get_next_ob_item(session)->frame.hd.type);
7198
7199 CU_ASSERT(0 == nghttp2_session_send(session));
7200 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
7201
7202 /* Incoming stream does not affect the number of outgoing max
7203 concurrent streams. */
7204 open_recv_stream(session, 2);
7205
7206 nghttp2_priority_spec_init(&pri_spec, 0, NGHTTP2_MAX_WEIGHT, 0);
7207
7208 CU_ASSERT(3 ==
7209 nghttp2_submit_request(session, &pri_spec, NULL, 0, NULL, NULL));
7210 CU_ASSERT(NGHTTP2_HEADERS ==
7211 nghttp2_session_get_next_ob_item(session)->frame.hd.type);
7212 CU_ASSERT(0 == nghttp2_session_send(session));
7213
7214 CU_ASSERT(5 ==
7215 nghttp2_submit_request(session, &pri_spec, NULL, 0, NULL, NULL));
7216 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
7217
7218 session->remote_settings.max_concurrent_streams = 3;
7219
7220 CU_ASSERT(NGHTTP2_HEADERS ==
7221 nghttp2_session_get_next_ob_item(session)->frame.hd.type);
7222
7223 nghttp2_session_del(session);
7224
7225 /* Check that push reply HEADERS are queued into ob_ss_pq */
7226 nghttp2_session_server_new(&session, &callbacks, NULL);
7227 session->remote_settings.max_concurrent_streams = 0;
7228 open_sent_stream2(session, 2, NGHTTP2_STREAM_RESERVED);
7229 CU_ASSERT(0 == nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, 2,
7230 NULL, NULL, 0, NULL));
7231 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
7232 CU_ASSERT(1 == nghttp2_outbound_queue_size(&session->ob_syn));
7233 nghttp2_session_del(session);
7234 }
7235
test_nghttp2_session_pop_next_ob_item(void)7236 void test_nghttp2_session_pop_next_ob_item(void) {
7237 nghttp2_session *session;
7238 nghttp2_session_callbacks callbacks;
7239 nghttp2_outbound_item *item;
7240 nghttp2_priority_spec pri_spec;
7241 nghttp2_mem *mem;
7242
7243 mem = nghttp2_mem_default();
7244 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7245 callbacks.send_callback = null_send_callback;
7246
7247 nghttp2_session_client_new(&session, &callbacks, NULL);
7248 session->remote_settings.max_concurrent_streams = 1;
7249
7250 CU_ASSERT(NULL == nghttp2_session_pop_next_ob_item(session));
7251
7252 nghttp2_submit_ping(session, NGHTTP2_FLAG_NONE, NULL);
7253
7254 nghttp2_priority_spec_init(&pri_spec, 0, 254, 0);
7255
7256 nghttp2_submit_request(session, &pri_spec, NULL, 0, NULL, NULL);
7257
7258 item = nghttp2_session_pop_next_ob_item(session);
7259 CU_ASSERT(NGHTTP2_PING == item->frame.hd.type);
7260 nghttp2_outbound_item_free(item, mem);
7261 mem->free(item, NULL);
7262
7263 item = nghttp2_session_pop_next_ob_item(session);
7264 CU_ASSERT(NGHTTP2_HEADERS == item->frame.hd.type);
7265 nghttp2_outbound_item_free(item, mem);
7266 mem->free(item, NULL);
7267
7268 CU_ASSERT(NULL == nghttp2_session_pop_next_ob_item(session));
7269
7270 /* Incoming stream does not affect the number of outgoing max
7271 concurrent streams. */
7272 open_recv_stream(session, 4);
7273 /* In-flight outgoing stream */
7274 open_sent_stream(session, 1);
7275
7276 nghttp2_priority_spec_init(&pri_spec, 0, NGHTTP2_MAX_WEIGHT, 0);
7277
7278 nghttp2_submit_request(session, &pri_spec, NULL, 0, NULL, NULL);
7279
7280 CU_ASSERT(NULL == nghttp2_session_pop_next_ob_item(session));
7281
7282 session->remote_settings.max_concurrent_streams = 2;
7283
7284 item = nghttp2_session_pop_next_ob_item(session);
7285 CU_ASSERT(NGHTTP2_HEADERS == item->frame.hd.type);
7286 nghttp2_outbound_item_free(item, mem);
7287 mem->free(item, NULL);
7288
7289 nghttp2_session_del(session);
7290
7291 /* Check that push reply HEADERS are queued into ob_ss_pq */
7292 nghttp2_session_server_new(&session, &callbacks, NULL);
7293 session->remote_settings.max_concurrent_streams = 0;
7294 open_sent_stream2(session, 2, NGHTTP2_STREAM_RESERVED);
7295 CU_ASSERT(0 == nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, 2,
7296 NULL, NULL, 0, NULL));
7297 CU_ASSERT(NULL == nghttp2_session_pop_next_ob_item(session));
7298 CU_ASSERT(1 == nghttp2_outbound_queue_size(&session->ob_syn));
7299 nghttp2_session_del(session);
7300 }
7301
test_nghttp2_session_reply_fail(void)7302 void test_nghttp2_session_reply_fail(void) {
7303 nghttp2_session *session;
7304 nghttp2_session_callbacks callbacks;
7305 nghttp2_data_provider data_prd;
7306 my_user_data ud;
7307
7308 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7309 callbacks.send_callback = fail_send_callback;
7310
7311 data_prd.read_callback = fixed_length_data_source_read_callback;
7312 ud.data_source_length = 4 * 1024;
7313 CU_ASSERT(0 == nghttp2_session_server_new(&session, &callbacks, &ud));
7314 open_recv_stream2(session, 1, NGHTTP2_STREAM_OPENING);
7315 CU_ASSERT(0 == nghttp2_submit_response(session, 1, NULL, 0, &data_prd));
7316 CU_ASSERT(NGHTTP2_ERR_CALLBACK_FAILURE == nghttp2_session_send(session));
7317 nghttp2_session_del(session);
7318 }
7319
test_nghttp2_session_max_concurrent_streams(void)7320 void test_nghttp2_session_max_concurrent_streams(void) {
7321 nghttp2_session *session;
7322 nghttp2_session_callbacks callbacks;
7323 nghttp2_frame frame;
7324 nghttp2_outbound_item *item;
7325 nghttp2_mem *mem;
7326
7327 mem = nghttp2_mem_default();
7328 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7329 callbacks.send_callback = null_send_callback;
7330
7331 nghttp2_session_server_new(&session, &callbacks, NULL);
7332 open_recv_stream(session, 1);
7333
7334 /* Check un-ACKed SETTINGS_MAX_CONCURRENT_STREAMS */
7335 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 3,
7336 NGHTTP2_HCAT_HEADERS, NULL, NULL, 0);
7337 session->pending_local_max_concurrent_stream = 1;
7338
7339 CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
7340 nghttp2_session_on_request_headers_received(session, &frame));
7341
7342 item = nghttp2_outbound_queue_top(&session->ob_reg);
7343 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
7344 CU_ASSERT(NGHTTP2_REFUSED_STREAM == item->frame.rst_stream.error_code);
7345
7346 CU_ASSERT(0 == nghttp2_session_send(session));
7347
7348 /* Check ACKed SETTINGS_MAX_CONCURRENT_STREAMS */
7349 session->local_settings.max_concurrent_streams = 1;
7350 frame.hd.stream_id = 5;
7351
7352 CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
7353 nghttp2_session_on_request_headers_received(session, &frame));
7354
7355 item = nghttp2_outbound_queue_top(&session->ob_reg);
7356 CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
7357 CU_ASSERT(NGHTTP2_PROTOCOL_ERROR == item->frame.goaway.error_code);
7358
7359 nghttp2_frame_headers_free(&frame.headers, mem);
7360 nghttp2_session_del(session);
7361 }
7362
test_nghttp2_session_stop_data_with_rst_stream(void)7363 void test_nghttp2_session_stop_data_with_rst_stream(void) {
7364 nghttp2_session *session;
7365 nghttp2_session_callbacks callbacks;
7366 my_user_data ud;
7367 nghttp2_data_provider data_prd;
7368 nghttp2_frame frame;
7369
7370 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7371 callbacks.on_frame_send_callback = on_frame_send_callback;
7372 callbacks.send_callback = block_count_send_callback;
7373 data_prd.read_callback = fixed_length_data_source_read_callback;
7374
7375 ud.frame_send_cb_called = 0;
7376 ud.data_source_length = NGHTTP2_DATA_PAYLOADLEN * 4;
7377
7378 nghttp2_session_server_new(&session, &callbacks, &ud);
7379 open_recv_stream2(session, 1, NGHTTP2_STREAM_OPENING);
7380 nghttp2_submit_response(session, 1, NULL, 0, &data_prd);
7381
7382 ud.block_count = 2;
7383 /* Sends response HEADERS + DATA[0] */
7384 CU_ASSERT(0 == nghttp2_session_send(session));
7385 CU_ASSERT(NGHTTP2_DATA == ud.sent_frame_type);
7386 /* data for DATA[1] is read from data_prd but it is not sent */
7387 CU_ASSERT(ud.data_source_length == NGHTTP2_DATA_PAYLOADLEN * 2);
7388
7389 nghttp2_frame_rst_stream_init(&frame.rst_stream, 1, NGHTTP2_CANCEL);
7390 CU_ASSERT(0 == nghttp2_session_on_rst_stream_received(session, &frame));
7391 nghttp2_frame_rst_stream_free(&frame.rst_stream);
7392
7393 /* Big enough number to send all DATA frames potentially. */
7394 ud.block_count = 100;
7395 /* Nothing will be sent in the following call. */
7396 CU_ASSERT(0 == nghttp2_session_send(session));
7397 /* With RST_STREAM, stream is canceled and further DATA on that
7398 stream are not sent. */
7399 CU_ASSERT(ud.data_source_length == NGHTTP2_DATA_PAYLOADLEN * 2);
7400
7401 CU_ASSERT(NULL == nghttp2_session_get_stream(session, 1));
7402
7403 nghttp2_session_del(session);
7404 }
7405
test_nghttp2_session_defer_data(void)7406 void test_nghttp2_session_defer_data(void) {
7407 nghttp2_session *session;
7408 nghttp2_session_callbacks callbacks;
7409 my_user_data ud;
7410 nghttp2_data_provider data_prd;
7411 nghttp2_outbound_item *item;
7412 nghttp2_stream *stream;
7413
7414 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7415 callbacks.on_frame_send_callback = on_frame_send_callback;
7416 callbacks.send_callback = block_count_send_callback;
7417 data_prd.read_callback = defer_data_source_read_callback;
7418
7419 ud.frame_send_cb_called = 0;
7420 ud.data_source_length = NGHTTP2_DATA_PAYLOADLEN * 4;
7421
7422 nghttp2_session_server_new(&session, &callbacks, &ud);
7423 stream = open_recv_stream2(session, 1, NGHTTP2_STREAM_OPENING);
7424
7425 session->remote_window_size = 1 << 20;
7426 stream->remote_window_size = 1 << 20;
7427
7428 nghttp2_submit_response(session, 1, NULL, 0, &data_prd);
7429
7430 ud.block_count = 1;
7431 /* Sends HEADERS reply */
7432 CU_ASSERT(0 == nghttp2_session_send(session));
7433 CU_ASSERT(NGHTTP2_HEADERS == ud.sent_frame_type);
7434 /* No data is read */
7435 CU_ASSERT(ud.data_source_length == NGHTTP2_DATA_PAYLOADLEN * 4);
7436
7437 ud.block_count = 1;
7438 nghttp2_submit_ping(session, NGHTTP2_FLAG_NONE, NULL);
7439 /* Sends PING */
7440 CU_ASSERT(0 == nghttp2_session_send(session));
7441 CU_ASSERT(NGHTTP2_PING == ud.sent_frame_type);
7442
7443 /* Resume deferred DATA */
7444 CU_ASSERT(0 == nghttp2_session_resume_data(session, 1));
7445 item = stream->item;
7446 item->aux_data.data.data_prd.read_callback =
7447 fixed_length_data_source_read_callback;
7448 ud.block_count = 1;
7449 /* Reads 2 DATA chunks */
7450 CU_ASSERT(0 == nghttp2_session_send(session));
7451 CU_ASSERT(ud.data_source_length == NGHTTP2_DATA_PAYLOADLEN * 2);
7452
7453 /* Deferred again */
7454 item->aux_data.data.data_prd.read_callback = defer_data_source_read_callback;
7455 /* This is needed since 16KiB block is already read and waiting to be
7456 sent. No read_callback invocation. */
7457 ud.block_count = 1;
7458 CU_ASSERT(0 == nghttp2_session_send(session));
7459 CU_ASSERT(ud.data_source_length == NGHTTP2_DATA_PAYLOADLEN * 2);
7460
7461 /* Resume deferred DATA */
7462 CU_ASSERT(0 == nghttp2_session_resume_data(session, 1));
7463 item->aux_data.data.data_prd.read_callback =
7464 fixed_length_data_source_read_callback;
7465 ud.block_count = 1;
7466 /* Reads 2 16KiB blocks */
7467 CU_ASSERT(0 == nghttp2_session_send(session));
7468 CU_ASSERT(ud.data_source_length == 0);
7469
7470 nghttp2_session_del(session);
7471 }
7472
test_nghttp2_session_flow_control(void)7473 void test_nghttp2_session_flow_control(void) {
7474 nghttp2_session *session;
7475 nghttp2_session_callbacks callbacks;
7476 my_user_data ud;
7477 nghttp2_data_provider data_prd;
7478 nghttp2_frame frame;
7479 nghttp2_stream *stream;
7480 int32_t new_initial_window_size;
7481 nghttp2_settings_entry iv[1];
7482 nghttp2_frame settings_frame;
7483 nghttp2_mem *mem;
7484
7485 mem = nghttp2_mem_default();
7486 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7487 callbacks.send_callback = fixed_bytes_send_callback;
7488 callbacks.on_frame_send_callback = on_frame_send_callback;
7489 data_prd.read_callback = fixed_length_data_source_read_callback;
7490
7491 ud.frame_send_cb_called = 0;
7492 ud.data_source_length = 128 * 1024;
7493 /* Use smaller emission count so that we can check outbound flow
7494 control window calculation is correct. */
7495 ud.fixed_sendlen = 2 * 1024;
7496
7497 /* Initial window size to 64KiB - 1*/
7498 nghttp2_session_client_new(&session, &callbacks, &ud);
7499 /* Change it to 64KiB for easy calculation */
7500 session->remote_window_size = 64 * 1024;
7501 session->remote_settings.initial_window_size = 64 * 1024;
7502
7503 nghttp2_submit_request(session, NULL, NULL, 0, &data_prd, NULL);
7504
7505 /* Sends 64KiB - 1 data */
7506 CU_ASSERT(0 == nghttp2_session_send(session));
7507 CU_ASSERT(64 * 1024 == ud.data_source_length);
7508
7509 /* Back 32KiB in stream window */
7510 nghttp2_frame_window_update_init(&frame.window_update, NGHTTP2_FLAG_NONE, 1,
7511 32 * 1024);
7512 nghttp2_session_on_window_update_received(session, &frame);
7513
7514 /* Send nothing because of connection-level window */
7515 CU_ASSERT(0 == nghttp2_session_send(session));
7516 CU_ASSERT(64 * 1024 == ud.data_source_length);
7517
7518 /* Back 32KiB in connection-level window */
7519 frame.hd.stream_id = 0;
7520 nghttp2_session_on_window_update_received(session, &frame);
7521
7522 /* Sends another 32KiB data */
7523 CU_ASSERT(0 == nghttp2_session_send(session));
7524 CU_ASSERT(32 * 1024 == ud.data_source_length);
7525
7526 stream = nghttp2_session_get_stream(session, 1);
7527 /* Change initial window size to 16KiB. The window_size becomes
7528 negative. */
7529 new_initial_window_size = 16 * 1024;
7530 stream->remote_window_size =
7531 new_initial_window_size -
7532 ((int32_t)session->remote_settings.initial_window_size -
7533 stream->remote_window_size);
7534 session->remote_settings.initial_window_size =
7535 (uint32_t)new_initial_window_size;
7536 CU_ASSERT(-48 * 1024 == stream->remote_window_size);
7537
7538 /* Back 48KiB to stream window */
7539 frame.hd.stream_id = 1;
7540 frame.window_update.window_size_increment = 48 * 1024;
7541 nghttp2_session_on_window_update_received(session, &frame);
7542
7543 /* Nothing is sent because window_size is 0 */
7544 CU_ASSERT(0 == nghttp2_session_send(session));
7545 CU_ASSERT(32 * 1024 == ud.data_source_length);
7546
7547 /* Back 16KiB in stream window */
7548 frame.hd.stream_id = 1;
7549 frame.window_update.window_size_increment = 16 * 1024;
7550 nghttp2_session_on_window_update_received(session, &frame);
7551
7552 /* Back 24KiB in connection-level window */
7553 frame.hd.stream_id = 0;
7554 frame.window_update.window_size_increment = 24 * 1024;
7555 nghttp2_session_on_window_update_received(session, &frame);
7556
7557 /* Sends another 16KiB data */
7558 CU_ASSERT(0 == nghttp2_session_send(session));
7559 CU_ASSERT(16 * 1024 == ud.data_source_length);
7560
7561 /* Increase initial window size to 32KiB */
7562 iv[0].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
7563 iv[0].value = 32 * 1024;
7564
7565 nghttp2_frame_settings_init(&settings_frame.settings, NGHTTP2_FLAG_NONE,
7566 dup_iv(iv, 1), 1);
7567 nghttp2_session_on_settings_received(session, &settings_frame, 1);
7568 nghttp2_frame_settings_free(&settings_frame.settings, mem);
7569
7570 /* Sends another 8KiB data */
7571 CU_ASSERT(0 == nghttp2_session_send(session));
7572 CU_ASSERT(8 * 1024 == ud.data_source_length);
7573
7574 /* Back 8KiB in connection-level window */
7575 frame.hd.stream_id = 0;
7576 frame.window_update.window_size_increment = 8 * 1024;
7577 nghttp2_session_on_window_update_received(session, &frame);
7578
7579 /* Sends last 8KiB data */
7580 CU_ASSERT(0 == nghttp2_session_send(session));
7581 CU_ASSERT(0 == ud.data_source_length);
7582 CU_ASSERT(nghttp2_session_get_stream(session, 1)->shut_flags &
7583 NGHTTP2_SHUT_WR);
7584
7585 nghttp2_frame_window_update_free(&frame.window_update);
7586 nghttp2_session_del(session);
7587 }
7588
test_nghttp2_session_flow_control_data_recv(void)7589 void test_nghttp2_session_flow_control_data_recv(void) {
7590 nghttp2_session *session;
7591 nghttp2_session_callbacks callbacks;
7592 uint8_t data[64 * 1024 + 16];
7593 nghttp2_frame_hd hd;
7594 nghttp2_outbound_item *item;
7595 nghttp2_stream *stream;
7596
7597 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7598 callbacks.send_callback = null_send_callback;
7599
7600 /* Initial window size to 64KiB - 1*/
7601 nghttp2_session_client_new(&session, &callbacks, NULL);
7602
7603 stream = open_sent_stream(session, 1);
7604
7605 nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_WR);
7606
7607 session->local_window_size = NGHTTP2_MAX_PAYLOADLEN;
7608 stream->local_window_size = NGHTTP2_MAX_PAYLOADLEN;
7609
7610 /* Create DATA frame */
7611 memset(data, 0, sizeof(data));
7612 nghttp2_frame_hd_init(&hd, NGHTTP2_MAX_PAYLOADLEN, NGHTTP2_DATA,
7613 NGHTTP2_FLAG_END_STREAM, 1);
7614
7615 nghttp2_frame_pack_frame_hd(data, &hd);
7616 CU_ASSERT(NGHTTP2_MAX_PAYLOADLEN + NGHTTP2_FRAME_HDLEN ==
7617 nghttp2_session_mem_recv(
7618 session, data, NGHTTP2_MAX_PAYLOADLEN + NGHTTP2_FRAME_HDLEN));
7619
7620 item = nghttp2_session_get_next_ob_item(session);
7621 /* Since this is the last frame, stream-level WINDOW_UPDATE is not
7622 issued, but connection-level is. */
7623 CU_ASSERT(NGHTTP2_WINDOW_UPDATE == item->frame.hd.type);
7624 CU_ASSERT(0 == item->frame.hd.stream_id);
7625 CU_ASSERT(NGHTTP2_MAX_PAYLOADLEN ==
7626 item->frame.window_update.window_size_increment);
7627
7628 CU_ASSERT(0 == nghttp2_session_send(session));
7629
7630 /* Receive DATA for closed stream. They are still subject to under
7631 connection-level flow control, since this situation arises when
7632 RST_STREAM is issued by the remote, but the local side keeps
7633 sending DATA frames. Without calculating connection-level window,
7634 the subsequent flow control gets confused. */
7635 CU_ASSERT(NGHTTP2_MAX_PAYLOADLEN + NGHTTP2_FRAME_HDLEN ==
7636 nghttp2_session_mem_recv(
7637 session, data, NGHTTP2_MAX_PAYLOADLEN + NGHTTP2_FRAME_HDLEN));
7638
7639 item = nghttp2_session_get_next_ob_item(session);
7640 CU_ASSERT(NGHTTP2_WINDOW_UPDATE == item->frame.hd.type);
7641 CU_ASSERT(0 == item->frame.hd.stream_id);
7642 CU_ASSERT(NGHTTP2_MAX_PAYLOADLEN ==
7643 item->frame.window_update.window_size_increment);
7644
7645 nghttp2_session_del(session);
7646 }
7647
test_nghttp2_session_flow_control_data_with_padding_recv(void)7648 void test_nghttp2_session_flow_control_data_with_padding_recv(void) {
7649 nghttp2_session *session;
7650 nghttp2_session_callbacks callbacks;
7651 uint8_t data[1024];
7652 nghttp2_frame_hd hd;
7653 nghttp2_stream *stream;
7654 nghttp2_option *option;
7655
7656 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7657 callbacks.send_callback = null_send_callback;
7658
7659 nghttp2_option_new(&option);
7660 /* Disable auto window update so that we can check padding is
7661 consumed automatically */
7662 nghttp2_option_set_no_auto_window_update(option, 1);
7663
7664 /* Initial window size to 64KiB - 1*/
7665 nghttp2_session_client_new2(&session, &callbacks, NULL, option);
7666
7667 nghttp2_option_del(option);
7668
7669 stream = open_sent_stream(session, 1);
7670
7671 /* Create DATA frame */
7672 memset(data, 0, sizeof(data));
7673 nghttp2_frame_hd_init(&hd, 357, NGHTTP2_DATA, NGHTTP2_FLAG_PADDED, 1);
7674
7675 nghttp2_frame_pack_frame_hd(data, &hd);
7676 /* Set Pad Length field, which itself is padding */
7677 data[NGHTTP2_FRAME_HDLEN] = 255;
7678
7679 CU_ASSERT(
7680 (ssize_t)(NGHTTP2_FRAME_HDLEN + hd.length) ==
7681 nghttp2_session_mem_recv(session, data, NGHTTP2_FRAME_HDLEN + hd.length));
7682
7683 CU_ASSERT((int32_t)hd.length == session->recv_window_size);
7684 CU_ASSERT((int32_t)hd.length == stream->recv_window_size);
7685 CU_ASSERT(256 == session->consumed_size);
7686 CU_ASSERT(256 == stream->consumed_size);
7687 CU_ASSERT(357 == session->recv_window_size);
7688 CU_ASSERT(357 == stream->recv_window_size);
7689
7690 /* Receive the same DATA frame, but in 2 parts: first 9 + 1 + 102
7691 bytes which includes 1st padding byte, and remainder */
7692 CU_ASSERT((ssize_t)(NGHTTP2_FRAME_HDLEN + 103) ==
7693 nghttp2_session_mem_recv(session, data, NGHTTP2_FRAME_HDLEN + 103));
7694 CU_ASSERT(258 == session->consumed_size);
7695 CU_ASSERT(258 == stream->consumed_size);
7696 CU_ASSERT(460 == session->recv_window_size);
7697 CU_ASSERT(460 == stream->recv_window_size);
7698
7699 /* 357 - 103 = 254 bytes left */
7700 CU_ASSERT(254 == nghttp2_session_mem_recv(session, data, 254));
7701 CU_ASSERT(512 == session->consumed_size);
7702 CU_ASSERT(512 == stream->consumed_size);
7703 CU_ASSERT(714 == session->recv_window_size);
7704 CU_ASSERT(714 == stream->recv_window_size);
7705
7706 /* Receive the same DATA frame, but in 2 parts: first 9 = 1 + 101
7707 bytes which only includes data without padding, 2nd part is
7708 padding only */
7709 CU_ASSERT((ssize_t)(NGHTTP2_FRAME_HDLEN + 102) ==
7710 nghttp2_session_mem_recv(session, data, NGHTTP2_FRAME_HDLEN + 102));
7711 CU_ASSERT(513 == session->consumed_size);
7712 CU_ASSERT(513 == stream->consumed_size);
7713 CU_ASSERT(816 == session->recv_window_size);
7714 CU_ASSERT(816 == stream->recv_window_size);
7715
7716 /* 357 - 102 = 255 bytes left */
7717 CU_ASSERT(255 == nghttp2_session_mem_recv(session, data, 255));
7718 CU_ASSERT(768 == session->consumed_size);
7719 CU_ASSERT(768 == stream->consumed_size);
7720 CU_ASSERT(1071 == session->recv_window_size);
7721 CU_ASSERT(1071 == stream->recv_window_size);
7722
7723 /* Receive the same DATA frame, but in 2 parts: first 9 = 1 + 50
7724 bytes which includes byte up to middle of data, 2nd part is the
7725 remainder */
7726 CU_ASSERT((ssize_t)(NGHTTP2_FRAME_HDLEN + 51) ==
7727 nghttp2_session_mem_recv(session, data, NGHTTP2_FRAME_HDLEN + 51));
7728 CU_ASSERT(769 == session->consumed_size);
7729 CU_ASSERT(769 == stream->consumed_size);
7730 CU_ASSERT(1122 == session->recv_window_size);
7731 CU_ASSERT(1122 == stream->recv_window_size);
7732
7733 /* 357 - 51 = 306 bytes left */
7734 CU_ASSERT(306 == nghttp2_session_mem_recv(session, data, 306));
7735 CU_ASSERT(1024 == session->consumed_size);
7736 CU_ASSERT(1024 == stream->consumed_size);
7737 CU_ASSERT(1428 == session->recv_window_size);
7738 CU_ASSERT(1428 == stream->recv_window_size);
7739
7740 nghttp2_session_del(session);
7741 }
7742
test_nghttp2_session_data_read_temporal_failure(void)7743 void test_nghttp2_session_data_read_temporal_failure(void) {
7744 nghttp2_session *session;
7745 nghttp2_session_callbacks callbacks;
7746 my_user_data ud;
7747 nghttp2_data_provider data_prd;
7748 nghttp2_frame frame;
7749 nghttp2_stream *stream;
7750 size_t data_size = 128 * 1024;
7751
7752 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7753 callbacks.send_callback = null_send_callback;
7754 callbacks.on_frame_send_callback = on_frame_send_callback;
7755 data_prd.read_callback = fixed_length_data_source_read_callback;
7756
7757 ud.data_source_length = data_size;
7758
7759 /* Initial window size is 64KiB - 1 */
7760 nghttp2_session_client_new(&session, &callbacks, &ud);
7761 nghttp2_submit_request(session, NULL, NULL, 0, &data_prd, NULL);
7762
7763 /* Sends NGHTTP2_INITIAL_WINDOW_SIZE data, assuming, it is equal to
7764 or smaller than NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE */
7765 CU_ASSERT(0 == nghttp2_session_send(session));
7766 CU_ASSERT(data_size - NGHTTP2_INITIAL_WINDOW_SIZE == ud.data_source_length);
7767
7768 stream = nghttp2_session_get_stream(session, 1);
7769 CU_ASSERT(NGHTTP2_DATA == stream->item->frame.hd.type);
7770
7771 stream->item->aux_data.data.data_prd.read_callback =
7772 temporal_failure_data_source_read_callback;
7773
7774 /* Back NGHTTP2_INITIAL_WINDOW_SIZE to both connection-level and
7775 stream-wise window */
7776 nghttp2_frame_window_update_init(&frame.window_update, NGHTTP2_FLAG_NONE, 1,
7777 NGHTTP2_INITIAL_WINDOW_SIZE);
7778 nghttp2_session_on_window_update_received(session, &frame);
7779 frame.hd.stream_id = 0;
7780 nghttp2_session_on_window_update_received(session, &frame);
7781 nghttp2_frame_window_update_free(&frame.window_update);
7782
7783 /* Sending data will fail (soft fail) and treated as stream error */
7784 ud.frame_send_cb_called = 0;
7785 CU_ASSERT(0 == nghttp2_session_send(session));
7786 CU_ASSERT(data_size - NGHTTP2_INITIAL_WINDOW_SIZE == ud.data_source_length);
7787
7788 CU_ASSERT(1 == ud.frame_send_cb_called);
7789 CU_ASSERT(NGHTTP2_RST_STREAM == ud.sent_frame_type);
7790
7791 data_prd.read_callback = fail_data_source_read_callback;
7792 nghttp2_submit_request(session, NULL, NULL, 0, &data_prd, NULL);
7793 /* Sending data will fail (hard fail) and session tear down */
7794 CU_ASSERT(NGHTTP2_ERR_CALLBACK_FAILURE == nghttp2_session_send(session));
7795
7796 nghttp2_session_del(session);
7797 }
7798
test_nghttp2_session_on_stream_close(void)7799 void test_nghttp2_session_on_stream_close(void) {
7800 nghttp2_session *session;
7801 nghttp2_session_callbacks callbacks;
7802 my_user_data user_data;
7803 nghttp2_stream *stream;
7804
7805 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7806 callbacks.on_stream_close_callback = on_stream_close_callback;
7807 user_data.stream_close_cb_called = 0;
7808
7809 nghttp2_session_client_new(&session, &callbacks, &user_data);
7810 stream =
7811 open_sent_stream3(session, 1, NGHTTP2_STREAM_FLAG_NONE, &pri_spec_default,
7812 NGHTTP2_STREAM_OPENED, &user_data);
7813 CU_ASSERT(stream != NULL);
7814 CU_ASSERT(nghttp2_session_close_stream(session, 1, NGHTTP2_NO_ERROR) == 0);
7815 CU_ASSERT(user_data.stream_close_cb_called == 1);
7816 nghttp2_session_del(session);
7817 }
7818
test_nghttp2_session_on_ctrl_not_send(void)7819 void test_nghttp2_session_on_ctrl_not_send(void) {
7820 nghttp2_session *session;
7821 nghttp2_session_callbacks callbacks;
7822 my_user_data user_data;
7823 nghttp2_stream *stream;
7824
7825 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7826 callbacks.on_frame_not_send_callback = on_frame_not_send_callback;
7827 callbacks.send_callback = null_send_callback;
7828 user_data.frame_not_send_cb_called = 0;
7829 user_data.not_sent_frame_type = 0;
7830 user_data.not_sent_error = 0;
7831
7832 nghttp2_session_server_new(&session, &callbacks, &user_data);
7833 stream =
7834 open_recv_stream3(session, 1, NGHTTP2_STREAM_FLAG_NONE, &pri_spec_default,
7835 NGHTTP2_STREAM_OPENING, &user_data);
7836
7837 /* Check response HEADERS */
7838 /* Send bogus stream ID */
7839 CU_ASSERT(0 == nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, 3,
7840 NULL, NULL, 0, NULL));
7841 CU_ASSERT(0 == nghttp2_session_send(session));
7842 CU_ASSERT(1 == user_data.frame_not_send_cb_called);
7843 CU_ASSERT(NGHTTP2_HEADERS == user_data.not_sent_frame_type);
7844 CU_ASSERT(NGHTTP2_ERR_STREAM_CLOSED == user_data.not_sent_error);
7845
7846 user_data.frame_not_send_cb_called = 0;
7847 /* Shutdown transmission */
7848 stream->shut_flags |= NGHTTP2_SHUT_WR;
7849 CU_ASSERT(0 == nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, 1,
7850 NULL, NULL, 0, NULL));
7851 CU_ASSERT(0 == nghttp2_session_send(session));
7852 CU_ASSERT(1 == user_data.frame_not_send_cb_called);
7853 CU_ASSERT(NGHTTP2_HEADERS == user_data.not_sent_frame_type);
7854 CU_ASSERT(NGHTTP2_ERR_STREAM_SHUT_WR == user_data.not_sent_error);
7855
7856 stream->shut_flags = NGHTTP2_SHUT_NONE;
7857 user_data.frame_not_send_cb_called = 0;
7858 /* Queue RST_STREAM */
7859 CU_ASSERT(0 == nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, 1,
7860 NULL, NULL, 0, NULL));
7861 CU_ASSERT(0 == nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, 1,
7862 NGHTTP2_INTERNAL_ERROR));
7863 CU_ASSERT(0 == nghttp2_session_send(session));
7864 CU_ASSERT(1 == user_data.frame_not_send_cb_called);
7865 CU_ASSERT(NGHTTP2_HEADERS == user_data.not_sent_frame_type);
7866 CU_ASSERT(NGHTTP2_ERR_STREAM_CLOSING == user_data.not_sent_error);
7867
7868 nghttp2_session_del(session);
7869
7870 /* Check request HEADERS */
7871 user_data.frame_not_send_cb_called = 0;
7872 CU_ASSERT(nghttp2_session_client_new(&session, &callbacks, &user_data) == 0);
7873 /* Maximum Stream ID is reached */
7874 session->next_stream_id = (1u << 31) + 1;
7875 CU_ASSERT(NGHTTP2_ERR_STREAM_ID_NOT_AVAILABLE ==
7876 nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, -1, NULL,
7877 NULL, 0, NULL));
7878
7879 user_data.frame_not_send_cb_called = 0;
7880 /* GOAWAY received */
7881 session->goaway_flags |= NGHTTP2_GOAWAY_RECV;
7882 session->next_stream_id = 9;
7883
7884 CU_ASSERT(0 < nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, -1,
7885 NULL, NULL, 0, NULL));
7886 CU_ASSERT(0 == nghttp2_session_send(session));
7887 CU_ASSERT(1 == user_data.frame_not_send_cb_called);
7888 CU_ASSERT(NGHTTP2_HEADERS == user_data.not_sent_frame_type);
7889 CU_ASSERT(NGHTTP2_ERR_START_STREAM_NOT_ALLOWED == user_data.not_sent_error);
7890
7891 nghttp2_session_del(session);
7892 }
7893
test_nghttp2_session_get_outbound_queue_size(void)7894 void test_nghttp2_session_get_outbound_queue_size(void) {
7895 nghttp2_session *session;
7896 nghttp2_session_callbacks callbacks;
7897
7898 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7899 CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, NULL));
7900 CU_ASSERT(0 == nghttp2_session_get_outbound_queue_size(session));
7901
7902 CU_ASSERT(0 == nghttp2_submit_ping(session, NGHTTP2_FLAG_NONE, NULL));
7903 CU_ASSERT(1 == nghttp2_session_get_outbound_queue_size(session));
7904
7905 CU_ASSERT(0 == nghttp2_submit_goaway(session, NGHTTP2_FLAG_NONE, 2,
7906 NGHTTP2_NO_ERROR, NULL, 0));
7907 CU_ASSERT(2 == nghttp2_session_get_outbound_queue_size(session));
7908
7909 nghttp2_session_del(session);
7910 }
7911
test_nghttp2_session_get_effective_local_window_size(void)7912 void test_nghttp2_session_get_effective_local_window_size(void) {
7913 nghttp2_session *session;
7914 nghttp2_session_callbacks callbacks;
7915 nghttp2_stream *stream;
7916
7917 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7918 CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, NULL));
7919
7920 stream = open_sent_stream(session, 1);
7921
7922 CU_ASSERT(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE ==
7923 nghttp2_session_get_effective_local_window_size(session));
7924 CU_ASSERT(0 == nghttp2_session_get_effective_recv_data_length(session));
7925
7926 CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE ==
7927 nghttp2_session_get_stream_effective_local_window_size(session, 1));
7928 CU_ASSERT(0 ==
7929 nghttp2_session_get_stream_effective_recv_data_length(session, 1));
7930
7931 /* Check connection flow control */
7932 session->recv_window_size = 100;
7933 nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 0, 1100);
7934
7935 CU_ASSERT(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE + 1000 ==
7936 nghttp2_session_get_effective_local_window_size(session));
7937 CU_ASSERT(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE + 1000 ==
7938 nghttp2_session_get_local_window_size(session));
7939 CU_ASSERT(0 == nghttp2_session_get_effective_recv_data_length(session));
7940
7941 nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 0, -50);
7942 /* Now session->recv_window_size = -50 */
7943 CU_ASSERT(-50 == session->recv_window_size);
7944 CU_ASSERT(50 == session->recv_reduction);
7945 CU_ASSERT(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE + 950 ==
7946 nghttp2_session_get_effective_local_window_size(session));
7947 CU_ASSERT(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE + 1000 ==
7948 nghttp2_session_get_local_window_size(session));
7949 CU_ASSERT(0 == nghttp2_session_get_effective_recv_data_length(session));
7950
7951 session->recv_window_size += 50;
7952
7953 /* Now session->recv_window_size = 0 */
7954
7955 CU_ASSERT(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE + 950 ==
7956 nghttp2_session_get_local_window_size(session));
7957
7958 nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 0, 100);
7959 CU_ASSERT(50 == session->recv_window_size);
7960 CU_ASSERT(0 == session->recv_reduction);
7961 CU_ASSERT(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE + 1050 ==
7962 nghttp2_session_get_effective_local_window_size(session));
7963 CU_ASSERT(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE + 1000 ==
7964 nghttp2_session_get_local_window_size(session));
7965 CU_ASSERT(50 == nghttp2_session_get_effective_recv_data_length(session));
7966
7967 /* Check stream flow control */
7968 stream->recv_window_size = 100;
7969 nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 1, 1100);
7970
7971 CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE + 1000 ==
7972 nghttp2_session_get_stream_effective_local_window_size(session, 1));
7973 CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE + 1000 ==
7974 nghttp2_session_get_stream_local_window_size(session, 1));
7975 CU_ASSERT(0 ==
7976 nghttp2_session_get_stream_effective_recv_data_length(session, 1));
7977
7978 nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 1, -50);
7979 /* Now stream->recv_window_size = -50 */
7980 CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE + 950 ==
7981 nghttp2_session_get_stream_effective_local_window_size(session, 1));
7982 CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE + 1000 ==
7983 nghttp2_session_get_stream_local_window_size(session, 1));
7984 CU_ASSERT(0 ==
7985 nghttp2_session_get_stream_effective_recv_data_length(session, 1));
7986
7987 stream->recv_window_size += 50;
7988 /* Now stream->recv_window_size = 0 */
7989 nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 1, 100);
7990 CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE + 1050 ==
7991 nghttp2_session_get_stream_effective_local_window_size(session, 1));
7992 CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE + 1000 ==
7993 nghttp2_session_get_stream_local_window_size(session, 1));
7994 CU_ASSERT(50 ==
7995 nghttp2_session_get_stream_effective_recv_data_length(session, 1));
7996
7997 nghttp2_session_del(session);
7998 }
7999
test_nghttp2_session_set_option(void)8000 void test_nghttp2_session_set_option(void) {
8001 nghttp2_session *session;
8002 nghttp2_session_callbacks callbacks;
8003 nghttp2_option *option;
8004 nghttp2_hd_deflater *deflater;
8005 int rv;
8006
8007 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
8008 callbacks.send_callback = null_send_callback;
8009
8010 /* Test for nghttp2_option_set_no_auto_window_update */
8011 nghttp2_option_new(&option);
8012 nghttp2_option_set_no_auto_window_update(option, 1);
8013
8014 nghttp2_session_client_new2(&session, &callbacks, NULL, option);
8015
8016 CU_ASSERT(session->opt_flags & NGHTTP2_OPTMASK_NO_AUTO_WINDOW_UPDATE);
8017
8018 nghttp2_session_del(session);
8019 nghttp2_option_del(option);
8020
8021 /* Test for nghttp2_option_set_peer_max_concurrent_streams */
8022 nghttp2_option_new(&option);
8023 nghttp2_option_set_peer_max_concurrent_streams(option, 100);
8024
8025 nghttp2_session_client_new2(&session, &callbacks, NULL, option);
8026
8027 CU_ASSERT(100 == session->remote_settings.max_concurrent_streams);
8028 nghttp2_session_del(session);
8029 nghttp2_option_del(option);
8030
8031 /* Test for nghttp2_option_set_max_reserved_remote_streams */
8032 nghttp2_option_new(&option);
8033 nghttp2_option_set_max_reserved_remote_streams(option, 99);
8034
8035 nghttp2_session_client_new2(&session, &callbacks, NULL, option);
8036
8037 CU_ASSERT(99 == session->max_incoming_reserved_streams);
8038 nghttp2_session_del(session);
8039 nghttp2_option_del(option);
8040
8041 /* Test for nghttp2_option_set_no_auto_ping_ack */
8042 nghttp2_option_new(&option);
8043 nghttp2_option_set_no_auto_ping_ack(option, 1);
8044
8045 nghttp2_session_client_new2(&session, &callbacks, NULL, option);
8046
8047 CU_ASSERT(session->opt_flags & NGHTTP2_OPTMASK_NO_AUTO_PING_ACK);
8048
8049 nghttp2_session_del(session);
8050 nghttp2_option_del(option);
8051
8052 /* Test for nghttp2_option_set_max_deflate_dynamic_table_size */
8053 nghttp2_option_new(&option);
8054 nghttp2_option_set_max_deflate_dynamic_table_size(option, 0);
8055
8056 nghttp2_session_client_new2(&session, &callbacks, NULL, option);
8057
8058 deflater = &session->hd_deflater;
8059
8060 rv = nghttp2_submit_request(session, NULL, reqnv, ARRLEN(reqnv), NULL, NULL);
8061
8062 CU_ASSERT(1 == rv);
8063
8064 rv = nghttp2_session_send(session);
8065
8066 CU_ASSERT(0 == rv);
8067 CU_ASSERT(0 == deflater->deflate_hd_table_bufsize_max);
8068 CU_ASSERT(0 == deflater->ctx.hd_table_bufsize);
8069
8070 nghttp2_session_del(session);
8071 nghttp2_option_del(option);
8072 }
8073
test_nghttp2_session_data_backoff_by_high_pri_frame(void)8074 void test_nghttp2_session_data_backoff_by_high_pri_frame(void) {
8075 nghttp2_session *session;
8076 nghttp2_session_callbacks callbacks;
8077 my_user_data ud;
8078 nghttp2_data_provider data_prd;
8079 nghttp2_stream *stream;
8080
8081 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
8082 callbacks.send_callback = block_count_send_callback;
8083 callbacks.on_frame_send_callback = on_frame_send_callback;
8084 data_prd.read_callback = fixed_length_data_source_read_callback;
8085
8086 ud.frame_send_cb_called = 0;
8087 ud.data_source_length = NGHTTP2_DATA_PAYLOADLEN * 4;
8088
8089 nghttp2_session_client_new(&session, &callbacks, &ud);
8090 nghttp2_submit_request(session, NULL, NULL, 0, &data_prd, NULL);
8091
8092 session->remote_window_size = 1 << 20;
8093
8094 ud.block_count = 2;
8095 /* Sends request HEADERS + DATA[0] */
8096 CU_ASSERT(0 == nghttp2_session_send(session));
8097
8098 stream = nghttp2_session_get_stream(session, 1);
8099 stream->remote_window_size = 1 << 20;
8100
8101 CU_ASSERT(NGHTTP2_DATA == ud.sent_frame_type);
8102 /* data for DATA[1] is read from data_prd but it is not sent */
8103 CU_ASSERT(ud.data_source_length == NGHTTP2_DATA_PAYLOADLEN * 2);
8104
8105 nghttp2_submit_ping(session, NGHTTP2_FLAG_NONE, NULL);
8106 ud.block_count = 2;
8107 /* Sends DATA[1] + PING, PING is interleaved in DATA sequence */
8108 CU_ASSERT(0 == nghttp2_session_send(session));
8109 CU_ASSERT(NGHTTP2_PING == ud.sent_frame_type);
8110 /* data for DATA[2] is read from data_prd but it is not sent */
8111 CU_ASSERT(ud.data_source_length == NGHTTP2_DATA_PAYLOADLEN);
8112
8113 ud.block_count = 2;
8114 /* Sends DATA[2..3] */
8115 CU_ASSERT(0 == nghttp2_session_send(session));
8116
8117 CU_ASSERT(stream->shut_flags & NGHTTP2_SHUT_WR);
8118
8119 nghttp2_session_del(session);
8120 }
8121
check_session_recv_data_with_padding(nghttp2_bufs * bufs,size_t datalen,nghttp2_mem * mem)8122 static void check_session_recv_data_with_padding(nghttp2_bufs *bufs,
8123 size_t datalen,
8124 nghttp2_mem *mem) {
8125 nghttp2_session *session;
8126 my_user_data ud;
8127 nghttp2_session_callbacks callbacks;
8128 uint8_t *in;
8129 size_t inlen;
8130
8131 memset(&callbacks, 0, sizeof(callbacks));
8132 callbacks.on_frame_recv_callback = on_frame_recv_callback;
8133 callbacks.on_data_chunk_recv_callback = on_data_chunk_recv_callback;
8134 nghttp2_session_server_new(&session, &callbacks, &ud);
8135
8136 open_recv_stream(session, 1);
8137
8138 inlen = (size_t)nghttp2_bufs_remove(bufs, &in);
8139
8140 ud.frame_recv_cb_called = 0;
8141 ud.data_chunk_len = 0;
8142
8143 CU_ASSERT((ssize_t)inlen == nghttp2_session_mem_recv(session, in, inlen));
8144
8145 CU_ASSERT(1 == ud.frame_recv_cb_called);
8146 CU_ASSERT(datalen == ud.data_chunk_len);
8147
8148 mem->free(in, NULL);
8149 nghttp2_session_del(session);
8150 }
8151
test_nghttp2_session_pack_data_with_padding(void)8152 void test_nghttp2_session_pack_data_with_padding(void) {
8153 nghttp2_session *session;
8154 my_user_data ud;
8155 nghttp2_session_callbacks callbacks;
8156 nghttp2_data_provider data_prd;
8157 nghttp2_frame *frame;
8158 size_t datalen = 55;
8159 nghttp2_mem *mem;
8160
8161 mem = nghttp2_mem_default();
8162
8163 memset(&callbacks, 0, sizeof(callbacks));
8164 callbacks.send_callback = block_count_send_callback;
8165 callbacks.on_frame_send_callback = on_frame_send_callback;
8166 callbacks.select_padding_callback = select_padding_callback;
8167
8168 data_prd.read_callback = fixed_length_data_source_read_callback;
8169
8170 nghttp2_session_client_new(&session, &callbacks, &ud);
8171
8172 ud.padlen = 63;
8173
8174 nghttp2_submit_request(session, NULL, NULL, 0, &data_prd, NULL);
8175 ud.block_count = 1;
8176 ud.data_source_length = datalen;
8177 /* Sends HEADERS */
8178 CU_ASSERT(0 == nghttp2_session_send(session));
8179 CU_ASSERT(NGHTTP2_HEADERS == ud.sent_frame_type);
8180
8181 frame = &session->aob.item->frame;
8182
8183 CU_ASSERT(ud.padlen == frame->data.padlen);
8184 CU_ASSERT(frame->hd.flags & NGHTTP2_FLAG_PADDED);
8185
8186 /* Check reception of this DATA frame */
8187 check_session_recv_data_with_padding(&session->aob.framebufs, datalen, mem);
8188
8189 nghttp2_session_del(session);
8190 }
8191
test_nghttp2_session_pack_headers_with_padding(void)8192 void test_nghttp2_session_pack_headers_with_padding(void) {
8193 nghttp2_session *session, *sv_session;
8194 accumulator acc;
8195 my_user_data ud;
8196 nghttp2_session_callbacks callbacks;
8197
8198 memset(&callbacks, 0, sizeof(callbacks));
8199 callbacks.send_callback = accumulator_send_callback;
8200 callbacks.on_frame_send_callback = on_frame_send_callback;
8201 callbacks.select_padding_callback = select_padding_callback;
8202 callbacks.on_frame_recv_callback = on_frame_recv_callback;
8203
8204 acc.length = 0;
8205 ud.acc = &acc;
8206
8207 nghttp2_session_client_new(&session, &callbacks, &ud);
8208 nghttp2_session_server_new(&sv_session, &callbacks, &ud);
8209
8210 ud.padlen = 163;
8211
8212 CU_ASSERT(1 == nghttp2_submit_request(session, NULL, reqnv, ARRLEN(reqnv),
8213 NULL, NULL));
8214 CU_ASSERT(0 == nghttp2_session_send(session));
8215
8216 CU_ASSERT(acc.length < NGHTTP2_MAX_PAYLOADLEN);
8217 ud.frame_recv_cb_called = 0;
8218 CU_ASSERT((ssize_t)acc.length ==
8219 nghttp2_session_mem_recv(sv_session, acc.buf, acc.length));
8220 CU_ASSERT(1 == ud.frame_recv_cb_called);
8221 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(sv_session));
8222
8223 nghttp2_session_del(sv_session);
8224 nghttp2_session_del(session);
8225 }
8226
test_nghttp2_pack_settings_payload(void)8227 void test_nghttp2_pack_settings_payload(void) {
8228 nghttp2_settings_entry iv[2];
8229 uint8_t buf[64];
8230 ssize_t len;
8231 nghttp2_settings_entry *resiv;
8232 size_t resniv;
8233 nghttp2_mem *mem;
8234
8235 mem = nghttp2_mem_default();
8236
8237 iv[0].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
8238 iv[0].value = 1023;
8239 iv[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
8240 iv[1].value = 4095;
8241
8242 len = nghttp2_pack_settings_payload(buf, sizeof(buf), iv, 2);
8243 CU_ASSERT(2 * NGHTTP2_FRAME_SETTINGS_ENTRY_LENGTH == len);
8244 CU_ASSERT(0 == nghttp2_frame_unpack_settings_payload2(&resiv, &resniv, buf,
8245 (size_t)len, mem));
8246 CU_ASSERT(2 == resniv);
8247 CU_ASSERT(NGHTTP2_SETTINGS_HEADER_TABLE_SIZE == resiv[0].settings_id);
8248 CU_ASSERT(1023 == resiv[0].value);
8249 CU_ASSERT(NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE == resiv[1].settings_id);
8250 CU_ASSERT(4095 == resiv[1].value);
8251
8252 mem->free(resiv, NULL);
8253
8254 len = nghttp2_pack_settings_payload(buf, 9 /* too small */, iv, 2);
8255 CU_ASSERT(NGHTTP2_ERR_INSUFF_BUFSIZE == len);
8256 }
8257
8258 #define check_stream_dep_sib(STREAM, DEP_PREV, DEP_NEXT, SIB_PREV, SIB_NEXT) \
8259 do { \
8260 CU_ASSERT(DEP_PREV == STREAM->dep_prev); \
8261 CU_ASSERT(DEP_NEXT == STREAM->dep_next); \
8262 CU_ASSERT(SIB_PREV == STREAM->sib_prev); \
8263 CU_ASSERT(SIB_NEXT == STREAM->sib_next); \
8264 } while (0)
8265
8266 /* nghttp2_stream_dep_add() and its families functions should be
8267 tested in nghttp2_stream_test.c, but it is easier to use
8268 nghttp2_session_open_stream(). Therefore, we test them here. */
test_nghttp2_session_stream_dep_add(void)8269 void test_nghttp2_session_stream_dep_add(void) {
8270 nghttp2_session *session;
8271 nghttp2_session_callbacks callbacks;
8272 nghttp2_stream *a, *b, *c, *d, *e, *root;
8273
8274 memset(&callbacks, 0, sizeof(callbacks));
8275
8276 nghttp2_session_server_new(&session, &callbacks, NULL);
8277
8278 root = &session->root;
8279
8280 a = open_stream(session, 1);
8281
8282 c = open_stream_with_dep(session, 5, a);
8283 b = open_stream_with_dep(session, 3, a);
8284 d = open_stream_with_dep(session, 7, c);
8285
8286 /* a
8287 * |
8288 * b--c
8289 * |
8290 * d
8291 */
8292
8293 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 2 == a->sum_dep_weight);
8294 CU_ASSERT(0 == b->sum_dep_weight);
8295 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == c->sum_dep_weight);
8296 CU_ASSERT(0 == d->sum_dep_weight);
8297
8298 check_stream_dep_sib(a, root, b, NULL, NULL);
8299 check_stream_dep_sib(b, a, NULL, NULL, c);
8300 check_stream_dep_sib(c, a, d, b, NULL);
8301 check_stream_dep_sib(d, c, NULL, NULL, NULL);
8302
8303 CU_ASSERT(a == session->root.dep_next);
8304
8305 e = open_stream_with_dep_excl(session, 9, a);
8306
8307 /* a
8308 * |
8309 * e
8310 * |
8311 * b--c
8312 * |
8313 * d
8314 */
8315
8316 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == a->sum_dep_weight);
8317 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 2 == e->sum_dep_weight);
8318 CU_ASSERT(0 == b->sum_dep_weight);
8319 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == c->sum_dep_weight);
8320 CU_ASSERT(0 == d->sum_dep_weight);
8321
8322 check_stream_dep_sib(a, root, e, NULL, NULL);
8323 check_stream_dep_sib(e, a, b, NULL, NULL);
8324 check_stream_dep_sib(b, e, NULL, NULL, c);
8325 check_stream_dep_sib(c, e, d, b, NULL);
8326 check_stream_dep_sib(d, c, NULL, NULL, NULL);
8327
8328 CU_ASSERT(a == session->root.dep_next);
8329
8330 nghttp2_session_del(session);
8331 }
8332
test_nghttp2_session_stream_dep_remove(void)8333 void test_nghttp2_session_stream_dep_remove(void) {
8334 nghttp2_session *session;
8335 nghttp2_session_callbacks callbacks;
8336 nghttp2_stream *a, *b, *c, *d, *e, *f, *root;
8337
8338 memset(&callbacks, 0, sizeof(callbacks));
8339
8340 /* Remove root */
8341 nghttp2_session_server_new(&session, &callbacks, NULL);
8342
8343 root = &session->root;
8344
8345 a = open_stream(session, 1);
8346 b = open_stream_with_dep(session, 3, a);
8347 c = open_stream_with_dep(session, 5, a);
8348 d = open_stream_with_dep(session, 7, c);
8349
8350 /* a
8351 * |
8352 * c--b
8353 * |
8354 * d
8355 */
8356
8357 nghttp2_stream_dep_remove(a);
8358
8359 /* becomes:
8360 * c b
8361 * |
8362 * d
8363 */
8364
8365 CU_ASSERT(0 == a->sum_dep_weight);
8366 CU_ASSERT(0 == b->sum_dep_weight);
8367 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == c->sum_dep_weight);
8368 CU_ASSERT(0 == d->sum_dep_weight);
8369
8370 check_stream_dep_sib(a, NULL, NULL, NULL, NULL);
8371 check_stream_dep_sib(b, root, NULL, c, NULL);
8372 check_stream_dep_sib(c, root, d, NULL, b);
8373 check_stream_dep_sib(d, c, NULL, NULL, NULL);
8374
8375 CU_ASSERT(c == session->root.dep_next);
8376
8377 nghttp2_session_del(session);
8378
8379 /* Remove right most stream */
8380 nghttp2_session_server_new(&session, &callbacks, NULL);
8381
8382 root = &session->root;
8383
8384 a = open_stream(session, 1);
8385 b = open_stream_with_dep(session, 3, a);
8386 c = open_stream_with_dep(session, 5, a);
8387 d = open_stream_with_dep(session, 7, c);
8388
8389 /* a
8390 * |
8391 * c--b
8392 * |
8393 * d
8394 */
8395
8396 nghttp2_stream_dep_remove(b);
8397
8398 /* becomes:
8399 * a
8400 * |
8401 * c
8402 * |
8403 * d
8404 */
8405
8406 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == a->sum_dep_weight);
8407 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == c->sum_dep_weight);
8408 CU_ASSERT(0 == d->sum_dep_weight);
8409 CU_ASSERT(0 == b->sum_dep_weight);
8410
8411 check_stream_dep_sib(a, root, c, NULL, NULL);
8412 check_stream_dep_sib(b, NULL, NULL, NULL, NULL);
8413 check_stream_dep_sib(c, a, d, NULL, NULL);
8414 check_stream_dep_sib(d, c, NULL, NULL, NULL);
8415
8416 CU_ASSERT(a == session->root.dep_next);
8417
8418 nghttp2_session_del(session);
8419
8420 /* Remove left most stream */
8421 nghttp2_session_server_new(&session, &callbacks, NULL);
8422
8423 root = &session->root;
8424
8425 a = open_stream(session, 1);
8426 b = open_stream_with_dep(session, 3, a);
8427 c = open_stream_with_dep(session, 5, a);
8428 d = open_stream_with_dep(session, 7, c);
8429 e = open_stream_with_dep(session, 9, c);
8430
8431 /* a
8432 * |
8433 * c--b
8434 * |
8435 * e--d
8436 */
8437
8438 nghttp2_stream_dep_remove(c);
8439
8440 /* becomes:
8441 * a
8442 * |
8443 * e--d--b
8444 */
8445
8446 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 2 == a->sum_dep_weight);
8447 CU_ASSERT(0 == b->sum_dep_weight);
8448 CU_ASSERT(0 == d->sum_dep_weight);
8449 CU_ASSERT(0 == c->sum_dep_weight);
8450 CU_ASSERT(0 == e->sum_dep_weight);
8451
8452 check_stream_dep_sib(a, root, e, NULL, NULL);
8453 check_stream_dep_sib(b, a, NULL, d, NULL);
8454 check_stream_dep_sib(c, NULL, NULL, NULL, NULL);
8455 check_stream_dep_sib(d, a, NULL, e, b);
8456 check_stream_dep_sib(e, a, NULL, NULL, d);
8457
8458 nghttp2_session_del(session);
8459
8460 /* Remove middle stream */
8461 nghttp2_session_server_new(&session, &callbacks, NULL);
8462
8463 root = &session->root;
8464
8465 a = open_stream(session, 1);
8466 b = open_stream_with_dep(session, 3, a);
8467 c = open_stream_with_dep(session, 5, a);
8468 d = open_stream_with_dep(session, 7, a);
8469 e = open_stream_with_dep(session, 9, c);
8470 f = open_stream_with_dep(session, 11, c);
8471
8472 /* a
8473 * |
8474 * d--c--b
8475 * |
8476 * f--e
8477 */
8478
8479 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 3 == a->sum_dep_weight);
8480 CU_ASSERT(0 == b->sum_dep_weight);
8481 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 2 == c->sum_dep_weight);
8482 CU_ASSERT(0 == d->sum_dep_weight);
8483 CU_ASSERT(0 == e->sum_dep_weight);
8484 CU_ASSERT(0 == f->sum_dep_weight);
8485
8486 nghttp2_stream_dep_remove(c);
8487
8488 /* becomes:
8489 * a
8490 * |
8491 * d--f--e--b
8492 */
8493
8494 /* c's weight 16 is distributed evenly to e and f. Each weight of e
8495 and f becomes 8. */
8496 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 2 + 8 * 2 == a->sum_dep_weight);
8497 CU_ASSERT(0 == b->sum_dep_weight);
8498 CU_ASSERT(0 == c->sum_dep_weight);
8499 CU_ASSERT(0 == d->sum_dep_weight);
8500 CU_ASSERT(0 == e->sum_dep_weight);
8501 CU_ASSERT(0 == f->sum_dep_weight);
8502
8503 check_stream_dep_sib(a, root, d, NULL, NULL);
8504 check_stream_dep_sib(b, a, NULL, e, NULL);
8505 check_stream_dep_sib(c, NULL, NULL, NULL, NULL);
8506 check_stream_dep_sib(e, a, NULL, f, b);
8507 check_stream_dep_sib(f, a, NULL, d, e);
8508 check_stream_dep_sib(d, a, NULL, NULL, f);
8509
8510 nghttp2_session_del(session);
8511 }
8512
test_nghttp2_session_stream_dep_add_subtree(void)8513 void test_nghttp2_session_stream_dep_add_subtree(void) {
8514 nghttp2_session *session;
8515 nghttp2_session_callbacks callbacks;
8516 nghttp2_stream *a, *b, *c, *d, *e, *f, *root;
8517
8518 memset(&callbacks, 0, sizeof(callbacks));
8519
8520 /* dep_stream has dep_next */
8521 nghttp2_session_server_new(&session, &callbacks, NULL);
8522
8523 root = &session->root;
8524
8525 a = open_stream(session, 1);
8526 b = open_stream_with_dep(session, 3, a);
8527 c = open_stream_with_dep(session, 5, a);
8528 d = open_stream_with_dep(session, 7, c);
8529
8530 e = open_stream(session, 9);
8531 f = open_stream_with_dep(session, 11, e);
8532
8533 /* a e
8534 * | |
8535 * c--b f
8536 * |
8537 * d
8538 */
8539
8540 nghttp2_stream_dep_remove_subtree(e);
8541 nghttp2_stream_dep_add_subtree(a, e);
8542
8543 /* becomes
8544 * a
8545 * |
8546 * e--c--b
8547 * | |
8548 * f d
8549 */
8550
8551 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 3 == a->sum_dep_weight);
8552 CU_ASSERT(0 == b->sum_dep_weight);
8553 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == c->sum_dep_weight);
8554 CU_ASSERT(0 == d->sum_dep_weight);
8555 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == e->sum_dep_weight);
8556 CU_ASSERT(0 == f->sum_dep_weight);
8557
8558 check_stream_dep_sib(a, root, e, NULL, NULL);
8559 check_stream_dep_sib(b, a, NULL, c, NULL);
8560 check_stream_dep_sib(c, a, d, e, b);
8561 check_stream_dep_sib(d, c, NULL, NULL, NULL);
8562 check_stream_dep_sib(e, a, f, NULL, c);
8563 check_stream_dep_sib(f, e, NULL, NULL, NULL);
8564
8565 nghttp2_session_del(session);
8566
8567 /* dep_stream has dep_next and now we insert subtree */
8568 nghttp2_session_server_new(&session, &callbacks, NULL);
8569
8570 root = &session->root;
8571
8572 a = open_stream(session, 1);
8573 b = open_stream_with_dep(session, 3, a);
8574 c = open_stream_with_dep(session, 5, a);
8575 d = open_stream_with_dep(session, 7, c);
8576
8577 e = open_stream(session, 9);
8578 f = open_stream_with_dep(session, 11, e);
8579
8580 /* a e
8581 * | |
8582 * c--b f
8583 * |
8584 * d
8585 */
8586
8587 nghttp2_stream_dep_remove_subtree(e);
8588 nghttp2_stream_dep_insert_subtree(a, e);
8589
8590 /* becomes
8591 * a
8592 * |
8593 * e
8594 * |
8595 * f--c--b
8596 * |
8597 * d
8598 */
8599
8600 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == a->sum_dep_weight);
8601 CU_ASSERT(0 == b->sum_dep_weight);
8602 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == c->sum_dep_weight);
8603 CU_ASSERT(0 == d->sum_dep_weight);
8604 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 3 == e->sum_dep_weight);
8605 CU_ASSERT(0 == f->sum_dep_weight);
8606
8607 check_stream_dep_sib(a, root, e, NULL, NULL);
8608 check_stream_dep_sib(e, a, f, NULL, NULL);
8609 check_stream_dep_sib(f, e, NULL, NULL, c);
8610 check_stream_dep_sib(b, e, NULL, c, NULL);
8611 check_stream_dep_sib(c, e, d, f, b);
8612 check_stream_dep_sib(d, c, NULL, NULL, NULL);
8613
8614 nghttp2_session_del(session);
8615 }
8616
test_nghttp2_session_stream_dep_remove_subtree(void)8617 void test_nghttp2_session_stream_dep_remove_subtree(void) {
8618 nghttp2_session *session;
8619 nghttp2_session_callbacks callbacks;
8620 nghttp2_stream *a, *b, *c, *d, *e, *root;
8621
8622 memset(&callbacks, 0, sizeof(callbacks));
8623
8624 /* Remove left most stream */
8625 nghttp2_session_server_new(&session, &callbacks, NULL);
8626
8627 root = &session->root;
8628
8629 a = open_stream(session, 1);
8630 b = open_stream_with_dep(session, 3, a);
8631 c = open_stream_with_dep(session, 5, a);
8632 d = open_stream_with_dep(session, 7, c);
8633
8634 /* a
8635 * |
8636 * c--b
8637 * |
8638 * d
8639 */
8640
8641 nghttp2_stream_dep_remove_subtree(c);
8642
8643 /* becomes
8644 * a c
8645 * | |
8646 * b d
8647 */
8648
8649 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == a->sum_dep_weight);
8650 CU_ASSERT(0 == b->sum_dep_weight);
8651 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == c->sum_dep_weight);
8652 CU_ASSERT(0 == d->sum_dep_weight);
8653
8654 check_stream_dep_sib(a, root, b, NULL, NULL);
8655 check_stream_dep_sib(b, a, NULL, NULL, NULL);
8656 check_stream_dep_sib(c, NULL, d, NULL, NULL);
8657 check_stream_dep_sib(d, c, NULL, NULL, NULL);
8658
8659 nghttp2_session_del(session);
8660
8661 /* Remove right most stream */
8662 nghttp2_session_server_new(&session, &callbacks, NULL);
8663
8664 root = &session->root;
8665
8666 a = open_stream(session, 1);
8667 b = open_stream_with_dep(session, 3, a);
8668 c = open_stream_with_dep(session, 5, a);
8669 d = open_stream_with_dep(session, 7, c);
8670
8671 /* a
8672 * |
8673 * c--b
8674 * |
8675 * d
8676 */
8677
8678 nghttp2_stream_dep_remove_subtree(b);
8679
8680 /* becomes
8681 * a b
8682 * |
8683 * c
8684 * |
8685 * d
8686 */
8687
8688 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == a->sum_dep_weight);
8689 CU_ASSERT(0 == b->sum_dep_weight);
8690 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == c->sum_dep_weight);
8691 CU_ASSERT(0 == d->sum_dep_weight);
8692
8693 check_stream_dep_sib(a, root, c, NULL, NULL);
8694 check_stream_dep_sib(c, a, d, NULL, NULL);
8695 check_stream_dep_sib(d, c, NULL, NULL, NULL);
8696 check_stream_dep_sib(b, NULL, NULL, NULL, NULL);
8697
8698 nghttp2_session_del(session);
8699
8700 /* Remove middle stream */
8701 nghttp2_session_server_new(&session, &callbacks, NULL);
8702
8703 root = &session->root;
8704
8705 a = open_stream(session, 1);
8706 e = open_stream_with_dep(session, 9, a);
8707 c = open_stream_with_dep(session, 5, a);
8708 b = open_stream_with_dep(session, 3, a);
8709 d = open_stream_with_dep(session, 7, c);
8710
8711 /* a
8712 * |
8713 * b--c--e
8714 * |
8715 * d
8716 */
8717
8718 nghttp2_stream_dep_remove_subtree(c);
8719
8720 /* becomes
8721 * a c
8722 * | |
8723 * b--e d
8724 */
8725
8726 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 2 == a->sum_dep_weight);
8727 CU_ASSERT(0 == b->sum_dep_weight);
8728 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == c->sum_dep_weight);
8729 CU_ASSERT(0 == d->sum_dep_weight);
8730 CU_ASSERT(0 == e->sum_dep_weight);
8731
8732 check_stream_dep_sib(a, root, b, NULL, NULL);
8733 check_stream_dep_sib(b, a, NULL, NULL, e);
8734 check_stream_dep_sib(e, a, NULL, b, NULL);
8735 check_stream_dep_sib(c, NULL, d, NULL, NULL);
8736 check_stream_dep_sib(d, c, NULL, NULL, NULL);
8737
8738 nghttp2_session_del(session);
8739 }
8740
test_nghttp2_session_stream_dep_all_your_stream_are_belong_to_us(void)8741 void test_nghttp2_session_stream_dep_all_your_stream_are_belong_to_us(void) {
8742 nghttp2_session *session;
8743 nghttp2_session_callbacks callbacks;
8744 nghttp2_stream *a, *b, *c, *d, *root;
8745 nghttp2_outbound_item *db, *dc;
8746 nghttp2_mem *mem;
8747
8748 mem = nghttp2_mem_default();
8749
8750 memset(&callbacks, 0, sizeof(callbacks));
8751
8752 nghttp2_session_server_new(&session, &callbacks, NULL);
8753
8754 root = &session->root;
8755
8756 a = open_stream(session, 1);
8757 b = open_stream_with_dep(session, 3, a);
8758
8759 c = open_stream(session, 5);
8760
8761 /* a c
8762 * |
8763 * b
8764 */
8765
8766 nghttp2_stream_dep_remove_subtree(c);
8767 CU_ASSERT(0 == nghttp2_stream_dep_insert_subtree(&session->root, c));
8768
8769 /*
8770 * c
8771 * |
8772 * a
8773 * |
8774 * b
8775 */
8776
8777 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == c->sum_dep_weight);
8778 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == a->sum_dep_weight);
8779 CU_ASSERT(0 == b->sum_dep_weight);
8780
8781 CU_ASSERT(nghttp2_pq_empty(&a->obq));
8782 CU_ASSERT(nghttp2_pq_empty(&b->obq));
8783 CU_ASSERT(nghttp2_pq_empty(&c->obq));
8784
8785 check_stream_dep_sib(c, root, a, NULL, NULL);
8786 check_stream_dep_sib(a, c, b, NULL, NULL);
8787 check_stream_dep_sib(b, a, NULL, NULL, NULL);
8788
8789 nghttp2_session_del(session);
8790
8791 nghttp2_session_server_new(&session, &callbacks, NULL);
8792
8793 root = &session->root;
8794
8795 a = open_stream(session, 1);
8796 b = open_stream(session, 3);
8797 c = open_stream(session, 5);
8798
8799 /*
8800 * a b c
8801 */
8802
8803 nghttp2_stream_dep_remove_subtree(c);
8804 CU_ASSERT(0 == nghttp2_stream_dep_insert_subtree(&session->root, c));
8805
8806 /*
8807 * c
8808 * |
8809 * b--a
8810 */
8811
8812 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 2 == c->sum_dep_weight);
8813 CU_ASSERT(0 == b->sum_dep_weight);
8814 CU_ASSERT(0 == a->sum_dep_weight);
8815
8816 CU_ASSERT(nghttp2_pq_empty(&a->obq));
8817 CU_ASSERT(nghttp2_pq_empty(&b->obq));
8818 CU_ASSERT(nghttp2_pq_empty(&c->obq));
8819
8820 check_stream_dep_sib(c, root, b, NULL, NULL);
8821 check_stream_dep_sib(b, c, NULL, NULL, a);
8822 check_stream_dep_sib(a, c, NULL, b, NULL);
8823
8824 nghttp2_session_del(session);
8825
8826 nghttp2_session_server_new(&session, &callbacks, NULL);
8827
8828 root = &session->root;
8829
8830 a = open_stream(session, 1);
8831 b = open_stream_with_dep(session, 3, a);
8832
8833 c = open_stream(session, 5);
8834 d = open_stream_with_dep(session, 7, c);
8835
8836 /* a c
8837 * | |
8838 * b d
8839 */
8840
8841 nghttp2_stream_dep_remove_subtree(c);
8842 CU_ASSERT(0 == nghttp2_stream_dep_insert_subtree(&session->root, c));
8843
8844 /*
8845 * c
8846 * |
8847 * d--a
8848 * |
8849 * b
8850 */
8851
8852 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 2 == c->sum_dep_weight);
8853 CU_ASSERT(0 == d->sum_dep_weight);
8854 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == a->sum_dep_weight);
8855 CU_ASSERT(0 == b->sum_dep_weight);
8856
8857 CU_ASSERT(nghttp2_pq_empty(&a->obq));
8858 CU_ASSERT(nghttp2_pq_empty(&b->obq));
8859 CU_ASSERT(nghttp2_pq_empty(&c->obq));
8860 CU_ASSERT(nghttp2_pq_empty(&d->obq));
8861
8862 check_stream_dep_sib(c, root, d, NULL, NULL);
8863 check_stream_dep_sib(d, c, NULL, NULL, a);
8864 check_stream_dep_sib(a, c, b, d, NULL);
8865 check_stream_dep_sib(b, a, NULL, NULL, NULL);
8866
8867 nghttp2_session_del(session);
8868
8869 nghttp2_session_server_new(&session, &callbacks, NULL);
8870
8871 root = &session->root;
8872
8873 a = open_stream(session, 1);
8874 b = open_stream_with_dep(session, 3, a);
8875
8876 c = open_stream(session, 5);
8877 d = open_stream_with_dep(session, 7, c);
8878
8879 /* a c
8880 * | |
8881 * b d
8882 */
8883
8884 db = create_data_ob_item(mem);
8885
8886 nghttp2_stream_attach_item(b, db);
8887
8888 nghttp2_stream_dep_remove_subtree(c);
8889 CU_ASSERT(0 == nghttp2_stream_dep_insert_subtree(&session->root, c));
8890
8891 /*
8892 * c
8893 * |
8894 * d--a
8895 * |
8896 * b
8897 */
8898
8899 CU_ASSERT(c->queued);
8900 CU_ASSERT(a->queued);
8901 CU_ASSERT(b->queued);
8902 CU_ASSERT(!d->queued);
8903
8904 CU_ASSERT(1 == nghttp2_pq_size(&a->obq));
8905 CU_ASSERT(1 == nghttp2_pq_size(&c->obq));
8906 CU_ASSERT(nghttp2_pq_empty(&d->obq));
8907
8908 check_stream_dep_sib(c, root, d, NULL, NULL);
8909 check_stream_dep_sib(d, c, NULL, NULL, a);
8910 check_stream_dep_sib(a, c, b, d, NULL);
8911 check_stream_dep_sib(b, a, NULL, NULL, NULL);
8912
8913 nghttp2_session_del(session);
8914
8915 nghttp2_session_server_new(&session, &callbacks, NULL);
8916
8917 root = &session->root;
8918
8919 a = open_stream(session, 1);
8920 b = open_stream_with_dep(session, 3, a);
8921
8922 c = open_stream(session, 5);
8923 d = open_stream_with_dep(session, 7, c);
8924
8925 /* a c
8926 * | |
8927 * b d
8928 */
8929
8930 db = create_data_ob_item(mem);
8931 dc = create_data_ob_item(mem);
8932
8933 nghttp2_stream_attach_item(b, db);
8934 nghttp2_stream_attach_item(c, dc);
8935
8936 nghttp2_stream_dep_remove_subtree(c);
8937 CU_ASSERT(0 == nghttp2_stream_dep_insert_subtree(&session->root, c));
8938
8939 /*
8940 * c
8941 * |
8942 * d--a
8943 * |
8944 * b
8945 */
8946
8947 CU_ASSERT(c->queued);
8948 CU_ASSERT(a->queued);
8949 CU_ASSERT(b->queued);
8950 CU_ASSERT(!d->queued);
8951
8952 check_stream_dep_sib(c, root, d, NULL, NULL);
8953 check_stream_dep_sib(d, c, NULL, NULL, a);
8954 check_stream_dep_sib(a, c, b, d, NULL);
8955 check_stream_dep_sib(b, a, NULL, NULL, NULL);
8956
8957 nghttp2_session_del(session);
8958 }
8959
test_nghttp2_session_stream_attach_item(void)8960 void test_nghttp2_session_stream_attach_item(void) {
8961 nghttp2_session *session;
8962 nghttp2_session_callbacks callbacks;
8963 nghttp2_stream *a, *b, *c, *d, *e;
8964 nghttp2_outbound_item *da, *db, *dc, *dd;
8965 nghttp2_mem *mem;
8966
8967 mem = nghttp2_mem_default();
8968
8969 memset(&callbacks, 0, sizeof(callbacks));
8970
8971 nghttp2_session_server_new(&session, &callbacks, NULL);
8972
8973 a = open_stream(session, 1);
8974 b = open_stream_with_dep(session, 3, a);
8975 c = open_stream_with_dep(session, 5, a);
8976 d = open_stream_with_dep(session, 7, c);
8977
8978 /* a
8979 * |
8980 * c--b
8981 * |
8982 * d
8983 */
8984
8985 db = create_data_ob_item(mem);
8986
8987 nghttp2_stream_attach_item(b, db);
8988
8989 CU_ASSERT(a->queued);
8990 CU_ASSERT(b->queued);
8991 CU_ASSERT(!c->queued);
8992 CU_ASSERT(!d->queued);
8993
8994 CU_ASSERT(1 == nghttp2_pq_size(&a->obq));
8995
8996 /* Attach item to c */
8997 dc = create_data_ob_item(mem);
8998
8999 nghttp2_stream_attach_item(c, dc);
9000
9001 CU_ASSERT(a->queued);
9002 CU_ASSERT(b->queued);
9003 CU_ASSERT(c->queued);
9004 CU_ASSERT(!d->queued);
9005
9006 CU_ASSERT(2 == nghttp2_pq_size(&a->obq));
9007
9008 /* Attach item to a */
9009 da = create_data_ob_item(mem);
9010
9011 nghttp2_stream_attach_item(a, da);
9012
9013 CU_ASSERT(a->queued);
9014 CU_ASSERT(b->queued);
9015 CU_ASSERT(c->queued);
9016 CU_ASSERT(!d->queued);
9017
9018 CU_ASSERT(2 == nghttp2_pq_size(&a->obq));
9019
9020 /* Detach item from a */
9021 nghttp2_stream_detach_item(a);
9022
9023 CU_ASSERT(a->queued);
9024 CU_ASSERT(b->queued);
9025 CU_ASSERT(c->queued);
9026 CU_ASSERT(!d->queued);
9027
9028 CU_ASSERT(2 == nghttp2_pq_size(&a->obq));
9029
9030 /* Attach item to d */
9031 dd = create_data_ob_item(mem);
9032
9033 nghttp2_stream_attach_item(d, dd);
9034
9035 CU_ASSERT(a->queued);
9036 CU_ASSERT(b->queued);
9037 CU_ASSERT(c->queued);
9038 CU_ASSERT(d->queued);
9039
9040 CU_ASSERT(2 == nghttp2_pq_size(&a->obq));
9041 CU_ASSERT(1 == nghttp2_pq_size(&c->obq));
9042
9043 /* Detach item from c */
9044 nghttp2_stream_detach_item(c);
9045
9046 CU_ASSERT(a->queued);
9047 CU_ASSERT(b->queued);
9048 CU_ASSERT(c->queued);
9049 CU_ASSERT(d->queued);
9050
9051 CU_ASSERT(2 == nghttp2_pq_size(&a->obq));
9052 CU_ASSERT(1 == nghttp2_pq_size(&c->obq));
9053
9054 /* Detach item from b */
9055 nghttp2_stream_detach_item(b);
9056
9057 CU_ASSERT(a->queued);
9058 CU_ASSERT(!b->queued);
9059 CU_ASSERT(c->queued);
9060 CU_ASSERT(d->queued);
9061
9062 CU_ASSERT(1 == nghttp2_pq_size(&a->obq));
9063
9064 /* exercises insertion */
9065 e = open_stream_with_dep_excl(session, 9, a);
9066
9067 /* a
9068 * |
9069 * e
9070 * |
9071 * c--b
9072 * |
9073 * d
9074 */
9075
9076 CU_ASSERT(a->queued);
9077 CU_ASSERT(e->queued);
9078 CU_ASSERT(!b->queued);
9079 CU_ASSERT(c->queued);
9080 CU_ASSERT(d->queued);
9081
9082 CU_ASSERT(1 == nghttp2_pq_size(&a->obq));
9083 CU_ASSERT(1 == nghttp2_pq_size(&e->obq));
9084 CU_ASSERT(nghttp2_pq_empty(&b->obq));
9085 CU_ASSERT(1 == nghttp2_pq_size(&c->obq));
9086 CU_ASSERT(nghttp2_pq_empty(&d->obq));
9087
9088 /* exercises deletion */
9089 nghttp2_stream_dep_remove(e);
9090
9091 /* a
9092 * |
9093 * c--b
9094 * |
9095 * d
9096 */
9097
9098 CU_ASSERT(a->queued);
9099 CU_ASSERT(!b->queued);
9100 CU_ASSERT(c->queued);
9101 CU_ASSERT(d->queued);
9102
9103 CU_ASSERT(1 == nghttp2_pq_size(&a->obq));
9104 CU_ASSERT(nghttp2_pq_empty(&b->obq));
9105 CU_ASSERT(1 == nghttp2_pq_size(&c->obq));
9106 CU_ASSERT(nghttp2_pq_empty(&d->obq));
9107
9108 /* e's weight 16 is distributed equally among c and b, both now have
9109 weight 8 each. */
9110 CU_ASSERT(8 == b->weight);
9111 CU_ASSERT(8 == c->weight);
9112
9113 /* da, db, dc have been detached */
9114 nghttp2_outbound_item_free(da, mem);
9115 nghttp2_outbound_item_free(db, mem);
9116 nghttp2_outbound_item_free(dc, mem);
9117 free(da);
9118 free(db);
9119 free(dc);
9120
9121 nghttp2_session_del(session);
9122
9123 nghttp2_session_server_new(&session, &callbacks, NULL);
9124
9125 a = open_stream(session, 1);
9126 b = open_stream_with_dep(session, 3, a);
9127 c = open_stream_with_dep(session, 5, a);
9128 d = open_stream_with_dep(session, 7, c);
9129
9130 /* a
9131 * |
9132 * c--b
9133 * |
9134 * d
9135 */
9136
9137 da = create_data_ob_item(mem);
9138 db = create_data_ob_item(mem);
9139 dc = create_data_ob_item(mem);
9140
9141 nghttp2_stream_attach_item(a, da);
9142 nghttp2_stream_attach_item(b, db);
9143 nghttp2_stream_attach_item(c, dc);
9144
9145 CU_ASSERT(a->queued);
9146 CU_ASSERT(b->queued);
9147 CU_ASSERT(c->queued);
9148 CU_ASSERT(!d->queued);
9149
9150 CU_ASSERT(2 == nghttp2_pq_size(&a->obq));
9151 CU_ASSERT(nghttp2_pq_empty(&b->obq));
9152 CU_ASSERT(nghttp2_pq_empty(&c->obq));
9153 CU_ASSERT(nghttp2_pq_empty(&d->obq));
9154
9155 /* Detach item from a */
9156 nghttp2_stream_detach_item(a);
9157
9158 CU_ASSERT(a->queued);
9159 CU_ASSERT(b->queued);
9160 CU_ASSERT(c->queued);
9161 CU_ASSERT(!d->queued);
9162
9163 CU_ASSERT(2 == nghttp2_pq_size(&a->obq));
9164 CU_ASSERT(nghttp2_pq_empty(&b->obq));
9165 CU_ASSERT(nghttp2_pq_empty(&c->obq));
9166 CU_ASSERT(nghttp2_pq_empty(&d->obq));
9167
9168 /* da has been detached */
9169 nghttp2_outbound_item_free(da, mem);
9170 free(da);
9171
9172 nghttp2_session_del(session);
9173 }
9174
test_nghttp2_session_stream_attach_item_subtree(void)9175 void test_nghttp2_session_stream_attach_item_subtree(void) {
9176 nghttp2_session *session;
9177 nghttp2_session_callbacks callbacks;
9178 nghttp2_stream *a, *b, *c, *d, *e, *f;
9179 nghttp2_outbound_item *da, *db, *dd, *de;
9180 nghttp2_mem *mem;
9181
9182 mem = nghttp2_mem_default();
9183
9184 memset(&callbacks, 0, sizeof(callbacks));
9185
9186 nghttp2_session_server_new(&session, &callbacks, NULL);
9187
9188 a = open_stream(session, 1);
9189 b = open_stream_with_dep(session, 3, a);
9190 c = open_stream_with_dep(session, 5, a);
9191 d = open_stream_with_dep(session, 7, c);
9192
9193 e = open_stream_with_dep_weight(session, 9, 32, &session->root);
9194 f = open_stream_with_dep(session, 11, e);
9195
9196 /*
9197 * a e
9198 * | |
9199 * c--b f
9200 * |
9201 * d
9202 */
9203
9204 de = create_data_ob_item(mem);
9205
9206 nghttp2_stream_attach_item(e, de);
9207
9208 db = create_data_ob_item(mem);
9209
9210 nghttp2_stream_attach_item(b, db);
9211
9212 CU_ASSERT(a->queued);
9213 CU_ASSERT(b->queued);
9214 CU_ASSERT(!c->queued);
9215 CU_ASSERT(!d->queued);
9216 CU_ASSERT(e->queued);
9217 CU_ASSERT(!f->queued);
9218
9219 CU_ASSERT(1 == nghttp2_pq_size(&a->obq));
9220 CU_ASSERT(nghttp2_pq_empty(&b->obq));
9221 CU_ASSERT(nghttp2_pq_empty(&c->obq));
9222 CU_ASSERT(nghttp2_pq_empty(&d->obq));
9223 CU_ASSERT(nghttp2_pq_empty(&e->obq));
9224 CU_ASSERT(nghttp2_pq_empty(&f->obq));
9225
9226 /* Insert subtree e under a */
9227
9228 nghttp2_stream_dep_remove_subtree(e);
9229 nghttp2_stream_dep_insert_subtree(a, e);
9230
9231 /*
9232 * a
9233 * |
9234 * e
9235 * |
9236 * f--c--b
9237 * |
9238 * d
9239 */
9240
9241 CU_ASSERT(a->queued);
9242 CU_ASSERT(b->queued);
9243 CU_ASSERT(!c->queued);
9244 CU_ASSERT(!d->queued);
9245 CU_ASSERT(e->queued);
9246 CU_ASSERT(!f->queued);
9247
9248 CU_ASSERT(1 == nghttp2_pq_size(&a->obq));
9249 CU_ASSERT(nghttp2_pq_empty(&b->obq));
9250 CU_ASSERT(nghttp2_pq_empty(&c->obq));
9251 CU_ASSERT(nghttp2_pq_empty(&d->obq));
9252 CU_ASSERT(1 == nghttp2_pq_size(&e->obq));
9253 CU_ASSERT(nghttp2_pq_empty(&f->obq));
9254
9255 /* Remove subtree b */
9256
9257 nghttp2_stream_dep_remove_subtree(b);
9258
9259 CU_ASSERT(0 == nghttp2_stream_dep_add_subtree(&session->root, b));
9260
9261 /*
9262 * a b
9263 * |
9264 * e
9265 * |
9266 * f--c
9267 * |
9268 * d
9269 */
9270
9271 CU_ASSERT(a->queued);
9272 CU_ASSERT(b->queued);
9273 CU_ASSERT(!c->queued);
9274 CU_ASSERT(!d->queued);
9275 CU_ASSERT(e->queued);
9276 CU_ASSERT(!f->queued);
9277
9278 CU_ASSERT(1 == nghttp2_pq_size(&a->obq));
9279 CU_ASSERT(nghttp2_pq_empty(&b->obq));
9280 CU_ASSERT(nghttp2_pq_empty(&c->obq));
9281 CU_ASSERT(nghttp2_pq_empty(&d->obq));
9282 CU_ASSERT(nghttp2_pq_empty(&e->obq));
9283 CU_ASSERT(nghttp2_pq_empty(&f->obq));
9284
9285 /* Remove subtree a, and add it to root again */
9286
9287 nghttp2_stream_dep_remove_subtree(a);
9288
9289 CU_ASSERT(0 == nghttp2_stream_dep_add_subtree(&session->root, a));
9290
9291 CU_ASSERT(a->queued);
9292 CU_ASSERT(b->queued);
9293 CU_ASSERT(!c->queued);
9294 CU_ASSERT(!d->queued);
9295 CU_ASSERT(e->queued);
9296 CU_ASSERT(!f->queued);
9297
9298 CU_ASSERT(1 == nghttp2_pq_size(&a->obq));
9299 CU_ASSERT(nghttp2_pq_empty(&b->obq));
9300 CU_ASSERT(nghttp2_pq_empty(&c->obq));
9301 CU_ASSERT(nghttp2_pq_empty(&d->obq));
9302 CU_ASSERT(nghttp2_pq_empty(&e->obq));
9303 CU_ASSERT(nghttp2_pq_empty(&f->obq));
9304
9305 /* Remove subtree c */
9306
9307 nghttp2_stream_dep_remove_subtree(c);
9308
9309 CU_ASSERT(0 == nghttp2_stream_dep_add_subtree(&session->root, c));
9310
9311 /*
9312 * a b c
9313 * | |
9314 * e d
9315 * |
9316 * f
9317 */
9318
9319 CU_ASSERT(a->queued);
9320 CU_ASSERT(b->queued);
9321 CU_ASSERT(!c->queued);
9322 CU_ASSERT(!d->queued);
9323 CU_ASSERT(e->queued);
9324 CU_ASSERT(!f->queued);
9325
9326 CU_ASSERT(1 == nghttp2_pq_size(&a->obq));
9327 CU_ASSERT(nghttp2_pq_empty(&b->obq));
9328 CU_ASSERT(nghttp2_pq_empty(&c->obq));
9329 CU_ASSERT(nghttp2_pq_empty(&d->obq));
9330 CU_ASSERT(nghttp2_pq_empty(&e->obq));
9331 CU_ASSERT(nghttp2_pq_empty(&f->obq));
9332
9333 dd = create_data_ob_item(mem);
9334
9335 nghttp2_stream_attach_item(d, dd);
9336
9337 /* Add subtree c to a */
9338
9339 nghttp2_stream_dep_remove_subtree(c);
9340 nghttp2_stream_dep_add_subtree(a, c);
9341
9342 /*
9343 * a b
9344 * |
9345 * c--e
9346 * | |
9347 * d f
9348 */
9349
9350 CU_ASSERT(a->queued);
9351 CU_ASSERT(b->queued);
9352 CU_ASSERT(c->queued);
9353 CU_ASSERT(d->queued);
9354 CU_ASSERT(e->queued);
9355 CU_ASSERT(!f->queued);
9356
9357 CU_ASSERT(2 == nghttp2_pq_size(&a->obq));
9358 CU_ASSERT(nghttp2_pq_empty(&b->obq));
9359 CU_ASSERT(1 == nghttp2_pq_size(&c->obq));
9360 CU_ASSERT(nghttp2_pq_empty(&d->obq));
9361 CU_ASSERT(nghttp2_pq_empty(&e->obq));
9362 CU_ASSERT(nghttp2_pq_empty(&f->obq));
9363
9364 /* Insert b under a */
9365
9366 nghttp2_stream_dep_remove_subtree(b);
9367 nghttp2_stream_dep_insert_subtree(a, b);
9368
9369 /*
9370 * a
9371 * |
9372 * b
9373 * |
9374 * c--e
9375 * | |
9376 * d f
9377 */
9378
9379 CU_ASSERT(a->queued);
9380 CU_ASSERT(b->queued);
9381 CU_ASSERT(c->queued);
9382 CU_ASSERT(d->queued);
9383 CU_ASSERT(e->queued);
9384 CU_ASSERT(!f->queued);
9385
9386 CU_ASSERT(1 == nghttp2_pq_size(&a->obq));
9387 CU_ASSERT(2 == nghttp2_pq_size(&b->obq));
9388 CU_ASSERT(1 == nghttp2_pq_size(&c->obq));
9389 CU_ASSERT(nghttp2_pq_empty(&d->obq));
9390 CU_ASSERT(nghttp2_pq_empty(&e->obq));
9391 CU_ASSERT(nghttp2_pq_empty(&f->obq));
9392
9393 /* Remove subtree b */
9394
9395 nghttp2_stream_dep_remove_subtree(b);
9396 CU_ASSERT(0 == nghttp2_stream_dep_add_subtree(&session->root, b));
9397
9398 /*
9399 * b a
9400 * |
9401 * e--c
9402 * | |
9403 * f d
9404 */
9405
9406 CU_ASSERT(!a->queued);
9407 CU_ASSERT(b->queued);
9408 CU_ASSERT(c->queued);
9409 CU_ASSERT(d->queued);
9410 CU_ASSERT(e->queued);
9411 CU_ASSERT(!f->queued);
9412
9413 CU_ASSERT(nghttp2_pq_empty(&a->obq));
9414 CU_ASSERT(2 == nghttp2_pq_size(&b->obq));
9415 CU_ASSERT(1 == nghttp2_pq_size(&c->obq));
9416 CU_ASSERT(nghttp2_pq_empty(&d->obq));
9417 CU_ASSERT(nghttp2_pq_empty(&e->obq));
9418 CU_ASSERT(nghttp2_pq_empty(&f->obq));
9419
9420 /* Remove subtree c, and detach item from b, and then re-add
9421 subtree c under b */
9422
9423 nghttp2_stream_dep_remove_subtree(c);
9424 nghttp2_stream_detach_item(b);
9425 nghttp2_stream_dep_add_subtree(b, c);
9426
9427 /*
9428 * b a
9429 * |
9430 * e--c
9431 * | |
9432 * f d
9433 */
9434
9435 CU_ASSERT(!a->queued);
9436 CU_ASSERT(b->queued);
9437 CU_ASSERT(c->queued);
9438 CU_ASSERT(d->queued);
9439 CU_ASSERT(e->queued);
9440 CU_ASSERT(!f->queued);
9441
9442 CU_ASSERT(nghttp2_pq_empty(&a->obq));
9443 CU_ASSERT(2 == nghttp2_pq_size(&b->obq));
9444 CU_ASSERT(1 == nghttp2_pq_size(&c->obq));
9445 CU_ASSERT(nghttp2_pq_empty(&d->obq));
9446 CU_ASSERT(nghttp2_pq_empty(&e->obq));
9447 CU_ASSERT(nghttp2_pq_empty(&f->obq));
9448
9449 /* Attach data to a, and add subtree a under b */
9450
9451 da = create_data_ob_item(mem);
9452 nghttp2_stream_attach_item(a, da);
9453 nghttp2_stream_dep_remove_subtree(a);
9454 nghttp2_stream_dep_add_subtree(b, a);
9455
9456 /*
9457 * b
9458 * |
9459 * a--e--c
9460 * | |
9461 * f d
9462 */
9463
9464 CU_ASSERT(a->queued);
9465 CU_ASSERT(b->queued);
9466 CU_ASSERT(c->queued);
9467 CU_ASSERT(d->queued);
9468 CU_ASSERT(e->queued);
9469 CU_ASSERT(!f->queued);
9470
9471 CU_ASSERT(nghttp2_pq_empty(&a->obq));
9472 CU_ASSERT(3 == nghttp2_pq_size(&b->obq));
9473 CU_ASSERT(1 == nghttp2_pq_size(&c->obq));
9474 CU_ASSERT(nghttp2_pq_empty(&d->obq));
9475 CU_ASSERT(nghttp2_pq_empty(&e->obq));
9476 CU_ASSERT(nghttp2_pq_empty(&f->obq));
9477
9478 /* Remove subtree c, and add under f */
9479 nghttp2_stream_dep_remove_subtree(c);
9480 nghttp2_stream_dep_insert_subtree(f, c);
9481
9482 /*
9483 * b
9484 * |
9485 * a--e
9486 * |
9487 * f
9488 * |
9489 * c
9490 * |
9491 * d
9492 */
9493
9494 CU_ASSERT(a->queued);
9495 CU_ASSERT(b->queued);
9496 CU_ASSERT(c->queued);
9497 CU_ASSERT(d->queued);
9498 CU_ASSERT(e->queued);
9499 CU_ASSERT(f->queued);
9500
9501 CU_ASSERT(nghttp2_pq_empty(&a->obq));
9502 CU_ASSERT(2 == nghttp2_pq_size(&b->obq));
9503 CU_ASSERT(1 == nghttp2_pq_size(&c->obq));
9504 CU_ASSERT(nghttp2_pq_empty(&d->obq));
9505 CU_ASSERT(1 == nghttp2_pq_size(&e->obq));
9506 CU_ASSERT(1 == nghttp2_pq_size(&f->obq));
9507
9508 /* db has been detached */
9509 nghttp2_outbound_item_free(db, mem);
9510 free(db);
9511
9512 nghttp2_session_del(session);
9513 }
9514
test_nghttp2_session_stream_get_state(void)9515 void test_nghttp2_session_stream_get_state(void) {
9516 nghttp2_session *session;
9517 nghttp2_session_callbacks callbacks;
9518 nghttp2_mem *mem;
9519 nghttp2_hd_deflater deflater;
9520 nghttp2_bufs bufs;
9521 nghttp2_buf *buf;
9522 nghttp2_stream *stream;
9523 ssize_t rv;
9524 nghttp2_data_provider data_prd;
9525 nghttp2_frame frame;
9526
9527 mem = nghttp2_mem_default();
9528 frame_pack_bufs_init(&bufs);
9529 memset(&data_prd, 0, sizeof(data_prd));
9530
9531 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
9532 callbacks.send_callback = null_send_callback;
9533
9534 nghttp2_session_server_new(&session, &callbacks, NULL);
9535 nghttp2_hd_deflate_init(&deflater, mem);
9536
9537 CU_ASSERT(NGHTTP2_STREAM_STATE_IDLE ==
9538 nghttp2_stream_get_state(nghttp2_session_get_root_stream(session)));
9539
9540 /* stream 1 HEADERS; without END_STREAM flag set */
9541 pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, reqnv,
9542 ARRLEN(reqnv), mem);
9543
9544 buf = &bufs.head->buf;
9545 rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
9546
9547 CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv);
9548
9549 stream = nghttp2_session_find_stream(session, 1);
9550
9551 CU_ASSERT(NULL != stream);
9552 CU_ASSERT(1 == stream->stream_id);
9553 CU_ASSERT(NGHTTP2_STREAM_STATE_OPEN == nghttp2_stream_get_state(stream));
9554
9555 nghttp2_bufs_reset(&bufs);
9556
9557 /* stream 3 HEADERS; with END_STREAM flag set */
9558 pack_headers(&bufs, &deflater, 3,
9559 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM, reqnv,
9560 ARRLEN(reqnv), mem);
9561
9562 buf = &bufs.head->buf;
9563 rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
9564
9565 CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv);
9566
9567 stream = nghttp2_session_find_stream(session, 3);
9568
9569 CU_ASSERT(NULL != stream);
9570 CU_ASSERT(3 == stream->stream_id);
9571 CU_ASSERT(NGHTTP2_STREAM_STATE_HALF_CLOSED_REMOTE ==
9572 nghttp2_stream_get_state(stream));
9573
9574 nghttp2_bufs_reset(&bufs);
9575
9576 /* Respond to stream 1 */
9577 nghttp2_submit_response(session, 1, resnv, ARRLEN(resnv), NULL);
9578
9579 rv = nghttp2_session_send(session);
9580
9581 CU_ASSERT(0 == rv);
9582
9583 stream = nghttp2_session_find_stream(session, 1);
9584
9585 CU_ASSERT(NGHTTP2_STREAM_STATE_HALF_CLOSED_LOCAL ==
9586 nghttp2_stream_get_state(stream));
9587
9588 /* Respond to stream 3 */
9589 nghttp2_submit_response(session, 3, resnv, ARRLEN(resnv), NULL);
9590
9591 rv = nghttp2_session_send(session);
9592
9593 CU_ASSERT(0 == rv);
9594
9595 stream = nghttp2_session_find_stream(session, 3);
9596
9597 CU_ASSERT(NGHTTP2_STREAM_STATE_CLOSED == nghttp2_stream_get_state(stream));
9598
9599 /* stream 5 HEADERS; with END_STREAM flag set */
9600 pack_headers(&bufs, &deflater, 5,
9601 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM, reqnv,
9602 ARRLEN(reqnv), mem);
9603
9604 buf = &bufs.head->buf;
9605 rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
9606
9607 CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv);
9608
9609 nghttp2_bufs_reset(&bufs);
9610
9611 /* Push stream 2 associated to stream 5 */
9612 rv = nghttp2_submit_push_promise(session, NGHTTP2_FLAG_NONE, 5, reqnv,
9613 ARRLEN(reqnv), NULL);
9614
9615 CU_ASSERT(2 == rv);
9616
9617 rv = nghttp2_session_send(session);
9618
9619 CU_ASSERT(0 == rv);
9620
9621 stream = nghttp2_session_find_stream(session, 2);
9622
9623 CU_ASSERT(NGHTTP2_STREAM_STATE_RESERVED_LOCAL ==
9624 nghttp2_stream_get_state(stream));
9625
9626 /* Send response to push stream 2 with END_STREAM set */
9627 nghttp2_submit_response(session, 2, resnv, ARRLEN(resnv), NULL);
9628
9629 rv = nghttp2_session_send(session);
9630
9631 CU_ASSERT(0 == rv);
9632
9633 stream = nghttp2_session_find_stream(session, 2);
9634
9635 /* At server, pushed stream object is not retained after closed */
9636 CU_ASSERT(NULL == stream);
9637
9638 /* Push stream 4 associated to stream 5 */
9639 rv = nghttp2_submit_push_promise(session, NGHTTP2_FLAG_NONE, 5, reqnv,
9640 ARRLEN(reqnv), NULL);
9641
9642 CU_ASSERT(4 == rv);
9643
9644 rv = nghttp2_session_send(session);
9645
9646 CU_ASSERT(0 == rv);
9647
9648 stream = nghttp2_session_find_stream(session, 4);
9649
9650 CU_ASSERT(NGHTTP2_STREAM_STATE_RESERVED_LOCAL ==
9651 nghttp2_stream_get_state(stream));
9652
9653 /* Send response to push stream 4 without closing */
9654 data_prd.read_callback = defer_data_source_read_callback;
9655
9656 nghttp2_submit_response(session, 4, resnv, ARRLEN(resnv), &data_prd);
9657
9658 rv = nghttp2_session_send(session);
9659
9660 CU_ASSERT(0 == rv);
9661
9662 stream = nghttp2_session_find_stream(session, 4);
9663
9664 CU_ASSERT(NGHTTP2_STREAM_STATE_HALF_CLOSED_REMOTE ==
9665 nghttp2_stream_get_state(stream));
9666
9667 /* Create idle stream by PRIORITY frame */
9668 nghttp2_frame_priority_init(&frame.priority, 7, &pri_spec_default);
9669
9670 nghttp2_frame_pack_priority(&bufs, &frame.priority);
9671
9672 nghttp2_frame_priority_free(&frame.priority);
9673
9674 buf = &bufs.head->buf;
9675 rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
9676
9677 CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv);
9678
9679 stream = nghttp2_session_find_stream(session, 7);
9680
9681 CU_ASSERT(NGHTTP2_STREAM_STATE_IDLE == nghttp2_stream_get_state(stream));
9682
9683 nghttp2_bufs_reset(&bufs);
9684
9685 nghttp2_hd_deflate_free(&deflater);
9686 nghttp2_session_del(session);
9687
9688 /* Test for client side */
9689
9690 nghttp2_session_client_new(&session, &callbacks, NULL);
9691 nghttp2_hd_deflate_init(&deflater, mem);
9692
9693 nghttp2_submit_request(session, NULL, reqnv, ARRLEN(reqnv), NULL, NULL);
9694
9695 rv = nghttp2_session_send(session);
9696
9697 CU_ASSERT(0 == rv);
9698
9699 /* Receive PUSH_PROMISE 2 associated to stream 1 */
9700 pack_push_promise(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, 2, reqnv,
9701 ARRLEN(reqnv), mem);
9702
9703 buf = &bufs.head->buf;
9704 rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
9705
9706 CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv);
9707
9708 stream = nghttp2_session_find_stream(session, 2);
9709
9710 CU_ASSERT(NGHTTP2_STREAM_STATE_RESERVED_REMOTE ==
9711 nghttp2_stream_get_state(stream));
9712
9713 nghttp2_bufs_reset(&bufs);
9714
9715 /* Receive push response for stream 2 without END_STREAM set */
9716 pack_headers(&bufs, &deflater, 2, NGHTTP2_FLAG_END_HEADERS, resnv,
9717 ARRLEN(resnv), mem);
9718
9719 buf = &bufs.head->buf;
9720 rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
9721
9722 CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv);
9723
9724 stream = nghttp2_session_find_stream(session, 2);
9725
9726 CU_ASSERT(NGHTTP2_STREAM_STATE_HALF_CLOSED_LOCAL ==
9727 nghttp2_stream_get_state(stream));
9728
9729 nghttp2_bufs_reset(&bufs);
9730
9731 nghttp2_hd_deflate_free(&deflater);
9732 nghttp2_session_del(session);
9733
9734 nghttp2_bufs_free(&bufs);
9735 }
9736
test_nghttp2_session_stream_get_something(void)9737 void test_nghttp2_session_stream_get_something(void) {
9738 nghttp2_session *session;
9739 nghttp2_session_callbacks callbacks;
9740 nghttp2_stream *a, *b, *c;
9741
9742 memset(&callbacks, 0, sizeof(callbacks));
9743
9744 nghttp2_session_server_new(&session, &callbacks, NULL);
9745
9746 a = open_stream(session, 1);
9747
9748 CU_ASSERT(nghttp2_session_get_root_stream(session) ==
9749 nghttp2_stream_get_parent(a));
9750 CU_ASSERT(NULL == nghttp2_stream_get_previous_sibling(a));
9751 CU_ASSERT(NULL == nghttp2_stream_get_next_sibling(a));
9752 CU_ASSERT(NULL == nghttp2_stream_get_first_child(a));
9753
9754 b = open_stream_with_dep(session, 3, a);
9755 c = open_stream_with_dep_weight(session, 5, 11, a);
9756
9757 CU_ASSERT(a == nghttp2_stream_get_parent(c));
9758 CU_ASSERT(a == nghttp2_stream_get_parent(b));
9759
9760 CU_ASSERT(c == nghttp2_stream_get_first_child(a));
9761
9762 CU_ASSERT(b == nghttp2_stream_get_next_sibling(c));
9763 CU_ASSERT(c == nghttp2_stream_get_previous_sibling(b));
9764
9765 CU_ASSERT(27 == nghttp2_stream_get_sum_dependency_weight(a));
9766
9767 CU_ASSERT(11 == nghttp2_stream_get_weight(c));
9768 CU_ASSERT(5 == nghttp2_stream_get_stream_id(c));
9769 CU_ASSERT(0 == nghttp2_stream_get_stream_id(&session->root));
9770
9771 nghttp2_session_del(session);
9772 }
9773
test_nghttp2_session_find_stream(void)9774 void test_nghttp2_session_find_stream(void) {
9775 nghttp2_session *session;
9776 nghttp2_session_callbacks callbacks;
9777 nghttp2_stream *stream;
9778
9779 memset(&callbacks, 0, sizeof(callbacks));
9780
9781 nghttp2_session_server_new(&session, &callbacks, NULL);
9782
9783 open_recv_stream(session, 1);
9784
9785 stream = nghttp2_session_find_stream(session, 1);
9786
9787 CU_ASSERT(NULL != stream);
9788 CU_ASSERT(1 == stream->stream_id);
9789
9790 stream = nghttp2_session_find_stream(session, 0);
9791
9792 CU_ASSERT(&session->root == stream);
9793 CU_ASSERT(0 == stream->stream_id);
9794
9795 stream = nghttp2_session_find_stream(session, 2);
9796
9797 CU_ASSERT(NULL == stream);
9798
9799 nghttp2_session_del(session);
9800 }
9801
test_nghttp2_session_keep_closed_stream(void)9802 void test_nghttp2_session_keep_closed_stream(void) {
9803 nghttp2_session *session;
9804 nghttp2_session_callbacks callbacks;
9805 const size_t max_concurrent_streams = 5;
9806 nghttp2_settings_entry iv = {NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS,
9807 (uint32_t)max_concurrent_streams};
9808 size_t i;
9809
9810 memset(&callbacks, 0, sizeof(callbacks));
9811 callbacks.send_callback = null_send_callback;
9812
9813 nghttp2_session_server_new(&session, &callbacks, NULL);
9814
9815 nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, &iv, 1);
9816
9817 for (i = 0; i < max_concurrent_streams; ++i) {
9818 open_recv_stream(session, (int32_t)i * 2 + 1);
9819 }
9820
9821 CU_ASSERT(0 == session->num_closed_streams);
9822
9823 nghttp2_session_close_stream(session, 1, NGHTTP2_NO_ERROR);
9824
9825 CU_ASSERT(1 == session->num_closed_streams);
9826 CU_ASSERT(1 == session->closed_stream_tail->stream_id);
9827 CU_ASSERT(session->closed_stream_tail == session->closed_stream_head);
9828
9829 nghttp2_session_close_stream(session, 5, NGHTTP2_NO_ERROR);
9830
9831 CU_ASSERT(2 == session->num_closed_streams);
9832 CU_ASSERT(5 == session->closed_stream_tail->stream_id);
9833 CU_ASSERT(1 == session->closed_stream_head->stream_id);
9834 CU_ASSERT(session->closed_stream_head ==
9835 session->closed_stream_tail->closed_prev);
9836 CU_ASSERT(NULL == session->closed_stream_tail->closed_next);
9837 CU_ASSERT(session->closed_stream_tail ==
9838 session->closed_stream_head->closed_next);
9839 CU_ASSERT(NULL == session->closed_stream_head->closed_prev);
9840
9841 open_recv_stream(session, 11);
9842 nghttp2_session_adjust_closed_stream(session);
9843
9844 CU_ASSERT(1 == session->num_closed_streams);
9845 CU_ASSERT(5 == session->closed_stream_tail->stream_id);
9846 CU_ASSERT(session->closed_stream_tail == session->closed_stream_head);
9847 CU_ASSERT(NULL == session->closed_stream_head->closed_prev);
9848 CU_ASSERT(NULL == session->closed_stream_head->closed_next);
9849
9850 open_recv_stream(session, 13);
9851 nghttp2_session_adjust_closed_stream(session);
9852
9853 CU_ASSERT(0 == session->num_closed_streams);
9854 CU_ASSERT(NULL == session->closed_stream_tail);
9855 CU_ASSERT(NULL == session->closed_stream_head);
9856
9857 nghttp2_session_close_stream(session, 3, NGHTTP2_NO_ERROR);
9858
9859 CU_ASSERT(1 == session->num_closed_streams);
9860 CU_ASSERT(3 == session->closed_stream_head->stream_id);
9861
9862 /* server initiated stream is not counted to max concurrent limit */
9863 open_sent_stream(session, 2);
9864 nghttp2_session_adjust_closed_stream(session);
9865
9866 CU_ASSERT(1 == session->num_closed_streams);
9867 CU_ASSERT(3 == session->closed_stream_head->stream_id);
9868
9869 nghttp2_session_close_stream(session, 2, NGHTTP2_NO_ERROR);
9870
9871 CU_ASSERT(1 == session->num_closed_streams);
9872 CU_ASSERT(3 == session->closed_stream_head->stream_id);
9873
9874 nghttp2_session_del(session);
9875 }
9876
test_nghttp2_session_keep_idle_stream(void)9877 void test_nghttp2_session_keep_idle_stream(void) {
9878 nghttp2_session *session;
9879 nghttp2_session_callbacks callbacks;
9880 const size_t max_concurrent_streams = 1;
9881 nghttp2_settings_entry iv = {NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS,
9882 (uint32_t)max_concurrent_streams};
9883 int i;
9884 int32_t stream_id;
9885
9886 memset(&callbacks, 0, sizeof(callbacks));
9887 callbacks.send_callback = null_send_callback;
9888
9889 nghttp2_session_server_new(&session, &callbacks, NULL);
9890
9891 nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, &iv, 1);
9892
9893 /* We at least allow NGHTTP2_MIN_IDLE_STREAM idle streams even if
9894 max concurrent streams is very low. */
9895 for (i = 0; i < NGHTTP2_MIN_IDLE_STREAMS; ++i) {
9896 open_recv_stream2(session, i * 2 + 1, NGHTTP2_STREAM_IDLE);
9897 nghttp2_session_adjust_idle_stream(session);
9898 }
9899
9900 CU_ASSERT(NGHTTP2_MIN_IDLE_STREAMS == session->num_idle_streams);
9901
9902 stream_id = (NGHTTP2_MIN_IDLE_STREAMS - 1) * 2 + 1;
9903 CU_ASSERT(1 == session->idle_stream_head->stream_id);
9904 CU_ASSERT(stream_id == session->idle_stream_tail->stream_id);
9905
9906 stream_id += 2;
9907
9908 open_recv_stream2(session, stream_id, NGHTTP2_STREAM_IDLE);
9909 nghttp2_session_adjust_idle_stream(session);
9910
9911 CU_ASSERT(NGHTTP2_MIN_IDLE_STREAMS == session->num_idle_streams);
9912 CU_ASSERT(3 == session->idle_stream_head->stream_id);
9913 CU_ASSERT(stream_id == session->idle_stream_tail->stream_id);
9914
9915 nghttp2_session_del(session);
9916 }
9917
test_nghttp2_session_detach_idle_stream(void)9918 void test_nghttp2_session_detach_idle_stream(void) {
9919 nghttp2_session *session;
9920 nghttp2_session_callbacks callbacks;
9921 int i;
9922 nghttp2_stream *stream;
9923
9924 memset(&callbacks, 0, sizeof(callbacks));
9925 callbacks.send_callback = null_send_callback;
9926
9927 nghttp2_session_server_new(&session, &callbacks, NULL);
9928
9929 for (i = 1; i <= 3; ++i) {
9930 nghttp2_session_open_stream(session, i, NGHTTP2_STREAM_FLAG_NONE,
9931 &pri_spec_default, NGHTTP2_STREAM_IDLE, NULL);
9932 }
9933
9934 CU_ASSERT(3 == session->num_idle_streams);
9935
9936 /* Detach middle stream */
9937 stream = nghttp2_session_get_stream_raw(session, 2);
9938
9939 CU_ASSERT(session->idle_stream_head == stream->closed_prev);
9940 CU_ASSERT(session->idle_stream_tail == stream->closed_next);
9941 CU_ASSERT(stream == session->idle_stream_head->closed_next);
9942 CU_ASSERT(stream == session->idle_stream_tail->closed_prev);
9943
9944 nghttp2_session_detach_idle_stream(session, stream);
9945
9946 CU_ASSERT(2 == session->num_idle_streams);
9947
9948 CU_ASSERT(NULL == stream->closed_prev);
9949 CU_ASSERT(NULL == stream->closed_next);
9950
9951 CU_ASSERT(session->idle_stream_head ==
9952 session->idle_stream_tail->closed_prev);
9953 CU_ASSERT(session->idle_stream_tail ==
9954 session->idle_stream_head->closed_next);
9955
9956 /* Detach head stream */
9957 stream = session->idle_stream_head;
9958
9959 nghttp2_session_detach_idle_stream(session, stream);
9960
9961 CU_ASSERT(1 == session->num_idle_streams);
9962
9963 CU_ASSERT(session->idle_stream_head == session->idle_stream_tail);
9964 CU_ASSERT(NULL == session->idle_stream_head->closed_prev);
9965 CU_ASSERT(NULL == session->idle_stream_head->closed_next);
9966
9967 /* Detach last stream */
9968
9969 stream = session->idle_stream_head;
9970
9971 nghttp2_session_detach_idle_stream(session, stream);
9972
9973 CU_ASSERT(0 == session->num_idle_streams);
9974
9975 CU_ASSERT(NULL == session->idle_stream_head);
9976 CU_ASSERT(NULL == session->idle_stream_tail);
9977
9978 for (i = 4; i <= 5; ++i) {
9979 nghttp2_session_open_stream(session, i, NGHTTP2_STREAM_FLAG_NONE,
9980 &pri_spec_default, NGHTTP2_STREAM_IDLE, NULL);
9981 }
9982
9983 CU_ASSERT(2 == session->num_idle_streams);
9984
9985 /* Detach tail stream */
9986
9987 stream = session->idle_stream_tail;
9988
9989 nghttp2_session_detach_idle_stream(session, stream);
9990
9991 CU_ASSERT(1 == session->num_idle_streams);
9992
9993 CU_ASSERT(session->idle_stream_head == session->idle_stream_tail);
9994 CU_ASSERT(NULL == session->idle_stream_head->closed_prev);
9995 CU_ASSERT(NULL == session->idle_stream_head->closed_next);
9996
9997 nghttp2_session_del(session);
9998 }
9999
test_nghttp2_session_large_dep_tree(void)10000 void test_nghttp2_session_large_dep_tree(void) {
10001 nghttp2_session *session;
10002 nghttp2_session_callbacks callbacks;
10003 size_t i;
10004 nghttp2_stream *dep_stream = NULL;
10005 nghttp2_stream *stream;
10006 int32_t stream_id;
10007
10008 memset(&callbacks, 0, sizeof(callbacks));
10009 callbacks.send_callback = null_send_callback;
10010
10011 nghttp2_session_server_new(&session, &callbacks, NULL);
10012
10013 stream_id = 1;
10014 for (i = 0; i < 250; ++i, stream_id += 2) {
10015 dep_stream = open_stream_with_dep(session, stream_id, dep_stream);
10016 }
10017
10018 stream_id = 1;
10019 for (i = 0; i < 250; ++i, stream_id += 2) {
10020 stream = nghttp2_session_get_stream(session, stream_id);
10021 CU_ASSERT(nghttp2_stream_dep_find_ancestor(stream, &session->root));
10022 CU_ASSERT(nghttp2_stream_in_dep_tree(stream));
10023 }
10024
10025 nghttp2_session_del(session);
10026 }
10027
test_nghttp2_session_graceful_shutdown(void)10028 void test_nghttp2_session_graceful_shutdown(void) {
10029 nghttp2_session *session;
10030 nghttp2_session_callbacks callbacks;
10031 my_user_data ud;
10032
10033 memset(&callbacks, 0, sizeof(callbacks));
10034 callbacks.send_callback = null_send_callback;
10035 callbacks.on_frame_send_callback = on_frame_send_callback;
10036 callbacks.on_stream_close_callback = on_stream_close_callback;
10037
10038 nghttp2_session_server_new(&session, &callbacks, &ud);
10039
10040 open_recv_stream(session, 301);
10041 open_sent_stream(session, 302);
10042 open_recv_stream(session, 309);
10043 open_recv_stream(session, 311);
10044 open_recv_stream(session, 319);
10045
10046 CU_ASSERT(0 == nghttp2_submit_shutdown_notice(session));
10047
10048 ud.frame_send_cb_called = 0;
10049
10050 CU_ASSERT(0 == nghttp2_session_send(session));
10051
10052 CU_ASSERT(1 == ud.frame_send_cb_called);
10053 CU_ASSERT((1u << 31) - 1 == session->local_last_stream_id);
10054
10055 CU_ASSERT(0 == nghttp2_submit_goaway(session, NGHTTP2_FLAG_NONE, 311,
10056 NGHTTP2_NO_ERROR, NULL, 0));
10057
10058 ud.frame_send_cb_called = 0;
10059 ud.stream_close_cb_called = 0;
10060
10061 CU_ASSERT(0 == nghttp2_session_send(session));
10062
10063 CU_ASSERT(1 == ud.frame_send_cb_called);
10064 CU_ASSERT(311 == session->local_last_stream_id);
10065 CU_ASSERT(1 == ud.stream_close_cb_called);
10066
10067 CU_ASSERT(0 ==
10068 nghttp2_session_terminate_session2(session, 301, NGHTTP2_NO_ERROR));
10069
10070 ud.frame_send_cb_called = 0;
10071 ud.stream_close_cb_called = 0;
10072
10073 CU_ASSERT(0 == nghttp2_session_send(session));
10074
10075 CU_ASSERT(1 == ud.frame_send_cb_called);
10076 CU_ASSERT(301 == session->local_last_stream_id);
10077 CU_ASSERT(2 == ud.stream_close_cb_called);
10078
10079 CU_ASSERT(NULL != nghttp2_session_get_stream(session, 301));
10080 CU_ASSERT(NULL != nghttp2_session_get_stream(session, 302));
10081 CU_ASSERT(NULL == nghttp2_session_get_stream(session, 309));
10082 CU_ASSERT(NULL == nghttp2_session_get_stream(session, 311));
10083 CU_ASSERT(NULL == nghttp2_session_get_stream(session, 319));
10084
10085 nghttp2_session_del(session);
10086 }
10087
test_nghttp2_session_on_header_temporal_failure(void)10088 void test_nghttp2_session_on_header_temporal_failure(void) {
10089 nghttp2_session *session;
10090 nghttp2_session_callbacks callbacks;
10091 my_user_data ud;
10092 nghttp2_bufs bufs;
10093 nghttp2_buf *buf;
10094 nghttp2_hd_deflater deflater;
10095 nghttp2_nv nv[] = {MAKE_NV("alpha", "bravo"), MAKE_NV("charlie", "delta")};
10096 nghttp2_nv *nva;
10097 size_t hdpos;
10098 ssize_t rv;
10099 nghttp2_frame frame;
10100 nghttp2_frame_hd hd;
10101 nghttp2_outbound_item *item;
10102 nghttp2_mem *mem;
10103
10104 mem = nghttp2_mem_default();
10105 memset(&callbacks, 0, sizeof(callbacks));
10106 callbacks.on_header_callback = temporal_failure_on_header_callback;
10107
10108 nghttp2_session_server_new(&session, &callbacks, &ud);
10109
10110 frame_pack_bufs_init(&bufs);
10111
10112 nghttp2_hd_deflate_init(&deflater, mem);
10113
10114 nghttp2_nv_array_copy(&nva, reqnv, ARRLEN(reqnv), mem);
10115
10116 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_STREAM, 1,
10117 NGHTTP2_HCAT_REQUEST, NULL, nva, ARRLEN(reqnv));
10118 nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
10119 nghttp2_frame_headers_free(&frame.headers, mem);
10120
10121 /* We are going to create CONTINUATION. First serialize header
10122 block, and then frame header. */
10123 hdpos = nghttp2_bufs_len(&bufs);
10124
10125 buf = &bufs.head->buf;
10126 buf->last += NGHTTP2_FRAME_HDLEN;
10127
10128 nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, &nv[1], 1);
10129
10130 nghttp2_frame_hd_init(&hd,
10131 nghttp2_bufs_len(&bufs) - hdpos - NGHTTP2_FRAME_HDLEN,
10132 NGHTTP2_CONTINUATION, NGHTTP2_FLAG_END_HEADERS, 1);
10133
10134 nghttp2_frame_pack_frame_hd(&buf->pos[hdpos], &hd);
10135
10136 ud.header_cb_called = 0;
10137 rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_bufs_len(&bufs));
10138
10139 CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == rv);
10140 CU_ASSERT(1 == ud.header_cb_called);
10141
10142 item = nghttp2_session_get_next_ob_item(session);
10143
10144 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
10145 CU_ASSERT(1 == item->frame.hd.stream_id);
10146
10147 /* Make sure no header decompression error occurred */
10148 CU_ASSERT(NGHTTP2_GOAWAY_NONE == session->goaway_flags);
10149
10150 nghttp2_hd_deflate_free(&deflater);
10151 nghttp2_session_del(session);
10152
10153 nghttp2_bufs_reset(&bufs);
10154
10155 /* Check for PUSH_PROMISE */
10156 nghttp2_hd_deflate_init(&deflater, mem);
10157 nghttp2_session_client_new(&session, &callbacks, &ud);
10158
10159 open_sent_stream(session, 1);
10160
10161 rv = pack_push_promise(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, 2,
10162 reqnv, ARRLEN(reqnv), mem);
10163 CU_ASSERT(0 == rv);
10164
10165 ud.header_cb_called = 0;
10166 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
10167 nghttp2_bufs_len(&bufs));
10168 CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == rv);
10169 CU_ASSERT(1 == ud.header_cb_called);
10170
10171 item = nghttp2_session_get_next_ob_item(session);
10172 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
10173 CU_ASSERT(2 == item->frame.hd.stream_id);
10174 CU_ASSERT(NGHTTP2_INTERNAL_ERROR == item->frame.rst_stream.error_code);
10175
10176 nghttp2_session_del(session);
10177 nghttp2_hd_deflate_free(&deflater);
10178 nghttp2_bufs_free(&bufs);
10179 }
10180
test_nghttp2_session_recv_client_magic(void)10181 void test_nghttp2_session_recv_client_magic(void) {
10182 nghttp2_session *session;
10183 nghttp2_session_callbacks callbacks;
10184 ssize_t rv;
10185 nghttp2_frame ping_frame;
10186 uint8_t buf[16];
10187
10188 /* enable global nghttp2_enable_strict_preface here */
10189 nghttp2_enable_strict_preface = 1;
10190
10191 memset(&callbacks, 0, sizeof(callbacks));
10192
10193 /* Check success case */
10194 nghttp2_session_server_new(&session, &callbacks, NULL);
10195
10196 rv = nghttp2_session_mem_recv(session, (const uint8_t *)NGHTTP2_CLIENT_MAGIC,
10197 NGHTTP2_CLIENT_MAGIC_LEN);
10198
10199 CU_ASSERT(rv == NGHTTP2_CLIENT_MAGIC_LEN);
10200 CU_ASSERT(NGHTTP2_IB_READ_FIRST_SETTINGS == session->iframe.state);
10201
10202 /* Receiving PING is error because we want SETTINGS. */
10203 nghttp2_frame_ping_init(&ping_frame.ping, NGHTTP2_FLAG_NONE, NULL);
10204
10205 nghttp2_frame_pack_frame_hd(buf, &ping_frame.ping.hd);
10206
10207 rv = nghttp2_session_mem_recv(session, buf, NGHTTP2_FRAME_HDLEN);
10208 CU_ASSERT(NGHTTP2_FRAME_HDLEN == rv);
10209 CU_ASSERT(NGHTTP2_IB_IGN_ALL == session->iframe.state);
10210 CU_ASSERT(0 == session->iframe.payloadleft);
10211
10212 nghttp2_frame_ping_free(&ping_frame.ping);
10213
10214 nghttp2_session_del(session);
10215
10216 /* Check bad case */
10217 nghttp2_session_server_new(&session, &callbacks, NULL);
10218
10219 /* Feed magic with one byte less */
10220 rv = nghttp2_session_mem_recv(session, (const uint8_t *)NGHTTP2_CLIENT_MAGIC,
10221 NGHTTP2_CLIENT_MAGIC_LEN - 1);
10222
10223 CU_ASSERT(rv == NGHTTP2_CLIENT_MAGIC_LEN - 1);
10224 CU_ASSERT(NGHTTP2_IB_READ_CLIENT_MAGIC == session->iframe.state);
10225 CU_ASSERT(1 == session->iframe.payloadleft);
10226
10227 rv = nghttp2_session_mem_recv(session, (const uint8_t *)"\0", 1);
10228
10229 CU_ASSERT(NGHTTP2_ERR_BAD_CLIENT_MAGIC == rv);
10230
10231 nghttp2_session_del(session);
10232
10233 /* disable global nghttp2_enable_strict_preface here */
10234 nghttp2_enable_strict_preface = 0;
10235 }
10236
test_nghttp2_session_delete_data_item(void)10237 void test_nghttp2_session_delete_data_item(void) {
10238 nghttp2_session *session;
10239 nghttp2_session_callbacks callbacks;
10240 nghttp2_stream *a;
10241 nghttp2_data_provider prd;
10242
10243 memset(&callbacks, 0, sizeof(callbacks));
10244
10245 nghttp2_session_server_new(&session, &callbacks, NULL);
10246
10247 a = open_recv_stream(session, 1);
10248 open_recv_stream_with_dep(session, 3, a);
10249
10250 /* We don't care about these members, since we won't send data */
10251 prd.source.ptr = NULL;
10252 prd.read_callback = fail_data_source_read_callback;
10253
10254 CU_ASSERT(0 == nghttp2_submit_data(session, NGHTTP2_FLAG_NONE, 1, &prd));
10255 CU_ASSERT(0 == nghttp2_submit_data(session, NGHTTP2_FLAG_NONE, 3, &prd));
10256
10257 nghttp2_session_del(session);
10258 }
10259
test_nghttp2_session_open_idle_stream(void)10260 void test_nghttp2_session_open_idle_stream(void) {
10261 nghttp2_session *session;
10262 nghttp2_session_callbacks callbacks;
10263 nghttp2_stream *stream;
10264 nghttp2_stream *opened_stream;
10265 nghttp2_priority_spec pri_spec;
10266 nghttp2_frame frame;
10267
10268 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
10269
10270 nghttp2_session_server_new(&session, &callbacks, NULL);
10271
10272 nghttp2_priority_spec_init(&pri_spec, 0, 3, 0);
10273
10274 nghttp2_frame_priority_init(&frame.priority, 1, &pri_spec);
10275
10276 CU_ASSERT(0 == nghttp2_session_on_priority_received(session, &frame));
10277
10278 stream = nghttp2_session_get_stream_raw(session, 1);
10279
10280 CU_ASSERT(NGHTTP2_STREAM_IDLE == stream->state);
10281 CU_ASSERT(NULL == stream->closed_prev);
10282 CU_ASSERT(NULL == stream->closed_next);
10283 CU_ASSERT(1 == session->num_idle_streams);
10284 CU_ASSERT(session->idle_stream_head == stream);
10285 CU_ASSERT(session->idle_stream_tail == stream);
10286
10287 opened_stream = open_recv_stream2(session, 1, NGHTTP2_STREAM_OPENING);
10288
10289 CU_ASSERT(stream == opened_stream);
10290 CU_ASSERT(NGHTTP2_STREAM_OPENING == stream->state);
10291 CU_ASSERT(0 == session->num_idle_streams);
10292 CU_ASSERT(NULL == session->idle_stream_head);
10293 CU_ASSERT(NULL == session->idle_stream_tail);
10294
10295 nghttp2_frame_priority_free(&frame.priority);
10296
10297 nghttp2_session_del(session);
10298 }
10299
test_nghttp2_session_cancel_reserved_remote(void)10300 void test_nghttp2_session_cancel_reserved_remote(void) {
10301 nghttp2_session *session;
10302 nghttp2_session_callbacks callbacks;
10303 nghttp2_stream *stream;
10304 nghttp2_frame frame;
10305 nghttp2_nv *nva;
10306 size_t nvlen;
10307 nghttp2_hd_deflater deflater;
10308 nghttp2_mem *mem;
10309 nghttp2_bufs bufs;
10310 ssize_t rv;
10311
10312 mem = nghttp2_mem_default();
10313 frame_pack_bufs_init(&bufs);
10314
10315 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
10316 callbacks.send_callback = null_send_callback;
10317
10318 nghttp2_session_client_new(&session, &callbacks, NULL);
10319
10320 nghttp2_hd_deflate_init(&deflater, mem);
10321
10322 stream = open_recv_stream2(session, 2, NGHTTP2_STREAM_RESERVED);
10323
10324 nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, 2, NGHTTP2_CANCEL);
10325
10326 CU_ASSERT(NGHTTP2_STREAM_CLOSING == stream->state);
10327
10328 CU_ASSERT(0 == nghttp2_session_send(session));
10329
10330 nvlen = ARRLEN(resnv);
10331 nghttp2_nv_array_copy(&nva, resnv, nvlen, mem);
10332
10333 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 2,
10334 NGHTTP2_HCAT_PUSH_RESPONSE, NULL, nva, nvlen);
10335 rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
10336
10337 CU_ASSERT(0 == rv);
10338
10339 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
10340 nghttp2_buf_len(&bufs.head->buf));
10341
10342 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
10343
10344 /* stream is not dangling, so assign NULL */
10345 stream = NULL;
10346
10347 /* No RST_STREAM or GOAWAY is generated since stream should be in
10348 NGHTTP2_STREAM_CLOSING and push response should be ignored. */
10349 CU_ASSERT(0 == nghttp2_outbound_queue_size(&session->ob_reg));
10350
10351 /* Check that we can receive push response HEADERS while RST_STREAM
10352 is just queued. */
10353 open_recv_stream2(session, 4, NGHTTP2_STREAM_RESERVED);
10354
10355 nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, 2, NGHTTP2_CANCEL);
10356
10357 nghttp2_bufs_reset(&bufs);
10358
10359 frame.hd.stream_id = 4;
10360 rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
10361
10362 CU_ASSERT(0 == rv);
10363
10364 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
10365 nghttp2_buf_len(&bufs.head->buf));
10366
10367 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
10368
10369 CU_ASSERT(1 == nghttp2_outbound_queue_size(&session->ob_reg));
10370
10371 nghttp2_frame_headers_free(&frame.headers, mem);
10372
10373 nghttp2_hd_deflate_free(&deflater);
10374
10375 nghttp2_session_del(session);
10376
10377 nghttp2_bufs_free(&bufs);
10378 }
10379
test_nghttp2_session_reset_pending_headers(void)10380 void test_nghttp2_session_reset_pending_headers(void) {
10381 nghttp2_session *session;
10382 nghttp2_session_callbacks callbacks;
10383 nghttp2_stream *stream;
10384 int32_t stream_id;
10385 my_user_data ud;
10386
10387 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
10388 callbacks.send_callback = null_send_callback;
10389 callbacks.on_frame_send_callback = on_frame_send_callback;
10390 callbacks.on_frame_not_send_callback = on_frame_not_send_callback;
10391 callbacks.on_stream_close_callback = on_stream_close_callback;
10392
10393 nghttp2_session_client_new(&session, &callbacks, &ud);
10394
10395 stream_id = nghttp2_submit_request(session, NULL, NULL, 0, NULL, NULL);
10396 CU_ASSERT(stream_id >= 1);
10397
10398 nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, stream_id,
10399 NGHTTP2_CANCEL);
10400
10401 session->remote_settings.max_concurrent_streams = 0;
10402
10403 /* RST_STREAM cancels pending HEADERS and is not actually sent. */
10404 ud.frame_send_cb_called = 0;
10405 CU_ASSERT(0 == nghttp2_session_send(session));
10406
10407 CU_ASSERT(0 == ud.frame_send_cb_called);
10408
10409 stream = nghttp2_session_get_stream(session, stream_id);
10410
10411 CU_ASSERT(NULL == stream);
10412
10413 /* See HEADERS is not sent. on_stream_close is called just like
10414 transmission failure. */
10415 session->remote_settings.max_concurrent_streams = 1;
10416
10417 ud.frame_not_send_cb_called = 0;
10418 ud.stream_close_error_code = 0;
10419 CU_ASSERT(0 == nghttp2_session_send(session));
10420
10421 CU_ASSERT(1 == ud.frame_not_send_cb_called);
10422 CU_ASSERT(NGHTTP2_HEADERS == ud.not_sent_frame_type);
10423 CU_ASSERT(NGHTTP2_CANCEL == ud.stream_close_error_code);
10424
10425 stream = nghttp2_session_get_stream(session, stream_id);
10426
10427 CU_ASSERT(NULL == stream);
10428
10429 nghttp2_session_del(session);
10430 }
10431
test_nghttp2_session_send_data_callback(void)10432 void test_nghttp2_session_send_data_callback(void) {
10433 nghttp2_session *session;
10434 nghttp2_session_callbacks callbacks;
10435 nghttp2_data_provider data_prd;
10436 my_user_data ud;
10437 accumulator acc;
10438 nghttp2_frame_hd hd;
10439
10440 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
10441 callbacks.send_callback = accumulator_send_callback;
10442 callbacks.send_data_callback = send_data_callback;
10443
10444 data_prd.read_callback = no_copy_data_source_read_callback;
10445
10446 acc.length = 0;
10447 ud.acc = &acc;
10448
10449 ud.data_source_length = NGHTTP2_DATA_PAYLOADLEN * 2;
10450
10451 nghttp2_session_client_new(&session, &callbacks, &ud);
10452
10453 open_sent_stream(session, 1);
10454
10455 nghttp2_submit_data(session, NGHTTP2_FLAG_END_STREAM, 1, &data_prd);
10456
10457 CU_ASSERT(0 == nghttp2_session_send(session));
10458
10459 CU_ASSERT((NGHTTP2_FRAME_HDLEN + NGHTTP2_DATA_PAYLOADLEN) * 2 == acc.length);
10460
10461 nghttp2_frame_unpack_frame_hd(&hd, acc.buf);
10462
10463 CU_ASSERT(16384 == hd.length);
10464 CU_ASSERT(NGHTTP2_DATA == hd.type);
10465 CU_ASSERT(NGHTTP2_FLAG_NONE == hd.flags);
10466
10467 nghttp2_frame_unpack_frame_hd(&hd, acc.buf + NGHTTP2_FRAME_HDLEN + hd.length);
10468
10469 CU_ASSERT(16384 == hd.length);
10470 CU_ASSERT(NGHTTP2_DATA == hd.type);
10471 CU_ASSERT(NGHTTP2_FLAG_END_STREAM == hd.flags);
10472
10473 nghttp2_session_del(session);
10474 }
10475
test_nghttp2_session_on_begin_headers_temporal_failure(void)10476 void test_nghttp2_session_on_begin_headers_temporal_failure(void) {
10477 nghttp2_session *session;
10478 nghttp2_session_callbacks callbacks;
10479 my_user_data ud;
10480 nghttp2_bufs bufs;
10481 nghttp2_mem *mem;
10482 ssize_t rv;
10483 nghttp2_hd_deflater deflater;
10484 nghttp2_outbound_item *item;
10485
10486 mem = nghttp2_mem_default();
10487 frame_pack_bufs_init(&bufs);
10488 nghttp2_hd_deflate_init(&deflater, mem);
10489
10490 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
10491 callbacks.on_begin_headers_callback =
10492 temporal_failure_on_begin_headers_callback;
10493 callbacks.on_header_callback = on_header_callback;
10494 callbacks.on_frame_recv_callback = on_frame_recv_callback;
10495 callbacks.send_callback = null_send_callback;
10496 nghttp2_session_server_new(&session, &callbacks, &ud);
10497
10498 rv = pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, reqnv,
10499 ARRLEN(reqnv), mem);
10500 CU_ASSERT(0 == rv);
10501
10502 ud.header_cb_called = 0;
10503 ud.frame_recv_cb_called = 0;
10504 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
10505 nghttp2_bufs_len(&bufs));
10506 CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == rv);
10507 CU_ASSERT(0 == ud.header_cb_called);
10508 CU_ASSERT(0 == ud.frame_recv_cb_called);
10509
10510 item = nghttp2_session_get_next_ob_item(session);
10511 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
10512 CU_ASSERT(1 == item->frame.hd.stream_id);
10513 CU_ASSERT(NGHTTP2_INTERNAL_ERROR == item->frame.rst_stream.error_code);
10514
10515 nghttp2_session_del(session);
10516 nghttp2_hd_deflate_free(&deflater);
10517
10518 nghttp2_bufs_reset(&bufs);
10519 /* check for PUSH_PROMISE */
10520 nghttp2_hd_deflate_init(&deflater, mem);
10521 nghttp2_session_client_new(&session, &callbacks, &ud);
10522
10523 open_sent_stream(session, 1);
10524
10525 rv = pack_push_promise(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, 2,
10526 reqnv, ARRLEN(reqnv), mem);
10527 CU_ASSERT(0 == rv);
10528
10529 ud.header_cb_called = 0;
10530 ud.frame_recv_cb_called = 0;
10531 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
10532 nghttp2_bufs_len(&bufs));
10533 CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == rv);
10534 CU_ASSERT(0 == ud.header_cb_called);
10535 CU_ASSERT(0 == ud.frame_recv_cb_called);
10536
10537 item = nghttp2_session_get_next_ob_item(session);
10538 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
10539 CU_ASSERT(2 == item->frame.hd.stream_id);
10540 CU_ASSERT(NGHTTP2_INTERNAL_ERROR == item->frame.rst_stream.error_code);
10541
10542 nghttp2_session_del(session);
10543 nghttp2_hd_deflate_free(&deflater);
10544 nghttp2_bufs_free(&bufs);
10545 }
10546
test_nghttp2_session_defer_then_close(void)10547 void test_nghttp2_session_defer_then_close(void) {
10548 nghttp2_session *session;
10549 nghttp2_session_callbacks callbacks;
10550 nghttp2_data_provider prd;
10551 int rv;
10552 const uint8_t *datap;
10553 ssize_t datalen;
10554 nghttp2_frame frame;
10555
10556 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
10557 callbacks.send_callback = null_send_callback;
10558
10559 nghttp2_session_client_new(&session, &callbacks, NULL);
10560
10561 prd.read_callback = defer_data_source_read_callback;
10562
10563 rv = nghttp2_submit_request(session, NULL, reqnv, ARRLEN(reqnv), &prd, NULL);
10564 CU_ASSERT(rv > 0);
10565
10566 /* This sends HEADERS */
10567 datalen = nghttp2_session_mem_send(session, &datap);
10568
10569 CU_ASSERT(datalen > 0);
10570
10571 /* This makes DATA item deferred */
10572 datalen = nghttp2_session_mem_send(session, &datap);
10573
10574 CU_ASSERT(datalen == 0);
10575
10576 nghttp2_frame_rst_stream_init(&frame.rst_stream, 1, NGHTTP2_CANCEL);
10577
10578 /* Assertion failure; GH-264 */
10579 rv = nghttp2_session_on_rst_stream_received(session, &frame);
10580
10581 CU_ASSERT(rv == 0);
10582
10583 nghttp2_session_del(session);
10584 }
10585
submit_response_on_stream_close(nghttp2_session * session,int32_t stream_id,uint32_t error_code,void * user_data)10586 static int submit_response_on_stream_close(nghttp2_session *session,
10587 int32_t stream_id,
10588 uint32_t error_code,
10589 void *user_data) {
10590 nghttp2_data_provider data_prd;
10591 (void)error_code;
10592 (void)user_data;
10593
10594 data_prd.read_callback = temporal_failure_data_source_read_callback;
10595
10596 // Attempt to submit response or data to the stream being closed
10597 switch (stream_id) {
10598 case 1:
10599 CU_ASSERT(0 == nghttp2_submit_response(session, stream_id, resnv,
10600 ARRLEN(resnv), &data_prd));
10601 break;
10602 case 3:
10603 CU_ASSERT(0 == nghttp2_submit_data(session, NGHTTP2_FLAG_NONE, stream_id,
10604 &data_prd));
10605 break;
10606 }
10607
10608 return 0;
10609 }
10610
test_nghttp2_session_detach_item_from_closed_stream(void)10611 void test_nghttp2_session_detach_item_from_closed_stream(void) {
10612 nghttp2_session *session;
10613 nghttp2_session_callbacks callbacks;
10614
10615 memset(&callbacks, 0, sizeof(callbacks));
10616
10617 callbacks.send_callback = null_send_callback;
10618 callbacks.on_stream_close_callback = submit_response_on_stream_close;
10619
10620 nghttp2_session_server_new(&session, &callbacks, NULL);
10621
10622 open_recv_stream(session, 1);
10623 open_recv_stream(session, 3);
10624
10625 nghttp2_session_close_stream(session, 1, NGHTTP2_NO_ERROR);
10626 nghttp2_session_close_stream(session, 3, NGHTTP2_NO_ERROR);
10627
10628 CU_ASSERT(0 == nghttp2_session_send(session));
10629
10630 nghttp2_session_del(session);
10631 }
10632
test_nghttp2_session_flooding(void)10633 void test_nghttp2_session_flooding(void) {
10634 nghttp2_session *session;
10635 nghttp2_session_callbacks callbacks;
10636 nghttp2_bufs bufs;
10637 nghttp2_buf *buf;
10638 nghttp2_frame frame;
10639 nghttp2_mem *mem;
10640 size_t i;
10641
10642 mem = nghttp2_mem_default();
10643
10644 frame_pack_bufs_init(&bufs);
10645
10646 memset(&callbacks, 0, sizeof(callbacks));
10647
10648 /* PING ACK */
10649 nghttp2_session_server_new(&session, &callbacks, NULL);
10650
10651 nghttp2_frame_ping_init(&frame.ping, NGHTTP2_FLAG_NONE, NULL);
10652 nghttp2_frame_pack_ping(&bufs, &frame.ping);
10653 nghttp2_frame_ping_free(&frame.ping);
10654
10655 buf = &bufs.head->buf;
10656
10657 for (i = 0; i < NGHTTP2_DEFAULT_MAX_OBQ_FLOOD_ITEM; ++i) {
10658 CU_ASSERT(
10659 (ssize_t)nghttp2_buf_len(buf) ==
10660 nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf)));
10661 }
10662
10663 CU_ASSERT(NGHTTP2_ERR_FLOODED ==
10664 nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf)));
10665
10666 nghttp2_session_del(session);
10667
10668 /* SETTINGS ACK */
10669 nghttp2_bufs_reset(&bufs);
10670
10671 nghttp2_session_server_new(&session, &callbacks, NULL);
10672
10673 nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE, NULL, 0);
10674 nghttp2_frame_pack_settings(&bufs, &frame.settings);
10675 nghttp2_frame_settings_free(&frame.settings, mem);
10676
10677 buf = &bufs.head->buf;
10678
10679 for (i = 0; i < NGHTTP2_DEFAULT_MAX_OBQ_FLOOD_ITEM; ++i) {
10680 CU_ASSERT(
10681 (ssize_t)nghttp2_buf_len(buf) ==
10682 nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf)));
10683 }
10684
10685 CU_ASSERT(NGHTTP2_ERR_FLOODED ==
10686 nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf)));
10687
10688 nghttp2_session_del(session);
10689 nghttp2_bufs_free(&bufs);
10690 }
10691
test_nghttp2_session_change_stream_priority(void)10692 void test_nghttp2_session_change_stream_priority(void) {
10693 nghttp2_session *session;
10694 nghttp2_session_callbacks callbacks;
10695 nghttp2_stream *stream1, *stream2, *stream3, *stream5;
10696 nghttp2_priority_spec pri_spec;
10697 int rv;
10698
10699 memset(&callbacks, 0, sizeof(callbacks));
10700
10701 nghttp2_session_server_new(&session, &callbacks, NULL);
10702
10703 stream1 = open_recv_stream(session, 1);
10704 stream3 = open_recv_stream_with_dep_weight(session, 3, 199, stream1);
10705 stream2 = open_sent_stream_with_dep_weight(session, 2, 101, stream3);
10706
10707 nghttp2_priority_spec_init(&pri_spec, 1, 256, 0);
10708
10709 rv = nghttp2_session_change_stream_priority(session, 2, &pri_spec);
10710
10711 CU_ASSERT(0 == rv);
10712
10713 CU_ASSERT(stream1 == stream2->dep_prev);
10714 CU_ASSERT(256 == stream2->weight);
10715
10716 /* Cannot change stream which does not exist */
10717 rv = nghttp2_session_change_stream_priority(session, 5, &pri_spec);
10718 CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT == rv);
10719
10720 /* It is an error to depend on itself */
10721 rv = nghttp2_session_change_stream_priority(session, 1, &pri_spec);
10722 CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT == rv);
10723
10724 /* It is an error to change priority of root stream (0) */
10725 rv = nghttp2_session_change_stream_priority(session, 0, &pri_spec);
10726 CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT == rv);
10727
10728 /* Depends on the non-existing idle stream. This creates that idle
10729 stream. */
10730 nghttp2_priority_spec_init(&pri_spec, 5, 9, 1);
10731
10732 rv = nghttp2_session_change_stream_priority(session, 2, &pri_spec);
10733
10734 CU_ASSERT(0 == rv);
10735
10736 stream5 = nghttp2_session_get_stream_raw(session, 5);
10737
10738 CU_ASSERT(NULL != stream5);
10739 CU_ASSERT(&session->root == stream5->dep_prev);
10740 CU_ASSERT(stream5 == stream2->dep_prev);
10741 CU_ASSERT(9 == stream2->weight);
10742
10743 nghttp2_session_del(session);
10744
10745 /* Check that this works in client session too */
10746 nghttp2_session_client_new(&session, &callbacks, NULL);
10747
10748 stream1 = open_sent_stream(session, 1);
10749
10750 nghttp2_priority_spec_init(&pri_spec, 5, 9, 1);
10751
10752 rv = nghttp2_session_change_stream_priority(session, 1, &pri_spec);
10753
10754 CU_ASSERT(0 == rv);
10755
10756 stream5 = nghttp2_session_get_stream_raw(session, 5);
10757
10758 CU_ASSERT(NULL != stream5);
10759 CU_ASSERT(&session->root == stream5->dep_prev);
10760 CU_ASSERT(stream5 == stream1->dep_prev);
10761 CU_ASSERT(9 == stream1->weight);
10762
10763 nghttp2_session_del(session);
10764 }
10765
test_nghttp2_session_change_extpri_stream_priority(void)10766 void test_nghttp2_session_change_extpri_stream_priority(void) {
10767 nghttp2_session *session;
10768 nghttp2_session_callbacks callbacks;
10769 nghttp2_bufs bufs;
10770 nghttp2_buf *buf;
10771 ssize_t rv;
10772 nghttp2_option *option;
10773 nghttp2_extension frame;
10774 nghttp2_ext_priority_update priority_update;
10775 nghttp2_extpri extpri;
10776 nghttp2_stream *stream;
10777 static const uint8_t field_value[] = "u=2";
10778
10779 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
10780
10781 frame_pack_bufs_init(&bufs);
10782
10783 nghttp2_option_new(&option);
10784 nghttp2_option_set_builtin_recv_extension_type(option,
10785 NGHTTP2_PRIORITY_UPDATE);
10786
10787 nghttp2_session_server_new2(&session, &callbacks, NULL, option);
10788
10789 session->pending_no_rfc7540_priorities = 1;
10790
10791 open_recv_stream(session, 1);
10792
10793 extpri.urgency = NGHTTP2_EXTPRI_URGENCY_LOW + 1;
10794 extpri.inc = 1;
10795
10796 rv = nghttp2_session_change_extpri_stream_priority(
10797 session, 1, &extpri, /* ignore_client_signal = */ 0);
10798
10799 CU_ASSERT(0 == rv);
10800
10801 stream = nghttp2_session_get_stream(session, 1);
10802
10803 CU_ASSERT(NGHTTP2_EXTPRI_URGENCY_LOW ==
10804 nghttp2_extpri_uint8_urgency(stream->extpri));
10805 CU_ASSERT(1 == nghttp2_extpri_uint8_inc(stream->extpri));
10806
10807 /* Client can still update stream priority. */
10808 frame.payload = &priority_update;
10809 nghttp2_frame_priority_update_init(&frame, 1, (uint8_t *)field_value,
10810 sizeof(field_value) - 1);
10811 nghttp2_frame_pack_priority_update(&bufs, &frame);
10812
10813 buf = &bufs.head->buf;
10814 rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
10815
10816 CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv);
10817 CU_ASSERT(2 == stream->extpri);
10818
10819 /* Start to ignore client priority signal for this stream. */
10820 rv = nghttp2_session_change_extpri_stream_priority(
10821 session, 1, &extpri, /* ignore_client_signal = */ 1);
10822
10823 CU_ASSERT(0 == rv);
10824
10825 stream = nghttp2_session_get_stream(session, 1);
10826
10827 CU_ASSERT(NGHTTP2_EXTPRI_URGENCY_LOW ==
10828 nghttp2_extpri_uint8_urgency(stream->extpri));
10829 CU_ASSERT(1 == nghttp2_extpri_uint8_inc(stream->extpri));
10830
10831 buf = &bufs.head->buf;
10832 rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
10833
10834 CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv);
10835 CU_ASSERT(NGHTTP2_EXTPRI_URGENCY_LOW ==
10836 nghttp2_extpri_uint8_urgency(stream->extpri));
10837 CU_ASSERT(1 == nghttp2_extpri_uint8_inc(stream->extpri));
10838
10839 nghttp2_session_del(session);
10840 nghttp2_option_del(option);
10841 nghttp2_bufs_free(&bufs);
10842 }
10843
test_nghttp2_session_create_idle_stream(void)10844 void test_nghttp2_session_create_idle_stream(void) {
10845 nghttp2_session *session;
10846 nghttp2_session_callbacks callbacks;
10847 nghttp2_stream *stream2, *stream4, *stream8, *stream10;
10848 nghttp2_priority_spec pri_spec;
10849 int rv;
10850 int i;
10851
10852 memset(&callbacks, 0, sizeof(callbacks));
10853 callbacks.send_callback = null_send_callback;
10854
10855 nghttp2_session_server_new(&session, &callbacks, NULL);
10856
10857 stream2 = open_sent_stream(session, 2);
10858
10859 nghttp2_priority_spec_init(&pri_spec, 2, 111, 1);
10860
10861 rv = nghttp2_session_create_idle_stream(session, 4, &pri_spec);
10862
10863 CU_ASSERT(0 == rv);
10864
10865 stream4 = nghttp2_session_get_stream_raw(session, 4);
10866
10867 CU_ASSERT(4 == stream4->stream_id);
10868 CU_ASSERT(111 == stream4->weight);
10869 CU_ASSERT(stream2 == stream4->dep_prev);
10870 CU_ASSERT(stream4 == stream2->dep_next);
10871
10872 /* If pri_spec->stream_id does not exist, and it is idle stream, it
10873 is created too */
10874 nghttp2_priority_spec_init(&pri_spec, 10, 109, 0);
10875
10876 rv = nghttp2_session_create_idle_stream(session, 8, &pri_spec);
10877
10878 CU_ASSERT(0 == rv);
10879
10880 stream8 = nghttp2_session_get_stream_raw(session, 8);
10881 stream10 = nghttp2_session_get_stream_raw(session, 10);
10882
10883 CU_ASSERT(8 == stream8->stream_id);
10884 CU_ASSERT(109 == stream8->weight);
10885 CU_ASSERT(10 == stream10->stream_id);
10886 CU_ASSERT(16 == stream10->weight);
10887 CU_ASSERT(stream10 == stream8->dep_prev);
10888 CU_ASSERT(&session->root == stream10->dep_prev);
10889
10890 /* It is an error to attempt to create already existing idle
10891 stream */
10892 rv = nghttp2_session_create_idle_stream(session, 4, &pri_spec);
10893
10894 CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT == rv);
10895
10896 /* It is an error to depend on itself */
10897 pri_spec.stream_id = 6;
10898
10899 rv = nghttp2_session_create_idle_stream(session, 6, &pri_spec);
10900 CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT == rv);
10901
10902 /* It is an error to create root stream (0) as idle stream */
10903 rv = nghttp2_session_create_idle_stream(session, 0, &pri_spec);
10904 CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT == rv);
10905
10906 /* It is an error to create non-idle stream */
10907 session->last_sent_stream_id = 20;
10908 pri_spec.stream_id = 2;
10909
10910 rv = nghttp2_session_create_idle_stream(session, 18, &pri_spec);
10911
10912 CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT == rv);
10913
10914 nghttp2_session_del(session);
10915
10916 /* Check that this works in client session too */
10917 nghttp2_session_client_new(&session, &callbacks, NULL);
10918
10919 nghttp2_priority_spec_init(&pri_spec, 4, 99, 1);
10920
10921 rv = nghttp2_session_create_idle_stream(session, 2, &pri_spec);
10922
10923 CU_ASSERT(0 == rv);
10924
10925 stream4 = nghttp2_session_get_stream_raw(session, 4);
10926 stream2 = nghttp2_session_get_stream_raw(session, 2);
10927
10928 CU_ASSERT(NULL != stream4);
10929 CU_ASSERT(NULL != stream2);
10930 CU_ASSERT(&session->root == stream4->dep_prev);
10931 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == stream4->weight);
10932 CU_ASSERT(stream4 == stream2->dep_prev);
10933 CU_ASSERT(99 == stream2->weight);
10934
10935 nghttp2_session_del(session);
10936
10937 /* Check that idle stream is reduced when nghttp2_session_send() is
10938 called. */
10939 nghttp2_session_server_new(&session, &callbacks, NULL);
10940
10941 session->local_settings.max_concurrent_streams = 30;
10942
10943 nghttp2_priority_spec_init(&pri_spec, 0, 16, 0);
10944 for (i = 0; i < 100; ++i) {
10945 rv = nghttp2_session_create_idle_stream(session, i * 2 + 1, &pri_spec);
10946
10947 CU_ASSERT(0 == rv);
10948
10949 nghttp2_priority_spec_init(&pri_spec, i * 2 + 1, 16, 0);
10950 }
10951
10952 CU_ASSERT(100 == session->num_idle_streams);
10953 CU_ASSERT(0 == nghttp2_session_send(session));
10954 CU_ASSERT(30 == session->num_idle_streams);
10955 CU_ASSERT(141 == session->idle_stream_head->stream_id);
10956
10957 nghttp2_session_del(session);
10958
10959 /* Check that idle stream is reduced when nghttp2_session_mem_recv() is
10960 called. */
10961 nghttp2_session_client_new(&session, &callbacks, NULL);
10962
10963 session->local_settings.max_concurrent_streams = 30;
10964
10965 nghttp2_priority_spec_init(&pri_spec, 0, 16, 0);
10966 for (i = 0; i < 100; ++i) {
10967 rv = nghttp2_session_create_idle_stream(session, i * 2 + 1, &pri_spec);
10968
10969 CU_ASSERT(0 == rv);
10970
10971 nghttp2_priority_spec_init(&pri_spec, i * 2 + 1, 16, 0);
10972 }
10973
10974 CU_ASSERT(100 == session->num_idle_streams);
10975 CU_ASSERT(0 == nghttp2_session_mem_recv(session, NULL, 0));
10976 CU_ASSERT(30 == session->num_idle_streams);
10977 CU_ASSERT(141 == session->idle_stream_head->stream_id);
10978
10979 nghttp2_session_del(session);
10980 }
10981
test_nghttp2_session_repeated_priority_change(void)10982 void test_nghttp2_session_repeated_priority_change(void) {
10983 nghttp2_session *session;
10984 nghttp2_session_callbacks callbacks;
10985 nghttp2_frame frame;
10986 nghttp2_priority_spec pri_spec;
10987 int32_t stream_id, last_stream_id;
10988 int32_t max_streams = 20;
10989
10990 memset(&callbacks, 0, sizeof(callbacks));
10991
10992 nghttp2_session_server_new(&session, &callbacks, NULL);
10993
10994 session->local_settings.max_concurrent_streams = (uint32_t)max_streams;
10995
10996 /* 1 -> 0 */
10997 nghttp2_priority_spec_init(&pri_spec, 0, 16, 0);
10998 nghttp2_frame_priority_init(&frame.priority, 1, &pri_spec);
10999
11000 CU_ASSERT(0 == nghttp2_session_on_priority_received(session, &frame));
11001
11002 nghttp2_frame_priority_free(&frame.priority);
11003
11004 last_stream_id = max_streams * 2 + 1;
11005
11006 for (stream_id = 3; stream_id < last_stream_id; stream_id += 2) {
11007 /* 1 -> stream_id */
11008 nghttp2_priority_spec_init(&pri_spec, stream_id, 16, 0);
11009 nghttp2_frame_priority_init(&frame.priority, 1, &pri_spec);
11010
11011 CU_ASSERT(0 == nghttp2_session_on_priority_received(session, &frame));
11012
11013 nghttp2_frame_priority_free(&frame.priority);
11014 }
11015
11016 CU_ASSERT(20 == session->num_idle_streams);
11017 CU_ASSERT(1 == session->idle_stream_head->stream_id);
11018
11019 /* 1 -> last_stream_id */
11020 nghttp2_priority_spec_init(&pri_spec, last_stream_id, 16, 0);
11021 nghttp2_frame_priority_init(&frame.priority, 1, &pri_spec);
11022
11023 CU_ASSERT(0 == nghttp2_session_on_priority_received(session, &frame));
11024
11025 nghttp2_frame_priority_free(&frame.priority);
11026
11027 CU_ASSERT(20 == session->num_idle_streams);
11028 CU_ASSERT(3 == session->idle_stream_head->stream_id);
11029
11030 nghttp2_session_del(session);
11031 }
11032
test_nghttp2_session_repeated_priority_submission(void)11033 void test_nghttp2_session_repeated_priority_submission(void) {
11034 nghttp2_session *session;
11035 nghttp2_session_callbacks callbacks;
11036 nghttp2_priority_spec pri_spec;
11037 int32_t stream_id, last_stream_id;
11038 uint32_t max_streams = NGHTTP2_MIN_IDLE_STREAMS;
11039
11040 memset(&callbacks, 0, sizeof(callbacks));
11041
11042 callbacks.send_callback = null_send_callback;
11043
11044 nghttp2_session_client_new(&session, &callbacks, NULL);
11045
11046 session->local_settings.max_concurrent_streams = max_streams;
11047
11048 /* 1 -> 0 */
11049 nghttp2_priority_spec_init(&pri_spec, 0, 16, 0);
11050
11051 CU_ASSERT(0 ==
11052 nghttp2_submit_priority(session, NGHTTP2_FLAG_NONE, 1, &pri_spec));
11053
11054 last_stream_id = (int32_t)(max_streams * 2 + 1);
11055
11056 for (stream_id = 3; stream_id < last_stream_id; stream_id += 2) {
11057 /* 1 -> stream_id */
11058 nghttp2_priority_spec_init(&pri_spec, stream_id, 16, 0);
11059
11060 CU_ASSERT(
11061 0 == nghttp2_submit_priority(session, NGHTTP2_FLAG_NONE, 1, &pri_spec));
11062 }
11063
11064 CU_ASSERT(0 == nghttp2_session_send(session));
11065 CU_ASSERT(max_streams == session->num_idle_streams);
11066 CU_ASSERT(1 == session->idle_stream_head->stream_id);
11067
11068 /* 1 -> last_stream_id */
11069 nghttp2_priority_spec_init(&pri_spec, last_stream_id, 16, 0);
11070
11071 CU_ASSERT(0 ==
11072 nghttp2_submit_priority(session, NGHTTP2_FLAG_NONE, 1, &pri_spec));
11073
11074 CU_ASSERT(0 == nghttp2_session_send(session));
11075 CU_ASSERT(max_streams == session->num_idle_streams);
11076 CU_ASSERT(3 == session->idle_stream_head->stream_id);
11077
11078 nghttp2_session_del(session);
11079 }
11080
test_nghttp2_session_set_local_window_size(void)11081 void test_nghttp2_session_set_local_window_size(void) {
11082 nghttp2_session *session;
11083 nghttp2_session_callbacks callbacks;
11084 nghttp2_outbound_item *item;
11085 nghttp2_stream *stream;
11086
11087 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
11088 callbacks.send_callback = null_send_callback;
11089
11090 nghttp2_session_client_new(&session, &callbacks, NULL);
11091 stream = open_sent_stream(session, 1);
11092 stream->recv_window_size = 4096;
11093
11094 CU_ASSERT(0 == nghttp2_session_set_local_window_size(
11095 session, NGHTTP2_FLAG_NONE, 1, 65536));
11096 CU_ASSERT(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE + 1 ==
11097 stream->local_window_size);
11098 CU_ASSERT(4096 == stream->recv_window_size);
11099 CU_ASSERT(65536 - 4096 ==
11100 nghttp2_session_get_stream_local_window_size(session, 1));
11101
11102 item = nghttp2_session_get_next_ob_item(session);
11103
11104 CU_ASSERT(NGHTTP2_WINDOW_UPDATE == item->frame.hd.type);
11105 CU_ASSERT(1 == item->frame.window_update.hd.stream_id);
11106 CU_ASSERT(1 == item->frame.window_update.window_size_increment);
11107
11108 CU_ASSERT(0 == nghttp2_session_send(session));
11109
11110 /* Go decrement part */
11111 CU_ASSERT(0 == nghttp2_session_set_local_window_size(
11112 session, NGHTTP2_FLAG_NONE, 1, 32768));
11113 CU_ASSERT(32768 == stream->local_window_size);
11114 CU_ASSERT(-28672 == stream->recv_window_size);
11115 CU_ASSERT(32768 == stream->recv_reduction);
11116 CU_ASSERT(65536 - 4096 ==
11117 nghttp2_session_get_stream_local_window_size(session, 1));
11118
11119 item = nghttp2_session_get_next_ob_item(session);
11120
11121 CU_ASSERT(item == NULL);
11122
11123 /* Increase local window size */
11124 CU_ASSERT(0 == nghttp2_session_set_local_window_size(
11125 session, NGHTTP2_FLAG_NONE, 1, 49152));
11126 CU_ASSERT(49152 == stream->local_window_size);
11127 CU_ASSERT(-12288 == stream->recv_window_size);
11128 CU_ASSERT(16384 == stream->recv_reduction);
11129 CU_ASSERT(65536 - 4096 ==
11130 nghttp2_session_get_stream_local_window_size(session, 1));
11131 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
11132
11133 /* Increase local window again */
11134 CU_ASSERT(0 == nghttp2_session_set_local_window_size(
11135 session, NGHTTP2_FLAG_NONE, 1, 65537));
11136 CU_ASSERT(65537 == stream->local_window_size);
11137 CU_ASSERT(4096 == stream->recv_window_size);
11138 CU_ASSERT(0 == stream->recv_reduction);
11139 CU_ASSERT(65537 - 4096 ==
11140 nghttp2_session_get_stream_local_window_size(session, 1));
11141
11142 item = nghttp2_session_get_next_ob_item(session);
11143
11144 CU_ASSERT(1 == item->frame.window_update.window_size_increment);
11145
11146 CU_ASSERT(0 == nghttp2_session_send(session));
11147
11148 /* Check connection-level flow control */
11149 session->recv_window_size = 4096;
11150 CU_ASSERT(0 == nghttp2_session_set_local_window_size(
11151 session, NGHTTP2_FLAG_NONE, 0, 65536));
11152 CU_ASSERT(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE + 1 ==
11153 session->local_window_size);
11154 CU_ASSERT(4096 == session->recv_window_size);
11155 CU_ASSERT(65536 - 4096 == nghttp2_session_get_local_window_size(session));
11156
11157 item = nghttp2_session_get_next_ob_item(session);
11158
11159 CU_ASSERT(NGHTTP2_WINDOW_UPDATE == item->frame.hd.type);
11160 CU_ASSERT(0 == item->frame.window_update.hd.stream_id);
11161 CU_ASSERT(1 == item->frame.window_update.window_size_increment);
11162
11163 CU_ASSERT(0 == nghttp2_session_send(session));
11164
11165 /* Go decrement part */
11166 CU_ASSERT(0 == nghttp2_session_set_local_window_size(
11167 session, NGHTTP2_FLAG_NONE, 0, 32768));
11168 CU_ASSERT(32768 == session->local_window_size);
11169 CU_ASSERT(-28672 == session->recv_window_size);
11170 CU_ASSERT(32768 == session->recv_reduction);
11171 CU_ASSERT(65536 - 4096 == nghttp2_session_get_local_window_size(session));
11172
11173 item = nghttp2_session_get_next_ob_item(session);
11174
11175 CU_ASSERT(item == NULL);
11176
11177 /* Increase local window size */
11178 CU_ASSERT(0 == nghttp2_session_set_local_window_size(
11179 session, NGHTTP2_FLAG_NONE, 0, 49152));
11180 CU_ASSERT(49152 == session->local_window_size);
11181 CU_ASSERT(-12288 == session->recv_window_size);
11182 CU_ASSERT(16384 == session->recv_reduction);
11183 CU_ASSERT(65536 - 4096 == nghttp2_session_get_local_window_size(session));
11184 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
11185
11186 /* Increase local window again */
11187 CU_ASSERT(0 == nghttp2_session_set_local_window_size(
11188 session, NGHTTP2_FLAG_NONE, 0, 65537));
11189 CU_ASSERT(65537 == session->local_window_size);
11190 CU_ASSERT(4096 == session->recv_window_size);
11191 CU_ASSERT(0 == session->recv_reduction);
11192 CU_ASSERT(65537 - 4096 == nghttp2_session_get_local_window_size(session));
11193
11194 item = nghttp2_session_get_next_ob_item(session);
11195
11196 CU_ASSERT(1 == item->frame.window_update.window_size_increment);
11197
11198 CU_ASSERT(0 == nghttp2_session_send(session));
11199
11200 nghttp2_session_del(session);
11201
11202 /* Make sure that nghttp2_session_set_local_window_size submits
11203 WINDOW_UPDATE if necessary to increase stream-level window. */
11204 nghttp2_session_client_new(&session, &callbacks, NULL);
11205 stream = open_sent_stream(session, 1);
11206 stream->recv_window_size = NGHTTP2_INITIAL_WINDOW_SIZE;
11207
11208 CU_ASSERT(0 == nghttp2_session_set_local_window_size(
11209 session, NGHTTP2_FLAG_NONE, 1, 0));
11210 CU_ASSERT(0 == stream->recv_window_size);
11211 CU_ASSERT(0 == nghttp2_session_get_stream_local_window_size(session, 1));
11212 /* This should submit WINDOW_UPDATE frame because stream-level
11213 receiving window is now full. */
11214 CU_ASSERT(0 ==
11215 nghttp2_session_set_local_window_size(session, NGHTTP2_FLAG_NONE, 1,
11216 NGHTTP2_INITIAL_WINDOW_SIZE));
11217 CU_ASSERT(0 == stream->recv_window_size);
11218 CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE ==
11219 nghttp2_session_get_stream_local_window_size(session, 1));
11220
11221 item = nghttp2_session_get_next_ob_item(session);
11222
11223 CU_ASSERT(NGHTTP2_WINDOW_UPDATE == item->frame.hd.type);
11224 CU_ASSERT(1 == item->frame.hd.stream_id);
11225 CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE ==
11226 item->frame.window_update.window_size_increment);
11227
11228 nghttp2_session_del(session);
11229
11230 /* Make sure that nghttp2_session_set_local_window_size submits
11231 WINDOW_UPDATE if necessary to increase connection-level
11232 window. */
11233 nghttp2_session_client_new(&session, &callbacks, NULL);
11234 session->recv_window_size = NGHTTP2_INITIAL_WINDOW_SIZE;
11235
11236 CU_ASSERT(0 == nghttp2_session_set_local_window_size(
11237 session, NGHTTP2_FLAG_NONE, 0, 0));
11238 CU_ASSERT(0 == session->recv_window_size);
11239 CU_ASSERT(0 == nghttp2_session_get_local_window_size(session));
11240 /* This should submit WINDOW_UPDATE frame because connection-level
11241 receiving window is now full. */
11242 CU_ASSERT(0 ==
11243 nghttp2_session_set_local_window_size(session, NGHTTP2_FLAG_NONE, 0,
11244 NGHTTP2_INITIAL_WINDOW_SIZE));
11245 CU_ASSERT(0 == session->recv_window_size);
11246 CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE ==
11247 nghttp2_session_get_local_window_size(session));
11248
11249 item = nghttp2_session_get_next_ob_item(session);
11250
11251 CU_ASSERT(NGHTTP2_WINDOW_UPDATE == item->frame.hd.type);
11252 CU_ASSERT(0 == item->frame.hd.stream_id);
11253 CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE ==
11254 item->frame.window_update.window_size_increment);
11255
11256 nghttp2_session_del(session);
11257 }
11258
test_nghttp2_session_cancel_from_before_frame_send(void)11259 void test_nghttp2_session_cancel_from_before_frame_send(void) {
11260 int rv;
11261 nghttp2_session *session;
11262 nghttp2_session_callbacks callbacks;
11263 my_user_data ud;
11264 nghttp2_settings_entry iv;
11265 nghttp2_data_provider data_prd;
11266 int32_t stream_id;
11267 nghttp2_stream *stream;
11268
11269 memset(&callbacks, 0, sizeof(callbacks));
11270
11271 callbacks.before_frame_send_callback = cancel_before_frame_send_callback;
11272 callbacks.on_frame_not_send_callback = on_frame_not_send_callback;
11273 callbacks.send_callback = null_send_callback;
11274
11275 nghttp2_session_client_new(&session, &callbacks, &ud);
11276
11277 iv.settings_id = 0;
11278 iv.value = 1000000009;
11279
11280 rv = nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, &iv, 1);
11281
11282 CU_ASSERT(0 == rv);
11283
11284 ud.frame_send_cb_called = 0;
11285 ud.before_frame_send_cb_called = 0;
11286 ud.frame_not_send_cb_called = 0;
11287
11288 rv = nghttp2_session_send(session);
11289
11290 CU_ASSERT(0 == rv);
11291 CU_ASSERT(0 == ud.frame_send_cb_called);
11292 CU_ASSERT(1 == ud.before_frame_send_cb_called);
11293 CU_ASSERT(1 == ud.frame_not_send_cb_called);
11294
11295 data_prd.source.ptr = NULL;
11296 data_prd.read_callback = temporal_failure_data_source_read_callback;
11297
11298 stream_id = nghttp2_submit_request(session, NULL, reqnv, ARRLEN(reqnv),
11299 &data_prd, NULL);
11300
11301 CU_ASSERT(stream_id > 0);
11302
11303 ud.frame_send_cb_called = 0;
11304 ud.before_frame_send_cb_called = 0;
11305 ud.frame_not_send_cb_called = 0;
11306
11307 rv = nghttp2_session_send(session);
11308
11309 CU_ASSERT(0 == rv);
11310 CU_ASSERT(0 == ud.frame_send_cb_called);
11311 CU_ASSERT(1 == ud.before_frame_send_cb_called);
11312 CU_ASSERT(1 == ud.frame_not_send_cb_called);
11313
11314 stream = nghttp2_session_get_stream_raw(session, stream_id);
11315
11316 CU_ASSERT(NULL == stream);
11317
11318 nghttp2_session_del(session);
11319
11320 nghttp2_session_server_new(&session, &callbacks, &ud);
11321
11322 open_recv_stream(session, 1);
11323
11324 stream_id = nghttp2_submit_push_promise(session, NGHTTP2_FLAG_NONE, 1, reqnv,
11325 ARRLEN(reqnv), NULL);
11326
11327 CU_ASSERT(stream_id > 0);
11328
11329 ud.frame_send_cb_called = 0;
11330 ud.before_frame_send_cb_called = 0;
11331 ud.frame_not_send_cb_called = 0;
11332
11333 rv = nghttp2_session_send(session);
11334
11335 CU_ASSERT(0 == rv);
11336 CU_ASSERT(0 == ud.frame_send_cb_called);
11337 CU_ASSERT(1 == ud.before_frame_send_cb_called);
11338 CU_ASSERT(1 == ud.frame_not_send_cb_called);
11339
11340 stream = nghttp2_session_get_stream_raw(session, stream_id);
11341
11342 CU_ASSERT(NULL == stream);
11343
11344 nghttp2_session_del(session);
11345 }
11346
test_nghttp2_session_too_many_settings(void)11347 void test_nghttp2_session_too_many_settings(void) {
11348 nghttp2_session *session;
11349 nghttp2_option *option;
11350 nghttp2_session_callbacks callbacks;
11351 nghttp2_frame frame;
11352 nghttp2_bufs bufs;
11353 nghttp2_buf *buf;
11354 ssize_t rv;
11355 my_user_data ud;
11356 nghttp2_settings_entry iv[3];
11357 nghttp2_mem *mem;
11358 nghttp2_outbound_item *item;
11359
11360 mem = nghttp2_mem_default();
11361 frame_pack_bufs_init(&bufs);
11362
11363 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
11364 callbacks.on_frame_recv_callback = on_frame_recv_callback;
11365 callbacks.send_callback = null_send_callback;
11366
11367 nghttp2_option_new(&option);
11368 nghttp2_option_set_max_settings(option, 1);
11369
11370 nghttp2_session_client_new2(&session, &callbacks, &ud, option);
11371
11372 CU_ASSERT(1 == session->max_settings);
11373
11374 nghttp2_option_del(option);
11375
11376 iv[0].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
11377 iv[0].value = 3000;
11378
11379 iv[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
11380 iv[1].value = 16384;
11381
11382 nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE, dup_iv(iv, 2),
11383 2);
11384
11385 rv = nghttp2_frame_pack_settings(&bufs, &frame.settings);
11386
11387 CU_ASSERT(0 == rv);
11388 CU_ASSERT(nghttp2_bufs_len(&bufs) > 0);
11389
11390 nghttp2_frame_settings_free(&frame.settings, mem);
11391
11392 buf = &bufs.head->buf;
11393 assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
11394
11395 ud.frame_recv_cb_called = 0;
11396
11397 rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
11398 CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv);
11399
11400 item = nghttp2_session_get_next_ob_item(session);
11401 CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
11402
11403 nghttp2_bufs_reset(&bufs);
11404 nghttp2_bufs_free(&bufs);
11405 nghttp2_session_del(session);
11406 }
11407
11408 static void
prepare_session_removed_closed_stream(nghttp2_session * session,nghttp2_hd_deflater * deflater)11409 prepare_session_removed_closed_stream(nghttp2_session *session,
11410 nghttp2_hd_deflater *deflater) {
11411 int rv;
11412 nghttp2_settings_entry iv;
11413 nghttp2_bufs bufs;
11414 nghttp2_mem *mem;
11415 ssize_t nread;
11416 int i;
11417 nghttp2_stream *stream;
11418 nghttp2_frame_hd hd;
11419
11420 mem = nghttp2_mem_default();
11421
11422 frame_pack_bufs_init(&bufs);
11423
11424 iv.settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS;
11425 iv.value = 2;
11426
11427 rv = nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, &iv, 1);
11428
11429 CU_ASSERT(0 == rv);
11430
11431 rv = nghttp2_session_send(session);
11432
11433 CU_ASSERT(0 == rv);
11434
11435 for (i = 1; i <= 3; i += 2) {
11436 rv = pack_headers(&bufs, deflater, i,
11437 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM, reqnv,
11438 ARRLEN(reqnv), mem);
11439
11440 CU_ASSERT(0 == rv);
11441
11442 nread = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11443 nghttp2_bufs_len(&bufs));
11444
11445 CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == nread);
11446
11447 nghttp2_bufs_reset(&bufs);
11448 }
11449
11450 nghttp2_session_close_stream(session, 3, NGHTTP2_NO_ERROR);
11451
11452 rv = pack_headers(&bufs, deflater, 5,
11453 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM, reqnv,
11454 ARRLEN(reqnv), mem);
11455
11456 CU_ASSERT(0 == rv);
11457
11458 /* Receiving stream 5 will erase stream 3 from closed stream list */
11459 nread = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11460 nghttp2_bufs_len(&bufs));
11461
11462 CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == nread);
11463
11464 stream = nghttp2_session_get_stream_raw(session, 3);
11465
11466 CU_ASSERT(NULL == stream);
11467
11468 /* Since the current max concurrent streams is
11469 NGHTTP2_DEFAULT_MAX_CONCURRENT_STREAMS, receiving frame on stream
11470 3 is ignored. */
11471 nghttp2_bufs_reset(&bufs);
11472 rv = pack_headers(&bufs, deflater, 3,
11473 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM,
11474 trailernv, ARRLEN(trailernv), mem);
11475
11476 CU_ASSERT(0 == rv);
11477
11478 nread = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11479 nghttp2_bufs_len(&bufs));
11480
11481 CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == nread);
11482 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
11483
11484 nghttp2_frame_hd_init(&hd, 0, NGHTTP2_DATA, NGHTTP2_FLAG_NONE, 3);
11485 nghttp2_bufs_reset(&bufs);
11486 nghttp2_frame_pack_frame_hd(bufs.head->buf.last, &hd);
11487 bufs.head->buf.last += NGHTTP2_FRAME_HDLEN;
11488
11489 nread = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11490 nghttp2_bufs_len(&bufs));
11491
11492 CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == nread);
11493 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
11494
11495 /* Now server receives SETTINGS ACK */
11496 nghttp2_frame_hd_init(&hd, 0, NGHTTP2_SETTINGS, NGHTTP2_FLAG_ACK, 0);
11497 nghttp2_bufs_reset(&bufs);
11498 nghttp2_frame_pack_frame_hd(bufs.head->buf.last, &hd);
11499 bufs.head->buf.last += NGHTTP2_FRAME_HDLEN;
11500
11501 nread = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11502 nghttp2_bufs_len(&bufs));
11503
11504 CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == nread);
11505
11506 nghttp2_bufs_free(&bufs);
11507 }
11508
test_nghttp2_session_removed_closed_stream(void)11509 void test_nghttp2_session_removed_closed_stream(void) {
11510 nghttp2_session *session;
11511 nghttp2_session_callbacks callbacks;
11512 int rv;
11513 nghttp2_hd_deflater deflater;
11514 nghttp2_bufs bufs;
11515 nghttp2_mem *mem;
11516 ssize_t nread;
11517 nghttp2_frame_hd hd;
11518 nghttp2_outbound_item *item;
11519
11520 mem = nghttp2_mem_default();
11521
11522 frame_pack_bufs_init(&bufs);
11523
11524 memset(&callbacks, 0, sizeof(callbacks));
11525
11526 callbacks.send_callback = null_send_callback;
11527
11528 nghttp2_session_server_new(&session, &callbacks, NULL);
11529
11530 /* Now local max concurrent streams is still unlimited, pending max
11531 concurrent streams is now 2. */
11532
11533 nghttp2_hd_deflate_init(&deflater, mem);
11534
11535 prepare_session_removed_closed_stream(session, &deflater);
11536
11537 /* Now current max concurrent streams is 2. Receiving frame on
11538 stream 3 is ignored because we have no stream object for stream
11539 3. */
11540 nghttp2_bufs_reset(&bufs);
11541 rv = pack_headers(&bufs, &deflater, 3,
11542 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM,
11543 trailernv, ARRLEN(trailernv), mem);
11544
11545 CU_ASSERT(0 == rv);
11546
11547 nread = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11548 nghttp2_bufs_len(&bufs));
11549
11550 CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == nread);
11551
11552 item = nghttp2_session_get_next_ob_item(session);
11553
11554 CU_ASSERT(NULL == item);
11555
11556 nghttp2_hd_deflate_free(&deflater);
11557 nghttp2_session_del(session);
11558
11559 nghttp2_session_server_new(&session, &callbacks, NULL);
11560 nghttp2_hd_deflate_init(&deflater, mem);
11561 /* Same setup, and then receive DATA instead of HEADERS */
11562
11563 prepare_session_removed_closed_stream(session, &deflater);
11564
11565 nghttp2_frame_hd_init(&hd, 0, NGHTTP2_DATA, NGHTTP2_FLAG_NONE, 3);
11566 nghttp2_bufs_reset(&bufs);
11567 nghttp2_frame_pack_frame_hd(bufs.head->buf.last, &hd);
11568 bufs.head->buf.last += NGHTTP2_FRAME_HDLEN;
11569
11570 nread = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11571 nghttp2_bufs_len(&bufs));
11572
11573 CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == nread);
11574
11575 item = nghttp2_session_get_next_ob_item(session);
11576
11577 CU_ASSERT(NULL == item);
11578
11579 nghttp2_hd_deflate_free(&deflater);
11580 nghttp2_session_del(session);
11581
11582 nghttp2_bufs_free(&bufs);
11583 }
11584
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)11585 static ssize_t pause_once_data_source_read_callback(
11586 nghttp2_session *session, int32_t stream_id, uint8_t *buf, size_t len,
11587 uint32_t *data_flags, nghttp2_data_source *source, void *user_data) {
11588 my_user_data *ud = user_data;
11589 if (ud->data_source_read_cb_paused == 0) {
11590 ++ud->data_source_read_cb_paused;
11591 return NGHTTP2_ERR_PAUSE;
11592 }
11593
11594 return fixed_length_data_source_read_callback(session, stream_id, buf, len,
11595 data_flags, source, user_data);
11596 }
11597
test_nghttp2_session_pause_data(void)11598 void test_nghttp2_session_pause_data(void) {
11599 nghttp2_session *session;
11600 nghttp2_session_callbacks callbacks;
11601 nghttp2_data_provider data_prd;
11602 my_user_data ud;
11603
11604 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
11605 callbacks.send_callback = null_send_callback;
11606 callbacks.on_frame_send_callback = on_frame_send_callback;
11607
11608 data_prd.read_callback = pause_once_data_source_read_callback;
11609 ud.data_source_length = NGHTTP2_DATA_PAYLOADLEN;
11610
11611 nghttp2_session_server_new(&session, &callbacks, &ud);
11612
11613 open_recv_stream(session, 1);
11614
11615 CU_ASSERT(
11616 0 == nghttp2_submit_data(session, NGHTTP2_FLAG_END_STREAM, 1, &data_prd));
11617
11618 ud.frame_send_cb_called = 0;
11619 ud.data_source_read_cb_paused = 0;
11620
11621 CU_ASSERT(0 == nghttp2_session_send(session));
11622 CU_ASSERT(0 == ud.frame_send_cb_called);
11623 CU_ASSERT(NULL == session->aob.item);
11624 CU_ASSERT(0 == nghttp2_session_send(session));
11625 CU_ASSERT(1 == ud.frame_send_cb_called);
11626 CU_ASSERT(NGHTTP2_DATA == ud.sent_frame_type);
11627 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
11628
11629 nghttp2_session_del(session);
11630 }
11631
test_nghttp2_session_no_closed_streams(void)11632 void test_nghttp2_session_no_closed_streams(void) {
11633 nghttp2_session *session;
11634 nghttp2_session_callbacks callbacks;
11635 nghttp2_option *option;
11636
11637 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
11638
11639 nghttp2_option_new(&option);
11640 nghttp2_option_set_no_closed_streams(option, 1);
11641
11642 nghttp2_session_server_new2(&session, &callbacks, NULL, option);
11643
11644 open_recv_stream(session, 1);
11645
11646 nghttp2_session_close_stream(session, 1, NGHTTP2_NO_ERROR);
11647
11648 CU_ASSERT(0 == session->num_closed_streams);
11649
11650 nghttp2_session_del(session);
11651 nghttp2_option_del(option);
11652 }
11653
test_nghttp2_session_set_stream_user_data(void)11654 void test_nghttp2_session_set_stream_user_data(void) {
11655 nghttp2_session *session;
11656 nghttp2_session_callbacks callbacks;
11657 int32_t stream_id;
11658 int user_data1, user_data2;
11659 int rv;
11660 const uint8_t *datap;
11661 ssize_t datalen;
11662
11663 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
11664
11665 nghttp2_session_client_new(&session, &callbacks, NULL);
11666
11667 stream_id = nghttp2_submit_request(session, NULL, reqnv, ARRLEN(reqnv), NULL,
11668 &user_data1);
11669
11670 rv = nghttp2_session_set_stream_user_data(session, stream_id, &user_data2);
11671
11672 CU_ASSERT(0 == rv);
11673
11674 datalen = nghttp2_session_mem_send(session, &datap);
11675
11676 CU_ASSERT(datalen > 0);
11677
11678 CU_ASSERT(&user_data2 ==
11679 nghttp2_session_get_stream_user_data(session, stream_id));
11680
11681 CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT ==
11682 nghttp2_session_set_stream_user_data(session, 2, NULL));
11683
11684 nghttp2_session_del(session);
11685 }
11686
test_nghttp2_session_no_rfc7540_priorities(void)11687 void test_nghttp2_session_no_rfc7540_priorities(void) {
11688 nghttp2_session *session;
11689 nghttp2_session_callbacks callbacks;
11690 nghttp2_data_provider data_prd;
11691 my_user_data ud;
11692 nghttp2_outbound_item *item;
11693 nghttp2_mem *mem;
11694 nghttp2_settings_entry iv;
11695 nghttp2_priority_spec pri_spec;
11696
11697 mem = nghttp2_mem_default();
11698
11699 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
11700 callbacks.send_callback = null_send_callback;
11701
11702 /* Do not use a dependency tree if SETTINGS_NO_RFC7540_PRIORITIES =
11703 1. */
11704 data_prd.read_callback = fixed_length_data_source_read_callback;
11705
11706 ud.data_source_length = 128 * 1024;
11707 CU_ASSERT(0 == nghttp2_session_server_new(&session, &callbacks, &ud));
11708
11709 iv.settings_id = NGHTTP2_SETTINGS_NO_RFC7540_PRIORITIES;
11710 iv.value = 1;
11711
11712 CU_ASSERT(0 == nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, &iv, 1));
11713 CU_ASSERT(0 == nghttp2_session_send(session));
11714
11715 open_recv_stream2(session, 1, NGHTTP2_STREAM_OPENING);
11716 CU_ASSERT(0 == nghttp2_submit_response(session, 1, resnv, ARRLEN(resnv),
11717 &data_prd));
11718 item = nghttp2_session_get_next_ob_item(session);
11719 CU_ASSERT(ARRLEN(resnv) == item->frame.headers.nvlen);
11720 assert_nv_equal(resnv, item->frame.headers.nva, item->frame.headers.nvlen,
11721 mem);
11722
11723 CU_ASSERT(0 == nghttp2_session_send(session));
11724 CU_ASSERT(1 == nghttp2_pq_size(
11725 &session->sched[NGHTTP2_EXTPRI_DEFAULT_URGENCY].ob_data));
11726 CU_ASSERT(nghttp2_pq_empty(&session->root.obq));
11727
11728 nghttp2_session_del(session);
11729
11730 /* Priorities are sent as is before client receives
11731 SETTINGS_NO_RFC7540_PRIORITIES = 1 from server. */
11732 CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, NULL));
11733
11734 iv.settings_id = NGHTTP2_SETTINGS_NO_RFC7540_PRIORITIES;
11735 iv.value = 1;
11736
11737 CU_ASSERT(0 == nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, &iv, 1));
11738
11739 pri_spec.stream_id = 5;
11740 pri_spec.weight = 111;
11741 pri_spec.exclusive = 1;
11742
11743 CU_ASSERT(1 == nghttp2_submit_request(session, &pri_spec, reqnv,
11744 ARRLEN(reqnv), NULL, NULL));
11745
11746 item = nghttp2_outbound_queue_top(&session->ob_syn);
11747
11748 CU_ASSERT(NULL != item);
11749 CU_ASSERT(NGHTTP2_HEADERS == item->frame.hd.type);
11750 CU_ASSERT(pri_spec.stream_id == item->frame.headers.pri_spec.stream_id);
11751 CU_ASSERT(pri_spec.weight == item->frame.headers.pri_spec.weight);
11752 CU_ASSERT(pri_spec.exclusive == item->frame.headers.pri_spec.exclusive);
11753
11754 nghttp2_session_del(session);
11755
11756 /* Priorities are defaulted if client received
11757 SETTINGS_NO_RFC7540_PRIORITIES = 1 from server. */
11758 CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, NULL));
11759
11760 iv.settings_id = NGHTTP2_SETTINGS_NO_RFC7540_PRIORITIES;
11761 iv.value = 1;
11762
11763 CU_ASSERT(0 == nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, &iv, 1));
11764
11765 session->remote_settings.no_rfc7540_priorities = 1;
11766
11767 pri_spec.stream_id = 5;
11768 pri_spec.weight = 111;
11769 pri_spec.exclusive = 1;
11770
11771 CU_ASSERT(1 == nghttp2_submit_request(session, &pri_spec, reqnv,
11772 ARRLEN(reqnv), NULL, NULL));
11773
11774 item = nghttp2_outbound_queue_top(&session->ob_syn);
11775
11776 CU_ASSERT(NULL != item);
11777 CU_ASSERT(NGHTTP2_HEADERS == item->frame.hd.type);
11778 CU_ASSERT(nghttp2_priority_spec_check_default(&item->frame.headers.pri_spec));
11779
11780 nghttp2_session_del(session);
11781 }
11782
test_nghttp2_session_server_fallback_rfc7540_priorities(void)11783 void test_nghttp2_session_server_fallback_rfc7540_priorities(void) {
11784 nghttp2_session *session;
11785 nghttp2_option *option;
11786 nghttp2_session_callbacks callbacks;
11787 nghttp2_frame frame;
11788 nghttp2_bufs bufs;
11789 nghttp2_buf *buf;
11790 ssize_t rv;
11791 nghttp2_settings_entry iv;
11792 nghttp2_mem *mem;
11793 nghttp2_hd_deflater deflater;
11794 nghttp2_nv *nva;
11795 size_t nvlen;
11796 nghttp2_priority_spec pri_spec;
11797 nghttp2_stream *anchor_stream, *stream;
11798 my_user_data ud;
11799 nghttp2_ext_priority_update priority_update;
11800 static const uint8_t field_value[] = "u=0";
11801
11802 mem = nghttp2_mem_default();
11803 frame_pack_bufs_init(&bufs);
11804
11805 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
11806 callbacks.send_callback = null_send_callback;
11807 callbacks.on_frame_recv_callback = on_frame_recv_callback;
11808
11809 nghttp2_option_new(&option);
11810 nghttp2_option_set_server_fallback_rfc7540_priorities(option, 1);
11811
11812 iv.settings_id = NGHTTP2_SETTINGS_NO_RFC7540_PRIORITIES;
11813 iv.value = 1;
11814
11815 /* Server falls back to RFC 7540 priorities. */
11816 nghttp2_session_server_new2(&session, &callbacks, &ud, option);
11817
11818 rv = nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, &iv, 1);
11819
11820 CU_ASSERT(0 == rv);
11821
11822 rv = nghttp2_session_send(session);
11823
11824 CU_ASSERT(0 == rv);
11825
11826 nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE, NULL, 0);
11827 rv = nghttp2_frame_pack_settings(&bufs, &frame.settings);
11828
11829 CU_ASSERT(0 == rv);
11830
11831 nghttp2_frame_settings_free(&frame.settings, mem);
11832
11833 buf = &bufs.head->buf;
11834 rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
11835
11836 CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv);
11837 CU_ASSERT(1 == session->fallback_rfc7540_priorities);
11838
11839 nghttp2_hd_deflate_init(&deflater, mem);
11840
11841 nvlen = ARRLEN(reqnv);
11842 nghttp2_nv_array_copy(&nva, reqnv, nvlen, mem);
11843 nghttp2_priority_spec_init(&pri_spec, 3, 111, 1);
11844 nghttp2_frame_headers_init(&frame.headers,
11845 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PRIORITY,
11846 1, NGHTTP2_HCAT_HEADERS, &pri_spec, nva, nvlen);
11847 nghttp2_bufs_reset(&bufs);
11848 rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
11849
11850 CU_ASSERT(0 == rv);
11851
11852 nghttp2_frame_headers_free(&frame.headers, mem);
11853
11854 buf = &bufs.head->buf;
11855 rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
11856
11857 CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv);
11858
11859 anchor_stream = nghttp2_session_get_stream_raw(session, 3);
11860
11861 CU_ASSERT(NGHTTP2_STREAM_IDLE == anchor_stream->state);
11862 CU_ASSERT(
11863 !(anchor_stream->flags & NGHTTP2_STREAM_FLAG_NO_RFC7540_PRIORITIES));
11864 CU_ASSERT(&session->root == anchor_stream->dep_prev);
11865
11866 stream = nghttp2_session_get_stream(session, 1);
11867
11868 CU_ASSERT(NGHTTP2_STREAM_OPENING == stream->state);
11869 CU_ASSERT(!(stream->flags & NGHTTP2_STREAM_FLAG_NO_RFC7540_PRIORITIES));
11870 CU_ASSERT(anchor_stream == stream->dep_prev);
11871
11872 /* Make sure that PRIORITY frame updates stream priority. */
11873 nghttp2_priority_spec_init(&pri_spec, 5, 1, 0);
11874 nghttp2_frame_priority_init(&frame.priority, 1, &pri_spec);
11875 nghttp2_bufs_reset(&bufs);
11876 nghttp2_frame_pack_priority(&bufs, &frame.priority);
11877
11878 nghttp2_frame_priority_free(&frame.priority);
11879
11880 buf = &bufs.head->buf;
11881 rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
11882
11883 CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv);
11884
11885 anchor_stream = nghttp2_session_get_stream_raw(session, 5);
11886
11887 CU_ASSERT(NGHTTP2_STREAM_IDLE == anchor_stream->state);
11888 CU_ASSERT(&session->root == anchor_stream->dep_prev);
11889 CU_ASSERT(anchor_stream == stream->dep_prev);
11890
11891 /* Make sure that PRIORITY_UPDATE frame is ignored. */
11892 frame.ext.payload = &priority_update;
11893 nghttp2_frame_priority_update_init(&frame.ext, 1, (uint8_t *)field_value,
11894 sizeof(field_value) - 1);
11895 nghttp2_bufs_reset(&bufs);
11896 nghttp2_frame_pack_priority_update(&bufs, &frame.ext);
11897
11898 ud.frame_recv_cb_called = 0;
11899 buf = &bufs.head->buf;
11900 rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
11901
11902 CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv);
11903 CU_ASSERT(0 == ud.frame_recv_cb_called);
11904 CU_ASSERT(NGHTTP2_EXTPRI_DEFAULT_URGENCY == stream->extpri);
11905
11906 nghttp2_hd_deflate_free(&deflater);
11907 nghttp2_session_del(session);
11908
11909 /* Server does not fallback to RFC 7540 priorities. */
11910 nghttp2_session_server_new2(&session, &callbacks, &ud, option);
11911
11912 rv = nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, &iv, 1);
11913
11914 CU_ASSERT(0 == rv);
11915
11916 rv = nghttp2_session_send(session);
11917
11918 CU_ASSERT(0 == rv);
11919
11920 iv.settings_id = NGHTTP2_SETTINGS_NO_RFC7540_PRIORITIES;
11921 iv.value = 0;
11922
11923 nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE,
11924 dup_iv(&iv, 1), 1);
11925 nghttp2_bufs_reset(&bufs);
11926 rv = nghttp2_frame_pack_settings(&bufs, &frame.settings);
11927
11928 CU_ASSERT(0 == rv);
11929
11930 nghttp2_frame_settings_free(&frame.settings, mem);
11931
11932 buf = &bufs.head->buf;
11933 rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
11934
11935 CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv);
11936 CU_ASSERT(0 == session->fallback_rfc7540_priorities);
11937
11938 nghttp2_hd_deflate_init(&deflater, mem);
11939
11940 nvlen = ARRLEN(reqnv);
11941 nghttp2_nv_array_copy(&nva, reqnv, nvlen, mem);
11942 nghttp2_priority_spec_init(&pri_spec, 3, 111, 1);
11943 nghttp2_frame_headers_init(&frame.headers,
11944 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PRIORITY,
11945 1, NGHTTP2_HCAT_HEADERS, &pri_spec, nva, nvlen);
11946 nghttp2_bufs_reset(&bufs);
11947 rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
11948
11949 CU_ASSERT(0 == rv);
11950
11951 nghttp2_frame_headers_free(&frame.headers, mem);
11952
11953 buf = &bufs.head->buf;
11954 rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
11955
11956 CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv);
11957 CU_ASSERT(NULL == nghttp2_session_get_stream_raw(session, 3));
11958
11959 stream = nghttp2_session_get_stream(session, 1);
11960
11961 CU_ASSERT(NGHTTP2_STREAM_OPENING == stream->state);
11962 CU_ASSERT(stream->flags & NGHTTP2_STREAM_FLAG_NO_RFC7540_PRIORITIES);
11963
11964 nghttp2_hd_deflate_free(&deflater);
11965 nghttp2_session_del(session);
11966
11967 nghttp2_option_del(option);
11968 nghttp2_bufs_free(&bufs);
11969 }
11970
test_nghttp2_session_stream_reset_ratelim(void)11971 void test_nghttp2_session_stream_reset_ratelim(void) {
11972 nghttp2_session *session;
11973 nghttp2_session_callbacks callbacks;
11974 nghttp2_frame frame;
11975 ssize_t rv;
11976 nghttp2_bufs bufs;
11977 nghttp2_buf *buf;
11978 nghttp2_mem *mem;
11979 size_t i;
11980 nghttp2_hd_deflater deflater;
11981 size_t nvlen;
11982 nghttp2_nv *nva;
11983 int32_t stream_id;
11984 nghttp2_outbound_item *item;
11985 nghttp2_option *option;
11986
11987 mem = nghttp2_mem_default();
11988 frame_pack_bufs_init(&bufs);
11989
11990 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
11991 callbacks.send_callback = null_send_callback;
11992
11993 nghttp2_option_new(&option);
11994 nghttp2_option_set_stream_reset_rate_limit(
11995 option, NGHTTP2_DEFAULT_STREAM_RESET_BURST, 0);
11996
11997 nghttp2_session_server_new2(&session, &callbacks, NULL, option);
11998
11999 nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE, NULL, 0);
12000 rv = nghttp2_frame_pack_settings(&bufs, &frame.settings);
12001
12002 CU_ASSERT(0 == rv);
12003
12004 nghttp2_frame_settings_free(&frame.settings, mem);
12005
12006 buf = &bufs.head->buf;
12007 rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
12008
12009 CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv);
12010
12011 /* Send SETTINGS ACK */
12012 rv = nghttp2_session_send(session);
12013
12014 CU_ASSERT(0 == rv);
12015
12016 nghttp2_hd_deflate_init(&deflater, mem);
12017
12018 for (i = 0; i < NGHTTP2_DEFAULT_STREAM_RESET_BURST + 2; ++i) {
12019 stream_id = (int32_t)(i * 2 + 1);
12020
12021 nghttp2_bufs_reset(&bufs);
12022
12023 /* HEADERS */
12024 nvlen = ARRLEN(reqnv);
12025 nghttp2_nv_array_copy(&nva, reqnv, nvlen, mem);
12026 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS,
12027 stream_id, NGHTTP2_HCAT_HEADERS, NULL, nva,
12028 nvlen);
12029 rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
12030
12031 CU_ASSERT(0 == rv);
12032
12033 nghttp2_frame_headers_free(&frame.headers, mem);
12034
12035 buf = &bufs.head->buf;
12036 rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
12037
12038 CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv);
12039
12040 nghttp2_bufs_reset(&bufs);
12041
12042 /* RST_STREAM */
12043 nghttp2_frame_rst_stream_init(&frame.rst_stream, stream_id,
12044 NGHTTP2_NO_ERROR);
12045 nghttp2_frame_pack_rst_stream(&bufs, &frame.rst_stream);
12046 nghttp2_frame_rst_stream_free(&frame.rst_stream);
12047
12048 buf = &bufs.head->buf;
12049 rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
12050
12051 CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv);
12052
12053 if (i < NGHTTP2_DEFAULT_STREAM_RESET_BURST) {
12054 CU_ASSERT(0 == nghttp2_outbound_queue_size(&session->ob_reg));
12055
12056 continue;
12057 }
12058
12059 CU_ASSERT(1 == nghttp2_outbound_queue_size(&session->ob_reg));
12060
12061 item = nghttp2_session_get_next_ob_item(session);
12062
12063 CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
12064 CU_ASSERT(NGHTTP2_DEFAULT_STREAM_RESET_BURST * 2 + 1 ==
12065 item->frame.goaway.last_stream_id);
12066 }
12067
12068 nghttp2_hd_deflate_free(&deflater);
12069 nghttp2_session_del(session);
12070 nghttp2_bufs_free(&bufs);
12071 nghttp2_option_del(option);
12072 }
12073
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)12074 static void check_nghttp2_http_recv_headers_fail(
12075 nghttp2_session *session, nghttp2_hd_deflater *deflater, int32_t stream_id,
12076 int stream_state, const nghttp2_nv *nva, size_t nvlen) {
12077 nghttp2_mem *mem;
12078 ssize_t rv;
12079 nghttp2_outbound_item *item;
12080 nghttp2_bufs bufs;
12081 my_user_data *ud;
12082
12083 mem = nghttp2_mem_default();
12084 frame_pack_bufs_init(&bufs);
12085
12086 ud = session->user_data;
12087
12088 if (stream_state != -1) {
12089 if (nghttp2_session_is_my_stream_id(session, stream_id)) {
12090 open_sent_stream2(session, stream_id, (nghttp2_stream_state)stream_state);
12091 } else {
12092 open_recv_stream2(session, stream_id, (nghttp2_stream_state)stream_state);
12093 }
12094 }
12095
12096 rv = pack_headers(&bufs, deflater, stream_id, NGHTTP2_FLAG_END_HEADERS, nva,
12097 nvlen, mem);
12098 CU_ASSERT(0 == rv);
12099
12100 ud->invalid_frame_recv_cb_called = 0;
12101
12102 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
12103 nghttp2_buf_len(&bufs.head->buf));
12104
12105 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
12106
12107 item = nghttp2_session_get_next_ob_item(session);
12108
12109 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
12110 CU_ASSERT(1 == ud->invalid_frame_recv_cb_called);
12111
12112 CU_ASSERT(0 == nghttp2_session_send(session));
12113
12114 nghttp2_bufs_free(&bufs);
12115 }
12116
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)12117 static void check_nghttp2_http_recv_headers_ok(
12118 nghttp2_session *session, nghttp2_hd_deflater *deflater, int32_t stream_id,
12119 int stream_state, const nghttp2_nv *nva, size_t nvlen) {
12120 nghttp2_mem *mem;
12121 ssize_t rv;
12122 nghttp2_bufs bufs;
12123 my_user_data *ud;
12124
12125 mem = nghttp2_mem_default();
12126 frame_pack_bufs_init(&bufs);
12127
12128 ud = session->user_data;
12129
12130 if (stream_state != -1) {
12131 if (nghttp2_session_is_my_stream_id(session, stream_id)) {
12132 open_sent_stream2(session, stream_id, (nghttp2_stream_state)stream_state);
12133 } else {
12134 open_recv_stream2(session, stream_id, (nghttp2_stream_state)stream_state);
12135 }
12136 }
12137
12138 rv = pack_headers(&bufs, deflater, stream_id, NGHTTP2_FLAG_END_HEADERS, nva,
12139 nvlen, mem);
12140 CU_ASSERT(0 == rv);
12141
12142 ud->frame_recv_cb_called = 0;
12143
12144 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
12145 nghttp2_buf_len(&bufs.head->buf));
12146
12147 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
12148 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
12149 CU_ASSERT(1 == ud->frame_recv_cb_called);
12150
12151 nghttp2_bufs_free(&bufs);
12152 }
12153
test_nghttp2_http_mandatory_headers(void)12154 void test_nghttp2_http_mandatory_headers(void) {
12155 nghttp2_session *session;
12156 nghttp2_session_callbacks callbacks;
12157 nghttp2_hd_deflater deflater;
12158 nghttp2_mem *mem;
12159 my_user_data ud;
12160 /* test case for response */
12161 const nghttp2_nv nostatus_resnv[] = {MAKE_NV("server", "foo")};
12162 const nghttp2_nv dupstatus_resnv[] = {MAKE_NV(":status", "200"),
12163 MAKE_NV(":status", "200")};
12164 const nghttp2_nv badpseudo_resnv[] = {MAKE_NV(":status", "200"),
12165 MAKE_NV(":scheme", "https")};
12166 const nghttp2_nv latepseudo_resnv[] = {MAKE_NV("server", "foo"),
12167 MAKE_NV(":status", "200")};
12168 const nghttp2_nv badstatus_resnv[] = {MAKE_NV(":status", "2000")};
12169 const nghttp2_nv badcl_resnv[] = {MAKE_NV(":status", "200"),
12170 MAKE_NV("content-length", "-1")};
12171 const nghttp2_nv dupcl_resnv[] = {MAKE_NV(":status", "200"),
12172 MAKE_NV("content-length", "0"),
12173 MAKE_NV("content-length", "0")};
12174 const nghttp2_nv badhd_resnv[] = {MAKE_NV(":status", "200"),
12175 MAKE_NV("connection", "close")};
12176 const nghttp2_nv cl1xx_resnv[] = {MAKE_NV(":status", "100"),
12177 MAKE_NV("content-length", "0")};
12178 const nghttp2_nv cl204_resnv[] = {MAKE_NV(":status", "204"),
12179 MAKE_NV("content-length", "0")};
12180 const nghttp2_nv clnonzero204_resnv[] = {MAKE_NV(":status", "204"),
12181 MAKE_NV("content-length", "100")};
12182 const nghttp2_nv status101_resnv[] = {MAKE_NV(":status", "101")};
12183 const nghttp2_nv unexpectedhost_resnv[] = {MAKE_NV(":status", "200"),
12184 MAKE_NV("host", "/localhost")};
12185
12186 /* test case for request */
12187 const nghttp2_nv nopath_reqnv[] = {MAKE_NV(":scheme", "https"),
12188 MAKE_NV(":method", "GET"),
12189 MAKE_NV(":authority", "localhost")};
12190 const nghttp2_nv earlyconnect_reqnv[] = {
12191 MAKE_NV(":method", "CONNECT"), MAKE_NV(":scheme", "https"),
12192 MAKE_NV(":path", "/"), MAKE_NV(":authority", "localhost")};
12193 const nghttp2_nv lateconnect_reqnv[] = {
12194 MAKE_NV(":scheme", "https"), MAKE_NV(":path", "/"),
12195 MAKE_NV(":method", "CONNECT"), MAKE_NV(":authority", "localhost")};
12196 const nghttp2_nv duppath_reqnv[] = {
12197 MAKE_NV(":scheme", "https"), MAKE_NV(":method", "GET"),
12198 MAKE_NV(":authority", "localhost"), MAKE_NV(":path", "/"),
12199 MAKE_NV(":path", "/")};
12200 const nghttp2_nv badcl_reqnv[] = {
12201 MAKE_NV(":scheme", "https"), MAKE_NV(":method", "POST"),
12202 MAKE_NV(":authority", "localhost"), MAKE_NV(":path", "/"),
12203 MAKE_NV("content-length", "-1")};
12204 const nghttp2_nv dupcl_reqnv[] = {
12205 MAKE_NV(":scheme", "https"), MAKE_NV(":method", "POST"),
12206 MAKE_NV(":authority", "localhost"), MAKE_NV(":path", "/"),
12207 MAKE_NV("content-length", "0"), MAKE_NV("content-length", "0")};
12208 const nghttp2_nv badhd_reqnv[] = {
12209 MAKE_NV(":scheme", "https"), MAKE_NV(":method", "GET"),
12210 MAKE_NV(":authority", "localhost"), MAKE_NV(":path", "/"),
12211 MAKE_NV("connection", "close")};
12212 const nghttp2_nv badauthority_reqnv[] = {
12213 MAKE_NV(":scheme", "https"), MAKE_NV(":method", "GET"),
12214 MAKE_NV(":authority", "\x0d\x0alocalhost"), MAKE_NV(":path", "/")};
12215 const nghttp2_nv badhdbtw_reqnv[] = {
12216 MAKE_NV(":scheme", "https"), MAKE_NV(":method", "GET"),
12217 MAKE_NV("foo", "\x0d\x0a"), MAKE_NV(":authority", "localhost"),
12218 MAKE_NV(":path", "/")};
12219 const nghttp2_nv asteriskget1_reqnv[] = {
12220 MAKE_NV(":path", "*"), MAKE_NV(":scheme", "https"),
12221 MAKE_NV(":authority", "localhost"), MAKE_NV(":method", "GET")};
12222 const nghttp2_nv asteriskget2_reqnv[] = {
12223 MAKE_NV(":scheme", "https"), MAKE_NV(":authority", "localhost"),
12224 MAKE_NV(":method", "GET"), MAKE_NV(":path", "*")};
12225 const nghttp2_nv asteriskoptions1_reqnv[] = {
12226 MAKE_NV(":path", "*"), MAKE_NV(":scheme", "https"),
12227 MAKE_NV(":authority", "localhost"), MAKE_NV(":method", "OPTIONS")};
12228 const nghttp2_nv asteriskoptions2_reqnv[] = {
12229 MAKE_NV(":scheme", "https"), MAKE_NV(":authority", "localhost"),
12230 MAKE_NV(":method", "OPTIONS"), MAKE_NV(":path", "*")};
12231 const nghttp2_nv connectproto_reqnv[] = {
12232 MAKE_NV(":scheme", "https"), MAKE_NV(":path", "/"),
12233 MAKE_NV(":method", "CONNECT"), MAKE_NV(":authority", "localhost"),
12234 MAKE_NV(":protocol", "websocket")};
12235 const nghttp2_nv connectprotoget_reqnv[] = {
12236 MAKE_NV(":scheme", "https"), MAKE_NV(":path", "/"),
12237 MAKE_NV(":method", "GET"), MAKE_NV(":authority", "localhost"),
12238 MAKE_NV(":protocol", "websocket")};
12239 const nghttp2_nv connectprotonopath_reqnv[] = {
12240 MAKE_NV(":scheme", "https"), MAKE_NV(":method", "CONNECT"),
12241 MAKE_NV(":authority", "localhost"), MAKE_NV(":protocol", "websocket")};
12242 const nghttp2_nv connectprotonoauth_reqnv[] = {
12243 MAKE_NV(":scheme", "http"), MAKE_NV(":path", "/"),
12244 MAKE_NV(":method", "CONNECT"), MAKE_NV("host", "localhost"),
12245 MAKE_NV(":protocol", "websocket")};
12246 const nghttp2_nv regularconnect_reqnv[] = {
12247 MAKE_NV(":method", "CONNECT"), MAKE_NV(":authority", "localhost")};
12248
12249 mem = nghttp2_mem_default();
12250
12251 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
12252 callbacks.send_callback = null_send_callback;
12253 callbacks.on_frame_recv_callback = on_frame_recv_callback;
12254 callbacks.on_invalid_frame_recv_callback = on_invalid_frame_recv_callback;
12255
12256 nghttp2_session_client_new(&session, &callbacks, &ud);
12257
12258 nghttp2_hd_deflate_init(&deflater, mem);
12259
12260 /* response header lacks :status */
12261 check_nghttp2_http_recv_headers_fail(session, &deflater, 1,
12262 NGHTTP2_STREAM_OPENING, nostatus_resnv,
12263 ARRLEN(nostatus_resnv));
12264
12265 /* response header has 2 :status */
12266 check_nghttp2_http_recv_headers_fail(session, &deflater, 3,
12267 NGHTTP2_STREAM_OPENING, dupstatus_resnv,
12268 ARRLEN(dupstatus_resnv));
12269
12270 /* response header has bad pseudo header :scheme */
12271 check_nghttp2_http_recv_headers_fail(session, &deflater, 5,
12272 NGHTTP2_STREAM_OPENING, badpseudo_resnv,
12273 ARRLEN(badpseudo_resnv));
12274
12275 /* response header has :status after regular header field */
12276 check_nghttp2_http_recv_headers_fail(session, &deflater, 7,
12277 NGHTTP2_STREAM_OPENING, latepseudo_resnv,
12278 ARRLEN(latepseudo_resnv));
12279
12280 /* response header has bad status code */
12281 check_nghttp2_http_recv_headers_fail(session, &deflater, 9,
12282 NGHTTP2_STREAM_OPENING, badstatus_resnv,
12283 ARRLEN(badstatus_resnv));
12284
12285 /* response header has bad content-length */
12286 check_nghttp2_http_recv_headers_fail(session, &deflater, 11,
12287 NGHTTP2_STREAM_OPENING, badcl_resnv,
12288 ARRLEN(badcl_resnv));
12289
12290 /* response header has multiple content-length */
12291 check_nghttp2_http_recv_headers_fail(session, &deflater, 13,
12292 NGHTTP2_STREAM_OPENING, dupcl_resnv,
12293 ARRLEN(dupcl_resnv));
12294
12295 /* response header has disallowed header field */
12296 check_nghttp2_http_recv_headers_fail(session, &deflater, 15,
12297 NGHTTP2_STREAM_OPENING, badhd_resnv,
12298 ARRLEN(badhd_resnv));
12299
12300 /* response header has content-length with 100 status code */
12301 check_nghttp2_http_recv_headers_fail(session, &deflater, 17,
12302 NGHTTP2_STREAM_OPENING, cl1xx_resnv,
12303 ARRLEN(cl1xx_resnv));
12304
12305 /* response header has 0 content-length with 204 status code */
12306 check_nghttp2_http_recv_headers_ok(session, &deflater, 19,
12307 NGHTTP2_STREAM_OPENING, cl204_resnv,
12308 ARRLEN(cl204_resnv));
12309
12310 /* response header has nonzero content-length with 204 status
12311 code */
12312 check_nghttp2_http_recv_headers_fail(
12313 session, &deflater, 21, NGHTTP2_STREAM_OPENING, clnonzero204_resnv,
12314 ARRLEN(clnonzero204_resnv));
12315
12316 /* status code 101 should not be used in HTTP/2 because it is used
12317 for HTTP Upgrade which HTTP/2 removes. */
12318 check_nghttp2_http_recv_headers_fail(session, &deflater, 23,
12319 NGHTTP2_STREAM_OPENING, status101_resnv,
12320 ARRLEN(status101_resnv));
12321
12322 /* Specific characters check for host field in response header
12323 should not be done as its use is undefined. */
12324 check_nghttp2_http_recv_headers_ok(
12325 session, &deflater, 25, NGHTTP2_STREAM_OPENING, unexpectedhost_resnv,
12326 ARRLEN(unexpectedhost_resnv));
12327
12328 nghttp2_hd_deflate_free(&deflater);
12329
12330 nghttp2_session_del(session);
12331
12332 /* check server side */
12333 nghttp2_session_server_new(&session, &callbacks, &ud);
12334
12335 nghttp2_hd_deflate_init(&deflater, mem);
12336
12337 /* request header has no :path */
12338 check_nghttp2_http_recv_headers_fail(session, &deflater, 1, -1, nopath_reqnv,
12339 ARRLEN(nopath_reqnv));
12340
12341 /* request header has CONNECT method, but followed by :path */
12342 check_nghttp2_http_recv_headers_fail(session, &deflater, 3, -1,
12343 earlyconnect_reqnv,
12344 ARRLEN(earlyconnect_reqnv));
12345
12346 /* request header has CONNECT method following :path */
12347 check_nghttp2_http_recv_headers_fail(
12348 session, &deflater, 5, -1, lateconnect_reqnv, ARRLEN(lateconnect_reqnv));
12349
12350 /* request header has multiple :path */
12351 check_nghttp2_http_recv_headers_fail(session, &deflater, 7, -1, duppath_reqnv,
12352 ARRLEN(duppath_reqnv));
12353
12354 /* request header has bad content-length */
12355 check_nghttp2_http_recv_headers_fail(session, &deflater, 9, -1, badcl_reqnv,
12356 ARRLEN(badcl_reqnv));
12357
12358 /* request header has multiple content-length */
12359 check_nghttp2_http_recv_headers_fail(session, &deflater, 11, -1, dupcl_reqnv,
12360 ARRLEN(dupcl_reqnv));
12361
12362 /* request header has disallowed header field */
12363 check_nghttp2_http_recv_headers_fail(session, &deflater, 13, -1, badhd_reqnv,
12364 ARRLEN(badhd_reqnv));
12365
12366 /* request header has :authority header field containing illegal
12367 characters */
12368 check_nghttp2_http_recv_headers_fail(session, &deflater, 15, -1,
12369 badauthority_reqnv,
12370 ARRLEN(badauthority_reqnv));
12371
12372 /* request header has regular header field containing illegal
12373 character before all mandatory header fields are seen. */
12374 check_nghttp2_http_recv_headers_fail(session, &deflater, 17, -1,
12375 badhdbtw_reqnv, ARRLEN(badhdbtw_reqnv));
12376
12377 /* request header has "*" in :path header field while method is GET.
12378 :path is received before :method */
12379 check_nghttp2_http_recv_headers_fail(session, &deflater, 19, -1,
12380 asteriskget1_reqnv,
12381 ARRLEN(asteriskget1_reqnv));
12382
12383 /* request header has "*" in :path header field while method is GET.
12384 :method is received before :path */
12385 check_nghttp2_http_recv_headers_fail(session, &deflater, 21, -1,
12386 asteriskget2_reqnv,
12387 ARRLEN(asteriskget2_reqnv));
12388
12389 /* OPTIONS method can include "*" in :path header field. :path is
12390 received before :method. */
12391 check_nghttp2_http_recv_headers_ok(session, &deflater, 23, -1,
12392 asteriskoptions1_reqnv,
12393 ARRLEN(asteriskoptions1_reqnv));
12394
12395 /* OPTIONS method can include "*" in :path header field. :method is
12396 received before :path. */
12397 check_nghttp2_http_recv_headers_ok(session, &deflater, 25, -1,
12398 asteriskoptions2_reqnv,
12399 ARRLEN(asteriskoptions2_reqnv));
12400
12401 /* :protocol is not allowed unless it is enabled by the local
12402 endpoint. */
12403 check_nghttp2_http_recv_headers_fail(session, &deflater, 27, -1,
12404 connectproto_reqnv,
12405 ARRLEN(connectproto_reqnv));
12406
12407 nghttp2_hd_deflate_free(&deflater);
12408
12409 nghttp2_session_del(session);
12410
12411 /* enable SETTINGS_CONNECT_PROTOCOL */
12412 nghttp2_session_server_new(&session, &callbacks, &ud);
12413
12414 session->pending_enable_connect_protocol = 1;
12415
12416 nghttp2_hd_deflate_init(&deflater, mem);
12417
12418 /* :protocol is allowed if SETTINGS_CONNECT_PROTOCOL is enabled by
12419 the local endpoint. */
12420 check_nghttp2_http_recv_headers_ok(session, &deflater, 1, -1,
12421 connectproto_reqnv,
12422 ARRLEN(connectproto_reqnv));
12423
12424 /* :protocol is only allowed with CONNECT method. */
12425 check_nghttp2_http_recv_headers_fail(session, &deflater, 3, -1,
12426 connectprotoget_reqnv,
12427 ARRLEN(connectprotoget_reqnv));
12428
12429 /* CONNECT method with :protocol requires :path. */
12430 check_nghttp2_http_recv_headers_fail(session, &deflater, 5, -1,
12431 connectprotonopath_reqnv,
12432 ARRLEN(connectprotonopath_reqnv));
12433
12434 /* CONNECT method with :protocol requires :authority. */
12435 check_nghttp2_http_recv_headers_fail(session, &deflater, 7, -1,
12436 connectprotonoauth_reqnv,
12437 ARRLEN(connectprotonoauth_reqnv));
12438
12439 /* regular CONNECT method should succeed with
12440 SETTINGS_CONNECT_PROTOCOL */
12441 check_nghttp2_http_recv_headers_ok(session, &deflater, 9, -1,
12442 regularconnect_reqnv,
12443 ARRLEN(regularconnect_reqnv));
12444
12445 nghttp2_hd_deflate_free(&deflater);
12446
12447 nghttp2_session_del(session);
12448 }
12449
test_nghttp2_http_content_length(void)12450 void test_nghttp2_http_content_length(void) {
12451 nghttp2_session *session;
12452 nghttp2_session_callbacks callbacks;
12453 nghttp2_hd_deflater deflater;
12454 nghttp2_mem *mem;
12455 nghttp2_bufs bufs;
12456 ssize_t rv;
12457 nghttp2_stream *stream;
12458 const nghttp2_nv cl_resnv[] = {MAKE_NV(":status", "200"),
12459 MAKE_NV("te", "trailers"),
12460 MAKE_NV("content-length", "9000000000")};
12461 const nghttp2_nv cl_reqnv[] = {
12462 MAKE_NV(":path", "/"), MAKE_NV(":method", "PUT"),
12463 MAKE_NV(":scheme", "https"), MAKE_NV("te", "trailers"),
12464 MAKE_NV("host", "localhost"), MAKE_NV("content-length", "9000000000")};
12465
12466 mem = nghttp2_mem_default();
12467 frame_pack_bufs_init(&bufs);
12468
12469 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
12470 callbacks.send_callback = null_send_callback;
12471
12472 nghttp2_session_client_new(&session, &callbacks, NULL);
12473
12474 nghttp2_hd_deflate_init(&deflater, mem);
12475
12476 stream = open_sent_stream2(session, 1, NGHTTP2_STREAM_OPENING);
12477
12478 rv = pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, cl_resnv,
12479 ARRLEN(cl_resnv), mem);
12480 CU_ASSERT(0 == rv);
12481
12482 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
12483 nghttp2_buf_len(&bufs.head->buf));
12484
12485 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
12486 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
12487 CU_ASSERT(9000000000LL == stream->content_length);
12488 CU_ASSERT(200 == stream->status_code);
12489
12490 nghttp2_hd_deflate_free(&deflater);
12491
12492 nghttp2_session_del(session);
12493
12494 nghttp2_bufs_reset(&bufs);
12495
12496 /* check server side */
12497 nghttp2_session_server_new(&session, &callbacks, NULL);
12498
12499 nghttp2_hd_deflate_init(&deflater, mem);
12500
12501 rv = pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, cl_reqnv,
12502 ARRLEN(cl_reqnv), mem);
12503 CU_ASSERT(0 == rv);
12504
12505 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
12506 nghttp2_buf_len(&bufs.head->buf));
12507
12508 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
12509
12510 stream = nghttp2_session_get_stream(session, 1);
12511
12512 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
12513 CU_ASSERT(9000000000LL == stream->content_length);
12514
12515 nghttp2_hd_deflate_free(&deflater);
12516
12517 nghttp2_session_del(session);
12518
12519 nghttp2_bufs_free(&bufs);
12520 }
12521
test_nghttp2_http_content_length_mismatch(void)12522 void test_nghttp2_http_content_length_mismatch(void) {
12523 nghttp2_session *session;
12524 nghttp2_session_callbacks callbacks;
12525 nghttp2_hd_deflater deflater;
12526 nghttp2_mem *mem;
12527 nghttp2_bufs bufs;
12528 ssize_t rv;
12529 const nghttp2_nv cl_reqnv[] = {
12530 MAKE_NV(":path", "/"), MAKE_NV(":method", "PUT"),
12531 MAKE_NV(":authority", "localhost"), MAKE_NV(":scheme", "https"),
12532 MAKE_NV("content-length", "20")};
12533 const nghttp2_nv cl_resnv[] = {MAKE_NV(":status", "200"),
12534 MAKE_NV("content-length", "20")};
12535 nghttp2_outbound_item *item;
12536 nghttp2_frame_hd hd;
12537
12538 mem = nghttp2_mem_default();
12539 frame_pack_bufs_init(&bufs);
12540
12541 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
12542 callbacks.send_callback = null_send_callback;
12543
12544 nghttp2_session_server_new(&session, &callbacks, NULL);
12545
12546 nghttp2_hd_deflate_init(&deflater, mem);
12547
12548 /* header says content-length: 20, but HEADERS has END_STREAM flag set */
12549 rv = pack_headers(&bufs, &deflater, 1,
12550 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM,
12551 cl_reqnv, ARRLEN(cl_reqnv), mem);
12552 CU_ASSERT(0 == rv);
12553
12554 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
12555 nghttp2_buf_len(&bufs.head->buf));
12556
12557 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
12558
12559 item = nghttp2_session_get_next_ob_item(session);
12560 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
12561
12562 CU_ASSERT(0 == nghttp2_session_send(session));
12563
12564 nghttp2_bufs_reset(&bufs);
12565
12566 /* header says content-length: 20, but DATA has 0 byte */
12567 rv = pack_headers(&bufs, &deflater, 3, NGHTTP2_FLAG_END_HEADERS, cl_reqnv,
12568 ARRLEN(cl_reqnv), mem);
12569 CU_ASSERT(0 == rv);
12570
12571 nghttp2_frame_hd_init(&hd, 0, NGHTTP2_DATA, NGHTTP2_FLAG_END_STREAM, 3);
12572 nghttp2_frame_pack_frame_hd(bufs.head->buf.last, &hd);
12573 bufs.head->buf.last += NGHTTP2_FRAME_HDLEN;
12574
12575 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
12576 nghttp2_buf_len(&bufs.head->buf));
12577
12578 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
12579
12580 item = nghttp2_session_get_next_ob_item(session);
12581 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
12582
12583 CU_ASSERT(0 == nghttp2_session_send(session));
12584
12585 nghttp2_bufs_reset(&bufs);
12586
12587 /* header says content-length: 20, but DATA has 21 bytes */
12588 rv = pack_headers(&bufs, &deflater, 5, NGHTTP2_FLAG_END_HEADERS, cl_reqnv,
12589 ARRLEN(cl_reqnv), mem);
12590 CU_ASSERT(0 == rv);
12591
12592 nghttp2_frame_hd_init(&hd, 21, NGHTTP2_DATA, NGHTTP2_FLAG_END_STREAM, 5);
12593 nghttp2_frame_pack_frame_hd(bufs.head->buf.last, &hd);
12594 bufs.head->buf.last += NGHTTP2_FRAME_HDLEN + 21;
12595
12596 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
12597 nghttp2_buf_len(&bufs.head->buf));
12598
12599 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
12600
12601 item = nghttp2_session_get_next_ob_item(session);
12602 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
12603
12604 CU_ASSERT(0 == nghttp2_session_send(session));
12605
12606 nghttp2_bufs_reset(&bufs);
12607
12608 nghttp2_hd_deflate_free(&deflater);
12609
12610 nghttp2_session_del(session);
12611
12612 /* Check for client */
12613 nghttp2_session_client_new(&session, &callbacks, NULL);
12614
12615 nghttp2_hd_deflate_init(&deflater, mem);
12616
12617 /* header says content-length: 20, but HEADERS has END_STREAM flag set */
12618 nghttp2_submit_request(session, NULL, reqnv, ARRLEN(reqnv), NULL, NULL);
12619
12620 CU_ASSERT(0 == nghttp2_session_send(session));
12621
12622 rv = pack_headers(&bufs, &deflater, 1,
12623 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM,
12624 cl_resnv, ARRLEN(cl_resnv), mem);
12625 CU_ASSERT(0 == rv);
12626
12627 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
12628 nghttp2_buf_len(&bufs.head->buf));
12629
12630 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
12631
12632 item = nghttp2_session_get_next_ob_item(session);
12633 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
12634
12635 CU_ASSERT(NULL != nghttp2_session_get_stream(session, 1));
12636 CU_ASSERT(0 == nghttp2_session_send(session));
12637 /* After sending RST_STREAM, stream must be closed */
12638 CU_ASSERT(NULL == nghttp2_session_get_stream(session, 1));
12639
12640 nghttp2_bufs_reset(&bufs);
12641
12642 /* header says content-length: 20, but DATA has 0 byte */
12643 nghttp2_submit_request(session, NULL, reqnv, ARRLEN(reqnv), NULL, NULL);
12644
12645 CU_ASSERT(0 == nghttp2_session_send(session));
12646
12647 rv = pack_headers(&bufs, &deflater, 3, NGHTTP2_FLAG_END_HEADERS, cl_resnv,
12648 ARRLEN(cl_resnv), mem);
12649 CU_ASSERT(0 == rv);
12650
12651 nghttp2_frame_hd_init(&hd, 0, NGHTTP2_DATA, NGHTTP2_FLAG_END_STREAM, 3);
12652 nghttp2_frame_pack_frame_hd(bufs.head->buf.last, &hd);
12653 bufs.head->buf.last += NGHTTP2_FRAME_HDLEN;
12654
12655 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
12656 nghttp2_buf_len(&bufs.head->buf));
12657
12658 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
12659
12660 item = nghttp2_session_get_next_ob_item(session);
12661 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
12662
12663 CU_ASSERT(NULL != nghttp2_session_get_stream(session, 3));
12664 CU_ASSERT(0 == nghttp2_session_send(session));
12665 /* After sending RST_STREAM, stream must be closed */
12666 CU_ASSERT(NULL == nghttp2_session_get_stream(session, 3));
12667
12668 nghttp2_bufs_reset(&bufs);
12669
12670 /* header says content-length: 20, but DATA has 21 bytes */
12671 nghttp2_submit_request(session, NULL, reqnv, ARRLEN(reqnv), NULL, NULL);
12672
12673 CU_ASSERT(0 == nghttp2_session_send(session));
12674
12675 rv = pack_headers(&bufs, &deflater, 5, NGHTTP2_FLAG_END_HEADERS, cl_resnv,
12676 ARRLEN(cl_resnv), mem);
12677 CU_ASSERT(0 == rv);
12678
12679 nghttp2_frame_hd_init(&hd, 21, NGHTTP2_DATA, NGHTTP2_FLAG_END_STREAM, 5);
12680 nghttp2_frame_pack_frame_hd(bufs.head->buf.last, &hd);
12681 bufs.head->buf.last += NGHTTP2_FRAME_HDLEN + 21;
12682
12683 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
12684 nghttp2_buf_len(&bufs.head->buf));
12685
12686 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
12687
12688 item = nghttp2_session_get_next_ob_item(session);
12689 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
12690
12691 CU_ASSERT(NULL != nghttp2_session_get_stream(session, 5));
12692 CU_ASSERT(0 == nghttp2_session_send(session));
12693 /* After sending RST_STREAM, stream must be closed */
12694 CU_ASSERT(NULL == nghttp2_session_get_stream(session, 5));
12695
12696 nghttp2_bufs_reset(&bufs);
12697
12698 nghttp2_bufs_free(&bufs);
12699
12700 nghttp2_hd_deflate_free(&deflater);
12701
12702 nghttp2_session_del(session);
12703 }
12704
test_nghttp2_http_non_final_response(void)12705 void test_nghttp2_http_non_final_response(void) {
12706 nghttp2_session *session;
12707 nghttp2_session_callbacks callbacks;
12708 nghttp2_hd_deflater deflater;
12709 nghttp2_mem *mem;
12710 nghttp2_bufs bufs;
12711 ssize_t rv;
12712 const nghttp2_nv nonfinal_resnv[] = {
12713 MAKE_NV(":status", "100"),
12714 };
12715 nghttp2_outbound_item *item;
12716 nghttp2_frame_hd hd;
12717
12718 mem = nghttp2_mem_default();
12719 frame_pack_bufs_init(&bufs);
12720
12721 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
12722 callbacks.send_callback = null_send_callback;
12723
12724 nghttp2_session_client_new(&session, &callbacks, NULL);
12725
12726 nghttp2_hd_deflate_init(&deflater, mem);
12727
12728 /* non-final HEADERS with END_STREAM is illegal */
12729 open_sent_stream2(session, 1, NGHTTP2_STREAM_OPENING);
12730
12731 rv = pack_headers(&bufs, &deflater, 1,
12732 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM,
12733 nonfinal_resnv, ARRLEN(nonfinal_resnv), mem);
12734 CU_ASSERT(0 == rv);
12735
12736 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
12737 nghttp2_buf_len(&bufs.head->buf));
12738
12739 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
12740
12741 item = nghttp2_session_get_next_ob_item(session);
12742 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
12743
12744 CU_ASSERT(0 == nghttp2_session_send(session));
12745
12746 nghttp2_bufs_reset(&bufs);
12747
12748 /* non-final HEADERS followed by non-empty DATA is illegal */
12749 open_sent_stream2(session, 3, NGHTTP2_STREAM_OPENING);
12750
12751 rv = pack_headers(&bufs, &deflater, 3, NGHTTP2_FLAG_END_HEADERS,
12752 nonfinal_resnv, ARRLEN(nonfinal_resnv), mem);
12753 CU_ASSERT(0 == rv);
12754
12755 nghttp2_frame_hd_init(&hd, 10, NGHTTP2_DATA, NGHTTP2_FLAG_END_STREAM, 3);
12756 nghttp2_frame_pack_frame_hd(bufs.head->buf.last, &hd);
12757 bufs.head->buf.last += NGHTTP2_FRAME_HDLEN + 10;
12758
12759 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
12760 nghttp2_buf_len(&bufs.head->buf));
12761
12762 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
12763
12764 item = nghttp2_session_get_next_ob_item(session);
12765 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
12766
12767 CU_ASSERT(0 == nghttp2_session_send(session));
12768
12769 nghttp2_bufs_reset(&bufs);
12770
12771 /* non-final HEADERS followed by empty DATA (without END_STREAM) is
12772 ok */
12773 open_sent_stream2(session, 5, NGHTTP2_STREAM_OPENING);
12774
12775 rv = pack_headers(&bufs, &deflater, 5, NGHTTP2_FLAG_END_HEADERS,
12776 nonfinal_resnv, ARRLEN(nonfinal_resnv), mem);
12777 CU_ASSERT(0 == rv);
12778
12779 nghttp2_frame_hd_init(&hd, 0, NGHTTP2_DATA, NGHTTP2_FLAG_NONE, 5);
12780 nghttp2_frame_pack_frame_hd(bufs.head->buf.last, &hd);
12781 bufs.head->buf.last += NGHTTP2_FRAME_HDLEN;
12782
12783 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
12784 nghttp2_buf_len(&bufs.head->buf));
12785
12786 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
12787
12788 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
12789
12790 nghttp2_bufs_reset(&bufs);
12791
12792 /* non-final HEADERS followed by empty DATA (with END_STREAM) is
12793 illegal */
12794 open_sent_stream2(session, 7, NGHTTP2_STREAM_OPENING);
12795
12796 rv = pack_headers(&bufs, &deflater, 7, NGHTTP2_FLAG_END_HEADERS,
12797 nonfinal_resnv, ARRLEN(nonfinal_resnv), mem);
12798 CU_ASSERT(0 == rv);
12799
12800 nghttp2_frame_hd_init(&hd, 0, NGHTTP2_DATA, NGHTTP2_FLAG_END_STREAM, 7);
12801 nghttp2_frame_pack_frame_hd(bufs.head->buf.last, &hd);
12802 bufs.head->buf.last += NGHTTP2_FRAME_HDLEN;
12803
12804 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
12805 nghttp2_buf_len(&bufs.head->buf));
12806
12807 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
12808
12809 item = nghttp2_session_get_next_ob_item(session);
12810
12811 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
12812
12813 CU_ASSERT(0 == nghttp2_session_send(session));
12814
12815 nghttp2_bufs_reset(&bufs);
12816
12817 /* non-final HEADERS followed by final HEADERS is OK */
12818 open_sent_stream2(session, 9, NGHTTP2_STREAM_OPENING);
12819
12820 rv = pack_headers(&bufs, &deflater, 9, NGHTTP2_FLAG_END_HEADERS,
12821 nonfinal_resnv, ARRLEN(nonfinal_resnv), mem);
12822 CU_ASSERT(0 == rv);
12823
12824 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
12825 nghttp2_buf_len(&bufs.head->buf));
12826
12827 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
12828
12829 nghttp2_bufs_reset(&bufs);
12830
12831 rv = pack_headers(&bufs, &deflater, 9, NGHTTP2_FLAG_END_HEADERS, resnv,
12832 ARRLEN(resnv), mem);
12833 CU_ASSERT(0 == rv);
12834
12835 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
12836 nghttp2_buf_len(&bufs.head->buf));
12837
12838 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
12839
12840 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
12841
12842 nghttp2_bufs_reset(&bufs);
12843
12844 nghttp2_hd_deflate_free(&deflater);
12845
12846 nghttp2_session_del(session);
12847
12848 nghttp2_bufs_free(&bufs);
12849 }
12850
test_nghttp2_http_trailer_headers(void)12851 void test_nghttp2_http_trailer_headers(void) {
12852 nghttp2_session *session;
12853 nghttp2_session_callbacks callbacks;
12854 nghttp2_hd_deflater deflater;
12855 nghttp2_mem *mem;
12856 nghttp2_bufs bufs;
12857 ssize_t rv;
12858 const nghttp2_nv trailer_reqnv[] = {
12859 MAKE_NV("foo", "bar"),
12860 };
12861 nghttp2_outbound_item *item;
12862
12863 mem = nghttp2_mem_default();
12864 frame_pack_bufs_init(&bufs);
12865
12866 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
12867 callbacks.send_callback = null_send_callback;
12868
12869 nghttp2_session_server_new(&session, &callbacks, NULL);
12870
12871 nghttp2_hd_deflate_init(&deflater, mem);
12872
12873 /* good trailer header */
12874 rv = pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, reqnv,
12875 ARRLEN(reqnv), mem);
12876 CU_ASSERT(0 == rv);
12877
12878 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
12879 nghttp2_buf_len(&bufs.head->buf));
12880
12881 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
12882
12883 nghttp2_bufs_reset(&bufs);
12884
12885 rv = pack_headers(&bufs, &deflater, 1,
12886 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM,
12887 trailer_reqnv, ARRLEN(trailer_reqnv), mem);
12888 CU_ASSERT(0 == rv);
12889
12890 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
12891 nghttp2_buf_len(&bufs.head->buf));
12892
12893 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
12894
12895 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
12896
12897 nghttp2_bufs_reset(&bufs);
12898
12899 /* trailer header without END_STREAM is illegal */
12900 rv = pack_headers(&bufs, &deflater, 3, NGHTTP2_FLAG_END_HEADERS, reqnv,
12901 ARRLEN(reqnv), mem);
12902 CU_ASSERT(0 == rv);
12903
12904 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
12905 nghttp2_buf_len(&bufs.head->buf));
12906
12907 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
12908
12909 nghttp2_bufs_reset(&bufs);
12910
12911 rv = pack_headers(&bufs, &deflater, 3, NGHTTP2_FLAG_END_HEADERS,
12912 trailer_reqnv, ARRLEN(trailer_reqnv), mem);
12913 CU_ASSERT(0 == rv);
12914
12915 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
12916 nghttp2_buf_len(&bufs.head->buf));
12917
12918 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
12919
12920 item = nghttp2_session_get_next_ob_item(session);
12921
12922 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
12923
12924 CU_ASSERT(0 == nghttp2_session_send(session));
12925
12926 nghttp2_bufs_reset(&bufs);
12927
12928 /* trailer header including pseudo header field is illegal */
12929 rv = pack_headers(&bufs, &deflater, 5, NGHTTP2_FLAG_END_HEADERS, reqnv,
12930 ARRLEN(reqnv), mem);
12931 CU_ASSERT(0 == rv);
12932
12933 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
12934 nghttp2_buf_len(&bufs.head->buf));
12935
12936 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
12937
12938 nghttp2_bufs_reset(&bufs);
12939
12940 rv = pack_headers(&bufs, &deflater, 5, NGHTTP2_FLAG_END_HEADERS, reqnv,
12941 ARRLEN(reqnv), mem);
12942 CU_ASSERT(0 == rv);
12943
12944 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
12945 nghttp2_buf_len(&bufs.head->buf));
12946
12947 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
12948
12949 item = nghttp2_session_get_next_ob_item(session);
12950
12951 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
12952
12953 CU_ASSERT(0 == nghttp2_session_send(session));
12954
12955 nghttp2_bufs_reset(&bufs);
12956
12957 nghttp2_hd_deflate_free(&deflater);
12958
12959 nghttp2_session_del(session);
12960
12961 nghttp2_bufs_free(&bufs);
12962 }
12963
test_nghttp2_http_ignore_regular_header(void)12964 void test_nghttp2_http_ignore_regular_header(void) {
12965 nghttp2_session *session;
12966 nghttp2_session_callbacks callbacks;
12967 nghttp2_hd_deflater deflater;
12968 nghttp2_mem *mem;
12969 nghttp2_bufs bufs;
12970 ssize_t rv;
12971 my_user_data ud;
12972 const nghttp2_nv bad_reqnv[] = {
12973 MAKE_NV(":authority", "localhost"),
12974 MAKE_NV(":scheme", "https"),
12975 MAKE_NV(":path", "/"),
12976 MAKE_NV(":method", "GET"),
12977 MAKE_NV("foo", "\x0zzz"),
12978 MAKE_NV("bar", "buzz"),
12979 };
12980 const nghttp2_nv bad_ansnv[] = {
12981 MAKE_NV(":authority", "localhost"), MAKE_NV(":scheme", "https"),
12982 MAKE_NV(":path", "/"), MAKE_NV(":method", "GET"), MAKE_NV("bar", "buzz")};
12983 size_t proclen;
12984 size_t i;
12985 nghttp2_outbound_item *item;
12986
12987 mem = nghttp2_mem_default();
12988 frame_pack_bufs_init(&bufs);
12989
12990 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
12991 callbacks.send_callback = null_send_callback;
12992 callbacks.on_header_callback = pause_on_header_callback;
12993
12994 nghttp2_session_server_new(&session, &callbacks, &ud);
12995 nghttp2_hd_deflate_init(&deflater, mem);
12996
12997 rv = pack_headers(&bufs, &deflater, 1,
12998 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM,
12999 bad_reqnv, ARRLEN(bad_reqnv), mem);
13000
13001 CU_ASSERT_FATAL(0 == rv);
13002
13003 nghttp2_hd_deflate_free(&deflater);
13004
13005 proclen = 0;
13006
13007 for (i = 0; i < 4; ++i) {
13008 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos + proclen,
13009 nghttp2_buf_len(&bufs.head->buf) - proclen);
13010 CU_ASSERT_FATAL(rv > 0);
13011 proclen += (size_t)rv;
13012 CU_ASSERT(nghttp2_nv_equal(&bad_ansnv[i], &ud.nv));
13013 }
13014
13015 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos + proclen,
13016 nghttp2_buf_len(&bufs.head->buf) - proclen);
13017 CU_ASSERT_FATAL(rv > 0);
13018 /* Without on_invalid_frame_recv_callback, bad header causes stream
13019 reset */
13020 item = nghttp2_session_get_next_ob_item(session);
13021
13022 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
13023
13024 proclen += (size_t)rv;
13025
13026 CU_ASSERT(nghttp2_buf_len(&bufs.head->buf) == proclen);
13027
13028 nghttp2_session_del(session);
13029
13030 /* use on_invalid_header_callback */
13031 callbacks.on_invalid_header_callback = pause_on_invalid_header_callback;
13032
13033 nghttp2_session_server_new(&session, &callbacks, &ud);
13034
13035 proclen = 0;
13036
13037 ud.invalid_header_cb_called = 0;
13038
13039 for (i = 0; i < 4; ++i) {
13040 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos + proclen,
13041 nghttp2_buf_len(&bufs.head->buf) - proclen);
13042 CU_ASSERT_FATAL(rv > 0);
13043 proclen += (size_t)rv;
13044 CU_ASSERT(nghttp2_nv_equal(&bad_ansnv[i], &ud.nv));
13045 }
13046
13047 CU_ASSERT(0 == ud.invalid_header_cb_called);
13048
13049 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos + proclen,
13050 nghttp2_buf_len(&bufs.head->buf) - proclen);
13051
13052 CU_ASSERT_FATAL(rv > 0);
13053 CU_ASSERT(1 == ud.invalid_header_cb_called);
13054 CU_ASSERT(nghttp2_nv_equal(&bad_reqnv[4], &ud.nv));
13055
13056 proclen += (size_t)rv;
13057
13058 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos + proclen,
13059 nghttp2_buf_len(&bufs.head->buf) - proclen);
13060
13061 CU_ASSERT(rv > 0);
13062 CU_ASSERT(nghttp2_nv_equal(&bad_ansnv[4], &ud.nv));
13063
13064 nghttp2_session_del(session);
13065
13066 /* make sure that we can reset stream from
13067 on_invalid_header_callback */
13068 callbacks.on_header_callback = on_header_callback;
13069 callbacks.on_invalid_header_callback = reset_on_invalid_header_callback;
13070
13071 nghttp2_session_server_new(&session, &callbacks, &ud);
13072
13073 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
13074 nghttp2_buf_len(&bufs.head->buf));
13075
13076 CU_ASSERT(rv == (ssize_t)nghttp2_buf_len(&bufs.head->buf));
13077
13078 item = nghttp2_session_get_next_ob_item(session);
13079
13080 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
13081 CU_ASSERT(1 == item->frame.hd.stream_id);
13082
13083 nghttp2_session_del(session);
13084 nghttp2_bufs_free(&bufs);
13085 }
13086
test_nghttp2_http_ignore_content_length(void)13087 void test_nghttp2_http_ignore_content_length(void) {
13088 nghttp2_session *session;
13089 nghttp2_session_callbacks callbacks;
13090 nghttp2_hd_deflater deflater;
13091 nghttp2_mem *mem;
13092 nghttp2_bufs bufs;
13093 ssize_t rv;
13094 const nghttp2_nv cl_resnv[] = {MAKE_NV(":status", "304"),
13095 MAKE_NV("content-length", "20")};
13096 const nghttp2_nv conn_reqnv[] = {MAKE_NV(":authority", "localhost"),
13097 MAKE_NV(":method", "CONNECT"),
13098 MAKE_NV("content-length", "999999")};
13099 const nghttp2_nv conn_cl_resnv[] = {MAKE_NV(":status", "200"),
13100 MAKE_NV("content-length", "0")};
13101 nghttp2_stream *stream;
13102
13103 mem = nghttp2_mem_default();
13104 frame_pack_bufs_init(&bufs);
13105
13106 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
13107 callbacks.send_callback = null_send_callback;
13108
13109 nghttp2_session_client_new(&session, &callbacks, NULL);
13110
13111 nghttp2_hd_deflate_init(&deflater, mem);
13112
13113 /* If status 304, content-length must be ignored */
13114 open_sent_stream2(session, 1, NGHTTP2_STREAM_OPENING);
13115
13116 rv = pack_headers(&bufs, &deflater, 1,
13117 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM,
13118 cl_resnv, ARRLEN(cl_resnv), mem);
13119 CU_ASSERT(0 == rv);
13120
13121 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
13122 nghttp2_buf_len(&bufs.head->buf));
13123
13124 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
13125
13126 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
13127
13128 nghttp2_bufs_reset(&bufs);
13129
13130 /* Content-Length in 200 response to CONNECT is ignored */
13131 stream = open_sent_stream2(session, 3, NGHTTP2_STREAM_OPENING);
13132 stream->http_flags |= NGHTTP2_HTTP_FLAG_METH_CONNECT;
13133
13134 rv = pack_headers(&bufs, &deflater, 3, NGHTTP2_FLAG_END_HEADERS,
13135 conn_cl_resnv, ARRLEN(conn_cl_resnv), mem);
13136 CU_ASSERT(0 == rv);
13137
13138 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
13139 nghttp2_buf_len(&bufs.head->buf));
13140
13141 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
13142
13143 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
13144 CU_ASSERT(-1 == stream->content_length);
13145
13146 nghttp2_bufs_reset(&bufs);
13147
13148 nghttp2_hd_deflate_free(&deflater);
13149 nghttp2_session_del(session);
13150
13151 /* If request method is CONNECT, content-length must be ignored */
13152 nghttp2_session_server_new(&session, &callbacks, NULL);
13153
13154 nghttp2_hd_deflate_init(&deflater, mem);
13155
13156 rv = pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, conn_reqnv,
13157 ARRLEN(conn_reqnv), mem);
13158
13159 CU_ASSERT(0 == rv);
13160
13161 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
13162 nghttp2_buf_len(&bufs.head->buf));
13163
13164 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
13165
13166 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
13167
13168 stream = nghttp2_session_get_stream(session, 1);
13169
13170 CU_ASSERT(-1 == stream->content_length);
13171 CU_ASSERT((stream->http_flags & NGHTTP2_HTTP_FLAG_METH_CONNECT) > 0);
13172
13173 nghttp2_hd_deflate_free(&deflater);
13174 nghttp2_session_del(session);
13175 nghttp2_bufs_free(&bufs);
13176 }
13177
test_nghttp2_http_record_request_method(void)13178 void test_nghttp2_http_record_request_method(void) {
13179 nghttp2_session *session;
13180 nghttp2_session_callbacks callbacks;
13181 const nghttp2_nv conn_reqnv[] = {MAKE_NV(":method", "CONNECT"),
13182 MAKE_NV(":authority", "localhost")};
13183 const nghttp2_nv conn_resnv[] = {MAKE_NV(":status", "200"),
13184 MAKE_NV("content-length", "9999")};
13185 nghttp2_stream *stream;
13186 ssize_t rv;
13187 nghttp2_bufs bufs;
13188 nghttp2_hd_deflater deflater;
13189 nghttp2_mem *mem;
13190 nghttp2_outbound_item *item;
13191
13192 mem = nghttp2_mem_default();
13193 frame_pack_bufs_init(&bufs);
13194
13195 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
13196 callbacks.send_callback = null_send_callback;
13197
13198 nghttp2_session_client_new(&session, &callbacks, NULL);
13199
13200 nghttp2_hd_deflate_init(&deflater, mem);
13201
13202 CU_ASSERT(1 == nghttp2_submit_request(session, NULL, conn_reqnv,
13203 ARRLEN(conn_reqnv), NULL, NULL));
13204
13205 CU_ASSERT(0 == nghttp2_session_send(session));
13206
13207 stream = nghttp2_session_get_stream(session, 1);
13208
13209 CU_ASSERT(NGHTTP2_HTTP_FLAG_METH_CONNECT == stream->http_flags);
13210
13211 rv = pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, conn_resnv,
13212 ARRLEN(conn_resnv), mem);
13213 CU_ASSERT(0 == rv);
13214
13215 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
13216 nghttp2_buf_len(&bufs.head->buf));
13217
13218 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
13219
13220 CU_ASSERT((NGHTTP2_HTTP_FLAG_METH_CONNECT & stream->http_flags) > 0);
13221 CU_ASSERT(-1 == stream->content_length);
13222
13223 /* content-length is ignored in 200 response to a CONNECT request */
13224 item = nghttp2_session_get_next_ob_item(session);
13225
13226 CU_ASSERT(NULL == item);
13227
13228 nghttp2_hd_deflate_free(&deflater);
13229 nghttp2_session_del(session);
13230 nghttp2_bufs_free(&bufs);
13231 }
13232
test_nghttp2_http_push_promise(void)13233 void test_nghttp2_http_push_promise(void) {
13234 nghttp2_session *session;
13235 nghttp2_session_callbacks callbacks;
13236 nghttp2_hd_deflater deflater;
13237 nghttp2_mem *mem;
13238 nghttp2_bufs bufs;
13239 ssize_t rv;
13240 nghttp2_stream *stream;
13241 const nghttp2_nv bad_reqnv[] = {MAKE_NV(":method", "GET")};
13242 nghttp2_outbound_item *item;
13243
13244 mem = nghttp2_mem_default();
13245 frame_pack_bufs_init(&bufs);
13246
13247 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
13248 callbacks.send_callback = null_send_callback;
13249
13250 /* good PUSH_PROMISE case */
13251 nghttp2_session_client_new(&session, &callbacks, NULL);
13252
13253 nghttp2_hd_deflate_init(&deflater, mem);
13254
13255 open_sent_stream2(session, 1, NGHTTP2_STREAM_OPENING);
13256
13257 rv = pack_push_promise(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, 2,
13258 reqnv, ARRLEN(reqnv), mem);
13259 CU_ASSERT(0 == rv);
13260
13261 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
13262 nghttp2_buf_len(&bufs.head->buf));
13263
13264 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
13265
13266 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
13267
13268 stream = nghttp2_session_get_stream(session, 2);
13269 CU_ASSERT(NULL != stream);
13270
13271 nghttp2_bufs_reset(&bufs);
13272
13273 rv = pack_headers(&bufs, &deflater, 2, NGHTTP2_FLAG_END_HEADERS, resnv,
13274 ARRLEN(resnv), mem);
13275
13276 CU_ASSERT(0 == rv);
13277
13278 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
13279 nghttp2_buf_len(&bufs.head->buf));
13280
13281 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
13282
13283 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
13284
13285 CU_ASSERT(200 == stream->status_code);
13286
13287 nghttp2_bufs_reset(&bufs);
13288
13289 /* PUSH_PROMISE lacks mandatory header */
13290 rv = pack_push_promise(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, 4,
13291 bad_reqnv, ARRLEN(bad_reqnv), mem);
13292
13293 CU_ASSERT(0 == rv);
13294
13295 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
13296 nghttp2_buf_len(&bufs.head->buf));
13297
13298 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
13299
13300 item = nghttp2_session_get_next_ob_item(session);
13301
13302 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
13303 CU_ASSERT(4 == item->frame.hd.stream_id);
13304
13305 nghttp2_bufs_reset(&bufs);
13306
13307 nghttp2_hd_deflate_free(&deflater);
13308 nghttp2_session_del(session);
13309 nghttp2_bufs_free(&bufs);
13310 }
13311
test_nghttp2_http_head_method_upgrade_workaround(void)13312 void test_nghttp2_http_head_method_upgrade_workaround(void) {
13313 nghttp2_session *session;
13314 nghttp2_session_callbacks callbacks;
13315 const nghttp2_nv cl_resnv[] = {MAKE_NV(":status", "200"),
13316 MAKE_NV("content-length", "1000000007")};
13317 nghttp2_bufs bufs;
13318 nghttp2_hd_deflater deflater;
13319 nghttp2_mem *mem;
13320 ssize_t rv;
13321 nghttp2_stream *stream;
13322
13323 mem = nghttp2_mem_default();
13324 frame_pack_bufs_init(&bufs);
13325
13326 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
13327 callbacks.send_callback = null_send_callback;
13328
13329 nghttp2_session_client_new(&session, &callbacks, NULL);
13330
13331 nghttp2_hd_deflate_init(&deflater, mem);
13332
13333 nghttp2_session_upgrade(session, NULL, 0, NULL);
13334
13335 rv = pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, cl_resnv,
13336 ARRLEN(cl_resnv), mem);
13337
13338 CU_ASSERT(0 == rv);
13339
13340 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
13341 nghttp2_buf_len(&bufs.head->buf));
13342
13343 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
13344
13345 stream = nghttp2_session_get_stream(session, 1);
13346
13347 CU_ASSERT(-1 == stream->content_length);
13348
13349 nghttp2_hd_deflate_free(&deflater);
13350 nghttp2_session_del(session);
13351 nghttp2_bufs_free(&bufs);
13352 }
13353
test_nghttp2_http_no_rfc9113_leading_and_trailing_ws_validation(void)13354 void test_nghttp2_http_no_rfc9113_leading_and_trailing_ws_validation(void) {
13355 nghttp2_session *session;
13356 nghttp2_session_callbacks callbacks;
13357 nghttp2_hd_deflater deflater;
13358 nghttp2_mem *mem;
13359 nghttp2_bufs bufs;
13360 ssize_t rv;
13361 const nghttp2_nv ws_reqnv[] = {
13362 MAKE_NV(":path", "/"),
13363 MAKE_NV(":method", "GET"),
13364 MAKE_NV(":authority", "localhost"),
13365 MAKE_NV(":scheme", "https"),
13366 MAKE_NV("foo", "bar "),
13367 };
13368 nghttp2_outbound_item *item;
13369 nghttp2_option *option;
13370
13371 mem = nghttp2_mem_default();
13372 frame_pack_bufs_init(&bufs);
13373
13374 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
13375 callbacks.send_callback = null_send_callback;
13376
13377 /* By default, the leading and trailing white spaces validation is
13378 enabled as per RFC 9113. */
13379 nghttp2_session_server_new(&session, &callbacks, NULL);
13380
13381 nghttp2_hd_deflate_init(&deflater, mem);
13382
13383 rv = pack_headers(&bufs, &deflater, 1,
13384 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM,
13385 ws_reqnv, ARRLEN(ws_reqnv), mem);
13386
13387 CU_ASSERT(0 == rv);
13388
13389 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
13390 nghttp2_buf_len(&bufs.head->buf));
13391
13392 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
13393
13394 item = nghttp2_session_get_next_ob_item(session);
13395
13396 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
13397 CU_ASSERT(0 == nghttp2_session_send(session));
13398
13399 nghttp2_bufs_reset(&bufs);
13400 nghttp2_hd_deflate_free(&deflater);
13401 nghttp2_session_del(session);
13402
13403 /* Turn off the validation */
13404 nghttp2_option_new(&option);
13405 nghttp2_option_set_no_rfc9113_leading_and_trailing_ws_validation(option, 1);
13406
13407 nghttp2_session_server_new2(&session, &callbacks, NULL, option);
13408
13409 nghttp2_hd_deflate_init(&deflater, mem);
13410
13411 rv = pack_headers(&bufs, &deflater, 1,
13412 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM,
13413 ws_reqnv, ARRLEN(ws_reqnv), mem);
13414
13415 CU_ASSERT(0 == rv);
13416
13417 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
13418 nghttp2_buf_len(&bufs.head->buf));
13419
13420 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
13421
13422 item = nghttp2_session_get_next_ob_item(session);
13423
13424 CU_ASSERT(NULL == item);
13425
13426 nghttp2_bufs_reset(&bufs);
13427 nghttp2_hd_deflate_free(&deflater);
13428 nghttp2_session_del(session);
13429 nghttp2_option_del(option);
13430
13431 nghttp2_bufs_free(&bufs);
13432 }
13433