diff --git a/.github/workflows/auto-start-ci.yml b/.github/workflows/auto-start-ci.yml index 104f6755d98c78..823bb4be4f0dbb 100644 --- a/.github/workflows/auto-start-ci.yml +++ b/.github/workflows/auto-start-ci.yml @@ -10,9 +10,8 @@ on: concurrency: ${{ github.workflow }} -# todo (node-fetch not working on 18, waiting for node-core-utils to fix) env: - NODE_VERSION: 16 + NODE_VERSION: lts/* permissions: contents: read @@ -51,7 +50,7 @@ jobs: persist-credentials: false - name: Install Node.js - uses: actions/setup-node@b39b52d1213e96004bfcb1c61a8a6fa8ab84f3e8 # v4.0.1 + uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 with: node-version: ${{ env.NODE_VERSION }} diff --git a/.github/workflows/build-tarball.yml b/.github/workflows/build-tarball.yml index 12fd9ce6e5d3fd..7e5d27d4247015 100644 --- a/.github/workflows/build-tarball.yml +++ b/.github/workflows/build-tarball.yml @@ -57,7 +57,7 @@ jobs: mkdir tarballs mv *.tar.gz tarballs - name: Upload tarball artifact - uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0 + uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 with: name: tarballs path: tarballs @@ -75,7 +75,7 @@ jobs: - name: Environment Information run: npx envinfo - name: Download tarball - uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1 + uses: actions/download-artifact@87c55149d96e628cc2ef7e6fc2aab372015aec85 # v4.1.3 with: name: tarballs path: tarballs diff --git a/.github/workflows/commit-lint.yml b/.github/workflows/commit-lint.yml index a00f9f262c4361..6edd0980695e97 100644 --- a/.github/workflows/commit-lint.yml +++ b/.github/workflows/commit-lint.yml @@ -23,7 +23,7 @@ jobs: persist-credentials: false - run: git reset HEAD^2 - name: Install Node.js - uses: actions/setup-node@b39b52d1213e96004bfcb1c61a8a6fa8ab84f3e8 # v4.0.1 + uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 with: node-version: ${{ env.NODE_VERSION }} - name: Validate commit message diff --git a/.github/workflows/commit-queue.yml b/.github/workflows/commit-queue.yml index 682e3494756064..7657a7790a94e1 100644 --- a/.github/workflows/commit-queue.yml +++ b/.github/workflows/commit-queue.yml @@ -71,7 +71,7 @@ jobs: # Install dependencies - name: Install Node.js - uses: actions/setup-node@b39b52d1213e96004bfcb1c61a8a6fa8ab84f3e8 # v4.0.1 + uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 with: node-version: ${{ env.NODE_VERSION }} - name: Install @node-core/utils diff --git a/.github/workflows/coverage-linux-without-intl.yml b/.github/workflows/coverage-linux-without-intl.yml index 620becf548d7e7..5d30b97f576828 100644 --- a/.github/workflows/coverage-linux-without-intl.yml +++ b/.github/workflows/coverage-linux-without-intl.yml @@ -68,6 +68,6 @@ jobs: - name: Clean tmp run: rm -rf coverage/tmp && rm -rf out - name: Upload - uses: codecov/codecov-action@e0b68c6749509c5f83f984dd99a76a1c1a231044 # v4.0.1 + uses: codecov/codecov-action@54bcd8715eee62d40e33596ef5e8f0f48dbbccab # v4.1.0 with: directory: ./coverage diff --git a/.github/workflows/coverage-linux.yml b/.github/workflows/coverage-linux.yml index 4bf71319e0dd77..43dded115d9488 100644 --- a/.github/workflows/coverage-linux.yml +++ b/.github/workflows/coverage-linux.yml @@ -68,6 +68,6 @@ jobs: - name: Clean tmp run: rm -rf coverage/tmp && rm -rf out - name: Upload - uses: codecov/codecov-action@e0b68c6749509c5f83f984dd99a76a1c1a231044 # v4.0.1 + uses: codecov/codecov-action@54bcd8715eee62d40e33596ef5e8f0f48dbbccab # v4.1.0 with: directory: ./coverage diff --git a/.github/workflows/coverage-windows.yml b/.github/workflows/coverage-windows.yml index 0badb25d24f332..1d00175325f33b 100644 --- a/.github/workflows/coverage-windows.yml +++ b/.github/workflows/coverage-windows.yml @@ -67,6 +67,6 @@ jobs: - name: Clean tmp run: npx rimraf ./coverage/tmp - name: Upload - uses: codecov/codecov-action@e0b68c6749509c5f83f984dd99a76a1c1a231044 # v4.0.1 + uses: codecov/codecov-action@54bcd8715eee62d40e33596ef5e8f0f48dbbccab # v4.1.0 with: directory: ./coverage diff --git a/.github/workflows/daily-wpt-fyi.yml b/.github/workflows/daily-wpt-fyi.yml index 57ca7289e5b3aa..1bef86c64336fe 100644 --- a/.github/workflows/daily-wpt-fyi.yml +++ b/.github/workflows/daily-wpt-fyi.yml @@ -45,7 +45,7 @@ jobs: run: echo "NIGHTLY=$(curl -s https://nodejs.org/download/nightly/index.json | jq -r '[.[] | select(.files[] | contains("linux-x64"))][0].version')" >> $GITHUB_ENV - name: Install Node.js id: setup-node - uses: actions/setup-node@b39b52d1213e96004bfcb1c61a8a6fa8ab84f3e8 # v4.0.1 + uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 with: node-version: ${{ env.NIGHTLY || matrix.node-version }} check-latest: true @@ -121,7 +121,7 @@ jobs: run: cp wptreport.json wptreport-${{ steps.setup-node.outputs.node-version }}.json - name: Upload GitHub Actions artifact if: ${{ env.WPT_REPORT != '' }} - uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0 + uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 with: path: out/wpt/wptreport-*.json name: WPT Report for ${{ steps.setup-node.outputs.node-version }} diff --git a/.github/workflows/daily.yml b/.github/workflows/daily.yml index 7ee9d1d853026c..d5f458f5b31a35 100644 --- a/.github/workflows/daily.yml +++ b/.github/workflows/daily.yml @@ -21,7 +21,7 @@ jobs: with: persist-credentials: false - name: Use Node.js ${{ env.NODE_VERSION }} - uses: actions/setup-node@b39b52d1213e96004bfcb1c61a8a6fa8ab84f3e8 # v4.0.1 + uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 with: node-version: ${{ env.NODE_VERSION }} - name: Environment Information diff --git a/.github/workflows/doc.yml b/.github/workflows/doc.yml index ff2f245c701575..5de7373a8baf35 100644 --- a/.github/workflows/doc.yml +++ b/.github/workflows/doc.yml @@ -28,14 +28,14 @@ jobs: with: persist-credentials: false - name: Use Node.js ${{ env.NODE_VERSION }} - uses: actions/setup-node@b39b52d1213e96004bfcb1c61a8a6fa8ab84f3e8 # v4.0.1 + uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 with: node-version: ${{ env.NODE_VERSION }} - name: Environment Information run: npx envinfo - name: Build run: NODE=$(command -v node) make doc-only - - uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0 + - uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 with: name: docs path: out/doc diff --git a/.github/workflows/find-inactive-collaborators.yml b/.github/workflows/find-inactive-collaborators.yml index c32e1dd6d0b3ba..4b60ad4b40f9ee 100644 --- a/.github/workflows/find-inactive-collaborators.yml +++ b/.github/workflows/find-inactive-collaborators.yml @@ -25,7 +25,7 @@ jobs: persist-credentials: false - name: Use Node.js ${{ env.NODE_VERSION }} - uses: actions/setup-node@b39b52d1213e96004bfcb1c61a8a6fa8ab84f3e8 # v4.0.1 + uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 with: node-version: ${{ env.NODE_VERSION }} diff --git a/.github/workflows/find-inactive-tsc.yml b/.github/workflows/find-inactive-tsc.yml index ee2db2b69ed59b..b8ef8ef1f92d8a 100644 --- a/.github/workflows/find-inactive-tsc.yml +++ b/.github/workflows/find-inactive-tsc.yml @@ -34,7 +34,7 @@ jobs: repository: nodejs/TSC - name: Use Node.js ${{ env.NODE_VERSION }} - uses: actions/setup-node@b39b52d1213e96004bfcb1c61a8a6fa8ab84f3e8 # v4.0.1 + uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 with: node-version: ${{ env.NODE_VERSION }} diff --git a/.github/workflows/linters.yml b/.github/workflows/linters.yml index 90518237732827..bb7b2d5cdbe572 100644 --- a/.github/workflows/linters.yml +++ b/.github/workflows/linters.yml @@ -29,7 +29,7 @@ jobs: with: persist-credentials: false - name: Use Node.js ${{ env.NODE_VERSION }} - uses: actions/setup-node@b39b52d1213e96004bfcb1c61a8a6fa8ab84f3e8 # v4.0.1 + uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 with: node-version: ${{ env.NODE_VERSION }} - name: Environment Information @@ -60,7 +60,7 @@ jobs: fetch-depth: 0 persist-credentials: false - name: Use Node.js ${{ env.NODE_VERSION }} - uses: actions/setup-node@b39b52d1213e96004bfcb1c61a8a6fa8ab84f3e8 # v4.0.1 + uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 with: node-version: ${{ env.NODE_VERSION }} - name: Set up Python ${{ env.PYTHON_VERSION }} @@ -97,7 +97,7 @@ jobs: with: persist-credentials: false - name: Use Node.js ${{ env.NODE_VERSION }} - uses: actions/setup-node@b39b52d1213e96004bfcb1c61a8a6fa8ab84f3e8 # v4.0.1 + uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 with: node-version: ${{ env.NODE_VERSION }} - name: Environment Information diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index 1a5ff4e9659b81..e74d17781bea19 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -65,7 +65,7 @@ jobs: # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF # format to the repository Actions tab. - name: Upload artifact - uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0 + uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 with: name: SARIF file path: results.sarif @@ -73,6 +73,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: Upload to code-scanning - uses: github/codeql-action/upload-sarif@b7bf0a3ed3ecfa44160715d7c442788f65f0f923 # v3.23.2 + uses: github/codeql-action/upload-sarif@8a470fddafa5cbb6266ee11b37ef4d8aae19c571 # v3.24.6 with: sarif_file: results.sarif diff --git a/.github/workflows/update-v8.yml b/.github/workflows/update-v8.yml index 7d4aedc4c40b43..22ba68435101a5 100644 --- a/.github/workflows/update-v8.yml +++ b/.github/workflows/update-v8.yml @@ -20,7 +20,7 @@ jobs: with: persist-credentials: false - name: Cache node modules and update-v8 - uses: actions/cache@13aacd865c20de90d75de3b17ebe84f7a17d57d2 # v4.0.0 + uses: actions/cache@ab5e6d0c87105b4c9c2047343972218f562e4319 # v4.0.1 id: cache-v8-npm env: cache-name: cache-v8-npm @@ -30,7 +30,7 @@ jobs: ~/.npm key: ${{ runner.os }}-build-${{ env.cache-name }} - name: Install Node.js - uses: actions/setup-node@b39b52d1213e96004bfcb1c61a8a6fa8ab84f3e8 # v4.0.1 + uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 with: node-version: ${{ env.NODE_VERSION }} - name: Install @node-core/utils diff --git a/CHANGELOG.md b/CHANGELOG.md index 8701b7bc5e099d..cbc67fb91693a3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -36,7 +36,8 @@ release. -21.7.0
+21.7.1
+21.7.0
21.6.2
21.6.1
21.6.0
diff --git a/Makefile b/Makefile index 1113873a21a298..7bd80d06c17125 100644 --- a/Makefile +++ b/Makefile @@ -77,7 +77,8 @@ EXEEXT := $(shell $(PYTHON) -c \ "import sys; print('.exe' if sys.platform == 'win32' else '')") NODE_EXE = node$(EXEEXT) -NODE ?= ./$(NODE_EXE) +# Use $(PWD) so we can cd to anywhere before calling this +NODE ?= "$(PWD)/$(NODE_EXE)" NODE_G_EXE = node_g$(EXEEXT) NPM ?= ./deps/npm/bin/npm-cli.js @@ -91,10 +92,9 @@ BUILD_RELEASE_FLAGS ?= $(BUILD_DOWNLOAD_FLAGS) $(BUILD_INTL_FLAGS) V ?= 0 # Use -e to double check in case it's a broken link -# Use $(PWD) so we can cd to anywhere before calling this available-node = \ - if [ -x $(PWD)/$(NODE) ] && [ -e $(PWD)/$(NODE) ]; then \ - $(PWD)/$(NODE) $(1); \ + if [ -x "$(NODE)" ] && [ -e "$(NODE)" ]; then \ + "$(NODE)" $(1); \ elif [ -x `command -v node` ] && [ -e `command -v node` ] && [ `command -v node` ]; then \ `command -v node` $(1); \ else \ diff --git a/SECURITY.md b/SECURITY.md index f5b17eb626987d..7d62c76e5b898c 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -201,6 +201,13 @@ the community they pose. that artifact is large enough to impact performance or cause the runtime to run out of resources. +#### Vulnerabilities affecting software downloaded by Corepack + +* Corepack defaults to downloading the latest version of the software requested + by the user, or a specific version requested by the user. For this reason, + Node.js releases won't be affected by such vulnerabilities, users are + responsible to keep the software they use through Corepack up-to-date. + ## Assessing experimental features reports Experimental features are eligible to reports as any other stable feature of diff --git a/benchmark/async_hooks/async-local-storage-getstore-nested-resources.js b/benchmark/async_hooks/async-local-storage-getstore-nested-resources.js index 05b43af627a79e..3474e801e01f35 100644 --- a/benchmark/async_hooks/async-local-storage-getstore-nested-resources.js +++ b/benchmark/async_hooks/async-local-storage-getstore-nested-resources.js @@ -16,7 +16,7 @@ const { AsyncLocalStorage, AsyncResource } = require('async_hooks'); */ const bench = common.createBenchmark(main, { resourceCount: [10, 100, 1000], - n: [1e4], + n: [5e5], }); function runBenchmark(store, n) { diff --git a/benchmark/domain/domain-fn-args.js b/benchmark/domain/domain-fn-args.js index d55658ccdbaabd..8a8a75c6d3150a 100644 --- a/benchmark/domain/domain-fn-args.js +++ b/benchmark/domain/domain-fn-args.js @@ -4,7 +4,7 @@ const domain = require('domain'); const bench = common.createBenchmark(main, { args: [0, 1, 2, 3], - n: [10], + n: [1e4], }); const bdomain = domain.create(); diff --git a/deps/base64/unofficial.gni b/deps/base64/unofficial.gni index 5c46dea5d90d90..0e69d7383762f6 100644 --- a/deps/base64/unofficial.gni +++ b/deps/base64/unofficial.gni @@ -19,7 +19,7 @@ template("base64_gn_build") { } else { defines = [] } - if (target_cpu == "x86" || target_cpu == "x64") { + if (current_cpu == "x86" || current_cpu == "x64") { defines += [ "HAVE_SSSE3=1", "HAVE_SSE41=1", @@ -29,10 +29,10 @@ template("base64_gn_build") { "HAVE_AVX512=1", ] } - if (target_cpu == "arm") { + if (current_cpu == "arm") { defines += [ "HAVE_NEON32=1" ] } - if (target_cpu == "arm64") { + if (current_cpu == "arm64") { defines += [ "HAVE_NEON64=1" ] } if (is_clang || !is_win) { @@ -69,7 +69,7 @@ template("base64_gn_build") { source_set("base64_ssse3") { configs += [ ":base64_internal_config" ] sources = [ "base64/lib/arch/ssse3/codec.c" ] - if (target_cpu == "x86" || target_cpu == "x64") { + if (current_cpu == "x86" || current_cpu == "x64") { if (is_clang || !is_win) { cflags_c = [ "-mssse3" ] } @@ -79,7 +79,7 @@ template("base64_gn_build") { source_set("base64_sse41") { configs += [ ":base64_internal_config" ] sources = [ "base64/lib/arch/sse41/codec.c" ] - if (target_cpu == "x86" || target_cpu == "x64") { + if (current_cpu == "x86" || current_cpu == "x64") { if (is_clang || !is_win) { cflags_c = [ "-msse4.1" ] } @@ -89,7 +89,7 @@ template("base64_gn_build") { source_set("base64_sse42") { configs += [ ":base64_internal_config" ] sources = [ "base64/lib/arch/sse42/codec.c" ] - if (target_cpu == "x86" || target_cpu == "x64") { + if (current_cpu == "x86" || current_cpu == "x64") { if (is_clang || !is_win) { cflags_c = [ "-msse4.2" ] } @@ -99,7 +99,7 @@ template("base64_gn_build") { source_set("base64_avx") { configs += [ ":base64_internal_config" ] sources = [ "base64/lib/arch/avx/codec.c" ] - if (target_cpu == "x86" || target_cpu == "x64") { + if (current_cpu == "x86" || current_cpu == "x64") { if (is_clang || !is_win) { cflags_c = [ "-mavx" ] } else if (is_win) { @@ -111,7 +111,7 @@ template("base64_gn_build") { source_set("base64_avx2") { configs += [ ":base64_internal_config" ] sources = [ "base64/lib/arch/avx2/codec.c" ] - if (target_cpu == "x86" || target_cpu == "x64") { + if (current_cpu == "x86" || current_cpu == "x64") { if (is_clang || !is_win) { cflags_c = [ "-mavx2" ] } else if (is_win) { @@ -123,7 +123,7 @@ template("base64_gn_build") { source_set("base64_avx512") { configs += [ ":base64_internal_config" ] sources = [ "base64/lib/arch/avx512/codec.c" ] - if (target_cpu == "x86" || target_cpu == "x64") { + if (current_cpu == "x86" || current_cpu == "x64") { if (is_clang || !is_win) { cflags_c = [ "-mavx512vl", @@ -138,7 +138,7 @@ template("base64_gn_build") { source_set("base64_neon32") { configs += [ ":base64_internal_config" ] sources = [ "base64/lib/arch/neon32/codec.c" ] - if (target_cpu == "arm") { + if (current_cpu == "arm") { if (is_clang || !is_win) { cflags_c = [ "-mfpu=neon" ] } diff --git a/deps/cares/unofficial.gni b/deps/cares/unofficial.gni index df6b2d0bcb11aa..a925eb14f33361 100644 --- a/deps/cares/unofficial.gni +++ b/deps/cares/unofficial.gni @@ -69,8 +69,6 @@ template("cares_gn_build") { cflags_c = [ "-Wno-implicit-fallthrough", "-Wno-unreachable-code", - # Remove after https://github.com/c-ares/c-ares/pull/709 lands in Node. - "-Wno-unused-result", ] } } diff --git a/deps/nghttp2/lib/CMakeLists.txt b/deps/nghttp2/lib/CMakeLists.txt index 4180748f209ff0..211c8e4340da12 100644 --- a/deps/nghttp2/lib/CMakeLists.txt +++ b/deps/nghttp2/lib/CMakeLists.txt @@ -31,6 +31,8 @@ set(NGHTTP2_SOURCES ) set(NGHTTP2_RES "") +set(STATIC_LIB "nghttp2_static") +set(SHARED_LIB "nghttp2") if(WIN32) configure_file( @@ -41,40 +43,61 @@ if(WIN32) set(NGHTTP2_RES ${CMAKE_CURRENT_BINARY_DIR}/version.rc) endif() +set(EXPORT_SET "${PROJECT_NAME}-targets") + # Public shared library -if(ENABLE_SHARED_LIB) - add_library(nghttp2 SHARED ${NGHTTP2_SOURCES} ${NGHTTP2_RES}) - set_target_properties(nghttp2 PROPERTIES +if(BUILD_SHARED_LIBS) + add_library(${SHARED_LIB} SHARED ${NGHTTP2_SOURCES} ${NGHTTP2_RES}) + + set_target_properties(${SHARED_LIB} PROPERTIES COMPILE_FLAGS "${WARNCFLAGS}" VERSION ${LT_VERSION} SOVERSION ${LT_SOVERSION} C_VISIBILITY_PRESET hidden ) - target_include_directories(nghttp2 INTERFACE - "${CMAKE_CURRENT_BINARY_DIR}/includes" - "${CMAKE_CURRENT_SOURCE_DIR}/includes" + + target_include_directories(${SHARED_LIB} INTERFACE + $ + $ + $ ) - install(TARGETS nghttp2 - ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" - LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" - RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}") + install(TARGETS ${SHARED_LIB} EXPORT ${EXPORT_SET}) + list(APPEND nghttp2_exports ${SHARED_LIB}) endif() -if(HAVE_CUNIT OR ENABLE_STATIC_LIB) - # Static library (for unittests because of symbol visibility) - add_library(nghttp2_static STATIC ${NGHTTP2_SOURCES}) - set_target_properties(nghttp2_static PROPERTIES - COMPILE_FLAGS "${WARNCFLAGS}" - VERSION ${LT_VERSION} SOVERSION ${LT_SOVERSION} - ARCHIVE_OUTPUT_NAME nghttp2${STATIC_LIB_SUFFIX} - ) - target_compile_definitions(nghttp2_static PUBLIC "-DNGHTTP2_STATICLIB") - if(ENABLE_STATIC_LIB) - install(TARGETS nghttp2_static - DESTINATION "${CMAKE_INSTALL_LIBDIR}") - endif() +# Static library (for unittests because of symbol visibility) +add_library(${STATIC_LIB} STATIC ${NGHTTP2_SOURCES}) + +set_target_properties(${STATIC_LIB} PROPERTIES + COMPILE_FLAGS "${WARNCFLAGS}" + VERSION ${LT_VERSION} SOVERSION ${LT_SOVERSION} + ARCHIVE_OUTPUT_NAME nghttp2${STATIC_LIB_SUFFIX} +) + +target_include_directories(${STATIC_LIB} INTERFACE + $ + $ + $ +) + +target_compile_definitions(${STATIC_LIB} PUBLIC "-DNGHTTP2_STATICLIB") + +if(BUILD_STATIC_LIBS) + install(TARGETS ${STATIC_LIB} EXPORT ${EXPORT_SET}) + list(APPEND nghttp2_exports ${STATIC_LIB}) endif() +if(BUILD_SHARED_LIBS) + set(LIB_SELECTED ${SHARED_LIB}) +else() + set(LIB_SELECTED ${STATIC_LIB}) +endif() + +add_library(${PROJECT_NAME}::nghttp2 ALIAS ${LIB_SELECTED}) install(FILES "${CMAKE_CURRENT_BINARY_DIR}/libnghttp2.pc" DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig") + +install(EXPORT ${EXPORT_SET} + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME} + NAMESPACE ${PROJECT_NAME}::) diff --git a/deps/nghttp2/lib/Makefile.in b/deps/nghttp2/lib/Makefile.in index 81d285390957c5..53ca2403de3552 100644 --- a/deps/nghttp2/lib/Makefile.in +++ b/deps/nghttp2/lib/Makefile.in @@ -306,8 +306,6 @@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CSCOPE = @CSCOPE@ CTAGS = @CTAGS@ -CUNIT_CFLAGS = @CUNIT_CFLAGS@ -CUNIT_LIBS = @CUNIT_LIBS@ CXX = @CXX@ CXX1XCXXFLAGS = @CXX1XCXXFLAGS@ CXXCPP = @CXXCPP@ @@ -345,6 +343,10 @@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBBPF_CFLAGS = @LIBBPF_CFLAGS@ LIBBPF_LIBS = @LIBBPF_LIBS@ +LIBBROTLIDEC_CFLAGS = @LIBBROTLIDEC_CFLAGS@ +LIBBROTLIDEC_LIBS = @LIBBROTLIDEC_LIBS@ +LIBBROTLIENC_CFLAGS = @LIBBROTLIENC_CFLAGS@ +LIBBROTLIENC_LIBS = @LIBBROTLIENC_LIBS@ LIBCARES_CFLAGS = @LIBCARES_CFLAGS@ LIBCARES_LIBS = @LIBCARES_LIBS@ LIBEVENT_OPENSSL_CFLAGS = @LIBEVENT_OPENSSL_CFLAGS@ diff --git a/deps/nghttp2/lib/includes/Makefile.in b/deps/nghttp2/lib/includes/Makefile.in index 3de90d7bef3e3a..eaab6b209030c5 100644 --- a/deps/nghttp2/lib/includes/Makefile.in +++ b/deps/nghttp2/lib/includes/Makefile.in @@ -211,8 +211,6 @@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CSCOPE = @CSCOPE@ CTAGS = @CTAGS@ -CUNIT_CFLAGS = @CUNIT_CFLAGS@ -CUNIT_LIBS = @CUNIT_LIBS@ CXX = @CXX@ CXX1XCXXFLAGS = @CXX1XCXXFLAGS@ CXXCPP = @CXXCPP@ @@ -250,6 +248,10 @@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBBPF_CFLAGS = @LIBBPF_CFLAGS@ LIBBPF_LIBS = @LIBBPF_LIBS@ +LIBBROTLIDEC_CFLAGS = @LIBBROTLIDEC_CFLAGS@ +LIBBROTLIDEC_LIBS = @LIBBROTLIDEC_LIBS@ +LIBBROTLIENC_CFLAGS = @LIBBROTLIENC_CFLAGS@ +LIBBROTLIENC_LIBS = @LIBBROTLIENC_LIBS@ LIBCARES_CFLAGS = @LIBCARES_CFLAGS@ LIBCARES_LIBS = @LIBCARES_LIBS@ LIBEVENT_OPENSSL_CFLAGS = @LIBEVENT_OPENSSL_CFLAGS@ diff --git a/deps/nghttp2/lib/includes/nghttp2/nghttp2.h b/deps/nghttp2/lib/includes/nghttp2/nghttp2.h index 7910db230aae3e..889176097dd31d 100644 --- a/deps/nghttp2/lib/includes/nghttp2/nghttp2.h +++ b/deps/nghttp2/lib/includes/nghttp2/nghttp2.h @@ -51,6 +51,7 @@ extern "C" { #endif /* !defined(_MSC_VER) || (_MSC_VER >= 1800) */ #include #include +#include #include @@ -71,6 +72,13 @@ extern "C" { # endif /* !BUILDING_NGHTTP2 */ #endif /* !defined(WIN32) */ +/** + * @typedef + * + * :type:`nghttp2_ssize` is a signed counterpart of size_t. + */ +typedef ptrdiff_t nghttp2_ssize; + /** * @macro * @@ -168,6 +176,12 @@ typedef struct { /** * @macro * + * .. warning:: + * + * Deprecated. :rfc:`7540` priorities are deprecated by + * :rfc:`9113`. Consider migrating to :rfc:`9218` extensible + * prioritization scheme. + * * The default weight of stream dependency. */ #define NGHTTP2_DEFAULT_WEIGHT 16 @@ -175,6 +189,12 @@ typedef struct { /** * @macro * + * .. warning:: + * + * Deprecated. :rfc:`7540` priorities are deprecated by + * :rfc:`9113`. Consider migrating to :rfc:`9218` extensible + * prioritization scheme. + * * The maximum weight of stream dependency. */ #define NGHTTP2_MAX_WEIGHT 256 @@ -182,6 +202,12 @@ typedef struct { /** * @macro * + * .. warning:: + * + * Deprecated. :rfc:`7540` priorities are deprecated by + * :rfc:`9113`. Consider migrating to :rfc:`9218` extensible + * prioritization scheme. + * * The minimum weight of stream dependency. */ #define NGHTTP2_MIN_WEIGHT 1 @@ -255,7 +281,7 @@ typedef enum { */ NGHTTP2_ERR_UNSUPPORTED_VERSION = -503, /** - * Used as a return value from :type:`nghttp2_send_callback`, + * Used as a return value from :type:`nghttp2_send_callback2`, * :type:`nghttp2_recv_callback` and * :type:`nghttp2_send_data_callback` to indicate that the operation * would block. @@ -275,9 +301,9 @@ typedef enum { NGHTTP2_ERR_EOF = -507, /** * Used as a return value from - * :func:`nghttp2_data_source_read_callback` to indicate that data + * :func:`nghttp2_data_source_read_callback2` to indicate that data * transfer is postponed. See - * :func:`nghttp2_data_source_read_callback` for details. + * :func:`nghttp2_data_source_read_callback2` for details. */ NGHTTP2_ERR_DEFERRED = -508, /** @@ -830,7 +856,7 @@ typedef struct { * @union * * This union represents the some kind of data source passed to - * :type:`nghttp2_data_source_read_callback`. + * :type:`nghttp2_data_source_read_callback2`. */ typedef union { /** @@ -847,7 +873,7 @@ typedef union { * @enum * * The flags used to set in |data_flags| output parameter in - * :type:`nghttp2_data_source_read_callback`. + * :type:`nghttp2_data_source_read_callback2`. */ typedef enum { /** @@ -861,8 +887,8 @@ typedef enum { /** * Indicates that END_STREAM flag must not be set even if * NGHTTP2_DATA_FLAG_EOF is set. Usually this flag is used to send - * trailer fields with `nghttp2_submit_request()` or - * `nghttp2_submit_response()`. + * trailer fields with `nghttp2_submit_request2()` or + * `nghttp2_submit_response2()`. */ NGHTTP2_DATA_FLAG_NO_END_STREAM = 0x02, /** @@ -872,9 +898,15 @@ typedef enum { NGHTTP2_DATA_FLAG_NO_COPY = 0x04 } nghttp2_data_flag; +#ifndef NGHTTP2_NO_SSIZE_T /** * @functypedef * + * .. warning:: + * + * Deprecated. Use :type:`nghttp2_data_source_read_callback2` + * instead. + * * Callback function invoked when the library wants to read data from * the |source|. The read data is sent in the stream |stream_id|. * The implementation of this function must read at most |length| @@ -939,9 +971,83 @@ typedef ssize_t (*nghttp2_data_source_read_callback)( nghttp2_session *session, int32_t stream_id, uint8_t *buf, size_t length, uint32_t *data_flags, nghttp2_data_source *source, void *user_data); +#endif /* NGHTTP2_NO_SSIZE_T */ + +/** + * @functypedef + * + * Callback function invoked when the library wants to read data from + * the |source|. The read data is sent in the stream |stream_id|. + * The implementation of this function must read at most |length| + * bytes of data from |source| (or possibly other places) and store + * them in |buf| and return number of data stored in |buf|. If EOF is + * reached, set :enum:`nghttp2_data_flag.NGHTTP2_DATA_FLAG_EOF` flag + * in |*data_flags|. + * + * Sometime it is desirable to avoid copying data into |buf| and let + * application to send data directly. To achieve this, set + * :enum:`nghttp2_data_flag.NGHTTP2_DATA_FLAG_NO_COPY` to + * |*data_flags| (and possibly other flags, just like when we do + * copy), and return the number of bytes to send without copying data + * into |buf|. The library, seeing + * :enum:`nghttp2_data_flag.NGHTTP2_DATA_FLAG_NO_COPY`, will invoke + * :type:`nghttp2_send_data_callback`. The application must send + * complete DATA frame in that callback. + * + * If this callback is set by `nghttp2_submit_request2()`, + * `nghttp2_submit_response2()` or `nghttp2_submit_headers()` and + * `nghttp2_submit_data2()` with flag parameter + * :enum:`nghttp2_flag.NGHTTP2_FLAG_END_STREAM` set, and + * :enum:`nghttp2_data_flag.NGHTTP2_DATA_FLAG_EOF` flag is set to + * |*data_flags|, DATA frame will have END_STREAM flag set. Usually, + * this is expected behaviour and all are fine. One exception is send + * trailer fields. You cannot send trailer fields after sending frame + * with END_STREAM set. To avoid this problem, one can set + * :enum:`nghttp2_data_flag.NGHTTP2_DATA_FLAG_NO_END_STREAM` along + * with :enum:`nghttp2_data_flag.NGHTTP2_DATA_FLAG_EOF` to signal the + * library not to set END_STREAM in DATA frame. Then application can + * use `nghttp2_submit_trailer()` to send trailer fields. + * `nghttp2_submit_trailer()` can be called inside this callback. + * + * If the application wants to postpone DATA frames (e.g., + * asynchronous I/O, or reading data blocks for long time), it is + * achieved by returning :enum:`nghttp2_error.NGHTTP2_ERR_DEFERRED` + * without reading any data in this invocation. The library removes + * DATA frame from the outgoing queue temporarily. To move back + * deferred DATA frame to outgoing queue, call + * `nghttp2_session_resume_data()`. + * + * By default, |length| is limited to 16KiB at maximum. If peer + * allows larger frames, application can enlarge transmission buffer + * size. See :type:`nghttp2_data_source_read_length_callback` for + * more details. + * + * If the application just wants to return from + * `nghttp2_session_send()` or `nghttp2_session_mem_send2()` without + * sending anything, return :enum:`nghttp2_error.NGHTTP2_ERR_PAUSE`. + * + * In case of error, there are 2 choices. Returning + * :enum:`nghttp2_error.NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE` will + * close the stream by issuing RST_STREAM with + * :enum:`nghttp2_error_code.NGHTTP2_INTERNAL_ERROR`. If a different + * error code is desirable, use `nghttp2_submit_rst_stream()` with a + * desired error code and then return + * :enum:`nghttp2_error.NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE`. + * Returning :enum:`nghttp2_error.NGHTTP2_ERR_CALLBACK_FAILURE` will + * signal the entire session failure. + */ +typedef nghttp2_ssize (*nghttp2_data_source_read_callback2)( + nghttp2_session *session, int32_t stream_id, uint8_t *buf, size_t length, + uint32_t *data_flags, nghttp2_data_source *source, void *user_data); + +#ifndef NGHTTP2_NO_SSIZE_T /** * @struct * + * .. warning:: + * + * Deprecated. Use :type:`nghttp2_data_provider2` instead. + * * This struct represents the data source and the way to read a chunk * of data from it. */ @@ -956,6 +1062,25 @@ typedef struct { nghttp2_data_source_read_callback read_callback; } nghttp2_data_provider; +#endif /* NGHTTP2_NO_SSIZE_T */ + +/** + * @struct + * + * This struct represents the data source and the way to read a chunk + * of data from it. + */ +typedef struct { + /** + * The data source. + */ + nghttp2_data_source source; + /** + * The callback function to read a chunk of data from the |source|. + */ + nghttp2_data_source_read_callback2 read_callback; +} nghttp2_data_provider2; + /** * @struct * @@ -1008,6 +1133,12 @@ typedef enum { /** * @struct * + * .. warning:: + * + * Deprecated. :rfc:`7540` priorities are deprecated by + * :rfc:`9113`. Consider migrating to :rfc:`9218` extensible + * prioritization scheme. + * * The structure to specify stream dependency. */ typedef struct { @@ -1042,6 +1173,12 @@ typedef struct { */ size_t padlen; /** + * .. warning:: + * + * Deprecated. :rfc:`7540` priorities are deprecated by + * :rfc:`9113`. Consider migrating to :rfc:`9218` extensible + * prioritization scheme. + * * The priority specification */ nghttp2_priority_spec pri_spec; @@ -1062,6 +1199,12 @@ typedef struct { /** * @struct * + * .. warning:: + * + * Deprecated. :rfc:`7540` priorities are deprecated by + * :rfc:`9113`. Consider migrating to :rfc:`9218` extensible + * prioritization scheme. + * * The PRIORITY frame. It has the following members: */ typedef struct { @@ -1305,9 +1448,14 @@ typedef union { nghttp2_extension ext; } nghttp2_frame; +#ifndef NGHTTP2_NO_SSIZE_T /** * @functypedef * + * .. warning:: + * + * Deprecated. Use :type:`nghttp2_send_callback2` instead. + * * Callback function invoked when |session| wants to send data to the * remote peer. The implementation of this function must send at most * |length| bytes of data stored in |data|. The |flags| is currently @@ -1340,6 +1488,44 @@ typedef ssize_t (*nghttp2_send_callback)(nghttp2_session *session, const uint8_t *data, size_t length, int flags, void *user_data); +#endif /* NGHTTP2_NO_SSIZE_T */ + +/** + * @functypedef + * + * Callback function invoked when |session| wants to send data to the + * remote peer. The implementation of this function must send at most + * |length| bytes of data stored in |data|. The |flags| is currently + * not used and always 0. It must return the number of bytes sent if + * it succeeds. If it cannot send any single byte without blocking, + * it must return :enum:`nghttp2_error.NGHTTP2_ERR_WOULDBLOCK`. For + * other errors, it must return + * :enum:`nghttp2_error.NGHTTP2_ERR_CALLBACK_FAILURE`. The + * |user_data| pointer is the third argument passed in to the call to + * `nghttp2_session_client_new()` or `nghttp2_session_server_new()`. + * + * This callback is required if the application uses + * `nghttp2_session_send()` to send data to the remote endpoint. If + * the application uses solely `nghttp2_session_mem_send2()` instead, + * this callback function is unnecessary. + * + * To set this callback to :type:`nghttp2_session_callbacks`, use + * `nghttp2_session_callbacks_set_send_callback2()`. + * + * .. note:: + * + * The |length| may be very small. If that is the case, and + * application disables Nagle algorithm (``TCP_NODELAY``), then just + * writing |data| to the network stack leads to very small packet, + * and it is very inefficient. An application should be responsible + * to buffer up small chunks of data as necessary to avoid this + * situation. + */ +typedef nghttp2_ssize (*nghttp2_send_callback2)(nghttp2_session *session, + const uint8_t *data, + size_t length, int flags, + void *user_data); + /** * @functypedef * @@ -1370,7 +1556,7 @@ typedef ssize_t (*nghttp2_send_callback)(nghttp2_session *session, * error; if partial frame data has already sent, it is impossible to * send another data in that state, and all we can do is tear down * connection). When data is fully processed, but application wants - * to make `nghttp2_session_mem_send()` or `nghttp2_session_send()` + * to make `nghttp2_session_mem_send2()` or `nghttp2_session_send()` * return immediately without processing next frames, return * :enum:`nghttp2_error.NGHTTP2_ERR_PAUSE`. If application decided to * reset this stream, return @@ -1387,9 +1573,14 @@ typedef int (*nghttp2_send_data_callback)(nghttp2_session *session, nghttp2_data_source *source, void *user_data); +#ifndef NGHTTP2_NO_SSIZE_T /** * @functypedef * + * .. warning:: + * + * Deprecated. Use :type:`nghttp2_recv_callback2` instead. + * * Callback function invoked when |session| wants to receive data from * the remote peer. The implementation of this function must read at * most |length| bytes of data and store it in |buf|. The |flags| is @@ -1417,11 +1608,43 @@ typedef ssize_t (*nghttp2_recv_callback)(nghttp2_session *session, uint8_t *buf, size_t length, int flags, void *user_data); +#endif /* NGHTTP2_NO_SSIZE_T */ + +/** + * @functypedef + * + * Callback function invoked when |session| wants to receive data from + * the remote peer. The implementation of this function must read at + * most |length| bytes of data and store it in |buf|. The |flags| is + * currently not used and always 0. It must return the number of + * bytes written in |buf| if it succeeds. If it cannot read any + * single byte without blocking, it must return + * :enum:`nghttp2_error.NGHTTP2_ERR_WOULDBLOCK`. If it gets EOF + * before it reads any single byte, it must return + * :enum:`nghttp2_error.NGHTTP2_ERR_EOF`. For other errors, it must + * return :enum:`nghttp2_error.NGHTTP2_ERR_CALLBACK_FAILURE`. + * Returning 0 is treated as + * :enum:`nghttp2_error.NGHTTP2_ERR_WOULDBLOCK`. The |user_data| + * pointer is the third argument passed in to the call to + * `nghttp2_session_client_new()` or `nghttp2_session_server_new()`. + * + * This callback is required if the application uses + * `nghttp2_session_recv()` to receive data from the remote endpoint. + * If the application uses solely `nghttp2_session_mem_recv2()` + * instead, this callback function is unnecessary. + * + * To set this callback to :type:`nghttp2_session_callbacks`, use + * `nghttp2_session_callbacks_set_recv_callback2()`. + */ +typedef nghttp2_ssize (*nghttp2_recv_callback2)(nghttp2_session *session, + uint8_t *buf, size_t length, + int flags, void *user_data); + /** * @functypedef * * Callback function invoked by `nghttp2_session_recv()` and - * `nghttp2_session_mem_recv()` when a frame is received. The + * `nghttp2_session_mem_recv2()` when a frame is received. The * |user_data| pointer is the third argument passed in to the call to * `nghttp2_session_client_new()` or `nghttp2_session_server_new()`. * @@ -1439,8 +1662,8 @@ typedef ssize_t (*nghttp2_recv_callback)(nghttp2_session *session, uint8_t *buf, * * The implementation of this function must return 0 if it succeeds. * If nonzero value is returned, it is treated as fatal error and - * `nghttp2_session_recv()` and `nghttp2_session_mem_recv()` functions - * immediately return + * `nghttp2_session_recv()` and `nghttp2_session_mem_recv2()` + * functions immediately return * :enum:`nghttp2_error.NGHTTP2_ERR_CALLBACK_FAILURE`. * * To set this callback to :type:`nghttp2_session_callbacks`, use @@ -1454,7 +1677,7 @@ typedef int (*nghttp2_on_frame_recv_callback)(nghttp2_session *session, * @functypedef * * Callback function invoked by `nghttp2_session_recv()` and - * `nghttp2_session_mem_recv()` when an invalid non-DATA frame is + * `nghttp2_session_mem_recv2()` when an invalid non-DATA frame is * received. The error is indicated by the |lib_error_code|, which is * one of the values defined in :type:`nghttp2_error`. When this * callback function is invoked, the library automatically submits @@ -1468,8 +1691,8 @@ typedef int (*nghttp2_on_frame_recv_callback)(nghttp2_session *session, * * The implementation of this function must return 0 if it succeeds. * If nonzero is returned, it is treated as fatal error and - * `nghttp2_session_recv()` and `nghttp2_session_mem_recv()` functions - * immediately return + * `nghttp2_session_recv()` and `nghttp2_session_mem_recv2()` + * functions immediately return * :enum:`nghttp2_error.NGHTTP2_ERR_CALLBACK_FAILURE`. * * To set this callback to :type:`nghttp2_session_callbacks`, use @@ -1492,19 +1715,19 @@ typedef int (*nghttp2_on_invalid_frame_recv_callback)( * argument passed in to the call to `nghttp2_session_client_new()` or * `nghttp2_session_server_new()`. * - * If the application uses `nghttp2_session_mem_recv()`, it can return - * :enum:`nghttp2_error.NGHTTP2_ERR_PAUSE` to make - * `nghttp2_session_mem_recv()` return without processing further + * If the application uses `nghttp2_session_mem_recv2()`, it can + * return :enum:`nghttp2_error.NGHTTP2_ERR_PAUSE` to make + * `nghttp2_session_mem_recv2()` return without processing further * input bytes. The memory by pointed by the |data| is retained until - * `nghttp2_session_mem_recv()` or `nghttp2_session_recv()` is called. - * The application must retain the input bytes which was used to - * produce the |data| parameter, because it may refer to the memory + * `nghttp2_session_mem_recv2()` or `nghttp2_session_recv()` is + * called. The application must retain the input bytes which was used + * to produce the |data| parameter, because it may refer to the memory * region included in the input bytes. * * The implementation of this function must return 0 if it succeeds. * If nonzero is returned, it is treated as fatal error, and - * `nghttp2_session_recv()` and `nghttp2_session_mem_recv()` functions - * immediately return + * `nghttp2_session_recv()` and `nghttp2_session_mem_recv2()` + * functions immediately return * :enum:`nghttp2_error.NGHTTP2_ERR_CALLBACK_FAILURE`. * * To set this callback to :type:`nghttp2_session_callbacks`, use @@ -1531,8 +1754,8 @@ typedef int (*nghttp2_on_data_chunk_recv_callback)(nghttp2_session *session, * If there is a fatal error while executing this callback, the * implementation should return * :enum:`nghttp2_error.NGHTTP2_ERR_CALLBACK_FAILURE`, which makes - * `nghttp2_session_send()` and `nghttp2_session_mem_send()` functions - * immediately return + * `nghttp2_session_send()` and `nghttp2_session_mem_send2()` + * functions immediately return * :enum:`nghttp2_error.NGHTTP2_ERR_CALLBACK_FAILURE`. * * If the other value is returned, it is treated as if @@ -1556,8 +1779,8 @@ typedef int (*nghttp2_before_frame_send_callback)(nghttp2_session *session, * * The implementation of this function must return 0 if it succeeds. * If nonzero is returned, it is treated as fatal error and - * `nghttp2_session_send()` and `nghttp2_session_mem_send()` functions - * immediately return + * `nghttp2_session_send()` and `nghttp2_session_mem_send2()` + * functions immediately return * :enum:`nghttp2_error.NGHTTP2_ERR_CALLBACK_FAILURE`. * * To set this callback to :type:`nghttp2_session_callbacks`, use @@ -1579,8 +1802,8 @@ typedef int (*nghttp2_on_frame_send_callback)(nghttp2_session *session, * * The implementation of this function must return 0 if it succeeds. * If nonzero is returned, it is treated as fatal error and - * `nghttp2_session_send()` and `nghttp2_session_mem_send()` functions - * immediately return + * `nghttp2_session_send()` and `nghttp2_session_mem_send2()` + * functions immediately return * :enum:`nghttp2_error.NGHTTP2_ERR_CALLBACK_FAILURE`. * * `nghttp2_session_get_stream_user_data()` can be used to get @@ -1601,7 +1824,7 @@ typedef int (*nghttp2_on_frame_not_send_callback)(nghttp2_session *session, * The reason of closure is indicated by the |error_code|. The * |error_code| is usually one of :enum:`nghttp2_error_code`, but that * is not guaranteed. The stream_user_data, which was specified in - * `nghttp2_submit_request()` or `nghttp2_submit_headers()`, is still + * `nghttp2_submit_request2()` or `nghttp2_submit_headers()`, is still * available in this function. The |user_data| pointer is the third * argument passed in to the call to `nghttp2_session_client_new()` or * `nghttp2_session_server_new()`. @@ -1610,8 +1833,8 @@ typedef int (*nghttp2_on_frame_not_send_callback)(nghttp2_session *session, * * The implementation of this function must return 0 if it succeeds. * If nonzero is returned, it is treated as fatal error and - * `nghttp2_session_recv()`, `nghttp2_session_mem_recv()`, - * `nghttp2_session_send()`, and `nghttp2_session_mem_send()` + * `nghttp2_session_recv()`, `nghttp2_session_mem_recv2()`, + * `nghttp2_session_send()`, and `nghttp2_session_mem_send2()` * functions immediately return * :enum:`nghttp2_error.NGHTTP2_ERR_CALLBACK_FAILURE`. * @@ -1681,7 +1904,7 @@ typedef int (*nghttp2_on_stream_close_callback)(nghttp2_session *session, * value is returned, it is treated as if * :enum:`nghttp2_error.NGHTTP2_ERR_CALLBACK_FAILURE` is returned. If * :enum:`nghttp2_error.NGHTTP2_ERR_CALLBACK_FAILURE` is returned, - * `nghttp2_session_mem_recv()` function will immediately return + * `nghttp2_session_mem_recv2()` function will immediately return * :enum:`nghttp2_error.NGHTTP2_ERR_CALLBACK_FAILURE`. * * To set this callback to :type:`nghttp2_session_callbacks`, use @@ -1726,11 +1949,11 @@ typedef int (*nghttp2_on_begin_headers_callback)(nghttp2_session *session, * performs validation based on HTTP Messaging rule, which is briefly * explained in :ref:`http-messaging` section. * - * If the application uses `nghttp2_session_mem_recv()`, it can return - * :enum:`nghttp2_error.NGHTTP2_ERR_PAUSE` to make - * `nghttp2_session_mem_recv()` return without processing further + * If the application uses `nghttp2_session_mem_recv2()`, it can + * return :enum:`nghttp2_error.NGHTTP2_ERR_PAUSE` to make + * `nghttp2_session_mem_recv2()` return without processing further * input bytes. The memory pointed by |frame|, |name| and |value| - * parameters are retained until `nghttp2_session_mem_recv()` or + * parameters are retained until `nghttp2_session_mem_recv2()` or * `nghttp2_session_recv()` is called. The application must retain * the input bytes which was used to produce these parameters, because * it may refer to the memory region included in the input bytes. @@ -1757,8 +1980,8 @@ typedef int (*nghttp2_on_begin_headers_callback)(nghttp2_session *session, * nonzero value is returned, it is treated as * :enum:`nghttp2_error.NGHTTP2_ERR_CALLBACK_FAILURE`. If * :enum:`nghttp2_error.NGHTTP2_ERR_CALLBACK_FAILURE` is returned, - * `nghttp2_session_recv()` and `nghttp2_session_mem_recv()` functions - * immediately return + * `nghttp2_session_recv()` and `nghttp2_session_mem_recv2()` + * functions immediately return * :enum:`nghttp2_error.NGHTTP2_ERR_CALLBACK_FAILURE`. * * To set this callback to :type:`nghttp2_session_callbacks`, use @@ -1873,9 +2096,15 @@ typedef int (*nghttp2_on_invalid_header_callback2)( nghttp2_session *session, const nghttp2_frame *frame, nghttp2_rcbuf *name, nghttp2_rcbuf *value, uint8_t flags, void *user_data); +#ifndef NGHTTP2_NO_SSIZE_T /** * @functypedef * + * .. warning:: + * + * Deprecated. Use :type:`nghttp2_select_padding_callback2` + * instead. + * * Callback function invoked when the library asks application how * many padding bytes are required for the transmission of the * |frame|. The application must choose the total length of payload @@ -1896,9 +2125,39 @@ typedef ssize_t (*nghttp2_select_padding_callback)(nghttp2_session *session, size_t max_payloadlen, void *user_data); +#endif /* NGHTTP2_NO_SSIZE_T */ + +/** + * @functypedef + * + * Callback function invoked when the library asks application how + * many padding bytes are required for the transmission of the + * |frame|. The application must choose the total length of payload + * including padded bytes in range [frame->hd.length, max_payloadlen], + * inclusive. Choosing number not in this range will be treated as + * :enum:`nghttp2_error.NGHTTP2_ERR_CALLBACK_FAILURE`. Returning + * ``frame->hd.length`` means no padding is added. Returning + * :enum:`nghttp2_error.NGHTTP2_ERR_CALLBACK_FAILURE` will make + * `nghttp2_session_send()` and `nghttp2_session_mem_send2()` + * functions immediately return + * :enum:`nghttp2_error.NGHTTP2_ERR_CALLBACK_FAILURE`. + * + * To set this callback to :type:`nghttp2_session_callbacks`, use + * `nghttp2_session_callbacks_set_select_padding_callback2()`. + */ +typedef nghttp2_ssize (*nghttp2_select_padding_callback2)( + nghttp2_session *session, const nghttp2_frame *frame, size_t max_payloadlen, + void *user_data); + +#ifndef NGHTTP2_NO_SSIZE_T /** * @functypedef * + * .. warning:: + * + * Deprecated. Use + * :type:`nghttp2_data_source_read_length_callback2` instead. + * * Callback function invoked when library wants to get max length of * data to send data to the remote peer. The implementation of this * function should return a value in the following range. [1, @@ -1926,6 +2185,38 @@ typedef ssize_t (*nghttp2_data_source_read_length_callback)( int32_t session_remote_window_size, int32_t stream_remote_window_size, uint32_t remote_max_frame_size, void *user_data); +#endif /* NGHTTP2_NO_SSIZE_T */ + +/** + * @functypedef + * + * Callback function invoked when library wants to get max length of + * data to send data to the remote peer. The implementation of this + * function should return a value in the following range. [1, + * min(|session_remote_window_size|, |stream_remote_window_size|, + * |remote_max_frame_size|)]. If a value greater than this range is + * returned than the max allow value will be used. Returning a value + * smaller than this range is treated as + * :enum:`nghttp2_error.NGHTTP2_ERR_CALLBACK_FAILURE`. The + * |frame_type| is provided for future extensibility and identifies + * the type of frame (see :type:`nghttp2_frame_type`) for which to get + * the length for. Currently supported frame types are: + * :enum:`nghttp2_frame_type.NGHTTP2_DATA`. + * + * This callback can be used to control the length in bytes for which + * :type:`nghttp2_data_source_read_callback` is allowed to send to the + * remote endpoint. This callback is optional. Returning + * :enum:`nghttp2_error.NGHTTP2_ERR_CALLBACK_FAILURE` will signal the + * entire session failure. + * + * To set this callback to :type:`nghttp2_session_callbacks`, use + * `nghttp2_session_callbacks_set_data_source_read_length_callback2()`. + */ +typedef nghttp2_ssize (*nghttp2_data_source_read_length_callback2)( + nghttp2_session *session, uint8_t frame_type, int32_t stream_id, + int32_t session_remote_window_size, int32_t stream_remote_window_size, + uint32_t remote_max_frame_size, void *user_data); + /** * @functypedef * @@ -1942,8 +2233,8 @@ typedef ssize_t (*nghttp2_data_source_read_length_callback)( * * The implementation of this function must return 0 if it succeeds. * If nonzero value is returned, it is treated as fatal error and - * `nghttp2_session_recv()` and `nghttp2_session_mem_recv()` functions - * immediately return + * `nghttp2_session_recv()` and `nghttp2_session_mem_recv2()` + * functions immediately return * :enum:`nghttp2_error.NGHTTP2_ERR_CALLBACK_FAILURE`. * * To set this callback to :type:`nghttp2_session_callbacks`, use @@ -1967,8 +2258,8 @@ typedef int (*nghttp2_on_begin_frame_callback)(nghttp2_session *session, * * If fatal error occurred, application should return * :enum:`nghttp2_error.NGHTTP2_ERR_CALLBACK_FAILURE`. In this case, - * `nghttp2_session_recv()` and `nghttp2_session_mem_recv()` functions - * immediately return + * `nghttp2_session_recv()` and `nghttp2_session_mem_recv2()` + * functions immediately return * :enum:`nghttp2_error.NGHTTP2_ERR_CALLBACK_FAILURE`. If the other * values are returned, currently they are treated as * :enum:`nghttp2_error.NGHTTP2_ERR_CALLBACK_FAILURE`. @@ -2005,8 +2296,8 @@ typedef int (*nghttp2_on_extension_chunk_recv_callback)( * * If fatal error occurred, application should return * :enum:`nghttp2_error.NGHTTP2_ERR_CALLBACK_FAILURE`. In this case, - * `nghttp2_session_recv()` and `nghttp2_session_mem_recv()` functions - * immediately return + * `nghttp2_session_recv()` and `nghttp2_session_mem_recv2()` + * functions immediately return * :enum:`nghttp2_error.NGHTTP2_ERR_CALLBACK_FAILURE`. If the other * values are returned, currently they are treated as * :enum:`nghttp2_error.NGHTTP2_ERR_CALLBACK_FAILURE`. @@ -2016,9 +2307,15 @@ typedef int (*nghttp2_unpack_extension_callback)(nghttp2_session *session, const nghttp2_frame_hd *hd, void *user_data); +#ifndef NGHTTP2_NO_SSIZE_T /** * @functypedef * + * .. warning:: + * + * Deprecated. Use :type:`nghttp2_pack_extension_callback2` + * instead. + * * Callback function invoked when library asks the application to pack * extension payload in its wire format. The frame header will be * packed by library. Application must pack payload only. @@ -2049,18 +2346,53 @@ typedef ssize_t (*nghttp2_pack_extension_callback)(nghttp2_session *session, const nghttp2_frame *frame, void *user_data); +#endif /* NGHTTP2_NO_SSIZE_T */ + /** * @functypedef * - * Callback function invoked when library provides the error message - * intended for human consumption. This callback is solely for - * debugging purpose. The |msg| is typically NULL-terminated string + * Callback function invoked when library asks the application to pack + * extension payload in its wire format. The frame header will be + * packed by library. Application must pack payload only. + * ``frame->ext.payload`` is the object passed to + * `nghttp2_submit_extension()` as payload parameter. Application + * must pack extension payload to the |buf| of its capacity |len| + * bytes. The |len| is at least 16KiB. + * + * The implementation of this function should return the number of + * bytes written into |buf| when it succeeds. + * + * To abort processing this extension frame, return + * :enum:`nghttp2_error.NGHTTP2_ERR_CANCEL`, and + * :type:`nghttp2_on_frame_not_send_callback` will be invoked. + * + * If fatal error occurred, application should return + * :enum:`nghttp2_error.NGHTTP2_ERR_CALLBACK_FAILURE`. In this case, + * `nghttp2_session_send()` and `nghttp2_session_mem_send2()` + * functions immediately return + * :enum:`nghttp2_error.NGHTTP2_ERR_CALLBACK_FAILURE`. If the other + * values are returned, currently they are treated as + * :enum:`nghttp2_error.NGHTTP2_ERR_CALLBACK_FAILURE`. If the return + * value is strictly larger than |len|, it is treated as + * :enum:`nghttp2_error.NGHTTP2_ERR_CALLBACK_FAILURE`. + */ +typedef nghttp2_ssize (*nghttp2_pack_extension_callback2)( + nghttp2_session *session, uint8_t *buf, size_t len, + const nghttp2_frame *frame, void *user_data); + +/** + * @functypedef + * + * .. warning:: + * + * Deprecated. Use :type:`nghttp2_error_callback2` instead. + * + * Callback function invoked when library provides the error message + * intended for human consumption. This callback is solely for + * debugging purpose. The |msg| is typically NULL-terminated string * of length |len|. |len| does not include the sentinel NULL * character. * - * This function is deprecated. The new application should use - * :type:`nghttp2_error_callback2`. - * * The format of error message may change between nghttp2 library * versions. The application should not depend on the particular * format. @@ -2143,9 +2475,15 @@ nghttp2_session_callbacks_new(nghttp2_session_callbacks **callbacks_ptr); NGHTTP2_EXTERN void nghttp2_session_callbacks_del(nghttp2_session_callbacks *callbacks); +#ifndef NGHTTP2_NO_SSIZE_T /** * @function * + * .. warning:: + * + * Deprecated. Use `nghttp2_session_callbacks_set_send_callback2()` + * with :type:`nghttp2_send_callback2` instead. + * * Sets callback function invoked when a session wants to send data to * the remote peer. This callback is not necessary if the application * uses solely `nghttp2_session_mem_send()` to serialize data to @@ -2154,9 +2492,28 @@ nghttp2_session_callbacks_del(nghttp2_session_callbacks *callbacks); NGHTTP2_EXTERN void nghttp2_session_callbacks_set_send_callback( nghttp2_session_callbacks *cbs, nghttp2_send_callback send_callback); +#endif /* NGHTTP2_NO_SSIZE_T */ + +/** + * @function + * + * Sets callback function invoked when a session wants to send data to + * the remote peer. This callback is not necessary if the application + * uses solely `nghttp2_session_mem_send2()` to serialize data to + * transmit. + */ +NGHTTP2_EXTERN void nghttp2_session_callbacks_set_send_callback2( + nghttp2_session_callbacks *cbs, nghttp2_send_callback2 send_callback); + +#ifndef NGHTTP2_NO_SSIZE_T /** * @function * + * .. warning:: + * + * Deprecated. Use `nghttp2_session_callbacks_set_recv_callback2()` + * with :type:`nghttp2_recv_callback2` instead. + * * Sets callback function invoked when the a session wants to receive * data from the remote peer. This callback is not necessary if the * application uses solely `nghttp2_session_mem_recv()` to process @@ -2165,11 +2522,24 @@ NGHTTP2_EXTERN void nghttp2_session_callbacks_set_send_callback( NGHTTP2_EXTERN void nghttp2_session_callbacks_set_recv_callback( nghttp2_session_callbacks *cbs, nghttp2_recv_callback recv_callback); +#endif /* NGHTTP2_NO_SSIZE_T */ + +/** + * @function + * + * Sets callback function invoked when the a session wants to receive + * data from the remote peer. This callback is not necessary if the + * application uses solely `nghttp2_session_mem_recv2()` to process + * received data. + */ +NGHTTP2_EXTERN void nghttp2_session_callbacks_set_recv_callback2( + nghttp2_session_callbacks *cbs, nghttp2_recv_callback2 recv_callback); + /** * @function * * Sets callback function invoked by `nghttp2_session_recv()` and - * `nghttp2_session_mem_recv()` when a frame is received. + * `nghttp2_session_mem_recv2()` when a frame is received. */ NGHTTP2_EXTERN void nghttp2_session_callbacks_set_on_frame_recv_callback( nghttp2_session_callbacks *cbs, @@ -2179,7 +2549,7 @@ NGHTTP2_EXTERN void nghttp2_session_callbacks_set_on_frame_recv_callback( * @function * * Sets callback function invoked by `nghttp2_session_recv()` and - * `nghttp2_session_mem_recv()` when an invalid non-DATA frame is + * `nghttp2_session_mem_recv2()` when an invalid non-DATA frame is * received. */ NGHTTP2_EXTERN void @@ -2290,9 +2660,16 @@ NGHTTP2_EXTERN void nghttp2_session_callbacks_set_on_invalid_header_callback2( nghttp2_session_callbacks *cbs, nghttp2_on_invalid_header_callback2 on_invalid_header_callback2); +#ifndef NGHTTP2_NO_SSIZE_T /** * @function * + * .. warning:: + * + * Deprecated. Use + * `nghttp2_session_callbacks_set_select_padding_callback2()` with + * :type:`nghttp2_select_padding_callback2` instead. + * * Sets callback function invoked when the library asks application * how many padding bytes are required for the transmission of the * given frame. @@ -2301,9 +2678,29 @@ NGHTTP2_EXTERN void nghttp2_session_callbacks_set_select_padding_callback( nghttp2_session_callbacks *cbs, nghttp2_select_padding_callback select_padding_callback); +#endif /* NGHTTP2_NO_SSIZE_T */ + +/** + * @function + * + * Sets callback function invoked when the library asks application + * how many padding bytes are required for the transmission of the + * given frame. + */ +NGHTTP2_EXTERN void nghttp2_session_callbacks_set_select_padding_callback2( + nghttp2_session_callbacks *cbs, + nghttp2_select_padding_callback2 select_padding_callback); + +#ifndef NGHTTP2_NO_SSIZE_T /** * @function * + * .. warning:: + * + * Deprecated. Use + * `nghttp2_session_callbacks_set_data_source_read_length_callback2()` + * with :type:`nghttp2_data_source_read_length_callback2` instead. + * * Sets callback function determine the length allowed in * :type:`nghttp2_data_source_read_callback`. */ @@ -2312,6 +2709,19 @@ nghttp2_session_callbacks_set_data_source_read_length_callback( nghttp2_session_callbacks *cbs, nghttp2_data_source_read_length_callback data_source_read_length_callback); +#endif /* NGHTTP2_NO_SSIZE_T */ + +/** + * @function + * + * Sets callback function determine the length allowed in + * :type:`nghttp2_data_source_read_callback2`. + */ +NGHTTP2_EXTERN void +nghttp2_session_callbacks_set_data_source_read_length_callback2( + nghttp2_session_callbacks *cbs, + nghttp2_data_source_read_length_callback2 data_source_read_length_callback); + /** * @function * @@ -2326,15 +2736,22 @@ NGHTTP2_EXTERN void nghttp2_session_callbacks_set_on_begin_frame_callback( * * Sets callback function invoked when * :enum:`nghttp2_data_flag.NGHTTP2_DATA_FLAG_NO_COPY` is used in - * :type:`nghttp2_data_source_read_callback` to avoid data copy. + * :type:`nghttp2_data_source_read_callback2` to avoid data copy. */ NGHTTP2_EXTERN void nghttp2_session_callbacks_set_send_data_callback( nghttp2_session_callbacks *cbs, nghttp2_send_data_callback send_data_callback); +#ifndef NGHTTP2_NO_SSIZE_T /** * @function * + * .. warning:: + * + * Deprecated. Use + * `nghttp2_session_callbacks_set_pack_extension_callback2()` with + * :type:`nghttp2_pack_extension_callback2` instead. + * * Sets callback function invoked when the library asks the * application to pack extension frame payload in wire format. */ @@ -2342,6 +2759,18 @@ NGHTTP2_EXTERN void nghttp2_session_callbacks_set_pack_extension_callback( nghttp2_session_callbacks *cbs, nghttp2_pack_extension_callback pack_extension_callback); +#endif /* NGHTTP2_NO_SSIZE_T */ + +/** + * @function + * + * Sets callback function invoked when the library asks the + * application to pack extension frame payload in wire format. + */ +NGHTTP2_EXTERN void nghttp2_session_callbacks_set_pack_extension_callback2( + nghttp2_session_callbacks *cbs, + nghttp2_pack_extension_callback2 pack_extension_callback); + /** * @function * @@ -2366,12 +2795,15 @@ nghttp2_session_callbacks_set_on_extension_chunk_recv_callback( /** * @function * + * .. warning:: + * + * Deprecated. Use + * `nghttp2_session_callbacks_set_error_callback2()` with + * :type:`nghttp2_error_callback2` instead. + * * Sets callback function invoked when library tells error message to * the application. * - * This function is deprecated. The new application should use - * `nghttp2_session_callbacks_set_error_callback2()`. - * * If both :type:`nghttp2_error_callback` and * :type:`nghttp2_error_callback2` are set, the latter takes * precedence. @@ -2568,7 +3000,7 @@ nghttp2_option_set_peer_max_concurrent_streams(nghttp2_option *option, * * If this option is not used or used with zero value, if MAGIC does * not match :macro:`NGHTTP2_CLIENT_MAGIC`, `nghttp2_session_recv()` - * and `nghttp2_session_mem_recv()` will return error + * and `nghttp2_session_mem_recv2()` will return error * :enum:`nghttp2_error.NGHTTP2_ERR_BAD_CLIENT_MAGIC`, which is fatal * error. */ @@ -2781,7 +3213,7 @@ nghttp2_option_set_stream_reset_rate_limit(nghttp2_option *option, * does not store |callbacks|. The |user_data| is an arbitrary user * supplied data, which will be passed to the callback functions. * - * The :type:`nghttp2_send_callback` must be specified. If the + * The :type:`nghttp2_send_callback2` must be specified. If the * application code uses `nghttp2_session_recv()`, the * :type:`nghttp2_recv_callback` must be specified. The other members * of |callbacks| can be ``NULL``. @@ -2807,7 +3239,7 @@ nghttp2_session_client_new(nghttp2_session **session_ptr, * does not store |callbacks|. The |user_data| is an arbitrary user * supplied data, which will be passed to the callback functions. * - * The :type:`nghttp2_send_callback` must be specified. If the + * The :type:`nghttp2_send_callback2` must be specified. If the * application code uses `nghttp2_session_recv()`, the * :type:`nghttp2_recv_callback` must be specified. The other members * of |callbacks| can be ``NULL``. @@ -2943,7 +3375,7 @@ NGHTTP2_EXTERN void nghttp2_session_del(nghttp2_session *session); * This function retrieves the highest prioritized frame from the * outbound queue and sends it to the remote peer. It does this as * many times as possible until the user callback - * :type:`nghttp2_send_callback` returns + * :type:`nghttp2_send_callback2` returns * :enum:`nghttp2_error.NGHTTP2_ERR_WOULDBLOCK`, the outbound queue * becomes empty or flow control is triggered (remote window size * becomes depleted or maximum number of concurrent streams is @@ -2973,7 +3405,7 @@ NGHTTP2_EXTERN void nghttp2_session_del(nghttp2_session *session); * :type:`nghttp2_on_frame_not_send_callback` is invoked. Abort * the following steps. * - * 8. :type:`nghttp2_send_callback` is invoked one or more times to + * 8. :type:`nghttp2_send_callback2` is invoked one or more times to * send the frame. * * 9. :type:`nghttp2_on_frame_send_callback` is invoked. @@ -2992,9 +3424,14 @@ NGHTTP2_EXTERN void nghttp2_session_del(nghttp2_session *session); */ NGHTTP2_EXTERN int nghttp2_session_send(nghttp2_session *session); +#ifndef NGHTTP2_NO_SSIZE_T /** * @function * + * .. warning:: + * + * Deprecated. Use `nghttp2_session_mem_send2()` instead. + * * Returns the serialized data to send. * * This function behaves like `nghttp2_session_send()` except that it @@ -3034,6 +3471,50 @@ NGHTTP2_EXTERN int nghttp2_session_send(nghttp2_session *session); NGHTTP2_EXTERN ssize_t nghttp2_session_mem_send(nghttp2_session *session, const uint8_t **data_ptr); +#endif /* NGHTTP2_NO_SSIZE_T */ + +/** + * @function + * + * Returns the serialized data to send. + * + * This function behaves like `nghttp2_session_send()` except that it + * does not use :type:`nghttp2_send_callback2` to transmit data. + * Instead, it assigns the pointer to the serialized data to the + * |*data_ptr| and returns its length. The other callbacks are called + * in the same way as they are in `nghttp2_session_send()`. + * + * If no data is available to send, this function returns 0. + * + * This function may not return all serialized data in one invocation. + * To get all data, call this function repeatedly until it returns 0 + * or one of negative error codes. + * + * The assigned |*data_ptr| is valid until the next call of + * `nghttp2_session_mem_send2()` or `nghttp2_session_send()`. + * + * The caller must send all data before sending the next chunk of + * data. + * + * This function returns the length of the data pointed by the + * |*data_ptr| if it succeeds, or one of the following negative error + * codes: + * + * :enum:`nghttp2_error.NGHTTP2_ERR_NOMEM` + * Out of memory. + * + * .. note:: + * + * This function may produce very small byte string. If that is the + * case, and application disables Nagle algorithm (``TCP_NODELAY``), + * then writing this small chunk leads to very small packet, and it + * is very inefficient. An application should be responsible to + * buffer up small chunks of data as necessary to avoid this + * situation. + */ +NGHTTP2_EXTERN nghttp2_ssize +nghttp2_session_mem_send2(nghttp2_session *session, const uint8_t **data_ptr); + /** * @function * @@ -3104,9 +3585,14 @@ NGHTTP2_EXTERN ssize_t nghttp2_session_mem_send(nghttp2_session *session, */ NGHTTP2_EXTERN int nghttp2_session_recv(nghttp2_session *session); +#ifndef NGHTTP2_NO_SSIZE_T /** * @function * + * .. warning:: + * + * Deprecated. Use `nghttp2_session_mem_recv2()` instead. + * * Processes data |in| as an input from the remote endpoint. The * |inlen| indicates the number of bytes to receive in the |in|. * @@ -3145,6 +3631,49 @@ NGHTTP2_EXTERN ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, size_t inlen); +#endif /* NGHTTP2_NO_SSIZE_T */ + +/** + * @function + * + * Processes data |in| as an input from the remote endpoint. The + * |inlen| indicates the number of bytes to receive in the |in|. + * + * This function behaves like `nghttp2_session_recv()` except that it + * does not use :type:`nghttp2_recv_callback` to receive data; the + * |in| is the only data for the invocation of this function. If all + * bytes are processed, this function returns. The other callbacks + * are called in the same way as they are in `nghttp2_session_recv()`. + * + * In the current implementation, this function always tries to + * processes |inlen| bytes of input data unless either an error occurs or + * :enum:`nghttp2_error.NGHTTP2_ERR_PAUSE` is returned from + * :type:`nghttp2_on_header_callback` or + * :type:`nghttp2_on_data_chunk_recv_callback`. If + * :enum:`nghttp2_error.NGHTTP2_ERR_PAUSE` is used, the return value + * includes the number of bytes which was used to produce the data or + * frame for the callback. + * + * This function returns the number of processed bytes, or one of the + * following negative error codes: + * + * :enum:`nghttp2_error.NGHTTP2_ERR_NOMEM` + * Out of memory. + * :enum:`nghttp2_error.NGHTTP2_ERR_CALLBACK_FAILURE` + * The callback function failed. + * :enum:`nghttp2_error.NGHTTP2_ERR_BAD_CLIENT_MAGIC` + * Invalid client magic was detected. This error only returns + * when |session| was configured as server and + * `nghttp2_option_set_no_recv_client_magic()` is not used with + * nonzero value. + * :enum:`nghttp2_error.NGHTTP2_ERR_FLOODED` + * Flooding was detected in this HTTP/2 session, and it must be + * closed. This is most likely caused by misbehaviour of peer. + */ +NGHTTP2_EXTERN nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session, + const uint8_t *in, + size_t inlen); + /** * @function * @@ -3190,7 +3719,7 @@ NGHTTP2_EXTERN int nghttp2_session_want_write(nghttp2_session *session); * @function * * Returns stream_user_data for the stream |stream_id|. The - * stream_user_data is provided by `nghttp2_submit_request()`, + * stream_user_data is provided by `nghttp2_submit_request2()`, * `nghttp2_submit_headers()` or * `nghttp2_session_set_stream_user_data()`. Unless it is set using * `nghttp2_session_set_stream_user_data()`, if the stream is @@ -3626,6 +4155,13 @@ NGHTTP2_EXTERN int nghttp2_session_consume_stream(nghttp2_session *session, /** * @function * + * .. warning:: + * + * Deprecated. :rfc:`7540` priorities are deprecated by + * :rfc:`9113`. Consider migrating to :rfc:`9218` extensible + * prioritization scheme. In the future release after the end of + * 2024, this function will always return 0 without doing anything. + * * Changes priority of existing stream denoted by |stream_id|. The * new priority specification is |pri_spec|. * @@ -3665,6 +4201,13 @@ nghttp2_session_change_stream_priority(nghttp2_session *session, /** * @function * + * .. warning:: + * + * Deprecated. :rfc:`7540` priorities are deprecated by + * :rfc:`9113`. Consider migrating to :rfc:`9218` extensible + * prioritization scheme. In the future release after the end of + * 2024, this function will always return 0 without doing anything. + * * Creates idle stream with the given |stream_id|, and priority * |pri_spec|. * @@ -3715,10 +4258,6 @@ nghttp2_session_create_idle_stream(nghttp2_session *session, int32_t stream_id, /** * @function * - * Performs post-process of HTTP Upgrade request. This function can - * be called from both client and server, but the behavior is very - * different in each other. - * * .. warning:: * * This function is deprecated in favor of @@ -3730,6 +4269,10 @@ nghttp2_session_create_idle_stream(nghttp2_session *session, int32_t stream_id, * HEAD is used in request, the length of response body must be 0 * regardless of value included in content-length header field. * + * Performs post-process of HTTP Upgrade request. This function can + * be called from both client and server, but the behavior is very + * different in each other. + * * If called from client side, the |settings_payload| must be the * value sent in ``HTTP2-Settings`` header field and must be decoded * by base64url decoder. The |settings_payloadlen| is the length of @@ -3809,9 +4352,14 @@ NGHTTP2_EXTERN int nghttp2_session_upgrade2(nghttp2_session *session, int head_request, void *stream_user_data); +#ifndef NGHTTP2_NO_SSIZE_T /** * @function * + * .. warning:: + * + * Deprecated. Use `nghttp2_pack_settings_payload2()` instead. + * * Serializes the SETTINGS values |iv| in the |buf|. The size of the * |buf| is specified by |buflen|. The number of entries in the |iv| * array is given by |niv|. The required space in |buf| for the |niv| @@ -3833,6 +4381,32 @@ NGHTTP2_EXTERN int nghttp2_session_upgrade2(nghttp2_session *session, NGHTTP2_EXTERN ssize_t nghttp2_pack_settings_payload( uint8_t *buf, size_t buflen, const nghttp2_settings_entry *iv, size_t niv); +#endif /* NGHTTP2_NO_SSIZE_T */ + +/** + * @function + * + * Serializes the SETTINGS values |iv| in the |buf|. The size of the + * |buf| is specified by |buflen|. The number of entries in the |iv| + * array is given by |niv|. The required space in |buf| for the |niv| + * entries is ``6*niv`` bytes and if the given buffer is too small, an + * error is returned. This function is used mainly for creating a + * SETTINGS payload to be sent with the ``HTTP2-Settings`` header + * field in an HTTP Upgrade request. The data written in |buf| is NOT + * base64url encoded and the application is responsible for encoding. + * + * This function returns the number of bytes written in |buf|, or one + * of the following negative error codes: + * + * :enum:`nghttp2_error.NGHTTP2_ERR_INVALID_ARGUMENT` + * The |iv| contains duplicate settings ID or invalid value. + * + * :enum:`nghttp2_error.NGHTTP2_ERR_INSUFF_BUFSIZE` + * The provided |buflen| size is too small to hold the output. + */ +NGHTTP2_EXTERN nghttp2_ssize nghttp2_pack_settings_payload2( + uint8_t *buf, size_t buflen, const nghttp2_settings_entry *iv, size_t niv); + /** * @function * @@ -3854,6 +4428,12 @@ NGHTTP2_EXTERN const char *nghttp2_http2_strerror(uint32_t error_code); /** * @function * + * .. warning:: + * + * Deprecated. :rfc:`7540` priorities are deprecated by + * :rfc:`9113`. Consider migrating to :rfc:`9218` extensible + * prioritization scheme. + * * Initializes |pri_spec| with the |stream_id| of the stream to depend * on with |weight| and its exclusive flag. If |exclusive| is * nonzero, exclusive flag is set. @@ -3868,6 +4448,12 @@ NGHTTP2_EXTERN void nghttp2_priority_spec_init(nghttp2_priority_spec *pri_spec, /** * @function * + * .. warning:: + * + * Deprecated. :rfc:`7540` priorities are deprecated by + * :rfc:`9113`. Consider migrating to :rfc:`9218` extensible + * prioritization scheme. + * * Initializes |pri_spec| with the default values. The default values * are: stream_id = 0, weight = :macro:`NGHTTP2_DEFAULT_WEIGHT` and * exclusive = 0. @@ -3878,18 +4464,29 @@ nghttp2_priority_spec_default_init(nghttp2_priority_spec *pri_spec); /** * @function * + * .. warning:: + * + * Deprecated. :rfc:`7540` priorities are deprecated by + * :rfc:`9113`. Consider migrating to :rfc:`9218` extensible + * prioritization scheme. + * * Returns nonzero if the |pri_spec| is filled with default values. */ NGHTTP2_EXTERN int nghttp2_priority_spec_check_default(const nghttp2_priority_spec *pri_spec); +#ifndef NGHTTP2_NO_SSIZE_T /** * @function * + * .. warning:: + * + * Deprecated. Use `nghttp2_submit_request2()` instead. + * * Submits HEADERS frame and optionally one or more DATA frames. * - * The |pri_spec| is priority specification of this request. ``NULL`` - * means the default priority (see + * The |pri_spec| is a deprecated priority specification of this + * request. ``NULL`` means the default priority (see * `nghttp2_priority_spec_default_init()`). To specify the priority, * use `nghttp2_priority_spec_init()`. If |pri_spec| is not ``NULL``, * this function will copy its data members. @@ -3970,11 +4567,107 @@ NGHTTP2_EXTERN int32_t nghttp2_submit_request( const nghttp2_nv *nva, size_t nvlen, const nghttp2_data_provider *data_prd, void *stream_user_data); +#endif /* NGHTTP2_NO_SSIZE_T */ + /** * @function * - * Submits response HEADERS frame and optionally one or more DATA - * frames against the stream |stream_id|. + * Submits HEADERS frame and optionally one or more DATA frames. + * + * The |pri_spec| is a deprecated priority specification of this + * request. ``NULL`` means the default priority (see + * `nghttp2_priority_spec_default_init()`). To specify the priority, + * use `nghttp2_priority_spec_init()`. If |pri_spec| is not ``NULL``, + * this function will copy its data members. In the future release + * after the end of 2024, this function will ignore |pri_spec| and + * behave as if ``NULL`` is given. + * + * The ``pri_spec->weight`` must be in [:macro:`NGHTTP2_MIN_WEIGHT`, + * :macro:`NGHTTP2_MAX_WEIGHT`], inclusive. If ``pri_spec->weight`` + * is strictly less than :macro:`NGHTTP2_MIN_WEIGHT`, it becomes + * :macro:`NGHTTP2_MIN_WEIGHT`. If it is strictly greater than + * :macro:`NGHTTP2_MAX_WEIGHT`, it becomes + * :macro:`NGHTTP2_MAX_WEIGHT`. + * + * If + * :enum:`nghttp2_settings_id.NGHTTP2_SETTINGS_NO_RFC7540_PRIORITIES` + * of value of 1 is received by a remote endpoint, |pri_spec| is + * ignored, and treated as if ``NULL`` is specified. + * + * The |nva| is an array of name/value pair :type:`nghttp2_nv` with + * |nvlen| elements. The application is responsible to include + * required pseudo-header fields (header field whose name starts with + * ":") in |nva| and must place pseudo-headers before regular header + * fields. + * + * This function creates copies of all name/value pairs in |nva|. It + * also lower-cases all names in |nva|. The order of elements in + * |nva| is preserved. For header fields with + * :enum:`nghttp2_nv_flag.NGHTTP2_NV_FLAG_NO_COPY_NAME` and + * :enum:`nghttp2_nv_flag.NGHTTP2_NV_FLAG_NO_COPY_VALUE` are set, + * header field name and value are not copied respectively. With + * :enum:`nghttp2_nv_flag.NGHTTP2_NV_FLAG_NO_COPY_NAME`, application + * is responsible to pass header field name in lowercase. The + * application should maintain the references to them until + * :type:`nghttp2_on_frame_send_callback` or + * :type:`nghttp2_on_frame_not_send_callback` is called. + * + * HTTP/2 specification has requirement about header fields in the + * request HEADERS. See the specification for more details. + * + * If |data_prd| is not ``NULL``, it provides data which will be sent + * in subsequent DATA frames. In this case, a method that allows + * request message bodies + * (https://tools.ietf.org/html/rfc7231#section-4) must be specified + * with ``:method`` key in |nva| (e.g. ``POST``). This function does + * not take ownership of the |data_prd|. The function copies the + * members of the |data_prd|. If |data_prd| is ``NULL``, HEADERS have + * END_STREAM set. The |stream_user_data| is data associated to the + * stream opened by this request and can be an arbitrary pointer, + * which can be retrieved later by + * `nghttp2_session_get_stream_user_data()`. + * + * This function returns assigned stream ID if it succeeds, or one of + * the following negative error codes: + * + * :enum:`nghttp2_error.NGHTTP2_ERR_NOMEM` + * Out of memory. + * :enum:`nghttp2_error.NGHTTP2_ERR_STREAM_ID_NOT_AVAILABLE` + * No stream ID is available because maximum stream ID was + * reached. + * :enum:`nghttp2_error.NGHTTP2_ERR_INVALID_ARGUMENT` + * Trying to depend on itself (new stream ID equals + * ``pri_spec->stream_id``). + * :enum:`nghttp2_error.NGHTTP2_ERR_PROTO` + * The |session| is server session. + * + * .. warning:: + * + * This function returns assigned stream ID if it succeeds. But + * that stream is not created yet. The application must not submit + * frame to that stream ID before + * :type:`nghttp2_before_frame_send_callback` is called for this + * frame. This means `nghttp2_session_get_stream_user_data()` does + * not work before the callback. But + * `nghttp2_session_set_stream_user_data()` handles this situation + * specially, and it can set data to a stream during this period. + * + */ +NGHTTP2_EXTERN int32_t nghttp2_submit_request2( + nghttp2_session *session, const nghttp2_priority_spec *pri_spec, + const nghttp2_nv *nva, size_t nvlen, const nghttp2_data_provider2 *data_prd, + void *stream_user_data); + +#ifndef NGHTTP2_NO_SSIZE_T +/** + * @function + * + * .. warning:: + * + * Deprecated. Use `nghttp2_submit_response2()` instead. + * + * Submits response HEADERS frame and optionally one or more DATA + * frames against the stream |stream_id|. * * The |nva| is an array of name/value pair :type:`nghttp2_nv` with * |nvlen| elements. The application is responsible to include @@ -4039,6 +4732,77 @@ nghttp2_submit_response(nghttp2_session *session, int32_t stream_id, const nghttp2_nv *nva, size_t nvlen, const nghttp2_data_provider *data_prd); +#endif /* NGHTTP2_NO_SSIZE_T */ + +/** + * @function + * + * Submits response HEADERS frame and optionally one or more DATA + * frames against the stream |stream_id|. + * + * The |nva| is an array of name/value pair :type:`nghttp2_nv` with + * |nvlen| elements. The application is responsible to include + * required pseudo-header fields (header field whose name starts with + * ":") in |nva| and must place pseudo-headers before regular header + * fields. + * + * This function creates copies of all name/value pairs in |nva|. It + * also lower-cases all names in |nva|. The order of elements in + * |nva| is preserved. For header fields with + * :enum:`nghttp2_nv_flag.NGHTTP2_NV_FLAG_NO_COPY_NAME` and + * :enum:`nghttp2_nv_flag.NGHTTP2_NV_FLAG_NO_COPY_VALUE` are set, + * header field name and value are not copied respectively. With + * :enum:`nghttp2_nv_flag.NGHTTP2_NV_FLAG_NO_COPY_NAME`, application + * is responsible to pass header field name in lowercase. The + * application should maintain the references to them until + * :type:`nghttp2_on_frame_send_callback` or + * :type:`nghttp2_on_frame_not_send_callback` is called. + * + * HTTP/2 specification has requirement about header fields in the + * response HEADERS. See the specification for more details. + * + * If |data_prd| is not ``NULL``, it provides data which will be sent + * in subsequent DATA frames. This function does not take ownership + * of the |data_prd|. The function copies the members of the + * |data_prd|. If |data_prd| is ``NULL``, HEADERS will have + * END_STREAM flag set. + * + * This method can be used as normal HTTP response and push response. + * When pushing a resource using this function, the |session| must be + * configured using `nghttp2_session_server_new()` or its variants and + * the target stream denoted by the |stream_id| must be reserved using + * `nghttp2_submit_push_promise()`. + * + * To send non-final response headers (e.g., HTTP status 101), don't + * use this function because this function half-closes the outbound + * stream. Instead, use `nghttp2_submit_headers()` for this purpose. + * + * This function returns 0 if it succeeds, or one of the following + * negative error codes: + * + * :enum:`nghttp2_error.NGHTTP2_ERR_NOMEM` + * Out of memory. + * :enum:`nghttp2_error.NGHTTP2_ERR_INVALID_ARGUMENT` + * The |stream_id| is 0. + * :enum:`nghttp2_error.NGHTTP2_ERR_DATA_EXIST` + * DATA or HEADERS has been already submitted and not fully + * processed yet. Normally, this does not happen, but when + * application wrongly calls `nghttp2_submit_response2()` twice, + * this may happen. + * :enum:`nghttp2_error.NGHTTP2_ERR_PROTO` + * The |session| is client session. + * + * .. warning:: + * + * Calling this function twice for the same stream ID may lead to + * program crash. It is generally considered to a programming error + * to commit response twice. + */ +NGHTTP2_EXTERN int +nghttp2_submit_response2(nghttp2_session *session, int32_t stream_id, + const nghttp2_nv *nva, size_t nvlen, + const nghttp2_data_provider2 *data_prd); + /** * @function * @@ -4064,22 +4828,23 @@ nghttp2_submit_response(nghttp2_session *session, int32_t stream_id, * DATA without END_STREAM flat set. The library does not enforce * this requirement, and applications should do this for themselves. * If `nghttp2_submit_trailer()` is called before any response HEADERS - * submission (usually by `nghttp2_submit_response()`), the content of - * |nva| will be sent as response headers, which will result in error. + * submission (usually by `nghttp2_submit_response2()`), the content + * of |nva| will be sent as response headers, which will result in + * error. * * This function has the same effect with `nghttp2_submit_headers()`, * with flags = :enum:`nghttp2_flag.NGHTTP2_FLAG_END_STREAM` and both * pri_spec and stream_user_data to NULL. * - * To submit trailer fields after `nghttp2_submit_response()` is + * To submit trailer fields after `nghttp2_submit_response2()` is * called, the application has to specify - * :type:`nghttp2_data_provider` to `nghttp2_submit_response()`. - * Inside of :type:`nghttp2_data_source_read_callback`, when setting + * :type:`nghttp2_data_provider2` to `nghttp2_submit_response2()`. + * Inside of :type:`nghttp2_data_source_read_callback2`, when setting * :enum:`nghttp2_data_flag.NGHTTP2_DATA_FLAG_EOF`, also set * :enum:`nghttp2_data_flag.NGHTTP2_DATA_FLAG_NO_END_STREAM`. After * that, the application can send trailer fields using * `nghttp2_submit_trailer()`. `nghttp2_submit_trailer()` can be used - * inside :type:`nghttp2_data_source_read_callback`. + * inside :type:`nghttp2_data_source_read_callback2`. * * This function returns 0 if it succeeds and |stream_id| is -1. * Otherwise, this function returns 0 if it succeeds, or one of the @@ -4114,11 +4879,13 @@ NGHTTP2_EXTERN int nghttp2_submit_trailer(nghttp2_session *session, * assigned stream ID will be returned. Otherwise, specify stream ID * in |stream_id|. * - * The |pri_spec| is priority specification of this request. ``NULL`` - * means the default priority (see + * The |pri_spec| is a deprecated priority specification of this + * request. ``NULL`` means the default priority (see * `nghttp2_priority_spec_default_init()`). To specify the priority, * use `nghttp2_priority_spec_init()`. If |pri_spec| is not ``NULL``, - * this function will copy its data members. + * this function will copy its data members. In the future release + * after the end of 2024, this function will ignore |pri_spec| and + * behave as if ``NULL`` is given. * * The ``pri_spec->weight`` must be in [:macro:`NGHTTP2_MIN_WEIGHT`, * :macro:`NGHTTP2_MAX_WEIGHT`], inclusive. If ``pri_spec->weight`` @@ -4156,8 +4923,8 @@ NGHTTP2_EXTERN int nghttp2_submit_trailer(nghttp2_session *session, * * This function is low-level in a sense that the application code can * specify flags directly. For usual HTTP request, - * `nghttp2_submit_request()` is useful. Likewise, for HTTP response, - * prefer `nghttp2_submit_response()`. + * `nghttp2_submit_request2()` is useful. Likewise, for HTTP + * response, prefer `nghttp2_submit_response2()`. * * This function returns newly assigned stream ID if it succeeds and * |stream_id| is -1. Otherwise, this function returns 0 if it @@ -4192,9 +4959,14 @@ NGHTTP2_EXTERN int32_t nghttp2_submit_headers( const nghttp2_priority_spec *pri_spec, const nghttp2_nv *nva, size_t nvlen, void *stream_user_data); +#ifndef NGHTTP2_NO_SSIZE_T /** * @function * + * .. warning:: + * + * Deprecated. Use `nghttp2_submit_data2()` instead. + * * Submits one or more DATA frames to the stream |stream_id|. The * data to be sent are provided by |data_prd|. If |flags| contains * :enum:`nghttp2_flag.NGHTTP2_FLAG_END_STREAM`, the last DATA frame @@ -4237,19 +5009,73 @@ NGHTTP2_EXTERN int nghttp2_submit_data(nghttp2_session *session, uint8_t flags, int32_t stream_id, const nghttp2_data_provider *data_prd); +#endif /* NGHTTP2_NO_SSIZE_T */ + +/** + * @function + * + * Submits one or more DATA frames to the stream |stream_id|. The + * data to be sent are provided by |data_prd|. If |flags| contains + * :enum:`nghttp2_flag.NGHTTP2_FLAG_END_STREAM`, the last DATA frame + * has END_STREAM flag set. + * + * This function does not take ownership of the |data_prd|. The + * function copies the members of the |data_prd|. + * + * This function returns 0 if it succeeds, or one of the following + * negative error codes: + * + * :enum:`nghttp2_error.NGHTTP2_ERR_NOMEM` + * Out of memory. + * :enum:`nghttp2_error.NGHTTP2_ERR_DATA_EXIST` + * DATA or HEADERS has been already submitted and not fully + * processed yet. + * :enum:`nghttp2_error.NGHTTP2_ERR_INVALID_ARGUMENT` + * The |stream_id| is 0. + * :enum:`nghttp2_error.NGHTTP2_ERR_STREAM_CLOSED` + * The stream was already closed; or the |stream_id| is invalid. + * + * .. note:: + * + * Currently, only one DATA or HEADERS is allowed for a stream at a + * time. Submitting these frames more than once before first DATA + * or HEADERS is finished results in + * :enum:`nghttp2_error.NGHTTP2_ERR_DATA_EXIST` error code. The + * earliest callback which tells that previous frame is done is + * :type:`nghttp2_on_frame_send_callback`. In side that callback, + * new data can be submitted using `nghttp2_submit_data2()`. Of + * course, all data except for last one must not have + * :enum:`nghttp2_flag.NGHTTP2_FLAG_END_STREAM` flag set in |flags|. + * This sounds a bit complicated, and we recommend to use + * `nghttp2_submit_request2()` and `nghttp2_submit_response2()` to + * avoid this cascading issue. The experience shows that for HTTP + * use, these two functions are enough to implement both client and + * server. + */ +NGHTTP2_EXTERN int nghttp2_submit_data2(nghttp2_session *session, uint8_t flags, + int32_t stream_id, + const nghttp2_data_provider2 *data_prd); + /** * @function * + * .. warning:: + * + * Deprecated. :rfc:`7540` priorities are deprecated by + * :rfc:`9113`. Consider migrating to :rfc:`9218` extensible + * prioritization scheme. In the future release after the end of + * 2024, this function will always return 0 without doing anything. + * * Submits PRIORITY frame to change the priority of stream |stream_id| * to the priority specification |pri_spec|. * * The |flags| is currently ignored and should be * :enum:`nghttp2_flag.NGHTTP2_FLAG_NONE`. * - * The |pri_spec| is priority specification of this request. ``NULL`` - * is not allowed for this function. To specify the priority, use - * `nghttp2_priority_spec_init()`. This function will copy its data - * members. + * The |pri_spec| is a deprecated priority specification of this + * request. ``NULL`` is not allowed for this function. To specify the + * priority, use `nghttp2_priority_spec_init()`. This function will + * copy its data members. * * The ``pri_spec->weight`` must be in [:macro:`NGHTTP2_MIN_WEIGHT`, * :macro:`NGHTTP2_MAX_WEIGHT`], inclusive. If ``pri_spec->weight`` @@ -4429,7 +5255,7 @@ NGHTTP2_EXTERN int nghttp2_submit_settings(nghttp2_session *session, * The client side is not allowed to use this function. * * To submit response headers and data, use - * `nghttp2_submit_response()`. + * `nghttp2_submit_response2()`. * * This function returns assigned promised stream ID if it succeeds, * or one of the following negative error codes: @@ -4568,10 +5394,11 @@ nghttp2_session_get_last_proc_stream_id(nghttp2_session *session); * reasons are: session is server; stream ID has been spent; GOAWAY * has been sent or received. * - * The application can call `nghttp2_submit_request()` without - * consulting this function. In that case, `nghttp2_submit_request()` - * may return error. Or, request is failed to sent, and - * :type:`nghttp2_on_stream_close_callback` is called. + * The application can call `nghttp2_submit_request2()` without + * consulting this function. In that case, + * `nghttp2_submit_request2()` may return error. Or, request is + * failed to sent, and :type:`nghttp2_on_stream_close_callback` is + * called. */ NGHTTP2_EXTERN int nghttp2_session_check_request_allowed(nghttp2_session *session); @@ -4673,11 +5500,11 @@ nghttp2_session_set_local_window_size(nghttp2_session *session, uint8_t flags, * Application can pass arbitrary frame flags and stream ID in |flags| * and |stream_id| respectively. The |payload| is opaque pointer, and * it can be accessible though ``frame->ext.payload`` in - * :type:`nghttp2_pack_extension_callback`. The library will not own + * :type:`nghttp2_pack_extension_callback2`. The library will not own * passed |payload| pointer. * - * The application must set :type:`nghttp2_pack_extension_callback` - * using `nghttp2_session_callbacks_set_pack_extension_callback()`. + * The application must set :type:`nghttp2_pack_extension_callback2` + * using `nghttp2_session_callbacks_set_pack_extension_callback2()`. * * The application should retain the memory pointed by |payload| until * the transmission of extension frame is done (which is indicated by @@ -4685,7 +5512,7 @@ nghttp2_session_set_local_window_size(nghttp2_session *session, uint8_t flags, * (which is indicated by :type:`nghttp2_on_frame_not_send_callback`). * If application does not touch this memory region after packing it * into a wire format, application can free it inside - * :type:`nghttp2_pack_extension_callback`. + * :type:`nghttp2_pack_extension_callback2`. * * The standard HTTP/2 frame cannot be sent with this function, so * |type| must be strictly grater than 0x9. Otherwise, this function @@ -4696,7 +5523,7 @@ nghttp2_session_set_local_window_size(nghttp2_session *session, uint8_t flags, * negative error codes: * * :enum:`nghttp2_error.NGHTTP2_ERR_INVALID_STATE` - * If :type:`nghttp2_pack_extension_callback` is not set. + * If :type:`nghttp2_pack_extension_callback2` is not set. * :enum:`nghttp2_error.NGHTTP2_ERR_INVALID_ARGUMENT` * If |type| specifies standard HTTP/2 frame type. The frame * types in the rage [0x0, 0x9], both inclusive, are standard @@ -5317,9 +6144,14 @@ NGHTTP2_EXTERN int nghttp2_hd_deflate_change_table_size(nghttp2_hd_deflater *deflater, size_t settings_max_dynamic_table_size); +#ifndef NGHTTP2_NO_SSIZE_T /** * @function * + * .. warning:: + * + * Deprecated. Use `nghttp2_hd_deflate_hd2()` instead. + * * Deflates the |nva|, which has the |nvlen| name/value pairs, into * the |buf| of length |buflen|. * @@ -5349,10 +6181,48 @@ NGHTTP2_EXTERN ssize_t nghttp2_hd_deflate_hd(nghttp2_hd_deflater *deflater, const nghttp2_nv *nva, size_t nvlen); +#endif /* NGHTTP2_NO_SSIZE_T */ + /** * @function * * Deflates the |nva|, which has the |nvlen| name/value pairs, into + * the |buf| of length |buflen|. + * + * If |buf| is not large enough to store the deflated header block, + * this function fails with + * :enum:`nghttp2_error.NGHTTP2_ERR_INSUFF_BUFSIZE`. The caller + * should use `nghttp2_hd_deflate_bound()` to know the upper bound of + * buffer size required to deflate given header name/value pairs. + * + * Once this function fails, subsequent call of this function always + * returns :enum:`nghttp2_error.NGHTTP2_ERR_HEADER_COMP`. + * + * After this function returns, it is safe to delete the |nva|. + * + * This function returns the number of bytes written to |buf| if it + * succeeds, or one of the following negative error codes: + * + * :enum:`nghttp2_error.NGHTTP2_ERR_NOMEM` + * Out of memory. + * :enum:`nghttp2_error.NGHTTP2_ERR_HEADER_COMP` + * Deflation process has failed. + * :enum:`nghttp2_error.NGHTTP2_ERR_INSUFF_BUFSIZE` + * The provided |buflen| size is too small to hold the output. + */ +NGHTTP2_EXTERN nghttp2_ssize +nghttp2_hd_deflate_hd2(nghttp2_hd_deflater *deflater, uint8_t *buf, + size_t buflen, const nghttp2_nv *nva, size_t nvlen); + +#ifndef NGHTTP2_NO_SSIZE_T +/** + * @function + * + * .. warning:: + * + * Deprecated. Use `nghttp2_hd_deflate_hd_vec2()` instead. + * + * Deflates the |nva|, which has the |nvlen| name/value pairs, into * the |veclen| size of buf vector |vec|. The each size of buffer * must be set in len field of :type:`nghttp2_vec`. If and only if * one chunk is filled up completely, next chunk will be used. If @@ -5383,6 +6253,40 @@ NGHTTP2_EXTERN ssize_t nghttp2_hd_deflate_hd_vec(nghttp2_hd_deflater *deflater, const nghttp2_nv *nva, size_t nvlen); +#endif /* NGHTTP2_NO_SSIZE_T */ + +/** + * @function + * + * Deflates the |nva|, which has the |nvlen| name/value pairs, into + * the |veclen| size of buf vector |vec|. The each size of buffer + * must be set in len field of :type:`nghttp2_vec`. If and only if + * one chunk is filled up completely, next chunk will be used. If + * |vec| is not large enough to store the deflated header block, this + * function fails with + * :enum:`nghttp2_error.NGHTTP2_ERR_INSUFF_BUFSIZE`. The caller + * should use `nghttp2_hd_deflate_bound()` to know the upper bound of + * buffer size required to deflate given header name/value pairs. + * + * Once this function fails, subsequent call of this function always + * returns :enum:`nghttp2_error.NGHTTP2_ERR_HEADER_COMP`. + * + * After this function returns, it is safe to delete the |nva|. + * + * This function returns the number of bytes written to |vec| if it + * succeeds, or one of the following negative error codes: + * + * :enum:`nghttp2_error.NGHTTP2_ERR_NOMEM` + * Out of memory. + * :enum:`nghttp2_error.NGHTTP2_ERR_HEADER_COMP` + * Deflation process has failed. + * :enum:`nghttp2_error.NGHTTP2_ERR_INSUFF_BUFSIZE` + * The provided |buflen| size is too small to hold the output. + */ +NGHTTP2_EXTERN nghttp2_ssize nghttp2_hd_deflate_hd_vec2( + nghttp2_hd_deflater *deflater, const nghttp2_vec *vec, size_t veclen, + const nghttp2_nv *nva, size_t nvlen); + /** * @function * @@ -5496,7 +6400,7 @@ NGHTTP2_EXTERN void nghttp2_hd_inflate_del(nghttp2_hd_inflater *inflater); * This function must not be called while header block is being * inflated. In other words, this function must be called after * initialization of |inflater|, but before calling - * `nghttp2_hd_inflate_hd2()`, or after + * `nghttp2_hd_inflate_hd3()`, or after * `nghttp2_hd_inflate_end_headers()`. Otherwise, * `NGHTTP2_ERR_INVALID_STATE` was returned. * @@ -5534,6 +6438,7 @@ typedef enum { NGHTTP2_HD_INFLATE_EMIT = 0x02 } nghttp2_hd_inflate_flag; +#ifndef NGHTTP2_NO_SSIZE_T /** * @function * @@ -5621,9 +6526,16 @@ NGHTTP2_EXTERN ssize_t nghttp2_hd_inflate_hd(nghttp2_hd_inflater *inflater, int *inflate_flags, uint8_t *in, size_t inlen, int in_final); +#endif /* NGHTTP2_NO_SSIZE_T */ + +#ifndef NGHTTP2_NO_SSIZE_T /** * @function * + * .. warning:: + * + * Deprecated. Use `nghttp2_hd_inflate_hd3()` instead. + * * Inflates name/value block stored in |in| with length |inlen|. This * function performs decompression. For each successful emission of * header name/value pair, @@ -5710,6 +6622,95 @@ NGHTTP2_EXTERN ssize_t nghttp2_hd_inflate_hd2(nghttp2_hd_inflater *inflater, const uint8_t *in, size_t inlen, int in_final); +#endif /* NGHTTP2_NO_SSIZE_T */ + +/** + * @function + * + * Inflates name/value block stored in |in| with length |inlen|. This + * function performs decompression. For each successful emission of + * header name/value pair, + * :enum:`nghttp2_hd_inflate_flag.NGHTTP2_HD_INFLATE_EMIT` is set in + * |*inflate_flags| and name/value pair is assigned to the |nv_out| + * and the function returns. The caller must not free the members of + * |nv_out|. + * + * The |nv_out| may include pointers to the memory region in the |in|. + * The caller must retain the |in| while the |nv_out| is used. + * + * The application should call this function repeatedly until the + * ``(*inflate_flags) & NGHTTP2_HD_INFLATE_FINAL`` is nonzero and + * return value is non-negative. If that happens, all given input + * data (|inlen| bytes) are processed successfully. Then the + * application must call `nghttp2_hd_inflate_end_headers()` to prepare + * for the next header block input. + * + * In other words, if |in_final| is nonzero, and this function returns + * |inlen|, you can assert that + * :enum:`nghttp2_hd_inflate_final.NGHTTP2_HD_INFLATE_FINAL` is set in + * |*inflate_flags|. + * + * The caller can feed complete compressed header block. It also can + * feed it in several chunks. The caller must set |in_final| to + * nonzero if the given input is the last block of the compressed + * header. + * + * This function returns the number of bytes processed if it succeeds, + * or one of the following negative error codes: + * + * :enum:`nghttp2_error.NGHTTP2_ERR_NOMEM` + * Out of memory. + * :enum:`nghttp2_error.NGHTTP2_ERR_HEADER_COMP` + * Inflation process has failed. + * :enum:`nghttp2_error.NGHTTP2_ERR_BUFFER_ERROR` + * The header field name or value is too large. + * + * Example follows:: + * + * int inflate_header_block(nghttp2_hd_inflater *hd_inflater, + * uint8_t *in, size_t inlen, int final) + * { + * nghttp2_ssize rv; + * + * for(;;) { + * nghttp2_nv nv; + * int inflate_flags = 0; + * + * rv = nghttp2_hd_inflate_hd3(hd_inflater, &nv, &inflate_flags, + * in, inlen, final); + * + * if(rv < 0) { + * fprintf(stderr, "inflate failed with error code %td", rv); + * return -1; + * } + * + * in += rv; + * inlen -= rv; + * + * if(inflate_flags & NGHTTP2_HD_INFLATE_EMIT) { + * fwrite(nv.name, nv.namelen, 1, stderr); + * fprintf(stderr, ": "); + * fwrite(nv.value, nv.valuelen, 1, stderr); + * fprintf(stderr, "\n"); + * } + * if(inflate_flags & NGHTTP2_HD_INFLATE_FINAL) { + * nghttp2_hd_inflate_end_headers(hd_inflater); + * break; + * } + * if((inflate_flags & NGHTTP2_HD_INFLATE_EMIT) == 0 && + * inlen == 0) { + * break; + * } + * } + * + * return 0; + * } + * + */ +NGHTTP2_EXTERN nghttp2_ssize nghttp2_hd_inflate_hd3( + nghttp2_hd_inflater *inflater, nghttp2_nv *nv_out, int *inflate_flags, + const uint8_t *in, size_t inlen, int in_final); + /** * @function * @@ -5783,8 +6784,8 @@ typedef struct nghttp2_stream nghttp2_stream; * `nghttp2_session_get_root_stream()`) if 0 is given in |stream_id|. * * Unless |stream_id| == 0, the returned pointer is valid until next - * call of `nghttp2_session_send()`, `nghttp2_session_mem_send()`, - * `nghttp2_session_recv()`, and `nghttp2_session_mem_recv()`. + * call of `nghttp2_session_send()`, `nghttp2_session_mem_send2()`, + * `nghttp2_session_recv()`, and `nghttp2_session_mem_recv2()`. */ NGHTTP2_EXTERN nghttp2_stream * nghttp2_session_find_stream(nghttp2_session *session, int32_t stream_id); @@ -5838,6 +6839,12 @@ nghttp2_stream_get_state(nghttp2_stream *stream); /** * @function * + * .. warning:: + * + * Deprecated. :rfc:`7540` priorities are deprecated by + * :rfc:`9113`. Consider migrating to :rfc:`9218` extensible + * prioritization scheme. + * * Returns root of dependency tree, which is imaginary stream with * stream ID 0. The returned pointer is valid until |session| is * freed by `nghttp2_session_del()`. @@ -5848,6 +6855,13 @@ nghttp2_session_get_root_stream(nghttp2_session *session); /** * @function * + * .. warning:: + * + * Deprecated. :rfc:`7540` priorities are deprecated by + * :rfc:`9113`. Consider migrating to :rfc:`9218` extensible + * prioritization scheme. In the future release after the end of + * 2024, this function will always return NULL. + * * Returns the parent stream of |stream| in dependency tree. Returns * NULL if there is no such stream. */ @@ -5859,6 +6873,13 @@ NGHTTP2_EXTERN int32_t nghttp2_stream_get_stream_id(nghttp2_stream *stream); /** * @function * + * .. warning:: + * + * Deprecated. :rfc:`7540` priorities are deprecated by + * :rfc:`9113`. Consider migrating to :rfc:`9218` extensible + * prioritization scheme. In the future release after the end of + * 2024, this function will always return NULL. + * * Returns the next sibling stream of |stream| in dependency tree. * Returns NULL if there is no such stream. */ @@ -5868,6 +6889,13 @@ nghttp2_stream_get_next_sibling(nghttp2_stream *stream); /** * @function * + * .. warning:: + * + * Deprecated. :rfc:`7540` priorities are deprecated by + * :rfc:`9113`. Consider migrating to :rfc:`9218` extensible + * prioritization scheme. In the future release after the end of + * 2024, this function will always return NULL. + * * Returns the previous sibling stream of |stream| in dependency tree. * Returns NULL if there is no such stream. */ @@ -5877,6 +6905,13 @@ nghttp2_stream_get_previous_sibling(nghttp2_stream *stream); /** * @function * + * .. warning:: + * + * Deprecated. :rfc:`7540` priorities are deprecated by + * :rfc:`9113`. Consider migrating to :rfc:`9218` extensible + * prioritization scheme. In the future release after the end of + * 2024, this function will always return NULL. + * * Returns the first child stream of |stream| in dependency tree. * Returns NULL if there is no such stream. */ @@ -5886,6 +6921,14 @@ nghttp2_stream_get_first_child(nghttp2_stream *stream); /** * @function * + * .. warning:: + * + * Deprecated. :rfc:`7540` priorities are deprecated by + * :rfc:`9113`. Consider migrating to :rfc:`9218` extensible + * prioritization scheme. In the future release after the end of + * 2024, this function will always return + * :macro:`NGHTTP2_DEFAULT_WEIGHT`. + * * Returns dependency weight to the parent stream of |stream|. */ NGHTTP2_EXTERN int32_t nghttp2_stream_get_weight(nghttp2_stream *stream); @@ -5893,6 +6936,13 @@ NGHTTP2_EXTERN int32_t nghttp2_stream_get_weight(nghttp2_stream *stream); /** * @function * + * .. warning:: + * + * Deprecated. :rfc:`7540` priorities are deprecated by + * :rfc:`9113`. Consider migrating to :rfc:`9218` extensible + * prioritization scheme. In the future release after the end of + * 2024, this function will always return 0. + * * Returns the sum of the weight for |stream|'s children. */ NGHTTP2_EXTERN int32_t diff --git a/deps/nghttp2/lib/includes/nghttp2/nghttp2ver.h b/deps/nghttp2/lib/includes/nghttp2/nghttp2ver.h index 518755bbab7914..d38b89adc6268a 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.59.0" +#define NGHTTP2_VERSION "1.60.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 0x013b00 +#define NGHTTP2_VERSION_NUM 0x013c00 #endif /* NGHTTP2VER_H */ diff --git a/deps/nghttp2/lib/nghttp2_buf.c b/deps/nghttp2/lib/nghttp2_buf.c index a32844712e4493..101035f923ec64 100644 --- a/deps/nghttp2/lib/nghttp2_buf.c +++ b/deps/nghttp2/lib/nghttp2_buf.c @@ -430,7 +430,7 @@ int nghttp2_bufs_orb_hold(nghttp2_bufs *bufs, uint8_t b) { return 0; } -ssize_t nghttp2_bufs_remove(nghttp2_bufs *bufs, uint8_t **out) { +nghttp2_ssize nghttp2_bufs_remove(nghttp2_bufs *bufs, uint8_t **out) { size_t len; nghttp2_buf_chain *chain; nghttp2_buf *buf; @@ -462,7 +462,7 @@ ssize_t nghttp2_bufs_remove(nghttp2_bufs *bufs, uint8_t **out) { *out = res; - return (ssize_t)len; + return (nghttp2_ssize)len; } size_t nghttp2_bufs_remove_copy(nghttp2_bufs *bufs, uint8_t *out) { diff --git a/deps/nghttp2/lib/nghttp2_buf.h b/deps/nghttp2/lib/nghttp2_buf.h index 45f62f16e271dc..95ff3706a232a3 100644 --- a/deps/nghttp2/lib/nghttp2_buf.h +++ b/deps/nghttp2/lib/nghttp2_buf.h @@ -349,7 +349,7 @@ int nghttp2_bufs_orb_hold(nghttp2_bufs *bufs, uint8_t b); * NGHTTP2_ERR_NOMEM * Out of memory */ -ssize_t nghttp2_bufs_remove(nghttp2_bufs *bufs, uint8_t **out); +nghttp2_ssize nghttp2_bufs_remove(nghttp2_bufs *bufs, uint8_t **out); /* * Copies all data stored in |bufs| to |out|. This function assumes diff --git a/deps/nghttp2/lib/nghttp2_callbacks.c b/deps/nghttp2/lib/nghttp2_callbacks.c index 3c38214859b17a..1776f7d276b79f 100644 --- a/deps/nghttp2/lib/nghttp2_callbacks.c +++ b/deps/nghttp2/lib/nghttp2_callbacks.c @@ -45,11 +45,21 @@ void nghttp2_session_callbacks_set_send_callback( cbs->send_callback = send_callback; } +void nghttp2_session_callbacks_set_send_callback2( + nghttp2_session_callbacks *cbs, nghttp2_send_callback2 send_callback) { + cbs->send_callback2 = send_callback; +} + void nghttp2_session_callbacks_set_recv_callback( nghttp2_session_callbacks *cbs, nghttp2_recv_callback recv_callback) { cbs->recv_callback = recv_callback; } +void nghttp2_session_callbacks_set_recv_callback2( + nghttp2_session_callbacks *cbs, nghttp2_recv_callback2 recv_callback) { + cbs->recv_callback2 = recv_callback; +} + void nghttp2_session_callbacks_set_on_frame_recv_callback( nghttp2_session_callbacks *cbs, nghttp2_on_frame_recv_callback on_frame_recv_callback) { @@ -128,12 +138,24 @@ void nghttp2_session_callbacks_set_select_padding_callback( cbs->select_padding_callback = select_padding_callback; } +void nghttp2_session_callbacks_set_select_padding_callback2( + nghttp2_session_callbacks *cbs, + nghttp2_select_padding_callback2 select_padding_callback) { + cbs->select_padding_callback2 = select_padding_callback; +} + void nghttp2_session_callbacks_set_data_source_read_length_callback( nghttp2_session_callbacks *cbs, nghttp2_data_source_read_length_callback data_source_read_length_callback) { cbs->read_length_callback = data_source_read_length_callback; } +void nghttp2_session_callbacks_set_data_source_read_length_callback2( + nghttp2_session_callbacks *cbs, nghttp2_data_source_read_length_callback2 + data_source_read_length_callback) { + cbs->read_length_callback2 = data_source_read_length_callback; +} + void nghttp2_session_callbacks_set_on_begin_frame_callback( nghttp2_session_callbacks *cbs, nghttp2_on_begin_frame_callback on_begin_frame_callback) { @@ -152,6 +174,12 @@ void nghttp2_session_callbacks_set_pack_extension_callback( cbs->pack_extension_callback = pack_extension_callback; } +void nghttp2_session_callbacks_set_pack_extension_callback2( + nghttp2_session_callbacks *cbs, + nghttp2_pack_extension_callback2 pack_extension_callback) { + cbs->pack_extension_callback2 = pack_extension_callback; +} + void nghttp2_session_callbacks_set_unpack_extension_callback( nghttp2_session_callbacks *cbs, nghttp2_unpack_extension_callback unpack_extension_callback) { diff --git a/deps/nghttp2/lib/nghttp2_callbacks.h b/deps/nghttp2/lib/nghttp2_callbacks.h index 61e51fa53638de..a611f485481e7c 100644 --- a/deps/nghttp2/lib/nghttp2_callbacks.h +++ b/deps/nghttp2/lib/nghttp2_callbacks.h @@ -35,20 +35,34 @@ * Callback functions. */ struct nghttp2_session_callbacks { + /** + * Deprecated. Use send_callback2 instead. Callback function + * invoked when the session wants to send data to the remote peer. + * This callback is not necessary if the application uses solely + * `nghttp2_session_mem_send()` to serialize data to transmit. + */ + nghttp2_send_callback send_callback; /** * Callback function invoked when the session wants to send data to * the remote peer. This callback is not necessary if the - * application uses solely `nghttp2_session_mem_send()` to serialize - * data to transmit. + * application uses solely `nghttp2_session_mem_send2()` to + * serialize data to transmit. */ - nghttp2_send_callback send_callback; + nghttp2_send_callback2 send_callback2; + /** + * Deprecated. Use recv_callback2 instead. Callback function + * invoked when the session wants to receive data from the remote + * peer. This callback is not necessary if the application uses + * solely `nghttp2_session_mem_recv()` to process received data. + */ + nghttp2_recv_callback recv_callback; /** * Callback function invoked when the session wants to receive data * from the remote peer. This callback is not necessary if the - * application uses solely `nghttp2_session_mem_recv()` to process + * application uses solely `nghttp2_session_mem_recv2()` to process * received data. */ - nghttp2_recv_callback recv_callback; + nghttp2_recv_callback2 recv_callback2; /** * Callback function invoked by `nghttp2_session_recv()` when a * frame is received. @@ -99,23 +113,40 @@ struct nghttp2_session_callbacks { */ nghttp2_on_invalid_header_callback on_invalid_header_callback; nghttp2_on_invalid_header_callback2 on_invalid_header_callback2; + /** + * Deprecated. Use select_padding_callback2 instead. Callback + * function invoked when the library asks application how many + * padding bytes are required for the transmission of the given + * frame. + */ + nghttp2_select_padding_callback select_padding_callback; /** * Callback function invoked when the library asks application how * many padding bytes are required for the transmission of the given * frame. */ - nghttp2_select_padding_callback select_padding_callback; + nghttp2_select_padding_callback2 select_padding_callback2; /** - * The callback function used to determine the length allowed in + * Deprecated. Use read_length_callback2 instead. The callback + * function used to determine the length allowed in * `nghttp2_data_source_read_callback()` */ nghttp2_data_source_read_length_callback read_length_callback; + /** + * The callback function used to determine the length allowed in + * `nghttp2_data_source_read_callback2()` + */ + nghttp2_data_source_read_length_callback2 read_length_callback2; /** * Sets callback function invoked when a frame header is received. */ nghttp2_on_begin_frame_callback on_begin_frame_callback; nghttp2_send_data_callback send_data_callback; + /** + * Deprecated. Use pack_extension_callback2 instead. + */ nghttp2_pack_extension_callback pack_extension_callback; + nghttp2_pack_extension_callback2 pack_extension_callback2; nghttp2_unpack_extension_callback unpack_extension_callback; nghttp2_on_extension_chunk_recv_callback on_extension_chunk_recv_callback; nghttp2_error_callback error_callback; diff --git a/deps/nghttp2/lib/nghttp2_hd.c b/deps/nghttp2/lib/nghttp2_hd.c index 8a2bda64c1fe46..1b0c71331ae61f 100644 --- a/deps/nghttp2/lib/nghttp2_hd.c +++ b/deps/nghttp2/lib/nghttp2_hd.c @@ -850,9 +850,10 @@ static size_t encode_length(uint8_t *buf, size_t n, size_t prefix) { * in the next call will be stored in |*shift_ptr|) and returns number * of bytes processed, or returns -1, indicating decoding error. */ -static ssize_t decode_length(uint32_t *res, size_t *shift_ptr, int *fin, - uint32_t initial, size_t shift, const uint8_t *in, - const uint8_t *last, size_t prefix) { +static nghttp2_ssize decode_length(uint32_t *res, size_t *shift_ptr, int *fin, + uint32_t initial, size_t shift, + const uint8_t *in, const uint8_t *last, + size_t prefix) { uint32_t k = (uint8_t)((1 << prefix) - 1); uint32_t n = initial; const uint8_t *start = in; @@ -871,7 +872,7 @@ static ssize_t decode_length(uint32_t *res, size_t *shift_ptr, int *fin, if (++in == last) { *res = n; - return (ssize_t)(in - start); + return (nghttp2_ssize)(in - start); } } @@ -906,12 +907,12 @@ static ssize_t decode_length(uint32_t *res, size_t *shift_ptr, int *fin, if (in == last) { *res = n; - return (ssize_t)(in - start); + return (nghttp2_ssize)(in - start); } *res = n; *fin = 1; - return (ssize_t)(in + 1 - start); + return (nghttp2_ssize)(in + 1 - start); } static int emit_table_size(nghttp2_bufs *bufs, size_t table_size) { @@ -1164,7 +1165,7 @@ static int add_hd_table_incremental(nghttp2_hd_context *context, } typedef struct { - ssize_t index; + nghttp2_ssize index; /* Nonzero if both name and value are matched. */ int name_value_match; } search_result; @@ -1213,8 +1214,8 @@ static search_result search_hd_table(nghttp2_hd_context *context, return res; } - res.index = - (ssize_t)(context->next_seq - 1 - ent->seq + NGHTTP2_STATIC_TABLE_LENGTH); + res.index = (nghttp2_ssize)(context->next_seq - 1 - ent->seq + + NGHTTP2_STATIC_TABLE_LENGTH); res.name_value_match = exact_match; return res; @@ -1343,7 +1344,7 @@ static int deflate_nv(nghttp2_hd_deflater *deflater, nghttp2_bufs *bufs, const nghttp2_nv *nv) { int rv; search_result res; - ssize_t idx; + nghttp2_ssize idx; int indexing_mode; int32_t token; nghttp2_mem *mem; @@ -1379,7 +1380,7 @@ static int deflate_nv(nghttp2_hd_deflater *deflater, nghttp2_bufs *bufs, if (res.name_value_match) { - DEBUGF("deflatehd: name/value match index=%zd\n", idx); + DEBUGF("deflatehd: name/value match index=%td\n", idx); rv = emit_indexed_block(bufs, (size_t)idx); if (rv != 0) { @@ -1390,7 +1391,7 @@ static int deflate_nv(nghttp2_hd_deflater *deflater, nghttp2_bufs *bufs, } if (res.index != -1) { - DEBUGF("deflatehd: name match index=%zd\n", res.index); + DEBUGF("deflatehd: name match index=%td\n", res.index); } if (indexing_mode == NGHTTP2_HD_WITH_INDEXING) { @@ -1491,6 +1492,12 @@ int nghttp2_hd_deflate_hd_bufs(nghttp2_hd_deflater *deflater, ssize_t nghttp2_hd_deflate_hd(nghttp2_hd_deflater *deflater, uint8_t *buf, size_t buflen, const nghttp2_nv *nv, size_t nvlen) { + return (ssize_t)nghttp2_hd_deflate_hd2(deflater, buf, buflen, nv, nvlen); +} + +nghttp2_ssize nghttp2_hd_deflate_hd2(nghttp2_hd_deflater *deflater, + uint8_t *buf, size_t buflen, + const nghttp2_nv *nv, size_t nvlen) { nghttp2_bufs bufs; int rv; nghttp2_mem *mem; @@ -1517,12 +1524,18 @@ ssize_t nghttp2_hd_deflate_hd(nghttp2_hd_deflater *deflater, uint8_t *buf, return rv; } - return (ssize_t)buflen; + return (nghttp2_ssize)buflen; } ssize_t nghttp2_hd_deflate_hd_vec(nghttp2_hd_deflater *deflater, const nghttp2_vec *vec, size_t veclen, const nghttp2_nv *nv, size_t nvlen) { + return (ssize_t)nghttp2_hd_deflate_hd_vec2(deflater, vec, veclen, nv, nvlen); +} + +nghttp2_ssize nghttp2_hd_deflate_hd_vec2(nghttp2_hd_deflater *deflater, + const nghttp2_vec *vec, size_t veclen, + const nghttp2_nv *nv, size_t nvlen) { nghttp2_bufs bufs; int rv; nghttp2_mem *mem; @@ -1550,7 +1563,7 @@ ssize_t nghttp2_hd_deflate_hd_vec(nghttp2_hd_deflater *deflater, return rv; } - return (ssize_t)buflen; + return (nghttp2_ssize)buflen; } size_t nghttp2_hd_deflate_bound(nghttp2_hd_deflater *deflater, @@ -1643,10 +1656,11 @@ static void hd_inflate_set_huffman_encoded(nghttp2_hd_inflater *inflater, * NGHTTP2_ERR_HEADER_COMP * Integer decoding failed */ -static ssize_t hd_inflate_read_len(nghttp2_hd_inflater *inflater, int *rfin, - const uint8_t *in, const uint8_t *last, - size_t prefix, size_t maxlen) { - ssize_t rv; +static nghttp2_ssize hd_inflate_read_len(nghttp2_hd_inflater *inflater, + int *rfin, const uint8_t *in, + const uint8_t *last, size_t prefix, + size_t maxlen) { + nghttp2_ssize rv; uint32_t out; *rfin = 0; @@ -1684,10 +1698,10 @@ static ssize_t hd_inflate_read_len(nghttp2_hd_inflater *inflater, int *rfin, * NGHTTP2_ERR_HEADER_COMP * Huffman decoding failed */ -static ssize_t hd_inflate_read_huff(nghttp2_hd_inflater *inflater, - nghttp2_buf *buf, const uint8_t *in, - const uint8_t *last) { - ssize_t readlen; +static nghttp2_ssize hd_inflate_read_huff(nghttp2_hd_inflater *inflater, + nghttp2_buf *buf, const uint8_t *in, + const uint8_t *last) { + nghttp2_ssize readlen; int fin = 0; if ((size_t)(last - in) >= inflater->left) { last = in + inflater->left; @@ -1721,14 +1735,15 @@ static ssize_t hd_inflate_read_huff(nghttp2_hd_inflater *inflater, * NGHTTP2_ERR_HEADER_COMP * Header decompression failed */ -static ssize_t hd_inflate_read(nghttp2_hd_inflater *inflater, nghttp2_buf *buf, - const uint8_t *in, const uint8_t *last) { +static nghttp2_ssize hd_inflate_read(nghttp2_hd_inflater *inflater, + nghttp2_buf *buf, const uint8_t *in, + const uint8_t *last) { size_t len = nghttp2_min((size_t)(last - in), inflater->left); buf->last = nghttp2_cpymem(buf->last, in, len); inflater->left -= len; - return (ssize_t)len; + return (nghttp2_ssize)len; } /* @@ -1843,7 +1858,15 @@ ssize_t nghttp2_hd_inflate_hd(nghttp2_hd_inflater *inflater, nghttp2_nv *nv_out, ssize_t nghttp2_hd_inflate_hd2(nghttp2_hd_inflater *inflater, nghttp2_nv *nv_out, int *inflate_flags, const uint8_t *in, size_t inlen, int in_final) { - ssize_t rv; + return (nghttp2_ssize)nghttp2_hd_inflate_hd3(inflater, nv_out, inflate_flags, + in, inlen, in_final); +} + +nghttp2_ssize nghttp2_hd_inflate_hd3(nghttp2_hd_inflater *inflater, + nghttp2_nv *nv_out, int *inflate_flags, + const uint8_t *in, size_t inlen, + int in_final) { + nghttp2_ssize rv; nghttp2_hd_nv hd_nv; rv = nghttp2_hd_inflate_hd_nv(inflater, &hd_nv, inflate_flags, in, inlen, @@ -1866,11 +1889,11 @@ ssize_t nghttp2_hd_inflate_hd2(nghttp2_hd_inflater *inflater, return rv; } -ssize_t nghttp2_hd_inflate_hd_nv(nghttp2_hd_inflater *inflater, - nghttp2_hd_nv *nv_out, int *inflate_flags, - const uint8_t *in, size_t inlen, - int in_final) { - ssize_t rv = 0; +nghttp2_ssize nghttp2_hd_inflate_hd_nv(nghttp2_hd_inflater *inflater, + nghttp2_hd_nv *nv_out, + int *inflate_flags, const uint8_t *in, + size_t inlen, int in_final) { + nghttp2_ssize rv = 0; const uint8_t *first = in; const uint8_t *last = in + inlen; int rfin = 0; @@ -1992,7 +2015,7 @@ ssize_t nghttp2_hd_inflate_hd_nv(nghttp2_hd_inflater *inflater, inflater->state = NGHTTP2_HD_STATE_OPCODE; *inflate_flags |= NGHTTP2_HD_INFLATE_EMIT; - return (ssize_t)(in - first); + return (nghttp2_ssize)(in - first); } else { inflater->index = inflater->left; --inflater->index; @@ -2050,7 +2073,7 @@ ssize_t nghttp2_hd_inflate_hd_nv(nghttp2_hd_inflater *inflater, in += rv; - DEBUGF("inflatehd: %zd bytes read\n", rv); + DEBUGF("inflatehd: %td bytes read\n", rv); if (inflater->left) { DEBUGF("inflatehd: still %zu bytes to go\n", inflater->left); @@ -2072,7 +2095,7 @@ ssize_t nghttp2_hd_inflate_hd_nv(nghttp2_hd_inflater *inflater, in += rv; - DEBUGF("inflatehd: %zd bytes read\n", rv); + DEBUGF("inflatehd: %td bytes read\n", rv); if (inflater->left) { DEBUGF("inflatehd: still %zu bytes to go\n", inflater->left); @@ -2138,7 +2161,7 @@ ssize_t nghttp2_hd_inflate_hd_nv(nghttp2_hd_inflater *inflater, in += rv; - DEBUGF("inflatehd: %zd bytes read\n", rv); + DEBUGF("inflatehd: %td bytes read\n", rv); if (inflater->left) { DEBUGF("inflatehd: still %zu bytes to go\n", inflater->left); @@ -2162,18 +2185,18 @@ ssize_t nghttp2_hd_inflate_hd_nv(nghttp2_hd_inflater *inflater, inflater->state = NGHTTP2_HD_STATE_OPCODE; *inflate_flags |= NGHTTP2_HD_INFLATE_EMIT; - return (ssize_t)(in - first); + return (nghttp2_ssize)(in - first); case NGHTTP2_HD_STATE_READ_VALUE: rv = hd_inflate_read(inflater, &inflater->valuebuf, in, last); if (rv < 0) { - DEBUGF("inflatehd: value read failure %zd: %s\n", rv, + DEBUGF("inflatehd: value read failure %td: %s\n", rv, nghttp2_strerror((int)rv)); goto fail; } in += rv; - DEBUGF("inflatehd: %zd bytes read\n", rv); + DEBUGF("inflatehd: %td bytes read\n", rv); if (inflater->left) { DEBUGF("inflatehd: still %zu bytes to go\n", inflater->left); @@ -2196,7 +2219,7 @@ ssize_t nghttp2_hd_inflate_hd_nv(nghttp2_hd_inflater *inflater, inflater->state = NGHTTP2_HD_STATE_OPCODE; *inflate_flags |= NGHTTP2_HD_INFLATE_EMIT; - return (ssize_t)(in - first); + return (nghttp2_ssize)(in - first); } } @@ -2216,7 +2239,7 @@ ssize_t nghttp2_hd_inflate_hd_nv(nghttp2_hd_inflater *inflater, } *inflate_flags |= NGHTTP2_HD_INFLATE_FINAL; } - return (ssize_t)(in - first); + return (nghttp2_ssize)(in - first); almost_ok: if (in_final) { @@ -2226,10 +2249,10 @@ ssize_t nghttp2_hd_inflate_hd_nv(nghttp2_hd_inflater *inflater, goto fail; } - return (ssize_t)(in - first); + return (nghttp2_ssize)(in - first); fail: - DEBUGF("inflatehd: error return %zd\n", rv); + DEBUGF("inflatehd: error return %td\n", rv); inflater->ctx.bad = 1; return rv; @@ -2297,9 +2320,10 @@ int nghttp2_hd_emit_table_size(nghttp2_bufs *bufs, size_t table_size) { return emit_table_size(bufs, table_size); } -ssize_t nghttp2_hd_decode_length(uint32_t *res, size_t *shift_ptr, int *fin, - uint32_t initial, size_t shift, uint8_t *in, - uint8_t *last, size_t prefix) { +nghttp2_ssize nghttp2_hd_decode_length(uint32_t *res, size_t *shift_ptr, + int *fin, uint32_t initial, size_t shift, + uint8_t *in, uint8_t *last, + size_t prefix) { return decode_length(res, shift_ptr, fin, initial, shift, in, last, prefix); } diff --git a/deps/nghttp2/lib/nghttp2_hd.h b/deps/nghttp2/lib/nghttp2_hd.h index 6de0052aaea6cd..38a31a83c3891d 100644 --- a/deps/nghttp2/lib/nghttp2_hd.h +++ b/deps/nghttp2/lib/nghttp2_hd.h @@ -357,9 +357,10 @@ void nghttp2_hd_inflate_free(nghttp2_hd_inflater *inflater); * that return values and semantics are the same as * nghttp2_hd_inflate_hd(). */ -ssize_t nghttp2_hd_inflate_hd_nv(nghttp2_hd_inflater *inflater, - nghttp2_hd_nv *nv_out, int *inflate_flags, - const uint8_t *in, size_t inlen, int in_final); +nghttp2_ssize nghttp2_hd_inflate_hd_nv(nghttp2_hd_inflater *inflater, + nghttp2_hd_nv *nv_out, + int *inflate_flags, const uint8_t *in, + size_t inlen, int in_final); /* For unittesting purpose */ int nghttp2_hd_emit_indname_block(nghttp2_bufs *bufs, size_t index, @@ -376,9 +377,10 @@ int nghttp2_hd_emit_table_size(nghttp2_bufs *bufs, size_t table_size); nghttp2_hd_nv nghttp2_hd_table_get(nghttp2_hd_context *context, size_t index); /* For unittesting purpose */ -ssize_t nghttp2_hd_decode_length(uint32_t *res, size_t *shift_ptr, int *fin, - uint32_t initial, size_t shift, uint8_t *in, - uint8_t *last, size_t prefix); +nghttp2_ssize nghttp2_hd_decode_length(uint32_t *res, size_t *shift_ptr, + int *fin, uint32_t initial, size_t shift, + uint8_t *in, uint8_t *last, + size_t prefix); /* Huffman encoding/decoding functions */ @@ -427,9 +429,9 @@ void nghttp2_hd_huff_decode_context_init(nghttp2_hd_huff_decode_context *ctx); * NGHTTP2_ERR_HEADER_COMP * Decoding process has failed. */ -ssize_t nghttp2_hd_huff_decode(nghttp2_hd_huff_decode_context *ctx, - nghttp2_buf *buf, const uint8_t *src, - size_t srclen, int fin); +nghttp2_ssize nghttp2_hd_huff_decode(nghttp2_hd_huff_decode_context *ctx, + nghttp2_buf *buf, const uint8_t *src, + size_t srclen, int fin); /* * nghttp2_hd_huff_decode_failure_state returns nonzero if |ctx| diff --git a/deps/nghttp2/lib/nghttp2_hd_huffman.c b/deps/nghttp2/lib/nghttp2_hd_huffman.c index ac90f49c44f147..959053f774eda3 100644 --- a/deps/nghttp2/lib/nghttp2_hd_huffman.c +++ b/deps/nghttp2/lib/nghttp2_hd_huffman.c @@ -107,9 +107,9 @@ void nghttp2_hd_huff_decode_context_init(nghttp2_hd_huff_decode_context *ctx) { ctx->fstate = NGHTTP2_HUFF_ACCEPTED; } -ssize_t nghttp2_hd_huff_decode(nghttp2_hd_huff_decode_context *ctx, - nghttp2_buf *buf, const uint8_t *src, - size_t srclen, int final) { +nghttp2_ssize nghttp2_hd_huff_decode(nghttp2_hd_huff_decode_context *ctx, + nghttp2_buf *buf, const uint8_t *src, + size_t srclen, int final) { const uint8_t *end = src + srclen; nghttp2_huff_decode node = {ctx->fstate, 0}; const nghttp2_huff_decode *t = &node; @@ -136,7 +136,7 @@ ssize_t nghttp2_hd_huff_decode(nghttp2_hd_huff_decode_context *ctx, return NGHTTP2_ERR_HEADER_COMP; } - return (ssize_t)srclen; + return (nghttp2_ssize)srclen; } int nghttp2_hd_huff_decode_failure_state(nghttp2_hd_huff_decode_context *ctx) { diff --git a/deps/nghttp2/lib/nghttp2_outbound_item.c b/deps/nghttp2/lib/nghttp2_outbound_item.c index 2a3041db195355..a9e9f7693eda8c 100644 --- a/deps/nghttp2/lib/nghttp2_outbound_item.c +++ b/deps/nghttp2/lib/nghttp2_outbound_item.c @@ -27,6 +27,32 @@ #include #include +nghttp2_data_provider_wrap * +nghttp2_data_provider_wrap_v1(nghttp2_data_provider_wrap *dpw, + const nghttp2_data_provider *data_prd) { + if (!data_prd) { + return NULL; + } + + dpw->version = NGHTTP2_DATA_PROVIDER_V1; + dpw->data_prd.v1 = *data_prd; + + return dpw; +} + +nghttp2_data_provider_wrap * +nghttp2_data_provider_wrap_v2(nghttp2_data_provider_wrap *dpw, + const nghttp2_data_provider2 *data_prd) { + if (!data_prd) { + return NULL; + } + + dpw->version = NGHTTP2_DATA_PROVIDER_V2; + dpw->data_prd.v2 = *data_prd; + + return dpw; +} + void nghttp2_outbound_item_init(nghttp2_outbound_item *item) { item->cycle = 0; item->qnext = NULL; diff --git a/deps/nghttp2/lib/nghttp2_outbound_item.h b/deps/nghttp2/lib/nghttp2_outbound_item.h index bd4611b551bbbd..4e91750088f809 100644 --- a/deps/nghttp2/lib/nghttp2_outbound_item.h +++ b/deps/nghttp2/lib/nghttp2_outbound_item.h @@ -33,9 +33,32 @@ #include "nghttp2_frame.h" #include "nghttp2_mem.h" +#define NGHTTP2_DATA_PROVIDER_V1 1 +#define NGHTTP2_DATA_PROVIDER_V2 2 + +typedef struct nghttp2_data_provider_wrap { + int version; + union { + struct { + nghttp2_data_source source; + void *read_callback; + }; + nghttp2_data_provider v1; + nghttp2_data_provider2 v2; + } data_prd; +} nghttp2_data_provider_wrap; + +nghttp2_data_provider_wrap * +nghttp2_data_provider_wrap_v1(nghttp2_data_provider_wrap *dpw, + const nghttp2_data_provider *data_prd); + +nghttp2_data_provider_wrap * +nghttp2_data_provider_wrap_v2(nghttp2_data_provider_wrap *dpw, + const nghttp2_data_provider2 *data_prd); + /* struct used for HEADERS and PUSH_PROMISE frame */ typedef struct { - nghttp2_data_provider data_prd; + nghttp2_data_provider_wrap dpw; void *stream_user_data; /* error code when request HEADERS is canceled by RST_STREAM while it is in queue. */ @@ -50,7 +73,7 @@ typedef struct { /** * The data to be sent for this DATA frame. */ - nghttp2_data_provider data_prd; + nghttp2_data_provider_wrap dpw; /** * The flags of DATA frame. We use separate flags here and * nghttp2_data frame. The latter contains flags actually sent to diff --git a/deps/nghttp2/lib/nghttp2_session.c b/deps/nghttp2/lib/nghttp2_session.c index ce21caf9d7bb9d..226cdd59e8e98e 100644 --- a/deps/nghttp2/lib/nghttp2_session.c +++ b/deps/nghttp2/lib/nghttp2_session.c @@ -39,6 +39,7 @@ #include "nghttp2_extpri.h" #include "nghttp2_time.h" #include "nghttp2_debug.h" +#include "nghttp2_submit.h" /* * Returns non-zero if the number of outgoing opened streams is larger @@ -2103,10 +2104,9 @@ static int session_predicate_priority_update_send(nghttp2_session *session, /* Take into account settings max frame size and both connection-level flow control here */ -static ssize_t -nghttp2_session_enforce_flow_control_limits(nghttp2_session *session, - nghttp2_stream *stream, - ssize_t requested_window_size) { +static nghttp2_ssize nghttp2_session_enforce_flow_control_limits( + nghttp2_session *session, nghttp2_stream *stream, + nghttp2_ssize requested_window_size) { DEBUGF("send: remote windowsize connection=%d, remote maxframsize=%u, " "stream(id %d)=%d\n", session->remote_window_size, session->remote_settings.max_frame_size, @@ -2126,12 +2126,12 @@ nghttp2_session_enforce_flow_control_limits(nghttp2_session *session, */ static size_t nghttp2_session_next_data_read(nghttp2_session *session, nghttp2_stream *stream) { - ssize_t window_size; + nghttp2_ssize window_size; window_size = nghttp2_session_enforce_flow_control_limits( session, stream, NGHTTP2_DATA_PAYLOADLEN); - DEBUGF("send: available window=%zd\n", window_size); + DEBUGF("send: available window=%td\n", window_size); return window_size > 0 ? (size_t)window_size : 0; } @@ -2186,29 +2186,33 @@ static int nghttp2_session_predicate_data_send(nghttp2_session *session, return NGHTTP2_ERR_INVALID_STREAM_STATE; } -static ssize_t session_call_select_padding(nghttp2_session *session, - const nghttp2_frame *frame, - size_t max_payloadlen) { - ssize_t rv; +static nghttp2_ssize session_call_select_padding(nghttp2_session *session, + const nghttp2_frame *frame, + size_t max_payloadlen) { + nghttp2_ssize rv; + size_t max_paddedlen; - if (frame->hd.length >= max_payloadlen) { - return (ssize_t)frame->hd.length; + if (frame->hd.length >= max_payloadlen || + (!session->callbacks.select_padding_callback2 && + !session->callbacks.select_padding_callback)) { + return (nghttp2_ssize)frame->hd.length; } - if (session->callbacks.select_padding_callback) { - size_t max_paddedlen; - - max_paddedlen = - nghttp2_min(frame->hd.length + NGHTTP2_MAX_PADLEN, max_payloadlen); + max_paddedlen = + nghttp2_min(frame->hd.length + NGHTTP2_MAX_PADLEN, max_payloadlen); - rv = session->callbacks.select_padding_callback( + if (session->callbacks.select_padding_callback2) { + rv = session->callbacks.select_padding_callback2( session, frame, max_paddedlen, session->user_data); - if (rv < (ssize_t)frame->hd.length || rv > (ssize_t)max_paddedlen) { - return NGHTTP2_ERR_CALLBACK_FAILURE; - } - return rv; + } else { + rv = (nghttp2_ssize)session->callbacks.select_padding_callback( + session, frame, max_paddedlen, session->user_data); + } + if (rv < (nghttp2_ssize)frame->hd.length || + rv > (nghttp2_ssize)max_paddedlen) { + return NGHTTP2_ERR_CALLBACK_FAILURE; } - return (ssize_t)frame->hd.length; + return rv; } /* Add padding to HEADERS or PUSH_PROMISE. We use @@ -2216,7 +2220,7 @@ 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) { - ssize_t padded_payloadlen; + nghttp2_ssize padded_payloadlen; nghttp2_active_outbound_item *aob; nghttp2_bufs *framebufs; size_t padlen; @@ -2237,7 +2241,7 @@ static int session_headers_add_pad(nghttp2_session *session, padlen = (size_t)padded_payloadlen - frame->hd.length; - DEBUGF("send: padding selected: payloadlen=%zd, padlen=%zu\n", + DEBUGF("send: padding selected: payloadlen=%td, padlen=%zu\n", padded_payloadlen, padlen); nghttp2_frame_add_pad(framebufs, &frame->hd, padlen, 0); @@ -2257,18 +2261,24 @@ static size_t session_estimate_headers_payload(nghttp2_session *session, static int session_pack_extension(nghttp2_session *session, nghttp2_bufs *bufs, nghttp2_frame *frame) { - ssize_t rv; + nghttp2_ssize rv; nghttp2_buf *buf; size_t buflen; size_t framelen; - assert(session->callbacks.pack_extension_callback); + assert(session->callbacks.pack_extension_callback2 || + session->callbacks.pack_extension_callback); buf = &bufs->head->buf; buflen = nghttp2_min(nghttp2_buf_avail(buf), NGHTTP2_MAX_PAYLOADLEN); - rv = session->callbacks.pack_extension_callback(session, buf->last, buflen, - frame, session->user_data); + if (session->callbacks.pack_extension_callback2) { + rv = session->callbacks.pack_extension_callback2(session, buf->last, buflen, + frame, session->user_data); + } else { + rv = (nghttp2_ssize)session->callbacks.pack_extension_callback( + session, buf->last, buflen, frame, session->user_data); + } if (rv == NGHTTP2_ERR_CANCEL) { return (int)rv; } @@ -2451,7 +2461,7 @@ static int session_prep_frame(nghttp2_session *session, return rv; } - DEBUGF("send: before padding, HEADERS serialized in %zd bytes\n", + DEBUGF("send: before padding, HEADERS serialized in %zu bytes\n", nghttp2_bufs_len(&session->aob.framebufs)); rv = session_headers_add_pad(session, frame); @@ -2460,7 +2470,7 @@ static int session_prep_frame(nghttp2_session *session, return rv; } - DEBUGF("send: HEADERS finally serialized in %zd bytes\n", + DEBUGF("send: HEADERS finally serialized in %zu bytes\n", nghttp2_bufs_len(&session->aob.framebufs)); if (frame->headers.cat == NGHTTP2_HCAT_REQUEST) { @@ -2877,7 +2887,7 @@ static int session_after_frame_sent1(nghttp2_session *session) { /* Call on_frame_send_callback after nghttp2_stream_detach_item(), so that application can issue - nghttp2_submit_data() in the callback. */ + nghttp2_submit_data2() in the callback. */ if (session->callbacks.on_frame_send_callback) { rv = session_call_on_frame_send(session, frame); if (nghttp2_is_fatal(rv)) { @@ -2949,15 +2959,17 @@ static int session_after_frame_sent1(nghttp2_session *session) { } /* We assume aux_data is a pointer to nghttp2_headers_aux_data */ aux_data = &item->aux_data.headers; - if (aux_data->data_prd.read_callback) { - /* nghttp2_submit_data() makes a copy of aux_data->data_prd */ - rv = nghttp2_submit_data(session, NGHTTP2_FLAG_END_STREAM, - frame->hd.stream_id, &aux_data->data_prd); + if (aux_data->dpw.data_prd.read_callback) { + /* nghttp2_submit_data_shared() makes a copy of + aux_data->dpw */ + rv = nghttp2_submit_data_shared(session, NGHTTP2_FLAG_END_STREAM, + frame->hd.stream_id, &aux_data->dpw); if (nghttp2_is_fatal(rv)) { return rv; } - /* TODO nghttp2_submit_data() may fail if stream has already - DATA frame item. We might have to handle it here. */ + /* TODO nghttp2_submit_data_shared() may fail if stream has + already DATA frame item. We might have to handle it + here. */ } return 0; } @@ -2978,14 +2990,15 @@ static int session_after_frame_sent1(nghttp2_session *session) { } /* We assume aux_data is a pointer to nghttp2_headers_aux_data */ aux_data = &item->aux_data.headers; - if (aux_data->data_prd.read_callback) { - rv = nghttp2_submit_data(session, NGHTTP2_FLAG_END_STREAM, - frame->hd.stream_id, &aux_data->data_prd); + if (aux_data->dpw.data_prd.read_callback) { + rv = nghttp2_submit_data_shared(session, NGHTTP2_FLAG_END_STREAM, + frame->hd.stream_id, &aux_data->dpw); if (nghttp2_is_fatal(rv)) { return rv; } - /* TODO nghttp2_submit_data() may fail if stream has already - DATA frame item. We might have to handle it here. */ + /* TODO nghttp2_submit_data_shared() may fail if stream has + already DATA frame item. We might have to handle it + here. */ } return 0; default: @@ -3144,7 +3157,7 @@ static void session_after_frame_sent2(nghttp2_session *session) { aux_data = &item->aux_data.data; /* On EOF, we have already detached data. Please note that - application may issue nghttp2_submit_data() in + application may issue nghttp2_submit_data2() in on_frame_send_callback (call from session_after_frame_sent1), which attach data to stream. We don't want to detach it. */ if (aux_data->eof) { @@ -3191,7 +3204,7 @@ static int session_call_send_data(nghttp2_session *session, aux_data = &item->aux_data.data; rv = session->callbacks.send_data_callback(session, frame, buf->pos, length, - &aux_data->data_prd.source, + &aux_data->dpw.data_prd.source, session->user_data); switch (rv) { @@ -3205,9 +3218,9 @@ static int session_call_send_data(nghttp2_session *session, } } -static ssize_t nghttp2_session_mem_send_internal(nghttp2_session *session, - const uint8_t **data_ptr, - int fast_cb) { +static nghttp2_ssize nghttp2_session_mem_send_internal(nghttp2_session *session, + const uint8_t **data_ptr, + int fast_cb) { int rv; nghttp2_active_outbound_item *aob; nghttp2_bufs *framebufs; @@ -3385,7 +3398,7 @@ static ssize_t nghttp2_session_mem_send_internal(nghttp2_session *session, } } - DEBUGF("send: start transmitting frame type=%u, length=%zd\n", + DEBUGF("send: start transmitting frame type=%u, length=%td\n", framebufs->cur->buf.pos[3], framebufs->cur->buf.last - framebufs->cur->buf.pos); @@ -3425,7 +3438,7 @@ static ssize_t nghttp2_session_mem_send_internal(nghttp2_session *session, everything, we will adjust it. */ buf->pos += datalen; - return (ssize_t)datalen; + return (nghttp2_ssize)datalen; } case NGHTTP2_OB_SEND_NO_COPY: { nghttp2_stream *stream; @@ -3502,7 +3515,7 @@ static ssize_t nghttp2_session_mem_send_internal(nghttp2_session *session, buf->pos += datalen; - return (ssize_t)datalen; + return (nghttp2_ssize)datalen; } } } @@ -3510,8 +3523,13 @@ static ssize_t nghttp2_session_mem_send_internal(nghttp2_session *session, ssize_t nghttp2_session_mem_send(nghttp2_session *session, const uint8_t **data_ptr) { + return (ssize_t)nghttp2_session_mem_send2(session, data_ptr); +} + +nghttp2_ssize nghttp2_session_mem_send2(nghttp2_session *session, + const uint8_t **data_ptr) { int rv; - ssize_t len; + nghttp2_ssize len; *data_ptr = NULL; @@ -3528,7 +3546,7 @@ ssize_t nghttp2_session_mem_send(nghttp2_session *session, rv = session_after_frame_sent1(session); if (rv < 0) { assert(nghttp2_is_fatal(rv)); - return (ssize_t)rv; + return (nghttp2_ssize)rv; } } @@ -3537,8 +3555,8 @@ ssize_t nghttp2_session_mem_send(nghttp2_session *session, int nghttp2_session_send(nghttp2_session *session) { const uint8_t *data = NULL; - ssize_t datalen; - ssize_t sentlen; + nghttp2_ssize datalen; + nghttp2_ssize sentlen; nghttp2_bufs *framebufs; framebufs = &session->aob.framebufs; @@ -3548,8 +3566,13 @@ int nghttp2_session_send(nghttp2_session *session) { if (datalen <= 0) { return (int)datalen; } - sentlen = session->callbacks.send_callback(session, data, (size_t)datalen, - 0, session->user_data); + if (session->callbacks.send_callback2) { + sentlen = session->callbacks.send_callback2( + session, data, (size_t)datalen, 0, session->user_data); + } else { + sentlen = (nghttp2_ssize)session->callbacks.send_callback( + session, data, (size_t)datalen, 0, session->user_data); + } if (sentlen < 0) { if (sentlen == NGHTTP2_ERR_WOULDBLOCK) { /* Transmission canceled. Rewind the offset */ @@ -3564,11 +3587,17 @@ int nghttp2_session_send(nghttp2_session *session) { } } -static ssize_t session_recv(nghttp2_session *session, uint8_t *buf, - size_t len) { - ssize_t rv; - rv = session->callbacks.recv_callback(session, buf, len, 0, - session->user_data); +static nghttp2_ssize session_recv(nghttp2_session *session, uint8_t *buf, + size_t len) { + nghttp2_ssize rv; + + if (session->callbacks.recv_callback2) { + rv = session->callbacks.recv_callback2(session, buf, len, 0, + session->user_data); + } else { + rv = (nghttp2_ssize)session->callbacks.recv_callback(session, buf, len, 0, + session->user_data); + } if (rv > 0) { if ((size_t)rv > len) { return NGHTTP2_ERR_CALLBACK_FAILURE; @@ -3870,7 +3899,7 @@ static int session_inflate_handle_invalid_connection(nghttp2_session *session, static int inflate_header_block(nghttp2_session *session, nghttp2_frame *frame, size_t *readlen_ptr, uint8_t *in, size_t inlen, int final, int call_header_cb) { - ssize_t proclen; + nghttp2_ssize proclen; int rv; int inflate_flags; nghttp2_hd_nv nv; @@ -3923,7 +3952,7 @@ static int inflate_header_block(nghttp2_session *session, nghttp2_frame *frame, inlen -= (size_t)proclen; *readlen_ptr += (size_t)proclen; - DEBUGF("recv: proclen=%zd\n", proclen); + DEBUGF("recv: proclen=%td\n", proclen); if (call_header_cb && (inflate_flags & NGHTTP2_HD_INFLATE_EMIT)) { rv = 0; @@ -5763,7 +5792,7 @@ static int inbound_frame_handle_pad(nghttp2_inbound_frame *iframe, * Computes number of padding based on flags. This function returns * the calculated length if it succeeds, or -1. */ -static ssize_t inbound_frame_compute_pad(nghttp2_inbound_frame *iframe) { +static nghttp2_ssize inbound_frame_compute_pad(nghttp2_inbound_frame *iframe) { size_t padlen; /* 1 for Pad Length field */ @@ -5778,7 +5807,7 @@ static ssize_t inbound_frame_compute_pad(nghttp2_inbound_frame *iframe) { iframe->padlen = padlen; - return (ssize_t)padlen; + return (nghttp2_ssize)padlen; } /* @@ -5787,9 +5816,9 @@ static ssize_t inbound_frame_compute_pad(nghttp2_inbound_frame *iframe) { * |payloadleft| does not include |readlen|. If padding was started * strictly before this data chunk, this function returns -1. */ -static ssize_t inbound_frame_effective_readlen(nghttp2_inbound_frame *iframe, - size_t payloadleft, - size_t readlen) { +static nghttp2_ssize +inbound_frame_effective_readlen(nghttp2_inbound_frame *iframe, + size_t payloadleft, size_t readlen) { size_t trail_padlen = nghttp2_frame_trail_padlen(&iframe->frame, iframe->padlen); @@ -5799,19 +5828,24 @@ static ssize_t inbound_frame_effective_readlen(nghttp2_inbound_frame *iframe, if (readlen < padlen) { return -1; } - return (ssize_t)(readlen - padlen); + return (nghttp2_ssize)(readlen - padlen); } - return (ssize_t)(readlen); + return (nghttp2_ssize)(readlen); } static const uint8_t static_in[] = {0}; ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, size_t inlen) { + return (ssize_t)nghttp2_session_mem_recv2(session, in, inlen); +} + +nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session, + const uint8_t *in, size_t inlen) { const uint8_t *first, *last; nghttp2_inbound_frame *iframe = &session->iframe; size_t readlen; - ssize_t padlen; + nghttp2_ssize padlen; int rv; int busy = 0; nghttp2_frame_hd cont_hd; @@ -5841,7 +5875,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, } if (!nghttp2_session_want_read(session)) { - return (ssize_t)inlen; + return (nghttp2_ssize)inlen; } for (;;) { @@ -5871,7 +5905,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, in += readlen; if (nghttp2_buf_mark_avail(&iframe->sbuf)) { - return (ssize_t)(in - first); + return (nghttp2_ssize)(in - first); } if (iframe->sbuf.pos[3] != NGHTTP2_SETTINGS || @@ -5893,7 +5927,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, return rv; } - return (ssize_t)inlen; + return (nghttp2_ssize)inlen; } iframe->state = NGHTTP2_IB_READ_HEAD; @@ -5908,7 +5942,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, in += readlen; if (nghttp2_buf_mark_avail(&iframe->sbuf)) { - return (ssize_t)(in - first); + return (nghttp2_ssize)(in - first); } nghttp2_frame_unpack_frame_hd(&iframe->frame.hd, iframe->sbuf.pos); @@ -5929,7 +5963,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, return rv; } - return (ssize_t)inlen; + return (nghttp2_ssize)inlen; } switch (iframe->frame.hd.type) { @@ -5944,7 +5978,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, rv = session_on_data_received_fail_fast(session); if (iframe->state == NGHTTP2_IB_IGN_ALL) { - return (ssize_t)inlen; + return (nghttp2_ssize)inlen; } if (rv == NGHTTP2_ERR_IGN_PAYLOAD) { DEBUGF("recv: DATA not allowed stream_id=%d\n", @@ -5966,7 +6000,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, if (nghttp2_is_fatal(rv)) { return rv; } - return (ssize_t)inlen; + return (nghttp2_ssize)inlen; } if (rv == 1) { @@ -5993,7 +6027,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, if (nghttp2_is_fatal(rv)) { return rv; } - return (ssize_t)inlen; + return (nghttp2_ssize)inlen; } if (rv == 1) { @@ -6036,7 +6070,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, busy = 1; if (iframe->state == NGHTTP2_IB_IGN_ALL) { - return (ssize_t)inlen; + return (nghttp2_ssize)inlen; } if (rv == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) { @@ -6137,7 +6171,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, if (nghttp2_is_fatal(rv)) { return rv; } - return (ssize_t)inlen; + return (nghttp2_ssize)inlen; } iframe->iv = nghttp2_mem_malloc(mem, sizeof(nghttp2_settings_entry) * @@ -6175,7 +6209,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, if (nghttp2_is_fatal(rv)) { return rv; } - return (ssize_t)inlen; + return (nghttp2_ssize)inlen; } if (rv == 1) { @@ -6235,7 +6269,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, return rv; } - return (ssize_t)inlen; + return (nghttp2_ssize)inlen; default: DEBUGF("recv: extension frame\n"); @@ -6346,7 +6380,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, if (nghttp2_is_fatal(rv)) { return rv; } - return (ssize_t)inlen; + return (nghttp2_ssize)inlen; } if (iframe->payloadleft < 4) { @@ -6404,11 +6438,11 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, in += readlen; iframe->payloadleft -= readlen; - DEBUGF("recv: readlen=%zu, payloadleft=%zu, left=%zd\n", readlen, + DEBUGF("recv: readlen=%zu, payloadleft=%zu, left=%zu\n", readlen, iframe->payloadleft, nghttp2_buf_mark_avail(&iframe->sbuf)); if (nghttp2_buf_mark_avail(&iframe->sbuf)) { - return (ssize_t)(in - first); + return (nghttp2_ssize)(in - first); } switch (iframe->frame.hd.type) { @@ -6424,7 +6458,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, if (nghttp2_is_fatal(rv)) { return rv; } - return (ssize_t)inlen; + return (nghttp2_ssize)inlen; } iframe->frame.headers.padlen = (size_t)padlen; @@ -6451,7 +6485,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, busy = 1; if (iframe->state == NGHTTP2_IB_IGN_ALL) { - return (ssize_t)inlen; + return (nghttp2_ssize)inlen; } if (rv == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) { @@ -6481,7 +6515,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, } if (iframe->state == NGHTTP2_IB_IGN_ALL) { - return (ssize_t)inlen; + return (nghttp2_ssize)inlen; } } @@ -6495,7 +6529,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, } if (iframe->state == NGHTTP2_IB_IGN_ALL) { - return (ssize_t)inlen; + return (nghttp2_ssize)inlen; } session_inbound_frame_reset(session); @@ -6513,7 +6547,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, if (nghttp2_is_fatal(rv)) { return rv; } - return (ssize_t)inlen; + return (nghttp2_ssize)inlen; } iframe->frame.push_promise.padlen = (size_t)padlen; @@ -6539,7 +6573,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, busy = 1; if (iframe->state == NGHTTP2_IB_IGN_ALL) { - return (ssize_t)inlen; + return (nghttp2_ssize)inlen; } if (rv == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) { @@ -6568,7 +6602,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, } if (iframe->state == NGHTTP2_IB_IGN_ALL) { - return (ssize_t)inlen; + return (nghttp2_ssize)inlen; } session_inbound_frame_reset(session); @@ -6603,7 +6637,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, } if (iframe->state == NGHTTP2_IB_IGN_ALL) { - return (ssize_t)inlen; + return (nghttp2_ssize)inlen; } session_inbound_frame_reset(session); @@ -6661,7 +6695,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, break; case NGHTTP2_IB_READ_HEADER_BLOCK: case NGHTTP2_IB_IGN_HEADER_BLOCK: { - ssize_t data_readlen; + nghttp2_ssize data_readlen; size_t trail_padlen; int final; #ifdef DEBUGBUILD @@ -6705,14 +6739,14 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, } if (iframe->state == NGHTTP2_IB_IGN_ALL) { - return (ssize_t)inlen; + return (nghttp2_ssize)inlen; } if (rv == NGHTTP2_ERR_PAUSE) { in += hd_proclen; iframe->payloadleft -= hd_proclen; - return (ssize_t)(in - first); + return (nghttp2_ssize)(in - first); } if (rv == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) { @@ -6819,7 +6853,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, assert(iframe->state == NGHTTP2_IB_IGN_ALL); - return (ssize_t)inlen; + return (nghttp2_ssize)inlen; case NGHTTP2_IB_READ_SETTINGS: DEBUGF("recv: [IB_READ_SETTINGS]\n"); @@ -6849,7 +6883,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, } if (iframe->state == NGHTTP2_IB_IGN_ALL) { - return (ssize_t)inlen; + return (nghttp2_ssize)inlen; } session_inbound_frame_reset(session); @@ -6883,7 +6917,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, } if (iframe->state == NGHTTP2_IB_IGN_ALL) { - return (ssize_t)inlen; + return (nghttp2_ssize)inlen; } session_inbound_frame_reset(session); @@ -6903,7 +6937,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, in += readlen; if (nghttp2_buf_mark_avail(&iframe->sbuf)) { - return (ssize_t)(in - first); + return (nghttp2_ssize)(in - first); } nghttp2_frame_unpack_frame_hd(&cont_hd, iframe->sbuf.pos); @@ -6925,7 +6959,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, return rv; } - return (ssize_t)inlen; + return (nghttp2_ssize)inlen; } /* CONTINUATION won't bear NGHTTP2_PADDED flag */ @@ -6961,7 +6995,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 (ssize_t)(in - first); + return (nghttp2_ssize)(in - first); } /* Pad Length field is subject to flow control */ @@ -6971,7 +7005,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, } if (iframe->state == NGHTTP2_IB_IGN_ALL) { - return (ssize_t)inlen; + return (nghttp2_ssize)inlen; } /* Pad Length field is consumed immediately */ @@ -6983,7 +7017,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, } if (iframe->state == NGHTTP2_IB_IGN_ALL) { - return (ssize_t)inlen; + return (nghttp2_ssize)inlen; } stream = nghttp2_session_get_stream(session, iframe->frame.hd.stream_id); @@ -7006,7 +7040,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, if (nghttp2_is_fatal(rv)) { return rv; } - return (ssize_t)inlen; + return (nghttp2_ssize)inlen; } iframe->frame.data.padlen = (size_t)padlen; @@ -7033,7 +7067,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, iframe->payloadleft); if (readlen > 0) { - ssize_t data_readlen; + nghttp2_ssize data_readlen; rv = nghttp2_session_update_recv_connection_window_size(session, readlen); @@ -7042,7 +7076,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, } if (iframe->state == NGHTTP2_IB_IGN_ALL) { - return (ssize_t)inlen; + return (nghttp2_ssize)inlen; } rv = nghttp2_session_update_recv_stream_window_size( @@ -7061,7 +7095,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, data_readlen = 0; } - padlen = (ssize_t)readlen - data_readlen; + padlen = (nghttp2_ssize)readlen - data_readlen; if (padlen > 0) { /* Padding is considered as "consumed" immediately */ @@ -7073,11 +7107,11 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, } if (iframe->state == NGHTTP2_IB_IGN_ALL) { - return (ssize_t)inlen; + return (nghttp2_ssize)inlen; } } - DEBUGF("recv: data_readlen=%zd\n", data_readlen); + DEBUGF("recv: data_readlen=%td\n", data_readlen); if (data_readlen > 0) { if (session_enforce_http_messaging(session)) { @@ -7092,7 +7126,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, } if (iframe->state == NGHTTP2_IB_IGN_DATA) { - return (ssize_t)inlen; + return (nghttp2_ssize)inlen; } } @@ -7111,7 +7145,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 (ssize_t)(in - first); + return (nghttp2_ssize)(in - first); } if (nghttp2_is_fatal(rv)) { @@ -7153,7 +7187,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, } if (iframe->state == NGHTTP2_IB_IGN_ALL) { - return (ssize_t)inlen; + return (nghttp2_ssize)inlen; } if (session->opt_flags & NGHTTP2_OPTMASK_NO_AUTO_WINDOW_UPDATE) { @@ -7166,7 +7200,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, } if (iframe->state == NGHTTP2_IB_IGN_ALL) { - return (ssize_t)inlen; + return (nghttp2_ssize)inlen; } } } @@ -7179,7 +7213,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, break; case NGHTTP2_IB_IGN_ALL: - return (ssize_t)inlen; + return (nghttp2_ssize)inlen; case NGHTTP2_IB_READ_EXTENSION_PAYLOAD: DEBUGF("recv: [IB_READ_EXTENSION_PAYLOAD]\n"); @@ -7274,7 +7308,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, } if (iframe->state == NGHTTP2_IB_IGN_ALL) { - return (ssize_t)inlen; + return (nghttp2_ssize)inlen; } session_inbound_frame_reset(session); @@ -7291,16 +7325,17 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, assert(in == last); - return (ssize_t)(in - first); + return (nghttp2_ssize)(in - first); } int nghttp2_session_recv(nghttp2_session *session) { uint8_t buf[NGHTTP2_INBOUND_BUFFER_LENGTH]; while (1) { - ssize_t readlen; + nghttp2_ssize readlen; readlen = session_recv(session, buf, sizeof(buf)); if (readlen > 0) { - ssize_t proclen = nghttp2_session_mem_recv(session, buf, (size_t)readlen); + nghttp2_ssize proclen = + nghttp2_session_mem_recv2(session, buf, (size_t)readlen); if (proclen < 0) { return (int)proclen; } @@ -7642,8 +7677,8 @@ int nghttp2_session_pack_data(nghttp2_session *session, nghttp2_bufs *bufs, nghttp2_stream *stream) { int rv; uint32_t data_flags; - ssize_t payloadlen; - ssize_t padded_payloadlen; + nghttp2_ssize payloadlen; + nghttp2_ssize padded_payloadlen; nghttp2_buf *buf; size_t max_payloadlen; @@ -7651,19 +7686,26 @@ int nghttp2_session_pack_data(nghttp2_session *session, nghttp2_bufs *bufs, buf = &bufs->cur->buf; - if (session->callbacks.read_length_callback) { - - payloadlen = session->callbacks.read_length_callback( - session, frame->hd.type, stream->stream_id, session->remote_window_size, - stream->remote_window_size, session->remote_settings.max_frame_size, - session->user_data); + if (session->callbacks.read_length_callback2 || + session->callbacks.read_length_callback) { + if (session->callbacks.read_length_callback2) { + payloadlen = session->callbacks.read_length_callback2( + session, frame->hd.type, stream->stream_id, + session->remote_window_size, stream->remote_window_size, + session->remote_settings.max_frame_size, session->user_data); + } else { + payloadlen = (nghttp2_ssize)session->callbacks.read_length_callback( + session, frame->hd.type, stream->stream_id, + session->remote_window_size, stream->remote_window_size, + session->remote_settings.max_frame_size, session->user_data); + } - DEBUGF("send: read_length_callback=%zd\n", payloadlen); + DEBUGF("send: read_length_callback=%td\n", payloadlen); payloadlen = nghttp2_session_enforce_flow_control_limits(session, stream, payloadlen); - DEBUGF("send: read_length_callback after flow control=%zd\n", payloadlen); + DEBUGF("send: read_length_callback after flow control=%td\n", payloadlen); if (payloadlen <= 0) { return NGHTTP2_ERR_CALLBACK_FAILURE; @@ -7679,9 +7721,9 @@ int nghttp2_session_pack_data(nghttp2_session *session, nghttp2_bufs *bufs, DEBUGF("send: realloc buffer failed rv=%d", rv); /* If reallocation failed, old buffers are still in tact. So use safe limit. */ - payloadlen = (ssize_t)datamax; + payloadlen = (nghttp2_ssize)datamax; - DEBUGF("send: use safe limit payloadlen=%zd", payloadlen); + DEBUGF("send: use safe limit payloadlen=%td", payloadlen); } else { assert(&session->aob.framebufs == bufs); @@ -7695,9 +7737,23 @@ int nghttp2_session_pack_data(nghttp2_session *session, nghttp2_bufs *bufs, assert(nghttp2_buf_avail(buf) >= datamax); data_flags = NGHTTP2_DATA_FLAG_NONE; - payloadlen = aux_data->data_prd.read_callback( - session, frame->hd.stream_id, buf->pos, datamax, &data_flags, - &aux_data->data_prd.source, session->user_data); + switch (aux_data->dpw.version) { + case NGHTTP2_DATA_PROVIDER_V1: + payloadlen = (nghttp2_ssize)aux_data->dpw.data_prd.v1.read_callback( + session, frame->hd.stream_id, buf->pos, datamax, &data_flags, + &aux_data->dpw.data_prd.source, session->user_data); + + break; + case NGHTTP2_DATA_PROVIDER_V2: + payloadlen = aux_data->dpw.data_prd.v2.read_callback( + session, frame->hd.stream_id, buf->pos, datamax, &data_flags, + &aux_data->dpw.data_prd.source, session->user_data); + + break; + default: + assert(0); + abort(); + } if (payloadlen == NGHTTP2_ERR_DEFERRED || payloadlen == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE || @@ -8275,7 +8331,7 @@ int nghttp2_session_change_stream_priority( /* We don't intentionally call nghttp2_session_adjust_idle_stream() so that idle stream created by this function, and existing ones are kept for application. We will adjust number of idle stream - in nghttp2_session_mem_send or nghttp2_session_mem_recv is + in nghttp2_session_mem_send2 or nghttp2_session_mem_recv2 is called. */ return 0; } @@ -8313,7 +8369,7 @@ int nghttp2_session_create_idle_stream(nghttp2_session *session, /* We don't intentionally call nghttp2_session_adjust_idle_stream() so that idle stream created by this function, and existing ones are kept for application. We will adjust number of idle stream - in nghttp2_session_mem_send or nghttp2_session_mem_recv is + in nghttp2_session_mem_send2 or nghttp2_session_mem_recv2 is called. */ return 0; } diff --git a/deps/nghttp2/lib/nghttp2_submit.c b/deps/nghttp2/lib/nghttp2_submit.c index f5554eb56494ed..f947969cd99c1f 100644 --- a/deps/nghttp2/lib/nghttp2_submit.c +++ b/deps/nghttp2/lib/nghttp2_submit.c @@ -68,7 +68,7 @@ static int32_t submit_headers_shared(nghttp2_session *session, uint8_t flags, int32_t stream_id, const nghttp2_priority_spec *pri_spec, nghttp2_nv *nva_copy, size_t nvlen, - const nghttp2_data_provider *data_prd, + const nghttp2_data_provider_wrap *dpw, void *stream_user_data) { int rv; uint8_t flags_copy; @@ -87,8 +87,8 @@ static int32_t submit_headers_shared(nghttp2_session *session, uint8_t flags, nghttp2_outbound_item_init(item); - if (data_prd != NULL && data_prd->read_callback != NULL) { - item->aux_data.headers.data_prd = *data_prd; + if (dpw != NULL && dpw->data_prd.read_callback != NULL) { + item->aux_data.headers.dpw = *dpw; } item->aux_data.headers.stream_user_data = stream_user_data; @@ -143,7 +143,7 @@ static int32_t submit_headers_shared_nva(nghttp2_session *session, uint8_t flags, int32_t stream_id, const nghttp2_priority_spec *pri_spec, const nghttp2_nv *nva, size_t nvlen, - const nghttp2_data_provider *data_prd, + const nghttp2_data_provider_wrap *dpw, void *stream_user_data) { int rv; nghttp2_nv *nva_copy; @@ -165,7 +165,7 @@ static int32_t submit_headers_shared_nva(nghttp2_session *session, } return submit_headers_shared(session, flags, stream_id, ©_pri_spec, - nva_copy, nvlen, data_prd, stream_user_data); + nva_copy, nvlen, dpw, stream_user_data); } int nghttp2_submit_trailer(nghttp2_session *session, int32_t stream_id, @@ -740,9 +740,9 @@ int nghttp2_submit_priority_update(nghttp2_session *session, uint8_t flags, } static uint8_t set_request_flags(const nghttp2_priority_spec *pri_spec, - const nghttp2_data_provider *data_prd) { + const nghttp2_data_provider_wrap *dpw) { uint8_t flags = NGHTTP2_FLAG_NONE; - if (data_prd == NULL || data_prd->read_callback == NULL) { + if (dpw == NULL || dpw->data_prd.read_callback == NULL) { flags |= NGHTTP2_FLAG_END_STREAM; } @@ -753,11 +753,11 @@ static uint8_t set_request_flags(const nghttp2_priority_spec *pri_spec, return flags; } -int32_t nghttp2_submit_request(nghttp2_session *session, - const nghttp2_priority_spec *pri_spec, - const nghttp2_nv *nva, size_t nvlen, - const nghttp2_data_provider *data_prd, - void *stream_user_data) { +static int32_t submit_request_shared(nghttp2_session *session, + const nghttp2_priority_spec *pri_spec, + const nghttp2_nv *nva, size_t nvlen, + const nghttp2_data_provider_wrap *dpw, + void *stream_user_data) { uint8_t flags; int rv; @@ -775,23 +775,47 @@ int32_t nghttp2_submit_request(nghttp2_session *session, pri_spec = NULL; } - flags = set_request_flags(pri_spec, data_prd); + flags = set_request_flags(pri_spec, dpw); return submit_headers_shared_nva(session, flags, -1, pri_spec, nva, nvlen, - data_prd, stream_user_data); + dpw, stream_user_data); +} + +int32_t nghttp2_submit_request(nghttp2_session *session, + const nghttp2_priority_spec *pri_spec, + const nghttp2_nv *nva, size_t nvlen, + const nghttp2_data_provider *data_prd, + void *stream_user_data) { + nghttp2_data_provider_wrap dpw; + + return submit_request_shared(session, pri_spec, nva, nvlen, + nghttp2_data_provider_wrap_v1(&dpw, data_prd), + stream_user_data); +} + +int32_t nghttp2_submit_request2(nghttp2_session *session, + const nghttp2_priority_spec *pri_spec, + const nghttp2_nv *nva, size_t nvlen, + const nghttp2_data_provider2 *data_prd, + void *stream_user_data) { + nghttp2_data_provider_wrap dpw; + + return submit_request_shared(session, pri_spec, nva, nvlen, + nghttp2_data_provider_wrap_v2(&dpw, data_prd), + stream_user_data); } -static uint8_t set_response_flags(const nghttp2_data_provider *data_prd) { +static uint8_t set_response_flags(const nghttp2_data_provider_wrap *dpw) { uint8_t flags = NGHTTP2_FLAG_NONE; - if (data_prd == NULL || data_prd->read_callback == NULL) { + if (dpw == NULL || dpw->data_prd.read_callback == NULL) { flags |= NGHTTP2_FLAG_END_STREAM; } return flags; } -int nghttp2_submit_response(nghttp2_session *session, int32_t stream_id, - const nghttp2_nv *nva, size_t nvlen, - const nghttp2_data_provider *data_prd) { +static int submit_response_shared(nghttp2_session *session, int32_t stream_id, + const nghttp2_nv *nva, size_t nvlen, + const nghttp2_data_provider_wrap *dpw) { uint8_t flags; if (stream_id <= 0) { @@ -802,14 +826,32 @@ int nghttp2_submit_response(nghttp2_session *session, int32_t stream_id, return NGHTTP2_ERR_PROTO; } - flags = set_response_flags(data_prd); + flags = set_response_flags(dpw); return submit_headers_shared_nva(session, flags, stream_id, NULL, nva, nvlen, - data_prd, NULL); + dpw, NULL); } -int nghttp2_submit_data(nghttp2_session *session, uint8_t flags, - int32_t stream_id, - const nghttp2_data_provider *data_prd) { +int nghttp2_submit_response(nghttp2_session *session, int32_t stream_id, + const nghttp2_nv *nva, size_t nvlen, + const nghttp2_data_provider *data_prd) { + nghttp2_data_provider_wrap dpw; + + return submit_response_shared(session, stream_id, nva, nvlen, + nghttp2_data_provider_wrap_v1(&dpw, data_prd)); +} + +int nghttp2_submit_response2(nghttp2_session *session, int32_t stream_id, + const nghttp2_nv *nva, size_t nvlen, + const nghttp2_data_provider2 *data_prd) { + nghttp2_data_provider_wrap dpw; + + return submit_response_shared(session, stream_id, nva, nvlen, + nghttp2_data_provider_wrap_v2(&dpw, data_prd)); +} + +int nghttp2_submit_data_shared(nghttp2_session *session, uint8_t flags, + int32_t stream_id, + const nghttp2_data_provider_wrap *dpw) { int rv; nghttp2_outbound_item *item; nghttp2_frame *frame; @@ -832,7 +874,7 @@ int nghttp2_submit_data(nghttp2_session *session, uint8_t flags, frame = &item->frame; aux_data = &item->aux_data.data; - aux_data->data_prd = *data_prd; + aux_data->dpw = *dpw; aux_data->eof = 0; aux_data->flags = nflags; @@ -848,9 +890,37 @@ int nghttp2_submit_data(nghttp2_session *session, uint8_t flags, return 0; } +int nghttp2_submit_data(nghttp2_session *session, uint8_t flags, + int32_t stream_id, + const nghttp2_data_provider *data_prd) { + nghttp2_data_provider_wrap dpw; + + assert(data_prd); + + return nghttp2_submit_data_shared( + session, flags, stream_id, nghttp2_data_provider_wrap_v1(&dpw, data_prd)); +} + +int nghttp2_submit_data2(nghttp2_session *session, uint8_t flags, + int32_t stream_id, + const nghttp2_data_provider2 *data_prd) { + nghttp2_data_provider_wrap dpw; + + assert(data_prd); + + return nghttp2_submit_data_shared( + session, flags, stream_id, nghttp2_data_provider_wrap_v2(&dpw, data_prd)); +} + ssize_t nghttp2_pack_settings_payload(uint8_t *buf, size_t buflen, const nghttp2_settings_entry *iv, size_t niv) { + return (ssize_t)nghttp2_pack_settings_payload2(buf, buflen, iv, niv); +} + +nghttp2_ssize nghttp2_pack_settings_payload2(uint8_t *buf, size_t buflen, + const nghttp2_settings_entry *iv, + size_t niv) { if (!nghttp2_iv_check(iv, niv)) { return NGHTTP2_ERR_INVALID_ARGUMENT; } @@ -859,7 +929,7 @@ ssize_t nghttp2_pack_settings_payload(uint8_t *buf, size_t buflen, return NGHTTP2_ERR_INSUFF_BUFSIZE; } - return (ssize_t)nghttp2_frame_pack_settings_payload(buf, iv, niv); + return (nghttp2_ssize)nghttp2_frame_pack_settings_payload(buf, iv, niv); } int nghttp2_submit_extension(nghttp2_session *session, uint8_t type, @@ -875,7 +945,8 @@ int nghttp2_submit_extension(nghttp2_session *session, uint8_t type, return NGHTTP2_ERR_INVALID_ARGUMENT; } - if (!session->callbacks.pack_extension_callback) { + if (!session->callbacks.pack_extension_callback2 && + !session->callbacks.pack_extension_callback) { return NGHTTP2_ERR_INVALID_STATE; } diff --git a/deps/nghttp2/lib/nghttp2_submit.h b/deps/nghttp2/lib/nghttp2_submit.h index 74d702fbcf077e..96781d2a274515 100644 --- a/deps/nghttp2/lib/nghttp2_submit.h +++ b/deps/nghttp2/lib/nghttp2_submit.h @@ -31,4 +31,10 @@ #include +typedef struct nghttp2_data_provider_wrap nghttp2_data_provider_wrap; + +int nghttp2_submit_data_shared(nghttp2_session *session, uint8_t flags, + int32_t stream_id, + const nghttp2_data_provider_wrap *dpw); + #endif /* NGHTTP2_SUBMIT_H */ diff --git a/deps/openssl/unofficial.gni b/deps/openssl/unofficial.gni index 5d58d1d55152f7..6cc699c900d1ff 100644 --- a/deps/openssl/unofficial.gni +++ b/deps/openssl/unofficial.gni @@ -95,29 +95,29 @@ template("openssl_gn_build") { config_path_name = "" if (is_win) { - if (target_cpu == "x86") { + if (current_cpu == "x86") { config_path_name = "VC-WIN32" - } else if (target_cpu == "x64") { + } else if (current_cpu == "x64") { config_path_name = "VC-WIN64A" - } else if (target_cpu == "arm64") { + } else if (current_cpu == "arm64") { config_path_name = "VC-WIN64-ARM" } } else if (is_linux) { - if (target_cpu == "x86") { + if (current_cpu == "x86") { config_path_name = "linux-elf" - } else if (target_cpu == "x64") { + } else if (current_cpu == "x64") { config_path_name = "linux-x86_64" - } else if (target_cpu == "arm") { + } else if (current_cpu == "arm") { config_path_name = "linux-armv4" - } else if (target_cpu == "arm64") { + } else if (current_cpu == "arm64") { config_path_name = "linux-aarch64" } } else if (is_apple) { - if (target_cpu == "x86") { + if (current_cpu == "x86") { config_path_name = "darwin-i386-cc" - } else if (target_cpu == "x64") { + } else if (current_cpu == "x64") { config_path_name = "darwin64-x86_64-cc" - } else if (target_cpu == "arm64") { + } else if (current_cpu == "arm64") { config_path_name = "darwin64-arm64-cc" } } @@ -132,7 +132,7 @@ template("openssl_gn_build") { # TODO(zcbenz): Check gas_version and nasm_version. asm_name = "asm_avx2" } - if (is_win && target_cpu == "arm64") { + if (is_win && current_cpu == "arm64") { asm_name = "no-asm" } config_path = "config/archs/" + config_path_name + "/" + asm_name diff --git a/doc/api/corepack.md b/doc/api/corepack.md index b9c3ddca09c78c..0b9d2baef33679 100644 --- a/doc/api/corepack.md +++ b/doc/api/corepack.md @@ -15,8 +15,16 @@ added: _[Corepack][Corepack repository]_ is an experimental tool to help with managing versions of your package managers. It exposes binary proxies for each [supported package manager][] that, when called, will identify whatever -package manager is configured for the current project, transparently install -it if needed, and finally run it without requiring explicit user interactions. +package manager is configured for the current project, download it if needed, +and finally run it. + +Despite Corepack being distributed with default installs of Node.js, the package +managers managed by Corepack are not part of the Node.js distribution and: + +* Upon first use, Corepack downloads the latest version from the network. +* Any required updates (related to security vulnerabilities or otherwise) are + out of scope of the Node.js project. If necessary end users must figure out + how to update on their own. This feature simplifies two core workflows: diff --git a/doc/api/events.md b/doc/api/events.md index c1b684cf3bd4e0..872ebfd6179d4e 100644 --- a/doc/api/events.md +++ b/doc/api/events.md @@ -73,6 +73,7 @@ myEmitter.on('event', function(a, b) { // _events: [Object: null prototype] { event: [Function (anonymous)] }, // _eventsCount: 1, // _maxListeners: undefined, + // [Symbol(shapeMode)]: false, // [Symbol(kCapture)]: false // } true }); @@ -90,6 +91,7 @@ myEmitter.on('event', function(a, b) { // _events: [Object: null prototype] { event: [Function (anonymous)] }, // _eventsCount: 1, // _maxListeners: undefined, + // [Symbol(shapeMode)]: false, // [Symbol(kCapture)]: false // } true }); diff --git a/doc/api/module.md b/doc/api/module.md index 9ddd0a64642e9d..a9ee987f667ef6 100644 --- a/doc/api/module.md +++ b/doc/api/module.md @@ -268,8 +268,8 @@ It's possible to call `register` more than once: // entrypoint.mjs import { register } from 'node:module'; -register('./first.mjs', import.meta.url); -register('./second.mjs', import.meta.url); +register('./foo.mjs', import.meta.url); +register('./bar.mjs', import.meta.url); await import('./my-app.mjs'); ``` @@ -279,20 +279,23 @@ const { register } = require('node:module'); const { pathToFileURL } = require('node:url'); const parentURL = pathToFileURL(__filename); -register('./first.mjs', parentURL); -register('./second.mjs', parentURL); +register('./foo.mjs', parentURL); +register('./bar.mjs', parentURL); import('./my-app.mjs'); ``` -In this example, the registered hooks will form chains. If both `first.mjs` and -`second.mjs` define a `resolve` hook, both will be called, in the order they -were registered. The same applies to all the other hooks. +In this example, the registered hooks will form chains. These chains run +last-in, first out (LIFO). If both `foo.mjs` and `bar.mjs` define a `resolve` +hook, they will be called like so (note the right-to-left): +node's default ← `./foo.mjs` ← `./bar.mjs` +(starting with `./bar.mjs`, then `./foo.mjs`, then the Node.js default). +The same applies to all the other hooks. The registered hooks also affect `register` itself. In this example, -`second.mjs` will be resolved and loaded per the hooks registered by -`first.mjs`. This allows for things like writing hooks in non-JavaScript -languages, so long as an earlier registered loader is one that transpiles into -JavaScript. +`bar.mjs` will be resolved and loaded via the hooks registered by `foo.mjs` +(because `foo`'s hooks will have already been added to the chain). This allows +for things like writing hooks in non-JavaScript languages, so long as +earlier registered hooks transpile into JavaScript. The `register` method cannot be called from within the module that defines the hooks. @@ -367,11 +370,11 @@ export async function load(url, context, nextLoad) { } ``` -Hooks are part of a chain, even if that chain consists of only one custom -(user-provided) hook and the default hook, which is always present. Hook +Hooks are part of a [chain][], even if that chain consists of only one +custom (user-provided) hook and the default hook, which is always present. Hook functions nest: each one must always return a plain object, and chaining happens as a result of each function calling `next()`, which is a reference to -the subsequent loader's hook. +the subsequent loader's hook (in LIFO order). A hook that returns a value lacking a required property triggers an exception. A hook that returns without calling `next()` _and_ without returning @@ -1049,6 +1052,7 @@ returned object contains the following keys: [`register`]: #moduleregisterspecifier-parenturl-options [`string`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String [`util.TextDecoder`]: util.md#class-utiltextdecoder +[chain]: #chaining [hooks]: #customization-hooks [load hook]: #loadurl-context-nextload [module wrapper]: modules.md#the-module-wrapper diff --git a/doc/changelogs/CHANGELOG_V21.md b/doc/changelogs/CHANGELOG_V21.md index b641380da62e93..25d60ac800bc3d 100644 --- a/doc/changelogs/CHANGELOG_V21.md +++ b/doc/changelogs/CHANGELOG_V21.md @@ -8,6 +8,7 @@ +21.7.1
21.7.0
21.6.2
21.6.1
@@ -45,6 +46,47 @@ * [io.js](CHANGELOG_IOJS.md) * [Archive](CHANGELOG_ARCHIVE.md) + + +## 2024-03-08, Version 21.7.1 (Current), @targos + +### Notable Changes + +This release reverts [#51389](https://github.com/nodejs/node/pull/51389), which +landed in Node.js 21.7.0. It is a documented feature that `t.after()` hooks are +run even if a test has no subtests. The hook can be used to clean up the test +itself. + +### Commits + +* \[[`0dfe810ac7`](https://github.com/nodejs/node/commit/0dfe810ac7)] - **benchmark**: update iterations of benchmark/async\_hooks/async-local- (Lei Shi) [#51420](https://github.com/nodejs/node/pull/51420) +* \[[`625c9e0ac9`](https://github.com/nodejs/node/commit/625c9e0ac9)] - **benchmark**: update iterations of benchmark/domain/domain-fn-args.js (Lei Shi) [#51408](https://github.com/nodejs/node/pull/51408) +* \[[`7ff3551bad`](https://github.com/nodejs/node/commit/7ff3551bad)] - **build**: fix arm64 host cross-compilation in GN (Cheng Zhao) [#51903](https://github.com/nodejs/node/pull/51903) +* \[[`fd86ea8b71`](https://github.com/nodejs/node/commit/fd86ea8b71)] - _**Revert**_ "**build**: workaround for node-core-utils" (Richard Lau) [#51975](https://github.com/nodejs/node/pull/51975) +* \[[`23c32ab3a7`](https://github.com/nodejs/node/commit/23c32ab3a7)] - **build**: respect the `NODE` env variable in `Makefile` (Antoine du Hamel) [#51743](https://github.com/nodejs/node/pull/51743) +* \[[`9617adc064`](https://github.com/nodejs/node/commit/9617adc064)] - _**Revert**_ "**build**: fix warning in cares under GN build" (Luigi Pinca) [#51865](https://github.com/nodejs/node/pull/51865) +* \[[`5864534095`](https://github.com/nodejs/node/commit/5864534095)] - **deps**: update nghttp2 to 1.60.0 (Node.js GitHub Bot) [#51948](https://github.com/nodejs/node/pull/51948) +* \[[`fcf235d623`](https://github.com/nodejs/node/commit/fcf235d623)] - **doc**: add policy for distribution (Geoffrey Booth) [#51918](https://github.com/nodejs/node/pull/51918) +* \[[`87d2acc8b1`](https://github.com/nodejs/node/commit/87d2acc8b1)] - **doc**: fix actual result of example is different in events (Deokjin Kim) [#51925](https://github.com/nodejs/node/pull/51925) +* \[[`5908c121c6`](https://github.com/nodejs/node/commit/5908c121c6)] - **doc**: clarify Corepack threat model (Antoine du Hamel) [#51917](https://github.com/nodejs/node/pull/51917) +* \[[`20e0ba3b94`](https://github.com/nodejs/node/commit/20e0ba3b94)] - **doc,module**: clarify hook chain execution sequence (Jacob Smith) [#51884](https://github.com/nodejs/node/pull/51884) +* \[[`4d997971ac`](https://github.com/nodejs/node/commit/4d997971ac)] - **lib**: make sure close net server (theanarkh) [#51929](https://github.com/nodejs/node/pull/51929) +* \[[`fcc6d54aa3`](https://github.com/nodejs/node/commit/fcc6d54aa3)] - **lib**: return directly if udp socket close before lookup (theanarkh) [#51914](https://github.com/nodejs/node/pull/51914) +* \[[`10aaabd158`](https://github.com/nodejs/node/commit/10aaabd158)] - **meta**: bump github/codeql-action from 3.23.2 to 3.24.6 (dependabot\[bot]) [#51942](https://github.com/nodejs/node/pull/51942) +* \[[`78f38a0143`](https://github.com/nodejs/node/commit/78f38a0143)] - **meta**: bump actions/upload-artifact from 4.3.0 to 4.3.1 (dependabot\[bot]) [#51941](https://github.com/nodejs/node/pull/51941) +* \[[`42ca5452c4`](https://github.com/nodejs/node/commit/42ca5452c4)] - **meta**: bump codecov/codecov-action from 4.0.1 to 4.1.0 (dependabot\[bot]) [#51940](https://github.com/nodejs/node/pull/51940) +* \[[`015a157375`](https://github.com/nodejs/node/commit/015a157375)] - **meta**: bump actions/cache from 4.0.0 to 4.0.1 (dependabot\[bot]) [#51939](https://github.com/nodejs/node/pull/51939) +* \[[`e476cb4a32`](https://github.com/nodejs/node/commit/e476cb4a32)] - **meta**: bump actions/download-artifact from 4.1.1 to 4.1.3 (dependabot\[bot]) [#51938](https://github.com/nodejs/node/pull/51938) +* \[[`67e8001790`](https://github.com/nodejs/node/commit/67e8001790)] - **meta**: bump actions/setup-node from 4.0.1 to 4.0.2 (dependabot\[bot]) [#51937](https://github.com/nodejs/node/pull/51937) +* \[[`50343636e8`](https://github.com/nodejs/node/commit/50343636e8)] - **src**: fix --disable-single-executable-application (Joyee Cheung) [#51808](https://github.com/nodejs/node/pull/51808) +* \[[`a48c9ca0db`](https://github.com/nodejs/node/commit/a48c9ca0db)] - **stream**: do not defer construction by one microtick (Matteo Collina) [#52005](https://github.com/nodejs/node/pull/52005) +* \[[`bee3b364f9`](https://github.com/nodejs/node/commit/bee3b364f9)] - **test**: add regression test for test\_runner after hook (Colin Ihrig) [#51998](https://github.com/nodejs/node/pull/51998) +* \[[`fff7f48f50`](https://github.com/nodejs/node/commit/fff7f48f50)] - **test**: reduce flakiness of `test-runner-output` (Antoine du Hamel) [#51952](https://github.com/nodejs/node/pull/51952) +* \[[`57ba8f5acb`](https://github.com/nodejs/node/commit/57ba8f5acb)] - **test**: fix flaky http-chunk-extensions-limit test (Ethan Arrowood) [#51943](https://github.com/nodejs/node/pull/51943) +* \[[`9d2c03990a`](https://github.com/nodejs/node/commit/9d2c03990a)] - **test**: remove flaky designation (Luigi Pinca) [#51736](https://github.com/nodejs/node/pull/51736) +* \[[`e992af81d3`](https://github.com/nodejs/node/commit/e992af81d3)] - **test**: skip SEA tests when SEA generation fails (Joyee Cheung) [#51887](https://github.com/nodejs/node/pull/51887) +* \[[`85aa6ca850`](https://github.com/nodejs/node/commit/85aa6ca850)] - _**Revert**_ "**test\_runner**: do not invoke after hook when test is empty" (Colin Ihrig) [#51998](https://github.com/nodejs/node/pull/51998) + ## 2024-03-06, Version 21.7.0 (Current), @RafaelGSS prepared by @marco-ippolito diff --git a/doc/contributing/distribution.md b/doc/contributing/distribution.md new file mode 100644 index 00000000000000..4727c03b6924e5 --- /dev/null +++ b/doc/contributing/distribution.md @@ -0,0 +1,27 @@ +# Node.js Distribution Policy + +This document describes some policies around what is and is not included in the +Node.js distribution. + +## Inclusion + +The Node.js distribution includes some external software that the Node.js +project does not maintain. The choice to include a particular piece of software +should not imply anything about that software relative to its competitors; in +some cases, software was added when it had no competitors. While the Node.js +project supports and encourages competition in the JavaScript ecosystem, as a +policy, the Node.js project does not include multiple dependencies or tools that +serve the same purpose. + +The following user-accessible external tools or libraries are the ones chosen +for their particular purposes: + +* JavaScript engine: V8 +* Package manager: `npm` +* Package manager version manager: Corepack + +Being user-accessible, removal or replacement of these projects could happen +only as a semver-major change, unless the related feature or project is +documented as experimental. In addition, Node.js includes external projects as +internal dependencies. These may be replaced or removed at any time, provided +that doing so is not a breaking change. diff --git a/lib/dgram.js b/lib/dgram.js index 8c8da1ad8856b5..969f696b9e50da 100644 --- a/lib/dgram.js +++ b/lib/dgram.js @@ -328,6 +328,9 @@ Socket.prototype.bind = function(port_, address_ /* , callback */) { // Resolve address first state.handle.lookup(address, (err, ip) => { + if (!state.handle) + return; // Handle has been closed in the mean time + if (err) { state.bindState = BIND_STATE_UNBOUND; this.emit('error', err); @@ -356,9 +359,6 @@ Socket.prototype.bind = function(port_, address_ /* , callback */) { this.emit('error', ex); }); } else { - if (!state.handle) - return; // Handle has been closed in the mean time - const err = state.handle.bind(ip, port || 0, flags); if (err) { const ex = new ExceptionWithHostPort(err, 'bind', ip, port); diff --git a/lib/internal/streams/destroy.js b/lib/internal/streams/destroy.js index 28802cae5eff32..96e61491f08cfc 100644 --- a/lib/internal/streams/destroy.js +++ b/lib/internal/streams/destroy.js @@ -291,7 +291,7 @@ function constructNT(stream) { } else if (err) { errorOrDestroy(stream, err, true); } else { - process.nextTick(emitConstructNT, stream); + stream.emit(kConstruct); } } @@ -304,10 +304,6 @@ function constructNT(stream) { } } -function emitConstructNT(stream) { - stream.emit(kConstruct); -} - function isRequest(stream) { return stream?.setHeader && typeof stream.abort === 'function'; } diff --git a/lib/internal/test_runner/test.js b/lib/internal/test_runner/test.js index ee2c345e7a0403..f24d74ac69f9f7 100644 --- a/lib/internal/test_runner/test.js +++ b/lib/internal/test_runner/test.js @@ -595,9 +595,7 @@ class Test extends AsyncResource { const { args, ctx } = this.getRunArgs(); const after = async () => { - // If its a root test then check for global after hook else check for parent after hook - const check = this.parent ? this.parent.hooks.after.length > 0 : this.hooks.after.length > 0; - if (check) { + if (this.hooks.after.length > 0) { await this.runHook('after', { __proto__: null, args, ctx }); } }; diff --git a/lib/net.js b/lib/net.js index 39ef8419112ec1..19d62d184a0e7d 100644 --- a/lib/net.js +++ b/lib/net.js @@ -1773,6 +1773,7 @@ function Server(options, connectionListener) { this._usingWorkers = false; this._workers = []; this._unref = false; + this._listeningId = 1; this.allowHalfOpen = options.allowHalfOpen || false; this.pauseOnConnect = !!options.pauseOnConnect; @@ -1954,10 +1955,14 @@ function listenInCluster(server, address, port, addressType, backlog, ...options, }; + const listeningId = server._listeningId; // Get the primary's server handle, and listen on it cluster._getServer(server, serverQuery, listenOnPrimaryHandle); - function listenOnPrimaryHandle(err, handle) { + if (listeningId !== server._listeningId) { + handle.close(); + return; + } err = checkBindError(err, port, handle); if (err) { @@ -2089,9 +2094,14 @@ Server.prototype.listen = function(...args) { throw new ERR_INVALID_ARG_VALUE('options', options); }; -function lookupAndListen(self, port, address, backlog, exclusive, flags) { +function lookupAndListen(self, port, address, backlog, + exclusive, flags) { if (dns === undefined) dns = require('dns'); + const listeningId = self._listeningId; dns.lookup(address, function doListen(err, ip, addressType) { + if (listeningId !== self._listeningId) { + return; + } if (err) { self.emit('error', err); } else { @@ -2237,6 +2247,7 @@ Server.prototype.getConnections = function(cb) { Server.prototype.close = function(cb) { + this._listeningId++; if (typeof cb === 'function') { if (!this._handle) { this.once('close', function close() { diff --git a/node.gni b/node.gni index 2445d09b8179a6..f7d896f0ef1c13 100644 --- a/node.gni +++ b/node.gni @@ -54,8 +54,10 @@ declare_args() { node_use_node_code_cache = host_os == target_os && host_cpu == target_cpu # Use snapshot to speed up startup. - # TODO(zcbenz): node_mksnapshot is not ready for cross-os compilation. - node_use_node_snapshot = host_os == target_os + # TODO(zcbenz): There are few broken things for now: + # 1. cross-os compilation is not supported. + # 2. node_mksnapshot crashes when cross-compiling for x64 from arm64. + node_use_node_snapshot = (host_os == target_os) && !(host_cpu == "arm64" && target_cpu == "x64") } assert(!node_enable_inspector || node_use_openssl, diff --git a/src/node.cc b/src/node.cc index 2b41e904180bed..10e04ed8a28bd0 100644 --- a/src/node.cc +++ b/src/node.cc @@ -1441,13 +1441,16 @@ static ExitCode StartInternal(int argc, char** argv) { }); uv_loop_configure(uv_default_loop(), UV_METRICS_IDLE_TIME); - std::string sea_config = per_process::cli_options->experimental_sea_config; if (!sea_config.empty()) { +#if !defined(DISABLE_SINGLE_EXECUTABLE_APPLICATION) return sea::BuildSingleExecutableBlob( sea_config, result->args(), result->exec_args()); +#else + fprintf(stderr, "Single executable application is disabled.\n"); + return ExitCode::kGenericUserError; +#endif // !defined(DISABLE_SINGLE_EXECUTABLE_APPLICATION) } - // --build-snapshot indicates that we are in snapshot building mode. if (per_process::cli_options->per_isolate->build_snapshot) { if (per_process::cli_options->per_isolate->build_snapshot_config.empty() && diff --git a/src/node_sea.cc b/src/node_sea.cc index a254c910edf238..c2b409de731c6e 100644 --- a/src/node_sea.cc +++ b/src/node_sea.cc @@ -27,8 +27,6 @@ #include #include -#if !defined(DISABLE_SINGLE_EXECUTABLE_APPLICATION) - using node::ExitCode; using v8::ArrayBuffer; using v8::BackingStore; @@ -189,6 +187,7 @@ SeaResource SeaDeserializer::Read() { } std::string_view FindSingleExecutableBlob() { +#if !defined(DISABLE_SINGLE_EXECUTABLE_APPLICATION) CHECK(IsSingleExecutable()); static const std::string_view result = []() -> std::string_view { size_t size; @@ -209,6 +208,9 @@ std::string_view FindSingleExecutableBlob() { result.data(), result.size()); return result; +#else + UNREACHABLE(); +#endif // !defined(DISABLE_SINGLE_EXECUTABLE_APPLICATION) } } // anonymous namespace @@ -668,5 +670,3 @@ void RegisterExternalReferences(ExternalReferenceRegistry* registry) { NODE_BINDING_CONTEXT_AWARE_INTERNAL(sea, node::sea::Initialize) NODE_BINDING_EXTERNAL_REFERENCE(sea, node::sea::RegisterExternalReferences) - -#endif // !defined(DISABLE_SINGLE_EXECUTABLE_APPLICATION) diff --git a/src/node_sea.h b/src/node_sea.h index bea9d579a2aa64..f90ef63cc7fd33 100644 --- a/src/node_sea.h +++ b/src/node_sea.h @@ -3,8 +3,6 @@ #if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS -#if !defined(DISABLE_SINGLE_EXECUTABLE_APPLICATION) - #include #include #include @@ -52,8 +50,6 @@ node::ExitCode BuildSingleExecutableBlob( } // namespace sea } // namespace node -#endif // !defined(DISABLE_SINGLE_EXECUTABLE_APPLICATION) - #endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS #endif // SRC_NODE_SEA_H_ diff --git a/src/node_version.h b/src/node_version.h index 52eee6decd2b2e..55d41c98a59e09 100644 --- a/src/node_version.h +++ b/src/node_version.h @@ -29,7 +29,7 @@ #define NODE_VERSION_IS_LTS 0 #define NODE_VERSION_LTS_CODENAME "" -#define NODE_VERSION_IS_RELEASE 0 +#define NODE_VERSION_IS_RELEASE 1 #ifndef NODE_STRINGIFY #define NODE_STRINGIFY(n) NODE_STRINGIFY_HELPER(n) diff --git a/test/common/README.md b/test/common/README.md index fa78b2792ef6ac..415601d1e25ecb 100644 --- a/test/common/README.md +++ b/test/common/README.md @@ -1048,11 +1048,13 @@ Application functionality. Skip the rest of the tests if single executable applications are not supported in the current configuration. -### `injectAndCodeSign(targetExecutable, resource)` +### `generateSEA(targetExecutable, sourceExecutable, seaBlob, verifyWorkflow)` -Uses Postect to inject the contents of the file at the path `resource` into -the target executable file at the path `targetExecutable` and ultimately code -sign the final binary. +Copy `sourceExecutable` to `targetExecutable`, use postject to inject `seaBlob` +into `targetExecutable` and sign it if necessary. + +If `verifyWorkflow` is false (default) and any of the steps fails, +it skips the tests. Otherwise, an error is thrown. ## tick Module diff --git a/test/common/sea.js b/test/common/sea.js index d57c9e4238d867..c726829cd2b6de 100644 --- a/test/common/sea.js +++ b/test/common/sea.js @@ -3,8 +3,9 @@ const common = require('../common'); const fixtures = require('../common/fixtures'); const tmpdir = require('../common/tmpdir'); +const { inspect } = require('util'); -const { readFileSync } = require('fs'); +const { readFileSync, copyFileSync } = require('fs'); const { spawnSyncAndExitWithoutError, } = require('../common/child_process'); @@ -54,47 +55,75 @@ function skipIfSingleExecutableIsNotSupported() { } } -function injectAndCodeSign(targetExecutable, resource) { +function generateSEA(targetExecutable, sourceExecutable, seaBlob, verifyWorkflow = false) { + try { + copyFileSync(sourceExecutable, targetExecutable); + } catch (e) { + const message = `Cannot copy ${sourceExecutable} to ${targetExecutable}: ${inspect(e)}`; + if (verifyWorkflow) { + throw new Error(message); + } + common.skip(message); + } + console.log(`Copied ${sourceExecutable} to ${targetExecutable}`); + const postjectFile = fixtures.path('postject-copy', 'node_modules', 'postject', 'dist', 'cli.js'); - spawnSyncAndExitWithoutError(process.execPath, [ - postjectFile, - targetExecutable, - 'NODE_SEA_BLOB', - resource, - '--sentinel-fuse', 'NODE_SEA_FUSE_fce680ab2cc467b6e072b8b5df1996b2', - ...process.platform === 'darwin' ? [ '--macho-segment-name', 'NODE_SEA' ] : [], - ], {}); + try { + spawnSyncAndExitWithoutError(process.execPath, [ + postjectFile, + targetExecutable, + 'NODE_SEA_BLOB', + seaBlob, + '--sentinel-fuse', 'NODE_SEA_FUSE_fce680ab2cc467b6e072b8b5df1996b2', + ...process.platform === 'darwin' ? [ '--macho-segment-name', 'NODE_SEA' ] : [], + ]); + } catch (e) { + const message = `Cannot inject ${seaBlob} into ${targetExecutable}: ${inspect(e)}`; + if (verifyWorkflow) { + throw new Error(message); + } + common.skip(message); + } + console.log(`Injected ${seaBlob} into ${targetExecutable}`); if (process.platform === 'darwin') { - spawnSyncAndExitWithoutError('codesign', [ '--sign', '-', targetExecutable ], {}); - spawnSyncAndExitWithoutError('codesign', [ '--verify', targetExecutable ], {}); + try { + spawnSyncAndExitWithoutError('codesign', [ '--sign', '-', targetExecutable ], {}); + spawnSyncAndExitWithoutError('codesign', [ '--verify', targetExecutable ], {}); + } catch (e) { + const message = `Cannot sign ${targetExecutable}: ${inspect(e)}`; + if (verifyWorkflow) { + throw new Error(message); + } + common.skip(message); + } + console.log(`Signed ${targetExecutable}`); } else if (process.platform === 'win32') { - let signtoolFound = false; try { spawnSyncAndExitWithoutError('where', [ 'signtool' ], {}); - signtoolFound = true; - } catch (err) { - console.log(err.message); - } - if (signtoolFound) { - let certificatesFound = false; - let stderr; - try { - ({ stderr } = spawnSyncAndExitWithoutError('signtool', [ 'sign', '/fd', 'SHA256', targetExecutable ], {})); - certificatesFound = true; - } catch (err) { - if (!/SignTool Error: No certificates were found that met all the given criteria/.test(stderr)) { - throw err; - } + } catch (e) { + const message = `Cannot find signtool: ${inspect(e)}`; + if (verifyWorkflow) { + throw new Error(message); } - if (certificatesFound) { - spawnSyncAndExitWithoutError('signtool', 'verify', '/pa', 'SHA256', targetExecutable, {}); + common.skip(message); + } + let stderr; + try { + ({ stderr } = spawnSyncAndExitWithoutError('signtool', [ 'sign', '/fd', 'SHA256', targetExecutable ], {})); + spawnSyncAndExitWithoutError('signtool', 'verify', '/pa', 'SHA256', targetExecutable, {}); + } catch (e) { + const message = `Cannot sign ${targetExecutable}: ${inspect(e)}\n${stderr}`; + if (verifyWorkflow) { + throw new Error(message); } + common.skip(message); } + console.log(`Signed ${targetExecutable}`); } } module.exports = { skipIfSingleExecutableIsNotSupported, - injectAndCodeSign, + generateSEA, }; diff --git a/test/fixtures/test-runner/output/describe_it.js b/test/fixtures/test-runner/output/describe_it.js index ba6a1aed064614..e41cc202637b6d 100644 --- a/test/fixtures/test-runner/output/describe_it.js +++ b/test/fixtures/test-runner/output/describe_it.js @@ -302,12 +302,18 @@ describe('describe async throw fails', async () => { describe('timeouts', () => { it('timed out async test', { timeout: 5 }, async () => { return new Promise((resolve) => { - setTimeout(resolve, 100); + setTimeout(() => { + // Empty timer so the process doesn't exit before the timeout triggers. + }, 5); + setTimeout(resolve, 30_000_000).unref(); }); }); it('timed out callback test', { timeout: 5 }, (t, done) => { - setTimeout(done, 100); + setTimeout(() => { + // Empty timer so the process doesn't exit before the timeout triggers. + }, 5); + setTimeout(done, 30_000_000).unref(); }); diff --git a/test/parallel/parallel.status b/test/parallel/parallel.status index e152015ea764ef..6175cac521589e 100644 --- a/test/parallel/parallel.status +++ b/test/parallel/parallel.status @@ -55,8 +55,6 @@ test-domain-with-abort-on-uncaught-exception: PASS, FLAKY test-tick-processor-arguments: SKIP [$system==freebsd] -# https://github.com/nodejs/node/issues/31280 -test-worker-message-port-message-before-close: PASS,FLAKY [$system==ibmi] # https://github.com/nodejs/node/pull/30819 diff --git a/test/parallel/test-dgram-bind-socket-close-before-lookup.js b/test/parallel/test-dgram-bind-socket-close-before-lookup.js new file mode 100644 index 00000000000000..96ca71c3deeb4e --- /dev/null +++ b/test/parallel/test-dgram-bind-socket-close-before-lookup.js @@ -0,0 +1,19 @@ +'use strict'; +const common = require('../common'); +const dgram = require('dgram'); + +// Do not emit error event in callback which is called by lookup when socket is closed +const socket = dgram.createSocket({ + type: 'udp4', + lookup: (...args) => { + // Call lookup callback after 1s + setTimeout(() => { + args.at(-1)(new Error('an error')); + }, 1000); + } +}); + +socket.on('error', common.mustNotCall()); +socket.bind(12345, 'localhost'); +// Close the socket before calling DNS lookup callback +socket.close(); diff --git a/test/parallel/test-fs-writestream-open-write.js b/test/parallel/test-fs-writestream-open-write.js new file mode 100644 index 00000000000000..af02d90ae6efd9 --- /dev/null +++ b/test/parallel/test-fs-writestream-open-write.js @@ -0,0 +1,28 @@ +'use strict'; + +const common = require('../common'); +const tmpdir = require('../common/tmpdir'); +const { strictEqual } = require('assert'); +const fs = require('fs'); + +// Regression test for https://github.com/nodejs/node/issues/51993 + +tmpdir.refresh(); + +const file = tmpdir.resolve('test-fs-writestream-open-write.txt'); + +const w = fs.createWriteStream(file); + +w.on('open', common.mustCall(() => { + w.write('hello'); + + process.nextTick(() => { + w.write('world'); + w.end(); + }); +})); + +w.on('close', common.mustCall(() => { + strictEqual(fs.readFileSync(file, 'utf8'), 'helloworld'); + fs.unlinkSync(file); +})); diff --git a/test/parallel/test-http-chunk-extensions-limit.js b/test/parallel/test-http-chunk-extensions-limit.js index 6868b3da6cbade..a9adacac5e7303 100644 --- a/test/parallel/test-http-chunk-extensions-limit.js +++ b/test/parallel/test-http-chunk-extensions-limit.js @@ -5,6 +5,11 @@ const http = require('http'); const net = require('net'); const assert = require('assert'); +// The maximum http chunk extension size is set in `src/node_http_parser.cc`. +// These tests assert that once the extension size is reached, an HTTP 413 +// response is returned. +// Currently, the max size is set to 16KiB (16384). + // Verify that chunk extensions are limited in size when sent all together. { const server = http.createServer((req, res) => { @@ -17,7 +22,8 @@ const assert = require('assert'); }); server.listen(0, () => { - const sock = net.connect(server.address().port); + const port = server.address().port; + const sock = net.connect(port); let data = ''; sock.on('data', (chunk) => data += chunk.toString('utf-8')); @@ -29,15 +35,17 @@ const assert = require('assert'); sock.end('' + 'GET / HTTP/1.1\r\n' + - 'Host: localhost:8080\r\n' + + `Host: localhost:${port}\r\n` + 'Transfer-Encoding: chunked\r\n\r\n' + - '2;' + 'A'.repeat(20000) + '=bar\r\nAA\r\n' + - '0\r\n\r\n' + '2;' + 'a'.repeat(17000) + '\r\n' + // Chunk size + chunk ext + CRLF + 'AA\r\n' + // Chunk data + '0\r\n' + // Last chunk + '\r\n' // End of http message ); }); } -// Verify that chunk extensions are limited in size when sent in intervals. +// Verify that chunk extensions are limited in size when sent in parts { const server = http.createServer((req, res) => { req.on('end', () => { @@ -49,24 +57,10 @@ const assert = require('assert'); }); server.listen(0, () => { - const sock = net.connect(server.address().port); - let remaining = 20000; + const port = server.address().port; + const sock = net.connect(port); let data = ''; - const interval = setInterval( - () => { - if (remaining > 0) { - sock.write('A'.repeat(1000)); - } else { - sock.write('=bar\r\nAA\r\n0\r\n\r\n'); - clearInterval(interval); - } - - remaining -= 1000; - }, - common.platformTimeout(20), - ).unref(); - sock.on('data', (chunk) => data += chunk.toString('utf-8')); sock.on('end', common.mustCall(function() { @@ -76,10 +70,20 @@ const assert = require('assert'); sock.write('' + 'GET / HTTP/1.1\r\n' + - 'Host: localhost:8080\r\n' + + `Host: localhost:${port}\r\n` + 'Transfer-Encoding: chunked\r\n\r\n' + - '2;' + '2;' // Chunk size + start of chunk-extension ); + + sock.write('A'.repeat(8500)); // Write half of the chunk-extension + + queueMicrotask(() => { + sock.write('A'.repeat(8500) + '\r\n' + // Remaining half of the chunk-extension + 'AA\r\n' + // Chunk data + '0\r\n' + // Last chunk + '\r\n' // End of http message + ); + }); }); } @@ -95,7 +99,8 @@ const assert = require('assert'); }); server.listen(0, () => { - const sock = net.connect(server.address().port); + const port = server.address().port; + const sock = net.connect(port); let data = ''; sock.on('data', (chunk) => data += chunk.toString('utf-8')); @@ -120,7 +125,7 @@ const assert = require('assert'); sock.end('' + 'GET / HTTP/1.1\r\n' + - 'Host: localhost:8080\r\n' + + `Host: localhost:${port}\r\n` + 'Transfer-Encoding: chunked\r\n\r\n' + '2;' + 'A'.repeat(10000) + '=bar\r\nAA\r\n' + '2;' + 'A'.repeat(10000) + '=bar\r\nAA\r\n' + diff --git a/test/parallel/test-net-server-close-before-calling-lookup-callback.js b/test/parallel/test-net-server-close-before-calling-lookup-callback.js new file mode 100644 index 00000000000000..58cfc5504c04fa --- /dev/null +++ b/test/parallel/test-net-server-close-before-calling-lookup-callback.js @@ -0,0 +1,7 @@ +'use strict'; + +const common = require('../common'); +const net = require('net'); +// Process should exit because it does not create a real TCP server. +// Paas localhost to ensure create TCP handle asynchronously because It causes DNS resolution. +net.createServer().listen(0, 'localhost', common.mustNotCall()).close(); diff --git a/test/parallel/test-net-server-close-before-ipc-response.js b/test/parallel/test-net-server-close-before-ipc-response.js new file mode 100644 index 00000000000000..e85bc96ee6200c --- /dev/null +++ b/test/parallel/test-net-server-close-before-ipc-response.js @@ -0,0 +1,22 @@ +'use strict'; + +const common = require('../common'); +const net = require('net'); +const cluster = require('cluster'); + +// Process should exit +if (cluster.isPrimary) { + cluster.fork(); +} else { + const send = process.send; + process.send = function(message) { + // listenOnPrimaryHandle in net.js should call handle.close() + if (message.act === 'close') { + setImmediate(() => { + process.disconnect(); + }); + } + return send.apply(this, arguments); + }; + net.createServer().listen(0, common.mustNotCall()).close(); +} diff --git a/test/parallel/test-runner-skip-after-hook.js b/test/parallel/test-runner-skip-after-hook.js deleted file mode 100644 index d8175135b02f0d..00000000000000 --- a/test/parallel/test-runner-skip-after-hook.js +++ /dev/null @@ -1,10 +0,0 @@ -'use strict'; -// Refs: https://github.com/nodejs/node/issues/51371 -const common = require('../common'); -const { test } = require('node:test'); - -test('test', async (t) => { - t.after(common.mustNotCall(() => { - t.fail('should not run'); - })); -}); diff --git a/test/parallel/test-runner-subtest-after-hook.js b/test/parallel/test-runner-subtest-after-hook.js new file mode 100644 index 00000000000000..f288abee243de2 --- /dev/null +++ b/test/parallel/test-runner-subtest-after-hook.js @@ -0,0 +1,12 @@ +'use strict'; +const common = require('../common'); +const { test } = require('node:test'); + +// Regression test for https://github.com/nodejs/node/issues/51997 +test('after hook should be called with no subtests', (t) => { + const timer = setTimeout(common.mustNotCall(), 2 ** 30); + + t.after(common.mustCall(() => { + clearTimeout(timer); + })); +}); diff --git a/test/sequential/test-single-executable-application-assets-raw.js b/test/sequential/test-single-executable-application-assets-raw.js index 6f0a8a77486fb6..4122e8b323a569 100644 --- a/test/sequential/test-single-executable-application-assets-raw.js +++ b/test/sequential/test-single-executable-application-assets-raw.js @@ -3,7 +3,7 @@ const common = require('../common'); const { - injectAndCodeSign, + generateSEA, skipIfSingleExecutableIsNotSupported, } = require('../common/sea'); @@ -56,8 +56,7 @@ const outputFile = tmpdir.resolve(process.platform === 'win32' ? 'sea.exe' : 'se assert(existsSync(seaPrepBlob)); - copyFileSync(process.execPath, outputFile); - injectAndCodeSign(outputFile, seaPrepBlob); + generateSEA(outputFile, process.execPath, seaPrepBlob); spawnSyncAndExitWithoutError( outputFile, diff --git a/test/sequential/test-single-executable-application-assets.js b/test/sequential/test-single-executable-application-assets.js index 366b606e37ce64..ed10e076ced883 100644 --- a/test/sequential/test-single-executable-application-assets.js +++ b/test/sequential/test-single-executable-application-assets.js @@ -3,7 +3,7 @@ const common = require('../common'); const { - injectAndCodeSign, + generateSEA, skipIfSingleExecutableIsNotSupported, } = require('../common/sea'); @@ -109,8 +109,7 @@ const outputFile = tmpdir.resolve(process.platform === 'win32' ? 'sea.exe' : 'se assert(existsSync(seaPrepBlob)); - copyFileSync(process.execPath, outputFile); - injectAndCodeSign(outputFile, seaPrepBlob); + generateSEA(outputFile, process.execPath, seaPrepBlob); spawnSyncAndExitWithoutError( outputFile, diff --git a/test/sequential/test-single-executable-application-disable-experimental-sea-warning.js b/test/sequential/test-single-executable-application-disable-experimental-sea-warning.js index fdd0c23a26da3e..5b1912f1a99eb0 100644 --- a/test/sequential/test-single-executable-application-disable-experimental-sea-warning.js +++ b/test/sequential/test-single-executable-application-disable-experimental-sea-warning.js @@ -3,7 +3,7 @@ require('../common'); const { - injectAndCodeSign, + generateSEA, skipIfSingleExecutableIsNotSupported, } = require('../common/sea'); @@ -51,8 +51,7 @@ spawnSyncAndExitWithoutError( assert(existsSync(seaPrepBlob)); -copyFileSync(process.execPath, outputFile); -injectAndCodeSign(outputFile, seaPrepBlob); +generateSEA(outputFile, process.execPath, seaPrepBlob); spawnSyncAndExitWithoutError( outputFile, diff --git a/test/sequential/test-single-executable-application-empty.js b/test/sequential/test-single-executable-application-empty.js index 047685b0074aa9..d26d72e47dafdd 100644 --- a/test/sequential/test-single-executable-application-empty.js +++ b/test/sequential/test-single-executable-application-empty.js @@ -1,9 +1,9 @@ 'use strict'; -require('../common'); +const common = require('../common'); const { - injectAndCodeSign, + generateSEA, skipIfSingleExecutableIsNotSupported, } = require('../common/sea'); @@ -13,7 +13,7 @@ skipIfSingleExecutableIsNotSupported(); // script. const tmpdir = require('../common/tmpdir'); -const { copyFileSync, writeFileSync, existsSync } = require('fs'); +const { writeFileSync, existsSync } = require('fs'); const { spawnSyncAndExitWithoutError } = require('../common/child_process'); const assert = require('assert'); @@ -38,8 +38,20 @@ spawnSyncAndExitWithoutError( assert(existsSync(seaPrepBlob)); -copyFileSync(process.execPath, outputFile); -injectAndCodeSign(outputFile, seaPrepBlob); +// Verify the workflow. +try { + generateSEA(outputFile, process.execPath, seaPrepBlob, true); +} catch (e) { + if (/Cannot copy/.test(e.message)) { + common.skip(e.message); + } else if (common.isWindows) { + if (/Cannot sign/.test(e.message) || /Cannot find signtool/.test(e.message)) { + common.skip(e.message); + } + } + + throw e; +} spawnSyncAndExitWithoutError( outputFile, diff --git a/test/sequential/test-single-executable-application-snapshot-and-code-cache.js b/test/sequential/test-single-executable-application-snapshot-and-code-cache.js index 952003cf02c585..18d66884e36cd0 100644 --- a/test/sequential/test-single-executable-application-snapshot-and-code-cache.js +++ b/test/sequential/test-single-executable-application-snapshot-and-code-cache.js @@ -3,7 +3,7 @@ require('../common'); const { - injectAndCodeSign, + generateSEA, skipIfSingleExecutableIsNotSupported, } = require('../common/sea'); @@ -12,7 +12,7 @@ skipIfSingleExecutableIsNotSupported(); // This tests "useCodeCache" is ignored when "useSnapshot" is true. const tmpdir = require('../common/tmpdir'); -const { copyFileSync, writeFileSync, existsSync } = require('fs'); +const { writeFileSync, existsSync } = require('fs'); const { spawnSyncAndExitWithoutError } = require('../common/child_process'); @@ -62,8 +62,7 @@ const outputFile = join(tmpdir.path, process.platform === 'win32' ? 'sea.exe' : assert(existsSync(seaPrepBlob)); - copyFileSync(process.execPath, outputFile); - injectAndCodeSign(outputFile, seaPrepBlob); + generateSEA(outputFile, process.execPath, seaPrepBlob); spawnSyncAndExitWithoutError( outputFile, diff --git a/test/sequential/test-single-executable-application-snapshot.js b/test/sequential/test-single-executable-application-snapshot.js index 402505a6122c74..779b3e9fb5f332 100644 --- a/test/sequential/test-single-executable-application-snapshot.js +++ b/test/sequential/test-single-executable-application-snapshot.js @@ -3,7 +3,7 @@ require('../common'); const { - injectAndCodeSign, + generateSEA, skipIfSingleExecutableIsNotSupported, } = require('../common/sea'); @@ -12,7 +12,7 @@ skipIfSingleExecutableIsNotSupported(); // This tests the snapshot support in single executable applications. const tmpdir = require('../common/tmpdir'); -const { copyFileSync, writeFileSync, existsSync } = require('fs'); +const { writeFileSync, existsSync } = require('fs'); const { spawnSyncAndExit, spawnSyncAndExitWithoutError @@ -85,8 +85,7 @@ const outputFile = tmpdir.resolve(process.platform === 'win32' ? 'sea.exe' : 'se assert(existsSync(seaPrepBlob)); - copyFileSync(process.execPath, outputFile); - injectAndCodeSign(outputFile, seaPrepBlob); + generateSEA(outputFile, process.execPath, seaPrepBlob); spawnSyncAndExitWithoutError( outputFile, diff --git a/test/sequential/test-single-executable-application-use-code-cache.js b/test/sequential/test-single-executable-application-use-code-cache.js index af5f2855ed6318..151e631eda7ea8 100644 --- a/test/sequential/test-single-executable-application-use-code-cache.js +++ b/test/sequential/test-single-executable-application-use-code-cache.js @@ -3,7 +3,7 @@ require('../common'); const { - injectAndCodeSign, + generateSEA, skipIfSingleExecutableIsNotSupported, } = require('../common/sea'); @@ -56,8 +56,7 @@ spawnSyncAndExitWithoutError( assert(existsSync(seaPrepBlob)); -copyFileSync(process.execPath, outputFile); -injectAndCodeSign(outputFile, seaPrepBlob); +generateSEA(outputFile, process.execPath, seaPrepBlob); spawnSyncAndExitWithoutError( outputFile, diff --git a/test/sequential/test-single-executable-application.js b/test/sequential/test-single-executable-application.js index 6379dfd2ea4b6d..2e5c7c1e5d564a 100644 --- a/test/sequential/test-single-executable-application.js +++ b/test/sequential/test-single-executable-application.js @@ -3,7 +3,7 @@ require('../common'); const { - injectAndCodeSign, + generateSEA, skipIfSingleExecutableIsNotSupported, } = require('../common/sea'); @@ -50,8 +50,7 @@ spawnSyncAndExitWithoutError( assert(existsSync(seaPrepBlob)); -copyFileSync(process.execPath, outputFile); -injectAndCodeSign(outputFile, seaPrepBlob); +generateSEA(outputFile, process.execPath, seaPrepBlob); spawnSyncAndExitWithoutError( outputFile, diff --git a/unofficial.gni b/unofficial.gni index aa2645a475b525..027805104fc8ec 100644 --- a/unofficial.gni +++ b/unofficial.gni @@ -82,10 +82,10 @@ template("node_gn_build") { "-Wno-unused-function", ] - if (target_cpu == "x86") { + if (current_cpu == "x86") { node_arch = "ia32" } else { - node_arch = target_cpu + node_arch = current_cpu } if (target_os == "win") { node_platform = "win32"