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