File CVE-2023-44487.patch of Package nodejs16

Index: node-v16.20.2/deps/nghttp2/lib/CMakeLists.txt
===================================================================
--- node-v16.20.2.orig/deps/nghttp2/lib/CMakeLists.txt
+++ node-v16.20.2/deps/nghttp2/lib/CMakeLists.txt
@@ -23,7 +23,11 @@ set(NGHTTP2_SOURCES
   nghttp2_mem.c
   nghttp2_http.c
   nghttp2_rcbuf.c
+  nghttp2_extpri.c
+  nghttp2_ratelim.c
+  nghttp2_time.c
   nghttp2_debug.c
+  sfparse.c
 )
 
 set(NGHTTP2_RES "")
Index: node-v16.20.2/deps/nghttp2/lib/Makefile.am
===================================================================
--- node-v16.20.2.orig/deps/nghttp2/lib/Makefile.am
+++ node-v16.20.2/deps/nghttp2/lib/Makefile.am
@@ -50,7 +50,11 @@ OBJECTS = nghttp2_pq.c nghttp2_map.c ngh
 	nghttp2_mem.c \
 	nghttp2_http.c \
 	nghttp2_rcbuf.c \
-	nghttp2_debug.c
+	nghttp2_extpri.c \
+	nghttp2_ratelim.c \
+	nghttp2_time.c \
+	nghttp2_debug.c \
+	sfparse.c
 
 HFILES = nghttp2_pq.h nghttp2_int.h nghttp2_map.h nghttp2_queue.h \
 	nghttp2_frame.h \
@@ -66,7 +70,11 @@ HFILES = nghttp2_pq.h nghttp2_int.h nght
 	nghttp2_mem.h \
 	nghttp2_http.h \
 	nghttp2_rcbuf.h \
-	nghttp2_debug.h
+	nghttp2_extpri.h \
+	nghttp2_ratelim.h \
+	nghttp2_time.h \
+	nghttp2_debug.h \
+	sfparse.h
 
 libnghttp2_la_SOURCES = $(HFILES) $(OBJECTS)
 libnghttp2_la_LDFLAGS = $(AM_LDFLAGS) -no-undefined \
Index: node-v16.20.2/deps/nghttp2/lib/Makefile.in
===================================================================
--- node-v16.20.2.orig/deps/nghttp2/lib/Makefile.in
+++ node-v16.20.2/deps/nghttp2/lib/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.16.4 from Makefile.am.
+# Makefile.in generated by automake 1.16.5 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2021 Free Software Foundation, Inc.
@@ -107,13 +107,8 @@ host_triplet = @host@
 target_triplet = @target@
 subdir = lib
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-am__aclocal_m4_deps = $(top_srcdir)/m4/ax_boost_asio.m4 \
-	$(top_srcdir)/m4/ax_boost_base.m4 \
-	$(top_srcdir)/m4/ax_boost_system.m4 \
-	$(top_srcdir)/m4/ax_boost_thread.m4 \
-	$(top_srcdir)/m4/ax_check_compile_flag.m4 \
+am__aclocal_m4_deps = $(top_srcdir)/m4/ax_check_compile_flag.m4 \
 	$(top_srcdir)/m4/ax_cxx_compile_stdcxx.m4 \
