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