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_submit_rst_stream(void)6401 void test_nghttp2_submit_rst_stream(void) {
6402 nghttp2_session *session;
6403 nghttp2_session_callbacks callbacks;
6404 nghttp2_outbound_item *item;
6405 int rv;
6406 int32_t stream_id;
6407
6408 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6409
6410 /* Sending RST_STREAM to idle stream (local) is ignored */
6411 nghttp2_session_client_new(&session, &callbacks, NULL);
6412
6413 rv = nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, 1,
6414 NGHTTP2_NO_ERROR);
6415
6416 CU_ASSERT(0 == rv);
6417
6418 item = nghttp2_outbound_queue_top(&session->ob_reg);
6419
6420 CU_ASSERT(NULL == item);
6421
6422 nghttp2_session_del(session);
6423
6424 /* Sending RST_STREAM to idle stream (remote) is ignored */
6425 nghttp2_session_client_new(&session, &callbacks, NULL);
6426
6427 rv = nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, 2,
6428 NGHTTP2_NO_ERROR);
6429
6430 CU_ASSERT(0 == rv);
6431
6432 item = nghttp2_outbound_queue_top(&session->ob_reg);
6433
6434 CU_ASSERT(NULL == item);
6435
6436 nghttp2_session_del(session);
6437
6438 /* Sending RST_STREAM to non-idle stream (local) */
6439 nghttp2_session_client_new(&session, &callbacks, NULL);
6440
6441 open_sent_stream(session, 1);
6442
6443 rv = nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, 1,
6444 NGHTTP2_NO_ERROR);
6445
6446 CU_ASSERT(0 == rv);
6447
6448 item = nghttp2_outbound_queue_top(&session->ob_reg);
6449
6450 CU_ASSERT(NULL != item);
6451 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
6452 CU_ASSERT(1 == item->frame.hd.stream_id);
6453
6454 nghttp2_session_del(session);
6455
6456 /* Sending RST_STREAM to non-idle stream (remote) */
6457 nghttp2_session_client_new(&session, &callbacks, NULL);
6458
6459 open_recv_stream(session, 2);
6460
6461 rv = nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, 2,
6462 NGHTTP2_NO_ERROR);
6463
6464 CU_ASSERT(0 == rv);
6465
6466 item = nghttp2_outbound_queue_top(&session->ob_reg);
6467
6468 CU_ASSERT(NULL != item);
6469 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
6470 CU_ASSERT(2 == item->frame.hd.stream_id);
6471
6472 nghttp2_session_del(session);
6473
6474 /* Sending RST_STREAM to pending stream */
6475 nghttp2_session_client_new(&session, &callbacks, NULL);
6476
6477 stream_id =
6478 nghttp2_submit_request(session, NULL, reqnv, ARRLEN(reqnv), NULL, NULL);
6479
6480 CU_ASSERT(stream_id > 0);
6481
6482 item = nghttp2_outbound_queue_top(&session->ob_syn);
6483
6484 CU_ASSERT(NULL != item);
6485 CU_ASSERT(NGHTTP2_HEADERS == item->frame.hd.type);
6486 CU_ASSERT(0 == item->aux_data.headers.canceled);
6487
6488 rv = nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, stream_id,
6489 NGHTTP2_NO_ERROR);
6490
6491 CU_ASSERT(0 == rv);
6492
6493 item = nghttp2_outbound_queue_top(&session->ob_syn);
6494
6495 CU_ASSERT(NULL != item);
6496 CU_ASSERT(NGHTTP2_HEADERS == item->frame.hd.type);
6497 CU_ASSERT(1 == item->aux_data.headers.canceled);
6498
6499 nghttp2_session_del(session);
6500 }
6501
test_nghttp2_session_open_stream(void)6502 void test_nghttp2_session_open_stream(void) {
6503 nghttp2_session *session;
6504 nghttp2_session_callbacks callbacks;
6505 nghttp2_stream *stream;
6506 nghttp2_priority_spec pri_spec;
6507
6508 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6509 nghttp2_session_server_new(&session, &callbacks, NULL);
6510
6511 nghttp2_priority_spec_init(&pri_spec, 0, 245, 0);
6512
6513 stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
6514 &pri_spec, NGHTTP2_STREAM_OPENED, NULL);
6515 CU_ASSERT(1 == session->num_incoming_streams);
6516 CU_ASSERT(0 == session->num_outgoing_streams);
6517 CU_ASSERT(NGHTTP2_STREAM_OPENED == stream->state);
6518 CU_ASSERT(245 == stream->weight);
6519 CU_ASSERT(&session->root == stream->dep_prev);
6520 CU_ASSERT(NGHTTP2_SHUT_NONE == stream->shut_flags);
6521
6522 stream = nghttp2_session_open_stream(session, 2, NGHTTP2_STREAM_FLAG_NONE,
6523 &pri_spec_default,
6524 NGHTTP2_STREAM_OPENING, NULL);
6525 CU_ASSERT(1 == session->num_incoming_streams);
6526 CU_ASSERT(1 == session->num_outgoing_streams);
6527 CU_ASSERT(&session->root == stream->dep_prev);
6528 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == stream->weight);
6529 CU_ASSERT(NGHTTP2_SHUT_NONE == stream->shut_flags);
6530
6531 stream = nghttp2_session_open_stream(session, 4, NGHTTP2_STREAM_FLAG_NONE,
6532 &pri_spec_default,
6533 NGHTTP2_STREAM_RESERVED, NULL);
6534 CU_ASSERT(1 == session->num_incoming_streams);
6535 CU_ASSERT(1 == session->num_outgoing_streams);
6536 CU_ASSERT(&session->root == stream->dep_prev);
6537 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == stream->weight);
6538 CU_ASSERT(NGHTTP2_SHUT_RD == stream->shut_flags);
6539
6540 nghttp2_priority_spec_init(&pri_spec, 1, 17, 1);
6541
6542 stream = nghttp2_session_open_stream(session, 3, NGHTTP2_STREAM_FLAG_NONE,
6543 &pri_spec, NGHTTP2_STREAM_OPENED, NULL);
6544 CU_ASSERT(17 == stream->weight);
6545 CU_ASSERT(1 == stream->dep_prev->stream_id);
6546
6547 /* Dependency to idle stream */
6548 nghttp2_priority_spec_init(&pri_spec, 1000000007, 240, 1);
6549
6550 stream = nghttp2_session_open_stream(session, 5, NGHTTP2_STREAM_FLAG_NONE,
6551 &pri_spec, NGHTTP2_STREAM_OPENED, NULL);
6552 CU_ASSERT(240 == stream->weight);
6553 CU_ASSERT(1000000007 == stream->dep_prev->stream_id);
6554
6555 stream = nghttp2_session_get_stream_raw(session, 1000000007);
6556
6557 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == stream->weight);
6558 CU_ASSERT(&session->root == stream->dep_prev);
6559
6560 /* Dependency to closed stream which is not in dependency tree */
6561 session->last_recv_stream_id = 7;
6562
6563 nghttp2_priority_spec_init(&pri_spec, 7, 10, 0);
6564
6565 stream = nghttp2_session_open_stream(session, 9, NGHTTP2_FLAG_NONE, &pri_spec,
6566 NGHTTP2_STREAM_OPENED, NULL);
6567
6568 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == stream->weight);
6569 CU_ASSERT(&session->root == stream->dep_prev);
6570
6571 nghttp2_session_del(session);
6572
6573 nghttp2_session_client_new(&session, &callbacks, NULL);
6574 stream = nghttp2_session_open_stream(session, 4, NGHTTP2_STREAM_FLAG_NONE,
6575 &pri_spec_default,
6576 NGHTTP2_STREAM_RESERVED, NULL);
6577 CU_ASSERT(0 == session->num_incoming_streams);
6578 CU_ASSERT(0 == session->num_outgoing_streams);
6579 CU_ASSERT(&session->root == stream->dep_prev);
6580 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == stream->weight);
6581 CU_ASSERT(NGHTTP2_SHUT_WR == stream->shut_flags);
6582
6583 nghttp2_session_del(session);
6584 }
6585
test_nghttp2_session_open_stream_with_idle_stream_dep(void)6586 void test_nghttp2_session_open_stream_with_idle_stream_dep(void) {
6587 nghttp2_session *session;
6588 nghttp2_session_callbacks callbacks;
6589 nghttp2_stream *stream;
6590 nghttp2_priority_spec pri_spec;
6591
6592 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6593 nghttp2_session_server_new(&session, &callbacks, NULL);
6594
6595 /* Dependency to idle stream */
6596 nghttp2_priority_spec_init(&pri_spec, 101, 245, 0);
6597
6598 stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
6599 &pri_spec, NGHTTP2_STREAM_OPENED, NULL);
6600
6601 CU_ASSERT(245 == stream->weight);
6602 CU_ASSERT(101 == stream->dep_prev->stream_id);
6603
6604 stream = nghttp2_session_get_stream_raw(session, 101);
6605
6606 CU_ASSERT(NGHTTP2_STREAM_IDLE == stream->state);
6607 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == stream->weight);
6608
6609 nghttp2_priority_spec_init(&pri_spec, 211, 1, 0);
6610
6611 /* stream 101 was already created as idle. */
6612 stream = nghttp2_session_open_stream(session, 101, NGHTTP2_STREAM_FLAG_NONE,
6613 &pri_spec, NGHTTP2_STREAM_OPENED, NULL);
6614
6615 CU_ASSERT(1 == stream->weight);
6616 CU_ASSERT(211 == stream->dep_prev->stream_id);
6617
6618 stream = nghttp2_session_get_stream_raw(session, 211);
6619
6620 CU_ASSERT(NGHTTP2_STREAM_IDLE == stream->state);
6621 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == stream->weight);
6622
6623 nghttp2_session_del(session);
6624 }
6625
test_nghttp2_session_get_next_ob_item(void)6626 void test_nghttp2_session_get_next_ob_item(void) {
6627 nghttp2_session *session;
6628 nghttp2_session_callbacks callbacks;
6629 nghttp2_priority_spec pri_spec;
6630
6631 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6632 callbacks.send_callback = null_send_callback;
6633
6634 nghttp2_session_client_new(&session, &callbacks, NULL);
6635 session->remote_settings.max_concurrent_streams = 2;
6636
6637 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
6638 nghttp2_submit_ping(session, NGHTTP2_FLAG_NONE, NULL);
6639 CU_ASSERT(NGHTTP2_PING ==
6640 nghttp2_session_get_next_ob_item(session)->frame.hd.type);
6641
6642 CU_ASSERT(1 == nghttp2_submit_request(session, NULL, NULL, 0, NULL, NULL));
6643 CU_ASSERT(NGHTTP2_PING ==
6644 nghttp2_session_get_next_ob_item(session)->frame.hd.type);
6645
6646 CU_ASSERT(0 == nghttp2_session_send(session));
6647 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
6648
6649 /* Incoming stream does not affect the number of outgoing max
6650 concurrent streams. */
6651 open_recv_stream(session, 2);
6652
6653 nghttp2_priority_spec_init(&pri_spec, 0, NGHTTP2_MAX_WEIGHT, 0);
6654
6655 CU_ASSERT(3 ==
6656 nghttp2_submit_request(session, &pri_spec, NULL, 0, NULL, NULL));
6657 CU_ASSERT(NGHTTP2_HEADERS ==
6658 nghttp2_session_get_next_ob_item(session)->frame.hd.type);
6659 CU_ASSERT(0 == nghttp2_session_send(session));
6660
6661 CU_ASSERT(5 ==
6662 nghttp2_submit_request(session, &pri_spec, NULL, 0, NULL, NULL));
6663 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
6664
6665 session->remote_settings.max_concurrent_streams = 3;
6666
6667 CU_ASSERT(NGHTTP2_HEADERS ==
6668 nghttp2_session_get_next_ob_item(session)->frame.hd.type);
6669
6670 nghttp2_session_del(session);
6671
6672 /* Check that push reply HEADERS are queued into ob_ss_pq */
6673 nghttp2_session_server_new(&session, &callbacks, NULL);
6674 session->remote_settings.max_concurrent_streams = 0;
6675 open_sent_stream2(session, 2, NGHTTP2_STREAM_RESERVED);
6676 CU_ASSERT(0 == nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, 2,
6677 NULL, NULL, 0, NULL));
6678 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
6679 CU_ASSERT(1 == nghttp2_outbound_queue_size(&session->ob_syn));
6680 nghttp2_session_del(session);
6681 }
6682
test_nghttp2_session_pop_next_ob_item(void)6683 void test_nghttp2_session_pop_next_ob_item(void) {
6684 nghttp2_session *session;
6685 nghttp2_session_callbacks callbacks;
6686 nghttp2_outbound_item *item;
6687 nghttp2_priority_spec pri_spec;
6688 nghttp2_mem *mem;
6689
6690 mem = nghttp2_mem_default();
6691 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6692 callbacks.send_callback = null_send_callback;
6693
6694 nghttp2_session_client_new(&session, &callbacks, NULL);
6695 session->remote_settings.max_concurrent_streams = 1;
6696
6697 CU_ASSERT(NULL == nghttp2_session_pop_next_ob_item(session));
6698
6699 nghttp2_submit_ping(session, NGHTTP2_FLAG_NONE, NULL);
6700
6701 nghttp2_priority_spec_init(&pri_spec, 0, 254, 0);
6702
6703 nghttp2_submit_request(session, &pri_spec, NULL, 0, NULL, NULL);
6704
6705 item = nghttp2_session_pop_next_ob_item(session);
6706 CU_ASSERT(NGHTTP2_PING == item->frame.hd.type);
6707 nghttp2_outbound_item_free(item, mem);
6708 mem->free(item, NULL);
6709
6710 item = nghttp2_session_pop_next_ob_item(session);
6711 CU_ASSERT(NGHTTP2_HEADERS == item->frame.hd.type);
6712 nghttp2_outbound_item_free(item, mem);
6713 mem->free(item, NULL);
6714
6715 CU_ASSERT(NULL == nghttp2_session_pop_next_ob_item(session));
6716
6717 /* Incoming stream does not affect the number of outgoing max
6718 concurrent streams. */
6719 open_recv_stream(session, 4);
6720 /* In-flight outgoing stream */
6721 open_sent_stream(session, 1);
6722
6723 nghttp2_priority_spec_init(&pri_spec, 0, NGHTTP2_MAX_WEIGHT, 0);
6724
6725 nghttp2_submit_request(session, &pri_spec, NULL, 0, NULL, NULL);
6726
6727 CU_ASSERT(NULL == nghttp2_session_pop_next_ob_item(session));
6728
6729 session->remote_settings.max_concurrent_streams = 2;
6730
6731 item = nghttp2_session_pop_next_ob_item(session);
6732 CU_ASSERT(NGHTTP2_HEADERS == item->frame.hd.type);
6733 nghttp2_outbound_item_free(item, mem);
6734 mem->free(item, NULL);
6735
6736 nghttp2_session_del(session);
6737
6738 /* Check that push reply HEADERS are queued into ob_ss_pq */
6739 nghttp2_session_server_new(&session, &callbacks, NULL);
6740 session->remote_settings.max_concurrent_streams = 0;
6741 open_sent_stream2(session, 2, NGHTTP2_STREAM_RESERVED);
6742 CU_ASSERT(0 == nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, 2,
6743 NULL, NULL, 0, NULL));
6744 CU_ASSERT(NULL == nghttp2_session_pop_next_ob_item(session));
6745 CU_ASSERT(1 == nghttp2_outbound_queue_size(&session->ob_syn));
6746 nghttp2_session_del(session);
6747 }
6748
test_nghttp2_session_reply_fail(void)6749 void test_nghttp2_session_reply_fail(void) {
6750 nghttp2_session *session;
6751 nghttp2_session_callbacks callbacks;
6752 nghttp2_data_provider data_prd;
6753 my_user_data ud;
6754
6755 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6756 callbacks.send_callback = fail_send_callback;
6757
6758 data_prd.read_callback = fixed_length_data_source_read_callback;
6759 ud.data_source_length = 4 * 1024;
6760 CU_ASSERT(0 == nghttp2_session_server_new(&session, &callbacks, &ud));
6761 open_recv_stream2(session, 1, NGHTTP2_STREAM_OPENING);
6762 CU_ASSERT(0 == nghttp2_submit_response(session, 1, NULL, 0, &data_prd));
6763 CU_ASSERT(NGHTTP2_ERR_CALLBACK_FAILURE == nghttp2_session_send(session));
6764 nghttp2_session_del(session);
6765 }
6766
test_nghttp2_session_max_concurrent_streams(void)6767 void test_nghttp2_session_max_concurrent_streams(void) {
6768 nghttp2_session *session;
6769 nghttp2_session_callbacks callbacks;
6770 nghttp2_frame frame;
6771 nghttp2_outbound_item *item;
6772 nghttp2_mem *mem;
6773
6774 mem = nghttp2_mem_default();
6775 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6776 callbacks.send_callback = null_send_callback;
6777
6778 nghttp2_session_server_new(&session, &callbacks, NULL);
6779 open_recv_stream(session, 1);
6780
6781 /* Check un-ACKed SETTINGS_MAX_CONCURRENT_STREAMS */
6782 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 3,
6783 NGHTTP2_HCAT_HEADERS, NULL, NULL, 0);
6784 session->pending_local_max_concurrent_stream = 1;
6785
6786 CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
6787 nghttp2_session_on_request_headers_received(session, &frame));
6788
6789 item = nghttp2_outbound_queue_top(&session->ob_reg);
6790 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
6791 CU_ASSERT(NGHTTP2_REFUSED_STREAM == item->frame.rst_stream.error_code);
6792
6793 CU_ASSERT(0 == nghttp2_session_send(session));
6794
6795 /* Check ACKed SETTINGS_MAX_CONCURRENT_STREAMS */
6796 session->local_settings.max_concurrent_streams = 1;
6797 frame.hd.stream_id = 5;
6798
6799 CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
6800 nghttp2_session_on_request_headers_received(session, &frame));
6801
6802 item = nghttp2_outbound_queue_top(&session->ob_reg);
6803 CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
6804 CU_ASSERT(NGHTTP2_PROTOCOL_ERROR == item->frame.goaway.error_code);
6805
6806 nghttp2_frame_headers_free(&frame.headers, mem);
6807 nghttp2_session_del(session);
6808 }
6809
test_nghttp2_session_stop_data_with_rst_stream(void)6810 void test_nghttp2_session_stop_data_with_rst_stream(void) {
6811 nghttp2_session *session;
6812 nghttp2_session_callbacks callbacks;
6813 my_user_data ud;
6814 nghttp2_data_provider data_prd;
6815 nghttp2_frame frame;
6816
6817 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6818 callbacks.on_frame_send_callback = on_frame_send_callback;
6819 callbacks.send_callback = block_count_send_callback;
6820 data_prd.read_callback = fixed_length_data_source_read_callback;
6821
6822 ud.frame_send_cb_called = 0;
6823 ud.data_source_length = NGHTTP2_DATA_PAYLOADLEN * 4;
6824
6825 nghttp2_session_server_new(&session, &callbacks, &ud);
6826 open_recv_stream2(session, 1, NGHTTP2_STREAM_OPENING);
6827 nghttp2_submit_response(session, 1, NULL, 0, &data_prd);
6828
6829 ud.block_count = 2;
6830 /* Sends response HEADERS + DATA[0] */
6831 CU_ASSERT(0 == nghttp2_session_send(session));
6832 CU_ASSERT(NGHTTP2_DATA == ud.sent_frame_type);
6833 /* data for DATA[1] is read from data_prd but it is not sent */
6834 CU_ASSERT(ud.data_source_length == NGHTTP2_DATA_PAYLOADLEN * 2);
6835
6836 nghttp2_frame_rst_stream_init(&frame.rst_stream, 1, NGHTTP2_CANCEL);
6837 CU_ASSERT(0 == nghttp2_session_on_rst_stream_received(session, &frame));
6838 nghttp2_frame_rst_stream_free(&frame.rst_stream);
6839
6840 /* Big enough number to send all DATA frames potentially. */
6841 ud.block_count = 100;
6842 /* Nothing will be sent in the following call. */
6843 CU_ASSERT(0 == nghttp2_session_send(session));
6844 /* With RST_STREAM, stream is canceled and further DATA on that
6845 stream are not sent. */
6846 CU_ASSERT(ud.data_source_length == NGHTTP2_DATA_PAYLOADLEN * 2);
6847
6848 CU_ASSERT(NULL == nghttp2_session_get_stream(session, 1));
6849
6850 nghttp2_session_del(session);
6851 }
6852
test_nghttp2_session_defer_data(void)6853 void test_nghttp2_session_defer_data(void) {
6854 nghttp2_session *session;
6855 nghttp2_session_callbacks callbacks;
6856 my_user_data ud;
6857 nghttp2_data_provider data_prd;
6858 nghttp2_outbound_item *item;
6859 nghttp2_stream *stream;
6860
6861 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6862 callbacks.on_frame_send_callback = on_frame_send_callback;
6863 callbacks.send_callback = block_count_send_callback;
6864 data_prd.read_callback = defer_data_source_read_callback;
6865
6866 ud.frame_send_cb_called = 0;
6867 ud.data_source_length = NGHTTP2_DATA_PAYLOADLEN * 4;
6868
6869 nghttp2_session_server_new(&session, &callbacks, &ud);
6870 stream = open_recv_stream2(session, 1, NGHTTP2_STREAM_OPENING);
6871
6872 session->remote_window_size = 1 << 20;
6873 stream->remote_window_size = 1 << 20;
6874
6875 nghttp2_submit_response(session, 1, NULL, 0, &data_prd);
6876
6877 ud.block_count = 1;
6878 /* Sends HEADERS reply */
6879 CU_ASSERT(0 == nghttp2_session_send(session));
6880 CU_ASSERT(NGHTTP2_HEADERS == ud.sent_frame_type);
6881 /* No data is read */
6882 CU_ASSERT(ud.data_source_length == NGHTTP2_DATA_PAYLOADLEN * 4);
6883
6884 ud.block_count = 1;
6885 nghttp2_submit_ping(session, NGHTTP2_FLAG_NONE, NULL);
6886 /* Sends PING */
6887 CU_ASSERT(0 == nghttp2_session_send(session));
6888 CU_ASSERT(NGHTTP2_PING == ud.sent_frame_type);
6889
6890 /* Resume deferred DATA */
6891 CU_ASSERT(0 == nghttp2_session_resume_data(session, 1));
6892 item = stream->item;
6893 item->aux_data.data.data_prd.read_callback =
6894 fixed_length_data_source_read_callback;
6895 ud.block_count = 1;
6896 /* Reads 2 DATA chunks */
6897 CU_ASSERT(0 == nghttp2_session_send(session));
6898 CU_ASSERT(ud.data_source_length == NGHTTP2_DATA_PAYLOADLEN * 2);
6899
6900 /* Deferred again */
6901 item->aux_data.data.data_prd.read_callback = defer_data_source_read_callback;
6902 /* This is needed since 16KiB block is already read and waiting to be
6903 sent. No read_callback invocation. */
6904 ud.block_count = 1;
6905 CU_ASSERT(0 == nghttp2_session_send(session));
6906 CU_ASSERT(ud.data_source_length == NGHTTP2_DATA_PAYLOADLEN * 2);
6907
6908 /* Resume deferred DATA */
6909 CU_ASSERT(0 == nghttp2_session_resume_data(session, 1));
6910 item->aux_data.data.data_prd.read_callback =
6911 fixed_length_data_source_read_callback;
6912 ud.block_count = 1;
6913 /* Reads 2 16KiB blocks */
6914 CU_ASSERT(0 == nghttp2_session_send(session));
6915 CU_ASSERT(ud.data_source_length == 0);
6916
6917 nghttp2_session_del(session);
6918 }
6919
test_nghttp2_session_flow_control(void)6920 void test_nghttp2_session_flow_control(void) {
6921 nghttp2_session *session;
6922 nghttp2_session_callbacks callbacks;
6923 my_user_data ud;
6924 nghttp2_data_provider data_prd;
6925 nghttp2_frame frame;
6926 nghttp2_stream *stream;
6927 int32_t new_initial_window_size;
6928 nghttp2_settings_entry iv[1];
6929 nghttp2_frame settings_frame;
6930 nghttp2_mem *mem;
6931
6932 mem = nghttp2_mem_default();
6933 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
6934 callbacks.send_callback = fixed_bytes_send_callback;
6935 callbacks.on_frame_send_callback = on_frame_send_callback;
6936 data_prd.read_callback = fixed_length_data_source_read_callback;
6937
6938 ud.frame_send_cb_called = 0;
6939 ud.data_source_length = 128 * 1024;
6940 /* Use smaller emission count so that we can check outbound flow
6941 control window calculation is correct. */
6942 ud.fixed_sendlen = 2 * 1024;
6943
6944 /* Initial window size to 64KiB - 1*/
6945 nghttp2_session_client_new(&session, &callbacks, &ud);
6946 /* Change it to 64KiB for easy calculation */
6947 session->remote_window_size = 64 * 1024;
6948 session->remote_settings.initial_window_size = 64 * 1024;
6949
6950 nghttp2_submit_request(session, NULL, NULL, 0, &data_prd, NULL);
6951
6952 /* Sends 64KiB - 1 data */
6953 CU_ASSERT(0 == nghttp2_session_send(session));
6954 CU_ASSERT(64 * 1024 == ud.data_source_length);
6955
6956 /* Back 32KiB in stream window */
6957 nghttp2_frame_window_update_init(&frame.window_update, NGHTTP2_FLAG_NONE, 1,
6958 32 * 1024);
6959 nghttp2_session_on_window_update_received(session, &frame);
6960
6961 /* Send nothing because of connection-level window */
6962 CU_ASSERT(0 == nghttp2_session_send(session));
6963 CU_ASSERT(64 * 1024 == ud.data_source_length);
6964
6965 /* Back 32KiB in connection-level window */
6966 frame.hd.stream_id = 0;
6967 nghttp2_session_on_window_update_received(session, &frame);
6968
6969 /* Sends another 32KiB data */
6970 CU_ASSERT(0 == nghttp2_session_send(session));
6971 CU_ASSERT(32 * 1024 == ud.data_source_length);
6972
6973 stream = nghttp2_session_get_stream(session, 1);
6974 /* Change initial window size to 16KiB. The window_size becomes
6975 negative. */
6976 new_initial_window_size = 16 * 1024;
6977 stream->remote_window_size =
6978 new_initial_window_size -
6979 ((int32_t)session->remote_settings.initial_window_size -
6980 stream->remote_window_size);
6981 session->remote_settings.initial_window_size =
6982 (uint32_t)new_initial_window_size;
6983 CU_ASSERT(-48 * 1024 == stream->remote_window_size);
6984
6985 /* Back 48KiB to stream window */
6986 frame.hd.stream_id = 1;
6987 frame.window_update.window_size_increment = 48 * 1024;
6988 nghttp2_session_on_window_update_received(session, &frame);
6989
6990 /* Nothing is sent because window_size is 0 */
6991 CU_ASSERT(0 == nghttp2_session_send(session));
6992 CU_ASSERT(32 * 1024 == ud.data_source_length);
6993
6994 /* Back 16KiB in stream window */
6995 frame.hd.stream_id = 1;
6996 frame.window_update.window_size_increment = 16 * 1024;
6997 nghttp2_session_on_window_update_received(session, &frame);
6998
6999 /* Back 24KiB in connection-level window */
7000 frame.hd.stream_id = 0;
7001 frame.window_update.window_size_increment = 24 * 1024;
7002 nghttp2_session_on_window_update_received(session, &frame);
7003
7004 /* Sends another 16KiB data */
7005 CU_ASSERT(0 == nghttp2_session_send(session));
7006 CU_ASSERT(16 * 1024 == ud.data_source_length);
7007
7008 /* Increase initial window size to 32KiB */
7009 iv[0].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
7010 iv[0].value = 32 * 1024;
7011
7012 nghttp2_frame_settings_init(&settings_frame.settings, NGHTTP2_FLAG_NONE,
7013 dup_iv(iv, 1), 1);
7014 nghttp2_session_on_settings_received(session, &settings_frame, 1);
7015 nghttp2_frame_settings_free(&settings_frame.settings, mem);
7016
7017 /* Sends another 8KiB data */
7018 CU_ASSERT(0 == nghttp2_session_send(session));
7019 CU_ASSERT(8 * 1024 == ud.data_source_length);
7020
7021 /* Back 8KiB in connection-level window */
7022 frame.hd.stream_id = 0;
7023 frame.window_update.window_size_increment = 8 * 1024;
7024 nghttp2_session_on_window_update_received(session, &frame);
7025
7026 /* Sends last 8KiB data */
7027 CU_ASSERT(0 == nghttp2_session_send(session));
7028 CU_ASSERT(0 == ud.data_source_length);
7029 CU_ASSERT(nghttp2_session_get_stream(session, 1)->shut_flags &
7030 NGHTTP2_SHUT_WR);
7031
7032 nghttp2_frame_window_update_free(&frame.window_update);
7033 nghttp2_session_del(session);
7034 }
7035
test_nghttp2_session_flow_control_data_recv(void)7036 void test_nghttp2_session_flow_control_data_recv(void) {
7037 nghttp2_session *session;
7038 nghttp2_session_callbacks callbacks;
7039 uint8_t data[64 * 1024 + 16];
7040 nghttp2_frame_hd hd;
7041 nghttp2_outbound_item *item;
7042 nghttp2_stream *stream;
7043
7044 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7045 callbacks.send_callback = null_send_callback;
7046
7047 /* Initial window size to 64KiB - 1*/
7048 nghttp2_session_client_new(&session, &callbacks, NULL);
7049
7050 stream = open_sent_stream(session, 1);
7051
7052 nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_WR);
7053
7054 session->local_window_size = NGHTTP2_MAX_PAYLOADLEN;
7055 stream->local_window_size = NGHTTP2_MAX_PAYLOADLEN;
7056
7057 /* Create DATA frame */
7058 memset(data, 0, sizeof(data));
7059 nghttp2_frame_hd_init(&hd, NGHTTP2_MAX_PAYLOADLEN, NGHTTP2_DATA,
7060 NGHTTP2_FLAG_END_STREAM, 1);
7061
7062 nghttp2_frame_pack_frame_hd(data, &hd);
7063 CU_ASSERT(NGHTTP2_MAX_PAYLOADLEN + NGHTTP2_FRAME_HDLEN ==
7064 nghttp2_session_mem_recv(
7065 session, data, NGHTTP2_MAX_PAYLOADLEN + NGHTTP2_FRAME_HDLEN));
7066
7067 item = nghttp2_session_get_next_ob_item(session);
7068 /* Since this is the last frame, stream-level WINDOW_UPDATE is not
7069 issued, but connection-level is. */
7070 CU_ASSERT(NGHTTP2_WINDOW_UPDATE == item->frame.hd.type);
7071 CU_ASSERT(0 == item->frame.hd.stream_id);
7072 CU_ASSERT(NGHTTP2_MAX_PAYLOADLEN ==
7073 item->frame.window_update.window_size_increment);
7074
7075 CU_ASSERT(0 == nghttp2_session_send(session));
7076
7077 /* Receive DATA for closed stream. They are still subject to under
7078 connection-level flow control, since this situation arises when
7079 RST_STREAM is issued by the remote, but the local side keeps
7080 sending DATA frames. Without calculating connection-level window,
7081 the subsequent flow control gets confused. */
7082 CU_ASSERT(NGHTTP2_MAX_PAYLOADLEN + NGHTTP2_FRAME_HDLEN ==
7083 nghttp2_session_mem_recv(
7084 session, data, NGHTTP2_MAX_PAYLOADLEN + NGHTTP2_FRAME_HDLEN));
7085
7086 item = nghttp2_session_get_next_ob_item(session);
7087 CU_ASSERT(NGHTTP2_WINDOW_UPDATE == item->frame.hd.type);
7088 CU_ASSERT(0 == item->frame.hd.stream_id);
7089 CU_ASSERT(NGHTTP2_MAX_PAYLOADLEN ==
7090 item->frame.window_update.window_size_increment);
7091
7092 nghttp2_session_del(session);
7093 }
7094
test_nghttp2_session_flow_control_data_with_padding_recv(void)7095 void test_nghttp2_session_flow_control_data_with_padding_recv(void) {
7096 nghttp2_session *session;
7097 nghttp2_session_callbacks callbacks;
7098 uint8_t data[1024];
7099 nghttp2_frame_hd hd;
7100 nghttp2_stream *stream;
7101 nghttp2_option *option;
7102
7103 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7104 callbacks.send_callback = null_send_callback;
7105
7106 nghttp2_option_new(&option);
7107 /* Disable auto window update so that we can check padding is
7108 consumed automatically */
7109 nghttp2_option_set_no_auto_window_update(option, 1);
7110
7111 /* Initial window size to 64KiB - 1*/
7112 nghttp2_session_client_new2(&session, &callbacks, NULL, option);
7113
7114 nghttp2_option_del(option);
7115
7116 stream = open_sent_stream(session, 1);
7117
7118 /* Create DATA frame */
7119 memset(data, 0, sizeof(data));
7120 nghttp2_frame_hd_init(&hd, 357, NGHTTP2_DATA, NGHTTP2_FLAG_PADDED, 1);
7121
7122 nghttp2_frame_pack_frame_hd(data, &hd);
7123 /* Set Pad Length field, which itself is padding */
7124 data[NGHTTP2_FRAME_HDLEN] = 255;
7125
7126 CU_ASSERT(
7127 (ssize_t)(NGHTTP2_FRAME_HDLEN + hd.length) ==
7128 nghttp2_session_mem_recv(session, data, NGHTTP2_FRAME_HDLEN + hd.length));
7129
7130 CU_ASSERT((int32_t)hd.length == session->recv_window_size);
7131 CU_ASSERT((int32_t)hd.length == stream->recv_window_size);
7132 CU_ASSERT(256 == session->consumed_size);
7133 CU_ASSERT(256 == stream->consumed_size);
7134 CU_ASSERT(357 == session->recv_window_size);
7135 CU_ASSERT(357 == stream->recv_window_size);
7136
7137 /* Receive the same DATA frame, but in 2 parts: first 9 + 1 + 102
7138 bytes which includes 1st padding byte, and remainder */
7139 CU_ASSERT((ssize_t)(NGHTTP2_FRAME_HDLEN + 103) ==
7140 nghttp2_session_mem_recv(session, data, NGHTTP2_FRAME_HDLEN + 103));
7141 CU_ASSERT(258 == session->consumed_size);
7142 CU_ASSERT(258 == stream->consumed_size);
7143 CU_ASSERT(460 == session->recv_window_size);
7144 CU_ASSERT(460 == stream->recv_window_size);
7145
7146 /* 357 - 103 = 254 bytes left */
7147 CU_ASSERT(254 == nghttp2_session_mem_recv(session, data, 254));
7148 CU_ASSERT(512 == session->consumed_size);
7149 CU_ASSERT(512 == stream->consumed_size);
7150 CU_ASSERT(714 == session->recv_window_size);
7151 CU_ASSERT(714 == stream->recv_window_size);
7152
7153 /* Receive the same DATA frame, but in 2 parts: first 9 = 1 + 101
7154 bytes which only includes data without padding, 2nd part is
7155 padding only */
7156 CU_ASSERT((ssize_t)(NGHTTP2_FRAME_HDLEN + 102) ==
7157 nghttp2_session_mem_recv(session, data, NGHTTP2_FRAME_HDLEN + 102));
7158 CU_ASSERT(513 == session->consumed_size);
7159 CU_ASSERT(513 == stream->consumed_size);
7160 CU_ASSERT(816 == session->recv_window_size);
7161 CU_ASSERT(816 == stream->recv_window_size);
7162
7163 /* 357 - 102 = 255 bytes left */
7164 CU_ASSERT(255 == nghttp2_session_mem_recv(session, data, 255));
7165 CU_ASSERT(768 == session->consumed_size);
7166 CU_ASSERT(768 == stream->consumed_size);
7167 CU_ASSERT(1071 == session->recv_window_size);
7168 CU_ASSERT(1071 == stream->recv_window_size);
7169
7170 /* Receive the same DATA frame, but in 2 parts: first 9 = 1 + 50
7171 bytes which includes byte up to middle of data, 2nd part is the
7172 remainder */
7173 CU_ASSERT((ssize_t)(NGHTTP2_FRAME_HDLEN + 51) ==
7174 nghttp2_session_mem_recv(session, data, NGHTTP2_FRAME_HDLEN + 51));
7175 CU_ASSERT(769 == session->consumed_size);
7176 CU_ASSERT(769 == stream->consumed_size);
7177 CU_ASSERT(1122 == session->recv_window_size);
7178 CU_ASSERT(1122 == stream->recv_window_size);
7179
7180 /* 357 - 51 = 306 bytes left */
7181 CU_ASSERT(306 == nghttp2_session_mem_recv(session, data, 306));
7182 CU_ASSERT(1024 == session->consumed_size);
7183 CU_ASSERT(1024 == stream->consumed_size);
7184 CU_ASSERT(1428 == session->recv_window_size);
7185 CU_ASSERT(1428 == stream->recv_window_size);
7186
7187 nghttp2_session_del(session);
7188 }
7189
test_nghttp2_session_data_read_temporal_failure(void)7190 void test_nghttp2_session_data_read_temporal_failure(void) {
7191 nghttp2_session *session;
7192 nghttp2_session_callbacks callbacks;
7193 my_user_data ud;
7194 nghttp2_data_provider data_prd;
7195 nghttp2_frame frame;
7196 nghttp2_stream *stream;
7197 size_t data_size = 128 * 1024;
7198
7199 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7200 callbacks.send_callback = null_send_callback;
7201 callbacks.on_frame_send_callback = on_frame_send_callback;
7202 data_prd.read_callback = fixed_length_data_source_read_callback;
7203
7204 ud.data_source_length = data_size;
7205
7206 /* Initial window size is 64KiB - 1 */
7207 nghttp2_session_client_new(&session, &callbacks, &ud);
7208 nghttp2_submit_request(session, NULL, NULL, 0, &data_prd, NULL);
7209
7210 /* Sends NGHTTP2_INITIAL_WINDOW_SIZE data, assuming, it is equal to
7211 or smaller than NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE */
7212 CU_ASSERT(0 == nghttp2_session_send(session));
7213 CU_ASSERT(data_size - NGHTTP2_INITIAL_WINDOW_SIZE == ud.data_source_length);
7214
7215 stream = nghttp2_session_get_stream(session, 1);
7216 CU_ASSERT(NGHTTP2_DATA == stream->item->frame.hd.type);
7217
7218 stream->item->aux_data.data.data_prd.read_callback =
7219 temporal_failure_data_source_read_callback;
7220
7221 /* Back NGHTTP2_INITIAL_WINDOW_SIZE to both connection-level and
7222 stream-wise window */
7223 nghttp2_frame_window_update_init(&frame.window_update, NGHTTP2_FLAG_NONE, 1,
7224 NGHTTP2_INITIAL_WINDOW_SIZE);
7225 nghttp2_session_on_window_update_received(session, &frame);
7226 frame.hd.stream_id = 0;
7227 nghttp2_session_on_window_update_received(session, &frame);
7228 nghttp2_frame_window_update_free(&frame.window_update);
7229
7230 /* Sending data will fail (soft fail) and treated as stream error */
7231 ud.frame_send_cb_called = 0;
7232 CU_ASSERT(0 == nghttp2_session_send(session));
7233 CU_ASSERT(data_size - NGHTTP2_INITIAL_WINDOW_SIZE == ud.data_source_length);
7234
7235 CU_ASSERT(1 == ud.frame_send_cb_called);
7236 CU_ASSERT(NGHTTP2_RST_STREAM == ud.sent_frame_type);
7237
7238 data_prd.read_callback = fail_data_source_read_callback;
7239 nghttp2_submit_request(session, NULL, NULL, 0, &data_prd, NULL);
7240 /* Sending data will fail (hard fail) and session tear down */
7241 CU_ASSERT(NGHTTP2_ERR_CALLBACK_FAILURE == nghttp2_session_send(session));
7242
7243 nghttp2_session_del(session);
7244 }
7245
test_nghttp2_session_on_stream_close(void)7246 void test_nghttp2_session_on_stream_close(void) {
7247 nghttp2_session *session;
7248 nghttp2_session_callbacks callbacks;
7249 my_user_data user_data;
7250 nghttp2_stream *stream;
7251
7252 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7253 callbacks.on_stream_close_callback = on_stream_close_callback;
7254 user_data.stream_close_cb_called = 0;
7255
7256 nghttp2_session_client_new(&session, &callbacks, &user_data);
7257 stream =
7258 open_sent_stream3(session, 1, NGHTTP2_STREAM_FLAG_NONE, &pri_spec_default,
7259 NGHTTP2_STREAM_OPENED, &user_data);
7260 CU_ASSERT(stream != NULL);
7261 CU_ASSERT(nghttp2_session_close_stream(session, 1, NGHTTP2_NO_ERROR) == 0);
7262 CU_ASSERT(user_data.stream_close_cb_called == 1);
7263 nghttp2_session_del(session);
7264 }
7265
test_nghttp2_session_on_ctrl_not_send(void)7266 void test_nghttp2_session_on_ctrl_not_send(void) {
7267 nghttp2_session *session;
7268 nghttp2_session_callbacks callbacks;
7269 my_user_data user_data;
7270 nghttp2_stream *stream;
7271
7272 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7273 callbacks.on_frame_not_send_callback = on_frame_not_send_callback;
7274 callbacks.send_callback = null_send_callback;
7275 user_data.frame_not_send_cb_called = 0;
7276 user_data.not_sent_frame_type = 0;
7277 user_data.not_sent_error = 0;
7278
7279 nghttp2_session_server_new(&session, &callbacks, &user_data);
7280 stream =
7281 open_recv_stream3(session, 1, NGHTTP2_STREAM_FLAG_NONE, &pri_spec_default,
7282 NGHTTP2_STREAM_OPENING, &user_data);
7283
7284 /* Check response HEADERS */
7285 /* Send bogus stream ID */
7286 CU_ASSERT(0 == nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, 3,
7287 NULL, NULL, 0, NULL));
7288 CU_ASSERT(0 == nghttp2_session_send(session));
7289 CU_ASSERT(1 == user_data.frame_not_send_cb_called);
7290 CU_ASSERT(NGHTTP2_HEADERS == user_data.not_sent_frame_type);
7291 CU_ASSERT(NGHTTP2_ERR_STREAM_CLOSED == user_data.not_sent_error);
7292
7293 user_data.frame_not_send_cb_called = 0;
7294 /* Shutdown transmission */
7295 stream->shut_flags |= NGHTTP2_SHUT_WR;
7296 CU_ASSERT(0 == nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, 1,
7297 NULL, NULL, 0, NULL));
7298 CU_ASSERT(0 == nghttp2_session_send(session));
7299 CU_ASSERT(1 == user_data.frame_not_send_cb_called);
7300 CU_ASSERT(NGHTTP2_HEADERS == user_data.not_sent_frame_type);
7301 CU_ASSERT(NGHTTP2_ERR_STREAM_SHUT_WR == user_data.not_sent_error);
7302
7303 stream->shut_flags = NGHTTP2_SHUT_NONE;
7304 user_data.frame_not_send_cb_called = 0;
7305 /* Queue RST_STREAM */
7306 CU_ASSERT(0 == nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, 1,
7307 NULL, NULL, 0, NULL));
7308 CU_ASSERT(0 == nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, 1,
7309 NGHTTP2_INTERNAL_ERROR));
7310 CU_ASSERT(0 == nghttp2_session_send(session));
7311 CU_ASSERT(1 == user_data.frame_not_send_cb_called);
7312 CU_ASSERT(NGHTTP2_HEADERS == user_data.not_sent_frame_type);
7313 CU_ASSERT(NGHTTP2_ERR_STREAM_CLOSING == user_data.not_sent_error);
7314
7315 nghttp2_session_del(session);
7316
7317 /* Check request HEADERS */
7318 user_data.frame_not_send_cb_called = 0;
7319 CU_ASSERT(nghttp2_session_client_new(&session, &callbacks, &user_data) == 0);
7320 /* Maximum Stream ID is reached */
7321 session->next_stream_id = (1u << 31) + 1;
7322 CU_ASSERT(NGHTTP2_ERR_STREAM_ID_NOT_AVAILABLE ==
7323 nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, -1, NULL,
7324 NULL, 0, NULL));
7325
7326 user_data.frame_not_send_cb_called = 0;
7327 /* GOAWAY received */
7328 session->goaway_flags |= NGHTTP2_GOAWAY_RECV;
7329 session->next_stream_id = 9;
7330
7331 CU_ASSERT(0 < nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, -1,
7332 NULL, NULL, 0, NULL));
7333 CU_ASSERT(0 == nghttp2_session_send(session));
7334 CU_ASSERT(1 == user_data.frame_not_send_cb_called);
7335 CU_ASSERT(NGHTTP2_HEADERS == user_data.not_sent_frame_type);
7336 CU_ASSERT(NGHTTP2_ERR_START_STREAM_NOT_ALLOWED == user_data.not_sent_error);
7337
7338 nghttp2_session_del(session);
7339 }
7340
test_nghttp2_session_get_outbound_queue_size(void)7341 void test_nghttp2_session_get_outbound_queue_size(void) {
7342 nghttp2_session *session;
7343 nghttp2_session_callbacks callbacks;
7344
7345 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7346 CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, NULL));
7347 CU_ASSERT(0 == nghttp2_session_get_outbound_queue_size(session));
7348
7349 CU_ASSERT(0 == nghttp2_submit_ping(session, NGHTTP2_FLAG_NONE, NULL));
7350 CU_ASSERT(1 == nghttp2_session_get_outbound_queue_size(session));
7351
7352 CU_ASSERT(0 == nghttp2_submit_goaway(session, NGHTTP2_FLAG_NONE, 2,
7353 NGHTTP2_NO_ERROR, NULL, 0));
7354 CU_ASSERT(2 == nghttp2_session_get_outbound_queue_size(session));
7355
7356 nghttp2_session_del(session);
7357 }
7358
test_nghttp2_session_get_effective_local_window_size(void)7359 void test_nghttp2_session_get_effective_local_window_size(void) {
7360 nghttp2_session *session;
7361 nghttp2_session_callbacks callbacks;
7362 nghttp2_stream *stream;
7363
7364 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7365 CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, NULL));
7366
7367 stream = open_sent_stream(session, 1);
7368
7369 CU_ASSERT(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE ==
7370 nghttp2_session_get_effective_local_window_size(session));
7371 CU_ASSERT(0 == nghttp2_session_get_effective_recv_data_length(session));
7372
7373 CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE ==
7374 nghttp2_session_get_stream_effective_local_window_size(session, 1));
7375 CU_ASSERT(0 ==
7376 nghttp2_session_get_stream_effective_recv_data_length(session, 1));
7377
7378 /* Check connection flow control */
7379 session->recv_window_size = 100;
7380 nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 0, 1100);
7381
7382 CU_ASSERT(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE + 1000 ==
7383 nghttp2_session_get_effective_local_window_size(session));
7384 CU_ASSERT(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE + 1000 ==
7385 nghttp2_session_get_local_window_size(session));
7386 CU_ASSERT(0 == nghttp2_session_get_effective_recv_data_length(session));
7387
7388 nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 0, -50);
7389 /* Now session->recv_window_size = -50 */
7390 CU_ASSERT(-50 == session->recv_window_size);
7391 CU_ASSERT(50 == session->recv_reduction);
7392 CU_ASSERT(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE + 950 ==
7393 nghttp2_session_get_effective_local_window_size(session));
7394 CU_ASSERT(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE + 1000 ==
7395 nghttp2_session_get_local_window_size(session));
7396 CU_ASSERT(0 == nghttp2_session_get_effective_recv_data_length(session));
7397
7398 session->recv_window_size += 50;
7399
7400 /* Now session->recv_window_size = 0 */
7401
7402 CU_ASSERT(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE + 950 ==
7403 nghttp2_session_get_local_window_size(session));
7404
7405 nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 0, 100);
7406 CU_ASSERT(50 == session->recv_window_size);
7407 CU_ASSERT(0 == session->recv_reduction);
7408 CU_ASSERT(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE + 1050 ==
7409 nghttp2_session_get_effective_local_window_size(session));
7410 CU_ASSERT(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE + 1000 ==
7411 nghttp2_session_get_local_window_size(session));
7412 CU_ASSERT(50 == nghttp2_session_get_effective_recv_data_length(session));
7413
7414 /* Check stream flow control */
7415 stream->recv_window_size = 100;
7416 nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 1, 1100);
7417
7418 CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE + 1000 ==
7419 nghttp2_session_get_stream_effective_local_window_size(session, 1));
7420 CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE + 1000 ==
7421 nghttp2_session_get_stream_local_window_size(session, 1));
7422 CU_ASSERT(0 ==
7423 nghttp2_session_get_stream_effective_recv_data_length(session, 1));
7424
7425 nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 1, -50);
7426 /* Now stream->recv_window_size = -50 */
7427 CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE + 950 ==
7428 nghttp2_session_get_stream_effective_local_window_size(session, 1));
7429 CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE + 1000 ==
7430 nghttp2_session_get_stream_local_window_size(session, 1));
7431 CU_ASSERT(0 ==
7432 nghttp2_session_get_stream_effective_recv_data_length(session, 1));
7433
7434 stream->recv_window_size += 50;
7435 /* Now stream->recv_window_size = 0 */
7436 nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 1, 100);
7437 CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE + 1050 ==
7438 nghttp2_session_get_stream_effective_local_window_size(session, 1));
7439 CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE + 1000 ==
7440 nghttp2_session_get_stream_local_window_size(session, 1));
7441 CU_ASSERT(50 ==
7442 nghttp2_session_get_stream_effective_recv_data_length(session, 1));
7443
7444 nghttp2_session_del(session);
7445 }
7446
test_nghttp2_session_set_option(void)7447 void test_nghttp2_session_set_option(void) {
7448 nghttp2_session *session;
7449 nghttp2_session_callbacks callbacks;
7450 nghttp2_option *option;
7451 nghttp2_hd_deflater *deflater;
7452 int rv;
7453
7454 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7455 callbacks.send_callback = null_send_callback;
7456
7457 /* Test for nghttp2_option_set_no_auto_window_update */
7458 nghttp2_option_new(&option);
7459 nghttp2_option_set_no_auto_window_update(option, 1);
7460
7461 nghttp2_session_client_new2(&session, &callbacks, NULL, option);
7462
7463 CU_ASSERT(session->opt_flags & NGHTTP2_OPTMASK_NO_AUTO_WINDOW_UPDATE);
7464
7465 nghttp2_session_del(session);
7466 nghttp2_option_del(option);
7467
7468 /* Test for nghttp2_option_set_peer_max_concurrent_streams */
7469 nghttp2_option_new(&option);
7470 nghttp2_option_set_peer_max_concurrent_streams(option, 100);
7471
7472 nghttp2_session_client_new2(&session, &callbacks, NULL, option);
7473
7474 CU_ASSERT(100 == session->remote_settings.max_concurrent_streams);
7475 nghttp2_session_del(session);
7476 nghttp2_option_del(option);
7477
7478 /* Test for nghttp2_option_set_max_reserved_remote_streams */
7479 nghttp2_option_new(&option);
7480 nghttp2_option_set_max_reserved_remote_streams(option, 99);
7481
7482 nghttp2_session_client_new2(&session, &callbacks, NULL, option);
7483
7484 CU_ASSERT(99 == session->max_incoming_reserved_streams);
7485 nghttp2_session_del(session);
7486 nghttp2_option_del(option);
7487
7488 /* Test for nghttp2_option_set_no_auto_ping_ack */
7489 nghttp2_option_new(&option);
7490 nghttp2_option_set_no_auto_ping_ack(option, 1);
7491
7492 nghttp2_session_client_new2(&session, &callbacks, NULL, option);
7493
7494 CU_ASSERT(session->opt_flags & NGHTTP2_OPTMASK_NO_AUTO_PING_ACK);
7495
7496 nghttp2_session_del(session);
7497 nghttp2_option_del(option);
7498
7499 /* Test for nghttp2_option_set_max_deflate_dynamic_table_size */
7500 nghttp2_option_new(&option);
7501 nghttp2_option_set_max_deflate_dynamic_table_size(option, 0);
7502
7503 nghttp2_session_client_new2(&session, &callbacks, NULL, option);
7504
7505 deflater = &session->hd_deflater;
7506
7507 rv = nghttp2_submit_request(session, NULL, reqnv, ARRLEN(reqnv), NULL, NULL);
7508
7509 CU_ASSERT(1 == rv);
7510
7511 rv = nghttp2_session_send(session);
7512
7513 CU_ASSERT(0 == rv);
7514 CU_ASSERT(0 == deflater->deflate_hd_table_bufsize_max);
7515 CU_ASSERT(0 == deflater->ctx.hd_table_bufsize);
7516
7517 nghttp2_session_del(session);
7518 nghttp2_option_del(option);
7519 }
7520
test_nghttp2_session_data_backoff_by_high_pri_frame(void)7521 void test_nghttp2_session_data_backoff_by_high_pri_frame(void) {
7522 nghttp2_session *session;
7523 nghttp2_session_callbacks callbacks;
7524 my_user_data ud;
7525 nghttp2_data_provider data_prd;
7526 nghttp2_stream *stream;
7527
7528 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
7529 callbacks.send_callback = block_count_send_callback;
7530 callbacks.on_frame_send_callback = on_frame_send_callback;
7531 data_prd.read_callback = fixed_length_data_source_read_callback;
7532
7533 ud.frame_send_cb_called = 0;
7534 ud.data_source_length = NGHTTP2_DATA_PAYLOADLEN * 4;
7535
7536 nghttp2_session_client_new(&session, &callbacks, &ud);
7537 nghttp2_submit_request(session, NULL, NULL, 0, &data_prd, NULL);
7538
7539 session->remote_window_size = 1 << 20;
7540
7541 ud.block_count = 2;
7542 /* Sends request HEADERS + DATA[0] */
7543 CU_ASSERT(0 == nghttp2_session_send(session));
7544
7545 stream = nghttp2_session_get_stream(session, 1);
7546 stream->remote_window_size = 1 << 20;
7547
7548 CU_ASSERT(NGHTTP2_DATA == ud.sent_frame_type);
7549 /* data for DATA[1] is read from data_prd but it is not sent */
7550 CU_ASSERT(ud.data_source_length == NGHTTP2_DATA_PAYLOADLEN * 2);
7551
7552 nghttp2_submit_ping(session, NGHTTP2_FLAG_NONE, NULL);
7553 ud.block_count = 2;
7554 /* Sends DATA[1] + PING, PING is interleaved in DATA sequence */
7555 CU_ASSERT(0 == nghttp2_session_send(session));
7556 CU_ASSERT(NGHTTP2_PING == ud.sent_frame_type);
7557 /* data for DATA[2] is read from data_prd but it is not sent */
7558 CU_ASSERT(ud.data_source_length == NGHTTP2_DATA_PAYLOADLEN);
7559
7560 ud.block_count = 2;
7561 /* Sends DATA[2..3] */
7562 CU_ASSERT(0 == nghttp2_session_send(session));
7563
7564 CU_ASSERT(stream->shut_flags & NGHTTP2_SHUT_WR);
7565
7566 nghttp2_session_del(session);
7567 }
7568
check_session_recv_data_with_padding(nghttp2_bufs * bufs,size_t datalen,nghttp2_mem * mem)7569 static void check_session_recv_data_with_padding(nghttp2_bufs *bufs,
7570 size_t datalen,
7571 nghttp2_mem *mem) {
7572 nghttp2_session *session;
7573 my_user_data ud;
7574 nghttp2_session_callbacks callbacks;
7575 uint8_t *in;
7576 size_t inlen;
7577
7578 memset(&callbacks, 0, sizeof(callbacks));
7579 callbacks.on_frame_recv_callback = on_frame_recv_callback;
7580 callbacks.on_data_chunk_recv_callback = on_data_chunk_recv_callback;
7581 nghttp2_session_server_new(&session, &callbacks, &ud);
7582
7583 open_recv_stream(session, 1);
7584
7585 inlen = (size_t)nghttp2_bufs_remove(bufs, &in);
7586
7587 ud.frame_recv_cb_called = 0;
7588 ud.data_chunk_len = 0;
7589
7590 CU_ASSERT((ssize_t)inlen == nghttp2_session_mem_recv(session, in, inlen));
7591
7592 CU_ASSERT(1 == ud.frame_recv_cb_called);
7593 CU_ASSERT(datalen == ud.data_chunk_len);
7594
7595 mem->free(in, NULL);
7596 nghttp2_session_del(session);
7597 }
7598
test_nghttp2_session_pack_data_with_padding(void)7599 void test_nghttp2_session_pack_data_with_padding(void) {
7600 nghttp2_session *session;
7601 my_user_data ud;
7602 nghttp2_session_callbacks callbacks;
7603 nghttp2_data_provider data_prd;
7604 nghttp2_frame *frame;
7605 size_t datalen = 55;
7606 nghttp2_mem *mem;
7607
7608 mem = nghttp2_mem_default();
7609
7610 memset(&callbacks, 0, sizeof(callbacks));
7611 callbacks.send_callback = block_count_send_callback;
7612 callbacks.on_frame_send_callback = on_frame_send_callback;
7613 callbacks.select_padding_callback = select_padding_callback;
7614
7615 data_prd.read_callback = fixed_length_data_source_read_callback;
7616
7617 nghttp2_session_client_new(&session, &callbacks, &ud);
7618
7619 ud.padlen = 63;
7620
7621 nghttp2_submit_request(session, NULL, NULL, 0, &data_prd, NULL);
7622 ud.block_count = 1;
7623 ud.data_source_length = datalen;
7624 /* Sends HEADERS */
7625 CU_ASSERT(0 == nghttp2_session_send(session));
7626 CU_ASSERT(NGHTTP2_HEADERS == ud.sent_frame_type);
7627
7628 frame = &session->aob.item->frame;
7629
7630 CU_ASSERT(ud.padlen == frame->data.padlen);
7631 CU_ASSERT(frame->hd.flags & NGHTTP2_FLAG_PADDED);
7632
7633 /* Check reception of this DATA frame */
7634 check_session_recv_data_with_padding(&session->aob.framebufs, datalen, mem);
7635
7636 nghttp2_session_del(session);
7637 }
7638
test_nghttp2_session_pack_headers_with_padding(void)7639 void test_nghttp2_session_pack_headers_with_padding(void) {
7640 nghttp2_session *session, *sv_session;
7641 accumulator acc;
7642 my_user_data ud;
7643 nghttp2_session_callbacks callbacks;
7644
7645 memset(&callbacks, 0, sizeof(callbacks));
7646 callbacks.send_callback = accumulator_send_callback;
7647 callbacks.on_frame_send_callback = on_frame_send_callback;
7648 callbacks.select_padding_callback = select_padding_callback;
7649 callbacks.on_frame_recv_callback = on_frame_recv_callback;
7650
7651 acc.length = 0;
7652 ud.acc = &acc;
7653
7654 nghttp2_session_client_new(&session, &callbacks, &ud);
7655 nghttp2_session_server_new(&sv_session, &callbacks, &ud);
7656
7657 ud.padlen = 163;
7658
7659 CU_ASSERT(1 == nghttp2_submit_request(session, NULL, reqnv, ARRLEN(reqnv),
7660 NULL, NULL));
7661 CU_ASSERT(0 == nghttp2_session_send(session));
7662
7663 CU_ASSERT(acc.length < NGHTTP2_MAX_PAYLOADLEN);
7664 ud.frame_recv_cb_called = 0;
7665 CU_ASSERT((ssize_t)acc.length ==
7666 nghttp2_session_mem_recv(sv_session, acc.buf, acc.length));
7667 CU_ASSERT(1 == ud.frame_recv_cb_called);
7668 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(sv_session));
7669
7670 nghttp2_session_del(sv_session);
7671 nghttp2_session_del(session);
7672 }
7673
test_nghttp2_pack_settings_payload(void)7674 void test_nghttp2_pack_settings_payload(void) {
7675 nghttp2_settings_entry iv[2];
7676 uint8_t buf[64];
7677 ssize_t len;
7678 nghttp2_settings_entry *resiv;
7679 size_t resniv;
7680 nghttp2_mem *mem;
7681
7682 mem = nghttp2_mem_default();
7683
7684 iv[0].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
7685 iv[0].value = 1023;
7686 iv[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
7687 iv[1].value = 4095;
7688
7689 len = nghttp2_pack_settings_payload(buf, sizeof(buf), iv, 2);
7690 CU_ASSERT(2 * NGHTTP2_FRAME_SETTINGS_ENTRY_LENGTH == len);
7691 CU_ASSERT(0 == nghttp2_frame_unpack_settings_payload2(&resiv, &resniv, buf,
7692 (size_t)len, mem));
7693 CU_ASSERT(2 == resniv);
7694 CU_ASSERT(NGHTTP2_SETTINGS_HEADER_TABLE_SIZE == resiv[0].settings_id);
7695 CU_ASSERT(1023 == resiv[0].value);
7696 CU_ASSERT(NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE == resiv[1].settings_id);
7697 CU_ASSERT(4095 == resiv[1].value);
7698
7699 mem->free(resiv, NULL);
7700
7701 len = nghttp2_pack_settings_payload(buf, 9 /* too small */, iv, 2);
7702 CU_ASSERT(NGHTTP2_ERR_INSUFF_BUFSIZE == len);
7703 }
7704
7705 #define check_stream_dep_sib(STREAM, DEP_PREV, DEP_NEXT, SIB_PREV, SIB_NEXT) \
7706 do { \
7707 CU_ASSERT(DEP_PREV == STREAM->dep_prev); \
7708 CU_ASSERT(DEP_NEXT == STREAM->dep_next); \
7709 CU_ASSERT(SIB_PREV == STREAM->sib_prev); \
7710 CU_ASSERT(SIB_NEXT == STREAM->sib_next); \
7711 } while (0)
7712
7713 /* nghttp2_stream_dep_add() and its families functions should be
7714 tested in nghttp2_stream_test.c, but it is easier to use
7715 nghttp2_session_open_stream(). Therefore, we test them here. */
test_nghttp2_session_stream_dep_add(void)7716 void test_nghttp2_session_stream_dep_add(void) {
7717 nghttp2_session *session;
7718 nghttp2_session_callbacks callbacks;
7719 nghttp2_stream *a, *b, *c, *d, *e, *root;
7720
7721 memset(&callbacks, 0, sizeof(callbacks));
7722
7723 nghttp2_session_server_new(&session, &callbacks, NULL);
7724
7725 root = &session->root;
7726
7727 a = open_stream(session, 1);
7728
7729 c = open_stream_with_dep(session, 5, a);
7730 b = open_stream_with_dep(session, 3, a);
7731 d = open_stream_with_dep(session, 7, c);
7732
7733 /* a
7734 * |
7735 * b--c
7736 * |
7737 * d
7738 */
7739
7740 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 2 == a->sum_dep_weight);
7741 CU_ASSERT(0 == b->sum_dep_weight);
7742 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == c->sum_dep_weight);
7743 CU_ASSERT(0 == d->sum_dep_weight);
7744
7745 check_stream_dep_sib(a, root, b, NULL, NULL);
7746 check_stream_dep_sib(b, a, NULL, NULL, c);
7747 check_stream_dep_sib(c, a, d, b, NULL);
7748 check_stream_dep_sib(d, c, NULL, NULL, NULL);
7749
7750 CU_ASSERT(a == session->root.dep_next);
7751
7752 e = open_stream_with_dep_excl(session, 9, a);
7753
7754 /* a
7755 * |
7756 * e
7757 * |
7758 * b--c
7759 * |
7760 * d
7761 */
7762
7763 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == a->sum_dep_weight);
7764 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 2 == e->sum_dep_weight);
7765 CU_ASSERT(0 == b->sum_dep_weight);
7766 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == c->sum_dep_weight);
7767 CU_ASSERT(0 == d->sum_dep_weight);
7768
7769 check_stream_dep_sib(a, root, e, NULL, NULL);
7770 check_stream_dep_sib(e, a, b, NULL, NULL);
7771 check_stream_dep_sib(b, e, NULL, NULL, c);
7772 check_stream_dep_sib(c, e, d, b, NULL);
7773 check_stream_dep_sib(d, c, NULL, NULL, NULL);
7774
7775 CU_ASSERT(a == session->root.dep_next);
7776
7777 nghttp2_session_del(session);
7778 }
7779
test_nghttp2_session_stream_dep_remove(void)7780 void test_nghttp2_session_stream_dep_remove(void) {
7781 nghttp2_session *session;
7782 nghttp2_session_callbacks callbacks;
7783 nghttp2_stream *a, *b, *c, *d, *e, *f, *root;
7784
7785 memset(&callbacks, 0, sizeof(callbacks));
7786
7787 /* Remove root */
7788 nghttp2_session_server_new(&session, &callbacks, NULL);
7789
7790 root = &session->root;
7791
7792 a = open_stream(session, 1);
7793 b = open_stream_with_dep(session, 3, a);
7794 c = open_stream_with_dep(session, 5, a);
7795 d = open_stream_with_dep(session, 7, c);
7796
7797 /* a
7798 * |
7799 * c--b
7800 * |
7801 * d
7802 */
7803
7804 nghttp2_stream_dep_remove(a);
7805
7806 /* becomes:
7807 * c b
7808 * |
7809 * d
7810 */
7811
7812 CU_ASSERT(0 == a->sum_dep_weight);
7813 CU_ASSERT(0 == b->sum_dep_weight);
7814 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == c->sum_dep_weight);
7815 CU_ASSERT(0 == d->sum_dep_weight);
7816
7817 check_stream_dep_sib(a, NULL, NULL, NULL, NULL);
7818 check_stream_dep_sib(b, root, NULL, c, NULL);
7819 check_stream_dep_sib(c, root, d, NULL, b);
7820 check_stream_dep_sib(d, c, NULL, NULL, NULL);
7821
7822 CU_ASSERT(c == session->root.dep_next);
7823
7824 nghttp2_session_del(session);
7825
7826 /* Remove right most stream */
7827 nghttp2_session_server_new(&session, &callbacks, NULL);
7828
7829 root = &session->root;
7830
7831 a = open_stream(session, 1);
7832 b = open_stream_with_dep(session, 3, a);
7833 c = open_stream_with_dep(session, 5, a);
7834 d = open_stream_with_dep(session, 7, c);
7835
7836 /* a
7837 * |
7838 * c--b
7839 * |
7840 * d
7841 */
7842
7843 nghttp2_stream_dep_remove(b);
7844
7845 /* becomes:
7846 * a
7847 * |
7848 * c
7849 * |
7850 * d
7851 */
7852
7853 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == a->sum_dep_weight);
7854 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == c->sum_dep_weight);
7855 CU_ASSERT(0 == d->sum_dep_weight);
7856 CU_ASSERT(0 == b->sum_dep_weight);
7857
7858 check_stream_dep_sib(a, root, c, NULL, NULL);
7859 check_stream_dep_sib(b, NULL, NULL, NULL, NULL);
7860 check_stream_dep_sib(c, a, d, NULL, NULL);
7861 check_stream_dep_sib(d, c, NULL, NULL, NULL);
7862
7863 CU_ASSERT(a == session->root.dep_next);
7864
7865 nghttp2_session_del(session);
7866
7867 /* Remove left most stream */
7868 nghttp2_session_server_new(&session, &callbacks, NULL);
7869
7870 root = &session->root;
7871
7872 a = open_stream(session, 1);
7873 b = open_stream_with_dep(session, 3, a);
7874 c = open_stream_with_dep(session, 5, a);
7875 d = open_stream_with_dep(session, 7, c);
7876 e = open_stream_with_dep(session, 9, c);
7877
7878 /* a
7879 * |
7880 * c--b
7881 * |
7882 * e--d
7883 */
7884
7885 nghttp2_stream_dep_remove(c);
7886
7887 /* becomes:
7888 * a
7889 * |
7890 * e--d--b
7891 */
7892
7893 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 2 == a->sum_dep_weight);
7894 CU_ASSERT(0 == b->sum_dep_weight);
7895 CU_ASSERT(0 == d->sum_dep_weight);
7896 CU_ASSERT(0 == c->sum_dep_weight);
7897 CU_ASSERT(0 == e->sum_dep_weight);
7898
7899 check_stream_dep_sib(a, root, e, NULL, NULL);
7900 check_stream_dep_sib(b, a, NULL, d, NULL);
7901 check_stream_dep_sib(c, NULL, NULL, NULL, NULL);
7902 check_stream_dep_sib(d, a, NULL, e, b);
7903 check_stream_dep_sib(e, a, NULL, NULL, d);
7904
7905 nghttp2_session_del(session);
7906
7907 /* Remove middle stream */
7908 nghttp2_session_server_new(&session, &callbacks, NULL);
7909
7910 root = &session->root;
7911
7912 a = open_stream(session, 1);
7913 b = open_stream_with_dep(session, 3, a);
7914 c = open_stream_with_dep(session, 5, a);
7915 d = open_stream_with_dep(session, 7, a);
7916 e = open_stream_with_dep(session, 9, c);
7917 f = open_stream_with_dep(session, 11, c);
7918
7919 /* a
7920 * |
7921 * d--c--b
7922 * |
7923 * f--e
7924 */
7925
7926 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 3 == a->sum_dep_weight);
7927 CU_ASSERT(0 == b->sum_dep_weight);
7928 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 2 == c->sum_dep_weight);
7929 CU_ASSERT(0 == d->sum_dep_weight);
7930 CU_ASSERT(0 == e->sum_dep_weight);
7931 CU_ASSERT(0 == f->sum_dep_weight);
7932
7933 nghttp2_stream_dep_remove(c);
7934
7935 /* becomes:
7936 * a
7937 * |
7938 * d--f--e--b
7939 */
7940
7941 /* c's weight 16 is distributed evenly to e and f. Each weight of e
7942 and f becomes 8. */
7943 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 2 + 8 * 2 == a->sum_dep_weight);
7944 CU_ASSERT(0 == b->sum_dep_weight);
7945 CU_ASSERT(0 == c->sum_dep_weight);
7946 CU_ASSERT(0 == d->sum_dep_weight);
7947 CU_ASSERT(0 == e->sum_dep_weight);
7948 CU_ASSERT(0 == f->sum_dep_weight);
7949
7950 check_stream_dep_sib(a, root, d, NULL, NULL);
7951 check_stream_dep_sib(b, a, NULL, e, NULL);
7952 check_stream_dep_sib(c, NULL, NULL, NULL, NULL);
7953 check_stream_dep_sib(e, a, NULL, f, b);
7954 check_stream_dep_sib(f, a, NULL, d, e);
7955 check_stream_dep_sib(d, a, NULL, NULL, f);
7956
7957 nghttp2_session_del(session);
7958 }
7959
test_nghttp2_session_stream_dep_add_subtree(void)7960 void test_nghttp2_session_stream_dep_add_subtree(void) {
7961 nghttp2_session *session;
7962 nghttp2_session_callbacks callbacks;
7963 nghttp2_stream *a, *b, *c, *d, *e, *f, *root;
7964
7965 memset(&callbacks, 0, sizeof(callbacks));
7966
7967 /* dep_stream has dep_next */
7968 nghttp2_session_server_new(&session, &callbacks, NULL);
7969
7970 root = &session->root;
7971
7972 a = open_stream(session, 1);
7973 b = open_stream_with_dep(session, 3, a);
7974 c = open_stream_with_dep(session, 5, a);
7975 d = open_stream_with_dep(session, 7, c);
7976
7977 e = open_stream(session, 9);
7978 f = open_stream_with_dep(session, 11, e);
7979
7980 /* a e
7981 * | |
7982 * c--b f
7983 * |
7984 * d
7985 */
7986
7987 nghttp2_stream_dep_remove_subtree(e);
7988 nghttp2_stream_dep_add_subtree(a, e);
7989
7990 /* becomes
7991 * a
7992 * |
7993 * e--c--b
7994 * | |
7995 * f d
7996 */
7997
7998 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 3 == a->sum_dep_weight);
7999 CU_ASSERT(0 == b->sum_dep_weight);
8000 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == c->sum_dep_weight);
8001 CU_ASSERT(0 == d->sum_dep_weight);
8002 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == e->sum_dep_weight);
8003 CU_ASSERT(0 == f->sum_dep_weight);
8004
8005 check_stream_dep_sib(a, root, e, NULL, NULL);
8006 check_stream_dep_sib(b, a, NULL, c, NULL);
8007 check_stream_dep_sib(c, a, d, e, b);
8008 check_stream_dep_sib(d, c, NULL, NULL, NULL);
8009 check_stream_dep_sib(e, a, f, NULL, c);
8010 check_stream_dep_sib(f, e, NULL, NULL, NULL);
8011
8012 nghttp2_session_del(session);
8013
8014 /* dep_stream has dep_next and now we insert subtree */
8015 nghttp2_session_server_new(&session, &callbacks, NULL);
8016
8017 root = &session->root;
8018
8019 a = open_stream(session, 1);
8020 b = open_stream_with_dep(session, 3, a);
8021 c = open_stream_with_dep(session, 5, a);
8022 d = open_stream_with_dep(session, 7, c);
8023
8024 e = open_stream(session, 9);
8025 f = open_stream_with_dep(session, 11, e);
8026
8027 /* a e
8028 * | |
8029 * c--b f
8030 * |
8031 * d
8032 */
8033
8034 nghttp2_stream_dep_remove_subtree(e);
8035 nghttp2_stream_dep_insert_subtree(a, e);
8036
8037 /* becomes
8038 * a
8039 * |
8040 * e
8041 * |
8042 * f--c--b
8043 * |
8044 * d
8045 */
8046
8047 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == a->sum_dep_weight);
8048 CU_ASSERT(0 == b->sum_dep_weight);
8049 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == c->sum_dep_weight);
8050 CU_ASSERT(0 == d->sum_dep_weight);
8051 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 3 == e->sum_dep_weight);
8052 CU_ASSERT(0 == f->sum_dep_weight);
8053
8054 check_stream_dep_sib(a, root, e, NULL, NULL);
8055 check_stream_dep_sib(e, a, f, NULL, NULL);
8056 check_stream_dep_sib(f, e, NULL, NULL, c);
8057 check_stream_dep_sib(b, e, NULL, c, NULL);
8058 check_stream_dep_sib(c, e, d, f, b);
8059 check_stream_dep_sib(d, c, NULL, NULL, NULL);
8060
8061 nghttp2_session_del(session);
8062 }
8063
test_nghttp2_session_stream_dep_remove_subtree(void)8064 void test_nghttp2_session_stream_dep_remove_subtree(void) {
8065 nghttp2_session *session;
8066 nghttp2_session_callbacks callbacks;
8067 nghttp2_stream *a, *b, *c, *d, *e, *root;
8068
8069 memset(&callbacks, 0, sizeof(callbacks));
8070
8071 /* Remove left most stream */
8072 nghttp2_session_server_new(&session, &callbacks, NULL);
8073
8074 root = &session->root;
8075
8076 a = open_stream(session, 1);
8077 b = open_stream_with_dep(session, 3, a);
8078 c = open_stream_with_dep(session, 5, a);
8079 d = open_stream_with_dep(session, 7, c);
8080
8081 /* a
8082 * |
8083 * c--b
8084 * |
8085 * d
8086 */
8087
8088 nghttp2_stream_dep_remove_subtree(c);
8089
8090 /* becomes
8091 * a c
8092 * | |
8093 * b d
8094 */
8095
8096 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == a->sum_dep_weight);
8097 CU_ASSERT(0 == b->sum_dep_weight);
8098 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == c->sum_dep_weight);
8099 CU_ASSERT(0 == d->sum_dep_weight);
8100
8101 check_stream_dep_sib(a, root, b, NULL, NULL);
8102 check_stream_dep_sib(b, a, NULL, NULL, NULL);
8103 check_stream_dep_sib(c, NULL, d, NULL, NULL);
8104 check_stream_dep_sib(d, c, NULL, NULL, NULL);
8105
8106 nghttp2_session_del(session);
8107
8108 /* Remove right most stream */
8109 nghttp2_session_server_new(&session, &callbacks, NULL);
8110
8111 root = &session->root;
8112
8113 a = open_stream(session, 1);
8114 b = open_stream_with_dep(session, 3, a);
8115 c = open_stream_with_dep(session, 5, a);
8116 d = open_stream_with_dep(session, 7, c);
8117
8118 /* a
8119 * |
8120 * c--b
8121 * |
8122 * d
8123 */
8124
8125 nghttp2_stream_dep_remove_subtree(b);
8126
8127 /* becomes
8128 * a b
8129 * |
8130 * c
8131 * |
8132 * d
8133 */
8134
8135 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == a->sum_dep_weight);
8136 CU_ASSERT(0 == b->sum_dep_weight);
8137 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == c->sum_dep_weight);
8138 CU_ASSERT(0 == d->sum_dep_weight);
8139
8140 check_stream_dep_sib(a, root, c, NULL, NULL);
8141 check_stream_dep_sib(c, a, d, NULL, NULL);
8142 check_stream_dep_sib(d, c, NULL, NULL, NULL);
8143 check_stream_dep_sib(b, NULL, NULL, NULL, NULL);
8144
8145 nghttp2_session_del(session);
8146
8147 /* Remove middle stream */
8148 nghttp2_session_server_new(&session, &callbacks, NULL);
8149
8150 root = &session->root;
8151
8152 a = open_stream(session, 1);
8153 e = open_stream_with_dep(session, 9, a);
8154 c = open_stream_with_dep(session, 5, a);
8155 b = open_stream_with_dep(session, 3, a);
8156 d = open_stream_with_dep(session, 7, c);
8157
8158 /* a
8159 * |
8160 * b--c--e
8161 * |
8162 * d
8163 */
8164
8165 nghttp2_stream_dep_remove_subtree(c);
8166
8167 /* becomes
8168 * a c
8169 * | |
8170 * b--e d
8171 */
8172
8173 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 2 == a->sum_dep_weight);
8174 CU_ASSERT(0 == b->sum_dep_weight);
8175 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == c->sum_dep_weight);
8176 CU_ASSERT(0 == d->sum_dep_weight);
8177 CU_ASSERT(0 == e->sum_dep_weight);
8178
8179 check_stream_dep_sib(a, root, b, NULL, NULL);
8180 check_stream_dep_sib(b, a, NULL, NULL, e);
8181 check_stream_dep_sib(e, a, NULL, b, NULL);
8182 check_stream_dep_sib(c, NULL, d, NULL, NULL);
8183 check_stream_dep_sib(d, c, NULL, NULL, NULL);
8184
8185 nghttp2_session_del(session);
8186 }
8187
test_nghttp2_session_stream_dep_all_your_stream_are_belong_to_us(void)8188 void test_nghttp2_session_stream_dep_all_your_stream_are_belong_to_us(void) {
8189 nghttp2_session *session;
8190 nghttp2_session_callbacks callbacks;
8191 nghttp2_stream *a, *b, *c, *d, *root;
8192 nghttp2_outbound_item *db, *dc;
8193 nghttp2_mem *mem;
8194
8195 mem = nghttp2_mem_default();
8196
8197 memset(&callbacks, 0, sizeof(callbacks));
8198
8199 nghttp2_session_server_new(&session, &callbacks, NULL);
8200
8201 root = &session->root;
8202
8203 a = open_stream(session, 1);
8204 b = open_stream_with_dep(session, 3, a);
8205
8206 c = open_stream(session, 5);
8207
8208 /* a c
8209 * |
8210 * b
8211 */
8212
8213 nghttp2_stream_dep_remove_subtree(c);
8214 CU_ASSERT(0 == nghttp2_stream_dep_insert_subtree(&session->root, c));
8215
8216 /*
8217 * c
8218 * |
8219 * a
8220 * |
8221 * b
8222 */
8223
8224 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == c->sum_dep_weight);
8225 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == a->sum_dep_weight);
8226 CU_ASSERT(0 == b->sum_dep_weight);
8227
8228 CU_ASSERT(nghttp2_pq_empty(&a->obq));
8229 CU_ASSERT(nghttp2_pq_empty(&b->obq));
8230 CU_ASSERT(nghttp2_pq_empty(&c->obq));
8231
8232 check_stream_dep_sib(c, root, a, NULL, NULL);
8233 check_stream_dep_sib(a, c, b, NULL, NULL);
8234 check_stream_dep_sib(b, a, NULL, NULL, NULL);
8235
8236 nghttp2_session_del(session);
8237
8238 nghttp2_session_server_new(&session, &callbacks, NULL);
8239
8240 root = &session->root;
8241
8242 a = open_stream(session, 1);
8243 b = open_stream(session, 3);
8244 c = open_stream(session, 5);
8245
8246 /*
8247 * a b c
8248 */
8249
8250 nghttp2_stream_dep_remove_subtree(c);
8251 CU_ASSERT(0 == nghttp2_stream_dep_insert_subtree(&session->root, c));
8252
8253 /*
8254 * c
8255 * |
8256 * b--a
8257 */
8258
8259 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 2 == c->sum_dep_weight);
8260 CU_ASSERT(0 == b->sum_dep_weight);
8261 CU_ASSERT(0 == a->sum_dep_weight);
8262
8263 CU_ASSERT(nghttp2_pq_empty(&a->obq));
8264 CU_ASSERT(nghttp2_pq_empty(&b->obq));
8265 CU_ASSERT(nghttp2_pq_empty(&c->obq));
8266
8267 check_stream_dep_sib(c, root, b, NULL, NULL);
8268 check_stream_dep_sib(b, c, NULL, NULL, a);
8269 check_stream_dep_sib(a, c, NULL, b, NULL);
8270
8271 nghttp2_session_del(session);
8272
8273 nghttp2_session_server_new(&session, &callbacks, NULL);
8274
8275 root = &session->root;
8276
8277 a = open_stream(session, 1);
8278 b = open_stream_with_dep(session, 3, a);
8279
8280 c = open_stream(session, 5);
8281 d = open_stream_with_dep(session, 7, c);
8282
8283 /* a c
8284 * | |
8285 * b d
8286 */
8287
8288 nghttp2_stream_dep_remove_subtree(c);
8289 CU_ASSERT(0 == nghttp2_stream_dep_insert_subtree(&session->root, c));
8290
8291 /*
8292 * c
8293 * |
8294 * d--a
8295 * |
8296 * b
8297 */
8298
8299 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 2 == c->sum_dep_weight);
8300 CU_ASSERT(0 == d->sum_dep_weight);
8301 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == a->sum_dep_weight);
8302 CU_ASSERT(0 == b->sum_dep_weight);
8303
8304 CU_ASSERT(nghttp2_pq_empty(&a->obq));
8305 CU_ASSERT(nghttp2_pq_empty(&b->obq));
8306 CU_ASSERT(nghttp2_pq_empty(&c->obq));
8307 CU_ASSERT(nghttp2_pq_empty(&d->obq));
8308
8309 check_stream_dep_sib(c, root, d, NULL, NULL);
8310 check_stream_dep_sib(d, c, NULL, NULL, a);
8311 check_stream_dep_sib(a, c, b, d, NULL);
8312 check_stream_dep_sib(b, a, NULL, NULL, NULL);
8313
8314 nghttp2_session_del(session);
8315
8316 nghttp2_session_server_new(&session, &callbacks, NULL);
8317
8318 root = &session->root;
8319
8320 a = open_stream(session, 1);
8321 b = open_stream_with_dep(session, 3, a);
8322
8323 c = open_stream(session, 5);
8324 d = open_stream_with_dep(session, 7, c);
8325
8326 /* a c
8327 * | |
8328 * b d
8329 */
8330
8331 db = create_data_ob_item(mem);
8332
8333 nghttp2_stream_attach_item(b, db);
8334
8335 nghttp2_stream_dep_remove_subtree(c);
8336 CU_ASSERT(0 == nghttp2_stream_dep_insert_subtree(&session->root, c));
8337
8338 /*
8339 * c
8340 * |
8341 * d--a
8342 * |
8343 * b
8344 */
8345
8346 CU_ASSERT(c->queued);
8347 CU_ASSERT(a->queued);
8348 CU_ASSERT(b->queued);
8349 CU_ASSERT(!d->queued);
8350
8351 CU_ASSERT(1 == nghttp2_pq_size(&a->obq));
8352 CU_ASSERT(1 == nghttp2_pq_size(&c->obq));
8353 CU_ASSERT(nghttp2_pq_empty(&d->obq));
8354
8355 check_stream_dep_sib(c, root, d, NULL, NULL);
8356 check_stream_dep_sib(d, c, NULL, NULL, a);
8357 check_stream_dep_sib(a, c, b, d, NULL);
8358 check_stream_dep_sib(b, a, NULL, NULL, NULL);
8359
8360 nghttp2_session_del(session);
8361
8362 nghttp2_session_server_new(&session, &callbacks, NULL);
8363
8364 root = &session->root;
8365
8366 a = open_stream(session, 1);
8367 b = open_stream_with_dep(session, 3, a);
8368
8369 c = open_stream(session, 5);
8370 d = open_stream_with_dep(session, 7, c);
8371
8372 /* a c
8373 * | |
8374 * b d
8375 */
8376
8377 db = create_data_ob_item(mem);
8378 dc = create_data_ob_item(mem);
8379
8380 nghttp2_stream_attach_item(b, db);
8381 nghttp2_stream_attach_item(c, dc);
8382
8383 nghttp2_stream_dep_remove_subtree(c);
8384 CU_ASSERT(0 == nghttp2_stream_dep_insert_subtree(&session->root, c));
8385
8386 /*
8387 * c
8388 * |
8389 * d--a
8390 * |
8391 * b
8392 */
8393
8394 CU_ASSERT(c->queued);
8395 CU_ASSERT(a->queued);
8396 CU_ASSERT(b->queued);
8397 CU_ASSERT(!d->queued);
8398
8399 check_stream_dep_sib(c, root, d, NULL, NULL);
8400 check_stream_dep_sib(d, c, NULL, NULL, a);
8401 check_stream_dep_sib(a, c, b, d, NULL);
8402 check_stream_dep_sib(b, a, NULL, NULL, NULL);
8403
8404 nghttp2_session_del(session);
8405 }
8406
test_nghttp2_session_stream_attach_item(void)8407 void test_nghttp2_session_stream_attach_item(void) {
8408 nghttp2_session *session;
8409 nghttp2_session_callbacks callbacks;
8410 nghttp2_stream *a, *b, *c, *d, *e;
8411 nghttp2_outbound_item *da, *db, *dc, *dd;
8412 nghttp2_mem *mem;
8413
8414 mem = nghttp2_mem_default();
8415
8416 memset(&callbacks, 0, sizeof(callbacks));
8417
8418 nghttp2_session_server_new(&session, &callbacks, NULL);
8419
8420 a = open_stream(session, 1);
8421 b = open_stream_with_dep(session, 3, a);
8422 c = open_stream_with_dep(session, 5, a);
8423 d = open_stream_with_dep(session, 7, c);
8424
8425 /* a
8426 * |
8427 * c--b
8428 * |
8429 * d
8430 */
8431
8432 db = create_data_ob_item(mem);
8433
8434 nghttp2_stream_attach_item(b, db);
8435
8436 CU_ASSERT(a->queued);
8437 CU_ASSERT(b->queued);
8438 CU_ASSERT(!c->queued);
8439 CU_ASSERT(!d->queued);
8440
8441 CU_ASSERT(1 == nghttp2_pq_size(&a->obq));
8442
8443 /* Attach item to c */
8444 dc = create_data_ob_item(mem);
8445
8446 nghttp2_stream_attach_item(c, dc);
8447
8448 CU_ASSERT(a->queued);
8449 CU_ASSERT(b->queued);
8450 CU_ASSERT(c->queued);
8451 CU_ASSERT(!d->queued);
8452
8453 CU_ASSERT(2 == nghttp2_pq_size(&a->obq));
8454
8455 /* Attach item to a */
8456 da = create_data_ob_item(mem);
8457
8458 nghttp2_stream_attach_item(a, da);
8459
8460 CU_ASSERT(a->queued);
8461 CU_ASSERT(b->queued);
8462 CU_ASSERT(c->queued);
8463 CU_ASSERT(!d->queued);
8464
8465 CU_ASSERT(2 == nghttp2_pq_size(&a->obq));
8466
8467 /* Detach item from a */
8468 nghttp2_stream_detach_item(a);
8469
8470 CU_ASSERT(a->queued);
8471 CU_ASSERT(b->queued);
8472 CU_ASSERT(c->queued);
8473 CU_ASSERT(!d->queued);
8474
8475 CU_ASSERT(2 == nghttp2_pq_size(&a->obq));
8476
8477 /* Attach item to d */
8478 dd = create_data_ob_item(mem);
8479
8480 nghttp2_stream_attach_item(d, dd);
8481
8482 CU_ASSERT(a->queued);
8483 CU_ASSERT(b->queued);
8484 CU_ASSERT(c->queued);
8485 CU_ASSERT(d->queued);
8486
8487 CU_ASSERT(2 == nghttp2_pq_size(&a->obq));
8488 CU_ASSERT(1 == nghttp2_pq_size(&c->obq));
8489
8490 /* Detach item from c */
8491 nghttp2_stream_detach_item(c);
8492
8493 CU_ASSERT(a->queued);
8494 CU_ASSERT(b->queued);
8495 CU_ASSERT(c->queued);
8496 CU_ASSERT(d->queued);
8497
8498 CU_ASSERT(2 == nghttp2_pq_size(&a->obq));
8499 CU_ASSERT(1 == nghttp2_pq_size(&c->obq));
8500
8501 /* Detach item from b */
8502 nghttp2_stream_detach_item(b);
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(1 == nghttp2_pq_size(&a->obq));
8510
8511 /* exercises insertion */
8512 e = open_stream_with_dep_excl(session, 9, a);
8513
8514 /* a
8515 * |
8516 * e
8517 * |
8518 * c--b
8519 * |
8520 * d
8521 */
8522
8523 CU_ASSERT(a->queued);
8524 CU_ASSERT(e->queued);
8525 CU_ASSERT(!b->queued);
8526 CU_ASSERT(c->queued);
8527 CU_ASSERT(d->queued);
8528
8529 CU_ASSERT(1 == nghttp2_pq_size(&a->obq));
8530 CU_ASSERT(1 == nghttp2_pq_size(&e->obq));
8531 CU_ASSERT(nghttp2_pq_empty(&b->obq));
8532 CU_ASSERT(1 == nghttp2_pq_size(&c->obq));
8533 CU_ASSERT(nghttp2_pq_empty(&d->obq));
8534
8535 /* exercises deletion */
8536 nghttp2_stream_dep_remove(e);
8537
8538 /* a
8539 * |
8540 * c--b
8541 * |
8542 * d
8543 */
8544
8545 CU_ASSERT(a->queued);
8546 CU_ASSERT(!b->queued);
8547 CU_ASSERT(c->queued);
8548 CU_ASSERT(d->queued);
8549
8550 CU_ASSERT(1 == nghttp2_pq_size(&a->obq));
8551 CU_ASSERT(nghttp2_pq_empty(&b->obq));
8552 CU_ASSERT(1 == nghttp2_pq_size(&c->obq));
8553 CU_ASSERT(nghttp2_pq_empty(&d->obq));
8554
8555 /* e's weight 16 is distributed equally among c and b, both now have
8556 weight 8 each. */
8557 CU_ASSERT(8 == b->weight);
8558 CU_ASSERT(8 == c->weight);
8559
8560 /* da, db, dc have been detached */
8561 nghttp2_outbound_item_free(da, mem);
8562 nghttp2_outbound_item_free(db, mem);
8563 nghttp2_outbound_item_free(dc, mem);
8564 free(da);
8565 free(db);
8566 free(dc);
8567
8568 nghttp2_session_del(session);
8569
8570 nghttp2_session_server_new(&session, &callbacks, NULL);
8571
8572 a = open_stream(session, 1);
8573 b = open_stream_with_dep(session, 3, a);
8574 c = open_stream_with_dep(session, 5, a);
8575 d = open_stream_with_dep(session, 7, c);
8576
8577 /* a
8578 * |
8579 * c--b
8580 * |
8581 * d
8582 */
8583
8584 da = create_data_ob_item(mem);
8585 db = create_data_ob_item(mem);
8586 dc = create_data_ob_item(mem);
8587
8588 nghttp2_stream_attach_item(a, da);
8589 nghttp2_stream_attach_item(b, db);
8590 nghttp2_stream_attach_item(c, dc);
8591
8592 CU_ASSERT(a->queued);
8593 CU_ASSERT(b->queued);
8594 CU_ASSERT(c->queued);
8595 CU_ASSERT(!d->queued);
8596
8597 CU_ASSERT(2 == nghttp2_pq_size(&a->obq));
8598 CU_ASSERT(nghttp2_pq_empty(&b->obq));
8599 CU_ASSERT(nghttp2_pq_empty(&c->obq));
8600 CU_ASSERT(nghttp2_pq_empty(&d->obq));
8601
8602 /* Detach item from a */
8603 nghttp2_stream_detach_item(a);
8604
8605 CU_ASSERT(a->queued);
8606 CU_ASSERT(b->queued);
8607 CU_ASSERT(c->queued);
8608 CU_ASSERT(!d->queued);
8609
8610 CU_ASSERT(2 == nghttp2_pq_size(&a->obq));
8611 CU_ASSERT(nghttp2_pq_empty(&b->obq));
8612 CU_ASSERT(nghttp2_pq_empty(&c->obq));
8613 CU_ASSERT(nghttp2_pq_empty(&d->obq));
8614
8615 /* da has been detached */
8616 nghttp2_outbound_item_free(da, mem);
8617 free(da);
8618
8619 nghttp2_session_del(session);
8620 }
8621
test_nghttp2_session_stream_attach_item_subtree(void)8622 void test_nghttp2_session_stream_attach_item_subtree(void) {
8623 nghttp2_session *session;
8624 nghttp2_session_callbacks callbacks;
8625 nghttp2_stream *a, *b, *c, *d, *e, *f;
8626 nghttp2_outbound_item *da, *db, *dd, *de;
8627 nghttp2_mem *mem;
8628
8629 mem = nghttp2_mem_default();
8630
8631 memset(&callbacks, 0, sizeof(callbacks));
8632
8633 nghttp2_session_server_new(&session, &callbacks, NULL);
8634
8635 a = open_stream(session, 1);
8636 b = open_stream_with_dep(session, 3, a);
8637 c = open_stream_with_dep(session, 5, a);
8638 d = open_stream_with_dep(session, 7, c);
8639
8640 e = open_stream_with_dep_weight(session, 9, 32, &session->root);
8641 f = open_stream_with_dep(session, 11, e);
8642
8643 /*
8644 * a e
8645 * | |
8646 * c--b f
8647 * |
8648 * d
8649 */
8650
8651 de = create_data_ob_item(mem);
8652
8653 nghttp2_stream_attach_item(e, de);
8654
8655 db = create_data_ob_item(mem);
8656
8657 nghttp2_stream_attach_item(b, db);
8658
8659 CU_ASSERT(a->queued);
8660 CU_ASSERT(b->queued);
8661 CU_ASSERT(!c->queued);
8662 CU_ASSERT(!d->queued);
8663 CU_ASSERT(e->queued);
8664 CU_ASSERT(!f->queued);
8665
8666 CU_ASSERT(1 == nghttp2_pq_size(&a->obq));
8667 CU_ASSERT(nghttp2_pq_empty(&b->obq));
8668 CU_ASSERT(nghttp2_pq_empty(&c->obq));
8669 CU_ASSERT(nghttp2_pq_empty(&d->obq));
8670 CU_ASSERT(nghttp2_pq_empty(&e->obq));
8671 CU_ASSERT(nghttp2_pq_empty(&f->obq));
8672
8673 /* Insert subtree e under a */
8674
8675 nghttp2_stream_dep_remove_subtree(e);
8676 nghttp2_stream_dep_insert_subtree(a, e);
8677
8678 /*
8679 * a
8680 * |
8681 * e
8682 * |
8683 * f--c--b
8684 * |
8685 * d
8686 */
8687
8688 CU_ASSERT(a->queued);
8689 CU_ASSERT(b->queued);
8690 CU_ASSERT(!c->queued);
8691 CU_ASSERT(!d->queued);
8692 CU_ASSERT(e->queued);
8693 CU_ASSERT(!f->queued);
8694
8695 CU_ASSERT(1 == nghttp2_pq_size(&a->obq));
8696 CU_ASSERT(nghttp2_pq_empty(&b->obq));
8697 CU_ASSERT(nghttp2_pq_empty(&c->obq));
8698 CU_ASSERT(nghttp2_pq_empty(&d->obq));
8699 CU_ASSERT(1 == nghttp2_pq_size(&e->obq));
8700 CU_ASSERT(nghttp2_pq_empty(&f->obq));
8701
8702 /* Remove subtree b */
8703
8704 nghttp2_stream_dep_remove_subtree(b);
8705
8706 CU_ASSERT(0 == nghttp2_stream_dep_add_subtree(&session->root, b));
8707
8708 /*
8709 * a b
8710 * |
8711 * e
8712 * |
8713 * f--c
8714 * |
8715 * d
8716 */
8717
8718 CU_ASSERT(a->queued);
8719 CU_ASSERT(b->queued);
8720 CU_ASSERT(!c->queued);
8721 CU_ASSERT(!d->queued);
8722 CU_ASSERT(e->queued);
8723 CU_ASSERT(!f->queued);
8724
8725 CU_ASSERT(1 == nghttp2_pq_size(&a->obq));
8726 CU_ASSERT(nghttp2_pq_empty(&b->obq));
8727 CU_ASSERT(nghttp2_pq_empty(&c->obq));
8728 CU_ASSERT(nghttp2_pq_empty(&d->obq));
8729 CU_ASSERT(nghttp2_pq_empty(&e->obq));
8730 CU_ASSERT(nghttp2_pq_empty(&f->obq));
8731
8732 /* Remove subtree a, and add it to root again */
8733
8734 nghttp2_stream_dep_remove_subtree(a);
8735
8736 CU_ASSERT(0 == nghttp2_stream_dep_add_subtree(&session->root, a));
8737
8738 CU_ASSERT(a->queued);
8739 CU_ASSERT(b->queued);
8740 CU_ASSERT(!c->queued);
8741 CU_ASSERT(!d->queued);
8742 CU_ASSERT(e->queued);
8743 CU_ASSERT(!f->queued);
8744
8745 CU_ASSERT(1 == nghttp2_pq_size(&a->obq));
8746 CU_ASSERT(nghttp2_pq_empty(&b->obq));
8747 CU_ASSERT(nghttp2_pq_empty(&c->obq));
8748 CU_ASSERT(nghttp2_pq_empty(&d->obq));
8749 CU_ASSERT(nghttp2_pq_empty(&e->obq));
8750 CU_ASSERT(nghttp2_pq_empty(&f->obq));
8751
8752 /* Remove subtree c */
8753
8754 nghttp2_stream_dep_remove_subtree(c);
8755
8756 CU_ASSERT(0 == nghttp2_stream_dep_add_subtree(&session->root, c));
8757
8758 /*
8759 * a b c
8760 * | |
8761 * e d
8762 * |
8763 * f
8764 */
8765
8766 CU_ASSERT(a->queued);
8767 CU_ASSERT(b->queued);
8768 CU_ASSERT(!c->queued);
8769 CU_ASSERT(!d->queued);
8770 CU_ASSERT(e->queued);
8771 CU_ASSERT(!f->queued);
8772
8773 CU_ASSERT(1 == nghttp2_pq_size(&a->obq));
8774 CU_ASSERT(nghttp2_pq_empty(&b->obq));
8775 CU_ASSERT(nghttp2_pq_empty(&c->obq));
8776 CU_ASSERT(nghttp2_pq_empty(&d->obq));
8777 CU_ASSERT(nghttp2_pq_empty(&e->obq));
8778 CU_ASSERT(nghttp2_pq_empty(&f->obq));
8779
8780 dd = create_data_ob_item(mem);
8781
8782 nghttp2_stream_attach_item(d, dd);
8783
8784 /* Add subtree c to a */
8785
8786 nghttp2_stream_dep_remove_subtree(c);
8787 nghttp2_stream_dep_add_subtree(a, c);
8788
8789 /*
8790 * a b
8791 * |
8792 * c--e
8793 * | |
8794 * d f
8795 */
8796
8797 CU_ASSERT(a->queued);
8798 CU_ASSERT(b->queued);
8799 CU_ASSERT(c->queued);
8800 CU_ASSERT(d->queued);
8801 CU_ASSERT(e->queued);
8802 CU_ASSERT(!f->queued);
8803
8804 CU_ASSERT(2 == nghttp2_pq_size(&a->obq));
8805 CU_ASSERT(nghttp2_pq_empty(&b->obq));
8806 CU_ASSERT(1 == nghttp2_pq_size(&c->obq));
8807 CU_ASSERT(nghttp2_pq_empty(&d->obq));
8808 CU_ASSERT(nghttp2_pq_empty(&e->obq));
8809 CU_ASSERT(nghttp2_pq_empty(&f->obq));
8810
8811 /* Insert b under a */
8812
8813 nghttp2_stream_dep_remove_subtree(b);
8814 nghttp2_stream_dep_insert_subtree(a, b);
8815
8816 /*
8817 * a
8818 * |
8819 * b
8820 * |
8821 * c--e
8822 * | |
8823 * d f
8824 */
8825
8826 CU_ASSERT(a->queued);
8827 CU_ASSERT(b->queued);
8828 CU_ASSERT(c->queued);
8829 CU_ASSERT(d->queued);
8830 CU_ASSERT(e->queued);
8831 CU_ASSERT(!f->queued);
8832
8833 CU_ASSERT(1 == nghttp2_pq_size(&a->obq));
8834 CU_ASSERT(2 == nghttp2_pq_size(&b->obq));
8835 CU_ASSERT(1 == nghttp2_pq_size(&c->obq));
8836 CU_ASSERT(nghttp2_pq_empty(&d->obq));
8837 CU_ASSERT(nghttp2_pq_empty(&e->obq));
8838 CU_ASSERT(nghttp2_pq_empty(&f->obq));
8839
8840 /* Remove subtree b */
8841
8842 nghttp2_stream_dep_remove_subtree(b);
8843 CU_ASSERT(0 == nghttp2_stream_dep_add_subtree(&session->root, b));
8844
8845 /*
8846 * b a
8847 * |
8848 * e--c
8849 * | |
8850 * f d
8851 */
8852
8853 CU_ASSERT(!a->queued);
8854 CU_ASSERT(b->queued);
8855 CU_ASSERT(c->queued);
8856 CU_ASSERT(d->queued);
8857 CU_ASSERT(e->queued);
8858 CU_ASSERT(!f->queued);
8859
8860 CU_ASSERT(nghttp2_pq_empty(&a->obq));
8861 CU_ASSERT(2 == nghttp2_pq_size(&b->obq));
8862 CU_ASSERT(1 == nghttp2_pq_size(&c->obq));
8863 CU_ASSERT(nghttp2_pq_empty(&d->obq));
8864 CU_ASSERT(nghttp2_pq_empty(&e->obq));
8865 CU_ASSERT(nghttp2_pq_empty(&f->obq));
8866
8867 /* Remove subtree c, and detach item from b, and then re-add
8868 subtree c under b */
8869
8870 nghttp2_stream_dep_remove_subtree(c);
8871 nghttp2_stream_detach_item(b);
8872 nghttp2_stream_dep_add_subtree(b, c);
8873
8874 /*
8875 * b a
8876 * |
8877 * e--c
8878 * | |
8879 * f d
8880 */
8881
8882 CU_ASSERT(!a->queued);
8883 CU_ASSERT(b->queued);
8884 CU_ASSERT(c->queued);
8885 CU_ASSERT(d->queued);
8886 CU_ASSERT(e->queued);
8887 CU_ASSERT(!f->queued);
8888
8889 CU_ASSERT(nghttp2_pq_empty(&a->obq));
8890 CU_ASSERT(2 == nghttp2_pq_size(&b->obq));
8891 CU_ASSERT(1 == nghttp2_pq_size(&c->obq));
8892 CU_ASSERT(nghttp2_pq_empty(&d->obq));
8893 CU_ASSERT(nghttp2_pq_empty(&e->obq));
8894 CU_ASSERT(nghttp2_pq_empty(&f->obq));
8895
8896 /* Attach data to a, and add subtree a under b */
8897
8898 da = create_data_ob_item(mem);
8899 nghttp2_stream_attach_item(a, da);
8900 nghttp2_stream_dep_remove_subtree(a);
8901 nghttp2_stream_dep_add_subtree(b, a);
8902
8903 /*
8904 * b
8905 * |
8906 * a--e--c
8907 * | |
8908 * f d
8909 */
8910
8911 CU_ASSERT(a->queued);
8912 CU_ASSERT(b->queued);
8913 CU_ASSERT(c->queued);
8914 CU_ASSERT(d->queued);
8915 CU_ASSERT(e->queued);
8916 CU_ASSERT(!f->queued);
8917
8918 CU_ASSERT(nghttp2_pq_empty(&a->obq));
8919 CU_ASSERT(3 == nghttp2_pq_size(&b->obq));
8920 CU_ASSERT(1 == nghttp2_pq_size(&c->obq));
8921 CU_ASSERT(nghttp2_pq_empty(&d->obq));
8922 CU_ASSERT(nghttp2_pq_empty(&e->obq));
8923 CU_ASSERT(nghttp2_pq_empty(&f->obq));
8924
8925 /* Remove subtree c, and add under f */
8926 nghttp2_stream_dep_remove_subtree(c);
8927 nghttp2_stream_dep_insert_subtree(f, c);
8928
8929 /*
8930 * b
8931 * |
8932 * a--e
8933 * |
8934 * f
8935 * |
8936 * c
8937 * |
8938 * d
8939 */
8940
8941 CU_ASSERT(a->queued);
8942 CU_ASSERT(b->queued);
8943 CU_ASSERT(c->queued);
8944 CU_ASSERT(d->queued);
8945 CU_ASSERT(e->queued);
8946 CU_ASSERT(f->queued);
8947
8948 CU_ASSERT(nghttp2_pq_empty(&a->obq));
8949 CU_ASSERT(2 == nghttp2_pq_size(&b->obq));
8950 CU_ASSERT(1 == nghttp2_pq_size(&c->obq));
8951 CU_ASSERT(nghttp2_pq_empty(&d->obq));
8952 CU_ASSERT(1 == nghttp2_pq_size(&e->obq));
8953 CU_ASSERT(1 == nghttp2_pq_size(&f->obq));
8954
8955 /* db has been detached */
8956 nghttp2_outbound_item_free(db, mem);
8957 free(db);
8958
8959 nghttp2_session_del(session);
8960 }
8961
test_nghttp2_session_stream_get_state(void)8962 void test_nghttp2_session_stream_get_state(void) {
8963 nghttp2_session *session;
8964 nghttp2_session_callbacks callbacks;
8965 nghttp2_mem *mem;
8966 nghttp2_hd_deflater deflater;
8967 nghttp2_bufs bufs;
8968 nghttp2_buf *buf;
8969 nghttp2_stream *stream;
8970 ssize_t rv;
8971 nghttp2_data_provider data_prd;
8972 nghttp2_frame frame;
8973
8974 mem = nghttp2_mem_default();
8975 frame_pack_bufs_init(&bufs);
8976 memset(&data_prd, 0, sizeof(data_prd));
8977
8978 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
8979 callbacks.send_callback = null_send_callback;
8980
8981 nghttp2_session_server_new(&session, &callbacks, NULL);
8982 nghttp2_hd_deflate_init(&deflater, mem);
8983
8984 CU_ASSERT(NGHTTP2_STREAM_STATE_IDLE ==
8985 nghttp2_stream_get_state(nghttp2_session_get_root_stream(session)));
8986
8987 /* stream 1 HEADERS; without END_STREAM flag set */
8988 pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, reqnv,
8989 ARRLEN(reqnv), mem);
8990
8991 buf = &bufs.head->buf;
8992 rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
8993
8994 CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv);
8995
8996 stream = nghttp2_session_find_stream(session, 1);
8997
8998 CU_ASSERT(NULL != stream);
8999 CU_ASSERT(1 == stream->stream_id);
9000 CU_ASSERT(NGHTTP2_STREAM_STATE_OPEN == nghttp2_stream_get_state(stream));
9001
9002 nghttp2_bufs_reset(&bufs);
9003
9004 /* stream 3 HEADERS; with END_STREAM flag set */
9005 pack_headers(&bufs, &deflater, 3,
9006 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM, reqnv,
9007 ARRLEN(reqnv), mem);
9008
9009 buf = &bufs.head->buf;
9010 rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
9011
9012 CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv);
9013
9014 stream = nghttp2_session_find_stream(session, 3);
9015
9016 CU_ASSERT(NULL != stream);
9017 CU_ASSERT(3 == stream->stream_id);
9018 CU_ASSERT(NGHTTP2_STREAM_STATE_HALF_CLOSED_REMOTE ==
9019 nghttp2_stream_get_state(stream));
9020
9021 nghttp2_bufs_reset(&bufs);
9022
9023 /* Respond to stream 1 */
9024 nghttp2_submit_response(session, 1, resnv, ARRLEN(resnv), NULL);
9025
9026 rv = nghttp2_session_send(session);
9027
9028 CU_ASSERT(0 == rv);
9029
9030 stream = nghttp2_session_find_stream(session, 1);
9031
9032 CU_ASSERT(NGHTTP2_STREAM_STATE_HALF_CLOSED_LOCAL ==
9033 nghttp2_stream_get_state(stream));
9034
9035 /* Respond to stream 3 */
9036 nghttp2_submit_response(session, 3, resnv, ARRLEN(resnv), NULL);
9037
9038 rv = nghttp2_session_send(session);
9039
9040 CU_ASSERT(0 == rv);
9041
9042 stream = nghttp2_session_find_stream(session, 3);
9043
9044 CU_ASSERT(NGHTTP2_STREAM_STATE_CLOSED == nghttp2_stream_get_state(stream));
9045
9046 /* stream 5 HEADERS; with END_STREAM flag set */
9047 pack_headers(&bufs, &deflater, 5,
9048 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM, 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 nghttp2_bufs_reset(&bufs);
9057
9058 /* Push stream 2 associated to stream 5 */
9059 rv = nghttp2_submit_push_promise(session, NGHTTP2_FLAG_NONE, 5, reqnv,
9060 ARRLEN(reqnv), NULL);
9061
9062 CU_ASSERT(2 == rv);
9063
9064 rv = nghttp2_session_send(session);
9065
9066 CU_ASSERT(0 == rv);
9067
9068 stream = nghttp2_session_find_stream(session, 2);
9069
9070 CU_ASSERT(NGHTTP2_STREAM_STATE_RESERVED_LOCAL ==
9071 nghttp2_stream_get_state(stream));
9072
9073 /* Send resposne to push stream 2 with END_STREAM set */
9074 nghttp2_submit_response(session, 2, resnv, ARRLEN(resnv), NULL);
9075
9076 rv = nghttp2_session_send(session);
9077
9078 CU_ASSERT(0 == rv);
9079
9080 stream = nghttp2_session_find_stream(session, 2);
9081
9082 /* At server, pushed stream object is not retained after closed */
9083 CU_ASSERT(NULL == stream);
9084
9085 /* Push stream 4 associated to stream 5 */
9086 rv = nghttp2_submit_push_promise(session, NGHTTP2_FLAG_NONE, 5, reqnv,
9087 ARRLEN(reqnv), NULL);
9088
9089 CU_ASSERT(4 == rv);
9090
9091 rv = nghttp2_session_send(session);
9092
9093 CU_ASSERT(0 == rv);
9094
9095 stream = nghttp2_session_find_stream(session, 4);
9096
9097 CU_ASSERT(NGHTTP2_STREAM_STATE_RESERVED_LOCAL ==
9098 nghttp2_stream_get_state(stream));
9099
9100 /* Send response to push stream 4 without closing */
9101 data_prd.read_callback = defer_data_source_read_callback;
9102
9103 nghttp2_submit_response(session, 4, resnv, ARRLEN(resnv), &data_prd);
9104
9105 rv = nghttp2_session_send(session);
9106
9107 CU_ASSERT(0 == rv);
9108
9109 stream = nghttp2_session_find_stream(session, 4);
9110
9111 CU_ASSERT(NGHTTP2_STREAM_STATE_HALF_CLOSED_REMOTE ==
9112 nghttp2_stream_get_state(stream));
9113
9114 /* Create idle stream by PRIORITY frame */
9115 nghttp2_frame_priority_init(&frame.priority, 7, &pri_spec_default);
9116
9117 rv = nghttp2_frame_pack_priority(&bufs, &frame.priority);
9118
9119 CU_ASSERT(0 == rv);
9120
9121 nghttp2_frame_priority_free(&frame.priority);
9122
9123 buf = &bufs.head->buf;
9124 rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
9125
9126 CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv);
9127
9128 stream = nghttp2_session_find_stream(session, 7);
9129
9130 CU_ASSERT(NGHTTP2_STREAM_STATE_IDLE == nghttp2_stream_get_state(stream));
9131
9132 nghttp2_bufs_reset(&bufs);
9133
9134 nghttp2_hd_deflate_free(&deflater);
9135 nghttp2_session_del(session);
9136
9137 /* Test for client side */
9138
9139 nghttp2_session_client_new(&session, &callbacks, NULL);
9140 nghttp2_hd_deflate_init(&deflater, mem);
9141
9142 nghttp2_submit_request(session, NULL, reqnv, ARRLEN(reqnv), NULL, NULL);
9143
9144 rv = nghttp2_session_send(session);
9145
9146 CU_ASSERT(0 == rv);
9147
9148 /* Receive PUSH_PROMISE 2 associated to stream 1 */
9149 pack_push_promise(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, 2, reqnv,
9150 ARRLEN(reqnv), mem);
9151
9152 buf = &bufs.head->buf;
9153 rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
9154
9155 CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv);
9156
9157 stream = nghttp2_session_find_stream(session, 2);
9158
9159 CU_ASSERT(NGHTTP2_STREAM_STATE_RESERVED_REMOTE ==
9160 nghttp2_stream_get_state(stream));
9161
9162 nghttp2_bufs_reset(&bufs);
9163
9164 /* Receive push response for stream 2 without END_STREAM set */
9165 pack_headers(&bufs, &deflater, 2, NGHTTP2_FLAG_END_HEADERS, resnv,
9166 ARRLEN(resnv), mem);
9167
9168 buf = &bufs.head->buf;
9169 rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
9170
9171 CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv);
9172
9173 stream = nghttp2_session_find_stream(session, 2);
9174
9175 CU_ASSERT(NGHTTP2_STREAM_STATE_HALF_CLOSED_LOCAL ==
9176 nghttp2_stream_get_state(stream));
9177
9178 nghttp2_bufs_reset(&bufs);
9179
9180 nghttp2_hd_deflate_free(&deflater);
9181 nghttp2_session_del(session);
9182
9183 nghttp2_bufs_free(&bufs);
9184 }
9185
test_nghttp2_session_stream_get_something(void)9186 void test_nghttp2_session_stream_get_something(void) {
9187 nghttp2_session *session;
9188 nghttp2_session_callbacks callbacks;
9189 nghttp2_stream *a, *b, *c;
9190
9191 memset(&callbacks, 0, sizeof(callbacks));
9192
9193 nghttp2_session_server_new(&session, &callbacks, NULL);
9194
9195 a = open_stream(session, 1);
9196
9197 CU_ASSERT(nghttp2_session_get_root_stream(session) ==
9198 nghttp2_stream_get_parent(a));
9199 CU_ASSERT(NULL == nghttp2_stream_get_previous_sibling(a));
9200 CU_ASSERT(NULL == nghttp2_stream_get_next_sibling(a));
9201 CU_ASSERT(NULL == nghttp2_stream_get_first_child(a));
9202
9203 b = open_stream_with_dep(session, 3, a);
9204 c = open_stream_with_dep_weight(session, 5, 11, a);
9205
9206 CU_ASSERT(a == nghttp2_stream_get_parent(c));
9207 CU_ASSERT(a == nghttp2_stream_get_parent(b));
9208
9209 CU_ASSERT(c == nghttp2_stream_get_first_child(a));
9210
9211 CU_ASSERT(b == nghttp2_stream_get_next_sibling(c));
9212 CU_ASSERT(c == nghttp2_stream_get_previous_sibling(b));
9213
9214 CU_ASSERT(27 == nghttp2_stream_get_sum_dependency_weight(a));
9215
9216 CU_ASSERT(11 == nghttp2_stream_get_weight(c));
9217 CU_ASSERT(5 == nghttp2_stream_get_stream_id(c));
9218 CU_ASSERT(0 == nghttp2_stream_get_stream_id(&session->root));
9219
9220 nghttp2_session_del(session);
9221 }
9222
test_nghttp2_session_find_stream(void)9223 void test_nghttp2_session_find_stream(void) {
9224 nghttp2_session *session;
9225 nghttp2_session_callbacks callbacks;
9226 nghttp2_stream *stream;
9227
9228 memset(&callbacks, 0, sizeof(callbacks));
9229
9230 nghttp2_session_server_new(&session, &callbacks, NULL);
9231
9232 open_recv_stream(session, 1);
9233
9234 stream = nghttp2_session_find_stream(session, 1);
9235
9236 CU_ASSERT(NULL != stream);
9237 CU_ASSERT(1 == stream->stream_id);
9238
9239 stream = nghttp2_session_find_stream(session, 0);
9240
9241 CU_ASSERT(&session->root == stream);
9242 CU_ASSERT(0 == stream->stream_id);
9243
9244 stream = nghttp2_session_find_stream(session, 2);
9245
9246 CU_ASSERT(NULL == stream);
9247
9248 nghttp2_session_del(session);
9249 }
9250
test_nghttp2_session_keep_closed_stream(void)9251 void test_nghttp2_session_keep_closed_stream(void) {
9252 nghttp2_session *session;
9253 nghttp2_session_callbacks callbacks;
9254 const size_t max_concurrent_streams = 5;
9255 nghttp2_settings_entry iv = {NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS,
9256 (uint32_t)max_concurrent_streams};
9257 size_t i;
9258
9259 memset(&callbacks, 0, sizeof(callbacks));
9260 callbacks.send_callback = null_send_callback;
9261
9262 nghttp2_session_server_new(&session, &callbacks, NULL);
9263
9264 nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, &iv, 1);
9265
9266 for (i = 0; i < max_concurrent_streams; ++i) {
9267 open_recv_stream(session, (int32_t)i * 2 + 1);
9268 }
9269
9270 CU_ASSERT(0 == session->num_closed_streams);
9271
9272 nghttp2_session_close_stream(session, 1, NGHTTP2_NO_ERROR);
9273
9274 CU_ASSERT(1 == session->num_closed_streams);
9275 CU_ASSERT(1 == session->closed_stream_tail->stream_id);
9276 CU_ASSERT(session->closed_stream_tail == session->closed_stream_head);
9277
9278 nghttp2_session_close_stream(session, 5, NGHTTP2_NO_ERROR);
9279
9280 CU_ASSERT(2 == session->num_closed_streams);
9281 CU_ASSERT(5 == session->closed_stream_tail->stream_id);
9282 CU_ASSERT(1 == session->closed_stream_head->stream_id);
9283 CU_ASSERT(session->closed_stream_head ==
9284 session->closed_stream_tail->closed_prev);
9285 CU_ASSERT(NULL == session->closed_stream_tail->closed_next);
9286 CU_ASSERT(session->closed_stream_tail ==
9287 session->closed_stream_head->closed_next);
9288 CU_ASSERT(NULL == session->closed_stream_head->closed_prev);
9289
9290 open_recv_stream(session, 11);
9291 nghttp2_session_adjust_closed_stream(session);
9292
9293 CU_ASSERT(1 == session->num_closed_streams);
9294 CU_ASSERT(5 == session->closed_stream_tail->stream_id);
9295 CU_ASSERT(session->closed_stream_tail == session->closed_stream_head);
9296 CU_ASSERT(NULL == session->closed_stream_head->closed_prev);
9297 CU_ASSERT(NULL == session->closed_stream_head->closed_next);
9298
9299 open_recv_stream(session, 13);
9300 nghttp2_session_adjust_closed_stream(session);
9301
9302 CU_ASSERT(0 == session->num_closed_streams);
9303 CU_ASSERT(NULL == session->closed_stream_tail);
9304 CU_ASSERT(NULL == session->closed_stream_head);
9305
9306 nghttp2_session_close_stream(session, 3, NGHTTP2_NO_ERROR);
9307
9308 CU_ASSERT(1 == session->num_closed_streams);
9309 CU_ASSERT(3 == session->closed_stream_head->stream_id);
9310
9311 /* server initiated stream is not counted to max concurrent limit */
9312 open_sent_stream(session, 2);
9313 nghttp2_session_adjust_closed_stream(session);
9314
9315 CU_ASSERT(1 == session->num_closed_streams);
9316 CU_ASSERT(3 == session->closed_stream_head->stream_id);
9317
9318 nghttp2_session_close_stream(session, 2, NGHTTP2_NO_ERROR);
9319
9320 CU_ASSERT(1 == session->num_closed_streams);
9321 CU_ASSERT(3 == session->closed_stream_head->stream_id);
9322
9323 nghttp2_session_del(session);
9324 }
9325
test_nghttp2_session_keep_idle_stream(void)9326 void test_nghttp2_session_keep_idle_stream(void) {
9327 nghttp2_session *session;
9328 nghttp2_session_callbacks callbacks;
9329 const size_t max_concurrent_streams = 1;
9330 nghttp2_settings_entry iv = {NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS,
9331 (uint32_t)max_concurrent_streams};
9332 int i;
9333 int32_t stream_id;
9334
9335 memset(&callbacks, 0, sizeof(callbacks));
9336 callbacks.send_callback = null_send_callback;
9337
9338 nghttp2_session_server_new(&session, &callbacks, NULL);
9339
9340 nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, &iv, 1);
9341
9342 /* We at least allow NGHTTP2_MIN_IDLE_STREAM idle streams even if
9343 max concurrent streams is very low. */
9344 for (i = 0; i < NGHTTP2_MIN_IDLE_STREAMS; ++i) {
9345 open_recv_stream2(session, i * 2 + 1, NGHTTP2_STREAM_IDLE);
9346 nghttp2_session_adjust_idle_stream(session);
9347 }
9348
9349 CU_ASSERT(NGHTTP2_MIN_IDLE_STREAMS == session->num_idle_streams);
9350
9351 stream_id = (NGHTTP2_MIN_IDLE_STREAMS - 1) * 2 + 1;
9352 CU_ASSERT(1 == session->idle_stream_head->stream_id);
9353 CU_ASSERT(stream_id == session->idle_stream_tail->stream_id);
9354
9355 stream_id += 2;
9356
9357 open_recv_stream2(session, stream_id, NGHTTP2_STREAM_IDLE);
9358 nghttp2_session_adjust_idle_stream(session);
9359
9360 CU_ASSERT(NGHTTP2_MIN_IDLE_STREAMS == session->num_idle_streams);
9361 CU_ASSERT(3 == session->idle_stream_head->stream_id);
9362 CU_ASSERT(stream_id == session->idle_stream_tail->stream_id);
9363
9364 nghttp2_session_del(session);
9365 }
9366
test_nghttp2_session_detach_idle_stream(void)9367 void test_nghttp2_session_detach_idle_stream(void) {
9368 nghttp2_session *session;
9369 nghttp2_session_callbacks callbacks;
9370 int i;
9371 nghttp2_stream *stream;
9372
9373 memset(&callbacks, 0, sizeof(callbacks));
9374 callbacks.send_callback = null_send_callback;
9375
9376 nghttp2_session_server_new(&session, &callbacks, NULL);
9377
9378 for (i = 1; i <= 3; ++i) {
9379 nghttp2_session_open_stream(session, i, NGHTTP2_STREAM_FLAG_NONE,
9380 &pri_spec_default, NGHTTP2_STREAM_IDLE, NULL);
9381 }
9382
9383 CU_ASSERT(3 == session->num_idle_streams);
9384
9385 /* Detach middle stream */
9386 stream = nghttp2_session_get_stream_raw(session, 2);
9387
9388 CU_ASSERT(session->idle_stream_head == stream->closed_prev);
9389 CU_ASSERT(session->idle_stream_tail == stream->closed_next);
9390 CU_ASSERT(stream == session->idle_stream_head->closed_next);
9391 CU_ASSERT(stream == session->idle_stream_tail->closed_prev);
9392
9393 nghttp2_session_detach_idle_stream(session, stream);
9394
9395 CU_ASSERT(2 == session->num_idle_streams);
9396
9397 CU_ASSERT(NULL == stream->closed_prev);
9398 CU_ASSERT(NULL == stream->closed_next);
9399
9400 CU_ASSERT(session->idle_stream_head ==
9401 session->idle_stream_tail->closed_prev);
9402 CU_ASSERT(session->idle_stream_tail ==
9403 session->idle_stream_head->closed_next);
9404
9405 /* Detach head stream */
9406 stream = session->idle_stream_head;
9407
9408 nghttp2_session_detach_idle_stream(session, stream);
9409
9410 CU_ASSERT(1 == session->num_idle_streams);
9411
9412 CU_ASSERT(session->idle_stream_head == session->idle_stream_tail);
9413 CU_ASSERT(NULL == session->idle_stream_head->closed_prev);
9414 CU_ASSERT(NULL == session->idle_stream_head->closed_next);
9415
9416 /* Detach last stream */
9417
9418 stream = session->idle_stream_head;
9419
9420 nghttp2_session_detach_idle_stream(session, stream);
9421
9422 CU_ASSERT(0 == session->num_idle_streams);
9423
9424 CU_ASSERT(NULL == session->idle_stream_head);
9425 CU_ASSERT(NULL == session->idle_stream_tail);
9426
9427 for (i = 4; i <= 5; ++i) {
9428 nghttp2_session_open_stream(session, i, NGHTTP2_STREAM_FLAG_NONE,
9429 &pri_spec_default, NGHTTP2_STREAM_IDLE, NULL);
9430 }
9431
9432 CU_ASSERT(2 == session->num_idle_streams);
9433
9434 /* Detach tail stream */
9435
9436 stream = session->idle_stream_tail;
9437
9438 nghttp2_session_detach_idle_stream(session, stream);
9439
9440 CU_ASSERT(1 == session->num_idle_streams);
9441
9442 CU_ASSERT(session->idle_stream_head == session->idle_stream_tail);
9443 CU_ASSERT(NULL == session->idle_stream_head->closed_prev);
9444 CU_ASSERT(NULL == session->idle_stream_head->closed_next);
9445
9446 nghttp2_session_del(session);
9447 }
9448
test_nghttp2_session_large_dep_tree(void)9449 void test_nghttp2_session_large_dep_tree(void) {
9450 nghttp2_session *session;
9451 nghttp2_session_callbacks callbacks;
9452 size_t i;
9453 nghttp2_stream *dep_stream = NULL;
9454 nghttp2_stream *stream;
9455 int32_t stream_id;
9456
9457 memset(&callbacks, 0, sizeof(callbacks));
9458 callbacks.send_callback = null_send_callback;
9459
9460 nghttp2_session_server_new(&session, &callbacks, NULL);
9461
9462 stream_id = 1;
9463 for (i = 0; i < 250; ++i, stream_id += 2) {
9464 dep_stream = open_stream_with_dep(session, stream_id, dep_stream);
9465 }
9466
9467 stream_id = 1;
9468 for (i = 0; i < 250; ++i, stream_id += 2) {
9469 stream = nghttp2_session_get_stream(session, stream_id);
9470 CU_ASSERT(nghttp2_stream_dep_find_ancestor(stream, &session->root));
9471 CU_ASSERT(nghttp2_stream_in_dep_tree(stream));
9472 }
9473
9474 nghttp2_session_del(session);
9475 }
9476
test_nghttp2_session_graceful_shutdown(void)9477 void test_nghttp2_session_graceful_shutdown(void) {
9478 nghttp2_session *session;
9479 nghttp2_session_callbacks callbacks;
9480 my_user_data ud;
9481
9482 memset(&callbacks, 0, sizeof(callbacks));
9483 callbacks.send_callback = null_send_callback;
9484 callbacks.on_frame_send_callback = on_frame_send_callback;
9485 callbacks.on_stream_close_callback = on_stream_close_callback;
9486
9487 nghttp2_session_server_new(&session, &callbacks, &ud);
9488
9489 open_recv_stream(session, 301);
9490 open_sent_stream(session, 302);
9491 open_recv_stream(session, 309);
9492 open_recv_stream(session, 311);
9493 open_recv_stream(session, 319);
9494
9495 CU_ASSERT(0 == nghttp2_submit_shutdown_notice(session));
9496
9497 ud.frame_send_cb_called = 0;
9498
9499 CU_ASSERT(0 == nghttp2_session_send(session));
9500
9501 CU_ASSERT(1 == ud.frame_send_cb_called);
9502 CU_ASSERT((1u << 31) - 1 == session->local_last_stream_id);
9503
9504 CU_ASSERT(0 == nghttp2_submit_goaway(session, NGHTTP2_FLAG_NONE, 311,
9505 NGHTTP2_NO_ERROR, NULL, 0));
9506
9507 ud.frame_send_cb_called = 0;
9508 ud.stream_close_cb_called = 0;
9509
9510 CU_ASSERT(0 == nghttp2_session_send(session));
9511
9512 CU_ASSERT(1 == ud.frame_send_cb_called);
9513 CU_ASSERT(311 == session->local_last_stream_id);
9514 CU_ASSERT(1 == ud.stream_close_cb_called);
9515
9516 CU_ASSERT(0 ==
9517 nghttp2_session_terminate_session2(session, 301, NGHTTP2_NO_ERROR));
9518
9519 ud.frame_send_cb_called = 0;
9520 ud.stream_close_cb_called = 0;
9521
9522 CU_ASSERT(0 == nghttp2_session_send(session));
9523
9524 CU_ASSERT(1 == ud.frame_send_cb_called);
9525 CU_ASSERT(301 == session->local_last_stream_id);
9526 CU_ASSERT(2 == ud.stream_close_cb_called);
9527
9528 CU_ASSERT(NULL != nghttp2_session_get_stream(session, 301));
9529 CU_ASSERT(NULL != nghttp2_session_get_stream(session, 302));
9530 CU_ASSERT(NULL == nghttp2_session_get_stream(session, 309));
9531 CU_ASSERT(NULL == nghttp2_session_get_stream(session, 311));
9532 CU_ASSERT(NULL == nghttp2_session_get_stream(session, 319));
9533
9534 nghttp2_session_del(session);
9535 }
9536
test_nghttp2_session_on_header_temporal_failure(void)9537 void test_nghttp2_session_on_header_temporal_failure(void) {
9538 nghttp2_session *session;
9539 nghttp2_session_callbacks callbacks;
9540 my_user_data ud;
9541 nghttp2_bufs bufs;
9542 nghttp2_buf *buf;
9543 nghttp2_hd_deflater deflater;
9544 nghttp2_nv nv[] = {MAKE_NV("alpha", "bravo"), MAKE_NV("charlie", "delta")};
9545 nghttp2_nv *nva;
9546 size_t hdpos;
9547 ssize_t rv;
9548 nghttp2_frame frame;
9549 nghttp2_frame_hd hd;
9550 nghttp2_outbound_item *item;
9551 nghttp2_mem *mem;
9552
9553 mem = nghttp2_mem_default();
9554 memset(&callbacks, 0, sizeof(callbacks));
9555 callbacks.on_header_callback = temporal_failure_on_header_callback;
9556
9557 nghttp2_session_server_new(&session, &callbacks, &ud);
9558
9559 frame_pack_bufs_init(&bufs);
9560
9561 nghttp2_hd_deflate_init(&deflater, mem);
9562
9563 nghttp2_nv_array_copy(&nva, reqnv, ARRLEN(reqnv), mem);
9564
9565 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_STREAM, 1,
9566 NGHTTP2_HCAT_REQUEST, NULL, nva, ARRLEN(reqnv));
9567 nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
9568 nghttp2_frame_headers_free(&frame.headers, mem);
9569
9570 /* We are going to create CONTINUATION. First serialize header
9571 block, and then frame header. */
9572 hdpos = nghttp2_bufs_len(&bufs);
9573
9574 buf = &bufs.head->buf;
9575 buf->last += NGHTTP2_FRAME_HDLEN;
9576
9577 nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, &nv[1], 1);
9578
9579 nghttp2_frame_hd_init(&hd,
9580 nghttp2_bufs_len(&bufs) - hdpos - NGHTTP2_FRAME_HDLEN,
9581 NGHTTP2_CONTINUATION, NGHTTP2_FLAG_END_HEADERS, 1);
9582
9583 nghttp2_frame_pack_frame_hd(&buf->pos[hdpos], &hd);
9584
9585 ud.header_cb_called = 0;
9586 rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_bufs_len(&bufs));
9587
9588 CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == rv);
9589 CU_ASSERT(1 == ud.header_cb_called);
9590
9591 item = nghttp2_session_get_next_ob_item(session);
9592
9593 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
9594 CU_ASSERT(1 == item->frame.hd.stream_id);
9595
9596 /* Make sure no header decompression error occurred */
9597 CU_ASSERT(NGHTTP2_GOAWAY_NONE == session->goaway_flags);
9598
9599 nghttp2_hd_deflate_free(&deflater);
9600 nghttp2_session_del(session);
9601
9602 nghttp2_bufs_reset(&bufs);
9603
9604 /* Check for PUSH_PROMISE */
9605 nghttp2_hd_deflate_init(&deflater, mem);
9606 nghttp2_session_client_new(&session, &callbacks, &ud);
9607
9608 open_sent_stream(session, 1);
9609
9610 rv = pack_push_promise(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, 2,
9611 reqnv, ARRLEN(reqnv), mem);
9612 CU_ASSERT(0 == rv);
9613
9614 ud.header_cb_called = 0;
9615 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
9616 nghttp2_bufs_len(&bufs));
9617 CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == rv);
9618 CU_ASSERT(1 == ud.header_cb_called);
9619
9620 item = nghttp2_session_get_next_ob_item(session);
9621 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
9622 CU_ASSERT(2 == item->frame.hd.stream_id);
9623 CU_ASSERT(NGHTTP2_INTERNAL_ERROR == item->frame.rst_stream.error_code);
9624
9625 nghttp2_session_del(session);
9626 nghttp2_hd_deflate_free(&deflater);
9627 nghttp2_bufs_free(&bufs);
9628 }
9629
test_nghttp2_session_recv_client_magic(void)9630 void test_nghttp2_session_recv_client_magic(void) {
9631 nghttp2_session *session;
9632 nghttp2_session_callbacks callbacks;
9633 ssize_t rv;
9634 nghttp2_frame ping_frame;
9635 uint8_t buf[16];
9636
9637 /* enable global nghttp2_enable_strict_preface here */
9638 nghttp2_enable_strict_preface = 1;
9639
9640 memset(&callbacks, 0, sizeof(callbacks));
9641
9642 /* Check success case */
9643 nghttp2_session_server_new(&session, &callbacks, NULL);
9644
9645 rv = nghttp2_session_mem_recv(session, (const uint8_t *)NGHTTP2_CLIENT_MAGIC,
9646 NGHTTP2_CLIENT_MAGIC_LEN);
9647
9648 CU_ASSERT(rv == NGHTTP2_CLIENT_MAGIC_LEN);
9649 CU_ASSERT(NGHTTP2_IB_READ_FIRST_SETTINGS == session->iframe.state);
9650
9651 /* Receiving PING is error because we want SETTINGS. */
9652 nghttp2_frame_ping_init(&ping_frame.ping, NGHTTP2_FLAG_NONE, NULL);
9653
9654 nghttp2_frame_pack_frame_hd(buf, &ping_frame.ping.hd);
9655
9656 rv = nghttp2_session_mem_recv(session, buf, NGHTTP2_FRAME_HDLEN);
9657 CU_ASSERT(NGHTTP2_FRAME_HDLEN == rv);
9658 CU_ASSERT(NGHTTP2_IB_IGN_ALL == session->iframe.state);
9659 CU_ASSERT(0 == session->iframe.payloadleft);
9660
9661 nghttp2_frame_ping_free(&ping_frame.ping);
9662
9663 nghttp2_session_del(session);
9664
9665 /* Check bad case */
9666 nghttp2_session_server_new(&session, &callbacks, NULL);
9667
9668 /* Feed magic with one byte less */
9669 rv = nghttp2_session_mem_recv(session, (const uint8_t *)NGHTTP2_CLIENT_MAGIC,
9670 NGHTTP2_CLIENT_MAGIC_LEN - 1);
9671
9672 CU_ASSERT(rv == NGHTTP2_CLIENT_MAGIC_LEN - 1);
9673 CU_ASSERT(NGHTTP2_IB_READ_CLIENT_MAGIC == session->iframe.state);
9674 CU_ASSERT(1 == session->iframe.payloadleft);
9675
9676 rv = nghttp2_session_mem_recv(session, (const uint8_t *)"\0", 1);
9677
9678 CU_ASSERT(NGHTTP2_ERR_BAD_CLIENT_MAGIC == rv);
9679
9680 nghttp2_session_del(session);
9681
9682 /* disable global nghttp2_enable_strict_preface here */
9683 nghttp2_enable_strict_preface = 0;
9684 }
9685
test_nghttp2_session_delete_data_item(void)9686 void test_nghttp2_session_delete_data_item(void) {
9687 nghttp2_session *session;
9688 nghttp2_session_callbacks callbacks;
9689 nghttp2_stream *a;
9690 nghttp2_data_provider prd;
9691
9692 memset(&callbacks, 0, sizeof(callbacks));
9693
9694 nghttp2_session_server_new(&session, &callbacks, NULL);
9695
9696 a = open_recv_stream(session, 1);
9697 open_recv_stream_with_dep(session, 3, a);
9698
9699 /* We don't care about these members, since we won't send data */
9700 prd.source.ptr = NULL;
9701 prd.read_callback = fail_data_source_read_callback;
9702
9703 CU_ASSERT(0 == nghttp2_submit_data(session, NGHTTP2_FLAG_NONE, 1, &prd));
9704 CU_ASSERT(0 == nghttp2_submit_data(session, NGHTTP2_FLAG_NONE, 3, &prd));
9705
9706 nghttp2_session_del(session);
9707 }
9708
test_nghttp2_session_open_idle_stream(void)9709 void test_nghttp2_session_open_idle_stream(void) {
9710 nghttp2_session *session;
9711 nghttp2_session_callbacks callbacks;
9712 nghttp2_stream *stream;
9713 nghttp2_stream *opened_stream;
9714 nghttp2_priority_spec pri_spec;
9715 nghttp2_frame frame;
9716
9717 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
9718
9719 nghttp2_session_server_new(&session, &callbacks, NULL);
9720
9721 nghttp2_priority_spec_init(&pri_spec, 0, 3, 0);
9722
9723 nghttp2_frame_priority_init(&frame.priority, 1, &pri_spec);
9724
9725 CU_ASSERT(0 == nghttp2_session_on_priority_received(session, &frame));
9726
9727 stream = nghttp2_session_get_stream_raw(session, 1);
9728
9729 CU_ASSERT(NGHTTP2_STREAM_IDLE == stream->state);
9730 CU_ASSERT(NULL == stream->closed_prev);
9731 CU_ASSERT(NULL == stream->closed_next);
9732 CU_ASSERT(1 == session->num_idle_streams);
9733 CU_ASSERT(session->idle_stream_head == stream);
9734 CU_ASSERT(session->idle_stream_tail == stream);
9735
9736 opened_stream = open_recv_stream2(session, 1, NGHTTP2_STREAM_OPENING);
9737
9738 CU_ASSERT(stream == opened_stream);
9739 CU_ASSERT(NGHTTP2_STREAM_OPENING == stream->state);
9740 CU_ASSERT(0 == session->num_idle_streams);
9741 CU_ASSERT(NULL == session->idle_stream_head);
9742 CU_ASSERT(NULL == session->idle_stream_tail);
9743
9744 nghttp2_frame_priority_free(&frame.priority);
9745
9746 nghttp2_session_del(session);
9747 }
9748
test_nghttp2_session_cancel_reserved_remote(void)9749 void test_nghttp2_session_cancel_reserved_remote(void) {
9750 nghttp2_session *session;
9751 nghttp2_session_callbacks callbacks;
9752 nghttp2_stream *stream;
9753 nghttp2_frame frame;
9754 nghttp2_nv *nva;
9755 size_t nvlen;
9756 nghttp2_hd_deflater deflater;
9757 nghttp2_mem *mem;
9758 nghttp2_bufs bufs;
9759 ssize_t rv;
9760
9761 mem = nghttp2_mem_default();
9762 frame_pack_bufs_init(&bufs);
9763
9764 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
9765 callbacks.send_callback = null_send_callback;
9766
9767 nghttp2_session_client_new(&session, &callbacks, NULL);
9768
9769 nghttp2_hd_deflate_init(&deflater, mem);
9770
9771 stream = open_recv_stream2(session, 2, NGHTTP2_STREAM_RESERVED);
9772
9773 nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, 2, NGHTTP2_CANCEL);
9774
9775 CU_ASSERT(NGHTTP2_STREAM_CLOSING == stream->state);
9776
9777 CU_ASSERT(0 == nghttp2_session_send(session));
9778
9779 nvlen = ARRLEN(resnv);
9780 nghttp2_nv_array_copy(&nva, resnv, nvlen, mem);
9781
9782 nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 2,
9783 NGHTTP2_HCAT_PUSH_RESPONSE, NULL, nva, nvlen);
9784 rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
9785
9786 CU_ASSERT(0 == rv);
9787
9788 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
9789 nghttp2_buf_len(&bufs.head->buf));
9790
9791 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
9792
9793 /* stream is not dangling, so assign NULL */
9794 stream = NULL;
9795
9796 /* No RST_STREAM or GOAWAY is generated since stream should be in
9797 NGHTTP2_STREAM_CLOSING and push response should be ignored. */
9798 CU_ASSERT(0 == nghttp2_outbound_queue_size(&session->ob_reg));
9799
9800 /* Check that we can receive push response HEADERS while RST_STREAM
9801 is just queued. */
9802 open_recv_stream2(session, 4, NGHTTP2_STREAM_RESERVED);
9803
9804 nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, 2, NGHTTP2_CANCEL);
9805
9806 nghttp2_bufs_reset(&bufs);
9807
9808 frame.hd.stream_id = 4;
9809 rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
9810
9811 CU_ASSERT(0 == rv);
9812
9813 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
9814 nghttp2_buf_len(&bufs.head->buf));
9815
9816 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
9817
9818 CU_ASSERT(1 == nghttp2_outbound_queue_size(&session->ob_reg));
9819
9820 nghttp2_frame_headers_free(&frame.headers, mem);
9821
9822 nghttp2_hd_deflate_free(&deflater);
9823
9824 nghttp2_session_del(session);
9825
9826 nghttp2_bufs_free(&bufs);
9827 }
9828
test_nghttp2_session_reset_pending_headers(void)9829 void test_nghttp2_session_reset_pending_headers(void) {
9830 nghttp2_session *session;
9831 nghttp2_session_callbacks callbacks;
9832 nghttp2_stream *stream;
9833 int32_t stream_id;
9834 my_user_data ud;
9835
9836 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
9837 callbacks.send_callback = null_send_callback;
9838 callbacks.on_frame_send_callback = on_frame_send_callback;
9839 callbacks.on_frame_not_send_callback = on_frame_not_send_callback;
9840 callbacks.on_stream_close_callback = on_stream_close_callback;
9841
9842 nghttp2_session_client_new(&session, &callbacks, &ud);
9843
9844 stream_id = nghttp2_submit_request(session, NULL, NULL, 0, NULL, NULL);
9845 CU_ASSERT(stream_id >= 1);
9846
9847 nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, stream_id,
9848 NGHTTP2_CANCEL);
9849
9850 session->remote_settings.max_concurrent_streams = 0;
9851
9852 /* RST_STREAM cancels pending HEADERS and is not actually sent. */
9853 ud.frame_send_cb_called = 0;
9854 CU_ASSERT(0 == nghttp2_session_send(session));
9855
9856 CU_ASSERT(0 == ud.frame_send_cb_called);
9857
9858 stream = nghttp2_session_get_stream(session, stream_id);
9859
9860 CU_ASSERT(NULL == stream);
9861
9862 /* See HEADERS is not sent. on_stream_close is called just like
9863 transmission failure. */
9864 session->remote_settings.max_concurrent_streams = 1;
9865
9866 ud.frame_not_send_cb_called = 0;
9867 ud.stream_close_error_code = 0;
9868 CU_ASSERT(0 == nghttp2_session_send(session));
9869
9870 CU_ASSERT(1 == ud.frame_not_send_cb_called);
9871 CU_ASSERT(NGHTTP2_HEADERS == ud.not_sent_frame_type);
9872 CU_ASSERT(NGHTTP2_CANCEL == ud.stream_close_error_code);
9873
9874 stream = nghttp2_session_get_stream(session, stream_id);
9875
9876 CU_ASSERT(NULL == stream);
9877
9878 nghttp2_session_del(session);
9879 }
9880
test_nghttp2_session_send_data_callback(void)9881 void test_nghttp2_session_send_data_callback(void) {
9882 nghttp2_session *session;
9883 nghttp2_session_callbacks callbacks;
9884 nghttp2_data_provider data_prd;
9885 my_user_data ud;
9886 accumulator acc;
9887 nghttp2_frame_hd hd;
9888
9889 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
9890 callbacks.send_callback = accumulator_send_callback;
9891 callbacks.send_data_callback = send_data_callback;
9892
9893 data_prd.read_callback = no_copy_data_source_read_callback;
9894
9895 acc.length = 0;
9896 ud.acc = &acc;
9897
9898 ud.data_source_length = NGHTTP2_DATA_PAYLOADLEN * 2;
9899
9900 nghttp2_session_client_new(&session, &callbacks, &ud);
9901
9902 open_sent_stream(session, 1);
9903
9904 nghttp2_submit_data(session, NGHTTP2_FLAG_END_STREAM, 1, &data_prd);
9905
9906 CU_ASSERT(0 == nghttp2_session_send(session));
9907
9908 CU_ASSERT((NGHTTP2_FRAME_HDLEN + NGHTTP2_DATA_PAYLOADLEN) * 2 == acc.length);
9909
9910 nghttp2_frame_unpack_frame_hd(&hd, acc.buf);
9911
9912 CU_ASSERT(16384 == hd.length);
9913 CU_ASSERT(NGHTTP2_DATA == hd.type);
9914 CU_ASSERT(NGHTTP2_FLAG_NONE == hd.flags);
9915
9916 nghttp2_frame_unpack_frame_hd(&hd, acc.buf + NGHTTP2_FRAME_HDLEN + hd.length);
9917
9918 CU_ASSERT(16384 == hd.length);
9919 CU_ASSERT(NGHTTP2_DATA == hd.type);
9920 CU_ASSERT(NGHTTP2_FLAG_END_STREAM == hd.flags);
9921
9922 nghttp2_session_del(session);
9923 }
9924
test_nghttp2_session_on_begin_headers_temporal_failure(void)9925 void test_nghttp2_session_on_begin_headers_temporal_failure(void) {
9926 nghttp2_session *session;
9927 nghttp2_session_callbacks callbacks;
9928 my_user_data ud;
9929 nghttp2_bufs bufs;
9930 nghttp2_mem *mem;
9931 ssize_t rv;
9932 nghttp2_hd_deflater deflater;
9933 nghttp2_outbound_item *item;
9934
9935 mem = nghttp2_mem_default();
9936 frame_pack_bufs_init(&bufs);
9937 nghttp2_hd_deflate_init(&deflater, mem);
9938
9939 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
9940 callbacks.on_begin_headers_callback =
9941 temporal_failure_on_begin_headers_callback;
9942 callbacks.on_header_callback = on_header_callback;
9943 callbacks.on_frame_recv_callback = on_frame_recv_callback;
9944 callbacks.send_callback = null_send_callback;
9945 nghttp2_session_server_new(&session, &callbacks, &ud);
9946
9947 rv = pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, reqnv,
9948 ARRLEN(reqnv), mem);
9949 CU_ASSERT(0 == rv);
9950
9951 ud.header_cb_called = 0;
9952 ud.frame_recv_cb_called = 0;
9953 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
9954 nghttp2_bufs_len(&bufs));
9955 CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == rv);
9956 CU_ASSERT(0 == ud.header_cb_called);
9957 CU_ASSERT(0 == ud.frame_recv_cb_called);
9958
9959 item = nghttp2_session_get_next_ob_item(session);
9960 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
9961 CU_ASSERT(1 == item->frame.hd.stream_id);
9962 CU_ASSERT(NGHTTP2_INTERNAL_ERROR == item->frame.rst_stream.error_code);
9963
9964 nghttp2_session_del(session);
9965 nghttp2_hd_deflate_free(&deflater);
9966
9967 nghttp2_bufs_reset(&bufs);
9968 /* check for PUSH_PROMISE */
9969 nghttp2_hd_deflate_init(&deflater, mem);
9970 nghttp2_session_client_new(&session, &callbacks, &ud);
9971
9972 open_sent_stream(session, 1);
9973
9974 rv = pack_push_promise(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, 2,
9975 reqnv, ARRLEN(reqnv), mem);
9976 CU_ASSERT(0 == rv);
9977
9978 ud.header_cb_called = 0;
9979 ud.frame_recv_cb_called = 0;
9980 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
9981 nghttp2_bufs_len(&bufs));
9982 CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == rv);
9983 CU_ASSERT(0 == ud.header_cb_called);
9984 CU_ASSERT(0 == ud.frame_recv_cb_called);
9985
9986 item = nghttp2_session_get_next_ob_item(session);
9987 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
9988 CU_ASSERT(2 == item->frame.hd.stream_id);
9989 CU_ASSERT(NGHTTP2_INTERNAL_ERROR == item->frame.rst_stream.error_code);
9990
9991 nghttp2_session_del(session);
9992 nghttp2_hd_deflate_free(&deflater);
9993 nghttp2_bufs_free(&bufs);
9994 }
9995
test_nghttp2_session_defer_then_close(void)9996 void test_nghttp2_session_defer_then_close(void) {
9997 nghttp2_session *session;
9998 nghttp2_session_callbacks callbacks;
9999 nghttp2_data_provider prd;
10000 int rv;
10001 const uint8_t *datap;
10002 ssize_t datalen;
10003 nghttp2_frame frame;
10004
10005 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
10006 callbacks.send_callback = null_send_callback;
10007
10008 nghttp2_session_client_new(&session, &callbacks, NULL);
10009
10010 prd.read_callback = defer_data_source_read_callback;
10011
10012 rv = nghttp2_submit_request(session, NULL, reqnv, ARRLEN(reqnv), &prd, NULL);
10013 CU_ASSERT(rv > 0);
10014
10015 /* This sends HEADERS */
10016 datalen = nghttp2_session_mem_send(session, &datap);
10017
10018 CU_ASSERT(datalen > 0);
10019
10020 /* This makes DATA item deferred */
10021 datalen = nghttp2_session_mem_send(session, &datap);
10022
10023 CU_ASSERT(datalen == 0);
10024
10025 nghttp2_frame_rst_stream_init(&frame.rst_stream, 1, NGHTTP2_CANCEL);
10026
10027 /* Assertion failure; GH-264 */
10028 rv = nghttp2_session_on_rst_stream_received(session, &frame);
10029
10030 CU_ASSERT(rv == 0);
10031
10032 nghttp2_session_del(session);
10033 }
10034
submit_response_on_stream_close(nghttp2_session * session,int32_t stream_id,uint32_t error_code,void * user_data)10035 static int submit_response_on_stream_close(nghttp2_session *session,
10036 int32_t stream_id,
10037 uint32_t error_code,
10038 void *user_data) {
10039 nghttp2_data_provider data_prd;
10040 (void)error_code;
10041 (void)user_data;
10042
10043 data_prd.read_callback = temporal_failure_data_source_read_callback;
10044
10045 // Attempt to submit response or data to the stream being closed
10046 switch (stream_id) {
10047 case 1:
10048 CU_ASSERT(0 == nghttp2_submit_response(session, stream_id, resnv,
10049 ARRLEN(resnv), &data_prd));
10050 break;
10051 case 3:
10052 CU_ASSERT(0 == nghttp2_submit_data(session, NGHTTP2_FLAG_NONE, stream_id,
10053 &data_prd));
10054 break;
10055 }
10056
10057 return 0;
10058 }
10059
test_nghttp2_session_detach_item_from_closed_stream(void)10060 void test_nghttp2_session_detach_item_from_closed_stream(void) {
10061 nghttp2_session *session;
10062 nghttp2_session_callbacks callbacks;
10063
10064 memset(&callbacks, 0, sizeof(callbacks));
10065
10066 callbacks.send_callback = null_send_callback;
10067 callbacks.on_stream_close_callback = submit_response_on_stream_close;
10068
10069 nghttp2_session_server_new(&session, &callbacks, NULL);
10070
10071 open_recv_stream(session, 1);
10072 open_recv_stream(session, 3);
10073
10074 nghttp2_session_close_stream(session, 1, NGHTTP2_NO_ERROR);
10075 nghttp2_session_close_stream(session, 3, NGHTTP2_NO_ERROR);
10076
10077 CU_ASSERT(0 == nghttp2_session_send(session));
10078
10079 nghttp2_session_del(session);
10080 }
10081
test_nghttp2_session_flooding(void)10082 void test_nghttp2_session_flooding(void) {
10083 nghttp2_session *session;
10084 nghttp2_session_callbacks callbacks;
10085 nghttp2_bufs bufs;
10086 nghttp2_buf *buf;
10087 nghttp2_frame frame;
10088 nghttp2_mem *mem;
10089 size_t i;
10090
10091 mem = nghttp2_mem_default();
10092
10093 frame_pack_bufs_init(&bufs);
10094
10095 memset(&callbacks, 0, sizeof(callbacks));
10096
10097 /* PING ACK */
10098 nghttp2_session_server_new(&session, &callbacks, NULL);
10099
10100 nghttp2_frame_ping_init(&frame.ping, NGHTTP2_FLAG_NONE, NULL);
10101 nghttp2_frame_pack_ping(&bufs, &frame.ping);
10102 nghttp2_frame_ping_free(&frame.ping);
10103
10104 buf = &bufs.head->buf;
10105
10106 for (i = 0; i < NGHTTP2_DEFAULT_MAX_OBQ_FLOOD_ITEM; ++i) {
10107 CU_ASSERT(
10108 (ssize_t)nghttp2_buf_len(buf) ==
10109 nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf)));
10110 }
10111
10112 CU_ASSERT(NGHTTP2_ERR_FLOODED ==
10113 nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf)));
10114
10115 nghttp2_session_del(session);
10116
10117 /* SETTINGS ACK */
10118 nghttp2_bufs_reset(&bufs);
10119
10120 nghttp2_session_server_new(&session, &callbacks, NULL);
10121
10122 nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE, NULL, 0);
10123 nghttp2_frame_pack_settings(&bufs, &frame.settings);
10124 nghttp2_frame_settings_free(&frame.settings, mem);
10125
10126 buf = &bufs.head->buf;
10127
10128 for (i = 0; i < NGHTTP2_DEFAULT_MAX_OBQ_FLOOD_ITEM; ++i) {
10129 CU_ASSERT(
10130 (ssize_t)nghttp2_buf_len(buf) ==
10131 nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf)));
10132 }
10133
10134 CU_ASSERT(NGHTTP2_ERR_FLOODED ==
10135 nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf)));
10136
10137 nghttp2_session_del(session);
10138 nghttp2_bufs_free(&bufs);
10139 }
10140
test_nghttp2_session_change_stream_priority(void)10141 void test_nghttp2_session_change_stream_priority(void) {
10142 nghttp2_session *session;
10143 nghttp2_session_callbacks callbacks;
10144 nghttp2_stream *stream1, *stream2, *stream3, *stream5;
10145 nghttp2_priority_spec pri_spec;
10146 int rv;
10147
10148 memset(&callbacks, 0, sizeof(callbacks));
10149
10150 nghttp2_session_server_new(&session, &callbacks, NULL);
10151
10152 stream1 = open_recv_stream(session, 1);
10153 stream3 = open_recv_stream_with_dep_weight(session, 3, 199, stream1);
10154 stream2 = open_sent_stream_with_dep_weight(session, 2, 101, stream3);
10155
10156 nghttp2_priority_spec_init(&pri_spec, 1, 256, 0);
10157
10158 rv = nghttp2_session_change_stream_priority(session, 2, &pri_spec);
10159
10160 CU_ASSERT(0 == rv);
10161
10162 CU_ASSERT(stream1 == stream2->dep_prev);
10163 CU_ASSERT(256 == stream2->weight);
10164
10165 /* Cannot change stream which does not exist */
10166 rv = nghttp2_session_change_stream_priority(session, 5, &pri_spec);
10167 CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT == rv);
10168
10169 /* It is an error to depend on itself */
10170 rv = nghttp2_session_change_stream_priority(session, 1, &pri_spec);
10171 CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT == rv);
10172
10173 /* It is an error to change priority of root stream (0) */
10174 rv = nghttp2_session_change_stream_priority(session, 0, &pri_spec);
10175 CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT == rv);
10176
10177 /* Depends on the non-existing idle stream. This creates that idle
10178 stream. */
10179 nghttp2_priority_spec_init(&pri_spec, 5, 9, 1);
10180
10181 rv = nghttp2_session_change_stream_priority(session, 2, &pri_spec);
10182
10183 CU_ASSERT(0 == rv);
10184
10185 stream5 = nghttp2_session_get_stream_raw(session, 5);
10186
10187 CU_ASSERT(NULL != stream5);
10188 CU_ASSERT(&session->root == stream5->dep_prev);
10189 CU_ASSERT(stream5 == stream2->dep_prev);
10190 CU_ASSERT(9 == stream2->weight);
10191
10192 nghttp2_session_del(session);
10193
10194 /* Check that this works in client session too */
10195 nghttp2_session_client_new(&session, &callbacks, NULL);
10196
10197 stream1 = open_sent_stream(session, 1);
10198
10199 nghttp2_priority_spec_init(&pri_spec, 5, 9, 1);
10200
10201 rv = nghttp2_session_change_stream_priority(session, 1, &pri_spec);
10202
10203 CU_ASSERT(0 == rv);
10204
10205 stream5 = nghttp2_session_get_stream_raw(session, 5);
10206
10207 CU_ASSERT(NULL != stream5);
10208 CU_ASSERT(&session->root == stream5->dep_prev);
10209 CU_ASSERT(stream5 == stream1->dep_prev);
10210 CU_ASSERT(9 == stream1->weight);
10211
10212 nghttp2_session_del(session);
10213 }
10214
test_nghttp2_session_create_idle_stream(void)10215 void test_nghttp2_session_create_idle_stream(void) {
10216 nghttp2_session *session;
10217 nghttp2_session_callbacks callbacks;
10218 nghttp2_stream *stream2, *stream4, *stream8, *stream10;
10219 nghttp2_priority_spec pri_spec;
10220 int rv;
10221 int i;
10222
10223 memset(&callbacks, 0, sizeof(callbacks));
10224 callbacks.send_callback = null_send_callback;
10225
10226 nghttp2_session_server_new(&session, &callbacks, NULL);
10227
10228 stream2 = open_sent_stream(session, 2);
10229
10230 nghttp2_priority_spec_init(&pri_spec, 2, 111, 1);
10231
10232 rv = nghttp2_session_create_idle_stream(session, 4, &pri_spec);
10233
10234 CU_ASSERT(0 == rv);
10235
10236 stream4 = nghttp2_session_get_stream_raw(session, 4);
10237
10238 CU_ASSERT(4 == stream4->stream_id);
10239 CU_ASSERT(111 == stream4->weight);
10240 CU_ASSERT(stream2 == stream4->dep_prev);
10241 CU_ASSERT(stream4 == stream2->dep_next);
10242
10243 /* If pri_spec->stream_id does not exist, and it is idle stream, it
10244 is created too */
10245 nghttp2_priority_spec_init(&pri_spec, 10, 109, 0);
10246
10247 rv = nghttp2_session_create_idle_stream(session, 8, &pri_spec);
10248
10249 CU_ASSERT(0 == rv);
10250
10251 stream8 = nghttp2_session_get_stream_raw(session, 8);
10252 stream10 = nghttp2_session_get_stream_raw(session, 10);
10253
10254 CU_ASSERT(8 == stream8->stream_id);
10255 CU_ASSERT(109 == stream8->weight);
10256 CU_ASSERT(10 == stream10->stream_id);
10257 CU_ASSERT(16 == stream10->weight);
10258 CU_ASSERT(stream10 == stream8->dep_prev);
10259 CU_ASSERT(&session->root == stream10->dep_prev);
10260
10261 /* It is an error to attempt to create already existing idle
10262 stream */
10263 rv = nghttp2_session_create_idle_stream(session, 4, &pri_spec);
10264
10265 CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT == rv);
10266
10267 /* It is an error to depend on itself */
10268 pri_spec.stream_id = 6;
10269
10270 rv = nghttp2_session_create_idle_stream(session, 6, &pri_spec);
10271 CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT == rv);
10272
10273 /* It is an error to create root stream (0) as idle stream */
10274 rv = nghttp2_session_create_idle_stream(session, 0, &pri_spec);
10275 CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT == rv);
10276
10277 /* It is an error to create non-idle stream */
10278 session->last_sent_stream_id = 20;
10279 pri_spec.stream_id = 2;
10280
10281 rv = nghttp2_session_create_idle_stream(session, 18, &pri_spec);
10282
10283 CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT == rv);
10284
10285 nghttp2_session_del(session);
10286
10287 /* Check that this works in client session too */
10288 nghttp2_session_client_new(&session, &callbacks, NULL);
10289
10290 nghttp2_priority_spec_init(&pri_spec, 4, 99, 1);
10291
10292 rv = nghttp2_session_create_idle_stream(session, 2, &pri_spec);
10293
10294 CU_ASSERT(0 == rv);
10295
10296 stream4 = nghttp2_session_get_stream_raw(session, 4);
10297 stream2 = nghttp2_session_get_stream_raw(session, 2);
10298
10299 CU_ASSERT(NULL != stream4);
10300 CU_ASSERT(NULL != stream2);
10301 CU_ASSERT(&session->root == stream4->dep_prev);
10302 CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == stream4->weight);
10303 CU_ASSERT(stream4 == stream2->dep_prev);
10304 CU_ASSERT(99 == stream2->weight);
10305
10306 nghttp2_session_del(session);
10307
10308 /* Check that idle stream is reduced when nghttp2_session_send() is
10309 called. */
10310 nghttp2_session_server_new(&session, &callbacks, NULL);
10311
10312 session->local_settings.max_concurrent_streams = 30;
10313
10314 nghttp2_priority_spec_init(&pri_spec, 0, 16, 0);
10315 for (i = 0; i < 100; ++i) {
10316 rv = nghttp2_session_create_idle_stream(session, i * 2 + 1, &pri_spec);
10317
10318 CU_ASSERT(0 == rv);
10319
10320 nghttp2_priority_spec_init(&pri_spec, i * 2 + 1, 16, 0);
10321 }
10322
10323 CU_ASSERT(100 == session->num_idle_streams);
10324 CU_ASSERT(0 == nghttp2_session_send(session));
10325 CU_ASSERT(30 == session->num_idle_streams);
10326 CU_ASSERT(141 == session->idle_stream_head->stream_id);
10327
10328 nghttp2_session_del(session);
10329
10330 /* Check that idle stream is reduced when nghttp2_session_mem_recv() is
10331 called. */
10332 nghttp2_session_client_new(&session, &callbacks, NULL);
10333
10334 session->local_settings.max_concurrent_streams = 30;
10335
10336 nghttp2_priority_spec_init(&pri_spec, 0, 16, 0);
10337 for (i = 0; i < 100; ++i) {
10338 rv = nghttp2_session_create_idle_stream(session, i * 2 + 1, &pri_spec);
10339
10340 CU_ASSERT(0 == rv);
10341
10342 nghttp2_priority_spec_init(&pri_spec, i * 2 + 1, 16, 0);
10343 }
10344
10345 CU_ASSERT(100 == session->num_idle_streams);
10346 CU_ASSERT(0 == nghttp2_session_mem_recv(session, NULL, 0));
10347 CU_ASSERT(30 == session->num_idle_streams);
10348 CU_ASSERT(141 == session->idle_stream_head->stream_id);
10349
10350 nghttp2_session_del(session);
10351 }
10352
test_nghttp2_session_repeated_priority_change(void)10353 void test_nghttp2_session_repeated_priority_change(void) {
10354 nghttp2_session *session;
10355 nghttp2_session_callbacks callbacks;
10356 nghttp2_frame frame;
10357 nghttp2_priority_spec pri_spec;
10358 int32_t stream_id, last_stream_id;
10359 int32_t max_streams = 20;
10360
10361 memset(&callbacks, 0, sizeof(callbacks));
10362
10363 nghttp2_session_server_new(&session, &callbacks, NULL);
10364
10365 session->local_settings.max_concurrent_streams = (uint32_t)max_streams;
10366
10367 /* 1 -> 0 */
10368 nghttp2_priority_spec_init(&pri_spec, 0, 16, 0);
10369 nghttp2_frame_priority_init(&frame.priority, 1, &pri_spec);
10370
10371 CU_ASSERT(0 == nghttp2_session_on_priority_received(session, &frame));
10372
10373 nghttp2_frame_priority_free(&frame.priority);
10374
10375 last_stream_id = max_streams * 2 + 1;
10376
10377 for (stream_id = 3; stream_id < last_stream_id; stream_id += 2) {
10378 /* 1 -> stream_id */
10379 nghttp2_priority_spec_init(&pri_spec, stream_id, 16, 0);
10380 nghttp2_frame_priority_init(&frame.priority, 1, &pri_spec);
10381
10382 CU_ASSERT(0 == nghttp2_session_on_priority_received(session, &frame));
10383
10384 nghttp2_frame_priority_free(&frame.priority);
10385 }
10386
10387 CU_ASSERT(20 == session->num_idle_streams);
10388 CU_ASSERT(1 == session->idle_stream_head->stream_id);
10389
10390 /* 1 -> last_stream_id */
10391 nghttp2_priority_spec_init(&pri_spec, last_stream_id, 16, 0);
10392 nghttp2_frame_priority_init(&frame.priority, 1, &pri_spec);
10393
10394 CU_ASSERT(0 == nghttp2_session_on_priority_received(session, &frame));
10395
10396 nghttp2_frame_priority_free(&frame.priority);
10397
10398 CU_ASSERT(20 == session->num_idle_streams);
10399 CU_ASSERT(3 == session->idle_stream_head->stream_id);
10400
10401 nghttp2_session_del(session);
10402 }
10403
test_nghttp2_session_repeated_priority_submission(void)10404 void test_nghttp2_session_repeated_priority_submission(void) {
10405 nghttp2_session *session;
10406 nghttp2_session_callbacks callbacks;
10407 nghttp2_priority_spec pri_spec;
10408 int32_t stream_id, last_stream_id;
10409 uint32_t max_streams = NGHTTP2_MIN_IDLE_STREAMS;
10410
10411 memset(&callbacks, 0, sizeof(callbacks));
10412
10413 callbacks.send_callback = null_send_callback;
10414
10415 nghttp2_session_client_new(&session, &callbacks, NULL);
10416
10417 session->local_settings.max_concurrent_streams = max_streams;
10418
10419 /* 1 -> 0 */
10420 nghttp2_priority_spec_init(&pri_spec, 0, 16, 0);
10421
10422 CU_ASSERT(0 ==
10423 nghttp2_submit_priority(session, NGHTTP2_FLAG_NONE, 1, &pri_spec));
10424
10425 last_stream_id = (int32_t)(max_streams * 2 + 1);
10426
10427 for (stream_id = 3; stream_id < last_stream_id; stream_id += 2) {
10428 /* 1 -> stream_id */
10429 nghttp2_priority_spec_init(&pri_spec, stream_id, 16, 0);
10430
10431 CU_ASSERT(
10432 0 == nghttp2_submit_priority(session, NGHTTP2_FLAG_NONE, 1, &pri_spec));
10433 }
10434
10435 CU_ASSERT(0 == nghttp2_session_send(session));
10436 CU_ASSERT(max_streams == session->num_idle_streams);
10437 CU_ASSERT(1 == session->idle_stream_head->stream_id);
10438
10439 /* 1 -> last_stream_id */
10440 nghttp2_priority_spec_init(&pri_spec, last_stream_id, 16, 0);
10441
10442 CU_ASSERT(0 ==
10443 nghttp2_submit_priority(session, NGHTTP2_FLAG_NONE, 1, &pri_spec));
10444
10445 CU_ASSERT(0 == nghttp2_session_send(session));
10446 CU_ASSERT(max_streams == session->num_idle_streams);
10447 CU_ASSERT(3 == session->idle_stream_head->stream_id);
10448
10449 nghttp2_session_del(session);
10450 }
10451
test_nghttp2_session_set_local_window_size(void)10452 void test_nghttp2_session_set_local_window_size(void) {
10453 nghttp2_session *session;
10454 nghttp2_session_callbacks callbacks;
10455 nghttp2_outbound_item *item;
10456 nghttp2_stream *stream;
10457
10458 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
10459 callbacks.send_callback = null_send_callback;
10460
10461 nghttp2_session_client_new(&session, &callbacks, NULL);
10462 stream = open_sent_stream(session, 1);
10463 stream->recv_window_size = 4096;
10464
10465 CU_ASSERT(0 == nghttp2_session_set_local_window_size(
10466 session, NGHTTP2_FLAG_NONE, 1, 65536));
10467 CU_ASSERT(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE + 1 ==
10468 stream->local_window_size);
10469 CU_ASSERT(4096 == stream->recv_window_size);
10470 CU_ASSERT(65536 - 4096 ==
10471 nghttp2_session_get_stream_local_window_size(session, 1));
10472
10473 item = nghttp2_session_get_next_ob_item(session);
10474
10475 CU_ASSERT(NGHTTP2_WINDOW_UPDATE == item->frame.hd.type);
10476 CU_ASSERT(1 == item->frame.window_update.hd.stream_id);
10477 CU_ASSERT(1 == item->frame.window_update.window_size_increment);
10478
10479 CU_ASSERT(0 == nghttp2_session_send(session));
10480
10481 /* Go decrement part */
10482 CU_ASSERT(0 == nghttp2_session_set_local_window_size(
10483 session, NGHTTP2_FLAG_NONE, 1, 32768));
10484 CU_ASSERT(32768 == stream->local_window_size);
10485 CU_ASSERT(-28672 == stream->recv_window_size);
10486 CU_ASSERT(32768 == stream->recv_reduction);
10487 CU_ASSERT(65536 - 4096 ==
10488 nghttp2_session_get_stream_local_window_size(session, 1));
10489
10490 item = nghttp2_session_get_next_ob_item(session);
10491
10492 CU_ASSERT(item == NULL);
10493
10494 /* Increase local window size */
10495 CU_ASSERT(0 == nghttp2_session_set_local_window_size(
10496 session, NGHTTP2_FLAG_NONE, 1, 49152));
10497 CU_ASSERT(49152 == stream->local_window_size);
10498 CU_ASSERT(-12288 == stream->recv_window_size);
10499 CU_ASSERT(16384 == stream->recv_reduction);
10500 CU_ASSERT(65536 - 4096 ==
10501 nghttp2_session_get_stream_local_window_size(session, 1));
10502 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
10503
10504 /* Increase local window again */
10505 CU_ASSERT(0 == nghttp2_session_set_local_window_size(
10506 session, NGHTTP2_FLAG_NONE, 1, 65537));
10507 CU_ASSERT(65537 == stream->local_window_size);
10508 CU_ASSERT(4096 == stream->recv_window_size);
10509 CU_ASSERT(0 == stream->recv_reduction);
10510 CU_ASSERT(65537 - 4096 ==
10511 nghttp2_session_get_stream_local_window_size(session, 1));
10512
10513 item = nghttp2_session_get_next_ob_item(session);
10514
10515 CU_ASSERT(1 == item->frame.window_update.window_size_increment);
10516
10517 CU_ASSERT(0 == nghttp2_session_send(session));
10518
10519 /* Check connection-level flow control */
10520 session->recv_window_size = 4096;
10521 CU_ASSERT(0 == nghttp2_session_set_local_window_size(
10522 session, NGHTTP2_FLAG_NONE, 0, 65536));
10523 CU_ASSERT(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE + 1 ==
10524 session->local_window_size);
10525 CU_ASSERT(4096 == session->recv_window_size);
10526 CU_ASSERT(65536 - 4096 == nghttp2_session_get_local_window_size(session));
10527
10528 item = nghttp2_session_get_next_ob_item(session);
10529
10530 CU_ASSERT(NGHTTP2_WINDOW_UPDATE == item->frame.hd.type);
10531 CU_ASSERT(0 == item->frame.window_update.hd.stream_id);
10532 CU_ASSERT(1 == item->frame.window_update.window_size_increment);
10533
10534 CU_ASSERT(0 == nghttp2_session_send(session));
10535
10536 /* Go decrement part */
10537 CU_ASSERT(0 == nghttp2_session_set_local_window_size(
10538 session, NGHTTP2_FLAG_NONE, 0, 32768));
10539 CU_ASSERT(32768 == session->local_window_size);
10540 CU_ASSERT(-28672 == session->recv_window_size);
10541 CU_ASSERT(32768 == session->recv_reduction);
10542 CU_ASSERT(65536 - 4096 == nghttp2_session_get_local_window_size(session));
10543
10544 item = nghttp2_session_get_next_ob_item(session);
10545
10546 CU_ASSERT(item == NULL);
10547
10548 /* Increase local window size */
10549 CU_ASSERT(0 == nghttp2_session_set_local_window_size(
10550 session, NGHTTP2_FLAG_NONE, 0, 49152));
10551 CU_ASSERT(49152 == session->local_window_size);
10552 CU_ASSERT(-12288 == session->recv_window_size);
10553 CU_ASSERT(16384 == session->recv_reduction);
10554 CU_ASSERT(65536 - 4096 == nghttp2_session_get_local_window_size(session));
10555 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
10556
10557 /* Increase local window again */
10558 CU_ASSERT(0 == nghttp2_session_set_local_window_size(
10559 session, NGHTTP2_FLAG_NONE, 0, 65537));
10560 CU_ASSERT(65537 == session->local_window_size);
10561 CU_ASSERT(4096 == session->recv_window_size);
10562 CU_ASSERT(0 == session->recv_reduction);
10563 CU_ASSERT(65537 - 4096 == nghttp2_session_get_local_window_size(session));
10564
10565 item = nghttp2_session_get_next_ob_item(session);
10566
10567 CU_ASSERT(1 == item->frame.window_update.window_size_increment);
10568
10569 CU_ASSERT(0 == nghttp2_session_send(session));
10570
10571 nghttp2_session_del(session);
10572
10573 /* Make sure that nghttp2_session_set_local_window_size submits
10574 WINDOW_UPDATE if necessary to increase stream-level window. */
10575 nghttp2_session_client_new(&session, &callbacks, NULL);
10576 stream = open_sent_stream(session, 1);
10577 stream->recv_window_size = NGHTTP2_INITIAL_WINDOW_SIZE;
10578
10579 CU_ASSERT(0 == nghttp2_session_set_local_window_size(
10580 session, NGHTTP2_FLAG_NONE, 1, 0));
10581 CU_ASSERT(0 == stream->recv_window_size);
10582 CU_ASSERT(0 == nghttp2_session_get_stream_local_window_size(session, 1));
10583 /* This should submit WINDOW_UPDATE frame because stream-level
10584 receiving window is now full. */
10585 CU_ASSERT(0 ==
10586 nghttp2_session_set_local_window_size(session, NGHTTP2_FLAG_NONE, 1,
10587 NGHTTP2_INITIAL_WINDOW_SIZE));
10588 CU_ASSERT(0 == stream->recv_window_size);
10589 CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE ==
10590 nghttp2_session_get_stream_local_window_size(session, 1));
10591
10592 item = nghttp2_session_get_next_ob_item(session);
10593
10594 CU_ASSERT(NGHTTP2_WINDOW_UPDATE == item->frame.hd.type);
10595 CU_ASSERT(1 == item->frame.hd.stream_id);
10596 CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE ==
10597 item->frame.window_update.window_size_increment);
10598
10599 nghttp2_session_del(session);
10600
10601 /* Make sure that nghttp2_session_set_local_window_size submits
10602 WINDOW_UPDATE if necessary to increase connection-level
10603 window. */
10604 nghttp2_session_client_new(&session, &callbacks, NULL);
10605 session->recv_window_size = NGHTTP2_INITIAL_WINDOW_SIZE;
10606
10607 CU_ASSERT(0 == nghttp2_session_set_local_window_size(
10608 session, NGHTTP2_FLAG_NONE, 0, 0));
10609 CU_ASSERT(0 == session->recv_window_size);
10610 CU_ASSERT(0 == nghttp2_session_get_local_window_size(session));
10611 /* This should submit WINDOW_UPDATE frame because connection-level
10612 receiving window is now full. */
10613 CU_ASSERT(0 ==
10614 nghttp2_session_set_local_window_size(session, NGHTTP2_FLAG_NONE, 0,
10615 NGHTTP2_INITIAL_WINDOW_SIZE));
10616 CU_ASSERT(0 == session->recv_window_size);
10617 CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE ==
10618 nghttp2_session_get_local_window_size(session));
10619
10620 item = nghttp2_session_get_next_ob_item(session);
10621
10622 CU_ASSERT(NGHTTP2_WINDOW_UPDATE == item->frame.hd.type);
10623 CU_ASSERT(0 == item->frame.hd.stream_id);
10624 CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE ==
10625 item->frame.window_update.window_size_increment);
10626
10627 nghttp2_session_del(session);
10628 }
10629
test_nghttp2_session_cancel_from_before_frame_send(void)10630 void test_nghttp2_session_cancel_from_before_frame_send(void) {
10631 int rv;
10632 nghttp2_session *session;
10633 nghttp2_session_callbacks callbacks;
10634 my_user_data ud;
10635 nghttp2_settings_entry iv;
10636 nghttp2_data_provider data_prd;
10637 int32_t stream_id;
10638 nghttp2_stream *stream;
10639
10640 memset(&callbacks, 0, sizeof(callbacks));
10641
10642 callbacks.before_frame_send_callback = cancel_before_frame_send_callback;
10643 callbacks.on_frame_not_send_callback = on_frame_not_send_callback;
10644 callbacks.send_callback = null_send_callback;
10645
10646 nghttp2_session_client_new(&session, &callbacks, &ud);
10647
10648 iv.settings_id = 0;
10649 iv.value = 1000000009;
10650
10651 rv = nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, &iv, 1);
10652
10653 CU_ASSERT(0 == rv);
10654
10655 ud.frame_send_cb_called = 0;
10656 ud.before_frame_send_cb_called = 0;
10657 ud.frame_not_send_cb_called = 0;
10658
10659 rv = nghttp2_session_send(session);
10660
10661 CU_ASSERT(0 == rv);
10662 CU_ASSERT(0 == ud.frame_send_cb_called);
10663 CU_ASSERT(1 == ud.before_frame_send_cb_called);
10664 CU_ASSERT(1 == ud.frame_not_send_cb_called);
10665
10666 data_prd.source.ptr = NULL;
10667 data_prd.read_callback = temporal_failure_data_source_read_callback;
10668
10669 stream_id = nghttp2_submit_request(session, NULL, reqnv, ARRLEN(reqnv),
10670 &data_prd, NULL);
10671
10672 CU_ASSERT(stream_id > 0);
10673
10674 ud.frame_send_cb_called = 0;
10675 ud.before_frame_send_cb_called = 0;
10676 ud.frame_not_send_cb_called = 0;
10677
10678 rv = nghttp2_session_send(session);
10679
10680 CU_ASSERT(0 == rv);
10681 CU_ASSERT(0 == ud.frame_send_cb_called);
10682 CU_ASSERT(1 == ud.before_frame_send_cb_called);
10683 CU_ASSERT(1 == ud.frame_not_send_cb_called);
10684
10685 stream = nghttp2_session_get_stream_raw(session, stream_id);
10686
10687 CU_ASSERT(NULL == stream);
10688
10689 nghttp2_session_del(session);
10690
10691 nghttp2_session_server_new(&session, &callbacks, &ud);
10692
10693 open_recv_stream(session, 1);
10694
10695 stream_id = nghttp2_submit_push_promise(session, NGHTTP2_FLAG_NONE, 1, reqnv,
10696 ARRLEN(reqnv), NULL);
10697
10698 CU_ASSERT(stream_id > 0);
10699
10700 ud.frame_send_cb_called = 0;
10701 ud.before_frame_send_cb_called = 0;
10702 ud.frame_not_send_cb_called = 0;
10703
10704 rv = nghttp2_session_send(session);
10705
10706 CU_ASSERT(0 == rv);
10707 CU_ASSERT(0 == ud.frame_send_cb_called);
10708 CU_ASSERT(1 == ud.before_frame_send_cb_called);
10709 CU_ASSERT(1 == ud.frame_not_send_cb_called);
10710
10711 stream = nghttp2_session_get_stream_raw(session, stream_id);
10712
10713 CU_ASSERT(NULL == stream);
10714
10715 nghttp2_session_del(session);
10716 }
10717
test_nghttp2_session_too_many_settings(void)10718 void test_nghttp2_session_too_many_settings(void) {
10719 nghttp2_session *session;
10720 nghttp2_option *option;
10721 nghttp2_session_callbacks callbacks;
10722 nghttp2_frame frame;
10723 nghttp2_bufs bufs;
10724 nghttp2_buf *buf;
10725 ssize_t rv;
10726 my_user_data ud;
10727 nghttp2_settings_entry iv[3];
10728 nghttp2_mem *mem;
10729 nghttp2_outbound_item *item;
10730
10731 mem = nghttp2_mem_default();
10732 frame_pack_bufs_init(&bufs);
10733
10734 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
10735 callbacks.on_frame_recv_callback = on_frame_recv_callback;
10736 callbacks.send_callback = null_send_callback;
10737
10738 nghttp2_option_new(&option);
10739 nghttp2_option_set_max_settings(option, 1);
10740
10741 nghttp2_session_client_new2(&session, &callbacks, &ud, option);
10742
10743 CU_ASSERT(1 == session->max_settings);
10744
10745 nghttp2_option_del(option);
10746
10747 iv[0].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
10748 iv[0].value = 3000;
10749
10750 iv[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
10751 iv[1].value = 16384;
10752
10753 nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE, dup_iv(iv, 2),
10754 2);
10755
10756 rv = nghttp2_frame_pack_settings(&bufs, &frame.settings);
10757
10758 CU_ASSERT(0 == rv);
10759 CU_ASSERT(nghttp2_bufs_len(&bufs) > 0);
10760
10761 nghttp2_frame_settings_free(&frame.settings, mem);
10762
10763 buf = &bufs.head->buf;
10764 assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
10765
10766 ud.frame_recv_cb_called = 0;
10767
10768 rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
10769 CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv);
10770
10771 item = nghttp2_session_get_next_ob_item(session);
10772 CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
10773
10774 nghttp2_bufs_reset(&bufs);
10775 nghttp2_bufs_free(&bufs);
10776 nghttp2_session_del(session);
10777 }
10778
10779 static void
prepare_session_removed_closed_stream(nghttp2_session * session,nghttp2_hd_deflater * deflater)10780 prepare_session_removed_closed_stream(nghttp2_session *session,
10781 nghttp2_hd_deflater *deflater) {
10782 int rv;
10783 nghttp2_settings_entry iv;
10784 nghttp2_bufs bufs;
10785 nghttp2_mem *mem;
10786 ssize_t nread;
10787 int i;
10788 nghttp2_stream *stream;
10789 nghttp2_frame_hd hd;
10790
10791 mem = nghttp2_mem_default();
10792
10793 frame_pack_bufs_init(&bufs);
10794
10795 iv.settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS;
10796 iv.value = 2;
10797
10798 rv = nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, &iv, 1);
10799
10800 CU_ASSERT(0 == rv);
10801
10802 rv = nghttp2_session_send(session);
10803
10804 CU_ASSERT(0 == rv);
10805
10806 for (i = 1; i <= 3; i += 2) {
10807 rv = pack_headers(&bufs, deflater, i,
10808 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM, reqnv,
10809 ARRLEN(reqnv), mem);
10810
10811 CU_ASSERT(0 == rv);
10812
10813 nread = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
10814 nghttp2_bufs_len(&bufs));
10815
10816 CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == nread);
10817
10818 nghttp2_bufs_reset(&bufs);
10819 }
10820
10821 nghttp2_session_close_stream(session, 3, NGHTTP2_NO_ERROR);
10822
10823 rv = pack_headers(&bufs, deflater, 5,
10824 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM, reqnv,
10825 ARRLEN(reqnv), mem);
10826
10827 CU_ASSERT(0 == rv);
10828
10829 /* Receiving stream 5 will erase stream 3 from closed stream list */
10830 nread = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
10831 nghttp2_bufs_len(&bufs));
10832
10833 CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == nread);
10834
10835 stream = nghttp2_session_get_stream_raw(session, 3);
10836
10837 CU_ASSERT(NULL == stream);
10838
10839 /* Since the current max concurrent streams is
10840 NGHTTP2_DEFAULT_MAX_CONCURRENT_STREAMS, receiving frame on stream
10841 3 is ignored. */
10842 nghttp2_bufs_reset(&bufs);
10843 rv = pack_headers(&bufs, deflater, 3,
10844 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM,
10845 trailernv, ARRLEN(trailernv), mem);
10846
10847 CU_ASSERT(0 == rv);
10848
10849 nread = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
10850 nghttp2_bufs_len(&bufs));
10851
10852 CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == nread);
10853 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
10854
10855 nghttp2_frame_hd_init(&hd, 0, NGHTTP2_DATA, NGHTTP2_FLAG_NONE, 3);
10856 nghttp2_bufs_reset(&bufs);
10857 nghttp2_frame_pack_frame_hd(bufs.head->buf.last, &hd);
10858 bufs.head->buf.last += NGHTTP2_FRAME_HDLEN;
10859
10860 nread = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
10861 nghttp2_bufs_len(&bufs));
10862
10863 CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == nread);
10864 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
10865
10866 /* Now server receives SETTINGS ACK */
10867 nghttp2_frame_hd_init(&hd, 0, NGHTTP2_SETTINGS, NGHTTP2_FLAG_ACK, 0);
10868 nghttp2_bufs_reset(&bufs);
10869 nghttp2_frame_pack_frame_hd(bufs.head->buf.last, &hd);
10870 bufs.head->buf.last += NGHTTP2_FRAME_HDLEN;
10871
10872 nread = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
10873 nghttp2_bufs_len(&bufs));
10874
10875 CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == nread);
10876
10877 nghttp2_bufs_free(&bufs);
10878 }
10879
test_nghttp2_session_removed_closed_stream(void)10880 void test_nghttp2_session_removed_closed_stream(void) {
10881 nghttp2_session *session;
10882 nghttp2_session_callbacks callbacks;
10883 int rv;
10884 nghttp2_hd_deflater deflater;
10885 nghttp2_bufs bufs;
10886 nghttp2_mem *mem;
10887 ssize_t nread;
10888 nghttp2_frame_hd hd;
10889 nghttp2_outbound_item *item;
10890
10891 mem = nghttp2_mem_default();
10892
10893 frame_pack_bufs_init(&bufs);
10894
10895 memset(&callbacks, 0, sizeof(callbacks));
10896
10897 callbacks.send_callback = null_send_callback;
10898
10899 nghttp2_session_server_new(&session, &callbacks, NULL);
10900
10901 /* Now local max concurrent streams is still unlimited, pending max
10902 concurrent streams is now 2. */
10903
10904 nghttp2_hd_deflate_init(&deflater, mem);
10905
10906 prepare_session_removed_closed_stream(session, &deflater);
10907
10908 /* Now current max concurrent streams is 2. Receiving frame on
10909 stream 3 is ignored because we have no stream object for stream
10910 3. */
10911 nghttp2_bufs_reset(&bufs);
10912 rv = pack_headers(&bufs, &deflater, 3,
10913 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM,
10914 trailernv, ARRLEN(trailernv), mem);
10915
10916 CU_ASSERT(0 == rv);
10917
10918 nread = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
10919 nghttp2_bufs_len(&bufs));
10920
10921 CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == nread);
10922
10923 item = nghttp2_session_get_next_ob_item(session);
10924
10925 CU_ASSERT(NULL == item);
10926
10927 nghttp2_hd_deflate_free(&deflater);
10928 nghttp2_session_del(session);
10929
10930 nghttp2_session_server_new(&session, &callbacks, NULL);
10931 nghttp2_hd_deflate_init(&deflater, mem);
10932 /* Same setup, and then receive DATA instead of HEADERS */
10933
10934 prepare_session_removed_closed_stream(session, &deflater);
10935
10936 nghttp2_frame_hd_init(&hd, 0, NGHTTP2_DATA, NGHTTP2_FLAG_NONE, 3);
10937 nghttp2_bufs_reset(&bufs);
10938 nghttp2_frame_pack_frame_hd(bufs.head->buf.last, &hd);
10939 bufs.head->buf.last += NGHTTP2_FRAME_HDLEN;
10940
10941 nread = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
10942 nghttp2_bufs_len(&bufs));
10943
10944 CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == nread);
10945
10946 item = nghttp2_session_get_next_ob_item(session);
10947
10948 CU_ASSERT(NULL == item);
10949
10950 nghttp2_hd_deflate_free(&deflater);
10951 nghttp2_session_del(session);
10952
10953 nghttp2_bufs_free(&bufs);
10954 }
10955
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)10956 static ssize_t pause_once_data_source_read_callback(
10957 nghttp2_session *session, int32_t stream_id, uint8_t *buf, size_t len,
10958 uint32_t *data_flags, nghttp2_data_source *source, void *user_data) {
10959 my_user_data *ud = user_data;
10960 if (ud->data_source_read_cb_paused == 0) {
10961 ++ud->data_source_read_cb_paused;
10962 return NGHTTP2_ERR_PAUSE;
10963 }
10964
10965 return fixed_length_data_source_read_callback(session, stream_id, buf, len,
10966 data_flags, source, user_data);
10967 }
10968
test_nghttp2_session_pause_data(void)10969 void test_nghttp2_session_pause_data(void) {
10970 nghttp2_session *session;
10971 nghttp2_session_callbacks callbacks;
10972 nghttp2_data_provider data_prd;
10973 my_user_data ud;
10974
10975 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
10976 callbacks.send_callback = null_send_callback;
10977 callbacks.on_frame_send_callback = on_frame_send_callback;
10978
10979 data_prd.read_callback = pause_once_data_source_read_callback;
10980 ud.data_source_length = NGHTTP2_DATA_PAYLOADLEN;
10981
10982 nghttp2_session_server_new(&session, &callbacks, &ud);
10983
10984 open_recv_stream(session, 1);
10985
10986 CU_ASSERT(
10987 0 == nghttp2_submit_data(session, NGHTTP2_FLAG_END_STREAM, 1, &data_prd));
10988
10989 ud.frame_send_cb_called = 0;
10990 ud.data_source_read_cb_paused = 0;
10991
10992 CU_ASSERT(0 == nghttp2_session_send(session));
10993 CU_ASSERT(0 == ud.frame_send_cb_called);
10994 CU_ASSERT(NULL == session->aob.item);
10995 CU_ASSERT(0 == nghttp2_session_send(session));
10996 CU_ASSERT(1 == ud.frame_send_cb_called);
10997 CU_ASSERT(NGHTTP2_DATA == ud.sent_frame_type);
10998 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
10999
11000 nghttp2_session_del(session);
11001 }
11002
test_nghttp2_session_no_closed_streams(void)11003 void test_nghttp2_session_no_closed_streams(void) {
11004 nghttp2_session *session;
11005 nghttp2_session_callbacks callbacks;
11006 nghttp2_option *option;
11007
11008 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
11009
11010 nghttp2_option_new(&option);
11011 nghttp2_option_set_no_closed_streams(option, 1);
11012
11013 nghttp2_session_server_new2(&session, &callbacks, NULL, option);
11014
11015 open_recv_stream(session, 1);
11016
11017 nghttp2_session_close_stream(session, 1, NGHTTP2_NO_ERROR);
11018
11019 CU_ASSERT(0 == session->num_closed_streams);
11020
11021 nghttp2_session_del(session);
11022 nghttp2_option_del(option);
11023 }
11024
test_nghttp2_session_set_stream_user_data(void)11025 void test_nghttp2_session_set_stream_user_data(void) {
11026 nghttp2_session *session;
11027 nghttp2_session_callbacks callbacks;
11028 int32_t stream_id;
11029 int user_data1, user_data2;
11030 int rv;
11031 const uint8_t *datap;
11032 ssize_t datalen;
11033
11034 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
11035
11036 nghttp2_session_client_new(&session, &callbacks, NULL);
11037
11038 stream_id = nghttp2_submit_request(session, NULL, reqnv, ARRLEN(reqnv), NULL,
11039 &user_data1);
11040
11041 rv = nghttp2_session_set_stream_user_data(session, stream_id, &user_data2);
11042
11043 CU_ASSERT(0 == rv);
11044
11045 datalen = nghttp2_session_mem_send(session, &datap);
11046
11047 CU_ASSERT(datalen > 0);
11048
11049 CU_ASSERT(&user_data2 ==
11050 nghttp2_session_get_stream_user_data(session, stream_id));
11051
11052 CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT ==
11053 nghttp2_session_set_stream_user_data(session, 2, NULL));
11054
11055 nghttp2_session_del(session);
11056 }
11057
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)11058 static void check_nghttp2_http_recv_headers_fail(
11059 nghttp2_session *session, nghttp2_hd_deflater *deflater, int32_t stream_id,
11060 int stream_state, const nghttp2_nv *nva, size_t nvlen) {
11061 nghttp2_mem *mem;
11062 ssize_t rv;
11063 nghttp2_outbound_item *item;
11064 nghttp2_bufs bufs;
11065 my_user_data *ud;
11066
11067 mem = nghttp2_mem_default();
11068 frame_pack_bufs_init(&bufs);
11069
11070 ud = session->user_data;
11071
11072 if (stream_state != -1) {
11073 if (nghttp2_session_is_my_stream_id(session, stream_id)) {
11074 open_sent_stream2(session, stream_id, (nghttp2_stream_state)stream_state);
11075 } else {
11076 open_recv_stream2(session, stream_id, (nghttp2_stream_state)stream_state);
11077 }
11078 }
11079
11080 rv = pack_headers(&bufs, deflater, stream_id, NGHTTP2_FLAG_END_HEADERS, nva,
11081 nvlen, mem);
11082 CU_ASSERT(0 == rv);
11083
11084 ud->invalid_frame_recv_cb_called = 0;
11085
11086 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11087 nghttp2_buf_len(&bufs.head->buf));
11088
11089 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
11090
11091 item = nghttp2_session_get_next_ob_item(session);
11092
11093 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
11094 CU_ASSERT(1 == ud->invalid_frame_recv_cb_called);
11095
11096 CU_ASSERT(0 == nghttp2_session_send(session));
11097
11098 nghttp2_bufs_free(&bufs);
11099 }
11100
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)11101 static void check_nghttp2_http_recv_headers_ok(
11102 nghttp2_session *session, nghttp2_hd_deflater *deflater, int32_t stream_id,
11103 int stream_state, const nghttp2_nv *nva, size_t nvlen) {
11104 nghttp2_mem *mem;
11105 ssize_t rv;
11106 nghttp2_bufs bufs;
11107 my_user_data *ud;
11108
11109 mem = nghttp2_mem_default();
11110 frame_pack_bufs_init(&bufs);
11111
11112 ud = session->user_data;
11113
11114 if (stream_state != -1) {
11115 if (nghttp2_session_is_my_stream_id(session, stream_id)) {
11116 open_sent_stream2(session, stream_id, (nghttp2_stream_state)stream_state);
11117 } else {
11118 open_recv_stream2(session, stream_id, (nghttp2_stream_state)stream_state);
11119 }
11120 }
11121
11122 rv = pack_headers(&bufs, deflater, stream_id, NGHTTP2_FLAG_END_HEADERS, nva,
11123 nvlen, mem);
11124 CU_ASSERT(0 == rv);
11125
11126 ud->frame_recv_cb_called = 0;
11127
11128 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11129 nghttp2_buf_len(&bufs.head->buf));
11130
11131 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
11132 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
11133 CU_ASSERT(1 == ud->frame_recv_cb_called);
11134
11135 nghttp2_bufs_free(&bufs);
11136 }
11137
test_nghttp2_http_mandatory_headers(void)11138 void test_nghttp2_http_mandatory_headers(void) {
11139 nghttp2_session *session;
11140 nghttp2_session_callbacks callbacks;
11141 nghttp2_hd_deflater deflater;
11142 nghttp2_mem *mem;
11143 my_user_data ud;
11144 /* test case for response */
11145 const nghttp2_nv nostatus_resnv[] = {MAKE_NV("server", "foo")};
11146 const nghttp2_nv dupstatus_resnv[] = {MAKE_NV(":status", "200"),
11147 MAKE_NV(":status", "200")};
11148 const nghttp2_nv badpseudo_resnv[] = {MAKE_NV(":status", "200"),
11149 MAKE_NV(":scheme", "https")};
11150 const nghttp2_nv latepseudo_resnv[] = {MAKE_NV("server", "foo"),
11151 MAKE_NV(":status", "200")};
11152 const nghttp2_nv badstatus_resnv[] = {MAKE_NV(":status", "2000")};
11153 const nghttp2_nv badcl_resnv[] = {MAKE_NV(":status", "200"),
11154 MAKE_NV("content-length", "-1")};
11155 const nghttp2_nv dupcl_resnv[] = {MAKE_NV(":status", "200"),
11156 MAKE_NV("content-length", "0"),
11157 MAKE_NV("content-length", "0")};
11158 const nghttp2_nv badhd_resnv[] = {MAKE_NV(":status", "200"),
11159 MAKE_NV("connection", "close")};
11160 const nghttp2_nv cl1xx_resnv[] = {MAKE_NV(":status", "100"),
11161 MAKE_NV("content-length", "0")};
11162 const nghttp2_nv cl204_resnv[] = {MAKE_NV(":status", "204"),
11163 MAKE_NV("content-length", "0")};
11164 const nghttp2_nv clnonzero204_resnv[] = {MAKE_NV(":status", "204"),
11165 MAKE_NV("content-length", "100")};
11166 const nghttp2_nv status101_resnv[] = {MAKE_NV(":status", "101")};
11167
11168 /* test case for request */
11169 const nghttp2_nv nopath_reqnv[] = {MAKE_NV(":scheme", "https"),
11170 MAKE_NV(":method", "GET"),
11171 MAKE_NV(":authority", "localhost")};
11172 const nghttp2_nv earlyconnect_reqnv[] = {
11173 MAKE_NV(":method", "CONNECT"), MAKE_NV(":scheme", "https"),
11174 MAKE_NV(":path", "/"), MAKE_NV(":authority", "localhost")};
11175 const nghttp2_nv lateconnect_reqnv[] = {
11176 MAKE_NV(":scheme", "https"), MAKE_NV(":path", "/"),
11177 MAKE_NV(":method", "CONNECT"), MAKE_NV(":authority", "localhost")};
11178 const nghttp2_nv duppath_reqnv[] = {
11179 MAKE_NV(":scheme", "https"), MAKE_NV(":method", "GET"),
11180 MAKE_NV(":authority", "localhost"), MAKE_NV(":path", "/"),
11181 MAKE_NV(":path", "/")};
11182 const nghttp2_nv badcl_reqnv[] = {
11183 MAKE_NV(":scheme", "https"), MAKE_NV(":method", "POST"),
11184 MAKE_NV(":authority", "localhost"), MAKE_NV(":path", "/"),
11185 MAKE_NV("content-length", "-1")};
11186 const nghttp2_nv dupcl_reqnv[] = {
11187 MAKE_NV(":scheme", "https"), MAKE_NV(":method", "POST"),
11188 MAKE_NV(":authority", "localhost"), MAKE_NV(":path", "/"),
11189 MAKE_NV("content-length", "0"), MAKE_NV("content-length", "0")};
11190 const nghttp2_nv badhd_reqnv[] = {
11191 MAKE_NV(":scheme", "https"), MAKE_NV(":method", "GET"),
11192 MAKE_NV(":authority", "localhost"), MAKE_NV(":path", "/"),
11193 MAKE_NV("connection", "close")};
11194 const nghttp2_nv badauthority_reqnv[] = {
11195 MAKE_NV(":scheme", "https"), MAKE_NV(":method", "GET"),
11196 MAKE_NV(":authority", "\x0d\x0alocalhost"), MAKE_NV(":path", "/")};
11197 const nghttp2_nv badhdbtw_reqnv[] = {
11198 MAKE_NV(":scheme", "https"), MAKE_NV(":method", "GET"),
11199 MAKE_NV("foo", "\x0d\x0a"), MAKE_NV(":authority", "localhost"),
11200 MAKE_NV(":path", "/")};
11201 const nghttp2_nv asteriskget1_reqnv[] = {
11202 MAKE_NV(":path", "*"), MAKE_NV(":scheme", "https"),
11203 MAKE_NV(":authority", "localhost"), MAKE_NV(":method", "GET")};
11204 const nghttp2_nv asteriskget2_reqnv[] = {
11205 MAKE_NV(":scheme", "https"), MAKE_NV(":authority", "localhost"),
11206 MAKE_NV(":method", "GET"), MAKE_NV(":path", "*")};
11207 const nghttp2_nv asteriskoptions1_reqnv[] = {
11208 MAKE_NV(":path", "*"), MAKE_NV(":scheme", "https"),
11209 MAKE_NV(":authority", "localhost"), MAKE_NV(":method", "OPTIONS")};
11210 const nghttp2_nv asteriskoptions2_reqnv[] = {
11211 MAKE_NV(":scheme", "https"), MAKE_NV(":authority", "localhost"),
11212 MAKE_NV(":method", "OPTIONS"), MAKE_NV(":path", "*")};
11213 const nghttp2_nv connectproto_reqnv[] = {
11214 MAKE_NV(":scheme", "https"), MAKE_NV(":path", "/"),
11215 MAKE_NV(":method", "CONNECT"), MAKE_NV(":authority", "localhost"),
11216 MAKE_NV(":protocol", "websocket")};
11217 const nghttp2_nv connectprotoget_reqnv[] = {
11218 MAKE_NV(":scheme", "https"), MAKE_NV(":path", "/"),
11219 MAKE_NV(":method", "GET"), MAKE_NV(":authority", "localhost"),
11220 MAKE_NV(":protocol", "websocket")};
11221 const nghttp2_nv connectprotonopath_reqnv[] = {
11222 MAKE_NV(":scheme", "https"), MAKE_NV(":method", "CONNECT"),
11223 MAKE_NV(":authority", "localhost"), MAKE_NV(":protocol", "websocket")};
11224 const nghttp2_nv connectprotonoauth_reqnv[] = {
11225 MAKE_NV(":scheme", "http"), MAKE_NV(":path", "/"),
11226 MAKE_NV(":method", "CONNECT"), MAKE_NV("host", "localhost"),
11227 MAKE_NV(":protocol", "websocket")};
11228 const nghttp2_nv regularconnect_reqnv[] = {
11229 MAKE_NV(":method", "CONNECT"), MAKE_NV(":authority", "localhost")};
11230
11231 mem = nghttp2_mem_default();
11232
11233 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
11234 callbacks.send_callback = null_send_callback;
11235 callbacks.on_frame_recv_callback = on_frame_recv_callback;
11236 callbacks.on_invalid_frame_recv_callback = on_invalid_frame_recv_callback;
11237
11238 nghttp2_session_client_new(&session, &callbacks, &ud);
11239
11240 nghttp2_hd_deflate_init(&deflater, mem);
11241
11242 /* response header lacks :status */
11243 check_nghttp2_http_recv_headers_fail(session, &deflater, 1,
11244 NGHTTP2_STREAM_OPENING, nostatus_resnv,
11245 ARRLEN(nostatus_resnv));
11246
11247 /* response header has 2 :status */
11248 check_nghttp2_http_recv_headers_fail(session, &deflater, 3,
11249 NGHTTP2_STREAM_OPENING, dupstatus_resnv,
11250 ARRLEN(dupstatus_resnv));
11251
11252 /* response header has bad pseudo header :scheme */
11253 check_nghttp2_http_recv_headers_fail(session, &deflater, 5,
11254 NGHTTP2_STREAM_OPENING, badpseudo_resnv,
11255 ARRLEN(badpseudo_resnv));
11256
11257 /* response header has :status after regular header field */
11258 check_nghttp2_http_recv_headers_fail(session, &deflater, 7,
11259 NGHTTP2_STREAM_OPENING, latepseudo_resnv,
11260 ARRLEN(latepseudo_resnv));
11261
11262 /* response header has bad status code */
11263 check_nghttp2_http_recv_headers_fail(session, &deflater, 9,
11264 NGHTTP2_STREAM_OPENING, badstatus_resnv,
11265 ARRLEN(badstatus_resnv));
11266
11267 /* response header has bad content-length */
11268 check_nghttp2_http_recv_headers_fail(session, &deflater, 11,
11269 NGHTTP2_STREAM_OPENING, badcl_resnv,
11270 ARRLEN(badcl_resnv));
11271
11272 /* response header has multiple content-length */
11273 check_nghttp2_http_recv_headers_fail(session, &deflater, 13,
11274 NGHTTP2_STREAM_OPENING, dupcl_resnv,
11275 ARRLEN(dupcl_resnv));
11276
11277 /* response header has disallowed header field */
11278 check_nghttp2_http_recv_headers_fail(session, &deflater, 15,
11279 NGHTTP2_STREAM_OPENING, badhd_resnv,
11280 ARRLEN(badhd_resnv));
11281
11282 /* response header has content-length with 100 status code */
11283 check_nghttp2_http_recv_headers_fail(session, &deflater, 17,
11284 NGHTTP2_STREAM_OPENING, cl1xx_resnv,
11285 ARRLEN(cl1xx_resnv));
11286
11287 /* response header has 0 content-length with 204 status code */
11288 check_nghttp2_http_recv_headers_ok(session, &deflater, 19,
11289 NGHTTP2_STREAM_OPENING, cl204_resnv,
11290 ARRLEN(cl204_resnv));
11291
11292 /* response header has nonzero content-length with 204 status
11293 code */
11294 check_nghttp2_http_recv_headers_fail(
11295 session, &deflater, 21, NGHTTP2_STREAM_OPENING, clnonzero204_resnv,
11296 ARRLEN(clnonzero204_resnv));
11297
11298 /* status code 101 should not be used in HTTP/2 because it is used
11299 for HTTP Upgrade which HTTP/2 removes. */
11300 check_nghttp2_http_recv_headers_fail(session, &deflater, 23,
11301 NGHTTP2_STREAM_OPENING, status101_resnv,
11302 ARRLEN(status101_resnv));
11303
11304 nghttp2_hd_deflate_free(&deflater);
11305
11306 nghttp2_session_del(session);
11307
11308 /* check server side */
11309 nghttp2_session_server_new(&session, &callbacks, &ud);
11310
11311 nghttp2_hd_deflate_init(&deflater, mem);
11312
11313 /* request header has no :path */
11314 check_nghttp2_http_recv_headers_fail(session, &deflater, 1, -1, nopath_reqnv,
11315 ARRLEN(nopath_reqnv));
11316
11317 /* request header has CONNECT method, but followed by :path */
11318 check_nghttp2_http_recv_headers_fail(session, &deflater, 3, -1,
11319 earlyconnect_reqnv,
11320 ARRLEN(earlyconnect_reqnv));
11321
11322 /* request header has CONNECT method following :path */
11323 check_nghttp2_http_recv_headers_fail(
11324 session, &deflater, 5, -1, lateconnect_reqnv, ARRLEN(lateconnect_reqnv));
11325
11326 /* request header has multiple :path */
11327 check_nghttp2_http_recv_headers_fail(session, &deflater, 7, -1, duppath_reqnv,
11328 ARRLEN(duppath_reqnv));
11329
11330 /* request header has bad content-length */
11331 check_nghttp2_http_recv_headers_fail(session, &deflater, 9, -1, badcl_reqnv,
11332 ARRLEN(badcl_reqnv));
11333
11334 /* request header has multiple content-length */
11335 check_nghttp2_http_recv_headers_fail(session, &deflater, 11, -1, dupcl_reqnv,
11336 ARRLEN(dupcl_reqnv));
11337
11338 /* request header has disallowed header field */
11339 check_nghttp2_http_recv_headers_fail(session, &deflater, 13, -1, badhd_reqnv,
11340 ARRLEN(badhd_reqnv));
11341
11342 /* request header has :authority header field containing illegal
11343 characters */
11344 check_nghttp2_http_recv_headers_fail(session, &deflater, 15, -1,
11345 badauthority_reqnv,
11346 ARRLEN(badauthority_reqnv));
11347
11348 /* request header has regular header field containing illegal
11349 character before all mandatory header fields are seen. */
11350 check_nghttp2_http_recv_headers_fail(session, &deflater, 17, -1,
11351 badhdbtw_reqnv, ARRLEN(badhdbtw_reqnv));
11352
11353 /* request header has "*" in :path header field while method is GET.
11354 :path is received before :method */
11355 check_nghttp2_http_recv_headers_fail(session, &deflater, 19, -1,
11356 asteriskget1_reqnv,
11357 ARRLEN(asteriskget1_reqnv));
11358
11359 /* request header has "*" in :path header field while method is GET.
11360 :method is received before :path */
11361 check_nghttp2_http_recv_headers_fail(session, &deflater, 21, -1,
11362 asteriskget2_reqnv,
11363 ARRLEN(asteriskget2_reqnv));
11364
11365 /* OPTIONS method can include "*" in :path header field. :path is
11366 received before :method. */
11367 check_nghttp2_http_recv_headers_ok(session, &deflater, 23, -1,
11368 asteriskoptions1_reqnv,
11369 ARRLEN(asteriskoptions1_reqnv));
11370
11371 /* OPTIONS method can include "*" in :path header field. :method is
11372 received before :path. */
11373 check_nghttp2_http_recv_headers_ok(session, &deflater, 25, -1,
11374 asteriskoptions2_reqnv,
11375 ARRLEN(asteriskoptions2_reqnv));
11376
11377 /* :protocol is not allowed unless it is enabled by the local
11378 endpoint. */
11379 check_nghttp2_http_recv_headers_fail(session, &deflater, 27, -1,
11380 connectproto_reqnv,
11381 ARRLEN(connectproto_reqnv));
11382
11383 nghttp2_hd_deflate_free(&deflater);
11384
11385 nghttp2_session_del(session);
11386
11387 /* enable SETTINGS_CONNECT_PROTOCOL */
11388 nghttp2_session_server_new(&session, &callbacks, &ud);
11389
11390 session->pending_enable_connect_protocol = 1;
11391
11392 nghttp2_hd_deflate_init(&deflater, mem);
11393
11394 /* :protocol is allowed if SETTINGS_CONNECT_PROTOCOL is enabled by
11395 the local endpoint. */
11396 check_nghttp2_http_recv_headers_ok(session, &deflater, 1, -1,
11397 connectproto_reqnv,
11398 ARRLEN(connectproto_reqnv));
11399
11400 /* :protocol is only allowed with CONNECT method. */
11401 check_nghttp2_http_recv_headers_fail(session, &deflater, 3, -1,
11402 connectprotoget_reqnv,
11403 ARRLEN(connectprotoget_reqnv));
11404
11405 /* CONNECT method with :protocol requires :path. */
11406 check_nghttp2_http_recv_headers_fail(session, &deflater, 5, -1,
11407 connectprotonopath_reqnv,
11408 ARRLEN(connectprotonopath_reqnv));
11409
11410 /* CONNECT method with :protocol requires :authority. */
11411 check_nghttp2_http_recv_headers_fail(session, &deflater, 7, -1,
11412 connectprotonoauth_reqnv,
11413 ARRLEN(connectprotonoauth_reqnv));
11414
11415 /* regular CONNECT method should succeed with
11416 SETTINGS_CONNECT_PROTOCOL */
11417 check_nghttp2_http_recv_headers_ok(session, &deflater, 9, -1,
11418 regularconnect_reqnv,
11419 ARRLEN(regularconnect_reqnv));
11420
11421 nghttp2_hd_deflate_free(&deflater);
11422
11423 nghttp2_session_del(session);
11424 }
11425
test_nghttp2_http_content_length(void)11426 void test_nghttp2_http_content_length(void) {
11427 nghttp2_session *session;
11428 nghttp2_session_callbacks callbacks;
11429 nghttp2_hd_deflater deflater;
11430 nghttp2_mem *mem;
11431 nghttp2_bufs bufs;
11432 ssize_t rv;
11433 nghttp2_stream *stream;
11434 const nghttp2_nv cl_resnv[] = {MAKE_NV(":status", "200"),
11435 MAKE_NV("te", "trailers"),
11436 MAKE_NV("content-length", "9000000000")};
11437 const nghttp2_nv cl_reqnv[] = {
11438 MAKE_NV(":path", "/"), MAKE_NV(":method", "PUT"),
11439 MAKE_NV(":scheme", "https"), MAKE_NV("te", "trailers"),
11440 MAKE_NV("host", "localhost"), MAKE_NV("content-length", "9000000000")};
11441
11442 mem = nghttp2_mem_default();
11443 frame_pack_bufs_init(&bufs);
11444
11445 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
11446 callbacks.send_callback = null_send_callback;
11447
11448 nghttp2_session_client_new(&session, &callbacks, NULL);
11449
11450 nghttp2_hd_deflate_init(&deflater, mem);
11451
11452 stream = open_sent_stream2(session, 1, NGHTTP2_STREAM_OPENING);
11453
11454 rv = pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, cl_resnv,
11455 ARRLEN(cl_resnv), mem);
11456 CU_ASSERT(0 == rv);
11457
11458 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11459 nghttp2_buf_len(&bufs.head->buf));
11460
11461 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
11462 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
11463 CU_ASSERT(9000000000LL == stream->content_length);
11464 CU_ASSERT(200 == stream->status_code);
11465
11466 nghttp2_hd_deflate_free(&deflater);
11467
11468 nghttp2_session_del(session);
11469
11470 nghttp2_bufs_reset(&bufs);
11471
11472 /* check server side */
11473 nghttp2_session_server_new(&session, &callbacks, NULL);
11474
11475 nghttp2_hd_deflate_init(&deflater, mem);
11476
11477 rv = pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, cl_reqnv,
11478 ARRLEN(cl_reqnv), mem);
11479 CU_ASSERT(0 == rv);
11480
11481 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11482 nghttp2_buf_len(&bufs.head->buf));
11483
11484 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
11485
11486 stream = nghttp2_session_get_stream(session, 1);
11487
11488 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
11489 CU_ASSERT(9000000000LL == stream->content_length);
11490
11491 nghttp2_hd_deflate_free(&deflater);
11492
11493 nghttp2_session_del(session);
11494
11495 nghttp2_bufs_free(&bufs);
11496 }
11497
test_nghttp2_http_content_length_mismatch(void)11498 void test_nghttp2_http_content_length_mismatch(void) {
11499 nghttp2_session *session;
11500 nghttp2_session_callbacks callbacks;
11501 nghttp2_hd_deflater deflater;
11502 nghttp2_mem *mem;
11503 nghttp2_bufs bufs;
11504 ssize_t rv;
11505 const nghttp2_nv cl_reqnv[] = {
11506 MAKE_NV(":path", "/"), MAKE_NV(":method", "PUT"),
11507 MAKE_NV(":authority", "localhost"), MAKE_NV(":scheme", "https"),
11508 MAKE_NV("content-length", "20")};
11509 const nghttp2_nv cl_resnv[] = {MAKE_NV(":status", "200"),
11510 MAKE_NV("content-length", "20")};
11511 nghttp2_outbound_item *item;
11512 nghttp2_frame_hd hd;
11513
11514 mem = nghttp2_mem_default();
11515 frame_pack_bufs_init(&bufs);
11516
11517 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
11518 callbacks.send_callback = null_send_callback;
11519
11520 nghttp2_session_server_new(&session, &callbacks, NULL);
11521
11522 nghttp2_hd_deflate_init(&deflater, mem);
11523
11524 /* header says content-length: 20, but HEADERS has END_STREAM flag set */
11525 rv = pack_headers(&bufs, &deflater, 1,
11526 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM,
11527 cl_reqnv, ARRLEN(cl_reqnv), mem);
11528 CU_ASSERT(0 == rv);
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(0 == nghttp2_session_send(session));
11539
11540 nghttp2_bufs_reset(&bufs);
11541
11542 /* header says content-length: 20, but DATA has 0 byte */
11543 rv = pack_headers(&bufs, &deflater, 3, NGHTTP2_FLAG_END_HEADERS, cl_reqnv,
11544 ARRLEN(cl_reqnv), mem);
11545 CU_ASSERT(0 == rv);
11546
11547 nghttp2_frame_hd_init(&hd, 0, NGHTTP2_DATA, NGHTTP2_FLAG_END_STREAM, 3);
11548 nghttp2_frame_pack_frame_hd(bufs.head->buf.last, &hd);
11549 bufs.head->buf.last += NGHTTP2_FRAME_HDLEN;
11550
11551 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11552 nghttp2_buf_len(&bufs.head->buf));
11553
11554 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
11555
11556 item = nghttp2_session_get_next_ob_item(session);
11557 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
11558
11559 CU_ASSERT(0 == nghttp2_session_send(session));
11560
11561 nghttp2_bufs_reset(&bufs);
11562
11563 /* header says content-length: 20, but DATA has 21 bytes */
11564 rv = pack_headers(&bufs, &deflater, 5, NGHTTP2_FLAG_END_HEADERS, cl_reqnv,
11565 ARRLEN(cl_reqnv), mem);
11566 CU_ASSERT(0 == rv);
11567
11568 nghttp2_frame_hd_init(&hd, 21, NGHTTP2_DATA, NGHTTP2_FLAG_END_STREAM, 5);
11569 nghttp2_frame_pack_frame_hd(bufs.head->buf.last, &hd);
11570 bufs.head->buf.last += NGHTTP2_FRAME_HDLEN + 21;
11571
11572 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11573 nghttp2_buf_len(&bufs.head->buf));
11574
11575 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
11576
11577 item = nghttp2_session_get_next_ob_item(session);
11578 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
11579
11580 CU_ASSERT(0 == nghttp2_session_send(session));
11581
11582 nghttp2_bufs_reset(&bufs);
11583
11584 nghttp2_hd_deflate_free(&deflater);
11585
11586 nghttp2_session_del(session);
11587
11588 /* Check for client */
11589 nghttp2_session_client_new(&session, &callbacks, NULL);
11590
11591 nghttp2_hd_deflate_init(&deflater, mem);
11592
11593 /* header says content-length: 20, but HEADERS has END_STREAM flag set */
11594 nghttp2_submit_request(session, NULL, reqnv, ARRLEN(reqnv), NULL, NULL);
11595
11596 CU_ASSERT(0 == nghttp2_session_send(session));
11597
11598 rv = pack_headers(&bufs, &deflater, 1,
11599 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM,
11600 cl_resnv, ARRLEN(cl_resnv), mem);
11601 CU_ASSERT(0 == rv);
11602
11603 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11604 nghttp2_buf_len(&bufs.head->buf));
11605
11606 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
11607
11608 item = nghttp2_session_get_next_ob_item(session);
11609 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
11610
11611 CU_ASSERT(NULL != nghttp2_session_get_stream(session, 1));
11612 CU_ASSERT(0 == nghttp2_session_send(session));
11613 /* After sending RST_STREAM, stream must be closed */
11614 CU_ASSERT(NULL == nghttp2_session_get_stream(session, 1));
11615
11616 nghttp2_bufs_reset(&bufs);
11617
11618 /* header says content-length: 20, but DATA has 0 byte */
11619 nghttp2_submit_request(session, NULL, reqnv, ARRLEN(reqnv), NULL, NULL);
11620
11621 CU_ASSERT(0 == nghttp2_session_send(session));
11622
11623 rv = pack_headers(&bufs, &deflater, 3, NGHTTP2_FLAG_END_HEADERS, cl_resnv,
11624 ARRLEN(cl_resnv), mem);
11625 CU_ASSERT(0 == rv);
11626
11627 nghttp2_frame_hd_init(&hd, 0, NGHTTP2_DATA, NGHTTP2_FLAG_END_STREAM, 3);
11628 nghttp2_frame_pack_frame_hd(bufs.head->buf.last, &hd);
11629 bufs.head->buf.last += NGHTTP2_FRAME_HDLEN;
11630
11631 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11632 nghttp2_buf_len(&bufs.head->buf));
11633
11634 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
11635
11636 item = nghttp2_session_get_next_ob_item(session);
11637 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
11638
11639 CU_ASSERT(NULL != nghttp2_session_get_stream(session, 3));
11640 CU_ASSERT(0 == nghttp2_session_send(session));
11641 /* After sending RST_STREAM, stream must be closed */
11642 CU_ASSERT(NULL == nghttp2_session_get_stream(session, 3));
11643
11644 nghttp2_bufs_reset(&bufs);
11645
11646 /* header says content-length: 20, but DATA has 21 bytes */
11647 nghttp2_submit_request(session, NULL, reqnv, ARRLEN(reqnv), NULL, NULL);
11648
11649 CU_ASSERT(0 == nghttp2_session_send(session));
11650
11651 rv = pack_headers(&bufs, &deflater, 5, NGHTTP2_FLAG_END_HEADERS, cl_resnv,
11652 ARRLEN(cl_resnv), mem);
11653 CU_ASSERT(0 == rv);
11654
11655 nghttp2_frame_hd_init(&hd, 21, NGHTTP2_DATA, NGHTTP2_FLAG_END_STREAM, 5);
11656 nghttp2_frame_pack_frame_hd(bufs.head->buf.last, &hd);
11657 bufs.head->buf.last += NGHTTP2_FRAME_HDLEN + 21;
11658
11659 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11660 nghttp2_buf_len(&bufs.head->buf));
11661
11662 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
11663
11664 item = nghttp2_session_get_next_ob_item(session);
11665 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
11666
11667 CU_ASSERT(NULL != nghttp2_session_get_stream(session, 5));
11668 CU_ASSERT(0 == nghttp2_session_send(session));
11669 /* After sending RST_STREAM, stream must be closed */
11670 CU_ASSERT(NULL == nghttp2_session_get_stream(session, 5));
11671
11672 nghttp2_bufs_reset(&bufs);
11673
11674 nghttp2_bufs_free(&bufs);
11675
11676 nghttp2_hd_deflate_free(&deflater);
11677
11678 nghttp2_session_del(session);
11679 }
11680
test_nghttp2_http_non_final_response(void)11681 void test_nghttp2_http_non_final_response(void) {
11682 nghttp2_session *session;
11683 nghttp2_session_callbacks callbacks;
11684 nghttp2_hd_deflater deflater;
11685 nghttp2_mem *mem;
11686 nghttp2_bufs bufs;
11687 ssize_t rv;
11688 const nghttp2_nv nonfinal_resnv[] = {
11689 MAKE_NV(":status", "100"),
11690 };
11691 nghttp2_outbound_item *item;
11692 nghttp2_frame_hd hd;
11693
11694 mem = nghttp2_mem_default();
11695 frame_pack_bufs_init(&bufs);
11696
11697 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
11698 callbacks.send_callback = null_send_callback;
11699
11700 nghttp2_session_client_new(&session, &callbacks, NULL);
11701
11702 nghttp2_hd_deflate_init(&deflater, mem);
11703
11704 /* non-final HEADERS with END_STREAM is illegal */
11705 open_sent_stream2(session, 1, NGHTTP2_STREAM_OPENING);
11706
11707 rv = pack_headers(&bufs, &deflater, 1,
11708 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM,
11709 nonfinal_resnv, ARRLEN(nonfinal_resnv), mem);
11710 CU_ASSERT(0 == rv);
11711
11712 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11713 nghttp2_buf_len(&bufs.head->buf));
11714
11715 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
11716
11717 item = nghttp2_session_get_next_ob_item(session);
11718 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
11719
11720 CU_ASSERT(0 == nghttp2_session_send(session));
11721
11722 nghttp2_bufs_reset(&bufs);
11723
11724 /* non-final HEADERS followed by non-empty DATA is illegal */
11725 open_sent_stream2(session, 3, NGHTTP2_STREAM_OPENING);
11726
11727 rv = pack_headers(&bufs, &deflater, 3, NGHTTP2_FLAG_END_HEADERS,
11728 nonfinal_resnv, ARRLEN(nonfinal_resnv), mem);
11729 CU_ASSERT(0 == rv);
11730
11731 nghttp2_frame_hd_init(&hd, 10, NGHTTP2_DATA, NGHTTP2_FLAG_END_STREAM, 3);
11732 nghttp2_frame_pack_frame_hd(bufs.head->buf.last, &hd);
11733 bufs.head->buf.last += NGHTTP2_FRAME_HDLEN + 10;
11734
11735 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11736 nghttp2_buf_len(&bufs.head->buf));
11737
11738 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
11739
11740 item = nghttp2_session_get_next_ob_item(session);
11741 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
11742
11743 CU_ASSERT(0 == nghttp2_session_send(session));
11744
11745 nghttp2_bufs_reset(&bufs);
11746
11747 /* non-final HEADERS followed by empty DATA (without END_STREAM) is
11748 ok */
11749 open_sent_stream2(session, 5, NGHTTP2_STREAM_OPENING);
11750
11751 rv = pack_headers(&bufs, &deflater, 5, NGHTTP2_FLAG_END_HEADERS,
11752 nonfinal_resnv, ARRLEN(nonfinal_resnv), mem);
11753 CU_ASSERT(0 == rv);
11754
11755 nghttp2_frame_hd_init(&hd, 0, NGHTTP2_DATA, NGHTTP2_FLAG_NONE, 5);
11756 nghttp2_frame_pack_frame_hd(bufs.head->buf.last, &hd);
11757 bufs.head->buf.last += NGHTTP2_FRAME_HDLEN;
11758
11759 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11760 nghttp2_buf_len(&bufs.head->buf));
11761
11762 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
11763
11764 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
11765
11766 nghttp2_bufs_reset(&bufs);
11767
11768 /* non-final HEADERS followed by empty DATA (with END_STREAM) is
11769 illegal */
11770 open_sent_stream2(session, 7, NGHTTP2_STREAM_OPENING);
11771
11772 rv = pack_headers(&bufs, &deflater, 7, NGHTTP2_FLAG_END_HEADERS,
11773 nonfinal_resnv, ARRLEN(nonfinal_resnv), mem);
11774 CU_ASSERT(0 == rv);
11775
11776 nghttp2_frame_hd_init(&hd, 0, NGHTTP2_DATA, NGHTTP2_FLAG_END_STREAM, 7);
11777 nghttp2_frame_pack_frame_hd(bufs.head->buf.last, &hd);
11778 bufs.head->buf.last += NGHTTP2_FRAME_HDLEN;
11779
11780 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11781 nghttp2_buf_len(&bufs.head->buf));
11782
11783 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
11784
11785 item = nghttp2_session_get_next_ob_item(session);
11786
11787 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
11788
11789 CU_ASSERT(0 == nghttp2_session_send(session));
11790
11791 nghttp2_bufs_reset(&bufs);
11792
11793 /* non-final HEADERS followed by final HEADERS is OK */
11794 open_sent_stream2(session, 9, NGHTTP2_STREAM_OPENING);
11795
11796 rv = pack_headers(&bufs, &deflater, 9, NGHTTP2_FLAG_END_HEADERS,
11797 nonfinal_resnv, ARRLEN(nonfinal_resnv), mem);
11798 CU_ASSERT(0 == rv);
11799
11800 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11801 nghttp2_buf_len(&bufs.head->buf));
11802
11803 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
11804
11805 nghttp2_bufs_reset(&bufs);
11806
11807 rv = pack_headers(&bufs, &deflater, 9, NGHTTP2_FLAG_END_HEADERS, resnv,
11808 ARRLEN(resnv), mem);
11809 CU_ASSERT(0 == rv);
11810
11811 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11812 nghttp2_buf_len(&bufs.head->buf));
11813
11814 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
11815
11816 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
11817
11818 nghttp2_bufs_reset(&bufs);
11819
11820 nghttp2_hd_deflate_free(&deflater);
11821
11822 nghttp2_session_del(session);
11823
11824 nghttp2_bufs_free(&bufs);
11825 }
11826
test_nghttp2_http_trailer_headers(void)11827 void test_nghttp2_http_trailer_headers(void) {
11828 nghttp2_session *session;
11829 nghttp2_session_callbacks callbacks;
11830 nghttp2_hd_deflater deflater;
11831 nghttp2_mem *mem;
11832 nghttp2_bufs bufs;
11833 ssize_t rv;
11834 const nghttp2_nv trailer_reqnv[] = {
11835 MAKE_NV("foo", "bar"),
11836 };
11837 nghttp2_outbound_item *item;
11838
11839 mem = nghttp2_mem_default();
11840 frame_pack_bufs_init(&bufs);
11841
11842 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
11843 callbacks.send_callback = null_send_callback;
11844
11845 nghttp2_session_server_new(&session, &callbacks, NULL);
11846
11847 nghttp2_hd_deflate_init(&deflater, mem);
11848
11849 /* good trailer header */
11850 rv = pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, reqnv,
11851 ARRLEN(reqnv), mem);
11852 CU_ASSERT(0 == rv);
11853
11854 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11855 nghttp2_buf_len(&bufs.head->buf));
11856
11857 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
11858
11859 nghttp2_bufs_reset(&bufs);
11860
11861 rv = pack_headers(&bufs, &deflater, 1,
11862 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM,
11863 trailer_reqnv, ARRLEN(trailer_reqnv), mem);
11864 CU_ASSERT(0 == rv);
11865
11866 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11867 nghttp2_buf_len(&bufs.head->buf));
11868
11869 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
11870
11871 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
11872
11873 nghttp2_bufs_reset(&bufs);
11874
11875 /* trailer header without END_STREAM is illegal */
11876 rv = pack_headers(&bufs, &deflater, 3, NGHTTP2_FLAG_END_HEADERS, reqnv,
11877 ARRLEN(reqnv), mem);
11878 CU_ASSERT(0 == rv);
11879
11880 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11881 nghttp2_buf_len(&bufs.head->buf));
11882
11883 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
11884
11885 nghttp2_bufs_reset(&bufs);
11886
11887 rv = pack_headers(&bufs, &deflater, 3, NGHTTP2_FLAG_END_HEADERS,
11888 trailer_reqnv, ARRLEN(trailer_reqnv), mem);
11889 CU_ASSERT(0 == rv);
11890
11891 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11892 nghttp2_buf_len(&bufs.head->buf));
11893
11894 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
11895
11896 item = nghttp2_session_get_next_ob_item(session);
11897
11898 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
11899
11900 CU_ASSERT(0 == nghttp2_session_send(session));
11901
11902 nghttp2_bufs_reset(&bufs);
11903
11904 /* trailer header including pseudo header field is illegal */
11905 rv = pack_headers(&bufs, &deflater, 5, NGHTTP2_FLAG_END_HEADERS, reqnv,
11906 ARRLEN(reqnv), mem);
11907 CU_ASSERT(0 == rv);
11908
11909 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11910 nghttp2_buf_len(&bufs.head->buf));
11911
11912 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
11913
11914 nghttp2_bufs_reset(&bufs);
11915
11916 rv = pack_headers(&bufs, &deflater, 5, NGHTTP2_FLAG_END_HEADERS, reqnv,
11917 ARRLEN(reqnv), mem);
11918 CU_ASSERT(0 == rv);
11919
11920 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
11921 nghttp2_buf_len(&bufs.head->buf));
11922
11923 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
11924
11925 item = nghttp2_session_get_next_ob_item(session);
11926
11927 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
11928
11929 CU_ASSERT(0 == nghttp2_session_send(session));
11930
11931 nghttp2_bufs_reset(&bufs);
11932
11933 nghttp2_hd_deflate_free(&deflater);
11934
11935 nghttp2_session_del(session);
11936
11937 nghttp2_bufs_free(&bufs);
11938 }
11939
test_nghttp2_http_ignore_regular_header(void)11940 void test_nghttp2_http_ignore_regular_header(void) {
11941 nghttp2_session *session;
11942 nghttp2_session_callbacks callbacks;
11943 nghttp2_hd_deflater deflater;
11944 nghttp2_mem *mem;
11945 nghttp2_bufs bufs;
11946 ssize_t rv;
11947 my_user_data ud;
11948 const nghttp2_nv bad_reqnv[] = {
11949 MAKE_NV(":authority", "localhost"),
11950 MAKE_NV(":scheme", "https"),
11951 MAKE_NV(":path", "/"),
11952 MAKE_NV(":method", "GET"),
11953 MAKE_NV("foo", "\x0zzz"),
11954 MAKE_NV("bar", "buzz"),
11955 };
11956 const nghttp2_nv bad_ansnv[] = {
11957 MAKE_NV(":authority", "localhost"), MAKE_NV(":scheme", "https"),
11958 MAKE_NV(":path", "/"), MAKE_NV(":method", "GET"), MAKE_NV("bar", "buzz")};
11959 size_t proclen;
11960 size_t i;
11961 nghttp2_outbound_item *item;
11962
11963 mem = nghttp2_mem_default();
11964 frame_pack_bufs_init(&bufs);
11965
11966 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
11967 callbacks.send_callback = null_send_callback;
11968 callbacks.on_header_callback = pause_on_header_callback;
11969
11970 nghttp2_session_server_new(&session, &callbacks, &ud);
11971 nghttp2_hd_deflate_init(&deflater, mem);
11972
11973 rv = pack_headers(&bufs, &deflater, 1,
11974 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM,
11975 bad_reqnv, ARRLEN(bad_reqnv), mem);
11976
11977 CU_ASSERT_FATAL(0 == rv);
11978
11979 nghttp2_hd_deflate_free(&deflater);
11980
11981 proclen = 0;
11982
11983 for (i = 0; i < 4; ++i) {
11984 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos + proclen,
11985 nghttp2_buf_len(&bufs.head->buf) - proclen);
11986 CU_ASSERT_FATAL(rv > 0);
11987 proclen += (size_t)rv;
11988 CU_ASSERT(nghttp2_nv_equal(&bad_ansnv[i], &ud.nv));
11989 }
11990
11991 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos + proclen,
11992 nghttp2_buf_len(&bufs.head->buf) - proclen);
11993 CU_ASSERT_FATAL(rv > 0);
11994 /* Without on_invalid_frame_recv_callback, bad header causes stream
11995 reset */
11996 item = nghttp2_session_get_next_ob_item(session);
11997
11998 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
11999
12000 proclen += (size_t)rv;
12001
12002 CU_ASSERT(nghttp2_buf_len(&bufs.head->buf) == proclen);
12003
12004 nghttp2_session_del(session);
12005
12006 /* use on_invalid_header_callback */
12007 callbacks.on_invalid_header_callback = pause_on_invalid_header_callback;
12008
12009 nghttp2_session_server_new(&session, &callbacks, &ud);
12010
12011 proclen = 0;
12012
12013 ud.invalid_header_cb_called = 0;
12014
12015 for (i = 0; i < 4; ++i) {
12016 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos + proclen,
12017 nghttp2_buf_len(&bufs.head->buf) - proclen);
12018 CU_ASSERT_FATAL(rv > 0);
12019 proclen += (size_t)rv;
12020 CU_ASSERT(nghttp2_nv_equal(&bad_ansnv[i], &ud.nv));
12021 }
12022
12023 CU_ASSERT(0 == ud.invalid_header_cb_called);
12024
12025 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos + proclen,
12026 nghttp2_buf_len(&bufs.head->buf) - proclen);
12027
12028 CU_ASSERT_FATAL(rv > 0);
12029 CU_ASSERT(1 == ud.invalid_header_cb_called);
12030 CU_ASSERT(nghttp2_nv_equal(&bad_reqnv[4], &ud.nv));
12031
12032 proclen += (size_t)rv;
12033
12034 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos + proclen,
12035 nghttp2_buf_len(&bufs.head->buf) - proclen);
12036
12037 CU_ASSERT(rv > 0);
12038 CU_ASSERT(nghttp2_nv_equal(&bad_ansnv[4], &ud.nv));
12039
12040 nghttp2_session_del(session);
12041
12042 /* make sure that we can reset stream from
12043 on_invalid_header_callback */
12044 callbacks.on_header_callback = on_header_callback;
12045 callbacks.on_invalid_header_callback = reset_on_invalid_header_callback;
12046
12047 nghttp2_session_server_new(&session, &callbacks, &ud);
12048
12049 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
12050 nghttp2_buf_len(&bufs.head->buf));
12051
12052 CU_ASSERT(rv == (ssize_t)nghttp2_buf_len(&bufs.head->buf));
12053
12054 item = nghttp2_session_get_next_ob_item(session);
12055
12056 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
12057 CU_ASSERT(1 == item->frame.hd.stream_id);
12058
12059 nghttp2_session_del(session);
12060 nghttp2_bufs_free(&bufs);
12061 }
12062
test_nghttp2_http_ignore_content_length(void)12063 void test_nghttp2_http_ignore_content_length(void) {
12064 nghttp2_session *session;
12065 nghttp2_session_callbacks callbacks;
12066 nghttp2_hd_deflater deflater;
12067 nghttp2_mem *mem;
12068 nghttp2_bufs bufs;
12069 ssize_t rv;
12070 const nghttp2_nv cl_resnv[] = {MAKE_NV(":status", "304"),
12071 MAKE_NV("content-length", "20")};
12072 const nghttp2_nv conn_reqnv[] = {MAKE_NV(":authority", "localhost"),
12073 MAKE_NV(":method", "CONNECT"),
12074 MAKE_NV("content-length", "999999")};
12075 const nghttp2_nv conn_cl_resnv[] = {MAKE_NV(":status", "200"),
12076 MAKE_NV("content-length", "0")};
12077 nghttp2_stream *stream;
12078
12079 mem = nghttp2_mem_default();
12080 frame_pack_bufs_init(&bufs);
12081
12082 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
12083 callbacks.send_callback = null_send_callback;
12084
12085 nghttp2_session_client_new(&session, &callbacks, NULL);
12086
12087 nghttp2_hd_deflate_init(&deflater, mem);
12088
12089 /* If status 304, content-length must be ignored */
12090 open_sent_stream2(session, 1, NGHTTP2_STREAM_OPENING);
12091
12092 rv = pack_headers(&bufs, &deflater, 1,
12093 NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM,
12094 cl_resnv, ARRLEN(cl_resnv), mem);
12095 CU_ASSERT(0 == rv);
12096
12097 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
12098 nghttp2_buf_len(&bufs.head->buf));
12099
12100 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
12101
12102 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
12103
12104 nghttp2_bufs_reset(&bufs);
12105
12106 /* Content-Length in 200 response to CONNECT is ignored */
12107 stream = open_sent_stream2(session, 3, NGHTTP2_STREAM_OPENING);
12108 stream->http_flags |= NGHTTP2_HTTP_FLAG_METH_CONNECT;
12109
12110 rv = pack_headers(&bufs, &deflater, 3, NGHTTP2_FLAG_END_HEADERS,
12111 conn_cl_resnv, ARRLEN(conn_cl_resnv), mem);
12112 CU_ASSERT(0 == rv);
12113
12114 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
12115 nghttp2_buf_len(&bufs.head->buf));
12116
12117 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
12118
12119 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
12120 CU_ASSERT(-1 == stream->content_length);
12121
12122 nghttp2_bufs_reset(&bufs);
12123
12124 nghttp2_hd_deflate_free(&deflater);
12125 nghttp2_session_del(session);
12126
12127 /* If request method is CONNECT, content-length must be ignored */
12128 nghttp2_session_server_new(&session, &callbacks, NULL);
12129
12130 nghttp2_hd_deflate_init(&deflater, mem);
12131
12132 rv = pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, conn_reqnv,
12133 ARRLEN(conn_reqnv), mem);
12134
12135 CU_ASSERT(0 == rv);
12136
12137 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
12138 nghttp2_buf_len(&bufs.head->buf));
12139
12140 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
12141
12142 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
12143
12144 stream = nghttp2_session_get_stream(session, 1);
12145
12146 CU_ASSERT(-1 == stream->content_length);
12147 CU_ASSERT((stream->http_flags & NGHTTP2_HTTP_FLAG_METH_CONNECT) > 0);
12148
12149 nghttp2_hd_deflate_free(&deflater);
12150 nghttp2_session_del(session);
12151 nghttp2_bufs_free(&bufs);
12152 }
12153
test_nghttp2_http_record_request_method(void)12154 void test_nghttp2_http_record_request_method(void) {
12155 nghttp2_session *session;
12156 nghttp2_session_callbacks callbacks;
12157 const nghttp2_nv conn_reqnv[] = {MAKE_NV(":method", "CONNECT"),
12158 MAKE_NV(":authority", "localhost")};
12159 const nghttp2_nv conn_resnv[] = {MAKE_NV(":status", "200"),
12160 MAKE_NV("content-length", "9999")};
12161 nghttp2_stream *stream;
12162 ssize_t rv;
12163 nghttp2_bufs bufs;
12164 nghttp2_hd_deflater deflater;
12165 nghttp2_mem *mem;
12166 nghttp2_outbound_item *item;
12167
12168 mem = nghttp2_mem_default();
12169 frame_pack_bufs_init(&bufs);
12170
12171 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
12172 callbacks.send_callback = null_send_callback;
12173
12174 nghttp2_session_client_new(&session, &callbacks, NULL);
12175
12176 nghttp2_hd_deflate_init(&deflater, mem);
12177
12178 CU_ASSERT(1 == nghttp2_submit_request(session, NULL, conn_reqnv,
12179 ARRLEN(conn_reqnv), NULL, NULL));
12180
12181 CU_ASSERT(0 == nghttp2_session_send(session));
12182
12183 stream = nghttp2_session_get_stream(session, 1);
12184
12185 CU_ASSERT(NGHTTP2_HTTP_FLAG_METH_CONNECT == stream->http_flags);
12186
12187 rv = pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, conn_resnv,
12188 ARRLEN(conn_resnv), mem);
12189 CU_ASSERT(0 == rv);
12190
12191 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
12192 nghttp2_buf_len(&bufs.head->buf));
12193
12194 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
12195
12196 CU_ASSERT((NGHTTP2_HTTP_FLAG_METH_CONNECT & stream->http_flags) > 0);
12197 CU_ASSERT(-1 == stream->content_length);
12198
12199 /* content-length is ignored in 200 response to a CONNECT request */
12200 item = nghttp2_session_get_next_ob_item(session);
12201
12202 CU_ASSERT(NULL == item);
12203
12204 nghttp2_hd_deflate_free(&deflater);
12205 nghttp2_session_del(session);
12206 nghttp2_bufs_free(&bufs);
12207 }
12208
test_nghttp2_http_push_promise(void)12209 void test_nghttp2_http_push_promise(void) {
12210 nghttp2_session *session;
12211 nghttp2_session_callbacks callbacks;
12212 nghttp2_hd_deflater deflater;
12213 nghttp2_mem *mem;
12214 nghttp2_bufs bufs;
12215 ssize_t rv;
12216 nghttp2_stream *stream;
12217 const nghttp2_nv bad_reqnv[] = {MAKE_NV(":method", "GET")};
12218 nghttp2_outbound_item *item;
12219
12220 mem = nghttp2_mem_default();
12221 frame_pack_bufs_init(&bufs);
12222
12223 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
12224 callbacks.send_callback = null_send_callback;
12225
12226 /* good PUSH_PROMISE case */
12227 nghttp2_session_client_new(&session, &callbacks, NULL);
12228
12229 nghttp2_hd_deflate_init(&deflater, mem);
12230
12231 open_sent_stream2(session, 1, NGHTTP2_STREAM_OPENING);
12232
12233 rv = pack_push_promise(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, 2,
12234 reqnv, ARRLEN(reqnv), mem);
12235 CU_ASSERT(0 == rv);
12236
12237 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
12238 nghttp2_buf_len(&bufs.head->buf));
12239
12240 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
12241
12242 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
12243
12244 stream = nghttp2_session_get_stream(session, 2);
12245 CU_ASSERT(NULL != stream);
12246
12247 nghttp2_bufs_reset(&bufs);
12248
12249 rv = pack_headers(&bufs, &deflater, 2, NGHTTP2_FLAG_END_HEADERS, resnv,
12250 ARRLEN(resnv), mem);
12251
12252 CU_ASSERT(0 == rv);
12253
12254 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
12255 nghttp2_buf_len(&bufs.head->buf));
12256
12257 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
12258
12259 CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
12260
12261 CU_ASSERT(200 == stream->status_code);
12262
12263 nghttp2_bufs_reset(&bufs);
12264
12265 /* PUSH_PROMISE lacks mandatory header */
12266 rv = pack_push_promise(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, 4,
12267 bad_reqnv, ARRLEN(bad_reqnv), mem);
12268
12269 CU_ASSERT(0 == rv);
12270
12271 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
12272 nghttp2_buf_len(&bufs.head->buf));
12273
12274 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
12275
12276 item = nghttp2_session_get_next_ob_item(session);
12277
12278 CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
12279 CU_ASSERT(4 == item->frame.hd.stream_id);
12280
12281 nghttp2_bufs_reset(&bufs);
12282
12283 nghttp2_hd_deflate_free(&deflater);
12284 nghttp2_session_del(session);
12285 nghttp2_bufs_free(&bufs);
12286 }
12287
test_nghttp2_http_head_method_upgrade_workaround(void)12288 void test_nghttp2_http_head_method_upgrade_workaround(void) {
12289 nghttp2_session *session;
12290 nghttp2_session_callbacks callbacks;
12291 const nghttp2_nv cl_resnv[] = {MAKE_NV(":status", "200"),
12292 MAKE_NV("content-length", "1000000007")};
12293 nghttp2_bufs bufs;
12294 nghttp2_hd_deflater deflater;
12295 nghttp2_mem *mem;
12296 ssize_t rv;
12297 nghttp2_stream *stream;
12298
12299 mem = nghttp2_mem_default();
12300 frame_pack_bufs_init(&bufs);
12301
12302 memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
12303 callbacks.send_callback = null_send_callback;
12304
12305 nghttp2_session_client_new(&session, &callbacks, NULL);
12306
12307 nghttp2_hd_deflate_init(&deflater, mem);
12308
12309 nghttp2_session_upgrade(session, NULL, 0, NULL);
12310
12311 rv = pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, cl_resnv,
12312 ARRLEN(cl_resnv), mem);
12313
12314 CU_ASSERT(0 == rv);
12315
12316 rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos,
12317 nghttp2_buf_len(&bufs.head->buf));
12318
12319 CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv);
12320
12321 stream = nghttp2_session_get_stream(session, 1);
12322
12323 CU_ASSERT(-1 == stream->content_length);
12324
12325 nghttp2_hd_deflate_free(&deflater);
12326 nghttp2_session_del(session);
12327 nghttp2_bufs_free(&bufs);
12328 }
12329