-	$(top_srcdir)/m4/ax_python_devel.m4 \
 	$(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
 	$(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
 	$(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac
@@ -162,7 +157,8 @@ am__objects_2 = nghttp2_pq.lo nghttp2_ma
 	nghttp2_hd_huffman.lo nghttp2_hd_huffman_data.lo \
 	nghttp2_version.lo nghttp2_priority_spec.lo nghttp2_option.lo \
 	nghttp2_callbacks.lo nghttp2_mem.lo nghttp2_http.lo \
-	nghttp2_rcbuf.lo nghttp2_debug.lo
+	nghttp2_rcbuf.lo nghttp2_extpri.lo nghttp2_ratelim.lo \
+	nghttp2_time.lo nghttp2_debug.lo sfparse.lo
 am_libnghttp2_la_OBJECTS = $(am__objects_1) $(am__objects_2)
 libnghttp2_la_OBJECTS = $(am_libnghttp2_la_OBJECTS)
 AM_V_lt = $(am__v_lt_@AM_V@)
@@ -189,8 +185,9 @@ depcomp = $(SHELL) $(top_srcdir)/depcomp
 am__maybe_remake_depfiles = depfiles
 am__depfiles_remade = ./$(DEPDIR)/nghttp2_buf.Plo \
 	./$(DEPDIR)/nghttp2_callbacks.Plo \
-	./$(DEPDIR)/nghttp2_debug.Plo ./$(DEPDIR)/nghttp2_frame.Plo \
-	./$(DEPDIR)/nghttp2_hd.Plo ./$(DEPDIR)/nghttp2_hd_huffman.Plo \
+	./$(DEPDIR)/nghttp2_debug.Plo ./$(DEPDIR)/nghttp2_extpri.Plo \
+	./$(DEPDIR)/nghttp2_frame.Plo ./$(DEPDIR)/nghttp2_hd.Plo \
+	./$(DEPDIR)/nghttp2_hd_huffman.Plo \
 	./$(DEPDIR)/nghttp2_hd_huffman_data.Plo \
 	./$(DEPDIR)/nghttp2_helper.Plo ./$(DEPDIR)/nghttp2_http.Plo \
 	./$(DEPDIR)/nghttp2_map.Plo ./$(DEPDIR)/nghttp2_mem.Plo \
@@ -198,9 +195,11 @@ am__depfiles_remade = ./$(DEPDIR)/nghttp
 	./$(DEPDIR)/nghttp2_outbound_item.Plo \
 	./$(DEPDIR)/nghttp2_pq.Plo \
 	./$(DEPDIR)/nghttp2_priority_spec.Plo \
-	./$(DEPDIR)/nghttp2_queue.Plo ./$(DEPDIR)/nghttp2_rcbuf.Plo \
-	./$(DEPDIR)/nghttp2_session.Plo ./$(DEPDIR)/nghttp2_stream.Plo \
-	./$(DEPDIR)/nghttp2_submit.Plo ./$(DEPDIR)/nghttp2_version.Plo
+	./$(DEPDIR)/nghttp2_queue.Plo ./$(DEPDIR)/nghttp2_ratelim.Plo \
+	./$(DEPDIR)/nghttp2_rcbuf.Plo ./$(DEPDIR)/nghttp2_session.Plo \
+	./$(DEPDIR)/nghttp2_stream.Plo ./$(DEPDIR)/nghttp2_submit.Plo \
+	./$(DEPDIR)/nghttp2_time.Plo ./$(DEPDIR)/nghttp2_version.Plo \
+	./$(DEPDIR)/sfparse.Plo
 am__mv = mv -f
 COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
 	$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
@@ -299,11 +298,6 @@ AUTOCONF = @AUTOCONF@
 AUTOHEADER = @AUTOHEADER@
 AUTOMAKE = @AUTOMAKE@
 AWK = @AWK@
-BOOST_ASIO_LIB = @BOOST_ASIO_LIB@
-BOOST_CPPFLAGS = @BOOST_CPPFLAGS@
-BOOST_LDFLAGS = @BOOST_LDFLAGS@
-BOOST_SYSTEM_LIB = @BOOST_SYSTEM_LIB@
-BOOST_THREAD_LIB = @BOOST_THREAD_LIB@
 BPFCFLAGS = @BPFCFLAGS@
 CC = @CC@
 CCDEPMODE = @CCDEPMODE@
@@ -320,7 +314,6 @@ CXXCPP = @CXXCPP@
 CXXDEPMODE = @CXXDEPMODE@
 CXXFLAGS = @CXXFLAGS@
 CYGPATH_W = @CYGPATH_W@
-CYTHON = @CYTHON@
 DEFS = @DEFS@
 DEPDIR = @DEPDIR@
 DLLTOOL = @DLLTOOL@
@@ -336,6 +329,7 @@ EXTRABPFCFLAGS = @EXTRABPFCFLAGS@
 EXTRACFLAG = @EXTRACFLAG@
 EXTRA_DEFS = @EXTRA_DEFS@
 FGREP = @FGREP@
+FILECMD = @FILECMD@
 GREP = @GREP@
 HAVE_CXX14 = @HAVE_CXX14@
 INSTALL = @INSTALL@
@@ -364,8 +358,8 @@ LIBNGHTTP3_LIBS = @LIBNGHTTP3_LIBS@
 LIBNGTCP2_CFLAGS = @LIBNGTCP2_CFLAGS@
 LIBNGTCP2_CRYPTO_BORINGSSL_CFLAGS = @LIBNGTCP2_CRYPTO_BORINGSSL_CFLAGS@
 LIBNGTCP2_CRYPTO_BORINGSSL_LIBS = @LIBNGTCP2_CRYPTO_BORINGSSL_LIBS@
-LIBNGTCP2_CRYPTO_OPENSSL_CFLAGS = @LIBNGTCP2_CRYPTO_OPENSSL_CFLAGS@
-LIBNGTCP2_CRYPTO_OPENSSL_LIBS = @LIBNGTCP2_CRYPTO_OPENSSL_LIBS@
+LIBNGTCP2_CRYPTO_QUICTLS_CFLAGS = @LIBNGTCP2_CRYPTO_QUICTLS_CFLAGS@
+LIBNGTCP2_CRYPTO_QUICTLS_LIBS = @LIBNGTCP2_CRYPTO_QUICTLS_LIBS@
 LIBNGTCP2_LIBS = @LIBNGTCP2_LIBS@
 LIBOBJS = @LIBOBJS@
 LIBS = @LIBS@
@@ -404,15 +398,9 @@ PKG_CONFIG = @PKG_CONFIG@
 PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
 PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
 PYTHON = @PYTHON@
-PYTHON_CPPFLAGS = @PYTHON_CPPFLAGS@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
-PYTHON_EXTRA_LDFLAGS = @PYTHON_EXTRA_LDFLAGS@
-PYTHON_EXTRA_LIBS = @PYTHON_EXTRA_LIBS@
-PYTHON_LIBS = @PYTHON_LIBS@
 PYTHON_PLATFORM = @PYTHON_PLATFORM@
-PYTHON_PLATFORM_SITE_PKG = @PYTHON_PLATFORM_SITE_PKG@
 PYTHON_PREFIX = @PYTHON_PREFIX@
-PYTHON_SITE_PKG = @PYTHON_SITE_PKG@
 PYTHON_VERSION = @PYTHON_VERSION@
 RANLIB = @RANLIB@
 SED = @SED@
@@ -523,7 +511,11 @@ OBJECTS = nghttp2_pq.c nghttp2_map.c ngh
 	nghttp2_mem.c \
 	nghttp2_http.c \
 	nghttp2_rcbuf.c \
-	nghttp2_debug.c
+	nghttp2_extpri.c \
+	nghttp2_ratelim.c \
+	nghttp2_time.c \
+	nghttp2_debug.c \
+	sfparse.c
 
 HFILES = nghttp2_pq.h nghttp2_int.h nghttp2_map.h nghttp2_queue.h \
 	nghttp2_frame.h \
@@ -539,7 +531,11 @@ HFILES = nghttp2_pq.h nghttp2_int.h nght
 	nghttp2_mem.h \
 	nghttp2_http.h \
 	nghttp2_rcbuf.h \
-	nghttp2_debug.h
+	nghttp2_extpri.h \
+	nghttp2_ratelim.h \
+	nghttp2_time.h \
+	nghttp2_debug.h \
+	sfparse.h
 
 libnghttp2_la_SOURCES = $(HFILES) $(OBJECTS)
 libnghttp2_la_LDFLAGS = $(AM_LDFLAGS) -no-undefined \
@@ -628,6 +624,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nghttp2_buf.Plo@am__quote@ # am--include-marker
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nghttp2_callbacks.Plo@am__quote@ # am--include-marker
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nghttp2_debug.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nghttp2_extpri.Plo@am__quote@ # am--include-marker
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nghttp2_frame.Plo@am__quote@ # am--include-marker
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nghttp2_hd.Plo@am__quote@ # am--include-marker
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nghttp2_hd_huffman.Plo@am__quote@ # am--include-marker
@@ -642,11 +639,14 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nghttp2_pq.Plo@am__quote@ # am--include-marker
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nghttp2_priority_spec.Plo@am__quote@ # am--include-marker
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nghttp2_queue.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nghttp2_ratelim.Plo@am__quote@ # am--include-marker
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nghttp2_rcbuf.Plo@am__quote@ # am--include-marker
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nghttp2_session.Plo@am__quote@ # am--include-marker
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nghttp2_stream.Plo@am__quote@ # am--include-marker
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nghttp2_submit.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nghttp2_time.Plo@am__quote@ # am--include-marker
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nghttp2_version.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sfparse.Plo@am__quote@ # am--include-marker
 
 $(am__depfiles_remade):
 	@$(MKDIR_P) $(@D)
@@ -909,6 +909,7 @@ distclean: distclean-recursive
 		-rm -f ./$(DEPDIR)/nghttp2_buf.Plo
 	-rm -f ./$(DEPDIR)/nghttp2_callbacks.Plo
 	-rm -f ./$(DEPDIR)/nghttp2_debug.Plo
+	-rm -f ./$(DEPDIR)/nghttp2_extpri.Plo
 	-rm -f ./$(DEPDIR)/nghttp2_frame.Plo
 	-rm -f ./$(DEPDIR)/nghttp2_hd.Plo
 	-rm -f ./$(DEPDIR)/nghttp2_hd_huffman.Plo
@@ -923,11 +924,14 @@ distclean: distclean-recursive
 	-rm -f ./$(DEPDIR)/nghttp2_pq.Plo
 	-rm -f ./$(DEPDIR)/nghttp2_priority_spec.Plo
 	-rm -f ./$(DEPDIR)/nghttp2_queue.Plo
+	-rm -f ./$(DEPDIR)/nghttp2_ratelim.Plo
 	-rm -f ./$(DEPDIR)/nghttp2_rcbuf.Plo
 	-rm -f ./$(DEPDIR)/nghttp2_session.Plo
 	-rm -f ./$(DEPDIR)/nghttp2_stream.Plo
 	-rm -f ./$(DEPDIR)/nghttp2_submit.Plo
+	-rm -f ./$(DEPDIR)/nghttp2_time.Plo
 	-rm -f ./$(DEPDIR)/nghttp2_version.Plo
+	-rm -f ./$(DEPDIR)/sfparse.Plo
 	-rm -f Makefile
 distclean-am: clean-am distclean-compile distclean-generic \
 	distclean-tags
@@ -976,6 +980,7 @@ maintainer-clean: maintainer-clean-recur
 		-rm -f ./$(DEPDIR)/nghttp2_buf.Plo
 	-rm -f ./$(DEPDIR)/nghttp2_callbacks.Plo
 	-rm -f ./$(DEPDIR)/nghttp2_debug.Plo
+	-rm -f ./$(DEPDIR)/nghttp2_extpri.Plo
 	-rm -f ./$(DEPDIR)/nghttp2_frame.Plo
 	-rm -f ./$(DEPDIR)/nghttp2_hd.Plo
 	-rm -f ./$(DEPDIR)/nghttp2_hd_huffman.Plo
@@ -990,11 +995,14 @@ maintainer-clean: maintainer-clean-recur
 	-rm -f ./$(DEPDIR)/nghttp2_pq.Plo
 	-rm -f ./$(DEPDIR)/nghttp2_priority_spec.Plo
 	-rm -f ./$(DEPDIR)/nghttp2_queue.Plo
+	-rm -f ./$(DEPDIR)/nghttp2_ratelim.Plo
 	-rm -f ./$(DEPDIR)/nghttp2_rcbuf.Plo
 	-rm -f ./$(DEPDIR)/nghttp2_session.Plo
 	-rm -f ./$(DEPDIR)/nghttp2_stream.Plo
 	-rm -f ./$(DEPDIR)/nghttp2_submit.Plo
+	-rm -f ./$(DEPDIR)/nghttp2_time.Plo
 	-rm -f ./$(DEPDIR)/nghttp2_version.Plo
+	-rm -f ./$(DEPDIR)/sfparse.Plo
 	-rm -f Makefile
 maintainer-clean-am: distclean-am maintainer-clean-generic
 
Index: node-v16.20.2/deps/nghttp2/lib/includes/Makefile.in
===================================================================
--- node-v16.20.2.orig/deps/nghttp2/lib/includes/Makefile.in
+++ node-v16.20.2/deps/nghttp2/lib/includes/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.16.4 from Makefile.am.
+# Makefile.in generated by automake 1.16.5 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2021 Free Software Foundation, Inc.
@@ -114,13 +114,8 @@ host_triplet = @host@
 target_triplet = @target@
 subdir = lib/includes
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-am__aclocal_m4_deps = $(top_srcdir)/m4/ax_boost_asio.m4 \
-	$(top_srcdir)/m4/ax_boost_base.m4 \
-	$(top_srcdir)/m4/ax_boost_system.m4 \
-	$(top_srcdir)/m4/ax_boost_thread.m4 \
-	$(top_srcdir)/m4/ax_check_compile_flag.m4 \
+am__aclocal_m4_deps = $(top_srcdir)/m4/ax_check_compile_flag.m4 \
 	$(top_srcdir)/m4/ax_cxx_compile_stdcxx.m4 \
-	$(top_srcdir)/m4/ax_python_devel.m4 \
 	$(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
 	$(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
 	$(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac
@@ -208,11 +203,6 @@ AUTOCONF = @AUTOCONF@
 AUTOHEADER = @AUTOHEADER@
 AUTOMAKE = @AUTOMAKE@
 AWK = @AWK@
-BOOST_ASIO_LIB = @BOOST_ASIO_LIB@
-BOOST_CPPFLAGS = @BOOST_CPPFLAGS@
-BOOST_LDFLAGS = @BOOST_LDFLAGS@
-BOOST_SYSTEM_LIB = @BOOST_SYSTEM_LIB@
-BOOST_THREAD_LIB = @BOOST_THREAD_LIB@
 BPFCFLAGS = @BPFCFLAGS@
 CC = @CC@
 CCDEPMODE = @CCDEPMODE@
@@ -229,7 +219,6 @@ CXXCPP = @CXXCPP@
 CXXDEPMODE = @CXXDEPMODE@
 CXXFLAGS = @CXXFLAGS@
 CYGPATH_W = @CYGPATH_W@
-CYTHON = @CYTHON@
 DEFS = @DEFS@
 DEPDIR = @DEPDIR@
 DLLTOOL = @DLLTOOL@
@@ -245,6 +234,7 @@ EXTRABPFCFLAGS = @EXTRABPFCFLAGS@
 EXTRACFLAG = @EXTRACFLAG@
 EXTRA_DEFS = @EXTRA_DEFS@
 FGREP = @FGREP@
+FILECMD = @FILECMD@
 GREP = @GREP@
 HAVE_CXX14 = @HAVE_CXX14@
 INSTALL = @INSTALL@
@@ -273,8 +263,8 @@ LIBNGHTTP3_LIBS = @LIBNGHTTP3_LIBS@
 LIBNGTCP2_CFLAGS = @LIBNGTCP2_CFLAGS@
 LIBNGTCP2_CRYPTO_BORINGSSL_CFLAGS = @LIBNGTCP2_CRYPTO_BORINGSSL_CFLAGS@
 LIBNGTCP2_CRYPTO_BORINGSSL_LIBS = @LIBNGTCP2_CRYPTO_BORINGSSL_LIBS@
-LIBNGTCP2_CRYPTO_OPENSSL_CFLAGS = @LIBNGTCP2_CRYPTO_OPENSSL_CFLAGS@
-LIBNGTCP2_CRYPTO_OPENSSL_LIBS = @LIBNGTCP2_CRYPTO_OPENSSL_LIBS@
+LIBNGTCP2_CRYPTO_QUICTLS_CFLAGS = @LIBNGTCP2_CRYPTO_QUICTLS_CFLAGS@
+LIBNGTCP2_CRYPTO_QUICTLS_LIBS = @LIBNGTCP2_CRYPTO_QUICTLS_LIBS@
 LIBNGTCP2_LIBS = @LIBNGTCP2_LIBS@
 LIBOBJS = @LIBOBJS@
 LIBS = @LIBS@
@@ -313,15 +303,9 @@ PKG_CONFIG = @PKG_CONFIG@
 PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
 PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
 PYTHON = @PYTHON@
-PYTHON_CPPFLAGS = @PYTHON_CPPFLAGS@
 PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
-PYTHON_EXTRA_LDFLAGS = @PYTHON_EXTRA_LDFLAGS@
-PYTHON_EXTRA_LIBS = @PYTHON_EXTRA_LIBS@
-PYTHON_LIBS = @PYTHON_LIBS@
 PYTHON_PLATFORM = @PYTHON_PLATFORM@
-PYTHON_PLATFORM_SITE_PKG = @PYTHON_PLATFORM_SITE_PKG@
 PYTHON_PREFIX = @PYTHON_PREFIX@
-PYTHON_SITE_PKG = @PYTHON_SITE_PKG@
 PYTHON_VERSION = @PYTHON_VERSION@
 RANLIB = @RANLIB@
 SED = @SED@
Index: node-v16.20.2/deps/nghttp2/lib/includes/nghttp2/nghttp2.h
===================================================================
--- node-v16.20.2.orig/deps/nghttp2/lib/includes/nghttp2/nghttp2.h
+++ node-v16.20.2/deps/nghttp2/lib/includes/nghttp2/nghttp2.h
@@ -634,7 +634,11 @@ typedef enum {
    * The ORIGIN frame, which is defined by `RFC 8336
    * <https://tools.ietf.org/html/rfc8336>`_.
    */
-  NGHTTP2_ORIGIN = 0x0c
+  NGHTTP2_ORIGIN = 0x0c,
+  /**
+   * The PRIORITY_UPDATE frame, which is defined by :rfc:`9218`.
+   */
+  NGHTTP2_PRIORITY_UPDATE = 0x10
 } nghttp2_frame_type;
 
 /**
@@ -703,7 +707,11 @@ typedef enum {
    * SETTINGS_ENABLE_CONNECT_PROTOCOL
    * (`RFC 8441 <https://tools.ietf.org/html/rfc8441>`_)
    */
-  NGHTTP2_SETTINGS_ENABLE_CONNECT_PROTOCOL = 0x08
+  NGHTTP2_SETTINGS_ENABLE_CONNECT_PROTOCOL = 0x08,
+  /**
+   * SETTINGS_NO_RFC7540_PRIORITIES (:rfc:`9218`)
+   */
+  NGHTTP2_SETTINGS_NO_RFC7540_PRIORITIES = 0x09
 } nghttp2_settings_id;
 /* Note: If we add SETTINGS, update the capacity of
    NGHTTP2_INBOUND_NUM_IV as well */
@@ -1422,12 +1430,6 @@ typedef ssize_t (*nghttp2_recv_callback)
  * respectively.  The header name/value pairs are emitted via
  * :type:`nghttp2_on_header_callback`.
  *
- * For HEADERS, PUSH_PROMISE and DATA frames, this callback may be
- * called after stream is closed (see
- * :type:`nghttp2_on_stream_close_callback`).  The application should
- * check that stream is still alive using its own stream management or
- * :func:`nghttp2_session_get_stream_user_data()`.
- *
  * Only HEADERS and DATA frame can signal the end of incoming data.
  * If ``frame->hd.flags & NGHTTP2_FLAG_END_STREAM`` is nonzero, the
  * |frame| is the last frame from the remote peer in this stream.
@@ -2693,6 +2695,11 @@ nghttp2_option_set_max_deflate_dynamic_t
  * This option prevents the library from retaining closed streams to
  * maintain the priority tree.  If this option is set to nonzero,
  * applications can discard closed stream completely to save memory.
+ *
+ * If
+ * :enum:`nghttp2_settings_id.NGHTTP2_SETTINGS_NO_RFC7540_PRIORITIES`
+ * of value of 1 is submitted via `nghttp2_submit_settings()`, any
+ * closed streams are not retained regardless of this option.
  */
 NGHTTP2_EXTERN void nghttp2_option_set_no_closed_streams(nghttp2_option *option,
                                                          int val);
@@ -2722,6 +2729,53 @@ NGHTTP2_EXTERN void nghttp2_option_set_m
 /**
  * @function
  *
+ * This option, if set to nonzero, allows server to fallback to
+ * :rfc:`7540` priorities if SETTINGS_NO_RFC7540_PRIORITIES was not
+ * received from client, and server submitted
+ * :enum:`nghttp2_settings_id.NGHTTP2_SETTINGS_NO_RFC7540_PRIORITIES`
+ * = 1 via `nghttp2_submit_settings()`.  Most of the advanced
+ * functionality for RFC 7540 priorities are still disabled.  This
+ * fallback only enables the minimal feature set of RFC 7540
+ * priorities to deal with priority signaling from client.
+ *
+ * Client session ignores this option.
+ */
+NGHTTP2_EXTERN void
+nghttp2_option_set_server_fallback_rfc7540_priorities(nghttp2_option *option,
+                                                      int val);
+
+/**
+ * @function
+ *
+ * This option, if set to nonzero, turns off RFC 9113 leading and
+ * trailing white spaces validation against HTTP field value.  Some
+ * important fields, such as HTTP/2 pseudo header fields, are
+ * validated more strictly and this option does not apply to them.
+ */
+NGHTTP2_EXTERN void
+nghttp2_option_set_no_rfc9113_leading_and_trailing_ws_validation(
+    nghttp2_option *option, int val);
+
+/**
+ * @function
+ *
+ * This function sets the rate limit for the incoming stream reset
+ * (RST_STREAM frame).  It is server use only.  It is a token-bucket
+ * based rate limiter.  |burst| specifies the number of tokens that is
+ * initially available.  The maximum number of tokens is capped to
+ * this value.  |rate| specifies the number of tokens that are
+ * regenerated per second.  An incoming RST_STREAM consumes one token.
+ * If there is no token available, GOAWAY is sent to tear down the
+ * connection.  |burst| and |rate| default to 1000 and 33
+ * respectively.
+ */
+NGHTTP2_EXTERN void
+nghttp2_option_set_stream_reset_rate_limit(nghttp2_option *option,
+                                           uint64_t burst, uint64_t rate);
+
+/**
+ * @function
+ *
  * Initializes |*session_ptr| for client use.  The all members of
  * |callbacks| are copied to |*session_ptr|.  Therefore |*session_ptr|
  * does not store |callbacks|.  The |user_data| is an arbitrary user
@@ -3589,6 +3643,11 @@ NGHTTP2_EXTERN int nghttp2_session_consu
  * found, we use default priority instead of given |pri_spec|.  That
  * is make stream depend on root stream with weight 16.
  *
+ * If
+ * :enum:`nghttp2_settings_id.NGHTTP2_SETTINGS_NO_RFC7540_PRIORITIES`
+ * of value of 1 is submitted via `nghttp2_submit_settings()`, this
+ * function does nothing and returns 0.
+ *
  * This function returns 0 if it succeeds, or one of the following
  * negative error codes:
  *
@@ -3632,6 +3691,11 @@ nghttp2_session_change_stream_priority(n
  * found, we use default priority instead of given |pri_spec|.  That
  * is make stream depend on root stream with weight 16.
  *
+ * If
+ * :enum:`nghttp2_settings_id.NGHTTP2_SETTINGS_NO_RFC7540_PRIORITIES`
+ * of value of 1 is submitted via `nghttp2_submit_settings()`, this
+ * function does nothing and returns 0.
+ *
  * This function returns 0 if it succeeds, or one of the following
  * negative error codes:
  *
@@ -3837,6 +3901,11 @@ nghttp2_priority_spec_check_default(cons
  * :macro:`NGHTTP2_MAX_WEIGHT`, it becomes
  * :macro:`NGHTTP2_MAX_WEIGHT`.
  *
+ * If
+ * :enum:`nghttp2_settings_id.NGHTTP2_SETTINGS_NO_RFC7540_PRIORITIES`
+ * of value of 1 is received by a remote endpoint, |pri_spec| is
+ * ignored, and treated as if ``NULL`` is specified.
+ *
  * The |nva| is an array of name/value pair :type:`nghttp2_nv` with
  * |nvlen| elements.  The application is responsible to include
  * required pseudo-header fields (header field whose name starts with
@@ -4057,6 +4126,11 @@ NGHTTP2_EXTERN int nghttp2_submit_traile
  * :macro:`NGHTTP2_MIN_WEIGHT`.  If it is strictly greater than
  * :macro:`NGHTTP2_MAX_WEIGHT`, it becomes :macro:`NGHTTP2_MAX_WEIGHT`.
  *
+ * If
+ * :enum:`nghttp2_settings_id.NGHTTP2_SETTINGS_NO_RFC7540_PRIORITIES`
+ * of value of 1 is received by a remote endpoint, |pri_spec| is
+ * ignored, and treated as if ``NULL`` is specified.
+ *
  * The |nva| is an array of name/value pair :type:`nghttp2_nv` with
  * |nvlen| elements.  The application is responsible to include
  * required pseudo-header fields (header field whose name starts with
@@ -4184,6 +4258,11 @@ NGHTTP2_EXTERN int nghttp2_submit_data(n
  * :macro:`NGHTTP2_MAX_WEIGHT`, it becomes
  * :macro:`NGHTTP2_MAX_WEIGHT`.
  *
+ * If
+ * :enum:`nghttp2_settings_id.NGHTTP2_SETTINGS_NO_RFC7540_PRIORITIES`
+ * of value of 1 is received by a remote endpoint, this function does
+ * nothing and returns 0.
+ *
  * This function returns 0 if it succeeds, or one of the following
  * negative error codes:
  *
@@ -4199,6 +4278,61 @@ nghttp2_submit_priority(nghttp2_session
                         const nghttp2_priority_spec *pri_spec);
 
 /**
+ * @macro
+ *
+ * :macro:`NGHTTP2_EXTPRI_DEFAULT_URGENCY` is the default urgency
+ * level for :rfc:`9218` extensible priorities.
+ */
+#define NGHTTP2_EXTPRI_DEFAULT_URGENCY 3
+
+/**
+ * @macro
+ *
+ * :macro:`NGHTTP2_EXTPRI_URGENCY_HIGH` is the highest urgency level
+ * for :rfc:`9218` extensible priorities.
+ */
+#define NGHTTP2_EXTPRI_URGENCY_HIGH 0
+
+/**
+ * @macro
+ *
+ * :macro:`NGHTTP2_EXTPRI_URGENCY_LOW` is the lowest urgency level for
+ * :rfc:`9218` extensible priorities.
+ */
+#define NGHTTP2_EXTPRI_URGENCY_LOW 7
+
+/**
+ * @macro
+ *
+ * :macro:`NGHTTP2_EXTPRI_URGENCY_LEVELS` is the number of urgency
+ * levels for :rfc:`9218` extensible priorities.
+ */
+#define NGHTTP2_EXTPRI_URGENCY_LEVELS (NGHTTP2_EXTPRI_URGENCY_LOW + 1)
+
+/**
+ * @struct
+ *
+ * :type:`nghttp2_extpri` is :rfc:`9218` extensible priorities
+ * specification for a stream.
+ */
+typedef struct nghttp2_extpri {
+  /**
+   * :member:`urgency` is the urgency of a stream, it must be in
+   * [:macro:`NGHTTP2_EXTPRI_URGENCY_HIGH`,
+   * :macro:`NGHTTP2_EXTPRI_URGENCY_LOW`], inclusive, and 0 is the
+   * highest urgency.
+   */
+  uint32_t urgency;
+  /**
+   * :member:`inc` indicates that a content can be processed
+   * incrementally or not.  If inc is 0, it cannot be processed
+   * incrementally.  If inc is 1, it can be processed incrementally.
+   * Other value is not permitted.
+   */
+  int inc;
+} nghttp2_extpri;
+
+/**
  * @function
  *
  * Submits RST_STREAM frame to cancel/reject the stream |stream_id|
@@ -4723,6 +4857,108 @@ NGHTTP2_EXTERN int nghttp2_submit_origin
                                          size_t nov);
 
 /**
+ * @struct
+ *
+ * The payload of PRIORITY_UPDATE frame.  PRIORITY_UPDATE frame is a
+ * non-critical extension to HTTP/2.  If this frame is received, and
+ * `nghttp2_option_set_user_recv_extension_type()` is not set, and
+ * `nghttp2_option_set_builtin_recv_extension_type()` is set for
+ * :enum:`nghttp2_frame_type.NGHTTP2_PRIORITY_UPDATE`,
+ * ``nghttp2_extension.payload`` will point to this struct.
+ *
+ * It has the following members:
+ */
+typedef struct {
+  /**
+   * The stream ID of the stream whose priority is updated.
+   */
+  int32_t stream_id;
+  /**
+   * The pointer to Priority field value.  It is not necessarily
+   * NULL-terminated.
+   */
+  uint8_t *field_value;
+  /**
+   * The length of the :member:`field_value`.
+   */
+  size_t field_value_len;
+} nghttp2_ext_priority_update;
+
+/**
+ * @function
+ *
+ * Submits PRIORITY_UPDATE frame.
+ *
+ * PRIORITY_UPDATE frame is a non-critical extension to HTTP/2, and
+ * defined in :rfc:`9218#section-7.1`.
+ *
+ * The |flags| is currently ignored and should be
+ * :enum:`nghttp2_flag.NGHTTP2_FLAG_NONE`.
+ *
+ * The |stream_id| is the ID of stream which is prioritized.  The
+ * |field_value| points to the Priority field value.  The
+ * |field_value_len| is the length of the Priority field value.
+ *
+ * If this function is called by server,
+ * :enum:`nghttp2_error.NGHTTP2_ERR_INVALID_STATE` is returned.
+ *
+ * If
+ * :enum:`nghttp2_settings_id.NGHTTP2_SETTINGS_NO_RFC7540_PRIORITIES`
+ * of value of 0 is received by a remote endpoint (or it is omitted),
+ * this function does nothing and returns 0.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :enum:`nghttp2_error.NGHTTP2_ERR_NOMEM`
+ *     Out of memory
+ * :enum:`nghttp2_error.NGHTTP2_ERR_INVALID_STATE`
+ *     The function is called from server side session
+ * :enum:`nghttp2_error.NGHTTP2_ERR_INVALID_ARGUMENT`
+ *     The |field_value_len| is larger than 16380; or |stream_id| is
+ *     0.
+ */
+NGHTTP2_EXTERN int nghttp2_submit_priority_update(nghttp2_session *session,
+                                                  uint8_t flags,
+                                                  int32_t stream_id,
+                                                  const uint8_t *field_value,
+                                                  size_t field_value_len);
+
+/**
+ * @function
+ *
+ * Changes the priority of the existing stream denoted by |stream_id|.
+ * The new priority is |extpri|.  This function is meant to be used by
+ * server for :rfc:`9218` extensible prioritization scheme.
+ *
+ * If |session| is initialized as client, this function returns
+ * :enum:`nghttp2_error.NGHTTP2_ERR_INVALID_STATE`.  For client, use
+ * `nghttp2_submit_priority_update()` instead.
+ *
+ * If :member:`extpri->urgency <nghttp2_extpri.urgency>` is out of
+ * bound, it is set to :macro:`NGHTTP2_EXTPRI_URGENCY_LOW`.
+ *
+ * If |ignore_client_signal| is nonzero, server starts to ignore
+ * client priority signals for this stream.
+ *
+ * If
+ * :enum:`nghttp2_settings_id.NGHTTP2_SETTINGS_NO_RFC7540_PRIORITIES`
+ * of value of 1 is not submitted via `nghttp2_submit_settings()`,
+ * this function does nothing and returns 0.
+ *
+ * :enum:`nghttp2_error.NGHTTP2_ERR_NOMEM`
+ *     Out of memory.
+ * :enum:`nghttp2_error.NGHTTP2_ERR_INVALID_STATE`
+ *     The |session| is initialized as client.
+ * :enum:`nghttp2_error.NGHTTP2_ERR_INVALID_ARGUMENT`
+ *     |stream_id| is zero; or a stream denoted by |stream_id| is not
+ *     found.
+ */
+NGHTTP2_EXTERN int nghttp2_session_change_extpri_stream_priority(
+    nghttp2_session *session, int32_t stream_id, const nghttp2_extpri *extpri,
+    int ignore_client_signal);
+
+/**
  * @function
  *
  * Compares ``lhs->name`` of length ``lhs->namelen`` bytes and
@@ -4833,11 +5069,25 @@ NGHTTP2_EXTERN int nghttp2_check_header_
  * Returns nonzero if HTTP header field value |value| of length |len|
  * is valid according to
  * http://tools.ietf.org/html/rfc7230#section-3.2
+ *
+ * This function is considered obsolete, and application should
+ * consider to use `nghttp2_check_header_value_rfc9113()` instead.
  */
 NGHTTP2_EXTERN int nghttp2_check_header_value(const uint8_t *value, size_t len);
 
 /**
  * @function
+ *
+ * Returns nonzero if HTTP header field value |value| of length |len|
+ * is valid according to
+ * http://tools.ietf.org/html/rfc7230#section-3.2, plus
+ * https://datatracker.ietf.org/doc/html/rfc9113#section-8.2.1
+ */
+NGHTTP2_EXTERN int nghttp2_check_header_value_rfc9113(const uint8_t *value,
+                                                      size_t len);
+
+/**
+ * @function
  *
  * Returns nonzero if the |value| which is supposed to be the value of
  * the :method header field is valid according to
Index: node-v16.20.2/deps/nghttp2/lib/includes/nghttp2/nghttp2ver.h
===================================================================
--- node-v16.20.2.orig/deps/nghttp2/lib/includes/nghttp2/nghttp2ver.h
+++ node-v16.20.2/deps/nghttp2/lib/includes/nghttp2/nghttp2ver.h
@@ -29,7 +29,7 @@
  * @macro
  * Version number of the nghttp2 library release
  */
-#define NGHTTP2_VERSION "1.47.0"
+#define NGHTTP2_VERSION "1.57.0"
 
 /**
  * @macro
@@ -37,6 +37,6 @@
  * release. This is a 24 bit number with 8 bits for major number, 8 bits
  * for minor and 8 bits for patch. Version 1.2.3 becomes 0x010203.
  */
-#define NGHTTP2_VERSION_NUM 0x012f00
+#define NGHTTP2_VERSION_NUM 0x013900
 
 #endif /* NGHTTP2VER_H */
Index: node-v16.20.2/deps/nghttp2/lib/nghttp2_extpri.c
===================================================================
--- /dev/null
+++ node-v16.20.2/deps/nghttp2/lib/nghttp2_extpri.c
@@ -0,0 +1,35 @@
+/*
+ * nghttp2 - HTTP/2 C Library
+ *
+ * Copyright (c) 2022 nghttp3 contributors
+ * Copyright (c) 2022 nghttp2 contributors
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include "nghttp2_extpri.h"
+
+uint8_t nghttp2_extpri_to_uint8(const nghttp2_extpri *extpri) {
+  return (uint8_t)((uint32_t)extpri->inc << 7 | extpri->urgency);
+}
+
+void nghttp2_extpri_from_uint8(nghttp2_extpri *extpri, uint8_t u8extpri) {
+  extpri->urgency = nghttp2_extpri_uint8_urgency(u8extpri);
+  extpri->inc = nghttp2_extpri_uint8_inc(u8extpri);
+}
Index: node-v16.20.2/deps/nghttp2/lib/nghttp2_extpri.h
===================================================================
--- /dev/null
+++ node-v16.20.2/deps/nghttp2/lib/nghttp2_extpri.h
@@ -0,0 +1,65 @@
+/*
+ * nghttp2 - HTTP/2 C Library
+ *
+ * Copyright (c) 2022 nghttp3 contributors
+ * Copyright (c) 2022 nghttp2 contributors
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#ifndef NGHTTP2_EXTPRI_H
+#define NGHTTP2_EXTPRI_H
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <nghttp2/nghttp2.h>
+
+/*
+ * NGHTTP2_EXTPRI_INC_MASK is a bit mask to retrieve incremental bit
+ * from a value produced by nghttp2_extpri_to_uint8.
+ */
+#define NGHTTP2_EXTPRI_INC_MASK (1 << 7)
+
+/*
+ * nghttp2_extpri_to_uint8 encodes |pri| into uint8_t variable.
+ */
+uint8_t nghttp2_extpri_to_uint8(const nghttp2_extpri *extpri);
+
+/*
+ * nghttp2_extpri_from_uint8 decodes |u8extpri|, which is produced by
+ * nghttp2_extpri_to_uint8, intto |extpri|.
+ */
+void nghttp2_extpri_from_uint8(nghttp2_extpri *extpri, uint8_t u8extpri);
+
+/*
+ * nghttp2_extpri_uint8_urgency extracts urgency from |PRI| which is
+ * supposed to be constructed by nghttp2_extpri_to_uint8.
+ */
+#define nghttp2_extpri_uint8_urgency(PRI)                                      \
+  ((uint32_t)((PRI) & ~NGHTTP2_EXTPRI_INC_MASK))
+
+/*
+ * nghttp2_extpri_uint8_inc extracts inc from |PRI| which is supposed to
+ * be constructed by nghttp2_extpri_to_uint8.
+ */
+#define nghttp2_extpri_uint8_inc(PRI) (((PRI)&NGHTTP2_EXTPRI_INC_MASK) != 0)
+
+#endif /* NGHTTP2_EXTPRI_H */
Index: node-v16.20.2/deps/nghttp2/lib/nghttp2_frame.c
===================================================================
--- node-v16.20.2.orig/deps/nghttp2/lib/nghttp2_frame.c
+++ node-v16.20.2/deps/nghttp2/lib/nghttp2_frame.c
@@ -253,6 +253,31 @@ void nghttp2_frame_origin_free(nghttp2_e
   nghttp2_mem_free(mem, origin->ov);
 }
 
+void nghttp2_frame_priority_update_init(nghttp2_extension *frame,
+                                        int32_t stream_id, uint8_t *field_value,
+                                        size_t field_value_len) {
+  nghttp2_ext_priority_update *priority_update;
+
+  nghttp2_frame_hd_init(&frame->hd, 4 + field_value_len,
+                        NGHTTP2_PRIORITY_UPDATE, NGHTTP2_FLAG_NONE, 0);
+
+  priority_update = frame->payload;
+  priority_update->stream_id = stream_id;
+  priority_update->field_value = field_value;
+  priority_update->field_value_len = field_value_len;
+}
+
+void nghttp2_frame_priority_update_free(nghttp2_extension *frame,
+                                        nghttp2_mem *mem) {
+  nghttp2_ext_priority_update *priority_update;
+
+  priority_update = frame->payload;
+  if (priority_update == NULL) {
+    return;
+  }
+  nghttp2_mem_free(mem, priority_update->field_value);
+}
+
 size_t nghttp2_frame_priority_len(uint8_t flags) {
   if (flags & NGHTTP2_FLAG_PRIORITY) {
     return NGHTTP2_PRIORITY_SPECLEN;
@@ -393,8 +418,8 @@ void nghttp2_frame_unpack_priority_spec(
   nghttp2_priority_spec_init(pri_spec, dep_stream_id, weight, exclusive);
 }
 
-int nghttp2_frame_unpack_headers_payload(nghttp2_headers *frame,
-                                         const uint8_t *payload) {
+void nghttp2_frame_unpack_headers_payload(nghttp2_headers *frame,
+                                          const uint8_t *payload) {
   if (frame->hd.flags & NGHTTP2_FLAG_PRIORITY) {
     nghttp2_frame_unpack_priority_spec(&frame->pri_spec, payload);
   } else {
@@ -403,11 +428,9 @@ int nghttp2_frame_unpack_headers_payload
 
   frame->nva = NULL;
   frame->nvlen = 0;
-
-  return 0;
 }
 
-int nghttp2_frame_pack_priority(nghttp2_bufs *bufs, nghttp2_priority *frame) {
+void nghttp2_frame_pack_priority(nghttp2_bufs *bufs, nghttp2_priority *frame) {
   nghttp2_buf *buf;
 
   assert(bufs->head == bufs->cur);
@@ -423,8 +446,6 @@ int nghttp2_frame_pack_priority(nghttp2_
   nghttp2_frame_pack_priority_spec(buf->last, &frame->pri_spec);
 
   buf->last += NGHTTP2_PRIORITY_SPECLEN;
-
-  return 0;
 }
 
 void nghttp2_frame_unpack_priority_payload(nghttp2_priority *frame,
@@ -432,8 +453,8 @@ void nghttp2_frame_unpack_priority_paylo
   nghttp2_frame_unpack_priority_spec(&frame->pri_spec, payload);
 }
 
-int nghttp2_frame_pack_rst_stream(nghttp2_bufs *bufs,
-                                  nghttp2_rst_stream *frame) {
+void nghttp2_frame_pack_rst_stream(nghttp2_bufs *bufs,
+                                   nghttp2_rst_stream *frame) {
   nghttp2_buf *buf;
 
   assert(bufs->head == bufs->cur);
@@ -448,8 +469,6 @@ int nghttp2_frame_pack_rst_stream(nghttp
 
   nghttp2_put_uint32be(buf->last, frame->error_code);
   buf->last += 4;
-
-  return 0;
 }
 
 void nghttp2_frame_unpack_rst_stream_payload(nghttp2_rst_stream *frame,
@@ -567,16 +586,15 @@ int nghttp2_frame_pack_push_promise(nght
   return frame_pack_headers_shared(bufs, &frame->hd);
 }
 
-int nghttp2_frame_unpack_push_promise_payload(nghttp2_push_promise *frame,
-                                              const uint8_t *payload) {
+void nghttp2_frame_unpack_push_promise_payload(nghttp2_push_promise *frame,
+                                               const uint8_t *payload) {
   frame->promised_stream_id =
       nghttp2_get_uint32(payload) & NGHTTP2_STREAM_ID_MASK;
   frame->nva = NULL;
   frame->nvlen = 0;
-  return 0;
 }
 
-int nghttp2_frame_pack_ping(nghttp2_bufs *bufs, nghttp2_ping *frame) {
+void nghttp2_frame_pack_ping(nghttp2_bufs *bufs, nghttp2_ping *frame) {
   nghttp2_buf *buf;
 
   assert(bufs->head == bufs->cur);
@@ -591,8 +609,6 @@ int nghttp2_frame_pack_ping(nghttp2_bufs
 
   buf->last =
       nghttp2_cpymem(buf->last, frame->opaque_data, sizeof(frame->opaque_data));
-
-  return 0;
 }
 
 void nghttp2_frame_unpack_ping_payload(nghttp2_ping *frame,
@@ -672,8 +688,8 @@ int nghttp2_frame_unpack_goaway_payload2
   return 0;
 }
 
-int nghttp2_frame_pack_window_update(nghttp2_bufs *bufs,
-                                     nghttp2_window_update *frame) {
+void nghttp2_frame_pack_window_update(nghttp2_bufs *bufs,
+                                      nghttp2_window_update *frame) {
   nghttp2_buf *buf;
 
   assert(bufs->head == bufs->cur);
@@ -688,8 +704,6 @@ int nghttp2_frame_pack_window_update(ngh
 
   nghttp2_put_uint32be(buf->last, (uint32_t)frame->window_size_increment);
   buf->last += 4;
-
-  return 0;
 }
 
 void nghttp2_frame_unpack_window_update_payload(nghttp2_window_update *frame,
@@ -698,7 +712,7 @@ void nghttp2_frame_unpack_window_update_
       nghttp2_get_uint32(payload) & NGHTTP2_WINDOW_SIZE_INCREMENT_MASK;
 }
 
-int nghttp2_frame_pack_altsvc(nghttp2_bufs *bufs, nghttp2_extension *frame) {
+void nghttp2_frame_pack_altsvc(nghttp2_bufs *bufs, nghttp2_extension *frame) {
   int rv;
   nghttp2_buf *buf;
   nghttp2_ext_altsvc *altsvc;
@@ -727,8 +741,6 @@ int nghttp2_frame_pack_altsvc(nghttp2_bu
   rv = nghttp2_bufs_add(bufs, altsvc->field_value, altsvc->field_value_len);
 
   assert(rv == 0);
-
-  return 0;
 }
 
 void nghttp2_frame_unpack_altsvc_payload(nghttp2_extension *frame,
@@ -876,6 +888,55 @@ int nghttp2_frame_unpack_origin_payload(
   return 0;
 }
 
+void nghttp2_frame_pack_priority_update(nghttp2_bufs *bufs,
+                                        nghttp2_extension *frame) {
+  int rv;
+  nghttp2_buf *buf;
+  nghttp2_ext_priority_update *priority_update;
+
+  /* This is required with --disable-assert. */
+  (void)rv;
+
+  priority_update = frame->payload;
+
+  buf = &bufs->head->buf;
+
+  assert(nghttp2_buf_avail(buf) >= 4 + priority_update->field_value_len);
+
+  buf->pos -= NGHTTP2_FRAME_HDLEN;
+
+  nghttp2_frame_pack_frame_hd(buf->pos, &frame->hd);
+
+  nghttp2_put_uint32be(buf->last, (uint32_t)priority_update->stream_id);
+  buf->last += 4;
+
+  rv = nghttp2_bufs_add(bufs, priority_update->field_value,
+                        priority_update->field_value_len);
+
+  assert(rv == 0);
+}
+
+void nghttp2_frame_unpack_priority_update_payload(nghttp2_extension *frame,
+                                                  uint8_t *payload,
+                                                  size_t payloadlen) {
+  nghttp2_ext_priority_update *priority_update;
+
+  assert(payloadlen >= 4);
+
+  priority_update = frame->payload;
+
+  priority_update->stream_id =
+      nghttp2_get_uint32(payload) & NGHTTP2_STREAM_ID_MASK;
+
+  if (payloadlen > 4) {
+    priority_update->field_value = payload + 4;
+    priority_update->field_value_len = payloadlen - 4;
+  } else {
+    priority_update->field_value = NULL;
+    priority_update->field_value_len = 0;
+  }
+}
+
 nghttp2_settings_entry *nghttp2_frame_iv_copy(const nghttp2_settings_entry *iv,
                                               size_t niv, nghttp2_mem *mem) {
   nghttp2_settings_entry *iv_copy;
@@ -1071,6 +1132,11 @@ int nghttp2_iv_check(const nghttp2_setti
         return 0;
       }
       break;
+    case NGHTTP2_SETTINGS_NO_RFC7540_PRIORITIES:
+      if (iv[i].value != 0 && iv[i].value != 1) {
+        return 0;
+      }
+      break;
     }
   }
   return 1;
@@ -1105,14 +1171,14 @@ static void frame_set_pad(nghttp2_buf *b
   buf->last += trail_padlen;
 }
 
-int nghttp2_frame_add_pad(nghttp2_bufs *bufs, nghttp2_frame_hd *hd,
-                          size_t padlen, int framehd_only) {
+void nghttp2_frame_add_pad(nghttp2_bufs *bufs, nghttp2_frame_hd *hd,
+                           size_t padlen, int framehd_only) {
   nghttp2_buf *buf;
 
   if (padlen == 0) {
     DEBUGF("send: padlen = 0, nothing to do\n");
 
-    return 0;
+    return;
   }
 
   /*
@@ -1145,6 +1211,4 @@ int nghttp2_frame_add_pad(nghttp2_bufs *
   hd->flags |= NGHTTP2_FLAG_PADDED;
 
   DEBUGF("send: final payloadlen=%zu, padlen=%zu\n", hd->length, padlen);
-
-  return 0;
 }
Index: node-v16.20.2/deps/nghttp2/lib/nghttp2_frame.h
===================================================================
--- node-v16.20.2.orig/deps/nghttp2/lib/nghttp2_frame.h
+++ node-v16.20.2/deps/nghttp2/lib/nghttp2_frame.h
@@ -73,6 +73,7 @@
 typedef union {
   nghttp2_ext_altsvc altsvc;
   nghttp2_ext_origin origin;
+  nghttp2_ext_priority_update priority_update;
 } nghttp2_ext_frame_payload;
 
 void nghttp2_frame_pack_frame_hd(uint8_t *buf, const nghttp2_frame_hd *hd);
@@ -142,11 +143,9 @@ int nghttp2_frame_pack_headers(nghttp2_b
  * Unpacks HEADERS frame byte sequence into |frame|.  This function
  * only unapcks bytes that come before name/value header block and
  * after possible Pad Length field.
- *
- * This function always succeeds and returns 0.
  */
-int nghttp2_frame_unpack_headers_payload(nghttp2_headers *frame,
-                                         const uint8_t *payload);
+void nghttp2_frame_unpack_headers_payload(nghttp2_headers *frame,
+                                          const uint8_t *payload);
 
 /*
  * Packs PRIORITY frame |frame| in wire format and store it in
@@ -154,10 +153,8 @@ int nghttp2_frame_unpack_headers_payload
  *
  * The caller must make sure that nghttp2_bufs_reset(bufs) is called
  * before calling this function.
- *
- * This function always succeeds and returns 0.
  */
-int nghttp2_frame_pack_priority(nghttp2_bufs *bufs, nghttp2_priority *frame);
+void nghttp2_frame_pack_priority(nghttp2_bufs *bufs, nghttp2_priority *frame);
 
 /*
  * Unpacks PRIORITY wire format into |frame|.
@@ -171,11 +168,9 @@ void nghttp2_frame_unpack_priority_paylo
  *
  * The caller must make sure that nghttp2_bufs_reset(bufs) is called
  * before calling this function.
- *
- * This function always succeeds and returns 0.
  */
-int nghttp2_frame_pack_rst_stream(nghttp2_bufs *bufs,
-                                  nghttp2_rst_stream *frame);
+void nghttp2_frame_pack_rst_stream(nghttp2_bufs *bufs,
+                                   nghttp2_rst_stream *frame);
 
 /*
  * Unpacks RST_STREAM frame byte sequence into |frame|.
@@ -264,15 +259,9 @@ int nghttp2_frame_pack_push_promise(nght
  * Unpacks PUSH_PROMISE frame byte sequence into |frame|.  This
  * function only unapcks bytes that come before name/value header
  * block and after possible Pad Length field.
- *
- * This function returns 0 if it succeeds or one of the following
- * negative error codes:
- *
- * NGHTTP2_ERR_PROTO
- *     TODO END_HEADERS flag is not set
  */
-int nghttp2_frame_unpack_push_promise_payload(nghttp2_push_promise *frame,
-                                              const uint8_t *payload);
+void nghttp2_frame_unpack_push_promise_payload(nghttp2_push_promise *frame,
+                                               const uint8_t *payload);
 
 /*
  * Packs PING frame |frame| in wire format and store it in
@@ -280,10 +269,8 @@ int nghttp2_frame_unpack_push_promise_pa
  *
  * The caller must make sure that nghttp2_bufs_reset(bufs) is called
  * before calling this function.
- *
- * This function always succeeds and returns 0.
  */
-int nghttp2_frame_pack_ping(nghttp2_bufs *bufs, nghttp2_ping *frame);
+void nghttp2_frame_pack_ping(nghttp2_bufs *bufs, nghttp2_ping *frame);
 
 /*
  * Unpacks PING wire format into |frame|.
@@ -342,11 +329,9 @@ int nghttp2_frame_unpack_goaway_payload2
  *
  * The caller must make sure that nghttp2_bufs_reset(bufs) is called
  * before calling this function.
- *
- * This function always succeeds and returns 0.
  */
-int nghttp2_frame_pack_window_update(nghttp2_bufs *bufs,
-                                     nghttp2_window_update *frame);
+void nghttp2_frame_pack_window_update(nghttp2_bufs *bufs,
+                                      nghttp2_window_update *frame);
 
 /*
  * Unpacks WINDOW_UPDATE frame byte sequence into |frame|.
@@ -360,17 +345,13 @@ void nghttp2_frame_unpack_window_update_
  *
  * The caller must make sure that nghttp2_bufs_reset(bufs) is called
  * before calling this function.
- *
- * This function always succeeds and returns 0.
  */
-int nghttp2_frame_pack_altsvc(nghttp2_bufs *bufs, nghttp2_extension *ext);
+void nghttp2_frame_pack_altsvc(nghttp2_bufs *bufs, nghttp2_extension *ext);
 
 /*
  * Unpacks ALTSVC wire format into |frame|.  The |payload| of
  * |payloadlen| bytes contains frame payload.  This function assumes
  * that frame->payload points to the nghttp2_ext_altsvc object.
- *
- * This function always succeeds and returns 0.
  */
 void nghttp2_frame_unpack_altsvc_payload(nghttp2_extension *frame,
                                          size_t origin_len, uint8_t *payload,
@@ -423,6 +404,27 @@ int nghttp2_frame_pack_origin(nghttp2_bu
 int nghttp2_frame_unpack_origin_payload(nghttp2_extension *frame,
                                         const uint8_t *payload,
                                         size_t payloadlen, nghttp2_mem *mem);
+
+/*
+ * Packs PRIORITY_UPDATE frame |frame| in wire frame format and store
+ * it in |bufs|.
+ *
+ * The caller must make sure that nghttp2_bufs_reset(bufs) is called
+ * before calling this function.
+ */
+void nghttp2_frame_pack_priority_update(nghttp2_bufs *bufs,
+                                        nghttp2_extension *ext);
+
+/*
+ * Unpacks PRIORITY_UPDATE wire format into |frame|.  The |payload| of
+ * |payloadlen| bytes contains frame payload.  This function assumes
+ * that frame->payload points to the nghttp2_ext_priority_update
+ * object.
+ */
+void nghttp2_frame_unpack_priority_update_payload(nghttp2_extension *frame,
+                                                  uint8_t *payload,
+                                                  size_t payloadlen);
+
 /*
  * Initializes HEADERS frame |frame| with given values.  |frame| takes
  * ownership of |nva|, so caller must not free it. If |stream_id| is
@@ -539,6 +541,25 @@ void nghttp2_frame_origin_init(nghttp2_e
 void nghttp2_frame_origin_free(nghttp2_extension *frame, nghttp2_mem *mem);
 
 /*
+ * Initializes PRIORITY_UPDATE frame |frame| with given values.  This
+ * function assumes that frame->payload points to
+ * nghttp2_ext_priority_update object.  On success, this function
+ * takes ownership of |field_value|, so caller must not free it.
+ */
+void nghttp2_frame_priority_update_init(nghttp2_extension *frame,
+                                        int32_t stream_id, uint8_t *field_value,
+                                        size_t field_value_len);
+
+/*
+ * Frees up resources under |frame|.  This function does not free
+ * nghttp2_ext_priority_update object pointed by frame->payload.  This
+ * function only frees field_value pointed by
+ * nghttp2_ext_priority_update.field_value.
+ */
+void nghttp2_frame_priority_update_free(nghttp2_extension *frame,
+                                        nghttp2_mem *mem);
+
+/*
  * Returns the number of padding bytes after payload.  The total
  * padding length is given in the |padlen|.  The returned value does
  * not include the Pad Length field.  If |padlen| is 0, this function
@@ -609,16 +630,8 @@ int nghttp2_iv_check(const nghttp2_setti
  * |padlen| including Pad Length field.  The |hd| is the frame header
  * for the serialized data.  This function fills zeros padding region
  * unless framehd_only is nonzero.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGHTTP2_ERR_NOMEM
- *     Out of memory.
- * NGHTTP2_ERR_FRAME_SIZE_ERROR
- *     The length of the resulting frame is too large.
  */
-int nghttp2_frame_add_pad(nghttp2_bufs *bufs, nghttp2_frame_hd *hd,
-                          size_t padlen, int framehd_only);
+void nghttp2_frame_add_pad(nghttp2_bufs *bufs, nghttp2_frame_hd *hd,
+                           size_t padlen, int framehd_only);
 
 #endif /* NGHTTP2_FRAME_H */
Index: node-v16.20.2/deps/nghttp2/lib/nghttp2_hd.c
===================================================================
--- node-v16.20.2.orig/deps/nghttp2/lib/nghttp2_hd.c
+++ node-v16.20.2/deps/nghttp2/lib/nghttp2_hd.c
@@ -269,6 +269,11 @@ static int32_t lookup_token(const uint8_
         return NGHTTP2_TOKEN_LOCATION;
       }
       break;
+    case 'y':
+      if (memeq("priorit", name, 7)) {
+        return NGHTTP2_TOKEN_PRIORITY;
+      }
+      break;
     }
     break;
   case 9:
Index: node-v16.20.2/deps/nghttp2/lib/nghttp2_hd.h
===================================================================
--- node-v16.20.2.orig/deps/nghttp2/lib/nghttp2_hd.h
+++ node-v16.20.2/deps/nghttp2/lib/nghttp2_hd.h
@@ -112,6 +112,7 @@ typedef enum {
   NGHTTP2_TOKEN_PROXY_CONNECTION,
   NGHTTP2_TOKEN_UPGRADE,
   NGHTTP2_TOKEN__PROTOCOL,
+  NGHTTP2_TOKEN_PRIORITY,
 } nghttp2_token;
 
 struct nghttp2_hd_entry;
Index: node-v16.20.2/deps/nghttp2/lib/nghttp2_helper.c
===================================================================
--- node-v16.20.2.orig/deps/nghttp2/lib/nghttp2_helper.c
+++ node-v16.20.2/deps/nghttp2/lib/nghttp2_helper.c
@@ -507,6 +507,19 @@ int nghttp2_check_header_value(const uin
   return 1;
 }
 
+int nghttp2_check_header_value_rfc9113(const uint8_t *value, size_t len) {
+  if (len == 0) {
+    return 1;
+  }
+
+  if (*value == ' ' || *value == '\t' || *(value + len - 1) == ' ' ||
+      *(value + len - 1) == '\t') {
+    return 0;
+  }
+
+  return nghttp2_check_header_value(value, len);
+}
+
 /* Generated by genmethodchartbl.py */
 static char VALID_METHOD_CHARS[] = {
     0 /* NUL  */, 0 /* SOH  */, 0 /* STX  */, 0 /* ETX  */,
Index: node-v16.20.2/deps/nghttp2/lib/nghttp2_http.c
===================================================================
--- node-v16.20.2.orig/deps/nghttp2/lib/nghttp2_http.c
+++ node-v16.20.2/deps/nghttp2/lib/nghttp2_http.c
@@ -30,6 +30,8 @@
 
 #include "nghttp2_hd.h"
 #include "nghttp2_helper.h"
+#include "nghttp2_extpri.h"
+#include "sfparse.h"
 
 static uint8_t downcase(uint8_t c) {
   return 'A' <= c && c <= 'Z' ? (uint8_t)(c - 'A' + 'a') : c;
@@ -72,25 +74,12 @@ static int64_t parse_uint(const uint8_t
   return n;
 }
 
-static int lws(const uint8_t *s, size_t n) {
-  size_t i;
-  for (i = 0; i < n; ++i) {
-    if (s[i] != ' ' && s[i] != '\t') {
-      return 0;
-    }
-  }
-  return 1;
-}
-
 static int check_pseudo_header(nghttp2_stream *stream, const nghttp2_hd_nv *nv,
-                               int flag) {
-  if (stream->http_flags & flag) {
-    return 0;
-  }
-  if (lws(nv->value->base, nv->value->len)) {
+                               uint32_t flag) {
+  if ((stream->http_flags & flag) || nv->value->len == 0) {
     return 0;
   }
-  stream->http_flags = (uint16_t)(stream->http_flags | flag);
+  stream->http_flags = stream->http_flags | flag;
   return 1;
 }
 
@@ -114,6 +103,8 @@ static int check_path(nghttp2_stream *st
 
 static int http_request_on_header(nghttp2_stream *stream, nghttp2_hd_nv *nv,
                                   int trailer, int connect_protocol) {
+  nghttp2_extpri extpri;
+
   if (nv->name->base[0] == ':') {
     if (trailer ||
         (stream->http_flags & NGHTTP2_HTTP_FLAG_PSEUDO_HEADER_DISALLOWED)) {
@@ -212,6 +203,23 @@ static int http_request_on_header(nghttp
       return NGHTTP2_ERR_HTTP_HEADER;
     }
     break;
+  case NGHTTP2_TOKEN_PRIORITY:
+    if (!trailer &&
+        /* Do not parse the header field in PUSH_PROMISE. */
+        (stream->stream_id & 1) &&
+        (stream->flags & NGHTTP2_STREAM_FLAG_NO_RFC7540_PRIORITIES) &&
+        !(stream->http_flags & NGHTTP2_HTTP_FLAG_BAD_PRIORITY)) {
+      nghttp2_extpri_from_uint8(&extpri, stream->http_extpri);
+      if (nghttp2_http_parse_priority(&extpri, nv->value->base,
+                                      nv->value->len) == 0) {
+        stream->http_extpri = nghttp2_extpri_to_uint8(&extpri);
+        stream->http_flags |= NGHTTP2_HTTP_FLAG_PRIORITY;
+      } else {
+        stream->http_flags &= (uint32_t)~NGHTTP2_HTTP_FLAG_PRIORITY;
+        stream->http_flags |= NGHTTP2_HTTP_FLAG_BAD_PRIORITY;
+      }
+    }
+    break;
   default:
     if (nv->name->base[0] == ':') {
       return NGHTTP2_ERR_HTTP_HEADER;
@@ -329,6 +337,16 @@ static int check_scheme(const uint8_t *v
   return 1;
 }
 
+static int lws(const uint8_t *s, size_t n) {
+  size_t i;
+  for (i = 0; i < n; ++i) {
+    if (s[i] != ' ' && s[i] != '\t') {
+      return 0;
+    }
+  }
+  return 1;
+}
+
 int nghttp2_http_on_header(nghttp2_session *session, nghttp2_stream *stream,
                            nghttp2_frame *frame, nghttp2_hd_nv *nv,
                            int trailer) {
@@ -369,13 +387,37 @@ int nghttp2_http_on_header(nghttp2_sessi
     break;
   case NGHTTP2_TOKEN__AUTHORITY:
   case NGHTTP2_TOKEN_HOST:
-    rv = nghttp2_check_authority(nv->value->base, nv->value->len);
+    if (session->server || frame->hd.type == NGHTTP2_PUSH_PROMISE) {
+      rv = nghttp2_check_authority(nv->value->base, nv->value->len);
+    } else if (
+        stream->flags &
+        NGHTTP2_STREAM_FLAG_NO_RFC9113_LEADING_AND_TRAILING_WS_VALIDATION) {
+      rv = nghttp2_check_header_value(nv->value->base, nv->value->len);
+    } else {
+      rv = nghttp2_check_header_value_rfc9113(nv->value->base, nv->value->len);
+    }
     break;
   case NGHTTP2_TOKEN__SCHEME:
     rv = check_scheme(nv->value->base, nv->value->len);
     break;
+  case NGHTTP2_TOKEN__PROTOCOL:
+    /* Check the value consists of just white spaces, which was done
+       in check_pseudo_header before
+       nghttp2_check_header_value_rfc9113 has been introduced. */
+    if ((stream->flags &
+         NGHTTP2_STREAM_FLAG_NO_RFC9113_LEADING_AND_TRAILING_WS_VALIDATION) &&
+        lws(nv->value->base, nv->value->len)) {
+      rv = 0;
+      break;
+    }
+    /* fall through */
   default:
-    rv = nghttp2_check_header_value(nv->value->base, nv->value->len);
+    if (stream->flags &
+        NGHTTP2_STREAM_FLAG_NO_RFC9113_LEADING_AND_TRAILING_WS_VALIDATION) {
+      rv = nghttp2_check_header_value(nv->value->base, nv->value->len);
+    } else {
+      rv = nghttp2_check_header_value_rfc9113(nv->value->base, nv->value->len);
+    }
   }
 
   if (rv == 0) {
@@ -443,16 +485,15 @@ int nghttp2_http_on_response_headers(ngh
 
   if (stream->status_code / 100 == 1) {
     /* non-final response */
-    stream->http_flags =
-        (uint16_t)((stream->http_flags & NGHTTP2_HTTP_FLAG_METH_ALL) |
-                   NGHTTP2_HTTP_FLAG_EXPECT_FINAL_RESPONSE);
+    stream->http_flags = (stream->http_flags & NGHTTP2_HTTP_FLAG_METH_ALL) |
+                         NGHTTP2_HTTP_FLAG_EXPECT_FINAL_RESPONSE;
     stream->content_length = -1;
     stream->status_code = -1;
     return 0;
   }
 
   stream->http_flags =
-      (uint16_t)(stream->http_flags & ~NGHTTP2_HTTP_FLAG_EXPECT_FINAL_RESPONSE);
+      stream->http_flags & (uint32_t)~NGHTTP2_HTTP_FLAG_EXPECT_FINAL_RESPONSE;
 
   if (!expect_response_body(stream)) {
     stream->content_length = 0;
@@ -537,3 +578,54 @@ void nghttp2_http_record_request_method(
     return;
   }
 }
+
+int nghttp2_http_parse_priority(nghttp2_extpri *dest, const uint8_t *value,
+                                size_t valuelen) {
+  nghttp2_extpri pri = *dest;
+  sf_parser sfp;
+  sf_vec key;
+  sf_value val;
+  int rv;
+
+  sf_parser_init(&sfp, value, valuelen);
+
+  for (;;) {
+    rv = sf_parser_dict(&sfp, &key, &val);
+    if (rv != 0) {
+      if (rv == SF_ERR_EOF) {
+        break;
+      }
+
+      return NGHTTP2_ERR_INVALID_ARGUMENT;
+    }
+
+    if (key.len != 1) {
+      continue;
+    }
+
+    switch (key.base[0]) {
+    case 'i':
+      if (val.type != SF_TYPE_BOOLEAN) {
+        return NGHTTP2_ERR_INVALID_ARGUMENT;
+      }
+
+      pri.inc = val.boolean;
+
+      break;
+    case 'u':
+      if (val.type != SF_TYPE_INTEGER ||
+          val.integer < NGHTTP2_EXTPRI_URGENCY_HIGH ||
+          NGHTTP2_EXTPRI_URGENCY_LOW < val.integer) {
+        return NGHTTP2_ERR_INVALID_ARGUMENT;
+      }
+
+      pri.urgency = (uint32_t)val.integer;
+
+      break;
+    }
+  }
+
+  *dest = pri;
+
+  return 0;
+}
Index: node-v16.20.2/deps/nghttp2/lib/nghttp2_http.h
===================================================================
--- node-v16.20.2.orig/deps/nghttp2/lib/nghttp2_http.h
+++ node-v16.20.2/deps/nghttp2/lib/nghttp2_http.h
@@ -94,4 +94,7 @@ int nghttp2_http_on_data_chunk(nghttp2_s
 void nghttp2_http_record_request_method(nghttp2_stream *stream,
                                         nghttp2_frame *frame);
 
+int nghttp2_http_parse_priority(nghttp2_extpri *dest, const uint8_t *value,
+                                size_t valuelen);
+
 #endif /* NGHTTP2_HTTP_H */
Index: node-v16.20.2/deps/nghttp2/lib/nghttp2_net.h
===================================================================
--- node-v16.20.2.orig/deps/nghttp2/lib/nghttp2_net.h
+++ node-v16.20.2/deps/nghttp2/lib/nghttp2_net.h
@@ -53,7 +53,7 @@
 STIN uint32_t htonl(uint32_t hostlong) {
   uint32_t res;
   unsigned char *p = (unsigned char *)&res;
-  *p++ = hostlong >> 24;
+  *p++ = (unsigned char)(hostlong >> 24);
   *p++ = (hostlong >> 16) & 0xffu;
   *p++ = (hostlong >> 8) & 0xffu;
   *p = hostlong & 0xffu;
@@ -63,7 +63,7 @@ STIN uint32_t htonl(uint32_t hostlong) {
 STIN uint16_t htons(uint16_t hostshort) {
   uint16_t res;
   unsigned char *p = (unsigned char *)&res;
-  *p++ = hostshort >> 8;
+  *p++ = (unsigned char)(hostshort >> 8);
   *p = hostshort & 0xffu;
   return res;
 }
@@ -71,9 +71,9 @@ STIN uint16_t htons(uint16_t hostshort)
 STIN uint32_t ntohl(uint32_t netlong) {
   uint32_t res;
   unsigned char *p = (unsigned char *)&netlong;
-  res = *p++ << 24;
-  res += *p++ << 16;
-  res += *p++ << 8;
+  res = (uint32_t)(*p++ << 24);
+  res += (uint32_t)(*p++ << 16);
+  res += (uint32_t)(*p++ << 8);
   res += *p;
   return res;
 }
@@ -81,7 +81,7 @@ STIN uint32_t ntohl(uint32_t netlong) {
 STIN uint16_t ntohs(uint16_t netshort) {
   uint16_t res;
   unsigned char *p = (unsigned char *)&netshort;
-  res = *p++ << 8;
+  res = (uint16_t)(*p++ << 8);
   res += *p;
   return res;
 }
Index: node-v16.20.2/deps/nghttp2/lib/nghttp2_option.c
===================================================================
--- node-v16.20.2.orig/deps/nghttp2/lib/nghttp2_option.c
+++ node-v16.20.2/deps/nghttp2/lib/nghttp2_option.c
@@ -90,6 +90,10 @@ void nghttp2_option_set_builtin_recv_ext
     option->opt_set_mask |= NGHTTP2_OPT_BUILTIN_RECV_EXT_TYPES;
     option->builtin_recv_ext_types |= NGHTTP2_TYPEMASK_ORIGIN;
     return;
+  case NGHTTP2_PRIORITY_UPDATE:
+    option->opt_set_mask |= NGHTTP2_OPT_BUILTIN_RECV_EXT_TYPES;
+    option->builtin_recv_ext_types |= NGHTTP2_TYPEMASK_PRIORITY_UPDATE;
+    return;
   default:
     return;
   }
@@ -126,3 +130,23 @@ void nghttp2_option_set_max_settings(ngh
   option->opt_set_mask |= NGHTTP2_OPT_MAX_SETTINGS;
   option->max_settings = val;
 }
+
+void nghttp2_option_set_server_fallback_rfc7540_priorities(
+    nghttp2_option *option, int val) {
+  option->opt_set_mask |= NGHTTP2_OPT_SERVER_FALLBACK_RFC7540_PRIORITIES;
+  option->server_fallback_rfc7540_priorities = val;
+}
+
+void nghttp2_option_set_no_rfc9113_leading_and_trailing_ws_validation(
+    nghttp2_option *option, int val) {
+  option->opt_set_mask |=
+      NGHTTP2_OPT_NO_RFC9113_LEADING_AND_TRAILING_WS_VALIDATION;
+  option->no_rfc9113_leading_and_trailing_ws_validation = val;
+}
+
+void nghttp2_option_set_stream_reset_rate_limit(nghttp2_option *option,
+                                                uint64_t burst, uint64_t rate) {
+  option->opt_set_mask |= NGHTTP2_OPT_STREAM_RESET_RATE_LIMIT;
+  option->stream_reset_burst = burst;
+  option->stream_reset_rate = rate;
+}
Index: node-v16.20.2/deps/nghttp2/lib/nghttp2_option.h
===================================================================
--- node-v16.20.2.orig/deps/nghttp2/lib/nghttp2_option.h
+++ node-v16.20.2/deps/nghttp2/lib/nghttp2_option.h
@@ -68,6 +68,9 @@ typedef enum {
   NGHTTP2_OPT_NO_CLOSED_STREAMS = 1 << 10,
   NGHTTP2_OPT_MAX_OUTBOUND_ACK = 1 << 11,
   NGHTTP2_OPT_MAX_SETTINGS = 1 << 12,
+  NGHTTP2_OPT_SERVER_FALLBACK_RFC7540_PRIORITIES = 1 << 13,
+  NGHTTP2_OPT_NO_RFC9113_LEADING_AND_TRAILING_WS_VALIDATION = 1 << 14,
+  NGHTTP2_OPT_STREAM_RESET_RATE_LIMIT = 1 << 15,
 } nghttp2_option_flag;
 
 /**
@@ -75,6 +78,11 @@ typedef enum {
  */
 struct nghttp2_option {
   /**
+   * NGHTTP2_OPT_STREAM_RESET_RATE_LIMIT
+   */
+  uint64_t stream_reset_burst;
+  uint64_t stream_reset_rate;
+  /**
    * NGHTTP2_OPT_MAX_SEND_HEADER_BLOCK_LENGTH
    */
   size_t max_send_header_block_length;
@@ -128,6 +136,14 @@ struct nghttp2_option {
    */
   int no_closed_streams;
   /**
+   * NGHTTP2_OPT_SERVER_FALLBACK_RFC7540_PRIORITIES
+   */
+  int server_fallback_rfc7540_priorities;
+  /**
+   * NGHTTP2_OPT_NO_RFC9113_LEADING_AND_TRAILING_WS_VALIDATION
+   */
+  int no_rfc9113_leading_and_trailing_ws_validation;
+  /**
    * NGHTTP2_OPT_USER_RECV_EXT_TYPES
    */
   uint8_t user_recv_ext_types[32];
Index: node-v16.20.2/deps/nghttp2/lib/nghttp2_outbound_item.c
===================================================================
--- node-v16.20.2.orig/deps/nghttp2/lib/nghttp2_outbound_item.c
+++ node-v16.20.2/deps/nghttp2/lib/nghttp2_outbound_item.c
@@ -89,6 +89,9 @@ void nghttp2_outbound_item_free(nghttp2_
     case NGHTTP2_ORIGIN:
       nghttp2_frame_origin_free(&frame->ext, mem);
       break;
+    case NGHTTP2_PRIORITY_UPDATE:
+      nghttp2_frame_priority_update_free(&frame->ext, mem);
+      break;
     default:
       assert(0);
       break;
Index: node-v16.20.2/deps/nghttp2/lib/nghttp2_pq.c
===================================================================
--- node-v16.20.2.orig/deps/nghttp2/lib/nghttp2_pq.c
+++ node-v16.20.2/deps/nghttp2/lib/nghttp2_pq.c
@@ -29,13 +29,12 @@
 
 #include "nghttp2_helper.h"
 
-int nghttp2_pq_init(nghttp2_pq *pq, nghttp2_less less, nghttp2_mem *mem) {
+void nghttp2_pq_init(nghttp2_pq *pq, nghttp2_less less, nghttp2_mem *mem) {
   pq->mem = mem;
   pq->capacity = 0;
   pq->q = NULL;
   pq->length = 0;
   pq->less = less;
-  return 0;
 }
 
 void nghttp2_pq_free(nghttp2_pq *pq) {
Index: node-v16.20.2/deps/nghttp2/lib/nghttp2_pq.h
===================================================================
--- node-v16.20.2.orig/deps/nghttp2/lib/nghttp2_pq.h
+++ node-v16.20.2/deps/nghttp2/lib/nghttp2_pq.h
@@ -55,14 +55,8 @@ typedef struct {
 
 /*
  * Initializes priority queue |pq| with compare function |cmp|.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGHTTP2_ERR_NOMEM
- *     Out of memory.
  */
-int nghttp2_pq_init(nghttp2_pq *pq, nghttp2_less less, nghttp2_mem *mem);
+void nghttp2_pq_init(nghttp2_pq *pq, nghttp2_less less, nghttp2_mem *mem);
 
 /*
  * Deallocates any resources allocated for |pq|.  The stored items are
Index: node-v16.20.2/deps/nghttp2/lib/nghttp2_session.c
===================================================================
--- node-v16.20.2.orig/deps/nghttp2/lib/nghttp2_session.c
+++ node-v16.20.2/deps/nghttp2/lib/nghttp2_session.c
@@ -36,6 +36,8 @@
 #include "nghttp2_option.h"
 #include "nghttp2_http.h"
 #include "nghttp2_pq.h"
+#include "nghttp2_extpri.h"
+#include "nghttp2_time.h"
 #include "nghttp2_debug.h"
 
 /*
@@ -143,6 +145,11 @@ static int session_detect_idle_stream(ng
   return 0;
 }
 
+static int session_no_rfc7540_pri_no_fallback(nghttp2_session *session) {
+  return session->pending_no_rfc7540_priorities == 1 &&
+         !session->fallback_rfc7540_priorities;
+}
+
 static int check_ext_type_set(const uint8_t *ext_types, uint8_t type) {
   return (ext_types[type / 8] & (1 << (type & 0x7))) > 0;
 }
@@ -354,6 +361,14 @@ static void session_inbound_frame_reset(
         }
         nghttp2_frame_origin_free(&iframe->frame.ext, mem);
         break;
+      case NGHTTP2_PRIORITY_UPDATE:
+        if ((session->builtin_recv_ext_types &
+             NGHTTP2_TYPEMASK_PRIORITY_UPDATE) == 0) {
+          break;
+        }
+        /* Do not call nghttp2_frame_priority_update_free, because all
+           fields point to sbuf. */
+        break;
       }
     }
 
@@ -385,6 +400,7 @@ static void init_settings(nghttp2_settin
   settings->initial_window_size = NGHTTP2_INITIAL_WINDOW_SIZE;
   settings->max_frame_size = NGHTTP2_MAX_FRAME_SIZE_MIN;
   settings->max_header_list_size = UINT32_MAX;
+  settings->no_rfc7540_priorities = UINT32_MAX;
 }
 
 static void active_outbound_item_reset(nghttp2_active_outbound_item *aob,
@@ -398,6 +414,21 @@ static void active_outbound_item_reset(n
   aob->state = NGHTTP2_OB_POP_ITEM;
 }
 
+#define NGHTTP2_STREAM_MAX_CYCLE_GAP ((uint64_t)NGHTTP2_MAX_FRAME_SIZE_MAX)
+
+static int stream_less(const void *lhsx, const void *rhsx) {
+  const nghttp2_stream *lhs, *rhs;
+
+  lhs = nghttp2_struct_of(lhsx, nghttp2_stream, pq_entry);
+  rhs = nghttp2_struct_of(rhsx, nghttp2_stream, pq_entry);
+
+  if (lhs->cycle == rhs->cycle) {
+    return lhs->seq < rhs->seq;
+  }
+
+  return rhs->cycle - lhs->cycle <= NGHTTP2_STREAM_MAX_CYCLE_GAP;
+}
+
 int nghttp2_enable_strict_preface = 1;
 
 static int session_new(nghttp2_session **session_ptr,
@@ -408,6 +439,7 @@ static int session_new(nghttp2_session *
   size_t nbuffer;
   size_t max_deflate_dynamic_table_size =
       NGHTTP2_HD_DEFAULT_MAX_DEFLATE_BUFFER_SIZE;
+  size_t i;
 
   if (mem == NULL) {
     mem = nghttp2_mem_default();
@@ -442,6 +474,11 @@ static int session_new(nghttp2_session *
   (*session_ptr)->pending_local_max_concurrent_stream =
       NGHTTP2_DEFAULT_MAX_CONCURRENT_STREAMS;
   (*session_ptr)->pending_enable_push = 1;
+  (*session_ptr)->pending_no_rfc7540_priorities = UINT8_MAX;
+
+  nghttp2_ratelim_init(&(*session_ptr)->stream_reset_ratelim,
+                       NGHTTP2_DEFAULT_STREAM_RESET_BURST,
+                       NGHTTP2_DEFAULT_STREAM_RESET_RATE);
 
   if (server) {
     (*session_ptr)->server = 1;
@@ -527,6 +564,26 @@ static int session_new(nghttp2_session *
         option->max_settings) {
       (*session_ptr)->max_settings = option->max_settings;
     }
+
+    if ((option->opt_set_mask &
+         NGHTTP2_OPT_SERVER_FALLBACK_RFC7540_PRIORITIES) &&
+        option->server_fallback_rfc7540_priorities) {
+      (*session_ptr)->opt_flags |=
+          NGHTTP2_OPTMASK_SERVER_FALLBACK_RFC7540_PRIORITIES;
+    }
+
+    if ((option->opt_set_mask &
+         NGHTTP2_OPT_NO_RFC9113_LEADING_AND_TRAILING_WS_VALIDATION) &&
+        option->no_rfc9113_leading_and_trailing_ws_validation) {
+      (*session_ptr)->opt_flags |=
+          NGHTTP2_OPTMASK_NO_RFC9113_LEADING_AND_TRAILING_WS_VALIDATION;
+    }
+
+    if (option->opt_set_mask & NGHTTP2_OPT_STREAM_RESET_RATE_LIMIT) {
+      nghttp2_ratelim_init(&(*session_ptr)->stream_reset_ratelim,
+                           option->stream_reset_burst,
+                           option->stream_reset_rate);
+    }
   }
 
   rv = nghttp2_hd_deflate_init2(&(*session_ptr)->hd_deflater,
@@ -538,10 +595,6 @@ static int session_new(nghttp2_session *
   if (rv != 0) {
     goto fail_hd_inflater;
   }
-  rv = nghttp2_map_init(&(*session_ptr)->streams, mem);
-  if (rv != 0) {
-    goto fail_map;
-  }
 
   nbuffer = ((*session_ptr)->max_send_header_block_length +
              NGHTTP2_FRAMEBUF_CHUNKLEN - 1) /
@@ -559,6 +612,8 @@ static int session_new(nghttp2_session *
     goto fail_aob_framebuf;
   }
 
+  nghttp2_map_init(&(*session_ptr)->streams, mem);
+
   active_outbound_item_reset(&(*session_ptr)->aob, mem);
 
   (*session_ptr)->callbacks = *callbacks;
@@ -584,11 +639,13 @@ static int session_new(nghttp2_session *
     }
   }
 
+  for (i = 0; i < NGHTTP2_EXTPRI_URGENCY_LEVELS; ++i) {
+    nghttp2_pq_init(&(*session_ptr)->sched[i].ob_data, stream_less, mem);
+  }
+
   return 0;
 
 fail_aob_framebuf:
-  nghttp2_map_free(&(*session_ptr)->streams);
-fail_map:
   nghttp2_hd_inflate_free(&(*session_ptr)->hd_inflater);
 fail_hd_inflater:
   nghttp2_hd_deflate_free(&(*session_ptr)->hd_deflater);
@@ -735,6 +792,7 @@ static void inflight_settings_del(nghttp
 void nghttp2_session_del(nghttp2_session *session) {
   nghttp2_mem *mem;
   nghttp2_inflight_settings *settings;
+  size_t i;
 
   if (session == NULL) {
     return;
@@ -748,6 +806,9 @@ void nghttp2_session_del(nghttp2_session
     settings = next;
   }
 
+  for (i = 0; i < NGHTTP2_EXTPRI_URGENCY_LEVELS; ++i) {
+    nghttp2_pq_free(&session->sched[i].ob_data);
+  }
   nghttp2_stream_free(&session->root);
 
   /* Have to free streams first, so that we can check
@@ -775,6 +836,8 @@ int nghttp2_session_reprioritize_stream(
   nghttp2_priority_spec pri_spec_default;
   const nghttp2_priority_spec *pri_spec = pri_spec_in;
 
+  assert((!session->server && session->pending_no_rfc7540_priorities != 1) ||
+         (session->server && !session_no_rfc7540_pri_no_fallback(session)));
   assert(pri_spec->stream_id != stream->stream_id);
 
   if (!nghttp2_stream_in_dep_tree(stream)) {
@@ -842,6 +905,202 @@ int nghttp2_session_reprioritize_stream(
   return 0;
 }
 
+static uint64_t pq_get_first_cycle(nghttp2_pq *pq) {
+  nghttp2_stream *stream;
+
+  if (nghttp2_pq_empty(pq)) {
+    return 0;
+  }
+
+  stream = nghttp2_struct_of(nghttp2_pq_top(pq), nghttp2_stream, pq_entry);
+  return stream->cycle;
+}
+
+static int session_ob_data_push(nghttp2_session *session,
+                                nghttp2_stream *stream) {
+  int rv;
+  uint32_t urgency;
+  int inc;
+  nghttp2_pq *pq;
+
+  assert(stream->flags & NGHTTP2_STREAM_FLAG_NO_RFC7540_PRIORITIES);
+  assert(stream->queued == 0);
+
+  urgency = nghttp2_extpri_uint8_urgency(stream->extpri);
+  inc = nghttp2_extpri_uint8_inc(stream->extpri);
+
+  assert(urgency < NGHTTP2_EXTPRI_URGENCY_LEVELS);
+
+  pq = &session->sched[urgency].ob_data;
+
+  stream->cycle = pq_get_first_cycle(pq);
+  if (inc) {
+    stream->cycle += stream->last_writelen;
+  }
+
+  rv = nghttp2_pq_push(pq, &stream->pq_entry);
+  if (rv != 0) {
+    return rv;
+  }
+
+  stream->queued = 1;
+
+  return 0;
+}
+
+static void session_ob_data_remove(nghttp2_session *session,
+                                   nghttp2_stream *stream) {
+  uint32_t urgency;
+
+  assert(stream->flags & NGHTTP2_STREAM_FLAG_NO_RFC7540_PRIORITIES);
+  assert(stream->queued == 1);
+
+  urgency = nghttp2_extpri_uint8_urgency(stream->extpri);
+
+  assert(urgency < NGHTTP2_EXTPRI_URGENCY_LEVELS);
+
+  nghttp2_pq_remove(&session->sched[urgency].ob_data, &stream->pq_entry);
+
+  stream->queued = 0;
+}
+
+static int session_attach_stream_item(nghttp2_session *session,
+                                      nghttp2_stream *stream,
+                                      nghttp2_outbound_item *item) {
+  int rv;
+
+  rv = nghttp2_stream_attach_item(stream, item);
+  if (rv != 0) {
+    return rv;
+  }
+
+  if (!(stream->flags & NGHTTP2_STREAM_FLAG_NO_RFC7540_PRIORITIES)) {
+    return 0;
+  }
+
+  return session_ob_data_push(session, stream);
+}
+
+static void session_detach_stream_item(nghttp2_session *session,
+                                       nghttp2_stream *stream) {
+  nghttp2_stream_detach_item(stream);
+
+  if (!(stream->flags & NGHTTP2_STREAM_FLAG_NO_RFC7540_PRIORITIES) ||
+      !stream->queued) {
+    return;
+  }
+
+  session_ob_data_remove(session, stream);
+}
+
+static void session_defer_stream_item(nghttp2_session *session,
+                                      nghttp2_stream *stream, uint8_t flags) {
+  nghttp2_stream_defer_item(stream, flags);
+
+  if (!(stream->flags & NGHTTP2_STREAM_FLAG_NO_RFC7540_PRIORITIES) ||
+      !stream->queued) {
+    return;
+  }
+
+  session_ob_data_remove(session, stream);
+}
+
+static int session_resume_deferred_stream_item(nghttp2_session *session,
+                                               nghttp2_stream *stream,
+                                               uint8_t flags) {
+  int rv;
+
+  rv = nghttp2_stream_resume_deferred_item(stream, flags);
+  if (rv != 0) {
+    return rv;
+  }
+
+  if (!(stream->flags & NGHTTP2_STREAM_FLAG_NO_RFC7540_PRIORITIES) ||
+      (stream->flags & NGHTTP2_STREAM_FLAG_DEFERRED_ALL)) {
+    return 0;
+  }
+
+  return session_ob_data_push(session, stream);
+}
+
+static nghttp2_outbound_item *
+session_sched_get_next_outbound_item(nghttp2_session *session) {
+  size_t i;
+  nghttp2_pq_entry *ent;
+  nghttp2_stream *stream;
+
+  for (i = 0; i < NGHTTP2_EXTPRI_URGENCY_LEVELS; ++i) {
+    ent = nghttp2_pq_top(&session->sched[i].ob_data);
+    if (!ent) {
+      continue;
+    }
+
+    stream = nghttp2_struct_of(ent, nghttp2_stream, pq_entry);
+    return stream->item;
+  }
+
+  return NULL;
+}
+
+static int session_sched_empty(nghttp2_session *session) {
+  size_t i;
+
+  for (i = 0; i < NGHTTP2_EXTPRI_URGENCY_LEVELS; ++i) {
+    if (!nghttp2_pq_empty(&session->sched[i].ob_data)) {
+      return 0;
+    }
+  }
+
+  return 1;
+}
+
+static void session_sched_reschedule_stream(nghttp2_session *session,
+                                            nghttp2_stream *stream) {
+  nghttp2_pq *pq;
+  uint32_t urgency = nghttp2_extpri_uint8_urgency(stream->extpri);
+  int inc = nghttp2_extpri_uint8_inc(stream->extpri);
+  uint64_t penalty = (uint64_t)stream->last_writelen;
+  int rv;
+
+  (void)rv;
+
+  assert(urgency < NGHTTP2_EXTPRI_URGENCY_LEVELS);
+
+  pq = &session->sched[urgency].ob_data;
+
+  if (!inc || nghttp2_pq_size(pq) == 1) {
+    return;
+  }
+
+  nghttp2_pq_remove(pq, &stream->pq_entry);
+
+  stream->cycle += penalty;
+
+  rv = nghttp2_pq_push(pq, &stream->pq_entry);
+
+  assert(0 == rv);
+}
+
+static int session_update_stream_priority(nghttp2_session *session,
+                                          nghttp2_stream *stream,
+                                          uint8_t u8extpri) {
+  if (stream->extpri == u8extpri) {
+    return 0;
+  }
+
+  if (stream->queued) {
+    session_ob_data_remove(session, stream);
+
+    stream->extpri = u8extpri;
+
+    return session_ob_data_push(session, stream);
+  }
+
+  stream->extpri = u8extpri;
+
+  return 0;
+}
+
 int nghttp2_session_add_item(nghttp2_session *session,
                              nghttp2_outbound_item *item) {
   /* TODO Return error if stream is not found for the frame requiring
@@ -863,7 +1122,7 @@ int nghttp2_session_add_item(nghttp2_ses
       return NGHTTP2_ERR_DATA_EXIST;
     }
 
-    rv = nghttp2_stream_attach_item(stream, item);
+    rv = session_attach_stream_item(session, stream, item);
 
     if (rv != 0) {
       return rv;
@@ -1039,13 +1298,27 @@ nghttp2_stream *nghttp2_session_open_str
   mem = &session->mem;
   stream = nghttp2_session_get_stream_raw(session, stream_id);
 
+  if (session->opt_flags &
+      NGHTTP2_OPTMASK_NO_RFC9113_LEADING_AND_TRAILING_WS_VALIDATION) {
+    flags |= NGHTTP2_STREAM_FLAG_NO_RFC9113_LEADING_AND_TRAILING_WS_VALIDATION;
+  }
+
   if (stream) {
     assert(stream->state == NGHTTP2_STREAM_IDLE);
-    assert(nghttp2_stream_in_dep_tree(stream));
-    nghttp2_session_detach_idle_stream(session, stream);
-    rv = nghttp2_stream_dep_remove(stream);
-    if (rv != 0) {
-      return NULL;
+    assert((stream->flags & NGHTTP2_STREAM_FLAG_NO_RFC7540_PRIORITIES) ||
+           nghttp2_stream_in_dep_tree(stream));
+
+    if (nghttp2_stream_in_dep_tree(stream)) {
+      assert(!(stream->flags & NGHTTP2_STREAM_FLAG_NO_RFC7540_PRIORITIES));
+      nghttp2_session_detach_idle_stream(session, stream);
+      rv = nghttp2_stream_dep_remove(stream);
+      if (rv != 0) {
+        return NULL;
+      }
+
+      if (session_no_rfc7540_pri_no_fallback(session)) {
+        stream->flags |= NGHTTP2_STREAM_FLAG_NO_RFC7540_PRIORITIES;
+      }
     }
   } else {
     stream = nghttp2_mem_malloc(mem, sizeof(nghttp2_stream));
@@ -1056,7 +1329,21 @@ nghttp2_stream *nghttp2_session_open_str
     stream_alloc = 1;
   }
 
-  if (pri_spec->stream_id != 0) {
+  if (session_no_rfc7540_pri_no_fallback(session) ||
+      session->remote_settings.no_rfc7540_priorities == 1) {
+    /* For client which has not received server
+       SETTINGS_NO_RFC7540_PRIORITIES = 1, send a priority signal
+       opportunistically. */
+    if (session->server ||
+        session->remote_settings.no_rfc7540_priorities == 1) {
+      nghttp2_priority_spec_default_init(&pri_spec_default);
+      pri_spec = &pri_spec_default;
+    }
+
+    if (session->pending_no_rfc7540_priorities == 1) {
+      flags |= NGHTTP2_STREAM_FLAG_NO_RFC7540_PRIORITIES;
+    }
+  } else if (pri_spec->stream_id != 0) {
     dep_stream = nghttp2_session_get_stream_raw(session, pri_spec->stream_id);
 
     if (!dep_stream &&
@@ -1102,6 +1389,10 @@ nghttp2_stream *nghttp2_session_open_str
                         (int32_t)session->local_settings.initial_window_size,
                         stream_user_data, mem);
 
+    if (session_no_rfc7540_pri_no_fallback(session)) {
+      stream->seq = session->stream_seq++;
+    }
+
     rv = nghttp2_map_insert(&session->streams, stream_id, stream);
     if (rv != 0) {
       nghttp2_stream_free(stream);
@@ -1141,6 +1432,10 @@ nghttp2_stream *nghttp2_session_open_str
     }
   }
 
+  if (stream->flags & NGHTTP2_STREAM_FLAG_NO_RFC7540_PRIORITIES) {
+    return stream;
+  }
+
   if (pri_spec->stream_id == 0) {
     dep_stream = &session->root;
   }
@@ -1180,11 +1475,7 @@ int nghttp2_session_close_stream(nghttp2
 
     item = stream->item;
 
-    rv = nghttp2_stream_detach_item(stream);
-
-    if (rv != 0) {
-      return rv;
-    }
+    session_detach_stream_item(session, stream);
 
     /* If item is queued, it will be deleted when it is popped
        (nghttp2_session_prep_frame() will fail).  If session->aob.item
@@ -1230,6 +1521,10 @@ int nghttp2_session_close_stream(nghttp2
   /* Closes both directions just in case they are not closed yet */
   stream->flags |= NGHTTP2_STREAM_FLAG_CLOSED;
 
+  if (session->pending_no_rfc7540_priorities == 1) {
+    return nghttp2_session_destroy_stream(session, stream);
+  }
+
   if ((session->opt_flags & NGHTTP2_OPTMASK_NO_CLOSED_STREAMS) == 0 &&
       session->server && !is_my_stream_id &&
       nghttp2_stream_in_dep_tree(stream)) {
@@ -1784,6 +2079,28 @@ static int session_predicate_origin_send
   return 0;
 }
 
+static int session_predicate_priority_update_send(nghttp2_session *session,
+                                                  int32_t stream_id) {
+  nghttp2_stream *stream;
+
+  if (session_is_closing(session)) {
+    return NGHTTP2_ERR_SESSION_CLOSING;
+  }
+
+  stream = nghttp2_session_get_stream(session, stream_id);
+  if (stream == NULL) {
+    return 0;
+  }
+  if (stream->state == NGHTTP2_STREAM_CLOSING) {
+    return NGHTTP2_ERR_STREAM_CLOSING;
+  }
+  if (stream->shut_flags & NGHTTP2_SHUT_RD) {
+    return NGHTTP2_ERR_INVALID_STREAM_STATE;
+  }
+
+  return 0;
+}
+
 /* Take into account settings max frame size and both connection-level
    flow control here */
 static ssize_t
@@ -1899,7 +2216,6 @@ static ssize_t session_call_select_paddi
    frame->push_promise has also padlen in the same position. */
 static int session_headers_add_pad(nghttp2_session *session,
                                    nghttp2_frame *frame) {
-  int rv;
   ssize_t padded_payloadlen;
   nghttp2_active_outbound_item *aob;
   nghttp2_bufs *framebufs;
@@ -1924,11 +2240,7 @@ static int session_headers_add_pad(nghtt
   DEBUGF("send: padding selected: payloadlen=%zd, padlen=%zu\n",
          padded_payloadlen, padlen);
 
-  rv = nghttp2_frame_add_pad(framebufs, &frame->hd, padlen, 0);
-
-  if (rv != 0) {
-    return rv;
-  }
+  nghttp2_frame_add_pad(framebufs, &frame->hd, padlen, 0);
 
   frame->headers.padlen = padlen;
 
@@ -2011,13 +2323,7 @@ static int session_prep_frame(nghttp2_se
       // Search stream including closed again.
       stream = nghttp2_session_get_stream_raw(session, frame->hd.stream_id);
       if (stream) {
-        int rv2;
-
-        rv2 = nghttp2_stream_detach_item(stream);
-
-        if (nghttp2_is_fatal(rv2)) {
-          return rv2;
-        }
+        session_detach_stream_item(session, stream);
       }
 
       return rv;
@@ -2032,12 +2338,8 @@ static int session_prep_frame(nghttp2_se
          queue when session->remote_window_size > 0 */
       assert(session->remote_window_size > 0);
 
-      rv = nghttp2_stream_defer_item(stream,
-                                     NGHTTP2_STREAM_FLAG_DEFERRED_FLOW_CONTROL);
-
-      if (nghttp2_is_fatal(rv)) {
-        return rv;
-      }
+      session_defer_stream_item(session, stream,
+                                NGHTTP2_STREAM_FLAG_DEFERRED_FLOW_CONTROL);
 
       session->aob.item = NULL;
       active_outbound_item_reset(&session->aob, mem);
@@ -2051,22 +2353,15 @@ static int session_prep_frame(nghttp2_se
       return rv;
     }
     if (rv == NGHTTP2_ERR_DEFERRED) {
-      rv = nghttp2_stream_defer_item(stream, NGHTTP2_STREAM_FLAG_DEFERRED_USER);
-
-      if (nghttp2_is_fatal(rv)) {
-        return rv;
-      }
+      session_defer_stream_item(session, stream,
+                                NGHTTP2_STREAM_FLAG_DEFERRED_USER);
 
       session->aob.item = NULL;
       active_outbound_item_reset(&session->aob, mem);
       return NGHTTP2_ERR_DEFERRED;
     }
     if (rv == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) {
-      rv = nghttp2_stream_detach_item(stream);
-
-      if (nghttp2_is_fatal(rv)) {
-        return rv;
-      }
+      session_detach_stream_item(session, stream);
 
       rv = nghttp2_session_add_rst_stream(session, frame->hd.stream_id,
                                           NGHTTP2_INTERNAL_ERROR);
@@ -2076,13 +2371,7 @@ static int session_prep_frame(nghttp2_se
       return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
     }
     if (rv != 0) {
-      int rv2;
-
-      rv2 = nghttp2_stream_detach_item(stream);
-
-      if (nghttp2_is_fatal(rv2)) {
-        return rv2;
-      }
+      session_detach_stream_item(session, stream);
 
       return rv;
     }
@@ -2328,6 +2617,18 @@ static int session_prep_frame(nghttp2_se
       }
 
       return 0;
+    case NGHTTP2_PRIORITY_UPDATE: {
+      nghttp2_ext_priority_update *priority_update = frame->ext.payload;
+      rv = session_predicate_priority_update_send(session,
+                                                  priority_update->stream_id);
+      if (rv != 0) {
+        return rv;
+      }
+
+      nghttp2_frame_pack_priority_update(&session->aob.framebufs, &frame->ext);
+
+      return 0;
+    }
     default:
       /* Unreachable here */
       assert(0);
@@ -2339,6 +2640,8 @@ static int session_prep_frame(nghttp2_se
 
 nghttp2_outbound_item *
 nghttp2_session_get_next_ob_item(nghttp2_session *session) {
+  nghttp2_outbound_item *item;
+
   if (nghttp2_outbound_queue_top(&session->ob_urgent)) {
     return nghttp2_outbound_queue_top(&session->ob_urgent);
   }
@@ -2354,7 +2657,12 @@ nghttp2_session_get_next_ob_item(nghttp2
   }
 
   if (session->remote_window_size > 0) {
-    return nghttp2_stream_next_outbound_item(&session->root);
+    item = nghttp2_stream_next_outbound_item(&session->root);
+    if (item) {
+      return item;
+    }
+
+    return session_sched_get_next_outbound_item(session);
   }
 
   return NULL;
@@ -2388,7 +2696,12 @@ nghttp2_session_pop_next_ob_item(nghttp2
   }
 
   if (session->remote_window_size > 0) {
-    return nghttp2_stream_next_outbound_item(&session->root);
+    item = nghttp2_stream_next_outbound_item(&session->root);
+    if (item) {
+      return item;
+    }
+
+    return session_sched_get_next_outbound_item(session);
   }
 
   return NULL;
@@ -2498,10 +2811,20 @@ static int session_close_stream_on_goawa
   return 0;
 }
 
-static void reschedule_stream(nghttp2_stream *stream) {
+static void session_reschedule_stream(nghttp2_session *session,
+                                      nghttp2_stream *stream) {
   stream->last_writelen = stream->item->frame.hd.length;
 
-  nghttp2_stream_reschedule(stream);
+  if (!(stream->flags & NGHTTP2_STREAM_FLAG_NO_RFC7540_PRIORITIES)) {
+    nghttp2_stream_reschedule(stream);
+    return;
+  }
+
+  if (!session->server) {
+    return;
+  }
+
+  session_sched_reschedule_stream(session, stream);
 }
 
 static int session_update_stream_consumed_size(nghttp2_session *session,
@@ -2550,10 +2873,7 @@ static int session_after_frame_sent1(ngh
     }
 
     if (stream && aux_data->eof) {
-      rv = nghttp2_stream_detach_item(stream);
-      if (nghttp2_is_fatal(rv)) {
-        return rv;
-      }
+      session_detach_stream_item(session, stream);
 
       /* Call on_frame_send_callback after
          nghttp2_stream_detach_item(), so that application can issue
@@ -2675,9 +2995,8 @@ static int session_after_frame_sent1(ngh
     }
   }
   case NGHTTP2_PRIORITY:
-    if (session->server) {
+    if (session->server || session->pending_no_rfc7540_priorities == 1) {
       return 0;
-      ;
     }
 
     stream = nghttp2_session_get_stream_raw(session, frame->hd.stream_id);
@@ -2787,17 +3106,8 @@ static int session_after_frame_sent1(ngh
 /*
  * Called after a frame is sent and session_after_frame_sent1.  This
  * function is responsible to reset session->aob.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGHTTP2_ERR_NOMEM
- *     Out of memory.
- * NGHTTP2_ERR_CALLBACK_FAILURE
- *     The callback function failed.
  */
-static int session_after_frame_sent2(nghttp2_session *session) {
-  int rv;
+static void session_after_frame_sent2(nghttp2_session *session) {
   nghttp2_active_outbound_item *aob = &session->aob;
   nghttp2_outbound_item *item = aob->item;
   nghttp2_bufs *framebufs = &aob->framebufs;
@@ -2820,13 +3130,13 @@ static int session_after_frame_sent2(ngh
         DEBUGF("send: next CONTINUATION frame, %zu bytes\n",
                nghttp2_buf_len(&framebufs->cur->buf));
 
-        return 0;
+        return;
       }
     }
 
     active_outbound_item_reset(&session->aob, mem);
 
-    return 0;
+    return;
   }
 
   /* DATA frame */
@@ -2840,7 +3150,7 @@ static int session_after_frame_sent2(ngh
   if (aux_data->eof) {
     active_outbound_item_reset(aob, mem);
 
-    return 0;
+    return;
   }
 
   /* Reset no_copy here because next write may not use this. */
@@ -2852,22 +3162,18 @@ static int session_after_frame_sent2(ngh
      further data. */
   if (nghttp2_session_predicate_data_send(session, stream) != 0) {
     if (stream) {
-      rv = nghttp2_stream_detach_item(stream);
-
-      if (nghttp2_is_fatal(rv)) {
-        return rv;
-      }
+      session_detach_stream_item(session, stream);
     }
 
     active_outbound_item_reset(aob, mem);
 
-    return 0;
+    return;
   }
 
   aob->item = NULL;
   active_outbound_item_reset(&session->aob, mem);
 
-  return 0;
+  return;
 }
 
 static int session_call_send_data(nghttp2_session *session,
@@ -2940,6 +3246,7 @@ static ssize_t nghttp2_session_mem_send_
       if (rv < 0) {
         int32_t opened_stream_id = 0;
         uint32_t error_code = NGHTTP2_INTERNAL_ERROR;
+        int rv2 = 0;
 
         DEBUGF("send: frame preparation failed with %s\n",
                nghttp2_strerror(rv));
@@ -2982,19 +3289,18 @@ static ssize_t nghttp2_session_mem_send_
         }
         if (opened_stream_id) {
           /* careful not to override rv */
-          int rv2;
           rv2 = nghttp2_session_close_stream(session, opened_stream_id,
                                              error_code);
-
-          if (nghttp2_is_fatal(rv2)) {
-            return rv2;
-          }
         }
 
         nghttp2_outbound_item_free(item, mem);
         nghttp2_mem_free(mem, item);
         active_outbound_item_reset(aob, mem);
 
+        if (nghttp2_is_fatal(rv2)) {
+          return rv2;
+        }
+
         if (rv == NGHTTP2_ERR_HEADER_COMP) {
           /* If header compression error occurred, should terminiate
              connection. */
@@ -3098,7 +3404,7 @@ static ssize_t nghttp2_session_mem_send_
 
         /* Frame has completely sent */
         if (fast_cb) {
-          rv = session_after_frame_sent2(session);
+          session_after_frame_sent2(session);
         } else {
           rv = session_after_frame_sent1(session);
           if (rv < 0) {
@@ -3106,12 +3412,7 @@ static ssize_t nghttp2_session_mem_send_
             assert(nghttp2_is_fatal(rv));
             return rv;
           }
-          rv = session_after_frame_sent2(session);
-        }
-        if (rv < 0) {
-          /* FATAL */
-          assert(nghttp2_is_fatal(rv));
-          return rv;
+          session_after_frame_sent2(session);
         }
         /* We have already adjusted the next state */
         break;
@@ -3150,11 +3451,7 @@ static ssize_t nghttp2_session_mem_send_
       }
 
       if (rv == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) {
-        rv = nghttp2_stream_detach_item(stream);
-
-        if (nghttp2_is_fatal(rv)) {
-          return rv;
-        }
+        session_detach_stream_item(session, stream);
 
         rv = nghttp2_session_add_rst_stream(session, frame->hd.stream_id,
                                             NGHTTP2_INTERNAL_ERROR);
@@ -3178,11 +3475,7 @@ static ssize_t nghttp2_session_mem_send_
         assert(nghttp2_is_fatal(rv));
         return rv;
       }
-      rv = session_after_frame_sent2(session);
-      if (rv < 0) {
-        assert(nghttp2_is_fatal(rv));
-        return rv;
-      }
+      session_after_frame_sent2(session);
 
       /* We have already adjusted the next state */
 
@@ -3730,6 +4023,21 @@ static int session_end_stream_headers_re
                                                nghttp2_frame *frame,
                                                nghttp2_stream *stream) {
   int rv;
+
+  assert(frame->hd.type == NGHTTP2_HEADERS);
+
+  if (session->server && session_enforce_http_messaging(session) &&
+      frame->headers.cat == NGHTTP2_HCAT_REQUEST &&
+      (stream->flags & NGHTTP2_STREAM_FLAG_NO_RFC7540_PRIORITIES) &&
+      !(stream->flags & NGHTTP2_STREAM_FLAG_IGNORE_CLIENT_PRIORITIES) &&
+      (stream->http_flags & NGHTTP2_HTTP_FLAG_PRIORITY)) {
+    rv = session_update_stream_priority(session, stream, stream->http_extpri);
+    if (rv != 0) {
+      assert(nghttp2_is_fatal(rv));
+      return rv;
+    }
+  }
+
   if ((frame->hd.flags & NGHTTP2_FLAG_END_STREAM) == 0) {
     return 0;
   }
@@ -4053,17 +4361,12 @@ int nghttp2_session_on_headers_received(
 }
 
 static int session_process_headers_frame(nghttp2_session *session) {
-  int rv;
   nghttp2_inbound_frame *iframe = &session->iframe;
   nghttp2_frame *frame = &iframe->frame;
   nghttp2_stream *stream;
 
-  rv = nghttp2_frame_unpack_headers_payload(&frame->headers, iframe->sbuf.pos);
+  nghttp2_frame_unpack_headers_payload(&frame->headers, iframe->sbuf.pos);
 
-  if (rv != 0) {
-    return nghttp2_session_terminate_session_with_reason(
-        session, NGHTTP2_PROTOCOL_ERROR, "HEADERS: could not unpack");
-  }
   stream = nghttp2_session_get_stream(session, frame->hd.stream_id);
   if (!stream) {
     frame->headers.cat = NGHTTP2_HCAT_REQUEST;
@@ -4091,6 +4394,8 @@ int nghttp2_session_on_priority_received
   int rv;
   nghttp2_stream *stream;
 
+  assert(!session_no_rfc7540_pri_no_fallback(session));
+
   if (frame->hd.stream_id == 0) {
     return session_handle_invalid_connection(session, frame, NGHTTP2_ERR_PROTO,
                                              "PRIORITY: stream_id == 0");
@@ -4148,11 +4453,30 @@ static int session_process_priority_fram
   nghttp2_inbound_frame *iframe = &session->iframe;
   nghttp2_frame *frame = &iframe->frame;
 
+  assert(!session_no_rfc7540_pri_no_fallback(session));
+
   nghttp2_frame_unpack_priority_payload(&frame->priority, iframe->sbuf.pos);
 
   return nghttp2_session_on_priority_received(session, frame);
 }
 
+static int session_update_stream_reset_ratelim(nghttp2_session *session) {
+  if (!session->server || (session->goaway_flags & NGHTTP2_GOAWAY_SUBMITTED)) {
+    return 0;
+  }
+
+  nghttp2_ratelim_update(&session->stream_reset_ratelim,
+                         nghttp2_time_now_sec());
+
+  if (nghttp2_ratelim_drain(&session->stream_reset_ratelim, 1) == 0) {
+    return 0;
+  }
+
+  return nghttp2_session_add_goaway(session, session->last_recv_stream_id,
+                                    NGHTTP2_INTERNAL_ERROR, NULL, 0,
+                                    NGHTTP2_GOAWAY_AUX_NONE);
+}
+
 int nghttp2_session_on_rst_stream_received(nghttp2_session *session,
                                            nghttp2_frame *frame) {
   int rv;
@@ -4182,7 +4506,8 @@ int nghttp2_session_on_rst_stream_receiv
   if (nghttp2_is_fatal(rv)) {
     return rv;
   }
-  return 0;
+
+  return session_update_stream_reset_ratelim(session);
 }
 
 static int session_process_rst_stream_frame(nghttp2_session *session) {
@@ -4214,8 +4539,8 @@ static int update_remote_initial_window_
   if (stream->remote_window_size > 0 &&
       nghttp2_stream_check_deferred_by_flow_control(stream)) {
 
-    rv = nghttp2_stream_resume_deferred_item(
-        stream, NGHTTP2_STREAM_FLAG_DEFERRED_FLOW_CONTROL);
+    rv = session_resume_deferred_stream_item(
+        arg->session, stream, NGHTTP2_STREAM_FLAG_DEFERRED_FLOW_CONTROL);
 
     if (nghttp2_is_fatal(rv)) {
       return rv;
@@ -4259,9 +4584,16 @@ static int update_local_initial_window_s
     return nghttp2_session_add_rst_stream(arg->session, stream->stream_id,
                                           NGHTTP2_FLOW_CONTROL_ERROR);
   }
-  if (!(arg->session->opt_flags & NGHTTP2_OPTMASK_NO_AUTO_WINDOW_UPDATE) &&
-      stream->window_update_queued == 0 &&
-      nghttp2_should_send_window_update(stream->local_window_size,
+
+  if (stream->window_update_queued) {
+    return 0;
+  }
+
+  if (arg->session->opt_flags & NGHTTP2_OPTMASK_NO_AUTO_WINDOW_UPDATE) {
+    return session_update_stream_consumed_size(arg->session, stream, 0);
+  }
+
+  if (nghttp2_should_send_window_update(stream->local_window_size,
                                         stream->recv_window_size)) {
 
     rv = nghttp2_session_add_window_update(arg->session, NGHTTP2_FLAG_NONE,
@@ -4382,6 +4714,9 @@ int nghttp2_session_update_local_setting
     case NGHTTP2_SETTINGS_ENABLE_CONNECT_PROTOCOL:
       session->local_settings.enable_connect_protocol = iv[i].value;
       break;
+    case NGHTTP2_SETTINGS_NO_RFC7540_PRIORITIES:
+      session->local_settings.no_rfc7540_priorities = iv[i].value;
+      break;
     }
   }
 
@@ -4541,6 +4876,34 @@ int nghttp2_session_on_settings_received
       session->remote_settings.enable_connect_protocol = entry->value;
 
       break;
+    case NGHTTP2_SETTINGS_NO_RFC7540_PRIORITIES:
+
+      if (entry->value != 0 && entry->value != 1) {
+        return session_handle_invalid_connection(
+            session, frame, NGHTTP2_ERR_PROTO,
+            "SETTINGS: invalid SETTINGS_NO_RFC7540_PRIORITIES");
+      }
+
+      if (session->remote_settings.no_rfc7540_priorities != UINT32_MAX &&
+          session->remote_settings.no_rfc7540_priorities != entry->value) {
+        return session_handle_invalid_connection(
+            session, frame, NGHTTP2_ERR_PROTO,
+            "SETTINGS: SETTINGS_NO_RFC7540_PRIORITIES cannot be changed");
+      }
+
+      session->remote_settings.no_rfc7540_priorities = entry->value;
+
+      break;
+    }
+  }
+
+  if (session->remote_settings.no_rfc7540_priorities == UINT32_MAX) {
+    session->remote_settings.no_rfc7540_priorities = 0;
+
+    if (session->server && session->pending_no_rfc7540_priorities &&
+        (session->opt_flags &
+         NGHTTP2_OPTMASK_SERVER_FALLBACK_RFC7540_PRIORITIES)) {
+      session->fallback_rfc7540_priorities = 1;
     }
   }
 
@@ -4684,17 +5047,11 @@ int nghttp2_session_on_push_promise_rece
 }
 
 static int session_process_push_promise_frame(nghttp2_session *session) {
-  int rv;
   nghttp2_inbound_frame *iframe = &session->iframe;
   nghttp2_frame *frame = &iframe->frame;
 
-  rv = nghttp2_frame_unpack_push_promise_payload(&frame->push_promise,
-                                                 iframe->sbuf.pos);
-
-  if (rv != 0) {
-    return nghttp2_session_terminate_session_with_reason(
-        session, NGHTTP2_PROTOCOL_ERROR, "PUSH_PROMISE: could not unpack");
-  }
+  nghttp2_frame_unpack_push_promise_payload(&frame->push_promise,
+                                            iframe->sbuf.pos);
 
   return nghttp2_session_on_push_promise_received(session, frame);
 }
@@ -4826,8 +5183,8 @@ static int session_on_stream_window_upda
   if (stream->remote_window_size > 0 &&
       nghttp2_stream_check_deferred_by_flow_control(stream)) {
 
-    rv = nghttp2_stream_resume_deferred_item(
-        stream, NGHTTP2_STREAM_FLAG_DEFERRED_FLOW_CONTROL);
+    rv = session_resume_deferred_stream_item(
+        session, stream, NGHTTP2_STREAM_FLAG_DEFERRED_FLOW_CONTROL);
 
     if (nghttp2_is_fatal(rv)) {
       return rv;
@@ -4898,6 +5255,80 @@ int nghttp2_session_on_origin_received(n
   return session_call_on_frame_received(session, frame);
 }
 
+int nghttp2_session_on_priority_update_received(nghttp2_session *session,
+                                                nghttp2_frame *frame) {
+  nghttp2_ext_priority_update *priority_update;
+  nghttp2_stream *stream;
+  nghttp2_priority_spec pri_spec;
+  nghttp2_extpri extpri;
+  int rv;
+
+  assert(session->server);
+
+  priority_update = frame->ext.payload;
+
+  if (frame->hd.stream_id != 0) {
+    return session_handle_invalid_connection(session, frame, NGHTTP2_ERR_PROTO,
+                                             "PRIORITY_UPDATE: stream_id == 0");
+  }
+
+  if (nghttp2_session_is_my_stream_id(session, priority_update->stream_id)) {
+    if (session_detect_idle_stream(session, priority_update->stream_id)) {
+      return session_handle_invalid_connection(
+          session, frame, NGHTTP2_ERR_PROTO,
+          "PRIORITY_UPDATE: prioritizing idle push is not allowed");
+    }
+
+    /* TODO Ignore priority signal to a push stream for now */
+    return session_call_on_frame_received(session, frame);
+  }
+
+  stream = nghttp2_session_get_stream_raw(session, priority_update->stream_id);
+  if (stream) {
+    /* Stream already exists. */
+    if (stream->flags & NGHTTP2_STREAM_FLAG_IGNORE_CLIENT_PRIORITIES) {
+      return session_call_on_frame_received(session, frame);
+    }
+  } else if (session_detect_idle_stream(session, priority_update->stream_id)) {
+    if (session->num_idle_streams + session->num_incoming_streams >=
+        session->local_settings.max_concurrent_streams) {
+      return session_handle_invalid_connection(
+          session, frame, NGHTTP2_ERR_PROTO,
+          "PRIORITY_UPDATE: max concurrent streams exceeded");
+    }
+
+    nghttp2_priority_spec_default_init(&pri_spec);
+    stream = nghttp2_session_open_stream(session, priority_update->stream_id,
+                                         NGHTTP2_FLAG_NONE, &pri_spec,
+                                         NGHTTP2_STREAM_IDLE, NULL);
+    if (!stream) {
+      return NGHTTP2_ERR_NOMEM;
+    }
+  } else {
+    return session_call_on_frame_received(session, frame);
+  }
+
+  extpri.urgency = NGHTTP2_EXTPRI_DEFAULT_URGENCY;
+  extpri.inc = 0;
+
+  rv = nghttp2_http_parse_priority(&extpri, priority_update->field_value,
+                                   priority_update->field_value_len);
+  if (rv != 0) {
+    /* Just ignore field_value if it cannot be parsed. */
+    return session_call_on_frame_received(session, frame);
+  }
+
+  rv = session_update_stream_priority(session, stream,
+                                      nghttp2_extpri_to_uint8(&extpri));
+  if (rv != 0) {
+    if (nghttp2_is_fatal(rv)) {
+      return rv;
+    }
+  }
+
+  return session_call_on_frame_received(session, frame);
+}
+
 static int session_process_altsvc_frame(nghttp2_session *session) {
   nghttp2_inbound_frame *iframe = &session->iframe;
   nghttp2_frame *frame = &iframe->frame;
@@ -4932,6 +5363,16 @@ static int session_process_origin_frame(
   return nghttp2_session_on_origin_received(session, frame);
 }
 
+static int session_process_priority_update_frame(nghttp2_session *session) {
+  nghttp2_inbound_frame *iframe = &session->iframe;
+  nghttp2_frame *frame = &iframe->frame;
+
+  nghttp2_frame_unpack_priority_update_payload(&frame->ext, iframe->sbuf.pos,
+                                               nghttp2_buf_len(&iframe->sbuf));
+
+  return nghttp2_session_on_priority_update_received(session, frame);
+}
+
 static int session_process_extension_frame(nghttp2_session *session) {
   int rv;
   nghttp2_inbound_frame *iframe = &session->iframe;
@@ -5269,6 +5710,7 @@ static void inbound_frame_set_settings_e
   case NGHTTP2_SETTINGS_MAX_FRAME_SIZE:
   case NGHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE:
   case NGHTTP2_SETTINGS_ENABLE_CONNECT_PROTOCOL:
+  case NGHTTP2_SETTINGS_NO_RFC7540_PRIORITIES:
     break;
   default:
     DEBUGF("recv: unknown settings id=0x%02x\n", iv.settings_id);
@@ -5429,7 +5871,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2
       in += readlen;
 
       if (nghttp2_buf_mark_avail(&iframe->sbuf)) {
-        return in - first;
+        return (ssize_t)(in - first);
       }
 
       if (iframe->sbuf.pos[3] != NGHTTP2_SETTINGS ||
@@ -5466,7 +5908,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2
       in += readlen;
 
       if (nghttp2_buf_mark_avail(&iframe->sbuf)) {
-        return in - first;
+        return (ssize_t)(in - first);
       }
 
       nghttp2_frame_unpack_frame_hd(&iframe->frame.hd, iframe->sbuf.pos);
@@ -5883,6 +6325,49 @@ ssize_t nghttp2_session_mem_recv(nghttp2
             iframe->state = NGHTTP2_IB_READ_ORIGIN_PAYLOAD;
 
             break;
+          case NGHTTP2_PRIORITY_UPDATE:
+            if ((session->builtin_recv_ext_types &
+                 NGHTTP2_TYPEMASK_PRIORITY_UPDATE) == 0) {
+              busy = 1;
+              iframe->state = NGHTTP2_IB_IGN_PAYLOAD;
+              break;
+            }
+
+            DEBUGF("recv: PRIORITY_UPDATE\n");
+
+            iframe->frame.hd.flags = NGHTTP2_FLAG_NONE;
+            iframe->frame.ext.payload =
+                &iframe->ext_frame_payload.priority_update;
+
+            if (!session->server) {
+              rv = nghttp2_session_terminate_session_with_reason(
+                  session, NGHTTP2_PROTOCOL_ERROR,
+                  "PRIORITY_UPDATE is received from server");
+              if (nghttp2_is_fatal(rv)) {
+                return rv;
+              }
+              return (ssize_t)inlen;
+            }
+
+            if (iframe->payloadleft < 4) {
+              busy = 1;
+              iframe->state = NGHTTP2_IB_FRAME_SIZE_ERROR;
+              break;
+            }
+
+            if (!session_no_rfc7540_pri_no_fallback(session) ||
+                iframe->payloadleft > sizeof(iframe->raw_sbuf)) {
+              busy = 1;
+              iframe->state = NGHTTP2_IB_IGN_PAYLOAD;
+              break;
+            }
+
+            busy = 1;
+
+            iframe->state = NGHTTP2_IB_READ_NBYTE;
+            inbound_frame_set_mark(iframe, iframe->payloadleft);
+
+            break;
           default:
             busy = 1;
 
@@ -5923,7 +6408,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2
              iframe->payloadleft, nghttp2_buf_mark_avail(&iframe->sbuf));
 
       if (nghttp2_buf_mark_avail(&iframe->sbuf)) {
-        return in - first;
+        return (ssize_t)(in - first);
       }
 
       switch (iframe->frame.hd.type) {
@@ -5988,13 +6473,16 @@ ssize_t nghttp2_session_mem_recv(nghttp2
 
         break;
       case NGHTTP2_PRIORITY:
-        rv = session_process_priority_frame(session);
-        if (nghttp2_is_fatal(rv)) {
-          return rv;
-        }
+        if (!session_no_rfc7540_pri_no_fallback(session) &&
+            session->remote_settings.no_rfc7540_priorities != 1) {
+          rv = session_process_priority_frame(session);
+          if (nghttp2_is_fatal(rv)) {
+            return rv;
+          }
 
-        if (iframe->state == NGHTTP2_IB_IGN_ALL) {
-          return (ssize_t)inlen;
+          if (iframe->state == NGHTTP2_IB_IGN_ALL) {
+            return (ssize_t)inlen;
+          }
         }
 
         session_inbound_frame_reset(session);
@@ -6151,6 +6639,18 @@ ssize_t nghttp2_session_mem_recv(nghttp2
         iframe->state = NGHTTP2_IB_READ_ALTSVC_PAYLOAD;
 
         break;
+      case NGHTTP2_PRIORITY_UPDATE:
+        DEBUGF("recv: prioritized_stream_id=%d\n",
+               nghttp2_get_uint32(iframe->sbuf.pos) & NGHTTP2_STREAM_ID_MASK);
+
+        rv = session_process_priority_update_frame(session);
+        if (nghttp2_is_fatal(rv)) {
+          return rv;
+        }
+
+        session_inbound_frame_reset(session);
+
+        break;
       }
       default:
         /* This is unknown frame */
@@ -6212,7 +6712,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2
           in += hd_proclen;
           iframe->payloadleft -= hd_proclen;
 
-          return in - first;
+          return (ssize_t)(in - first);
         }
 
         if (rv == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) {
@@ -6403,7 +6903,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2
       in += readlen;
 
       if (nghttp2_buf_mark_avail(&iframe->sbuf)) {
-        return in - first;
+        return (ssize_t)(in - first);
       }
 
       nghttp2_frame_unpack_frame_hd(&cont_hd, iframe->sbuf.pos);
@@ -6461,7 +6961,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2
              iframe->payloadleft, nghttp2_buf_mark_avail(&iframe->sbuf));
 
       if (nghttp2_buf_mark_avail(&iframe->sbuf)) {
-        return in - first;
+        return (ssize_t)(in - first);
       }
 
       /* Pad Length field is subject to flow control */
@@ -6611,7 +7111,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2
                 session, iframe->frame.hd.flags, iframe->frame.hd.stream_id,
                 in - readlen, (size_t)data_readlen, session->user_data);
             if (rv == NGHTTP2_ERR_PAUSE) {
-              return in - first;
+              return (ssize_t)(in - first);
             }
 
             if (nghttp2_is_fatal(rv)) {
@@ -6791,7 +7291,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2
 
   assert(in == last);
 
-  return in - first;
+  return (ssize_t)(in - first);
 }
 
 int nghttp2_session_recv(nghttp2_session *session) {
@@ -6863,7 +7363,8 @@ int nghttp2_session_want_write(nghttp2_s
    */
   return session->aob.item || nghttp2_outbound_queue_top(&session->ob_urgent) ||
          nghttp2_outbound_queue_top(&session->ob_reg) ||
-         (!nghttp2_pq_empty(&session->root.obq) &&
+         ((!nghttp2_pq_empty(&session->root.obq) ||
+           !session_sched_empty(session)) &&
           session->remote_window_size > 0) ||
          (nghttp2_outbound_queue_top(&session->ob_syn) &&
           !session_is_outgoing_concurrent_streams_max(session));
@@ -6962,6 +7463,9 @@ int nghttp2_session_add_goaway(nghttp2_s
     nghttp2_mem_free(mem, item);
     return rv;
   }
+
+  session->goaway_flags |= NGHTTP2_GOAWAY_SUBMITTED;
+
   return 0;
 }
 
@@ -7016,6 +7520,7 @@ int nghttp2_session_add_settings(nghttp2
   int rv;
   nghttp2_mem *mem;
   nghttp2_inflight_settings *inflight_settings = NULL;
+  uint8_t no_rfc7540_pri = session->pending_no_rfc7540_priorities;
 
   mem = &session->mem;
 
@@ -7033,6 +7538,21 @@ int nghttp2_session_add_settings(nghttp2
     return NGHTTP2_ERR_INVALID_ARGUMENT;
   }
 
+  for (i = 0; i < niv; ++i) {
+    if (iv[i].settings_id != NGHTTP2_SETTINGS_NO_RFC7540_PRIORITIES) {
+      continue;
+    }
+
+    if (no_rfc7540_pri == UINT8_MAX) {
+      no_rfc7540_pri = (uint8_t)iv[i].value;
+      continue;
+    }
+
+    if (iv[i].value != (uint32_t)no_rfc7540_pri) {
+      return NGHTTP2_ERR_INVALID_ARGUMENT;
+    }
+  }
+
   item = nghttp2_mem_malloc(mem, sizeof(nghttp2_outbound_item));
   if (item == NULL) {
     return NGHTTP2_ERR_NOMEM;
@@ -7107,6 +7627,12 @@ int nghttp2_session_add_settings(nghttp2
     }
   }
 
+  if (no_rfc7540_pri == UINT8_MAX) {
+    session->pending_no_rfc7540_priorities = 0;
+  } else {
+    session->pending_no_rfc7540_priorities = no_rfc7540_pri;
+  }
+
   return 0;
 }
 
@@ -7229,13 +7755,10 @@ int nghttp2_session_pack_data(nghttp2_se
 
   nghttp2_frame_pack_frame_hd(buf->pos, &frame->hd);
 
-  rv = nghttp2_frame_add_pad(bufs, &frame->hd, frame->data.padlen,
-                             aux_data->no_copy);
-  if (rv != 0) {
-    return rv;
-  }
+  nghttp2_frame_add_pad(bufs, &frame->hd, frame->data.padlen,
+                        aux_data->no_copy);
 
-  reschedule_stream(stream);
+  session_reschedule_stream(session, stream);
 
   if (frame->hd.length == 0 && (data_flags & NGHTTP2_DATA_FLAG_EOF) &&
       (data_flags & NGHTTP2_DATA_FLAG_NO_END_STREAM)) {
@@ -7309,7 +7832,7 @@ int nghttp2_session_resume_data(nghttp2_
     return NGHTTP2_ERR_INVALID_ARGUMENT;
   }
 
-  rv = nghttp2_stream_resume_deferred_item(stream,
+  rv = session_resume_deferred_stream_item(session, stream,
                                            NGHTTP2_STREAM_FLAG_DEFERRED_USER);
 
   if (nghttp2_is_fatal(rv)) {
@@ -7417,6 +7940,8 @@ uint32_t nghttp2_session_get_remote_sett
     return session->remote_settings.max_header_list_size;
   case NGHTTP2_SETTINGS_ENABLE_CONNECT_PROTOCOL:
     return session->remote_settings.enable_connect_protocol;
+  case NGHTTP2_SETTINGS_NO_RFC7540_PRIORITIES:
+    return session->remote_settings.no_rfc7540_priorities;
   }
 
   assert(0);
@@ -7440,6 +7965,8 @@ uint32_t nghttp2_session_get_local_setti
     return session->local_settings.max_header_list_size;
   case NGHTTP2_SETTINGS_ENABLE_CONNECT_PROTOCOL:
     return session->local_settings.enable_connect_protocol;
+  case NGHTTP2_SETTINGS_NO_RFC7540_PRIORITIES:
+    return session->local_settings.no_rfc7540_priorities;
   }
 
   assert(0);
@@ -7723,6 +8250,10 @@ int nghttp2_session_change_stream_priori
   nghttp2_stream *stream;
   nghttp2_priority_spec pri_spec_copy;
 
+  if (session->pending_no_rfc7540_priorities == 1) {
+    return 0;
+  }
+
   if (stream_id == 0 || stream_id == pri_spec->stream_id) {
     return NGHTTP2_ERR_INVALID_ARGUMENT;
   }
@@ -7755,6 +8286,10 @@ int nghttp2_session_create_idle_stream(n
   nghttp2_stream *stream;
   nghttp2_priority_spec pri_spec_copy;
 
+  if (session->pending_no_rfc7540_priorities == 1) {
+    return 0;
+  }
+
   if (stream_id == 0 || stream_id == pri_spec->stream_id ||
       !session_detect_idle_stream(session, stream_id)) {
     return NGHTTP2_ERR_INVALID_ARGUMENT;
@@ -7796,3 +8331,38 @@ nghttp2_session_get_hd_deflate_dynamic_t
 void nghttp2_session_set_user_data(nghttp2_session *session, void *user_data) {
   session->user_data = user_data;
 }
+
+int nghttp2_session_change_extpri_stream_priority(
+    nghttp2_session *session, int32_t stream_id,
+    const nghttp2_extpri *extpri_in, int ignore_client_signal) {
+  nghttp2_stream *stream;
+  nghttp2_extpri extpri = *extpri_in;
+
+  if (!session->server) {
+    return NGHTTP2_ERR_INVALID_STATE;
+  }
+
+  if (session->pending_no_rfc7540_priorities != 1) {
+    return 0;
+  }
+
+  if (stream_id == 0) {
+    return NGHTTP2_ERR_INVALID_ARGUMENT;
+  }
+
+  stream = nghttp2_session_get_stream_raw(session, stream_id);
+  if (!stream) {
+    return NGHTTP2_ERR_INVALID_ARGUMENT;
+  }
+
+  if (extpri.urgency > NGHTTP2_EXTPRI_URGENCY_LOW) {
+    extpri.urgency = NGHTTP2_EXTPRI_URGENCY_LOW;
+  }
+
+  if (ignore_client_signal) {
+    stream->flags |= NGHTTP2_STREAM_FLAG_IGNORE_CLIENT_PRIORITIES;
+  }
+
+  return session_update_stream_priority(session, stream,
+                                        nghttp2_extpri_to_uint8(&extpri));
+}
Index: node-v16.20.2/deps/nghttp2/lib/nghttp2_session.h
===================================================================
--- node-v16.20.2.orig/deps/nghttp2/lib/nghttp2_session.h
+++ node-v16.20.2/deps/nghttp2/lib/nghttp2_session.h
@@ -39,6 +39,7 @@
 #include "nghttp2_buf.h"
 #include "nghttp2_callbacks.h"
 #include "nghttp2_mem.h"
+#include "nghttp2_ratelim.h"
 
 /* The global variable for tests where we want to disable strict
    preface handling. */
@@ -52,7 +53,9 @@ typedef enum {
   NGHTTP2_OPTMASK_NO_RECV_CLIENT_MAGIC = 1 << 1,
   NGHTTP2_OPTMASK_NO_HTTP_MESSAGING = 1 << 2,
   NGHTTP2_OPTMASK_NO_AUTO_PING_ACK = 1 << 3,
-  NGHTTP2_OPTMASK_NO_CLOSED_STREAMS = 1 << 4
+  NGHTTP2_OPTMASK_NO_CLOSED_STREAMS = 1 << 4,
+  NGHTTP2_OPTMASK_SERVER_FALLBACK_RFC7540_PRIORITIES = 1 << 5,
+  NGHTTP2_OPTMASK_NO_RFC9113_LEADING_AND_TRAILING_WS_VALIDATION = 1 << 6,
 } nghttp2_optmask;
 
 /*
@@ -62,7 +65,8 @@ typedef enum {
 typedef enum {
   NGHTTP2_TYPEMASK_NONE = 0,
   NGHTTP2_TYPEMASK_ALTSVC = 1 << 0,
-  NGHTTP2_TYPEMASK_ORIGIN = 1 << 1
+  NGHTTP2_TYPEMASK_ORIGIN = 1 << 1,
+  NGHTTP2_TYPEMASK_PRIORITY_UPDATE = 1 << 2
 } nghttp2_typemask;
 
 typedef enum {
@@ -102,6 +106,10 @@ typedef struct {
 /* The default value of maximum number of concurrent streams. */
 #define NGHTTP2_DEFAULT_MAX_CONCURRENT_STREAMS 0xffffffffu
 
+/* The default values for stream reset rate limiter. */
+#define NGHTTP2_DEFAULT_STREAM_RESET_BURST 1000
+#define NGHTTP2_DEFAULT_STREAM_RESET_RATE 33
+
 /* Internal state when receiving incoming frame */
 typedef enum {
   /* Receiving frame header */
@@ -151,10 +159,8 @@ typedef struct {
   /* padding length for the current frame */
   size_t padlen;
   nghttp2_inbound_state state;
-  /* Small buffer.  Currently the largest contiguous chunk to buffer
-     is frame header.  We buffer part of payload, but they are smaller
-     than frame header. */
-  uint8_t raw_sbuf[NGHTTP2_FRAME_HDLEN];
+  /* Small fixed sized buffer. */
+  uint8_t raw_sbuf[32];
 } nghttp2_inbound_frame;
 
 typedef struct {
@@ -165,6 +171,7 @@ typedef struct {
   uint32_t max_frame_size;
   uint32_t max_header_list_size;
   uint32_t enable_connect_protocol;
+  uint32_t no_rfc7540_priorities;
 } nghttp2_settings_storage;
 
 typedef enum {
@@ -176,7 +183,9 @@ typedef enum {
   /* Flag means GOAWAY was sent */
   NGHTTP2_GOAWAY_SENT = 0x4,
   /* Flag means GOAWAY was received */
-  NGHTTP2_GOAWAY_RECV = 0x8
+  NGHTTP2_GOAWAY_RECV = 0x8,
+  /* Flag means GOAWAY has been submitted at least once */
+  NGHTTP2_GOAWAY_SUBMITTED = 0x10
 } nghttp2_goaway_flag;
 
 /* nghttp2_inflight_settings stores the SETTINGS entries which local
@@ -202,6 +211,12 @@ struct nghttp2_session {
      response) frame, which are subject to
      SETTINGS_MAX_CONCURRENT_STREAMS limit. */
   nghttp2_outbound_queue ob_syn;
+  /* Queues for DATA frames which is used when
+     SETTINGS_NO_RFC7540_PRIORITIES is enabled.  This implements RFC
+     9218 extensible prioritization scheme. */
+  struct {
+    nghttp2_pq ob_data;
+  } sched[NGHTTP2_EXTPRI_URGENCY_LEVELS];
   nghttp2_active_outbound_item aob;
   nghttp2_inbound_frame iframe;
   nghttp2_hd_deflater hd_deflater;
@@ -227,6 +242,12 @@ struct nghttp2_session {
   /* Queue of In-flight SETTINGS values.  SETTINGS bearing ACK is not
      considered as in-flight. */
   nghttp2_inflight_settings *inflight_settings_head;
+  /* Stream reset rate limiter.  If receiving excessive amount of
+     stream resets, GOAWAY will be sent. */
+  nghttp2_ratelim stream_reset_ratelim;
+  /* Sequential number across all streams to process streams in
+     FIFO. */
+  uint64_t stream_seq;
   /* The number of outgoing streams. This will be capped by
      remote_settings.max_concurrent_streams. */
   size_t num_outgoing_streams;
@@ -328,6 +349,11 @@ struct nghttp2_session {
   /* Unacked local ENABLE_CONNECT_PROTOCOL value.  We use this to
      accept :protocol header field before SETTINGS_ACK is received. */
   uint8_t pending_enable_connect_protocol;
+  /* Unacked local SETTINGS_NO_RFC7540_PRIORITIES value, which is
+     effective before it is acknowledged. */
+  uint8_t pending_no_rfc7540_priorities;
+  /* Turn on fallback to RFC 7540 priorities; for server use only. */
+  uint8_t fallback_rfc7540_priorities;
   /* Nonzero if the session is server side. */
   uint8_t server;
   /* Flags indicating GOAWAY is sent and/or received. The flags are
@@ -774,6 +800,19 @@ int nghttp2_session_on_origin_received(n
                                        nghttp2_frame *frame);
 
 /*
+ * Called when PRIORITY_UPDATE is received, assuming |frame| is
+ * properly initialized.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_CALLBACK_FAILURE
+ *     The callback function failed.
+ */
+int nghttp2_session_on_priority_update_received(nghttp2_session *session,
+                                                nghttp2_frame *frame);
+
+/*
  * Called when DATA is received, assuming |frame| is properly
  * initialized.
  *
Index: node-v16.20.2/deps/nghttp2/lib/nghttp2_stream.c
===================================================================
--- node-v16.20.2.orig/deps/nghttp2/lib/nghttp2_stream.c
+++ node-v16.20.2/deps/nghttp2/lib/nghttp2_stream.c
@@ -100,6 +100,8 @@ void nghttp2_stream_init(nghttp2_stream
   stream->descendant_next_seq = 0;
   stream->seq = 0;
   stream->last_writelen = 0;
+
+  stream->extpri = stream->http_extpri = NGHTTP2_EXTPRI_DEFAULT_URGENCY;
 }
 
 void nghttp2_stream_free(nghttp2_stream *stream) {
@@ -463,14 +465,12 @@ static int stream_update_dep_on_attach_i
   return 0;
 }
 
-static int stream_update_dep_on_detach_item(nghttp2_stream *stream) {
+static void stream_update_dep_on_detach_item(nghttp2_stream *stream) {
   if (nghttp2_pq_empty(&stream->obq)) {
     stream_obq_remove(stream);
   }
 
   validate_tree(stream);
-
-  return 0;
 }
 
 int nghttp2_stream_attach_item(nghttp2_stream *stream,
@@ -484,6 +484,10 @@ int nghttp2_stream_attach_item(nghttp2_s
 
   stream->item = item;
 
+  if (stream->flags & NGHTTP2_STREAM_FLAG_NO_RFC7540_PRIORITIES) {
+    return 0;
+  }
+
   rv = stream_update_dep_on_attach_item(stream);
   if (rv != 0) {
     /* This may relave stream->queued == 1, but stream->item == NULL.
@@ -497,16 +501,20 @@ int nghttp2_stream_attach_item(nghttp2_s
   return 0;
 }
 
-int nghttp2_stream_detach_item(nghttp2_stream *stream) {
+void nghttp2_stream_detach_item(nghttp2_stream *stream) {
   DEBUGF("stream: stream=%d detach item=%p\n", stream->stream_id, stream->item);
 
   stream->item = NULL;
   stream->flags = (uint8_t)(stream->flags & ~NGHTTP2_STREAM_FLAG_DEFERRED_ALL);
 
-  return stream_update_dep_on_detach_item(stream);
+  if (stream->flags & NGHTTP2_STREAM_FLAG_NO_RFC7540_PRIORITIES) {
+    return;
+  }
+
+  stream_update_dep_on_detach_item(stream);
 }
 
-int nghttp2_stream_defer_item(nghttp2_stream *stream, uint8_t flags) {
+void nghttp2_stream_defer_item(nghttp2_stream *stream, uint8_t flags) {
   assert(stream->item);
 
   DEBUGF("stream: stream=%d defer item=%p cause=%02x\n", stream->stream_id,
@@ -514,7 +522,11 @@ int nghttp2_stream_defer_item(nghttp2_st
 
   stream->flags |= flags;
 
-  return stream_update_dep_on_detach_item(stream);
+  if (stream->flags & NGHTTP2_STREAM_FLAG_NO_RFC7540_PRIORITIES) {
+    return;
+  }
+
+  stream_update_dep_on_detach_item(stream);
 }
 
 int nghttp2_stream_resume_deferred_item(nghttp2_stream *stream, uint8_t flags) {
@@ -529,6 +541,10 @@ int nghttp2_stream_resume_deferred_item(
     return 0;
   }
 
+  if (stream->flags & NGHTTP2_STREAM_FLAG_NO_RFC7540_PRIORITIES) {
+    return 0;
+  }
+
   return stream_update_dep_on_attach_item(stream);
 }
 
Index: node-v16.20.2/deps/nghttp2/lib/nghttp2_stream.h
===================================================================
--- node-v16.20.2.orig/deps/nghttp2/lib/nghttp2_stream.h
+++ node-v16.20.2/deps/nghttp2/lib/nghttp2_stream.h
@@ -90,8 +90,15 @@ typedef enum {
   NGHTTP2_STREAM_FLAG_DEFERRED_USER = 0x08,
   /* bitwise OR of NGHTTP2_STREAM_FLAG_DEFERRED_FLOW_CONTROL and
      NGHTTP2_STREAM_FLAG_DEFERRED_USER. */
-  NGHTTP2_STREAM_FLAG_DEFERRED_ALL = 0x0c
-
+  NGHTTP2_STREAM_FLAG_DEFERRED_ALL = 0x0c,
+  /* Indicates that this stream is not subject to RFC7540
+     priorities scheme. */
+  NGHTTP2_STREAM_FLAG_NO_RFC7540_PRIORITIES = 0x10,
+  /* Ignore client RFC 9218 priority signal. */
+  NGHTTP2_STREAM_FLAG_IGNORE_CLIENT_PRIORITIES = 0x20,
+  /* Indicates that RFC 9113 leading and trailing white spaces
+     validation against a field value is not performed. */
+  NGHTTP2_STREAM_FLAG_NO_RFC9113_LEADING_AND_TRAILING_WS_VALIDATION = 0x40,
 } nghttp2_stream_flag;
 
 /* HTTP related flags to enforce HTTP semantics */
@@ -132,6 +139,11 @@ typedef enum {
   /* set if final response is expected */
   NGHTTP2_HTTP_FLAG_EXPECT_FINAL_RESPONSE = 1 << 14,
   NGHTTP2_HTTP_FLAG__PROTOCOL = 1 << 15,
+  /* set if priority header field is received */
+  NGHTTP2_HTTP_FLAG_PRIORITY = 1 << 16,
+  /* set if an error is encountered while parsing priority header
+     field */
+  NGHTTP2_HTTP_FLAG_BAD_PRIORITY = 1 << 17,
 } nghttp2_http_flag;
 
 struct nghttp2_stream {
@@ -204,7 +216,7 @@ struct nghttp2_stream {
   /* status code from remote server */
   int16_t status_code;
   /* Bitwise OR of zero or more nghttp2_http_flag values */
-  uint16_t http_flags;
+  uint32_t http_flags;
   /* This is bitwise-OR of 0 or more of nghttp2_stream_flag. */
   uint8_t flags;
   /* Bitwise OR of zero or more nghttp2_shut_flag values */
@@ -218,6 +230,12 @@ struct nghttp2_stream {
      this stream.  The nonzero does not necessarily mean WINDOW_UPDATE
      is not queued. */
   uint8_t window_update_queued;
+  /* extpri is a stream priority produced by nghttp2_extpri_to_uint8
+     used by RFC 9218 extensible priorities. */
+  uint8_t extpri;
+  /* http_extpri is a stream priority received in HTTP request header
+     fields and produced by nghttp2_extpri_to_uint8. */
+  uint8_t http_extpri;
 };
 
 void nghttp2_stream_init(nghttp2_stream *stream, int32_t stream_id,
@@ -240,14 +258,8 @@ void nghttp2_stream_shutdown(nghttp2_str
  * more of NGHTTP2_STREAM_FLAG_DEFERRED_USER and
  * NGHTTP2_STREAM_FLAG_DEFERRED_FLOW_CONTROL.  The |flags| indicates
  * the reason of this action.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGHTTP2_ERR_NOMEM
- *     Out of memory
  */
-int nghttp2_stream_defer_item(nghttp2_stream *stream, uint8_t flags);
+void nghttp2_stream_defer_item(nghttp2_stream *stream, uint8_t flags);
 
 /*
  * Put back deferred data in this stream to active state.  The |flags|
@@ -361,14 +373,8 @@ int nghttp2_stream_attach_item(nghttp2_s
 /*
  * Detaches |stream->item|.  This function does not free
  * |stream->item|.  The caller must free it.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGHTTP2_ERR_NOMEM
- *     Out of memory
  */
-int nghttp2_stream_detach_item(nghttp2_stream *stream);
+void nghttp2_stream_detach_item(nghttp2_stream *stream);
 
 /*
  * Makes the |stream| depend on the |dep_stream|.  This dependency is
Index: node-v16.20.2/deps/nghttp2/lib/nghttp2_submit.c
===================================================================
--- node-v16.20.2.orig/deps/nghttp2/lib/nghttp2_submit.c
+++ node-v16.20.2/deps/nghttp2/lib/nghttp2_submit.c
@@ -196,7 +196,8 @@ int32_t nghttp2_submit_headers(nghttp2_s
 
   flags &= NGHTTP2_FLAG_END_STREAM;
 
-  if (pri_spec && !nghttp2_priority_spec_check_default(pri_spec)) {
+  if (pri_spec && !nghttp2_priority_spec_check_default(pri_spec) &&
+      session->remote_settings.no_rfc7540_priorities != 1) {
     rv = detect_self_dependency(session, stream_id, pri_spec);
     if (rv != 0) {
       return rv;
@@ -229,6 +230,10 @@ int nghttp2_submit_priority(nghttp2_sess
 
   mem = &session->mem;
 
+  if (session->remote_settings.no_rfc7540_priorities == 1) {
+    return 0;
+  }
+
   if (stream_id == 0 || pri_spec == NULL) {
     return NGHTTP2_ERR_INVALID_ARGUMENT;
   }
@@ -662,6 +667,78 @@ fail_item_malloc:
   return rv;
 }
 
+int nghttp2_submit_priority_update(nghttp2_session *session, uint8_t flags,
+                                   int32_t stream_id,
+                                   const uint8_t *field_value,
+                                   size_t field_value_len) {
+  nghttp2_mem *mem;
+  uint8_t *buf, *p;
+  nghttp2_outbound_item *item;
+  nghttp2_frame *frame;
+  nghttp2_ext_priority_update *priority_update;
+  int rv;
+  (void)flags;
+
+  mem = &session->mem;
+
+  if (session->server) {
+    return NGHTTP2_ERR_INVALID_STATE;
+  }
+
+  if (session->remote_settings.no_rfc7540_priorities == 0) {
+    return 0;
+  }
+
+  if (stream_id == 0 || 4 + field_value_len > NGHTTP2_MAX_PAYLOADLEN) {
+    return NGHTTP2_ERR_INVALID_ARGUMENT;
+  }
+
+  if (field_value_len) {
+    buf = nghttp2_mem_malloc(mem, field_value_len + 1);
+    if (buf == NULL) {
+      return NGHTTP2_ERR_NOMEM;
+    }
+
+    p = nghttp2_cpymem(buf, field_value, field_value_len);
+    *p = '\0';
+  } else {
+    buf = NULL;
+  }
+
+  item = nghttp2_mem_malloc(mem, sizeof(nghttp2_outbound_item));
+  if (item == NULL) {
+    rv = NGHTTP2_ERR_NOMEM;
+    goto fail_item_malloc;
+  }
+
+  nghttp2_outbound_item_init(item);
+
+  item->aux_data.ext.builtin = 1;
+
+  priority_update = &item->ext_frame_payload.priority_update;
+
+  frame = &item->frame;
+  frame->ext.payload = priority_update;
+
+  nghttp2_frame_priority_update_init(&frame->ext, stream_id, buf,
+                                     field_value_len);
+
+  rv = nghttp2_session_add_item(session, item);
+  if (rv != 0) {
+    nghttp2_frame_priority_update_free(&frame->ext, mem);
+    nghttp2_mem_free(mem, item);
+
+    return rv;
+  }
+
+  return 0;
+
+fail_item_malloc:
+  free(buf);
+
+  return rv;
+}
+
 static uint8_t set_request_flags(const nghttp2_priority_spec *pri_spec,
                                  const nghttp2_data_provider *data_prd) {
   uint8_t flags = NGHTTP2_FLAG_NONE;
@@ -688,7 +765,8 @@ int32_t nghttp2_submit_request(nghttp2_s
     return NGHTTP2_ERR_PROTO;
   }
 
-  if (pri_spec && !nghttp2_priority_spec_check_default(pri_spec)) {
+  if (pri_spec && !nghttp2_priority_spec_check_default(pri_spec) &&
+      session->remote_settings.no_rfc7540_priorities != 1) {
     rv = detect_self_dependency(session, -1, pri_spec);
     if (rv != 0) {
       return rv;
Index: node-v16.20.2/deps/nghttp2/nghttp2.gyp
===================================================================
--- node-v16.20.2.orig/deps/nghttp2/nghttp2.gyp
+++ node-v16.20.2/deps/nghttp2/nghttp2.gyp
@@ -1,4 +1,34 @@
 {
+  'variables': {
+    'nghttp2_sources': [
+      'lib/nghttp2_buf.c',
+      'lib/nghttp2_callbacks.c',
+      'lib/nghttp2_debug.c',
+      'lib/nghttp2_extpri.c',
+      'lib/nghttp2_frame.c',
+      'lib/nghttp2_hd.c',
+      'lib/nghttp2_hd_huffman.c',
+      'lib/nghttp2_hd_huffman_data.c',
+      'lib/nghttp2_helper.c',
+      'lib/nghttp2_http.c',
+      'lib/nghttp2_map.c',
+      'lib/nghttp2_mem.c',
+      'lib/nghttp2_npn.c',
+      'lib/nghttp2_option.c',
+      'lib/nghttp2_outbound_item.c',
+      'lib/nghttp2_pq.c',
+      'lib/nghttp2_priority_spec.c',
+      'lib/nghttp2_queue.c',
+      'lib/nghttp2_ratelim.c',
+      'lib/nghttp2_rcbuf.c',
+      'lib/nghttp2_session.c',
+      'lib/nghttp2_stream.c',
+      'lib/nghttp2_submit.c',
+      'lib/nghttp2_time.c',
+      'lib/nghttp2_version.c',
+      'lib/sfparse.c',
+    ]
+  },
   'target_defaults': {
     'defines': [
       '_U_='
@@ -35,28 +65,7 @@
         'include_dirs': [ 'lib/includes' ]
       },
       'sources': [
-        'lib/nghttp2_buf.c',
-        'lib/nghttp2_callbacks.c',
-        'lib/nghttp2_debug.c',
-        'lib/nghttp2_frame.c',
-        'lib/nghttp2_hd.c',
-        'lib/nghttp2_hd_huffman.c',
-        'lib/nghttp2_hd_huffman_data.c',
-        'lib/nghttp2_helper.c',
-        'lib/nghttp2_http.c',
-        'lib/nghttp2_map.c',
-        'lib/nghttp2_mem.c',
-        'lib/nghttp2_npn.c',
-        'lib/nghttp2_option.c',
-        'lib/nghttp2_outbound_item.c',
-        'lib/nghttp2_pq.c',
-        'lib/nghttp2_priority_spec.c',
-        'lib/nghttp2_queue.c',
-        'lib/nghttp2_rcbuf.c',
-        'lib/nghttp2_session.c',
-        'lib/nghttp2_stream.c',
-        'lib/nghttp2_submit.c',
-        'lib/nghttp2_version.c'
+        '<@(nghttp2_sources)',
       ]
     }
   ]
Index: node-v16.20.2/deps/nghttp2/lib/Makefile.msvc
===================================================================
--- node-v16.20.2.orig/deps/nghttp2/lib/Makefile.msvc
+++ node-v16.20.2/deps/nghttp2/lib/Makefile.msvc
@@ -6,15 +6,8 @@
 # The MIT License apply.
 #
 
-#
-# Choose your weapons:
-#  Set 'USE_CYTHON=1' to build and install the 'nghttp2.pyd' Python extension.
-#
 THIS_MAKEFILE := $(lastword $(MAKEFILE_LIST))
 
-USE_CYTHON := 0
-#USE_CYTHON := 1
-
 _VERSION	:= $(shell grep AC_INIT ../configure.ac | cut -d'[' -f3 | sed -e 's/-DEV//g' -e 's/], //g')
 _VERSION   	:= $(subst ., ,$(_VERSION))
 VER_MAJOR  	:= $(word 1,$(_VERSION))
@@ -102,7 +95,7 @@ NGHTTP2_OBJ_D := $(addprefix $(OBJ_DIR)/
 	clean_nghttp2_pyd_0 clean_nghttp2_pyd_1
 
 
-all: intro includes/nghttp2/nghttp2ver.h $(OBJ_DIR) $(TARGETS) build_nghttp2_pyd_$(USE_CYTHON)
+all: intro includes/nghttp2/nghttp2ver.h $(OBJ_DIR) $(TARGETS)
 	@echo 'Welcome to NgHTTP2 (release + debug).'
 	@echo 'Do a "make -f Makefile.MSVC install" at own risk!'
 
@@ -121,7 +114,7 @@ $(OBJ_DIR):
 
 install: includes/nghttp2/nghttp2.h includes/nghttp2/nghttp2ver.h \
          $(TARGETS) \
-         copy_headers_and_libs install_nghttp2_pyd_$(USE_CYTHON) 
+         copy_headers_and_libs
 
 #
 # This MUST be done before using the 'install_nghttp2_pyd_1' rule.
@@ -160,31 +153,6 @@ $(DLL_D): $(NGHTTP2_OBJ_D) $(OBJ_DIR)/d_
 WIN_OBJDIR:=$(shell cygpath -w $(abspath $(OBJ_DIR)))
 WIN_OBJDIR:=$(subst \,/,$(WIN_OBJDIR))
 
-../python/setup.py: ../python/setup.py.in $(THIS_MAKEFILE)
-	cd ../python ; \
-	echo '# $(GENERATED). DO NOT EDIT.' > setup.py ; \
-	sed -e 's/@top_srcdir@/../'   \
-	    -e 's%@top_builddir@%$(WIN_OBJDIR)%' \
-	    -e 's/@PACKAGE_VERSION@/$(VERSION)/' setup.py.in >> setup.py ;
-
-build_nghttp2_pyd_0: ;
-
-build_nghttp2_pyd_1: $(addprefix ../python/, setup.py nghttp2.pyx)
-	cd ../python ; \
-	python setup.py build_ext -i -f bdist_wininst
-
-install_nghttp2_pyd_0: ;
-		
-install_nghttp2_pyd_1: $(addprefix ../python/, setup.py nghttp2.pyx)
-	cd ../python ; \
-	pip install .
-
-clean_nghttp2_pyd_0: ;
-
-clean_nghttp2_pyd_1:
-	cd ../python ; \
-	rm -fR build dist
-
 $(OBJ_DIR)/r_%.obj: %.c $(THIS_MAKEFILE)
 	$(CC) $(CFLAGS_R) $(CFLAGS) -Fo$@ -c $<
 	@echo
@@ -262,7 +230,7 @@ clean:
 	rm -f $(OBJ_DIR)/* includes/nghttp2/nghttp2ver.h
 	@echo
 
-vclean realclean: clean clean_nghttp2_pyd_$(USE_CYTHON)
+vclean realclean: clean
 	- rm -rf $(OBJ_DIR)
 	- rm -f .depend.MSVC
 
Index: node-v16.20.2/deps/nghttp2/lib/nghttp2_map.c
===================================================================
--- node-v16.20.2.orig/deps/nghttp2/lib/nghttp2_map.c
+++ node-v16.20.2/deps/nghttp2/lib/nghttp2_map.c
@@ -31,21 +31,14 @@
 
 #include "nghttp2_helper.h"
 
-#define NGHTTP2_INITIAL_TABLE_LENBITS 8
+#define NGHTTP2_INITIAL_TABLE_LENBITS 4
 
-int nghttp2_map_init(nghttp2_map *map, nghttp2_mem *mem) {
+void nghttp2_map_init(nghttp2_map *map, nghttp2_mem *mem) {
   map->mem = mem;
-  map->tablelen = 1 << NGHTTP2_INITIAL_TABLE_LENBITS;
-  map->tablelenbits = NGHTTP2_INITIAL_TABLE_LENBITS;
-  map->table =
-      nghttp2_mem_calloc(mem, map->tablelen, sizeof(nghttp2_map_bucket));
-  if (map->table == NULL) {
-    return NGHTTP2_ERR_NOMEM;
-  }
-
+  map->tablelen = 0;
+  map->tablelenbits = 0;
+  map->table = NULL;
   map->size = 0;
-
-  return 0;
 }
 
 void nghttp2_map_free(nghttp2_map *map) {
@@ -78,6 +71,10 @@ int nghttp2_map_each(nghttp2_map *map, i
   uint32_t i;
   nghttp2_map_bucket *bkt;
 
+  if (map->size == 0) {
+    return 0;
+  }
+
   for (i = 0; i < map->tablelen; ++i) {
     bkt = &map->table[i];
 
@@ -223,9 +220,17 @@ int nghttp2_map_insert(nghttp2_map *map,
 
   /* Load factor is 0.75 */
   if ((map->size + 1) * 4 > map->tablelen * 3) {
-    rv = map_resize(map, map->tablelen * 2, map->tablelenbits + 1);
-    if (rv != 0) {
-      return rv;
+    if (map->tablelen) {
+      rv = map_resize(map, map->tablelen * 2, map->tablelenbits + 1);
+      if (rv != 0) {
+        return rv;
+      }
+    } else {
+      rv = map_resize(map, 1 << NGHTTP2_INITIAL_TABLE_LENBITS,
+                      NGHTTP2_INITIAL_TABLE_LENBITS);
+      if (rv != 0) {
+        return rv;
+      }
     }
   }
 
@@ -239,11 +244,18 @@ int nghttp2_map_insert(nghttp2_map *map,
 }
 
 void *nghttp2_map_find(nghttp2_map *map, nghttp2_map_key_type key) {
-  uint32_t h = hash(key);
-  size_t idx = h2idx(h, map->tablelenbits);
+  uint32_t h;
+  size_t idx;
   nghttp2_map_bucket *bkt;
   size_t d = 0;
 
+  if (map->size == 0) {
+    return NULL;
+  }
+
+  h = hash(key);
+  idx = h2idx(h, map->tablelenbits);
+
   for (;;) {
     bkt = &map->table[idx];
 
@@ -262,11 +274,18 @@ void *nghttp2_map_find(nghttp2_map *map,
 }
 
 int nghttp2_map_remove(nghttp2_map *map, nghttp2_map_key_type key) {
-  uint32_t h = hash(key);
-  size_t idx = h2idx(h, map->tablelenbits), didx;
+  uint32_t h;
+  size_t idx, didx;
   nghttp2_map_bucket *bkt;
   size_t d = 0;
 
+  if (map->size == 0) {
+    return NGHTTP2_ERR_INVALID_ARGUMENT;
+  }
+
+  h = hash(key);
+  idx = h2idx(h, map->tablelenbits);
+
   for (;;) {
     bkt = &map->table[idx];
 
@@ -306,6 +325,10 @@ int nghttp2_map_remove(nghttp2_map *map,
 }
 
 void nghttp2_map_clear(nghttp2_map *map) {
+  if (map->tablelen == 0) {
+    return;
+  }
+
   memset(map->table, 0, sizeof(*map->table) * map->tablelen);
   map->size = 0;
 }
Index: node-v16.20.2/deps/nghttp2/lib/nghttp2_map.h
===================================================================
--- node-v16.20.2.orig/deps/nghttp2/lib/nghttp2_map.h
+++ node-v16.20.2/deps/nghttp2/lib/nghttp2_map.h
@@ -54,14 +54,8 @@ typedef struct nghttp2_map {
 
 /*
  * Initializes the map |map|.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGHTTP2_ERR_NOMEM
- *   Out of memory
  */
-int nghttp2_map_init(nghttp2_map *map, nghttp2_mem *mem);
+void nghttp2_map_init(nghttp2_map *map, nghttp2_mem *mem);
 
 /*
  * Deallocates any resources allocated for |map|. The stored entries
Index: node-v16.20.2/deps/nghttp2/lib/sfparse.c
===================================================================
--- /dev/null
+++ node-v16.20.2/deps/nghttp2/lib/sfparse.c
@@ -0,0 +1,1146 @@
+/*
+ * sfparse
+ *
+ * Copyright (c) 2023 sfparse contributors
+ * Copyright (c) 2019 nghttp3 contributors
+ * Copyright (c) 2015 nghttp2 contributors
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include "sfparse.h"
+
+#include <string.h>
+#include <assert.h>
+#include <stdlib.h>
+
+#define SF_STATE_DICT 0x08u
+#define SF_STATE_LIST 0x10u
+#define SF_STATE_ITEM 0x18u
+
+#define SF_STATE_INNER_LIST 0x04u
+
+#define SF_STATE_BEFORE 0x00u
+#define SF_STATE_BEFORE_PARAMS 0x01u
+#define SF_STATE_PARAMS 0x02u
+#define SF_STATE_AFTER 0x03u
+
+#define SF_STATE_OP_MASK 0x03u
+
+#define SF_SET_STATE_AFTER(NAME) (SF_STATE_##NAME | SF_STATE_AFTER)
+#define SF_SET_STATE_BEFORE_PARAMS(NAME)                                       \
+  (SF_STATE_##NAME | SF_STATE_BEFORE_PARAMS)
+#define SF_SET_STATE_INNER_LIST_BEFORE(NAME)                                   \
+  (SF_STATE_##NAME | SF_STATE_INNER_LIST | SF_STATE_BEFORE)
+
+#define SF_STATE_DICT_AFTER SF_SET_STATE_AFTER(DICT)
+#define SF_STATE_DICT_BEFORE_PARAMS SF_SET_STATE_BEFORE_PARAMS(DICT)
+#define SF_STATE_DICT_INNER_LIST_BEFORE SF_SET_STATE_INNER_LIST_BEFORE(DICT)
+
+#define SF_STATE_LIST_AFTER SF_SET_STATE_AFTER(LIST)
+#define SF_STATE_LIST_BEFORE_PARAMS SF_SET_STATE_BEFORE_PARAMS(LIST)
+#define SF_STATE_LIST_INNER_LIST_BEFORE SF_SET_STATE_INNER_LIST_BEFORE(LIST)
+
+#define SF_STATE_ITEM_AFTER SF_SET_STATE_AFTER(ITEM)
+#define SF_STATE_ITEM_BEFORE_PARAMS SF_SET_STATE_BEFORE_PARAMS(ITEM)
+#define SF_STATE_ITEM_INNER_LIST_BEFORE SF_SET_STATE_INNER_LIST_BEFORE(ITEM)
+
+#define SF_STATE_INITIAL 0x00u
+
+#define DIGIT_CASES                                                            \
+  case '0':                                                                    \
+  case '1':                                                                    \
+  case '2':                                                                    \
+  case '3':                                                                    \
+  case '4':                                                                    \
+  case '5':                                                                    \
+  case '6':                                                                    \
+  case '7':                                                                    \
+  case '8':                                                                    \
+  case '9'
+
+#define LCALPHA_CASES                                                          \
+  case 'a':                                                                    \
+  case 'b':                                                                    \
+  case 'c':                                                                    \
+  case 'd':                                                                    \
+  case 'e':                                                                    \
+  case 'f':                                                                    \
+  case 'g':                                                                    \
+  case 'h':                                                                    \
+  case 'i':                                                                    \
+  case 'j':                                                                    \
+  case 'k':                                                                    \
+  case 'l':                                                                    \
+  case 'm':                                                                    \
+  case 'n':                                                                    \
+  case 'o':                                                                    \
+  case 'p':                                                                    \
+  case 'q':                                                                    \
+  case 'r':                                                                    \
+  case 's':                                                                    \
+  case 't':                                                                    \
+  case 'u':                                                                    \
+  case 'v':                                                                    \
+  case 'w':                                                                    \
+  case 'x':                                                                    \
+  case 'y':                                                                    \
+  case 'z'
+
+#define UCALPHA_CASES                                                          \
+  case 'A':                                                                    \
+  case 'B':                                                                    \
+  case 'C':                                                                    \
+  case 'D':                                                                    \
+  case 'E':                                                                    \
+  case 'F':                                                                    \
+  case 'G':                                                                    \
+  case 'H':                                                                    \
+  case 'I':                                                                    \
+  case 'J':                                                                    \
+  case 'K':                                                                    \
+  case 'L':                                                                    \
+  case 'M':                                                                    \
+  case 'N':                                                                    \
+  case 'O':                                                                    \
+  case 'P':                                                                    \
+  case 'Q':                                                                    \
+  case 'R':                                                                    \
+  case 'S':                                                                    \
+  case 'T':                                                                    \
+  case 'U':                                                                    \
+  case 'V':                                                                    \
+  case 'W':                                                                    \
+  case 'X':                                                                    \
+  case 'Y':                                                                    \
+  case 'Z'
+
+#define ALPHA_CASES                                                            \
+  UCALPHA_CASES:                                                               \
+  LCALPHA_CASES
+
+#define X20_21_CASES                                                           \
+  case ' ':                                                                    \
+  case '!'
+
+#define X23_5B_CASES                                                           \
+  case '#':                                                                    \
+  case '$':                                                                    \
+  case '%':                                                                    \
+  case '&':                                                                    \
+  case '\'':                                                                   \
+  case '(':                                                                    \
+  case ')':                                                                    \
+  case '*':                                                                    \
+  case '+':                                                                    \
+  case ',':                                                                    \
+  case '-':                                                                    \
+  case '.':                                                                    \
+  case '/':                                                                    \
+  DIGIT_CASES:                                                                 \
+  case ':':                                                                    \
+  case ';':                                                                    \
+  case '<':                                                                    \
+  case '=':                                                                    \
+  case '>':                                                                    \
+  case '?':                                                                    \
+  case '@':                                                                    \
+  UCALPHA_CASES:                                                               \
+  case '['
+
+#define X5D_7E_CASES                                                           \
+  case ']':                                                                    \
+  case '^':                                                                    \
+  case '_':                                                                    \
+  case '`':                                                                    \
+  LCALPHA_CASES:                                                               \
+  case '{':                                                                    \
+  case '|':                                                                    \
+  case '}':                                                                    \
+  case '~'
+
+static int is_ws(uint8_t c) {
+  switch (c) {
+  case ' ':
+  case '\t':
+    return 1;
+  default:
+    return 0;
+  }
+}
+
+static int parser_eof(sf_parser *sfp) { return sfp->pos == sfp->end; }
+
+static void parser_discard_ows(sf_parser *sfp) {
+  for (; !parser_eof(sfp) && is_ws(*sfp->pos); ++sfp->pos)
+    ;
+}
+
+static void parser_discard_sp(sf_parser *sfp) {
+  for (; !parser_eof(sfp) && *sfp->pos == ' '; ++sfp->pos)
+    ;
+}
+
+static void parser_set_op_state(sf_parser *sfp, uint32_t op) {
+  sfp->state &= ~SF_STATE_OP_MASK;
+  sfp->state |= op;
+}
+
+static void parser_unset_inner_list_state(sf_parser *sfp) {
+  sfp->state &= ~SF_STATE_INNER_LIST;
+}
+
+static int parser_key(sf_parser *sfp, sf_vec *dest) {
+  const uint8_t *base;
+
+  switch (*sfp->pos) {
+  case '*':
+  LCALPHA_CASES:
+    break;
+  default:
+    return SF_ERR_PARSE_ERROR;
+  }
+
+  base = sfp->pos++;
+
+  for (; !parser_eof(sfp); ++sfp->pos) {
+    switch (*sfp->pos) {
+    case '_':
+    case '-':
+    case '.':
+    case '*':
+    DIGIT_CASES:
+    LCALPHA_CASES:
+      continue;
+    }
+
+    break;
+  }
+
+  if (dest) {
+    dest->base = (uint8_t *)base;
+    dest->len = (size_t)(sfp->pos - dest->base);
+  }
+
+  return 0;
+}
+
+static int parser_number(sf_parser *sfp, sf_value *dest) {
+  int sign = 1;
+  int64_t value = 0;
+  size_t len = 0;
+  size_t fpos = 0;
+
+  if (*sfp->pos == '-') {
+    ++sfp->pos;
+    if (parser_eof(sfp)) {
+      return SF_ERR_PARSE_ERROR;
+    }
+
+    sign = -1;
+  }
+
+  assert(!parser_eof(sfp));
+
+  for (; !parser_eof(sfp); ++sfp->pos) {
+    switch (*sfp->pos) {
+    DIGIT_CASES:
+      if (++len > 15) {
+        return SF_ERR_PARSE_ERROR;
+      }
+
+      value *= 10;
+      value += *sfp->pos - '0';
+
+      continue;
+    }
+
+    break;
+  }
+
+  if (len == 0) {
+    return SF_ERR_PARSE_ERROR;
+  }
+
+  if (parser_eof(sfp) || *sfp->pos != '.') {
+    if (dest) {
+      dest->type = SF_TYPE_INTEGER;
+      dest->flags = SF_VALUE_FLAG_NONE;
+      dest->integer = value * sign;
+    }
+
+    return 0;
+  }
+
+  /* decimal */
+
+  if (len > 12) {
+    return SF_ERR_PARSE_ERROR;
+  }
+
+  fpos = len;
+
+  ++sfp->pos;
+
+  for (; !parser_eof(sfp); ++sfp->pos) {
+    switch (*sfp->pos) {
+    DIGIT_CASES:
+      if (++len > 15) {
+        return SF_ERR_PARSE_ERROR;
+      }
+
+      value *= 10;
+      value += *sfp->pos - '0';
+
+      continue;
+    }
+
+    break;
+  }
+
+  if (fpos == len || len - fpos > 3) {
+    return SF_ERR_PARSE_ERROR;
+  }
+
+  if (dest) {
+    dest->type = SF_TYPE_DECIMAL;
+    dest->flags = SF_VALUE_FLAG_NONE;
+    dest->decimal.numer = value * sign;
+
+    switch (len - fpos) {
+    case 1:
+      dest->decimal.denom = 10;
+
+      break;
+    case 2:
+      dest->decimal.denom = 100;
+
+      break;
+    case 3:
+      dest->decimal.denom = 1000;
+
+      break;
+    }
+  }
+
+  return 0;
+}
+
+static int parser_date(sf_parser *sfp, sf_value *dest) {
+  int rv;
+  sf_value val;
+
+  /* The first byte has already been validated by the caller. */
+  assert('@' == *sfp->pos);
+
+  ++sfp->pos;
+
+  if (parser_eof(sfp)) {
+    return SF_ERR_PARSE_ERROR;
+  }
+
+  rv = parser_number(sfp, &val);
+  if (rv != 0) {
+    return rv;
+  }
+
+  if (val.type != SF_TYPE_INTEGER) {
+    return SF_ERR_PARSE_ERROR;
+  }
+
+  if (dest) {
+    *dest = val;
+    dest->type = SF_TYPE_DATE;
+  }
+
+  return 0;
+}
+
+static int parser_string(sf_parser *sfp, sf_value *dest) {
+  const uint8_t *base;
+  uint32_t flags = SF_VALUE_FLAG_NONE;
+
+  /* The first byte has already been validated by the caller. */
+  assert('"' == *sfp->pos);
+
+  base = ++sfp->pos;
+
+  for (; !parser_eof(sfp); ++sfp->pos) {
+    switch (*sfp->pos) {
+    X20_21_CASES:
+    X23_5B_CASES:
+    X5D_7E_CASES:
+      break;
+    case '\\':
+      ++sfp->pos;
+      if (parser_eof(sfp)) {
+        return SF_ERR_PARSE_ERROR;
+      }
+
+      switch (*sfp->pos) {
+      case '"':
+      case '\\':
+        flags = SF_VALUE_FLAG_ESCAPED_STRING;
+
+        break;
+      default:
+        return SF_ERR_PARSE_ERROR;
+      }
+
+      break;
+    case '"':
+      if (dest) {
+        dest->type = SF_TYPE_STRING;
+        dest->flags = flags;
+        dest->vec.len = (size_t)(sfp->pos - base);
+        dest->vec.base = dest->vec.len == 0 ? NULL : (uint8_t *)base;
+      }
+
+      ++sfp->pos;
+
+      return 0;
+    default:
+      return SF_ERR_PARSE_ERROR;
+    }
+  }
+
+  return SF_ERR_PARSE_ERROR;
+}
+
+static int parser_token(sf_parser *sfp, sf_value *dest) {
+  const uint8_t *base;
+
+  /* The first byte has already been validated by the caller. */
+  base = sfp->pos++;
+
+  for (; !parser_eof(sfp); ++sfp->pos) {
+    switch (*sfp->pos) {
+    case '!':
+    case '#':
+    case '$':
+    case '%':
+    case '&':
+    case '\'':
+    case '*':
+    case '+':
+    case '-':
+    case '.':
+    case '^':
+    case '_':
+    case '`':
+    case '|':
+    case '~':
+    case ':':
+    case '/':
+    DIGIT_CASES:
+    ALPHA_CASES:
+      continue;
+    }
+
+    break;
+  }
+
+  if (dest) {
+    dest->type = SF_TYPE_TOKEN;
+    dest->flags = SF_VALUE_FLAG_NONE;
+    dest->vec.base = (uint8_t *)base;
+    dest->vec.len = (size_t)(sfp->pos - base);
+  }
+
+  return 0;
+}
+
+static int parser_byteseq(sf_parser *sfp, sf_value *dest) {
+  const uint8_t *base;
+
+  /* The first byte has already been validated by the caller. */
+  assert(':' == *sfp->pos);
+
+  base = ++sfp->pos;
+
+  for (; !parser_eof(sfp); ++sfp->pos) {
+    switch (*sfp->pos) {
+    case '+':
+    case '/':
+    DIGIT_CASES:
+    ALPHA_CASES:
+      continue;
+    case '=':
+      switch ((sfp->pos - base) & 0x3) {
+      case 0:
+      case 1:
+        return SF_ERR_PARSE_ERROR;
+      case 2:
+        switch (*(sfp->pos - 1)) {
+        case 'A':
+        case 'Q':
+        case 'g':
+        case 'w':
+          break;
+        default:
+          return SF_ERR_PARSE_ERROR;
+        }
+
+        ++sfp->pos;
+
+        if (parser_eof(sfp) || *sfp->pos != '=') {
+          return SF_ERR_PARSE_ERROR;
+        }
+
+        break;
+      case 3:
+        switch (*(sfp->pos - 1)) {
+        case 'A':
+        case 'E':
+        case 'I':
+        case 'M':
+        case 'Q':
+        case 'U':
+        case 'Y':
+        case 'c':
+        case 'g':
+        case 'k':
+        case 'o':
+        case 's':
+        case 'w':
+        case '0':
+        case '4':
+        case '8':
+          break;
+        default:
+          return SF_ERR_PARSE_ERROR;
+        }
+
+        break;
+      }
+
+      ++sfp->pos;
+
+      if (parser_eof(sfp) || *sfp->pos != ':') {
+        return SF_ERR_PARSE_ERROR;
+      }
+
+      goto fin;
+    case ':':
+      if ((sfp->pos - base) & 0x3) {
+        return SF_ERR_PARSE_ERROR;
+      }
+
+      goto fin;
+    default:
+      return SF_ERR_PARSE_ERROR;
+    }
+  }
+
+  return SF_ERR_PARSE_ERROR;
+
+fin:
+  if (dest) {
+    dest->type = SF_TYPE_BYTESEQ;
+    dest->flags = SF_VALUE_FLAG_NONE;
+    dest->vec.len = (size_t)(sfp->pos - base);
+    dest->vec.base = dest->vec.len == 0 ? NULL : (uint8_t *)base;
+  }
+
+  ++sfp->pos;
+
+  return 0;
+}
+
+static int parser_boolean(sf_parser *sfp, sf_value *dest) {
+  int b;
+
+  /* The first byte has already been validated by the caller. */
+  assert('?' == *sfp->pos);
+
+  ++sfp->pos;
+
+  if (parser_eof(sfp)) {
+    return SF_ERR_PARSE_ERROR;
+  }
+
+  switch (*sfp->pos) {
+  case '0':
+    b = 0;
+
+    break;
+  case '1':
+    b = 1;
+
+    break;
+  default:
+    return SF_ERR_PARSE_ERROR;
+  }
+
+  ++sfp->pos;
+
+  if (dest) {
+    dest->type = SF_TYPE_BOOLEAN;
+    dest->flags = SF_VALUE_FLAG_NONE;
+    dest->boolean = b;
+  }
+
+  return 0;
+}
+
+static int parser_bare_item(sf_parser *sfp, sf_value *dest) {
+  switch (*sfp->pos) {
+  case '"':
+    return parser_string(sfp, dest);
+  case '-':
+  DIGIT_CASES:
+    return parser_number(sfp, dest);
+  case '@':
+    return parser_date(sfp, dest);
+  case ':':
+    return parser_byteseq(sfp, dest);
+  case '?':
+    return parser_boolean(sfp, dest);
+  case '*':
+  ALPHA_CASES:
+    return parser_token(sfp, dest);
+  default:
+    return SF_ERR_PARSE_ERROR;
+  }
+}
+
+static int parser_skip_inner_list(sf_parser *sfp);
+
+int sf_parser_param(sf_parser *sfp, sf_vec *dest_key, sf_value *dest_value) {
+  int rv;
+
+  switch (sfp->state & SF_STATE_OP_MASK) {
+  case SF_STATE_BEFORE:
+    rv = parser_skip_inner_list(sfp);
+    if (rv != 0) {
+      return rv;
+    }
+
+    /* fall through */
+  case SF_STATE_BEFORE_PARAMS:
+    parser_set_op_state(sfp, SF_STATE_PARAMS);
+
+    break;
+  case SF_STATE_PARAMS:
+    break;
+  default:
+    assert(0);
+    abort();
+  }
+
+  if (parser_eof(sfp) || *sfp->pos != ';') {
+    parser_set_op_state(sfp, SF_STATE_AFTER);
+
+    return SF_ERR_EOF;
+  }
+
+  ++sfp->pos;
+
+  parser_discard_sp(sfp);
+  if (parser_eof(sfp)) {
+    return SF_ERR_PARSE_ERROR;
+  }
+
+  rv = parser_key(sfp, dest_key);
+  if (rv != 0) {
+    return rv;
+  }
+
+  if (parser_eof(sfp) || *sfp->pos != '=') {
+    if (dest_value) {
+      dest_value->type = SF_TYPE_BOOLEAN;
+      dest_value->flags = SF_VALUE_FLAG_NONE;
+      dest_value->boolean = 1;
+    }
+
+    return 0;
+  }
+
+  ++sfp->pos;
+
+  if (parser_eof(sfp)) {
+    return SF_ERR_PARSE_ERROR;
+  }
+
+  return parser_bare_item(sfp, dest_value);
+}
+
+static int parser_skip_params(sf_parser *sfp) {
+  int rv;
+
+  for (;;) {
+    rv = sf_parser_param(sfp, NULL, NULL);
+    switch (rv) {
+    case 0:
+      break;
+    case SF_ERR_EOF:
+      return 0;
+    case SF_ERR_PARSE_ERROR:
+      return rv;
+    default:
+      assert(0);
+      abort();
+    }
+  }
+}
+
+int sf_parser_inner_list(sf_parser *sfp, sf_value *dest) {
+  int rv;
+
+  switch (sfp->state & SF_STATE_OP_MASK) {
+  case SF_STATE_BEFORE:
+    parser_discard_sp(sfp);
+    if (parser_eof(sfp)) {
+      return SF_ERR_PARSE_ERROR;
+    }
+
+    break;
+  case SF_STATE_BEFORE_PARAMS:
+    rv = parser_skip_params(sfp);
+    if (rv != 0) {
+      return rv;
+    }
+
+    /* Technically, we are entering SF_STATE_AFTER, but we will set
+       another state without reading the state. */
+    /* parser_set_op_state(sfp, SF_STATE_AFTER); */
+
+    /* fall through */
+  case SF_STATE_AFTER:
+    if (parser_eof(sfp)) {
+      return SF_ERR_PARSE_ERROR;
+    }
+
+    switch (*sfp->pos) {
+    case ' ':
+      parser_discard_sp(sfp);
+      if (parser_eof(sfp)) {
+        return SF_ERR_PARSE_ERROR;
+      }
+
+      break;
+    case ')':
+      break;
+    default:
+      return SF_ERR_PARSE_ERROR;
+    }
+
+    break;
+  default:
+    assert(0);
+    abort();
+  }
+
+  if (*sfp->pos == ')') {
+    ++sfp->pos;
+
+    parser_unset_inner_list_state(sfp);
+    parser_set_op_state(sfp, SF_STATE_BEFORE_PARAMS);
+
+    return SF_ERR_EOF;
+  }
+
+  rv = parser_bare_item(sfp, dest);
+  if (rv != 0) {
+    return rv;
+  }
+
+  parser_set_op_state(sfp, SF_STATE_BEFORE_PARAMS);
+
+  return 0;
+}
+
+static int parser_skip_inner_list(sf_parser *sfp) {
+  int rv;
+
+  for (;;) {
+    rv = sf_parser_inner_list(sfp, NULL);
+    switch (rv) {
+    case 0:
+      break;
+    case SF_ERR_EOF:
+      return 0;
+    case SF_ERR_PARSE_ERROR:
+      return rv;
+    default:
+      assert(0);
+      abort();
+    }
+  }
+}
+
+static int parser_next_key_or_item(sf_parser *sfp) {
+  parser_discard_ows(sfp);
+
+  if (parser_eof(sfp)) {
+    return SF_ERR_EOF;
+  }
+
+  if (*sfp->pos != ',') {
+    return SF_ERR_PARSE_ERROR;
+  }
+
+  ++sfp->pos;
+
+  parser_discard_ows(sfp);
+  if (parser_eof(sfp)) {
+    return SF_ERR_PARSE_ERROR;
+  }
+
+  return 0;
+}
+
+static int parser_dict_value(sf_parser *sfp, sf_value *dest) {
+  int rv;
+
+  if (parser_eof(sfp) || *(sfp->pos) != '=') {
+    /* Boolean true */
+    if (dest) {
+      dest->type = SF_TYPE_BOOLEAN;
+      dest->flags = SF_VALUE_FLAG_NONE;
+      dest->boolean = 1;
+    }
+
+    sfp->state = SF_STATE_DICT_BEFORE_PARAMS;
+
+    return 0;
+  }
+
+  ++sfp->pos;
+
+  if (parser_eof(sfp)) {
+    return SF_ERR_PARSE_ERROR;
+  }
+
+  if (*sfp->pos == '(') {
+    if (dest) {
+      dest->type = SF_TYPE_INNER_LIST;
+      dest->flags = SF_VALUE_FLAG_NONE;
+    }
+
+    ++sfp->pos;
+
+    sfp->state = SF_STATE_DICT_INNER_LIST_BEFORE;
+
+    return 0;
+  }
+
+  rv = parser_bare_item(sfp, dest);
+  if (rv != 0) {
+    return rv;
+  }
+
+  sfp->state = SF_STATE_DICT_BEFORE_PARAMS;
+
+  return 0;
+}
+
+int sf_parser_dict(sf_parser *sfp, sf_vec *dest_key, sf_value *dest_value) {
+  int rv;
+
+  switch (sfp->state) {
+  case SF_STATE_DICT_INNER_LIST_BEFORE:
+    rv = parser_skip_inner_list(sfp);
+    if (rv != 0) {
+      return rv;
+    }
+
+    /* fall through */
+  case SF_STATE_DICT_BEFORE_PARAMS:
+    rv = parser_skip_params(sfp);
+    if (rv != 0) {
+      return rv;
+    }
+
+    /* fall through */
+  case SF_STATE_DICT_AFTER:
+    rv = parser_next_key_or_item(sfp);
+    if (rv != 0) {
+      return rv;
+    }
+
+    break;
+  case SF_STATE_INITIAL:
+    parser_discard_sp(sfp);
+
+    if (parser_eof(sfp)) {
+      return SF_ERR_EOF;
+    }
+
+    break;
+  default:
+    assert(0);
+    abort();
+  }
+
+  rv = parser_key(sfp, dest_key);
+  if (rv != 0) {
+    return rv;
+  }
+
+  return parser_dict_value(sfp, dest_value);
+}
+
+int sf_parser_list(sf_parser *sfp, sf_value *dest) {
+  int rv;
+
+  switch (sfp->state) {
+  case SF_STATE_LIST_INNER_LIST_BEFORE:
+    rv = parser_skip_inner_list(sfp);
+    if (rv != 0) {
+      return rv;
+    }
+
+    /* fall through */
+  case SF_STATE_LIST_BEFORE_PARAMS:
+    rv = parser_skip_params(sfp);
+    if (rv != 0) {
+      return rv;
+    }
+
+    /* fall through */
+  case SF_STATE_LIST_AFTER:
+    rv = parser_next_key_or_item(sfp);
+    if (rv != 0) {
+      return rv;
+    }
+
+    break;
+  case SF_STATE_INITIAL:
+    parser_discard_sp(sfp);
+
+    if (parser_eof(sfp)) {
+      return SF_ERR_EOF;
+    }
+
+    break;
+  default:
+    assert(0);
+    abort();
+  }
+
+  if (*sfp->pos == '(') {
+    if (dest) {
+      dest->type = SF_TYPE_INNER_LIST;
+      dest->flags = SF_VALUE_FLAG_NONE;
+    }
+
+    ++sfp->pos;
+
+    sfp->state = SF_STATE_LIST_INNER_LIST_BEFORE;
+
+    return 0;
+  }
+
+  rv = parser_bare_item(sfp, dest);
+  if (rv != 0) {
+    return rv;
+  }
+
+  sfp->state = SF_STATE_LIST_BEFORE_PARAMS;
+
+  return 0;
+}
+
+int sf_parser_item(sf_parser *sfp, sf_value *dest) {
+  int rv;
+
+  switch (sfp->state) {
+  case SF_STATE_INITIAL:
+    parser_discard_sp(sfp);
+
+    if (parser_eof(sfp)) {
+      return SF_ERR_PARSE_ERROR;
+    }
+
+    break;
+  case SF_STATE_ITEM_INNER_LIST_BEFORE:
+    rv = parser_skip_inner_list(sfp);
+    if (rv != 0) {
+      return rv;
+    }
+
+    /* fall through */
+  case SF_STATE_ITEM_BEFORE_PARAMS:
+    rv = parser_skip_params(sfp);
+    if (rv != 0) {
+      return rv;
+    }
+
+    /* fall through */
+  case SF_STATE_ITEM_AFTER:
+    parser_discard_sp(sfp);
+
+    if (!parser_eof(sfp)) {
+      return SF_ERR_PARSE_ERROR;
+    }
+
+    return SF_ERR_EOF;
+  default:
+    assert(0);
+    abort();
+  }
+
+  if (*sfp->pos == '(') {
+    if (dest) {
+      dest->type = SF_TYPE_INNER_LIST;
+      dest->flags = SF_VALUE_FLAG_NONE;
+    }
+
+    ++sfp->pos;
+
+    sfp->state = SF_STATE_ITEM_INNER_LIST_BEFORE;
+
+    return 0;
+  }
+
+  rv = parser_bare_item(sfp, dest);
+  if (rv != 0) {
+    return rv;
+  }
+
+  sfp->state = SF_STATE_ITEM_BEFORE_PARAMS;
+
+  return 0;
+}
+
+void sf_parser_init(sf_parser *sfp, const uint8_t *data, size_t datalen) {
+  if (datalen == 0) {
+    sfp->pos = sfp->end = NULL;
+  } else {
+    sfp->pos = data;
+    sfp->end = data + datalen;
+  }
+
+  sfp->state = SF_STATE_INITIAL;
+}
+
+void sf_unescape(sf_vec *dest, const sf_vec *src) {
+  const uint8_t *p, *q;
+  uint8_t *o;
+  size_t len, slen;
+
+  if (src->len == 0) {
+    *dest = *src;
+
+    return;
+  }
+
+  o = dest->base;
+  p = src->base;
+  len = src->len;
+
+  for (;;) {
+    q = memchr(p, '\\', len);
+    if (q == NULL) {
+      if (len == src->len) {
+        *dest = *src;
+
+        return;
+      }
+
+      memcpy(o, p, len);
+      o += len;
+
+      break;
+    }
+
+    slen = (size_t)(q - p);
+    memcpy(o, p, slen);
+    o += slen;
+
+    p = q + 1;
+    *o++ = *p++;
+    len -= slen + 2;
+  }
+
+  dest->len = (size_t)(o - dest->base);
+}
+
+void sf_base64decode(sf_vec *dest, const sf_vec *src) {
+  static const int index_tbl[] = {
+      -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+      -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+      -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57,
+      58, 59, 60, 61, -1, -1, -1, -1, -1, -1, -1, 0,  1,  2,  3,  4,  5,  6,
+      7,  8,  9,  10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
+      25, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,
+      37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1,
+      -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+      -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+      -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+      -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+      -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+      -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+      -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+      -1, -1, -1, -1};
+  uint8_t *o;
+  const uint8_t *p, *end;
+  uint32_t n;
+  size_t i;
+  int idx;
+
+  assert((src->len & 0x3) == 0);
+
+  if (src->len == 0) {
+    *dest = *src;
+
+    return;
+  }
+
+  o = dest->base;
+  p = src->base;
+  end = src->base + src->len;
+
+  for (; p != end;) {
+    n = 0;
+
+    for (i = 1; i <= 4; ++i, ++p) {
+      idx = index_tbl[*p];
+
+      if (idx == -1) {
+        assert(i > 2);
+
+        if (i == 3) {
+          assert(*p == '=' && *(p + 1) == '=' && p + 2 == end);
+
+          *o++ = (uint8_t)(n >> 16);
+
+          goto fin;
+        }
+
+        assert(*p == '=' && p + 1 == end);
+
+        *o++ = (uint8_t)(n >> 16);
+        *o++ = (n >> 8) & 0xffu;
+
+        goto fin;
+      }
+
+      n += (uint32_t)(idx << (24 - i * 6));
+    }
+
+    *o++ = (uint8_t)(n >> 16);
+    *o++ = (n >> 8) & 0xffu;
+    *o++ = n & 0xffu;
+  }
+
+fin:
+  dest->len = (size_t)(o - dest->base);
+}
Index: node-v16.20.2/deps/nghttp2/lib/sfparse.h
===================================================================
--- /dev/null
+++ node-v16.20.2/deps/nghttp2/lib/sfparse.h
@@ -0,0 +1,409 @@
+/*
+ * sfparse
+ *
+ * Copyright (c) 2023 sfparse contributors
+ * Copyright (c) 2019 nghttp3 contributors
+ * Copyright (c) 2015 nghttp2 contributors
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#ifndef SFPARSE_H
+#define SFPARSE_H
+
+/* Define WIN32 when build target is Win32 API (borrowed from
+   libcurl) */
+#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32)
+#  define WIN32
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined(_MSC_VER) && (_MSC_VER < 1800)
+/* MSVC < 2013 does not have inttypes.h because it is not C99
+   compliant.  See compiler macros and version number in
+   https://sourceforge.net/p/predef/wiki/Compilers/ */
+#  include <stdint.h>
+#else /* !defined(_MSC_VER) || (_MSC_VER >= 1800) */
+#  include <inttypes.h>
+#endif /* !defined(_MSC_VER) || (_MSC_VER >= 1800) */
+#include <sys/types.h>
+#include <stddef.h>
+
+/**
+ * @enum
+ *
+ * :type:`sf_type` defines value type.
+ */
+typedef enum sf_type {
+  /**
+   * :enum:`SF_TYPE_BOOLEAN` indicates boolean type.
+   */
+  SF_TYPE_BOOLEAN,
+  /**
+   * :enum:`SF_TYPE_INTEGER` indicates integer type.
+   */
+  SF_TYPE_INTEGER,
+  /**
+   * :enum:`SF_TYPE_DECIMAL` indicates decimal type.
+   */
+  SF_TYPE_DECIMAL,
+  /**
+   * :enum:`SF_TYPE_STRING` indicates string type.
+   */
+  SF_TYPE_STRING,
+  /**
+   * :enum:`SF_TYPE_TOKEN` indicates token type.
+   */
+  SF_TYPE_TOKEN,
+  /**
+   * :enum:`SF_TYPE_BYTESEQ` indicates byte sequence type.
+   */
+  SF_TYPE_BYTESEQ,
+  /**
+   * :enum:`SF_TYPE_INNER_LIST` indicates inner list type.
+   */
+  SF_TYPE_INNER_LIST,
+  /**
+   * :enum:`SF_TYPE_DATE` indicates date type.
+   */
+  SF_TYPE_DATE
+} sf_type;
+
+/**
+ * @macro
+ *
+ * :macro:`SF_ERR_PARSE_ERROR` indicates fatal parse error has
+ * occurred, and it is not possible to continue the processing.
+ */
+#define SF_ERR_PARSE_ERROR -1
+
+/**
+ * @macro
+ *
+ * :macro:`SF_ERR_EOF` indicates that there is nothing left to read.
+ * The context of this error varies depending on the function that
+ * returns this error code.
+ */
+#define SF_ERR_EOF -2
+
+/**
+ * @struct
+ *
+ * :type:`sf_vec` stores sequence of bytes.
+ */
+typedef struct sf_vec {
+  /**
+   * :member:`base` points to the beginning of the sequence of bytes.
+   */
+  uint8_t *base;
+  /**
+   * :member:`len` is the number of bytes contained in this sequence.
+   */
+  size_t len;
+} sf_vec;
+
+/**
+ * @macro
+ *
+ * :macro:`SF_VALUE_FLAG_NONE` indicates no flag set.
+ */
+#define SF_VALUE_FLAG_NONE 0x0u
+
+/**
+ * @macro
+ *
+ * :macro:`SF_VALUE_FLAG_ESCAPED_STRING` indicates that a string
+ * contains escaped character(s).
+ */
+#define SF_VALUE_FLAG_ESCAPED_STRING 0x1u
+
+/**
+ * @struct
+ *
+ * :type:`sf_decimal` contains decimal value.
+ */
+typedef struct sf_decimal {
+  /**
+   * :member:`numer` contains numerator of the decimal value.
+   */
+  int64_t numer;
+  /**
+   * :member:`denom` contains denominator of the decimal value.
+   */
+  int64_t denom;
+} sf_decimal;
+
+/**
+ * @struct
+ *
+ * :type:`sf_value` stores a Structured Field item.  For Inner List,
+ * only type is set to :enum:`sf_type.SF_TYPE_INNER_LIST`.  In order
+ * to read the items contained in an inner list, call
+ * `sf_parser_inner_list`.
+ */
+typedef struct sf_value {
+  /**
+   * :member:`type` is the type of the value contained in this
+   * particular object.
+   */
+  sf_type type;
+  /**
+   * :member:`flags` is bitwise OR of one or more of
+   * :macro:`SF_VALUE_FLAG_* <SF_VALUE_FLAG_NONE>`.
+   */
+  uint32_t flags;
+  /**
+   * @anonunion_start
+   *
+   * @sf_value_value
+   */
+  union {
+    /**
+     * :member:`boolean` contains boolean value if :member:`type` ==
+     * :enum:`sf_type.SF_TYPE_BOOLEAN`.  1 indicates true, and 0
+     * indicates false.
+     */
+    int boolean;
+    /**
+     * :member:`integer` contains integer value if :member:`type` is
+     * either :enum:`sf_type.SF_TYPE_INTEGER` or
+     * :enum:`sf_type.SF_TYPE_DATE`.
+     */
+    int64_t integer;
+    /**
+     * :member:`decimal` contains decimal value if :member:`type` ==
+     * :enum:`sf_type.SF_TYPE_DECIMAL`.
+     */
+    sf_decimal decimal;
+    /**
+     * :member:`vec` contains sequence of bytes if :member:`type` is
+     * either :enum:`sf_type.SF_TYPE_STRING`,
+     * :enum:`sf_type.SF_TYPE_TOKEN`, or
+     * :enum:`sf_type.SF_TYPE_BYTESEQ`.
+     *
+     * For :enum:`sf_type.SF_TYPE_STRING`, this field contains one or
+     * more escaped characters if :member:`flags` has
+     * :macro:`SF_VALUE_FLAG_ESCAPED_STRING` set.  To unescape the
+     * string, use `sf_unescape`.
+     *
+     * For :enum:`sf_type.SF_TYPE_BYTESEQ`, this field contains base64
+     * encoded string.  To decode this byte string, use
+     * `sf_base64decode`.
+     *
+     * If :member:`vec.len <sf_vec.len>` == 0, :member:`vec.base
+     * <sf_vec.base>` is guaranteed to be NULL.
+     */
+    sf_vec vec;
+    /**
+     * @anonunion_end
+     */
+  };
+} sf_value;
+
+/**
+ * @struct
+ *
+ * :type:`sf_parser` is the Structured Field Values parser.  Use
+ * `sf_parser_init` to initialize it.
+ */
+typedef struct sf_parser {
+  /* all fields are private */
+  const uint8_t *pos;
+  const uint8_t *end;
+  uint32_t state;
+} sf_parser;
+
+/**
+ * @function
+ *
+ * `sf_parser_init` initializes |sfp| with the given buffer pointed by
+ * |data| of length |datalen|.
+ */
+void sf_parser_init(sf_parser *sfp, const uint8_t *data, size_t datalen);
+
+/**
+ * @function
+ *
+ * `sf_parser_param` reads a parameter.  If this function returns 0,
+ * it stores parameter key and value in |dest_key| and |dest_value|
+ * respectively, if they are not NULL.
+ *
+ * This function does no effort to find duplicated keys.  Same key may
+ * be reported more than once.
+ *
+ * Caller should keep calling this function until it returns negative
+ * error code.  If it returns :macro:`SF_ERR_EOF`, all parameters have
+ * read, and caller can continue to read rest of the values.  If it
+ * returns :macro:`SF_ERR_PARSE_ERROR`, it encountered fatal error
+ * while parsing field value.
+ */
+int sf_parser_param(sf_parser *sfp, sf_vec *dest_key, sf_value *dest_value);
+
+/**
+ * @function
+ *
+ * `sf_parser_dict` reads the next dictionary key and value pair.  If
+ * this function returns 0, it stores the key and value in |dest_key|
+ * and |dest_value| respectively, if they are not NULL.
+ *
+ * Caller can optionally read parameters attached to the pair by
+ * calling `sf_parser_param`.
+ *
+ * This function does no effort to find duplicated keys.  Same key may
+ * be reported more than once.
+ *
+ * Caller should keep calling this function until it returns negative
+ * error code.  If it returns :macro:`SF_ERR_EOF`, all key and value
+ * pairs have been read, and there is nothing left to read.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :macro:`SF_ERR_EOF`
+ *     All values in the dictionary have read.
+ * :macro:`SF_ERR_PARSE_ERROR`
+ *     It encountered fatal error while parsing field value.
+ */
+int sf_parser_dict(sf_parser *sfp, sf_vec *dest_key, sf_value *dest_value);
+
+/**
+ * @function
+ *
+ * `sf_parser_list` reads the next list item.  If this function
+ * returns 0, it stores the item in |dest| if it is not NULL.
+ *
+ * Caller can optionally read parameters attached to the item by
+ * calling `sf_parser_param`.
+ *
+ * Caller should keep calling this function until it returns negative
+ * error code.  If it returns :macro:`SF_ERR_EOF`, all values in the
+ * list have been read, and there is nothing left to read.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :macro:`SF_ERR_EOF`
+ *     All values in the list have read.
+ * :macro:`SF_ERR_PARSE_ERROR`
+ *     It encountered fatal error while parsing field value.
+ */
+int sf_parser_list(sf_parser *sfp, sf_value *dest);
+
+/**
+ * @function
+ *
+ * `sf_parser_item` reads a single item.  If this function returns 0,
+ * it stores the item in |dest| if it is not NULL.
+ *
+ * This function is only used for the field value that consists of a
+ * single item.
+ *
+ * Caller can optionally read parameters attached to the item by
+ * calling `sf_parser_param`.
+ *
+ * Caller should call this function again to make sure that there is
+ * nothing left to read.  If this 2nd function call returns
+ * :macro:`SF_ERR_EOF`, all data have been processed successfully.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :macro:`SF_ERR_EOF`
+ *     There is nothing left to read.
+ * :macro:`SF_ERR_PARSE_ERROR`
+ *     It encountered fatal error while parsing field value.
+ */
+int sf_parser_item(sf_parser *sfp, sf_value *dest);
+
+/**
+ * @function
+ *
+ * `sf_parser_inner_list` reads the next inner list item.  If this
+ * function returns 0, it stores the item in |dest| if it is not NULL.
+ *
+ * Caller can optionally read parameters attached to the item by
+ * calling `sf_parser_param`.
+ *
+ * Caller should keep calling this function until it returns negative
+ * error code.  If it returns :macro:`SF_ERR_EOF`, all values in this
+ * inner list have been read, and caller can optionally read
+ * parameters attached to this inner list by calling
+ * `sf_parser_param`.  Then caller can continue to read rest of the
+ * values.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :macro:`SF_ERR_EOF`
+ *     All values in the inner list have read.
+ * :macro:`SF_ERR_PARSE_ERROR`
+ *     It encountered fatal error while parsing field value.
+ */
+int sf_parser_inner_list(sf_parser *sfp, sf_value *dest);
+
+/**
+ * @function
+ *
+ * `sf_unescape` copies |src| to |dest| by removing escapes (``\``).
+ * |src| should be the pointer to :member:`sf_value.vec` of type
+ * :enum:`sf_type.SF_TYPE_STRING` produced by either `sf_parser_dict`,
+ * `sf_parser_list`, `sf_parser_inner_list`, `sf_parser_item`, or
+ * `sf_parser_param`, otherwise the behavior is undefined.
+ *
+ * :member:`dest->base <sf_vec.base>` must point to the buffer that
+ * has sufficient space to store the unescaped string.
+ *
+ * If there is no escape character in |src|, |*src| is assigned to
+ * |*dest|.  This includes the case that :member:`src->len
+ * <sf_vec.len>` == 0.
+ *
+ * This function sets the length of unescaped string to
+ * :member:`dest->len <sf_vec.len>`.
+ */
+void sf_unescape(sf_vec *dest, const sf_vec *src);
+
+/**
+ * @function
+ *
+ * `sf_base64decode` decodes Base64 encoded string |src| and writes
+ * the result into |dest|.  |src| should be the pointer to
+ * :member:`sf_value.vec` of type :enum:`sf_type.SF_TYPE_BYTESEQ`
+ * produced by either `sf_parser_dict`, `sf_parser_list`,
+ * `sf_parser_inner_list`, `sf_parser_item`, or `sf_parser_param`,
+ * otherwise the behavior is undefined.
+ *
+ * :member:`dest->base <sf_vec.base>` must point to the buffer that
+ * has sufficient space to store the decoded byte string.
+ *
+ * If :member:`src->len <sf_vec.len>` == 0, |*src| is assigned to
+ * |*dest|.
+ *
+ * This function sets the length of decoded byte string to
+ * :member:`dest->len <sf_vec.len>`.
+ */
+void sf_base64decode(sf_vec *dest, const sf_vec *src);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* SFPARSE_H */
Index: node-v16.20.2/deps/nghttp2/lib/nghttp2_ratelim.c
===================================================================
--- /dev/null
+++ node-v16.20.2/deps/nghttp2/lib/nghttp2_ratelim.c
@@ -0,0 +1,75 @@
+/*
+ * nghttp2 - HTTP/2 C Library
+ *
+ * Copyright (c) 2023 nghttp2 contributors
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include "nghttp2_ratelim.h"
+#include "nghttp2_helper.h"
+
+void nghttp2_ratelim_init(nghttp2_ratelim *rl, uint64_t burst, uint64_t rate) {
+  rl->val = rl->burst = burst;
+  rl->rate = rate;
+  rl->tstamp = 0;
+}
+
+void nghttp2_ratelim_update(nghttp2_ratelim *rl, uint64_t tstamp) {
+  uint64_t d, gain;
+
+  if (tstamp == rl->tstamp) {
+    return;
+  }
+
+  if (tstamp > rl->tstamp) {
+    d = tstamp - rl->tstamp;
+  } else {
+    d = 1;
+  }
+
+  rl->tstamp = tstamp;
+
+  if (UINT64_MAX / d < rl->rate) {
+    rl->val = rl->burst;
+
+    return;
+  }
+
+  gain = rl->rate * d;
+
+  if (UINT64_MAX - gain < rl->val) {
+    rl->val = rl->burst;
+
+    return;
+  }
+
+  rl->val += gain;
+  rl->val = nghttp2_min(rl->val, rl->burst);
+}
+
+int nghttp2_ratelim_drain(nghttp2_ratelim *rl, uint64_t n) {
+  if (rl->val < n) {
+    return -1;
+  }
+
+  rl->val -= n;
+
+  return 0;
+}
Index: node-v16.20.2/deps/nghttp2/lib/nghttp2_ratelim.h
===================================================================
--- /dev/null
+++ node-v16.20.2/deps/nghttp2/lib/nghttp2_ratelim.h
@@ -0,0 +1,57 @@
+/*
+ * nghttp2 - HTTP/2 C Library
+ *
+ * Copyright (c) 2023 nghttp2 contributors
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#ifndef NGHTTP2_RATELIM_H
+#define NGHTTP2_RATELIM_H
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <nghttp2/nghttp2.h>
+
+typedef struct nghttp2_ratelim {
+  /* burst is the maximum value of val. */
+  uint64_t burst;
+  /* rate is the amount of value that is regenerated per 1 tstamp. */
+  uint64_t rate;
+  /* val is the amount of value available to drain. */
+  uint64_t val;
+  /* tstamp is the last timestamp in second resolution that is known
+     to this object. */
+  uint64_t tstamp;
+} nghttp2_ratelim;
+
+/* nghttp2_ratelim_init initializes |rl| with the given parameters. */
+void nghttp2_ratelim_init(nghttp2_ratelim *rl, uint64_t burst, uint64_t rate);
+
+/* nghttp2_ratelim_update updates rl->val with the current |tstamp|
+   given in second resolution. */
+void nghttp2_ratelim_update(nghttp2_ratelim *rl, uint64_t tstamp);
+
+/* nghttp2_ratelim_drain drains |n| from rl->val.  It returns 0 if it
+   succeeds, or -1. */
+int nghttp2_ratelim_drain(nghttp2_ratelim *rl, uint64_t n);
+
+#endif /* NGHTTP2_RATELIM_H */
Index: node-v16.20.2/deps/nghttp2/lib/nghttp2_time.c
===================================================================
--- /dev/null
+++ node-v16.20.2/deps/nghttp2/lib/nghttp2_time.c
@@ -0,0 +1,62 @@
+/*
+ * nghttp2 - HTTP/2 C Library
+ *
+ * Copyright (c) 2023 nghttp2 contributors
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include "nghttp2_time.h"
+
+#ifdef HAVE_TIME_H
+#  include <time.h>
+#endif /* HAVE_TIME_H */
+
+#ifdef HAVE_SYSINFOAPI_H
+#  include <sysinfoapi.h>
+#endif /* HAVE_SYSINFOAPI_H */
+
+#ifndef HAVE_GETTICKCOUNT64
+static uint64_t time_now_sec(void) {
+  time_t t = time(NULL);
+
+  if (t == -1) {
+    return 0;
+  }
+
+  return (uint64_t)t;
+}
+#endif /* HAVE_GETTICKCOUNT64 */
+
+#ifdef HAVE_CLOCK_GETTIME
+uint64_t nghttp2_time_now_sec(void) {
+  struct timespec tp;
+  int rv = clock_gettime(CLOCK_MONOTONIC, &tp);
+
+  if (rv == -1) {
+    return time_now_sec();
+  }
+
+  return (uint64_t)tp.tv_sec;
+}
+#elif defined(HAVE_GETTICKCOUNT64)
+uint64_t nghttp2_time_now_sec(void) { return GetTickCount64() / 1000; }
+#else  /* !HAVE_CLOCK_GETTIME && !HAVE_GETTICKCOUNT64 */
+uint64_t nghttp2_time_now_sec(void) { return time_now_sec(); }
+#endif /* !HAVE_CLOCK_GETTIME && !HAVE_GETTICKCOUNT64 */
Index: node-v16.20.2/deps/nghttp2/lib/nghttp2_time.h
===================================================================
--- /dev/null
+++ node-v16.20.2/deps/nghttp2/lib/nghttp2_time.h
@@ -0,0 +1,38 @@
+/*
+ * nghttp2 - HTTP/2 C Library
+ *
+ * Copyright (c) 2023 nghttp2 contributors
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#ifndef NGHTTP2_TIME_H
+#define NGHTTP2_TIME_H
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <nghttp2/nghttp2.h>
+
+/* nghttp2_time_now_sec returns seconds from implementation-specific
+   timepoint.  If it is unable to get seconds, it returns 0. */
+uint64_t nghttp2_time_now_sec(void);
+
+#endif /* NGHTTP2_TIME_H */
openSUSE Build Service is sponsored by