@@ -497,6 +497,7 @@ static int session_new(nghttp2_session **session_ptr,
497
497
(* session_ptr )-> max_send_header_block_length = NGHTTP2_MAX_HEADERSLEN ;
498
498
(* session_ptr )-> max_outbound_ack = NGHTTP2_DEFAULT_MAX_OBQ_FLOOD_ITEM ;
499
499
(* session_ptr )-> max_settings = NGHTTP2_DEFAULT_MAX_SETTINGS ;
500
+ (* session_ptr )-> max_continuations = NGHTTP2_DEFAULT_MAX_CONTINUATIONS ;
500
501
501
502
if (option ) {
502
503
if ((option -> opt_set_mask & NGHTTP2_OPT_NO_AUTO_WINDOW_UPDATE ) &&
@@ -585,6 +586,10 @@ static int session_new(nghttp2_session **session_ptr,
585
586
option -> stream_reset_burst ,
586
587
option -> stream_reset_rate );
587
588
}
589
+
590
+ if (option -> opt_set_mask & NGHTTP2_OPT_MAX_CONTINUATIONS ) {
591
+ (* session_ptr )-> max_continuations = option -> max_continuations ;
592
+ }
588
593
}
589
594
590
595
rv = nghttp2_hd_deflate_init2 (& (* session_ptr )-> hd_deflater ,
@@ -979,7 +984,14 @@ static int session_attach_stream_item(nghttp2_session *session,
979
984
return 0 ;
980
985
}
981
986
982
- return session_ob_data_push (session , stream );
987
+ rv = session_ob_data_push (session , stream );
988
+ if (rv != 0 ) {
989
+ nghttp2_stream_detach_item (stream );
990
+
991
+ return rv ;
992
+ }
993
+
994
+ return 0 ;
983
995
}
984
996
985
997
static void session_detach_stream_item (nghttp2_session * session ,
@@ -1309,9 +1321,11 @@ nghttp2_stream *nghttp2_session_open_stream(nghttp2_session *session,
1309
1321
assert ((stream -> flags & NGHTTP2_STREAM_FLAG_NO_RFC7540_PRIORITIES ) ||
1310
1322
nghttp2_stream_in_dep_tree (stream ));
1311
1323
1324
+ nghttp2_session_detach_idle_stream (session , stream );
1325
+
1312
1326
if (nghttp2_stream_in_dep_tree (stream )) {
1313
1327
assert (!(stream -> flags & NGHTTP2_STREAM_FLAG_NO_RFC7540_PRIORITIES ));
1314
- nghttp2_session_detach_idle_stream ( session , stream );
1328
+
1315
1329
rv = nghttp2_stream_dep_remove (stream );
1316
1330
if (rv != 0 ) {
1317
1331
return NULL ;
@@ -1471,6 +1485,21 @@ int nghttp2_session_close_stream(nghttp2_session *session, int32_t stream_id,
1471
1485
1472
1486
DEBUGF ("stream: stream(%p)=%d close\n" , stream , stream -> stream_id );
1473
1487
1488
+ /* We call on_stream_close_callback even if stream->state is
1489
+ NGHTTP2_STREAM_INITIAL. This will happen while sending request
1490
+ HEADERS, a local endpoint receives RST_STREAM for that stream. It
1491
+ may be PROTOCOL_ERROR, but without notifying stream closure will
1492
+ hang the stream in a local endpoint.
1493
+ */
1494
+
1495
+ if (session -> callbacks .on_stream_close_callback ) {
1496
+ if (session -> callbacks .on_stream_close_callback (
1497
+ session , stream_id , error_code , session -> user_data ) != 0 ) {
1498
+
1499
+ return NGHTTP2_ERR_CALLBACK_FAILURE ;
1500
+ }
1501
+ }
1502
+
1474
1503
if (stream -> item ) {
1475
1504
nghttp2_outbound_item * item ;
1476
1505
@@ -1488,21 +1517,6 @@ int nghttp2_session_close_stream(nghttp2_session *session, int32_t stream_id,
1488
1517
}
1489
1518
}
1490
1519
1491
- /* We call on_stream_close_callback even if stream->state is
1492
- NGHTTP2_STREAM_INITIAL. This will happen while sending request
1493
- HEADERS, a local endpoint receives RST_STREAM for that stream. It
1494
- may be PROTOCOL_ERROR, but without notifying stream closure will
1495
- hang the stream in a local endpoint.
1496
- */
1497
-
1498
- if (session -> callbacks .on_stream_close_callback ) {
1499
- if (session -> callbacks .on_stream_close_callback (
1500
- session , stream_id , error_code , session -> user_data ) != 0 ) {
1501
-
1502
- return NGHTTP2_ERR_CALLBACK_FAILURE ;
1503
- }
1504
- }
1505
-
1506
1520
is_my_stream_id = nghttp2_session_is_my_stream_id (session , stream_id );
1507
1521
1508
1522
/* pushed streams which is not opened yet is not counted toward max
@@ -1559,6 +1573,11 @@ int nghttp2_session_destroy_stream(nghttp2_session *session,
1559
1573
}
1560
1574
}
1561
1575
1576
+ if (stream -> queued &&
1577
+ (stream -> flags & NGHTTP2_STREAM_FLAG_NO_RFC7540_PRIORITIES )) {
1578
+ session_ob_data_remove (session , stream );
1579
+ }
1580
+
1562
1581
nghttp2_map_remove (& session -> streams , stream -> stream_id );
1563
1582
nghttp2_stream_free (stream );
1564
1583
nghttp2_mem_free (mem , stream );
@@ -6812,6 +6831,8 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session,
6812
6831
}
6813
6832
}
6814
6833
session_inbound_frame_reset (session );
6834
+
6835
+ session -> num_continuations = 0 ;
6815
6836
}
6816
6837
break ;
6817
6838
}
@@ -6933,6 +6954,10 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session,
6933
6954
}
6934
6955
#endif /* DEBUGBUILD */
6935
6956
6957
+ if (++ session -> num_continuations > session -> max_continuations ) {
6958
+ return NGHTTP2_ERR_TOO_MANY_CONTINUATIONS ;
6959
+ }
6960
+
6936
6961
readlen = inbound_frame_buf_read (iframe , in , last );
6937
6962
in += readlen ;
6938
6963
0 commit comments