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