From cda2c32111576f227d860b94d14985b3c0cc81c4 Mon Sep 17 00:00:00 2001 From: ajayk Date: Wed, 11 Oct 2023 23:47:37 -0700 Subject: [PATCH] nodejs-18: add nghttp2 patches --- nodejs-18.yaml | 6 +- nodejs-18/nghttp2.patch | 4501 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 4506 insertions(+), 1 deletion(-) create mode 100644 nodejs-18/nghttp2.patch diff --git a/nodejs-18.yaml b/nodejs-18.yaml index 8f680c7b258..a7a3b544dfa 100644 --- a/nodejs-18.yaml +++ b/nodejs-18.yaml @@ -1,7 +1,7 @@ package: name: nodejs-18 version: 18.18.1 # When bumping this, also bump the provides below! - epoch: 0 + epoch: 1 description: "JavaScript runtime built on V8 engine - LTS version" copyright: - license: MIT @@ -36,6 +36,10 @@ pipeline: uri: https://nodejs.org/dist/v${{package.version}}/node-v${{package.version}}.tar.gz expected-sha256: f882080b1a5ee2fd5078521ec3016cb8472740d671d19465d377207d671af372 + - uses: patch + with: + patches: nghttp2.patch + - name: Configure and build runs: | # Add defines recommended in libuv readme. diff --git a/nodejs-18/nghttp2.patch b/nodejs-18/nghttp2.patch new file mode 100644 index 00000000000..4a45bd23d2d --- /dev/null +++ b/nodejs-18/nghttp2.patch @@ -0,0 +1,4501 @@ +From 76f4747105f846f60ec5f9904e5c4ae693dbe7be Mon Sep 17 00:00:00 2001 +From: Richard Lau +Date: Wed, 11 Oct 2023 14:30:01 -0400 +Subject: [PATCH 1/6] Revert "deps: update nghttp2 to 1.55.0" + +This reverts commit c8da8c80b9923952499ed013fa6d88cb67fd6b9f. +--- + deps/nghttp2/lib/Makefile.in | 4 ++-- + deps/nghttp2/lib/includes/Makefile.in | 4 ++-- + deps/nghttp2/lib/includes/nghttp2/nghttp2ver.h | 4 ++-- + 3 files changed, 6 insertions(+), 6 deletions(-) + +diff --git a/deps/nghttp2/lib/Makefile.in b/deps/nghttp2/lib/Makefile.in +index 8f7dc349d7cb1..2c6edc3a05c7d 100644 +--- a/deps/nghttp2/lib/Makefile.in ++++ b/deps/nghttp2/lib/Makefile.in +@@ -355,8 +355,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_QUICTLS_CFLAGS = @LIBNGTCP2_CRYPTO_QUICTLS_CFLAGS@ +-LIBNGTCP2_CRYPTO_QUICTLS_LIBS = @LIBNGTCP2_CRYPTO_QUICTLS_LIBS@ ++LIBNGTCP2_CRYPTO_OPENSSL_CFLAGS = @LIBNGTCP2_CRYPTO_OPENSSL_CFLAGS@ ++LIBNGTCP2_CRYPTO_OPENSSL_LIBS = @LIBNGTCP2_CRYPTO_OPENSSL_LIBS@ + LIBNGTCP2_LIBS = @LIBNGTCP2_LIBS@ + LIBOBJS = @LIBOBJS@ + LIBS = @LIBS@ +diff --git a/deps/nghttp2/lib/includes/Makefile.in b/deps/nghttp2/lib/includes/Makefile.in +index 3de90d7bef3e3..18b45672406fe 100644 +--- a/deps/nghttp2/lib/includes/Makefile.in ++++ b/deps/nghttp2/lib/includes/Makefile.in +@@ -263,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_QUICTLS_CFLAGS = @LIBNGTCP2_CRYPTO_QUICTLS_CFLAGS@ +-LIBNGTCP2_CRYPTO_QUICTLS_LIBS = @LIBNGTCP2_CRYPTO_QUICTLS_LIBS@ ++LIBNGTCP2_CRYPTO_OPENSSL_CFLAGS = @LIBNGTCP2_CRYPTO_OPENSSL_CFLAGS@ ++LIBNGTCP2_CRYPTO_OPENSSL_LIBS = @LIBNGTCP2_CRYPTO_OPENSSL_LIBS@ + LIBNGTCP2_LIBS = @LIBNGTCP2_LIBS@ + LIBOBJS = @LIBOBJS@ + LIBS = @LIBS@ +diff --git a/deps/nghttp2/lib/includes/nghttp2/nghttp2ver.h b/deps/nghttp2/lib/includes/nghttp2/nghttp2ver.h +index 5dea3ffe100b4..6ed0ac4a9bfae 100644 +--- a/deps/nghttp2/lib/includes/nghttp2/nghttp2ver.h ++++ b/deps/nghttp2/lib/includes/nghttp2/nghttp2ver.h +@@ -29,7 +29,7 @@ + * @macro + * Version number of the nghttp2 library release + */ +-#define NGHTTP2_VERSION "1.55.0" ++#define NGHTTP2_VERSION "1.52.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 0x013700 ++#define NGHTTP2_VERSION_NUM 0x013400 + + #endif /* NGHTTP2VER_H */ + +From 985a2042d839cffa637a4e0e201a0048e64be7fd Mon Sep 17 00:00:00 2001 +From: "Node.js GitHub Bot" +Date: Thu, 18 May 2023 14:59:03 +0100 +Subject: [PATCH 2/6] deps: update nghttp2 to 1.53.0 + +PR-URL: https://github.com/nodejs/node/pull/47997 +Reviewed-By: Rafael Gonzaga +Reviewed-By: Luigi Pinca +Reviewed-By: Marco Ippolito +--- + deps/nghttp2/lib/CMakeLists.txt | 1 + + deps/nghttp2/lib/Makefile.am | 6 +- + deps/nghttp2/lib/Makefile.in | 14 +- + .../nghttp2/lib/includes/nghttp2/nghttp2ver.h | 4 +- + deps/nghttp2/lib/nghttp2_http.c | 716 +--------- + deps/nghttp2/lib/nghttp2_http.h | 48 - + deps/nghttp2/lib/nghttp2_map.c | 61 +- + deps/nghttp2/lib/nghttp2_map.h | 8 +- + deps/nghttp2/lib/nghttp2_session.c | 24 +- + deps/nghttp2/lib/sfparse.c | 1146 +++++++++++++++++ + deps/nghttp2/lib/sfparse.h | 409 ++++++ + deps/nghttp2/nghttp2.gyp | 52 +- + 12 files changed, 1682 insertions(+), 807 deletions(-) + create mode 100644 deps/nghttp2/lib/sfparse.c + create mode 100644 deps/nghttp2/lib/sfparse.h + +diff --git a/deps/nghttp2/lib/CMakeLists.txt b/deps/nghttp2/lib/CMakeLists.txt +index fb24fa186f111..fad04716ffafb 100644 +--- a/deps/nghttp2/lib/CMakeLists.txt ++++ b/deps/nghttp2/lib/CMakeLists.txt +@@ -25,6 +25,7 @@ set(NGHTTP2_SOURCES + nghttp2_rcbuf.c + nghttp2_extpri.c + nghttp2_debug.c ++ sfparse.c + ) + + set(NGHTTP2_RES "") +diff --git a/deps/nghttp2/lib/Makefile.am b/deps/nghttp2/lib/Makefile.am +index 9a985bf76b28a..cd928ae465501 100644 +--- a/deps/nghttp2/lib/Makefile.am ++++ b/deps/nghttp2/lib/Makefile.am +@@ -51,7 +51,8 @@ OBJECTS = nghttp2_pq.c nghttp2_map.c nghttp2_queue.c \ + nghttp2_http.c \ + nghttp2_rcbuf.c \ + nghttp2_extpri.c \ +- nghttp2_debug.c ++ nghttp2_debug.c \ ++ sfparse.c + + HFILES = nghttp2_pq.h nghttp2_int.h nghttp2_map.h nghttp2_queue.h \ + nghttp2_frame.h \ +@@ -68,7 +69,8 @@ HFILES = nghttp2_pq.h nghttp2_int.h nghttp2_map.h nghttp2_queue.h \ + nghttp2_http.h \ + nghttp2_rcbuf.h \ + nghttp2_extpri.h \ +- nghttp2_debug.h ++ nghttp2_debug.h \ ++ sfparse.h + + libnghttp2_la_SOURCES = $(HFILES) $(OBJECTS) + libnghttp2_la_LDFLAGS = $(AM_LDFLAGS) -no-undefined \ +diff --git a/deps/nghttp2/lib/Makefile.in b/deps/nghttp2/lib/Makefile.in +index 2c6edc3a05c7d..7c07e0c83a0fa 100644 +--- a/deps/nghttp2/lib/Makefile.in ++++ b/deps/nghttp2/lib/Makefile.in +@@ -157,7 +157,7 @@ am__objects_2 = nghttp2_pq.lo nghttp2_map.lo nghttp2_queue.lo \ + 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_extpri.lo nghttp2_debug.lo ++ nghttp2_rcbuf.lo nghttp2_extpri.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@) +@@ -196,7 +196,8 @@ am__depfiles_remade = ./$(DEPDIR)/nghttp2_buf.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_submit.Plo ./$(DEPDIR)/nghttp2_version.Plo \ ++ ./$(DEPDIR)/sfparse.Plo + am__mv = mv -f + COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +@@ -509,7 +510,8 @@ OBJECTS = nghttp2_pq.c nghttp2_map.c nghttp2_queue.c \ + nghttp2_http.c \ + nghttp2_rcbuf.c \ + nghttp2_extpri.c \ +- nghttp2_debug.c ++ nghttp2_debug.c \ ++ sfparse.c + + HFILES = nghttp2_pq.h nghttp2_int.h nghttp2_map.h nghttp2_queue.h \ + nghttp2_frame.h \ +@@ -526,7 +528,8 @@ HFILES = nghttp2_pq.h nghttp2_int.h nghttp2_map.h nghttp2_queue.h \ + nghttp2_http.h \ + nghttp2_rcbuf.h \ + nghttp2_extpri.h \ +- nghttp2_debug.h ++ nghttp2_debug.h \ ++ sfparse.h + + libnghttp2_la_SOURCES = $(HFILES) $(OBJECTS) + libnghttp2_la_LDFLAGS = $(AM_LDFLAGS) -no-undefined \ +@@ -635,6 +638,7 @@ distclean-compile: + @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_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) +@@ -917,6 +921,7 @@ distclean: distclean-recursive + -rm -f ./$(DEPDIR)/nghttp2_stream.Plo + -rm -f ./$(DEPDIR)/nghttp2_submit.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 +@@ -985,6 +990,7 @@ maintainer-clean: maintainer-clean-recursive + -rm -f ./$(DEPDIR)/nghttp2_stream.Plo + -rm -f ./$(DEPDIR)/nghttp2_submit.Plo + -rm -f ./$(DEPDIR)/nghttp2_version.Plo ++ -rm -f ./$(DEPDIR)/sfparse.Plo + -rm -f Makefile + maintainer-clean-am: distclean-am maintainer-clean-generic + +diff --git a/deps/nghttp2/lib/includes/nghttp2/nghttp2ver.h b/deps/nghttp2/lib/includes/nghttp2/nghttp2ver.h +index 6ed0ac4a9bfae..46e7004be2c60 100644 +--- a/deps/nghttp2/lib/includes/nghttp2/nghttp2ver.h ++++ b/deps/nghttp2/lib/includes/nghttp2/nghttp2ver.h +@@ -29,7 +29,7 @@ + * @macro + * Version number of the nghttp2 library release + */ +-#define NGHTTP2_VERSION "1.52.0" ++#define NGHTTP2_VERSION "1.53.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 0x013400 ++#define NGHTTP2_VERSION_NUM 0x013500 + + #endif /* NGHTTP2VER_H */ +diff --git a/deps/nghttp2/lib/nghttp2_http.c b/deps/nghttp2/lib/nghttp2_http.c +index 83e5e6685f86d..ecdeb21ddb694 100644 +--- a/deps/nghttp2/lib/nghttp2_http.c ++++ b/deps/nghttp2/lib/nghttp2_http.c +@@ -31,6 +31,7 @@ + #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; +@@ -578,713 +579,52 @@ void nghttp2_http_record_request_method(nghttp2_stream *stream, + } + } + +-/* Generated by genchartbl.py */ +-static const int SF_KEY_CHARS[] = { +- 0 /* NUL */, 0 /* SOH */, 0 /* STX */, 0 /* ETX */, 0 /* EOT */, +- 0 /* ENQ */, 0 /* ACK */, 0 /* BEL */, 0 /* BS */, 0 /* HT */, +- 0 /* LF */, 0 /* VT */, 0 /* FF */, 0 /* CR */, 0 /* SO */, +- 0 /* SI */, 0 /* DLE */, 0 /* DC1 */, 0 /* DC2 */, 0 /* DC3 */, +- 0 /* DC4 */, 0 /* NAK */, 0 /* SYN */, 0 /* ETB */, 0 /* CAN */, +- 0 /* EM */, 0 /* SUB */, 0 /* ESC */, 0 /* FS */, 0 /* GS */, +- 0 /* RS */, 0 /* US */, 0 /* SPC */, 0 /* ! */, 0 /* " */, +- 0 /* # */, 0 /* $ */, 0 /* % */, 0 /* & */, 0 /* ' */, +- 0 /* ( */, 0 /* ) */, 1 /* * */, 0 /* + */, 0 /* , */, +- 1 /* - */, 1 /* . */, 0 /* / */, 1 /* 0 */, 1 /* 1 */, +- 1 /* 2 */, 1 /* 3 */, 1 /* 4 */, 1 /* 5 */, 1 /* 6 */, +- 1 /* 7 */, 1 /* 8 */, 1 /* 9 */, 0 /* : */, 0 /* ; */, +- 0 /* < */, 0 /* = */, 0 /* > */, 0 /* ? */, 0 /* @ */, +- 0 /* A */, 0 /* B */, 0 /* C */, 0 /* D */, 0 /* E */, +- 0 /* F */, 0 /* G */, 0 /* H */, 0 /* I */, 0 /* J */, +- 0 /* K */, 0 /* L */, 0 /* M */, 0 /* N */, 0 /* O */, +- 0 /* P */, 0 /* Q */, 0 /* R */, 0 /* S */, 0 /* T */, +- 0 /* U */, 0 /* V */, 0 /* W */, 0 /* X */, 0 /* Y */, +- 0 /* Z */, 0 /* [ */, 0 /* \ */, 0 /* ] */, 0 /* ^ */, +- 1 /* _ */, 0 /* ` */, 1 /* a */, 1 /* b */, 1 /* c */, +- 1 /* d */, 1 /* e */, 1 /* f */, 1 /* g */, 1 /* h */, +- 1 /* i */, 1 /* j */, 1 /* k */, 1 /* l */, 1 /* m */, +- 1 /* n */, 1 /* o */, 1 /* p */, 1 /* q */, 1 /* r */, +- 1 /* s */, 1 /* t */, 1 /* u */, 1 /* v */, 1 /* w */, +- 1 /* x */, 1 /* y */, 1 /* z */, 0 /* { */, 0 /* | */, +- 0 /* } */, 0 /* ~ */, 0 /* DEL */, 0 /* 0x80 */, 0 /* 0x81 */, +- 0 /* 0x82 */, 0 /* 0x83 */, 0 /* 0x84 */, 0 /* 0x85 */, 0 /* 0x86 */, +- 0 /* 0x87 */, 0 /* 0x88 */, 0 /* 0x89 */, 0 /* 0x8a */, 0 /* 0x8b */, +- 0 /* 0x8c */, 0 /* 0x8d */, 0 /* 0x8e */, 0 /* 0x8f */, 0 /* 0x90 */, +- 0 /* 0x91 */, 0 /* 0x92 */, 0 /* 0x93 */, 0 /* 0x94 */, 0 /* 0x95 */, +- 0 /* 0x96 */, 0 /* 0x97 */, 0 /* 0x98 */, 0 /* 0x99 */, 0 /* 0x9a */, +- 0 /* 0x9b */, 0 /* 0x9c */, 0 /* 0x9d */, 0 /* 0x9e */, 0 /* 0x9f */, +- 0 /* 0xa0 */, 0 /* 0xa1 */, 0 /* 0xa2 */, 0 /* 0xa3 */, 0 /* 0xa4 */, +- 0 /* 0xa5 */, 0 /* 0xa6 */, 0 /* 0xa7 */, 0 /* 0xa8 */, 0 /* 0xa9 */, +- 0 /* 0xaa */, 0 /* 0xab */, 0 /* 0xac */, 0 /* 0xad */, 0 /* 0xae */, +- 0 /* 0xaf */, 0 /* 0xb0 */, 0 /* 0xb1 */, 0 /* 0xb2 */, 0 /* 0xb3 */, +- 0 /* 0xb4 */, 0 /* 0xb5 */, 0 /* 0xb6 */, 0 /* 0xb7 */, 0 /* 0xb8 */, +- 0 /* 0xb9 */, 0 /* 0xba */, 0 /* 0xbb */, 0 /* 0xbc */, 0 /* 0xbd */, +- 0 /* 0xbe */, 0 /* 0xbf */, 0 /* 0xc0 */, 0 /* 0xc1 */, 0 /* 0xc2 */, +- 0 /* 0xc3 */, 0 /* 0xc4 */, 0 /* 0xc5 */, 0 /* 0xc6 */, 0 /* 0xc7 */, +- 0 /* 0xc8 */, 0 /* 0xc9 */, 0 /* 0xca */, 0 /* 0xcb */, 0 /* 0xcc */, +- 0 /* 0xcd */, 0 /* 0xce */, 0 /* 0xcf */, 0 /* 0xd0 */, 0 /* 0xd1 */, +- 0 /* 0xd2 */, 0 /* 0xd3 */, 0 /* 0xd4 */, 0 /* 0xd5 */, 0 /* 0xd6 */, +- 0 /* 0xd7 */, 0 /* 0xd8 */, 0 /* 0xd9 */, 0 /* 0xda */, 0 /* 0xdb */, +- 0 /* 0xdc */, 0 /* 0xdd */, 0 /* 0xde */, 0 /* 0xdf */, 0 /* 0xe0 */, +- 0 /* 0xe1 */, 0 /* 0xe2 */, 0 /* 0xe3 */, 0 /* 0xe4 */, 0 /* 0xe5 */, +- 0 /* 0xe6 */, 0 /* 0xe7 */, 0 /* 0xe8 */, 0 /* 0xe9 */, 0 /* 0xea */, +- 0 /* 0xeb */, 0 /* 0xec */, 0 /* 0xed */, 0 /* 0xee */, 0 /* 0xef */, +- 0 /* 0xf0 */, 0 /* 0xf1 */, 0 /* 0xf2 */, 0 /* 0xf3 */, 0 /* 0xf4 */, +- 0 /* 0xf5 */, 0 /* 0xf6 */, 0 /* 0xf7 */, 0 /* 0xf8 */, 0 /* 0xf9 */, +- 0 /* 0xfa */, 0 /* 0xfb */, 0 /* 0xfc */, 0 /* 0xfd */, 0 /* 0xfe */, +- 0 /* 0xff */, +-}; +- +-static ssize_t sf_parse_key(const uint8_t *begin, const uint8_t *end) { +- const uint8_t *p = begin; +- +- if ((*p < 'a' || 'z' < *p) && *p != '*') { +- return -1; +- } +- +- for (; p != end && SF_KEY_CHARS[*p]; ++p) +- ; +- +- return p - begin; +-} +- +-static ssize_t sf_parse_integer_or_decimal(nghttp2_sf_value *dest, +- const uint8_t *begin, +- const uint8_t *end) { +- const uint8_t *p = begin; +- int sign = 1; +- int64_t value = 0; +- int type = NGHTTP2_SF_VALUE_TYPE_INTEGER; +- size_t len = 0; +- size_t fpos = 0; +- size_t i; +- +- if (*p == '-') { +- if (++p == end) { +- return -1; +- } +- +- sign = -1; +- } +- +- if (*p < '0' || '9' < *p) { +- return -1; +- } +- +- for (; p != end; ++p) { +- switch (*p) { +- case '0': +- case '1': +- case '2': +- case '3': +- case '4': +- case '5': +- case '6': +- case '7': +- case '8': +- case '9': +- value *= 10; +- value += *p - '0'; +- +- if (++len > 15) { +- return -1; +- } +- +- break; +- case '.': +- if (type != NGHTTP2_SF_VALUE_TYPE_INTEGER) { +- goto fin; +- } +- +- if (len > 12) { +- return -1; +- } +- fpos = len; +- type = NGHTTP2_SF_VALUE_TYPE_DECIMAL; +- +- break; +- default: +- goto fin; +- }; +- } +- +-fin: +- switch (type) { +- case NGHTTP2_SF_VALUE_TYPE_INTEGER: +- if (dest) { +- dest->type = (uint8_t)type; +- dest->i = value * sign; +- } +- +- return p - begin; +- case NGHTTP2_SF_VALUE_TYPE_DECIMAL: +- if (fpos == len || len - fpos > 3) { +- return -1; +- } +- +- if (dest) { +- dest->type = (uint8_t)type; +- dest->d = (double)value; +- for (i = len - fpos; i > 0; --i) { +- dest->d /= (double)10; +- } +- dest->d *= sign; +- } +- +- return p - begin; +- default: +- assert(0); +- abort(); +- } +-} +- +-/* Generated by genchartbl.py */ +-static const int SF_DQUOTE_CHARS[] = { +- 0 /* NUL */, 0 /* SOH */, 0 /* STX */, 0 /* ETX */, 0 /* EOT */, +- 0 /* ENQ */, 0 /* ACK */, 0 /* BEL */, 0 /* BS */, 0 /* HT */, +- 0 /* LF */, 0 /* VT */, 0 /* FF */, 0 /* CR */, 0 /* SO */, +- 0 /* SI */, 0 /* DLE */, 0 /* DC1 */, 0 /* DC2 */, 0 /* DC3 */, +- 0 /* DC4 */, 0 /* NAK */, 0 /* SYN */, 0 /* ETB */, 0 /* CAN */, +- 0 /* EM */, 0 /* SUB */, 0 /* ESC */, 0 /* FS */, 0 /* GS */, +- 0 /* RS */, 0 /* US */, 1 /* SPC */, 1 /* ! */, 0 /* " */, +- 1 /* # */, 1 /* $ */, 1 /* % */, 1 /* & */, 1 /* ' */, +- 1 /* ( */, 1 /* ) */, 1 /* * */, 1 /* + */, 1 /* , */, +- 1 /* - */, 1 /* . */, 1 /* / */, 1 /* 0 */, 1 /* 1 */, +- 1 /* 2 */, 1 /* 3 */, 1 /* 4 */, 1 /* 5 */, 1 /* 6 */, +- 1 /* 7 */, 1 /* 8 */, 1 /* 9 */, 1 /* : */, 1 /* ; */, +- 1 /* < */, 1 /* = */, 1 /* > */, 1 /* ? */, 1 /* @ */, +- 1 /* A */, 1 /* B */, 1 /* C */, 1 /* D */, 1 /* E */, +- 1 /* F */, 1 /* G */, 1 /* H */, 1 /* I */, 1 /* J */, +- 1 /* K */, 1 /* L */, 1 /* M */, 1 /* N */, 1 /* O */, +- 1 /* P */, 1 /* Q */, 1 /* R */, 1 /* S */, 1 /* T */, +- 1 /* U */, 1 /* V */, 1 /* W */, 1 /* X */, 1 /* Y */, +- 1 /* Z */, 1 /* [ */, 0 /* \ */, 1 /* ] */, 1 /* ^ */, +- 1 /* _ */, 1 /* ` */, 1 /* a */, 1 /* b */, 1 /* c */, +- 1 /* d */, 1 /* e */, 1 /* f */, 1 /* g */, 1 /* h */, +- 1 /* i */, 1 /* j */, 1 /* k */, 1 /* l */, 1 /* m */, +- 1 /* n */, 1 /* o */, 1 /* p */, 1 /* q */, 1 /* r */, +- 1 /* s */, 1 /* t */, 1 /* u */, 1 /* v */, 1 /* w */, +- 1 /* x */, 1 /* y */, 1 /* z */, 1 /* { */, 1 /* | */, +- 1 /* } */, 1 /* ~ */, 0 /* DEL */, 0 /* 0x80 */, 0 /* 0x81 */, +- 0 /* 0x82 */, 0 /* 0x83 */, 0 /* 0x84 */, 0 /* 0x85 */, 0 /* 0x86 */, +- 0 /* 0x87 */, 0 /* 0x88 */, 0 /* 0x89 */, 0 /* 0x8a */, 0 /* 0x8b */, +- 0 /* 0x8c */, 0 /* 0x8d */, 0 /* 0x8e */, 0 /* 0x8f */, 0 /* 0x90 */, +- 0 /* 0x91 */, 0 /* 0x92 */, 0 /* 0x93 */, 0 /* 0x94 */, 0 /* 0x95 */, +- 0 /* 0x96 */, 0 /* 0x97 */, 0 /* 0x98 */, 0 /* 0x99 */, 0 /* 0x9a */, +- 0 /* 0x9b */, 0 /* 0x9c */, 0 /* 0x9d */, 0 /* 0x9e */, 0 /* 0x9f */, +- 0 /* 0xa0 */, 0 /* 0xa1 */, 0 /* 0xa2 */, 0 /* 0xa3 */, 0 /* 0xa4 */, +- 0 /* 0xa5 */, 0 /* 0xa6 */, 0 /* 0xa7 */, 0 /* 0xa8 */, 0 /* 0xa9 */, +- 0 /* 0xaa */, 0 /* 0xab */, 0 /* 0xac */, 0 /* 0xad */, 0 /* 0xae */, +- 0 /* 0xaf */, 0 /* 0xb0 */, 0 /* 0xb1 */, 0 /* 0xb2 */, 0 /* 0xb3 */, +- 0 /* 0xb4 */, 0 /* 0xb5 */, 0 /* 0xb6 */, 0 /* 0xb7 */, 0 /* 0xb8 */, +- 0 /* 0xb9 */, 0 /* 0xba */, 0 /* 0xbb */, 0 /* 0xbc */, 0 /* 0xbd */, +- 0 /* 0xbe */, 0 /* 0xbf */, 0 /* 0xc0 */, 0 /* 0xc1 */, 0 /* 0xc2 */, +- 0 /* 0xc3 */, 0 /* 0xc4 */, 0 /* 0xc5 */, 0 /* 0xc6 */, 0 /* 0xc7 */, +- 0 /* 0xc8 */, 0 /* 0xc9 */, 0 /* 0xca */, 0 /* 0xcb */, 0 /* 0xcc */, +- 0 /* 0xcd */, 0 /* 0xce */, 0 /* 0xcf */, 0 /* 0xd0 */, 0 /* 0xd1 */, +- 0 /* 0xd2 */, 0 /* 0xd3 */, 0 /* 0xd4 */, 0 /* 0xd5 */, 0 /* 0xd6 */, +- 0 /* 0xd7 */, 0 /* 0xd8 */, 0 /* 0xd9 */, 0 /* 0xda */, 0 /* 0xdb */, +- 0 /* 0xdc */, 0 /* 0xdd */, 0 /* 0xde */, 0 /* 0xdf */, 0 /* 0xe0 */, +- 0 /* 0xe1 */, 0 /* 0xe2 */, 0 /* 0xe3 */, 0 /* 0xe4 */, 0 /* 0xe5 */, +- 0 /* 0xe6 */, 0 /* 0xe7 */, 0 /* 0xe8 */, 0 /* 0xe9 */, 0 /* 0xea */, +- 0 /* 0xeb */, 0 /* 0xec */, 0 /* 0xed */, 0 /* 0xee */, 0 /* 0xef */, +- 0 /* 0xf0 */, 0 /* 0xf1 */, 0 /* 0xf2 */, 0 /* 0xf3 */, 0 /* 0xf4 */, +- 0 /* 0xf5 */, 0 /* 0xf6 */, 0 /* 0xf7 */, 0 /* 0xf8 */, 0 /* 0xf9 */, +- 0 /* 0xfa */, 0 /* 0xfb */, 0 /* 0xfc */, 0 /* 0xfd */, 0 /* 0xfe */, +- 0 /* 0xff */, +-}; +- +-static ssize_t sf_parse_string(nghttp2_sf_value *dest, const uint8_t *begin, +- const uint8_t *end) { +- const uint8_t *p = begin; +- +- if (*p++ != '"') { +- return -1; +- } +- +- for (; p != end; ++p) { +- switch (*p) { +- case '\\': +- if (++p == end) { +- return -1; +- } +- +- switch (*p) { +- case '"': +- case '\\': +- break; +- default: +- return -1; +- } +- +- break; +- case '"': +- if (dest) { +- dest->type = NGHTTP2_SF_VALUE_TYPE_STRING; +- dest->s.base = begin + 1; +- dest->s.len = (size_t)(p - dest->s.base); +- } +- +- ++p; +- +- return p - begin; +- default: +- if (!SF_DQUOTE_CHARS[*p]) { +- return -1; +- } +- } +- } +- +- return -1; +-} +- +-/* Generated by genchartbl.py */ +-static const int SF_TOKEN_CHARS[] = { +- 0 /* NUL */, 0 /* SOH */, 0 /* STX */, 0 /* ETX */, 0 /* EOT */, +- 0 /* ENQ */, 0 /* ACK */, 0 /* BEL */, 0 /* BS */, 0 /* HT */, +- 0 /* LF */, 0 /* VT */, 0 /* FF */, 0 /* CR */, 0 /* SO */, +- 0 /* SI */, 0 /* DLE */, 0 /* DC1 */, 0 /* DC2 */, 0 /* DC3 */, +- 0 /* DC4 */, 0 /* NAK */, 0 /* SYN */, 0 /* ETB */, 0 /* CAN */, +- 0 /* EM */, 0 /* SUB */, 0 /* ESC */, 0 /* FS */, 0 /* GS */, +- 0 /* RS */, 0 /* US */, 0 /* SPC */, 1 /* ! */, 0 /* " */, +- 1 /* # */, 1 /* $ */, 1 /* % */, 1 /* & */, 1 /* ' */, +- 0 /* ( */, 0 /* ) */, 1 /* * */, 1 /* + */, 0 /* , */, +- 1 /* - */, 1 /* . */, 1 /* / */, 1 /* 0 */, 1 /* 1 */, +- 1 /* 2 */, 1 /* 3 */, 1 /* 4 */, 1 /* 5 */, 1 /* 6 */, +- 1 /* 7 */, 1 /* 8 */, 1 /* 9 */, 1 /* : */, 0 /* ; */, +- 0 /* < */, 0 /* = */, 0 /* > */, 0 /* ? */, 0 /* @ */, +- 1 /* A */, 1 /* B */, 1 /* C */, 1 /* D */, 1 /* E */, +- 1 /* F */, 1 /* G */, 1 /* H */, 1 /* I */, 1 /* J */, +- 1 /* K */, 1 /* L */, 1 /* M */, 1 /* N */, 1 /* O */, +- 1 /* P */, 1 /* Q */, 1 /* R */, 1 /* S */, 1 /* T */, +- 1 /* U */, 1 /* V */, 1 /* W */, 1 /* X */, 1 /* Y */, +- 1 /* Z */, 0 /* [ */, 0 /* \ */, 0 /* ] */, 1 /* ^ */, +- 1 /* _ */, 1 /* ` */, 1 /* a */, 1 /* b */, 1 /* c */, +- 1 /* d */, 1 /* e */, 1 /* f */, 1 /* g */, 1 /* h */, +- 1 /* i */, 1 /* j */, 1 /* k */, 1 /* l */, 1 /* m */, +- 1 /* n */, 1 /* o */, 1 /* p */, 1 /* q */, 1 /* r */, +- 1 /* s */, 1 /* t */, 1 /* u */, 1 /* v */, 1 /* w */, +- 1 /* x */, 1 /* y */, 1 /* z */, 0 /* { */, 1 /* | */, +- 0 /* } */, 1 /* ~ */, 0 /* DEL */, 0 /* 0x80 */, 0 /* 0x81 */, +- 0 /* 0x82 */, 0 /* 0x83 */, 0 /* 0x84 */, 0 /* 0x85 */, 0 /* 0x86 */, +- 0 /* 0x87 */, 0 /* 0x88 */, 0 /* 0x89 */, 0 /* 0x8a */, 0 /* 0x8b */, +- 0 /* 0x8c */, 0 /* 0x8d */, 0 /* 0x8e */, 0 /* 0x8f */, 0 /* 0x90 */, +- 0 /* 0x91 */, 0 /* 0x92 */, 0 /* 0x93 */, 0 /* 0x94 */, 0 /* 0x95 */, +- 0 /* 0x96 */, 0 /* 0x97 */, 0 /* 0x98 */, 0 /* 0x99 */, 0 /* 0x9a */, +- 0 /* 0x9b */, 0 /* 0x9c */, 0 /* 0x9d */, 0 /* 0x9e */, 0 /* 0x9f */, +- 0 /* 0xa0 */, 0 /* 0xa1 */, 0 /* 0xa2 */, 0 /* 0xa3 */, 0 /* 0xa4 */, +- 0 /* 0xa5 */, 0 /* 0xa6 */, 0 /* 0xa7 */, 0 /* 0xa8 */, 0 /* 0xa9 */, +- 0 /* 0xaa */, 0 /* 0xab */, 0 /* 0xac */, 0 /* 0xad */, 0 /* 0xae */, +- 0 /* 0xaf */, 0 /* 0xb0 */, 0 /* 0xb1 */, 0 /* 0xb2 */, 0 /* 0xb3 */, +- 0 /* 0xb4 */, 0 /* 0xb5 */, 0 /* 0xb6 */, 0 /* 0xb7 */, 0 /* 0xb8 */, +- 0 /* 0xb9 */, 0 /* 0xba */, 0 /* 0xbb */, 0 /* 0xbc */, 0 /* 0xbd */, +- 0 /* 0xbe */, 0 /* 0xbf */, 0 /* 0xc0 */, 0 /* 0xc1 */, 0 /* 0xc2 */, +- 0 /* 0xc3 */, 0 /* 0xc4 */, 0 /* 0xc5 */, 0 /* 0xc6 */, 0 /* 0xc7 */, +- 0 /* 0xc8 */, 0 /* 0xc9 */, 0 /* 0xca */, 0 /* 0xcb */, 0 /* 0xcc */, +- 0 /* 0xcd */, 0 /* 0xce */, 0 /* 0xcf */, 0 /* 0xd0 */, 0 /* 0xd1 */, +- 0 /* 0xd2 */, 0 /* 0xd3 */, 0 /* 0xd4 */, 0 /* 0xd5 */, 0 /* 0xd6 */, +- 0 /* 0xd7 */, 0 /* 0xd8 */, 0 /* 0xd9 */, 0 /* 0xda */, 0 /* 0xdb */, +- 0 /* 0xdc */, 0 /* 0xdd */, 0 /* 0xde */, 0 /* 0xdf */, 0 /* 0xe0 */, +- 0 /* 0xe1 */, 0 /* 0xe2 */, 0 /* 0xe3 */, 0 /* 0xe4 */, 0 /* 0xe5 */, +- 0 /* 0xe6 */, 0 /* 0xe7 */, 0 /* 0xe8 */, 0 /* 0xe9 */, 0 /* 0xea */, +- 0 /* 0xeb */, 0 /* 0xec */, 0 /* 0xed */, 0 /* 0xee */, 0 /* 0xef */, +- 0 /* 0xf0 */, 0 /* 0xf1 */, 0 /* 0xf2 */, 0 /* 0xf3 */, 0 /* 0xf4 */, +- 0 /* 0xf5 */, 0 /* 0xf6 */, 0 /* 0xf7 */, 0 /* 0xf8 */, 0 /* 0xf9 */, +- 0 /* 0xfa */, 0 /* 0xfb */, 0 /* 0xfc */, 0 /* 0xfd */, 0 /* 0xfe */, +- 0 /* 0xff */, +-}; +- +-static ssize_t sf_parse_token(nghttp2_sf_value *dest, const uint8_t *begin, +- const uint8_t *end) { +- const uint8_t *p = begin; +- +- if ((*p < 'A' || 'Z' < *p) && (*p < 'a' || 'z' < *p) && *p != '*') { +- return -1; +- } +- +- for (; p != end && SF_TOKEN_CHARS[*p]; ++p) +- ; +- +- if (dest) { +- dest->type = NGHTTP2_SF_VALUE_TYPE_TOKEN; +- dest->s.base = begin; +- dest->s.len = (size_t)(p - begin); +- } +- +- return p - begin; +-} +- +-/* Generated by genchartbl.py */ +-static const int SF_BYTESEQ_CHARS[] = { +- 0 /* NUL */, 0 /* SOH */, 0 /* STX */, 0 /* ETX */, 0 /* EOT */, +- 0 /* ENQ */, 0 /* ACK */, 0 /* BEL */, 0 /* BS */, 0 /* HT */, +- 0 /* LF */, 0 /* VT */, 0 /* FF */, 0 /* CR */, 0 /* SO */, +- 0 /* SI */, 0 /* DLE */, 0 /* DC1 */, 0 /* DC2 */, 0 /* DC3 */, +- 0 /* DC4 */, 0 /* NAK */, 0 /* SYN */, 0 /* ETB */, 0 /* CAN */, +- 0 /* EM */, 0 /* SUB */, 0 /* ESC */, 0 /* FS */, 0 /* GS */, +- 0 /* RS */, 0 /* US */, 0 /* SPC */, 0 /* ! */, 0 /* " */, +- 0 /* # */, 0 /* $ */, 0 /* % */, 0 /* & */, 0 /* ' */, +- 0 /* ( */, 0 /* ) */, 0 /* * */, 1 /* + */, 0 /* , */, +- 0 /* - */, 0 /* . */, 1 /* / */, 1 /* 0 */, 1 /* 1 */, +- 1 /* 2 */, 1 /* 3 */, 1 /* 4 */, 1 /* 5 */, 1 /* 6 */, +- 1 /* 7 */, 1 /* 8 */, 1 /* 9 */, 0 /* : */, 0 /* ; */, +- 0 /* < */, 1 /* = */, 0 /* > */, 0 /* ? */, 0 /* @ */, +- 1 /* A */, 1 /* B */, 1 /* C */, 1 /* D */, 1 /* E */, +- 1 /* F */, 1 /* G */, 1 /* H */, 1 /* I */, 1 /* J */, +- 1 /* K */, 1 /* L */, 1 /* M */, 1 /* N */, 1 /* O */, +- 1 /* P */, 1 /* Q */, 1 /* R */, 1 /* S */, 1 /* T */, +- 1 /* U */, 1 /* V */, 1 /* W */, 1 /* X */, 1 /* Y */, +- 1 /* Z */, 0 /* [ */, 0 /* \ */, 0 /* ] */, 0 /* ^ */, +- 0 /* _ */, 0 /* ` */, 1 /* a */, 1 /* b */, 1 /* c */, +- 1 /* d */, 1 /* e */, 1 /* f */, 1 /* g */, 1 /* h */, +- 1 /* i */, 1 /* j */, 1 /* k */, 1 /* l */, 1 /* m */, +- 1 /* n */, 1 /* o */, 1 /* p */, 1 /* q */, 1 /* r */, +- 1 /* s */, 1 /* t */, 1 /* u */, 1 /* v */, 1 /* w */, +- 1 /* x */, 1 /* y */, 1 /* z */, 0 /* { */, 0 /* | */, +- 0 /* } */, 0 /* ~ */, 0 /* DEL */, 0 /* 0x80 */, 0 /* 0x81 */, +- 0 /* 0x82 */, 0 /* 0x83 */, 0 /* 0x84 */, 0 /* 0x85 */, 0 /* 0x86 */, +- 0 /* 0x87 */, 0 /* 0x88 */, 0 /* 0x89 */, 0 /* 0x8a */, 0 /* 0x8b */, +- 0 /* 0x8c */, 0 /* 0x8d */, 0 /* 0x8e */, 0 /* 0x8f */, 0 /* 0x90 */, +- 0 /* 0x91 */, 0 /* 0x92 */, 0 /* 0x93 */, 0 /* 0x94 */, 0 /* 0x95 */, +- 0 /* 0x96 */, 0 /* 0x97 */, 0 /* 0x98 */, 0 /* 0x99 */, 0 /* 0x9a */, +- 0 /* 0x9b */, 0 /* 0x9c */, 0 /* 0x9d */, 0 /* 0x9e */, 0 /* 0x9f */, +- 0 /* 0xa0 */, 0 /* 0xa1 */, 0 /* 0xa2 */, 0 /* 0xa3 */, 0 /* 0xa4 */, +- 0 /* 0xa5 */, 0 /* 0xa6 */, 0 /* 0xa7 */, 0 /* 0xa8 */, 0 /* 0xa9 */, +- 0 /* 0xaa */, 0 /* 0xab */, 0 /* 0xac */, 0 /* 0xad */, 0 /* 0xae */, +- 0 /* 0xaf */, 0 /* 0xb0 */, 0 /* 0xb1 */, 0 /* 0xb2 */, 0 /* 0xb3 */, +- 0 /* 0xb4 */, 0 /* 0xb5 */, 0 /* 0xb6 */, 0 /* 0xb7 */, 0 /* 0xb8 */, +- 0 /* 0xb9 */, 0 /* 0xba */, 0 /* 0xbb */, 0 /* 0xbc */, 0 /* 0xbd */, +- 0 /* 0xbe */, 0 /* 0xbf */, 0 /* 0xc0 */, 0 /* 0xc1 */, 0 /* 0xc2 */, +- 0 /* 0xc3 */, 0 /* 0xc4 */, 0 /* 0xc5 */, 0 /* 0xc6 */, 0 /* 0xc7 */, +- 0 /* 0xc8 */, 0 /* 0xc9 */, 0 /* 0xca */, 0 /* 0xcb */, 0 /* 0xcc */, +- 0 /* 0xcd */, 0 /* 0xce */, 0 /* 0xcf */, 0 /* 0xd0 */, 0 /* 0xd1 */, +- 0 /* 0xd2 */, 0 /* 0xd3 */, 0 /* 0xd4 */, 0 /* 0xd5 */, 0 /* 0xd6 */, +- 0 /* 0xd7 */, 0 /* 0xd8 */, 0 /* 0xd9 */, 0 /* 0xda */, 0 /* 0xdb */, +- 0 /* 0xdc */, 0 /* 0xdd */, 0 /* 0xde */, 0 /* 0xdf */, 0 /* 0xe0 */, +- 0 /* 0xe1 */, 0 /* 0xe2 */, 0 /* 0xe3 */, 0 /* 0xe4 */, 0 /* 0xe5 */, +- 0 /* 0xe6 */, 0 /* 0xe7 */, 0 /* 0xe8 */, 0 /* 0xe9 */, 0 /* 0xea */, +- 0 /* 0xeb */, 0 /* 0xec */, 0 /* 0xed */, 0 /* 0xee */, 0 /* 0xef */, +- 0 /* 0xf0 */, 0 /* 0xf1 */, 0 /* 0xf2 */, 0 /* 0xf3 */, 0 /* 0xf4 */, +- 0 /* 0xf5 */, 0 /* 0xf6 */, 0 /* 0xf7 */, 0 /* 0xf8 */, 0 /* 0xf9 */, +- 0 /* 0xfa */, 0 /* 0xfb */, 0 /* 0xfc */, 0 /* 0xfd */, 0 /* 0xfe */, +- 0 /* 0xff */, +-}; +- +-static ssize_t sf_parse_byteseq(nghttp2_sf_value *dest, const uint8_t *begin, +- const uint8_t *end) { +- const uint8_t *p = begin; +- +- if (*p++ != ':') { +- return -1; +- } +- +- for (; p != end; ++p) { +- switch (*p) { +- case ':': +- if (dest) { +- dest->type = NGHTTP2_SF_VALUE_TYPE_BYTESEQ; +- dest->s.base = begin + 1; +- dest->s.len = (size_t)(p - dest->s.base); +- } +- +- ++p; +- +- return p - begin; +- default: +- if (!SF_BYTESEQ_CHARS[*p]) { +- return -1; +- } +- } +- } +- +- return -1; +-} +- +-static ssize_t sf_parse_boolean(nghttp2_sf_value *dest, const uint8_t *begin, +- const uint8_t *end) { +- const uint8_t *p = begin; +- int b; +- +- if (*p++ != '?') { +- return -1; +- } +- +- if (p == end) { +- return -1; +- } +- +- switch (*p++) { +- case '0': +- b = 0; +- break; +- case '1': +- b = 1; +- break; +- default: +- return -1; +- } +- +- if (dest) { +- dest->type = NGHTTP2_SF_VALUE_TYPE_BOOLEAN; +- dest->b = b; +- } +- +- return p - begin; +-} +- +-static ssize_t sf_parse_bare_item(nghttp2_sf_value *dest, const uint8_t *begin, +- const uint8_t *end) { +- switch (*begin) { +- case '-': +- case '0': +- case '1': +- case '2': +- case '3': +- case '4': +- case '5': +- case '6': +- case '7': +- case '8': +- case '9': +- return sf_parse_integer_or_decimal(dest, begin, end); +- case '"': +- return sf_parse_string(dest, begin, end); +- case '*': +- return sf_parse_token(dest, begin, end); +- case ':': +- return sf_parse_byteseq(dest, begin, end); +- case '?': +- return sf_parse_boolean(dest, begin, end); +- default: +- if (('A' <= *begin && *begin <= 'Z') || ('a' <= *begin && *begin <= 'z')) { +- return sf_parse_token(dest, begin, end); +- } +- return -1; +- } +-} +- +-#define sf_discard_sp_end_err(BEGIN, END, ERR) \ +- for (;; ++(BEGIN)) { \ +- if ((BEGIN) == (END)) { \ +- return (ERR); \ +- } \ +- if (*(BEGIN) != ' ') { \ +- break; \ +- } \ +- } +- +-static ssize_t sf_parse_params(const uint8_t *begin, const uint8_t *end) { +- const uint8_t *p = begin; +- ssize_t slen; +- +- for (; p != end && *p == ';';) { +- ++p; +- +- sf_discard_sp_end_err(p, end, -1); +- +- slen = sf_parse_key(p, end); +- if (slen < 0) { +- return -1; +- } +- +- p += slen; +- +- if (p == end || *p != '=') { +- /* Boolean true */ +- } else if (++p == end) { +- return -1; +- } else { +- slen = sf_parse_bare_item(NULL, p, end); +- if (slen < 0) { +- return -1; +- } +- +- p += slen; +- } +- } +- +- return p - begin; +-} +- +-static ssize_t sf_parse_item(nghttp2_sf_value *dest, const uint8_t *begin, +- const uint8_t *end) { +- const uint8_t *p = begin; +- ssize_t slen; +- +- slen = sf_parse_bare_item(dest, p, end); +- if (slen < 0) { +- return -1; +- } +- +- p += slen; +- +- slen = sf_parse_params(p, end); +- if (slen < 0) { +- return -1; +- } +- +- p += slen; +- +- return p - begin; +-} +- +-ssize_t nghttp2_sf_parse_item(nghttp2_sf_value *dest, const uint8_t *begin, +- const uint8_t *end) { +- return sf_parse_item(dest, begin, end); +-} +- +-static ssize_t sf_parse_inner_list(nghttp2_sf_value *dest, const uint8_t *begin, +- const uint8_t *end) { +- const uint8_t *p = begin; +- ssize_t slen; +- +- if (*p++ != '(') { +- return -1; +- } +- +- for (;;) { +- sf_discard_sp_end_err(p, end, -1); +- +- if (*p == ')') { +- ++p; +- +- slen = sf_parse_params(p, end); +- if (slen < 0) { +- return -1; +- } +- +- p += slen; +- +- if (dest) { +- dest->type = NGHTTP2_SF_VALUE_TYPE_INNER_LIST; +- } +- +- return p - begin; +- } +- +- slen = sf_parse_item(NULL, p, end); +- if (slen < 0) { +- return -1; +- } +- +- p += slen; +- +- if (p == end || (*p != ' ' && *p != ')')) { +- return -1; +- } +- } +-} +- +-ssize_t nghttp2_sf_parse_inner_list(nghttp2_sf_value *dest, +- const uint8_t *begin, const uint8_t *end) { +- return sf_parse_inner_list(dest, begin, end); +-} +- +-static ssize_t sf_parse_item_or_inner_list(nghttp2_sf_value *dest, +- const uint8_t *begin, +- const uint8_t *end) { +- if (*begin == '(') { +- return sf_parse_inner_list(dest, begin, end); +- } +- +- return sf_parse_item(dest, begin, end); +-} +- +-#define sf_discard_ows(BEGIN, END) \ +- for (;; ++(BEGIN)) { \ +- if ((BEGIN) == (END)) { \ +- goto fin; \ +- } \ +- if (*(BEGIN) != ' ' && *(BEGIN) != '\t') { \ +- break; \ +- } \ +- } +- +-#define sf_discard_ows_end_err(BEGIN, END, ERR) \ +- for (;; ++(BEGIN)) { \ +- if ((BEGIN) == (END)) { \ +- return (ERR); \ +- } \ +- if (*(BEGIN) != ' ' && *(BEGIN) != '\t') { \ +- break; \ +- } \ +- } +- + int nghttp2_http_parse_priority(nghttp2_extpri *dest, const uint8_t *value, + size_t valuelen) { +- const uint8_t *p = value, *end = value + valuelen; +- ssize_t slen; +- nghttp2_sf_value val; + nghttp2_extpri pri = *dest; +- const uint8_t *key; +- size_t keylen; ++ sf_parser sfp; ++ sf_vec key; ++ sf_value val; ++ int rv; ++ ++ sf_parser_init(&sfp, value, valuelen); + +- for (; p != end && *p == ' '; ++p) +- ; ++ for (;;) { ++ rv = sf_parser_dict(&sfp, &key, &val); ++ if (rv != 0) { ++ if (rv == SF_ERR_EOF) { ++ break; ++ } + +- for (; p != end;) { +- slen = sf_parse_key(p, end); +- if (slen < 0) { + return NGHTTP2_ERR_INVALID_ARGUMENT; + } + +- key = p; +- keylen = (size_t)slen; +- +- p += slen; +- +- if (p == end || *p != '=') { +- /* Boolean true */ +- val.type = NGHTTP2_SF_VALUE_TYPE_BOOLEAN; +- val.b = 1; ++ if (key.len != 1) { ++ continue; ++ } + +- slen = sf_parse_params(p, end); +- if (slen < 0) { ++ switch (key.base[0]) { ++ case 'i': ++ if (val.type != SF_TYPE_BOOLEAN) { + return NGHTTP2_ERR_INVALID_ARGUMENT; + } +- } else if (++p == end) { +- return NGHTTP2_ERR_INVALID_ARGUMENT; +- } else { +- slen = sf_parse_item_or_inner_list(&val, p, end); +- if (slen < 0) { +- return NGHTTP2_ERR_INVALID_ARGUMENT; +- } +- } +- +- p += slen; + +- if (keylen == 1) { +- switch (key[0]) { +- case 'i': +- if (val.type != NGHTTP2_SF_VALUE_TYPE_BOOLEAN) { +- return NGHTTP2_ERR_INVALID_ARGUMENT; +- } +- +- pri.inc = val.b; ++ pri.inc = val.boolean; + +- break; +- case 'u': +- if (val.type != NGHTTP2_SF_VALUE_TYPE_INTEGER || +- val.i < NGHTTP2_EXTPRI_URGENCY_HIGH || +- NGHTTP2_EXTPRI_URGENCY_LOW < val.i) { +- return NGHTTP2_ERR_INVALID_ARGUMENT; +- } +- +- pri.urgency = (uint32_t)val.i; +- +- break; ++ 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; + } +- } + +- sf_discard_ows(p, end); ++ pri.urgency = (uint32_t)val.integer; + +- if (*p++ != ',') { +- return NGHTTP2_ERR_INVALID_ARGUMENT; ++ break; + } +- +- sf_discard_ows_end_err(p, end, NGHTTP2_ERR_INVALID_ARGUMENT); + } + +-fin: + *dest = pri; + + return 0; +diff --git a/deps/nghttp2/lib/nghttp2_http.h b/deps/nghttp2/lib/nghttp2_http.h +index 0c3a78eeefab7..d9992fe690830 100644 +--- a/deps/nghttp2/lib/nghttp2_http.h ++++ b/deps/nghttp2/lib/nghttp2_http.h +@@ -94,54 +94,6 @@ int nghttp2_http_on_data_chunk(nghttp2_stream *stream, size_t n); + void nghttp2_http_record_request_method(nghttp2_stream *stream, + nghttp2_frame *frame); + +-/* +- * RFC 8941 Structured Field Values. +- */ +-typedef enum nghttp2_sf_value_type { +- NGHTTP2_SF_VALUE_TYPE_BOOLEAN, +- NGHTTP2_SF_VALUE_TYPE_INTEGER, +- NGHTTP2_SF_VALUE_TYPE_DECIMAL, +- NGHTTP2_SF_VALUE_TYPE_STRING, +- NGHTTP2_SF_VALUE_TYPE_TOKEN, +- NGHTTP2_SF_VALUE_TYPE_BYTESEQ, +- NGHTTP2_SF_VALUE_TYPE_INNER_LIST, +-} nghttp2_sf_value_type; +- +-/* +- * nghttp2_sf_value stores Structured Field Values item. For Inner +- * List, only type is set to NGHTTP2_SF_VALUE_TYPE_INNER_LIST. +- */ +-typedef struct nghttp2_sf_value { +- uint8_t type; +- union { +- int b; +- int64_t i; +- double d; +- struct { +- const uint8_t *base; +- size_t len; +- } s; +- }; +-} nghttp2_sf_value; +- +-/* +- * nghttp2_sf_parse_item parses the input sequence [|begin|, |end|) +- * and stores the parsed an Item in |dest|. It returns the number of +- * bytes consumed if it succeeds, or -1. This function is declared +- * here for unit tests. +- */ +-ssize_t nghttp2_sf_parse_item(nghttp2_sf_value *dest, const uint8_t *begin, +- const uint8_t *end); +- +-/* +- * nghttp2_sf_parse_inner_list parses the input sequence [|begin|, |end|) +- * and stores the parsed an Inner List in |dest|. It returns the number of +- * bytes consumed if it succeeds, or -1. This function is declared +- * here for unit tests. +- */ +-ssize_t nghttp2_sf_parse_inner_list(nghttp2_sf_value *dest, +- const uint8_t *begin, const uint8_t *end); +- + int nghttp2_http_parse_priority(nghttp2_extpri *dest, const uint8_t *value, + size_t valuelen); + +diff --git a/deps/nghttp2/lib/nghttp2_map.c b/deps/nghttp2/lib/nghttp2_map.c +index e5db168ca2bc3..5f63fc2bb87e9 100644 +--- a/deps/nghttp2/lib/nghttp2_map.c ++++ b/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, int (*func)(void *data, void *ptr), + 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, nghttp2_map_key_type key, void *data) { + + /* 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, nghttp2_map_key_type key, void *data) { + } + + 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, nghttp2_map_key_type key) { + } + + 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, nghttp2_map_key_type key) { + } + + void nghttp2_map_clear(nghttp2_map *map) { ++ if (map->tablelen == 0) { ++ return; ++ } ++ + memset(map->table, 0, sizeof(*map->table) * map->tablelen); + map->size = 0; + } +diff --git a/deps/nghttp2/lib/nghttp2_map.h b/deps/nghttp2/lib/nghttp2_map.h +index 1419a09a35b10..d90245aab74c9 100644 +--- a/deps/nghttp2/lib/nghttp2_map.h ++++ b/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 +diff --git a/deps/nghttp2/lib/nghttp2_session.c b/deps/nghttp2/lib/nghttp2_session.c +index 93f3f07cf782b..7509ceb5c6a59 100644 +--- a/deps/nghttp2/lib/nghttp2_session.c ++++ b/deps/nghttp2/lib/nghttp2_session.c +@@ -584,10 +584,6 @@ static int session_new(nghttp2_session **session_ptr, + 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) / +@@ -605,6 +601,8 @@ static int session_new(nghttp2_session **session_ptr, + goto fail_aob_framebuf; + } + ++ nghttp2_map_init(&(*session_ptr)->streams, mem); ++ + active_outbound_item_reset(&(*session_ptr)->aob, mem); + + (*session_ptr)->callbacks = *callbacks; +@@ -637,8 +635,6 @@ static int session_new(nghttp2_session **session_ptr, + 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); +@@ -5931,7 +5927,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, + in += readlen; + + if (nghttp2_buf_mark_avail(&iframe->sbuf)) { +- return in - first; ++ return (ssize_t)(in - first); + } + + if (iframe->sbuf.pos[3] != NGHTTP2_SETTINGS || +@@ -5968,7 +5964,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, + 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); +@@ -6468,7 +6464,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, + 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) { +@@ -6772,7 +6768,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, + in += hd_proclen; + iframe->payloadleft -= hd_proclen; + +- return in - first; ++ return (ssize_t)(in - first); + } + + if (rv == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) { +@@ -6963,7 +6959,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, + 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); +@@ -7021,7 +7017,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, + 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 */ +@@ -7171,7 +7167,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, + 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)) { +@@ -7351,7 +7347,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, + + assert(in == last); + +- return in - first; ++ return (ssize_t)(in - first); + } + + int nghttp2_session_recv(nghttp2_session *session) { +diff --git a/deps/nghttp2/lib/sfparse.c b/deps/nghttp2/lib/sfparse.c +new file mode 100644 +index 0000000000000..efa2850c9d661 +--- /dev/null ++++ b/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 ++#include ++#include ++ ++#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); ++} +diff --git a/deps/nghttp2/lib/sfparse.h b/deps/nghttp2/lib/sfparse.h +new file mode 100644 +index 0000000000000..1474db1429ace +--- /dev/null ++++ b/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 ++#else /* !defined(_MSC_VER) || (_MSC_VER >= 1800) */ ++# include ++#endif /* !defined(_MSC_VER) || (_MSC_VER >= 1800) */ ++#include ++#include ++ ++/** ++ * @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_* `. ++ */ ++ 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 ` == 0, :member:`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 ` 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 ++ * ` == 0. ++ * ++ * This function sets the length of unescaped string to ++ * :member:`dest->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 ` must point to the buffer that ++ * has sufficient space to store the decoded byte string. ++ * ++ * If :member:`src->len ` == 0, |*src| is assigned to ++ * |*dest|. ++ * ++ * This function sets the length of decoded byte string to ++ * :member:`dest->len `. ++ */ ++void sf_base64decode(sf_vec *dest, const sf_vec *src); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* SFPARSE_H */ +diff --git a/deps/nghttp2/nghttp2.gyp b/deps/nghttp2/nghttp2.gyp +index c4a18650efe78..8a3ee0dbc4e2e 100644 +--- a/deps/nghttp2/nghttp2.gyp ++++ b/deps/nghttp2/nghttp2.gyp +@@ -1,4 +1,32 @@ + { ++ '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_rcbuf.c', ++ 'lib/nghttp2_session.c', ++ 'lib/nghttp2_stream.c', ++ 'lib/nghttp2_submit.c', ++ 'lib/nghttp2_version.c', ++ 'lib/sfparse.c', ++ ] ++ }, + 'target_defaults': { + 'defines': [ + '_U_=' +@@ -35,29 +63,7 @@ + 'include_dirs': [ 'lib/includes' ] + }, + '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_rcbuf.c', +- 'lib/nghttp2_session.c', +- 'lib/nghttp2_stream.c', +- 'lib/nghttp2_submit.c', +- 'lib/nghttp2_version.c' ++ '<@(nghttp2_sources)', + ] + } + ] + +From 3902f5d235709d5974f09f05274fba03d5efb499 Mon Sep 17 00:00:00 2001 +From: "Node.js GitHub Bot" +Date: Fri, 14 Jul 2023 10:37:47 +0100 +Subject: [PATCH 3/6] deps: update nghttp2 to 1.55.0 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +PR-URL: https://github.com/nodejs/node/pull/48746 +Reviewed-By: Luigi Pinca +Reviewed-By: Michaël Zasso +Reviewed-By: Rafael Gonzaga +Reviewed-By: Marco Ippolito +Reviewed-By: Yagiz Nizipli +Reviewed-By: Trivikram Kamat +--- + deps/nghttp2/lib/Makefile.in | 4 ++-- + deps/nghttp2/lib/includes/Makefile.in | 4 ++-- + deps/nghttp2/lib/includes/nghttp2/nghttp2ver.h | 4 ++-- + 3 files changed, 6 insertions(+), 6 deletions(-) + +diff --git a/deps/nghttp2/lib/Makefile.in b/deps/nghttp2/lib/Makefile.in +index 7c07e0c83a0fa..24a6cc468ed77 100644 +--- a/deps/nghttp2/lib/Makefile.in ++++ b/deps/nghttp2/lib/Makefile.in +@@ -356,8 +356,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@ +diff --git a/deps/nghttp2/lib/includes/Makefile.in b/deps/nghttp2/lib/includes/Makefile.in +index 18b45672406fe..3de90d7bef3e3 100644 +--- a/deps/nghttp2/lib/includes/Makefile.in ++++ b/deps/nghttp2/lib/includes/Makefile.in +@@ -263,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@ +diff --git a/deps/nghttp2/lib/includes/nghttp2/nghttp2ver.h b/deps/nghttp2/lib/includes/nghttp2/nghttp2ver.h +index 46e7004be2c60..5dea3ffe100b4 100644 +--- a/deps/nghttp2/lib/includes/nghttp2/nghttp2ver.h ++++ b/deps/nghttp2/lib/includes/nghttp2/nghttp2ver.h +@@ -29,7 +29,7 @@ + * @macro + * Version number of the nghttp2 library release + */ +-#define NGHTTP2_VERSION "1.53.0" ++#define NGHTTP2_VERSION "1.55.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 0x013500 ++#define NGHTTP2_VERSION_NUM 0x013700 + + #endif /* NGHTTP2VER_H */ + +From dd75e44f2f4900f0dfd29a79e19e117266d88a5a Mon Sep 17 00:00:00 2001 +From: "Node.js GitHub Bot" +Date: Mon, 17 Jul 2023 18:54:55 +0100 +Subject: [PATCH 4/6] deps: update nghttp2 to 1.55.1 + +PR-URL: https://github.com/nodejs/node/pull/48790 +Reviewed-By: Luigi Pinca +Reviewed-By: Yongsheng Zhang +Reviewed-By: Stephen Belanger +Reviewed-By: Rafael Gonzaga +Reviewed-By: Yagiz Nizipli +--- + deps/nghttp2/lib/includes/nghttp2/nghttp2ver.h | 4 ++-- + deps/nghttp2/lib/nghttp2_session.c | 10 +++++----- + 2 files changed, 7 insertions(+), 7 deletions(-) + +diff --git a/deps/nghttp2/lib/includes/nghttp2/nghttp2ver.h b/deps/nghttp2/lib/includes/nghttp2/nghttp2ver.h +index 5dea3ffe100b4..fba310c7888d0 100644 +--- a/deps/nghttp2/lib/includes/nghttp2/nghttp2ver.h ++++ b/deps/nghttp2/lib/includes/nghttp2/nghttp2ver.h +@@ -29,7 +29,7 @@ + * @macro + * Version number of the nghttp2 library release + */ +-#define NGHTTP2_VERSION "1.55.0" ++#define NGHTTP2_VERSION "1.55.1" + + /** + * @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 0x013700 ++#define NGHTTP2_VERSION_NUM 0x013701 + + #endif /* NGHTTP2VER_H */ +diff --git a/deps/nghttp2/lib/nghttp2_session.c b/deps/nghttp2/lib/nghttp2_session.c +index 7509ceb5c6a59..71858a39e07db 100644 +--- a/deps/nghttp2/lib/nghttp2_session.c ++++ b/deps/nghttp2/lib/nghttp2_session.c +@@ -3296,6 +3296,7 @@ static ssize_t nghttp2_session_mem_send_internal(nghttp2_session *session, + 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)); +@@ -3338,19 +3339,18 @@ static ssize_t nghttp2_session_mem_send_internal(nghttp2_session *session, + } + 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. */ + +From 8a10c6e9db9bd01055542095e710ec6ae9ede64c Mon Sep 17 00:00:00 2001 +From: "Node.js GitHub Bot" +Date: Sun, 17 Sep 2023 19:22:51 +0100 +Subject: [PATCH 5/6] deps: update nghttp2 to 1.56.0 + +PR-URL: https://github.com/nodejs/node/pull/49582 +Reviewed-By: Luigi Pinca +--- + .../nghttp2/lib/includes/nghttp2/nghttp2ver.h | 4 +- + deps/nghttp2/lib/nghttp2_frame.c | 49 ++---- + deps/nghttp2/lib/nghttp2_frame.h | 62 ++----- + deps/nghttp2/lib/nghttp2_session.c | 164 ++++-------------- + deps/nghttp2/lib/nghttp2_stream.c | 16 +- + deps/nghttp2/lib/nghttp2_stream.h | 16 +- + 6 files changed, 80 insertions(+), 231 deletions(-) + +diff --git a/deps/nghttp2/lib/includes/nghttp2/nghttp2ver.h b/deps/nghttp2/lib/includes/nghttp2/nghttp2ver.h +index fba310c7888d0..7f5251a6243e4 100644 +--- a/deps/nghttp2/lib/includes/nghttp2/nghttp2ver.h ++++ b/deps/nghttp2/lib/includes/nghttp2/nghttp2ver.h +@@ -29,7 +29,7 @@ + * @macro + * Version number of the nghttp2 library release + */ +-#define NGHTTP2_VERSION "1.55.1" ++#define NGHTTP2_VERSION "1.56.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 0x013701 ++#define NGHTTP2_VERSION_NUM 0x013800 + + #endif /* NGHTTP2VER_H */ +diff --git a/deps/nghttp2/lib/nghttp2_frame.c b/deps/nghttp2/lib/nghttp2_frame.c +index 35072c15fc18e..77cb463df5441 100644 +--- a/deps/nghttp2/lib/nghttp2_frame.c ++++ b/deps/nghttp2/lib/nghttp2_frame.c +@@ -418,8 +418,8 @@ void nghttp2_frame_unpack_priority_spec(nghttp2_priority_spec *pri_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 { +@@ -428,11 +428,9 @@ int nghttp2_frame_unpack_headers_payload(nghttp2_headers *frame, + + 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); +@@ -448,8 +446,6 @@ int nghttp2_frame_pack_priority(nghttp2_bufs *bufs, nghttp2_priority *frame) { + 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, +@@ -457,8 +453,8 @@ void nghttp2_frame_unpack_priority_payload(nghttp2_priority *frame, + 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); +@@ -473,8 +469,6 @@ int nghttp2_frame_pack_rst_stream(nghttp2_bufs *bufs, + + nghttp2_put_uint32be(buf->last, frame->error_code); + buf->last += 4; +- +- return 0; + } + + void nghttp2_frame_unpack_rst_stream_payload(nghttp2_rst_stream *frame, +@@ -592,16 +586,15 @@ int nghttp2_frame_pack_push_promise(nghttp2_bufs *bufs, + 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); +@@ -616,8 +609,6 @@ int nghttp2_frame_pack_ping(nghttp2_bufs *bufs, nghttp2_ping *frame) { + + buf->last = + nghttp2_cpymem(buf->last, frame->opaque_data, sizeof(frame->opaque_data)); +- +- return 0; + } + + void nghttp2_frame_unpack_ping_payload(nghttp2_ping *frame, +@@ -697,8 +688,8 @@ int nghttp2_frame_unpack_goaway_payload2(nghttp2_goaway *frame, + 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); +@@ -713,8 +704,6 @@ int nghttp2_frame_pack_window_update(nghttp2_bufs *bufs, + + 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, +@@ -723,7 +712,7 @@ void nghttp2_frame_unpack_window_update_payload(nghttp2_window_update *frame, + 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; +@@ -752,8 +741,6 @@ int nghttp2_frame_pack_altsvc(nghttp2_bufs *bufs, nghttp2_extension *frame) { + 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, +@@ -901,8 +888,8 @@ int nghttp2_frame_unpack_origin_payload(nghttp2_extension *frame, + return 0; + } + +-int nghttp2_frame_pack_priority_update(nghttp2_bufs *bufs, +- nghttp2_extension *frame) { ++void nghttp2_frame_pack_priority_update(nghttp2_bufs *bufs, ++ nghttp2_extension *frame) { + int rv; + nghttp2_buf *buf; + nghttp2_ext_priority_update *priority_update; +@@ -927,8 +914,6 @@ int nghttp2_frame_pack_priority_update(nghttp2_bufs *bufs, + priority_update->field_value_len); + + assert(rv == 0); +- +- return 0; + } + + void nghttp2_frame_unpack_priority_update_payload(nghttp2_extension *frame, +@@ -1186,14 +1171,14 @@ static void frame_set_pad(nghttp2_buf *buf, size_t padlen, int framehd_only) { + 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; + } + + /* +@@ -1226,6 +1211,4 @@ int nghttp2_frame_add_pad(nghttp2_bufs *bufs, nghttp2_frame_hd *hd, + hd->flags |= NGHTTP2_FLAG_PADDED; + + DEBUGF("send: final payloadlen=%zu, padlen=%zu\n", hd->length, padlen); +- +- return 0; + } +diff --git a/deps/nghttp2/lib/nghttp2_frame.h b/deps/nghttp2/lib/nghttp2_frame.h +index 5f6152b74587a..d58668806c432 100644 +--- a/deps/nghttp2/lib/nghttp2_frame.h ++++ b/deps/nghttp2/lib/nghttp2_frame.h +@@ -143,11 +143,9 @@ int nghttp2_frame_pack_headers(nghttp2_bufs *bufs, nghttp2_headers *frame, + * 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 +@@ -155,10 +153,8 @@ int nghttp2_frame_unpack_headers_payload(nghttp2_headers *frame, + * + * 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|. +@@ -172,11 +168,9 @@ void nghttp2_frame_unpack_priority_payload(nghttp2_priority *frame, + * + * 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|. +@@ -265,15 +259,9 @@ int nghttp2_frame_pack_push_promise(nghttp2_bufs *bufs, + * 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 +@@ -281,10 +269,8 @@ int nghttp2_frame_unpack_push_promise_payload(nghttp2_push_promise *frame, + * + * 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|. +@@ -343,11 +329,9 @@ int nghttp2_frame_unpack_goaway_payload2(nghttp2_goaway *frame, + * + * 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|. +@@ -361,17 +345,13 @@ void nghttp2_frame_unpack_window_update_payload(nghttp2_window_update *frame, + * + * 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, +@@ -431,19 +411,15 @@ int nghttp2_frame_unpack_origin_payload(nghttp2_extension *frame, + * + * 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_update(nghttp2_bufs *bufs, +- nghttp2_extension *ext); ++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. +- * +- * This function always succeeds and returns 0. + */ + void nghttp2_frame_unpack_priority_update_payload(nghttp2_extension *frame, + uint8_t *payload, +@@ -654,16 +630,8 @@ int nghttp2_iv_check(const nghttp2_settings_entry *iv, size_t niv); + * |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 */ +diff --git a/deps/nghttp2/lib/nghttp2_session.c b/deps/nghttp2/lib/nghttp2_session.c +index 71858a39e07db..a45cbeef67310 100644 +--- a/deps/nghttp2/lib/nghttp2_session.c ++++ b/deps/nghttp2/lib/nghttp2_session.c +@@ -937,8 +937,8 @@ static int session_ob_data_push(nghttp2_session *session, + return 0; + } + +-static int session_ob_data_remove(nghttp2_session *session, +- nghttp2_stream *stream) { ++static void session_ob_data_remove(nghttp2_session *session, ++ nghttp2_stream *stream) { + uint32_t urgency; + + assert(stream->flags & NGHTTP2_STREAM_FLAG_NO_RFC7540_PRIORITIES); +@@ -951,8 +951,6 @@ static int session_ob_data_remove(nghttp2_session *session, + nghttp2_pq_remove(&session->sched[urgency].ob_data, &stream->pq_entry); + + stream->queued = 0; +- +- return 0; + } + + static int session_attach_stream_item(nghttp2_session *session, +@@ -972,38 +970,28 @@ static int session_attach_stream_item(nghttp2_session *session, + return session_ob_data_push(session, stream); + } + +-static int session_detach_stream_item(nghttp2_session *session, +- nghttp2_stream *stream) { +- int rv; +- +- rv = nghttp2_stream_detach_item(stream); +- if (rv != 0) { +- return rv; +- } ++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 0; ++ return; + } + +- return session_ob_data_remove(session, stream); ++ session_ob_data_remove(session, stream); + } + +-static int session_defer_stream_item(nghttp2_session *session, +- nghttp2_stream *stream, uint8_t flags) { +- int rv; +- +- rv = nghttp2_stream_defer_item(stream, flags); +- if (rv != 0) { +- return rv; +- } ++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 0; ++ return; + } + +- return session_ob_data_remove(session, stream); ++ session_ob_data_remove(session, stream); + } + + static int session_resume_deferred_stream_item(nghttp2_session *session, +@@ -1476,11 +1464,7 @@ int nghttp2_session_close_stream(nghttp2_session *session, int32_t stream_id, + + item = stream->item; + +- rv = session_detach_stream_item(session, 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 +@@ -2221,7 +2205,6 @@ static ssize_t session_call_select_padding(nghttp2_session *session, + 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; +@@ -2246,11 +2229,7 @@ static int session_headers_add_pad(nghttp2_session *session, + 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; + +@@ -2333,13 +2312,7 @@ static int session_prep_frame(nghttp2_session *session, + // Search stream including closed again. + stream = nghttp2_session_get_stream_raw(session, frame->hd.stream_id); + if (stream) { +- int rv2; +- +- rv2 = session_detach_stream_item(session, stream); +- +- if (nghttp2_is_fatal(rv2)) { +- return rv2; +- } ++ session_detach_stream_item(session, stream); + } + + return rv; +@@ -2354,12 +2327,8 @@ static int session_prep_frame(nghttp2_session *session, + queue when session->remote_window_size > 0 */ + assert(session->remote_window_size > 0); + +- rv = session_defer_stream_item(session, 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); +@@ -2373,23 +2342,15 @@ static int session_prep_frame(nghttp2_session *session, + return rv; + } + if (rv == NGHTTP2_ERR_DEFERRED) { +- rv = session_defer_stream_item(session, 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 = session_detach_stream_item(session, 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); +@@ -2399,13 +2360,7 @@ static int session_prep_frame(nghttp2_session *session, + return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE; + } + if (rv != 0) { +- int rv2; +- +- rv2 = session_detach_stream_item(session, stream); +- +- if (nghttp2_is_fatal(rv2)) { +- return rv2; +- } ++ session_detach_stream_item(session, stream); + + return rv; + } +@@ -2907,10 +2862,7 @@ static int session_after_frame_sent1(nghttp2_session *session) { + } + + if (stream && aux_data->eof) { +- rv = session_detach_stream_item(session, 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 +@@ -3143,17 +3095,8 @@ static int session_after_frame_sent1(nghttp2_session *session) { + /* + * 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; +@@ -3176,13 +3119,13 @@ static int session_after_frame_sent2(nghttp2_session *session) { + 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 */ +@@ -3196,7 +3139,7 @@ static int session_after_frame_sent2(nghttp2_session *session) { + if (aux_data->eof) { + active_outbound_item_reset(aob, mem); + +- return 0; ++ return; + } + + /* Reset no_copy here because next write may not use this. */ +@@ -3208,22 +3151,18 @@ static int session_after_frame_sent2(nghttp2_session *session) { + further data. */ + if (nghttp2_session_predicate_data_send(session, stream) != 0) { + if (stream) { +- rv = session_detach_stream_item(session, 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, +@@ -3454,7 +3393,7 @@ static ssize_t nghttp2_session_mem_send_internal(nghttp2_session *session, + + /* 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) { +@@ -3462,12 +3401,7 @@ static ssize_t nghttp2_session_mem_send_internal(nghttp2_session *session, + 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; +@@ -3506,11 +3440,7 @@ static ssize_t nghttp2_session_mem_send_internal(nghttp2_session *session, + } + + if (rv == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) { +- rv = session_detach_stream_item(session, 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); +@@ -3534,11 +3464,7 @@ static ssize_t nghttp2_session_mem_send_internal(nghttp2_session *session, + 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 */ + +@@ -4424,17 +4350,12 @@ int nghttp2_session_on_headers_received(nghttp2_session *session, + } + + 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; +@@ -5097,17 +5018,11 @@ int nghttp2_session_on_push_promise_received(nghttp2_session *session, + } + + 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); + } +@@ -7808,11 +7723,8 @@ int nghttp2_session_pack_data(nghttp2_session *session, nghttp2_bufs *bufs, + + 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); + + session_reschedule_stream(session, stream); + +diff --git a/deps/nghttp2/lib/nghttp2_stream.c b/deps/nghttp2/lib/nghttp2_stream.c +index b3614a0b02761..f1951f879d792 100644 +--- a/deps/nghttp2/lib/nghttp2_stream.c ++++ b/deps/nghttp2/lib/nghttp2_stream.c +@@ -465,14 +465,12 @@ static int stream_update_dep_on_attach_item(nghttp2_stream *stream) { + 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, +@@ -503,20 +501,20 @@ int nghttp2_stream_attach_item(nghttp2_stream *stream, + 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); + + if (stream->flags & NGHTTP2_STREAM_FLAG_NO_RFC7540_PRIORITIES) { +- return 0; ++ return; + } + +- return stream_update_dep_on_detach_item(stream); ++ 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, +@@ -525,10 +523,10 @@ int nghttp2_stream_defer_item(nghttp2_stream *stream, uint8_t flags) { + stream->flags |= flags; + + if (stream->flags & NGHTTP2_STREAM_FLAG_NO_RFC7540_PRIORITIES) { +- return 0; ++ return; + } + +- return stream_update_dep_on_detach_item(stream); ++ stream_update_dep_on_detach_item(stream); + } + + int nghttp2_stream_resume_deferred_item(nghttp2_stream *stream, uint8_t flags) { +diff --git a/deps/nghttp2/lib/nghttp2_stream.h b/deps/nghttp2/lib/nghttp2_stream.h +index 7a8e4c6c1ddb0..71b9fb1140c93 100644 +--- a/deps/nghttp2/lib/nghttp2_stream.h ++++ b/deps/nghttp2/lib/nghttp2_stream.h +@@ -258,14 +258,8 @@ void nghttp2_stream_shutdown(nghttp2_stream *stream, nghttp2_shut_flag flag); + * 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| +@@ -379,14 +373,8 @@ int nghttp2_stream_attach_item(nghttp2_stream *stream, + /* + * 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 + +From e7163c78f3b78cf9e04e019cb74618abdddb02f2 Mon Sep 17 00:00:00 2001 +From: James M Snell +Date: Wed, 11 Oct 2023 10:00:54 -0700 +Subject: [PATCH 6/6] deps: update nghttp2 to 1.57.0 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +PR-URL: https://github.com/nodejs/node/pull/50121 +Reviewed-By: Matteo Collina +Reviewed-By: Michael Dawson +Reviewed-By: Rich Trott +Reviewed-By: Marco Ippolito +Reviewed-By: Tobias Nießen +--- + deps/nghttp2/lib/CMakeLists.txt | 2 + + deps/nghttp2/lib/Makefile.am | 4 + + deps/nghttp2/lib/Makefile.in | 20 ++++- + deps/nghttp2/lib/includes/nghttp2/nghttp2.h | 17 +++++ + .../nghttp2/lib/includes/nghttp2/nghttp2ver.h | 4 +- + deps/nghttp2/lib/nghttp2_option.c | 7 ++ + deps/nghttp2/lib/nghttp2_option.h | 6 ++ + deps/nghttp2/lib/nghttp2_ratelim.c | 75 +++++++++++++++++++ + deps/nghttp2/lib/nghttp2_ratelim.h | 57 ++++++++++++++ + deps/nghttp2/lib/nghttp2_session.c | 34 ++++++++- + deps/nghttp2/lib/nghttp2_session.h | 12 ++- + deps/nghttp2/lib/nghttp2_time.c | 62 +++++++++++++++ + deps/nghttp2/lib/nghttp2_time.h | 38 ++++++++++ + deps/nghttp2/nghttp2.gyp | 2 + + 14 files changed, 332 insertions(+), 8 deletions(-) + create mode 100644 deps/nghttp2/lib/nghttp2_ratelim.c + create mode 100644 deps/nghttp2/lib/nghttp2_ratelim.h + create mode 100644 deps/nghttp2/lib/nghttp2_time.c + create mode 100644 deps/nghttp2/lib/nghttp2_time.h + +diff --git a/deps/nghttp2/lib/CMakeLists.txt b/deps/nghttp2/lib/CMakeLists.txt +index fad04716ffafb..7adba3a3ffa2d 100644 +--- a/deps/nghttp2/lib/CMakeLists.txt ++++ b/deps/nghttp2/lib/CMakeLists.txt +@@ -24,6 +24,8 @@ set(NGHTTP2_SOURCES + nghttp2_http.c + nghttp2_rcbuf.c + nghttp2_extpri.c ++ nghttp2_ratelim.c ++ nghttp2_time.c + nghttp2_debug.c + sfparse.c + ) +diff --git a/deps/nghttp2/lib/Makefile.am b/deps/nghttp2/lib/Makefile.am +index cd928ae465501..c3ace4029a69b 100644 +--- a/deps/nghttp2/lib/Makefile.am ++++ b/deps/nghttp2/lib/Makefile.am +@@ -51,6 +51,8 @@ OBJECTS = nghttp2_pq.c nghttp2_map.c nghttp2_queue.c \ + nghttp2_http.c \ + nghttp2_rcbuf.c \ + nghttp2_extpri.c \ ++ nghttp2_ratelim.c \ ++ nghttp2_time.c \ + nghttp2_debug.c \ + sfparse.c + +@@ -69,6 +71,8 @@ HFILES = nghttp2_pq.h nghttp2_int.h nghttp2_map.h nghttp2_queue.h \ + nghttp2_http.h \ + nghttp2_rcbuf.h \ + nghttp2_extpri.h \ ++ nghttp2_ratelim.h \ ++ nghttp2_time.h \ + nghttp2_debug.h \ + sfparse.h + +diff --git a/deps/nghttp2/lib/Makefile.in b/deps/nghttp2/lib/Makefile.in +index 24a6cc468ed77..0b95613bc2180 100644 +--- a/deps/nghttp2/lib/Makefile.in ++++ b/deps/nghttp2/lib/Makefile.in +@@ -157,7 +157,8 @@ am__objects_2 = nghttp2_pq.lo nghttp2_map.lo nghttp2_queue.lo \ + 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_extpri.lo nghttp2_debug.lo sfparse.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@) +@@ -194,9 +195,10 @@ am__depfiles_remade = ./$(DEPDIR)/nghttp2_buf.Plo \ + ./$(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) \ +@@ -510,6 +512,8 @@ OBJECTS = nghttp2_pq.c nghttp2_map.c nghttp2_queue.c \ + nghttp2_http.c \ + nghttp2_rcbuf.c \ + nghttp2_extpri.c \ ++ nghttp2_ratelim.c \ ++ nghttp2_time.c \ + nghttp2_debug.c \ + sfparse.c + +@@ -528,6 +532,8 @@ HFILES = nghttp2_pq.h nghttp2_int.h nghttp2_map.h nghttp2_queue.h \ + nghttp2_http.h \ + nghttp2_rcbuf.h \ + nghttp2_extpri.h \ ++ nghttp2_ratelim.h \ ++ nghttp2_time.h \ + nghttp2_debug.h \ + sfparse.h + +@@ -633,10 +639,12 @@ 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 + +@@ -916,10 +924,12 @@ 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 +@@ -985,10 +995,12 @@ maintainer-clean: maintainer-clean-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 +diff --git a/deps/nghttp2/lib/includes/nghttp2/nghttp2.h b/deps/nghttp2/lib/includes/nghttp2/nghttp2.h +index 65077dd51613c..fa22081c51749 100644 +--- a/deps/nghttp2/lib/includes/nghttp2/nghttp2.h ++++ b/deps/nghttp2/lib/includes/nghttp2/nghttp2.h +@@ -2756,6 +2756,23 @@ 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 + * +diff --git a/deps/nghttp2/lib/includes/nghttp2/nghttp2ver.h b/deps/nghttp2/lib/includes/nghttp2/nghttp2ver.h +index 7f5251a6243e4..f56954e7fded4 100644 +--- a/deps/nghttp2/lib/includes/nghttp2/nghttp2ver.h ++++ b/deps/nghttp2/lib/includes/nghttp2/nghttp2ver.h +@@ -29,7 +29,7 @@ + * @macro + * Version number of the nghttp2 library release + */ +-#define NGHTTP2_VERSION "1.56.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 0x013800 ++#define NGHTTP2_VERSION_NUM 0x013900 + + #endif /* NGHTTP2VER_H */ +diff --git a/deps/nghttp2/lib/nghttp2_option.c b/deps/nghttp2/lib/nghttp2_option.c +index ee0cd0f0226db..43d4e952291ba 100644 +--- a/deps/nghttp2/lib/nghttp2_option.c ++++ b/deps/nghttp2/lib/nghttp2_option.c +@@ -143,3 +143,10 @@ void nghttp2_option_set_no_rfc9113_leading_and_trailing_ws_validation( + 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; ++} +diff --git a/deps/nghttp2/lib/nghttp2_option.h b/deps/nghttp2/lib/nghttp2_option.h +index b228a0754c989..2259e1849d810 100644 +--- a/deps/nghttp2/lib/nghttp2_option.h ++++ b/deps/nghttp2/lib/nghttp2_option.h +@@ -70,12 +70,18 @@ typedef enum { + 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; + + /** + * Struct to store option values for nghttp2_session. + */ + 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 + */ +diff --git a/deps/nghttp2/lib/nghttp2_ratelim.c b/deps/nghttp2/lib/nghttp2_ratelim.c +new file mode 100644 +index 0000000000000..7011655b006f7 +--- /dev/null ++++ b/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; ++} +diff --git a/deps/nghttp2/lib/nghttp2_ratelim.h b/deps/nghttp2/lib/nghttp2_ratelim.h +new file mode 100644 +index 0000000000000..866ed3f00aed4 +--- /dev/null ++++ b/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 ++#endif /* HAVE_CONFIG_H */ ++ ++#include ++ ++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 */ +diff --git a/deps/nghttp2/lib/nghttp2_session.c b/deps/nghttp2/lib/nghttp2_session.c +index a45cbeef67310..ec5024d0f2168 100644 +--- a/deps/nghttp2/lib/nghttp2_session.c ++++ b/deps/nghttp2/lib/nghttp2_session.c +@@ -37,6 +37,7 @@ + #include "nghttp2_http.h" + #include "nghttp2_pq.h" + #include "nghttp2_extpri.h" ++#include "nghttp2_time.h" + #include "nghttp2_debug.h" + + /* +@@ -475,6 +476,10 @@ static int session_new(nghttp2_session **session_ptr, + (*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; + } +@@ -573,6 +578,12 @@ static int session_new(nghttp2_session **session_ptr, + (*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, +@@ -4449,6 +4460,23 @@ static int session_process_priority_frame(nghttp2_session *session) { + 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; +@@ -4478,7 +4506,8 @@ int nghttp2_session_on_rst_stream_received(nghttp2_session *session, + 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) { +@@ -7434,6 +7463,9 @@ int nghttp2_session_add_goaway(nghttp2_session *session, int32_t last_stream_id, + nghttp2_mem_free(mem, item); + return rv; + } ++ ++ session->goaway_flags |= NGHTTP2_GOAWAY_SUBMITTED; ++ + return 0; + } + +diff --git a/deps/nghttp2/lib/nghttp2_session.h b/deps/nghttp2/lib/nghttp2_session.h +index 34d2d58528a79..b119329a04da4 100644 +--- a/deps/nghttp2/lib/nghttp2_session.h ++++ b/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. */ +@@ -105,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 */ +@@ -178,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 +@@ -235,6 +242,9 @@ 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; +diff --git a/deps/nghttp2/lib/nghttp2_time.c b/deps/nghttp2/lib/nghttp2_time.c +new file mode 100644 +index 0000000000000..2a5f1a6ff524d +--- /dev/null ++++ b/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 ++#endif /* HAVE_TIME_H */ ++ ++#ifdef HAVE_SYSINFOAPI_H ++# include ++#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 */ +diff --git a/deps/nghttp2/lib/nghttp2_time.h b/deps/nghttp2/lib/nghttp2_time.h +new file mode 100644 +index 0000000000000..03c0bbe944ee3 +--- /dev/null ++++ b/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 ++#endif /* HAVE_CONFIG_H */ ++ ++#include ++ ++/* 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 */ +diff --git a/deps/nghttp2/nghttp2.gyp b/deps/nghttp2/nghttp2.gyp +index 8a3ee0dbc4e2e..87909c5f296a2 100644 +--- a/deps/nghttp2/nghttp2.gyp ++++ b/deps/nghttp2/nghttp2.gyp +@@ -19,10 +19,12 @@ + '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', + ] \ No newline at end of file