@@ -497,6 +497,7 @@ static int session_new(nghttp2_session **session_ptr,
497497 (* session_ptr )-> max_send_header_block_length = NGHTTP2_MAX_HEADERSLEN ;
498498 (* session_ptr )-> max_outbound_ack = NGHTTP2_DEFAULT_MAX_OBQ_FLOOD_ITEM ;
499499 (* session_ptr )-> max_settings = NGHTTP2_DEFAULT_MAX_SETTINGS ;
500+ (* session_ptr )-> max_continuations = NGHTTP2_DEFAULT_MAX_CONTINUATIONS ;
500501
501502 if (option ) {
502503 if ((option -> opt_set_mask & NGHTTP2_OPT_NO_AUTO_WINDOW_UPDATE ) &&
@@ -585,6 +586,10 @@ static int session_new(nghttp2_session **session_ptr,
585586 option -> stream_reset_burst ,
586587 option -> stream_reset_rate );
587588 }
589+
590+ if (option -> opt_set_mask & NGHTTP2_OPT_MAX_CONTINUATIONS ) {
591+ (* session_ptr )-> max_continuations = option -> max_continuations ;
592+ }
588593 }
589594
590595 rv = nghttp2_hd_deflate_init2 (& (* session_ptr )-> hd_deflater ,
@@ -979,7 +984,14 @@ static int session_attach_stream_item(nghttp2_session *session,
979984 return 0 ;
980985 }
981986
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 ;
983995}
984996
985997static void session_detach_stream_item (nghttp2_session * session ,
@@ -1309,9 +1321,11 @@ nghttp2_stream *nghttp2_session_open_stream(nghttp2_session *session,
13091321 assert ((stream -> flags & NGHTTP2_STREAM_FLAG_NO_RFC7540_PRIORITIES ) ||
13101322 nghttp2_stream_in_dep_tree (stream ));
13111323
1324+ nghttp2_session_detach_idle_stream (session , stream );
1325+
13121326 if (nghttp2_stream_in_dep_tree (stream )) {
13131327 assert (!(stream -> flags & NGHTTP2_STREAM_FLAG_NO_RFC7540_PRIORITIES ));
1314- nghttp2_session_detach_idle_stream ( session , stream );
1328+
13151329 rv = nghttp2_stream_dep_remove (stream );
13161330 if (rv != 0 ) {
13171331 return NULL ;
@@ -1471,6 +1485,21 @@ int nghttp2_session_close_stream(nghttp2_session *session, int32_t stream_id,
14711485
14721486 DEBUGF ("stream: stream(%p)=%d close\n" , stream , stream -> stream_id );
14731487
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+
14741503 if (stream -> item ) {
14751504 nghttp2_outbound_item * item ;
14761505
@@ -1488,21 +1517,6 @@ int nghttp2_session_close_stream(nghttp2_session *session, int32_t stream_id,
14881517 }
14891518 }
14901519
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-
15061520 is_my_stream_id = nghttp2_session_is_my_stream_id (session , stream_id );
15071521
15081522 /* pushed streams which is not opened yet is not counted toward max
@@ -1559,6 +1573,11 @@ int nghttp2_session_destroy_stream(nghttp2_session *session,
15591573 }
15601574 }
15611575
1576+ if (stream -> queued &&
1577+ (stream -> flags & NGHTTP2_STREAM_FLAG_NO_RFC7540_PRIORITIES )) {
1578+ session_ob_data_remove (session , stream );
1579+ }
1580+
15621581 nghttp2_map_remove (& session -> streams , stream -> stream_id );
15631582 nghttp2_stream_free (stream );
15641583 nghttp2_mem_free (mem , stream );
@@ -6812,6 +6831,8 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session,
68126831 }
68136832 }
68146833 session_inbound_frame_reset (session );
6834+
6835+ session -> num_continuations = 0 ;
68156836 }
68166837 break ;
68176838 }
@@ -6933,6 +6954,10 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session,
69336954 }
69346955#endif /* DEBUGBUILD */
69356956
6957+ if (++ session -> num_continuations > session -> max_continuations ) {
6958+ return NGHTTP2_ERR_TOO_MANY_CONTINUATIONS ;
6959+ }
6960+
69366961 readlen = inbound_frame_buf_read (iframe , in , last );
69376962 in += readlen ;
69386963
0 commit comments